diff options
author | Jesse Plamondon-Willard <Pathoschild@users.noreply.github.com> | 2020-03-22 19:52:42 -0400 |
---|---|---|
committer | Jesse Plamondon-Willard <Pathoschild@users.noreply.github.com> | 2020-03-22 19:52:42 -0400 |
commit | 7ca5efbbc576f3c6c43493654b2a0ac040fd4f31 (patch) | |
tree | fae7a4e06a14ff7f8d709e2f4d5b8b92b8784a37 /src/SMAPI.Web | |
parent | 5ae640dc91adff8dfb0827e2a3c3f6b54be7c612 (diff) | |
parent | 6d1494a56c5d04e7bc1ee406810a5a53dea2229a (diff) | |
download | SMAPI-7ca5efbbc576f3c6c43493654b2a0ac040fd4f31.tar.gz SMAPI-7ca5efbbc576f3c6c43493654b2a0ac040fd4f31.tar.bz2 SMAPI-7ca5efbbc576f3c6c43493654b2a0ac040fd4f31.zip |
Merge branch 'develop' into stable
Diffstat (limited to 'src/SMAPI.Web')
-rw-r--r-- | src/SMAPI.Web/Framework/LogParsing/LogMessageBuilder.cs | 89 | ||||
-rw-r--r-- | src/SMAPI.Web/Framework/LogParsing/LogParser.cs | 66 | ||||
-rw-r--r-- | src/SMAPI.Web/Program.cs | 2 | ||||
-rw-r--r-- | src/SMAPI.Web/SMAPI.Web.csproj | 12 | ||||
-rw-r--r-- | src/SMAPI.Web/Startup.cs | 3 | ||||
-rw-r--r-- | src/SMAPI.Web/Views/JsonValidator/Index.cshtml | 9 | ||||
-rw-r--r-- | src/SMAPI.Web/Views/LogParser/Index.cshtml | 12 | ||||
-rw-r--r-- | src/SMAPI.Web/wwwroot/Content/css/file-upload.css | 25 | ||||
-rw-r--r-- | src/SMAPI.Web/wwwroot/Content/css/json-validator.css | 25 | ||||
-rw-r--r-- | src/SMAPI.Web/wwwroot/Content/css/log-parser.css | 21 | ||||
-rw-r--r-- | src/SMAPI.Web/wwwroot/Content/js/file-upload.js | 71 | ||||
-rw-r--r-- | src/SMAPI.Web/wwwroot/Content/js/json-validator.js | 51 | ||||
-rw-r--r-- | src/SMAPI.Web/wwwroot/Content/js/log-parser.js | 38 |
13 files changed, 264 insertions, 160 deletions
diff --git a/src/SMAPI.Web/Framework/LogParsing/LogMessageBuilder.cs b/src/SMAPI.Web/Framework/LogParsing/LogMessageBuilder.cs new file mode 100644 index 00000000..42e283a9 --- /dev/null +++ b/src/SMAPI.Web/Framework/LogParsing/LogMessageBuilder.cs @@ -0,0 +1,89 @@ +using System; +using System.Text; +using StardewModdingAPI.Web.Framework.LogParsing.Models; + +namespace StardewModdingAPI.Web.Framework.LogParsing +{ + /// <summary>Handles constructing log message instances with minimal memory allocation.</summary> + internal class LogMessageBuilder + { + /********* + ** Fields + *********/ + /// <summary>The local time when the next log was posted.</summary> + public string Time { get; set; } + + /// <summary>The log level for the next log message.</summary> + public LogLevel Level { get; set; } + + /// <summary>The mod name for the next log message.</summary> + public string Mod { get; set; } + + /// <summary>The text for the next log message.</summary> + private readonly StringBuilder Text = new StringBuilder(); + + + /********* + ** Accessors + *********/ + /// <summary>Whether the next log message has been started.</summary> + public bool Started { get; private set; } + + + /********* + ** Public methods + *********/ + /// <summary>Start accumulating values for a new log message.</summary> + /// <param name="time">The local time when the log was posted.</param> + /// <param name="level">The log level.</param> + /// <param name="mod">The mod name.</param> + /// <param name="text">The initial log text.</param> + /// <exception cref="InvalidOperationException">A log message is already started; call <see cref="Clear"/> before starting a new message.</exception> + public void Start(string time, LogLevel level, string mod, string text) + { + if (this.Started) + throw new InvalidOperationException("Can't start new message, previous log message isn't done yet."); + + this.Started = true; + + this.Time = time; + this.Level = level; + this.Mod = mod; + this.Text.Append(text); + } + + /// <summary>Add a new line to the next log message being built.</summary> + /// <param name="text">The line to add.</param> + /// <exception cref="InvalidOperationException">A log message hasn't been started yet.</exception> + public void AddLine(string text) + { + if (!this.Started) + throw new InvalidOperationException("Can't add text, no log message started yet."); + + this.Text.Append("\n"); + this.Text.Append(text); + } + + /// <summary>Get a log message for the accumulated values.</summary> + public LogMessage Build() + { + if (!this.Started) + return null; + + return new LogMessage + { + Time = this.Time, + Level = this.Level, + Mod = this.Mod, + Text = this.Text.ToString() + }; + } + + /// <summary>Reset to start a new log message.</summary> + public void Clear() + { + this.Started = false; + this.Text.Clear(); + } + } +} diff --git a/src/SMAPI.Web/Framework/LogParsing/LogParser.cs b/src/SMAPI.Web/Framework/LogParsing/LogParser.cs index cc91ec51..cce80816 100644 --- a/src/SMAPI.Web/Framework/LogParsing/LogParser.cs +++ b/src/SMAPI.Web/Framework/LogParsing/LogParser.cs @@ -201,7 +201,7 @@ namespace StardewModdingAPI.Web.Framework.LogParsing } // mod path line - else if (message.Level == LogLevel.Debug && this.ModPathPattern.IsMatch(message.Text)) + else if (message.Level == LogLevel.Info && this.ModPathPattern.IsMatch(message.Text)) { Match match = this.ModPathPattern.Match(message.Text); log.ModPath = match.Groups["path"].Value; @@ -282,43 +282,47 @@ namespace StardewModdingAPI.Web.Framework.LogParsing /// <exception cref="LogParseException">The log text can't be parsed successfully.</exception> private IEnumerable<LogMessage> GetMessages(string logText) { - LogMessage message = new LogMessage(); - using (StringReader reader = new StringReader(logText)) + LogMessageBuilder builder = new LogMessageBuilder(); + using StringReader reader = new StringReader(logText); + while (true) { - while (true) - { - // read data - string line = reader.ReadLine(); - if (line == null) - break; - Match header = this.MessageHeaderPattern.Match(line); - - // validate - if (message.Text == null && !header.Success) - throw new LogParseException("Found a log message with no SMAPI metadata. Is this a SMAPI log file?"); + // read line + string line = reader.ReadLine(); + if (line == null) + break; - // start or continue message - if (header.Success) - { - if (message.Text != null) - yield return message; + // match header + Match header = this.MessageHeaderPattern.Match(line); + bool isNewMessage = header.Success; - message = new LogMessage - { - Time = header.Groups["time"].Value, - Level = Enum.Parse<LogLevel>(header.Groups["level"].Value, ignoreCase: true), - Mod = header.Groups["modName"].Value, - Text = line.Substring(header.Length) - }; + // start/continue message + if (isNewMessage) + { + if (builder.Started) + { + yield return builder.Build(); + builder.Clear(); } - else - message.Text += "\n" + line; + + builder.Start( + time: header.Groups["time"].Value, + level: Enum.Parse<LogLevel>(header.Groups["level"].Value, ignoreCase: true), + mod: header.Groups["modName"].Value, + text: line.Substring(header.Length) + ); } + else + { + if (!builder.Started) + throw new LogParseException("Found a log message with no SMAPI metadata. Is this a SMAPI log file?"); - // end last message - if (message.Text != null) - yield return message; + builder.AddLine(line); + } } + + // end last message + if (builder.Started) + yield return builder.Build(); } } } diff --git a/src/SMAPI.Web/Program.cs b/src/SMAPI.Web/Program.cs index 5856fc98..5d13cdf3 100644 --- a/src/SMAPI.Web/Program.cs +++ b/src/SMAPI.Web/Program.cs @@ -16,6 +16,8 @@ namespace StardewModdingAPI.Web // configure web server WebHost .CreateDefaultBuilder(args) + .CaptureStartupErrors(true) + .UseSetting("detailedErrors", "true") .UseStartup<Startup>() .Build() .Run(); diff --git a/src/SMAPI.Web/SMAPI.Web.csproj b/src/SMAPI.Web/SMAPI.Web.csproj index 97bea0fb..0a978b30 100644 --- a/src/SMAPI.Web/SMAPI.Web.csproj +++ b/src/SMAPI.Web/SMAPI.Web.csproj @@ -12,14 +12,14 @@ </ItemGroup> <ItemGroup> - <PackageReference Include="Azure.Storage.Blobs" Version="12.3.0" /> + <PackageReference Include="Azure.Storage.Blobs" Version="12.4.0" /> <PackageReference Include="Hangfire.AspNetCore" Version="1.7.9" /> - <PackageReference Include="Hangfire.MemoryStorage" Version="1.6.3" /> - <PackageReference Include="Hangfire.Mongo" Version="0.6.6" /> - <PackageReference Include="HtmlAgilityPack" Version="1.11.20" /> + <PackageReference Include="Hangfire.MemoryStorage" Version="1.7.0" /> + <PackageReference Include="Hangfire.Mongo" Version="0.6.7" /> + <PackageReference Include="HtmlAgilityPack" Version="1.11.23" /> <PackageReference Include="Humanizer.Core" Version="2.7.9" /> <PackageReference Include="JetBrains.Annotations" Version="2019.1.3" /> - <PackageReference Include="Markdig" Version="0.18.1" /> + <PackageReference Include="Markdig" Version="0.18.3" /> <PackageReference Include="Microsoft.AspNetCore" Version="2.2.0" /> <PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.2.0" /> <PackageReference Include="Microsoft.AspNetCore.Rewrite" Version="2.2.0" /> @@ -27,7 +27,7 @@ <PackageReference Include="Mongo2Go" Version="2.2.12" /> <PackageReference Include="MongoDB.Driver" Version="2.10.2" /> <PackageReference Include="Newtonsoft.Json.Schema" Version="3.0.13" /> - <PackageReference Include="Pathoschild.FluentNexus" Version="0.8.0" /> + <PackageReference Include="Pathoschild.FluentNexus" Version="1.0.0" /> <PackageReference Include="Pathoschild.Http.FluentClient" Version="3.3.1" /> </ItemGroup> <ItemGroup> diff --git a/src/SMAPI.Web/Startup.cs b/src/SMAPI.Web/Startup.cs index 29086472..56ef9a79 100644 --- a/src/SMAPI.Web/Startup.cs +++ b/src/SMAPI.Web/Startup.cs @@ -192,8 +192,7 @@ namespace StardewModdingAPI.Web public void Configure(IApplicationBuilder app, IHostingEnvironment env) { // basic config - if (env.IsDevelopment()) - app.UseDeveloperExceptionPage(); + app.UseDeveloperExceptionPage(); app .UseCors(policy => policy .AllowAnyHeader() diff --git a/src/SMAPI.Web/Views/JsonValidator/Index.cshtml b/src/SMAPI.Web/Views/JsonValidator/Index.cshtml index a00c8387..7287e00b 100644 --- a/src/SMAPI.Web/Views/JsonValidator/Index.cshtml +++ b/src/SMAPI.Web/Views/JsonValidator/Index.cshtml @@ -28,14 +28,16 @@ { <meta name="robots" content="noindex" /> } - <link rel="stylesheet" href="~/Content/css/json-validator.css?r=20191204" /> + <link rel="stylesheet" href="~/Content/css/file-upload.css?r=202002" /> + <link rel="stylesheet" href="~/Content/css/json-validator.css?r=202002" /> <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/tmont/sunlight@1.22.0/src/themes/sunlight.default.min.css" /> <script src="https://cdn.jsdelivr.net/npm/jquery@3.3.1/dist/jquery.min.js" crossorigin="anonymous"></script> <script src="https://cdn.jsdelivr.net/gh/tmont/sunlight@1.22.0/src/sunlight.min.js" crossorigin="anonymous"></script> <script src="https://cdn.jsdelivr.net/gh/tmont/sunlight@1.22.0/src/plugins/sunlight-plugin.linenumbers.min.js" crossorigin="anonymous"></script> <script src="https://cdn.jsdelivr.net/gh/tmont/sunlight@1.22.0/src/lang/sunlight.javascript.min.js" crossorigin="anonymous"></script> - <script src="~/Content/js/json-validator.js?r=20191204"></script> + <script src="~/Content/js/file-upload.js?r=202002"></script> + <script src="~/Content/js/json-validator.js?r=202002"></script> <script> $(function() { smapi.jsonValidator(@Json.Serialize(this.Url.PlainAction("Index", "JsonValidator", new { schemaName = "$schemaName", id = "$id" })), @Json.Serialize(Model.PasteID)); @@ -86,6 +88,7 @@ else if (!isEditView && Model.PasteID != null) { <h2>Upload a JSON file</h2> <form action="@this.Url.PlainAction("PostAsync", "JsonValidator")" method="post"> + <input id="inputFile" type="file" /> <ol> <li> Choose the JSON format:<br /> @@ -97,7 +100,7 @@ else if (!isEditView && Model.PasteID != null) </select> </li> <li> - Drag the file onto this textbox (or paste the text in):<br /> + Drag the file onto this textbox <small>(or <a href="#" id="choose-file-link">choose a file</a>)</small>:<br /> <textarea id="input" name="Content" placeholder="paste file here">@Model.Content</textarea> </li> <li> diff --git a/src/SMAPI.Web/Views/LogParser/Index.cshtml b/src/SMAPI.Web/Views/LogParser/Index.cshtml index 87c7f918..2183992b 100644 --- a/src/SMAPI.Web/Views/LogParser/Index.cshtml +++ b/src/SMAPI.Web/Views/LogParser/Index.cshtml @@ -22,10 +22,13 @@ { <meta name="robots" content="noindex" /> } - <link rel="stylesheet" href="~/Content/css/log-parser.css?r=20191127" /> + <link rel="stylesheet" href="~/Content/css/file-upload.css?r=202002" /> + <link rel="stylesheet" href="~/Content/css/log-parser.css?r=202002" /> + <script src="https://cdn.jsdelivr.net/npm/vue@2.5.17/dist/vue.min.js" crossorigin="anonymous"></script> <script src="https://cdn.jsdelivr.net/npm/jquery@3.3.1/dist/jquery.min.js" crossorigin="anonymous"></script> - <script src="~/Content/js/log-parser.js?r=20190515"></script> + <script src="~/Content/js/file-upload.js?r=202002"></script> + <script src="~/Content/js/log-parser.js?r=202002"></script> <script> $(function() { smapi.logParser({ @@ -135,9 +138,10 @@ else if (Model.ParsedLog?.IsValid == true) <h2>How do I share my log?</h2> <form action="@this.Url.PlainAction("PostAsync", "LogParser")" method="post"> + <input id="inputFile" type="file" /> <ol> <li> - Drag the file onto this textbox (or paste the text in):<br /> + Drag the file onto this textbox <small>(or <a href="#" id="choose-file-link">choose a file</a>)</small>:<br /> <textarea id="input" name="input" placeholder="paste log here"></textarea> </li> <li> @@ -300,7 +304,7 @@ else if (Model.ParsedLog?.IsValid == true) string sectionFilter = message.Section != null && !message.IsStartOfSection ? $"&& sectionsAllow('{message.Section}')" : null; // filter the message by section if applicable <tr class="mod @levelStr @sectionStartClass" - @if (message.IsStartOfSection) { <text> v-on:click="toggleSection('@message.Section')" </text> } + @if (message.IsStartOfSection) { <text> v-on:click="toggleSection('@message.Section')" </text> } v-show="filtersAllow('@Model.GetSlug(message.Mod)', '@levelStr') @sectionFilter"> <td v-pre>@message.Time</td> <td v-pre>@message.Level.ToString().ToUpper()</td> diff --git a/src/SMAPI.Web/wwwroot/Content/css/file-upload.css b/src/SMAPI.Web/wwwroot/Content/css/file-upload.css new file mode 100644 index 00000000..ff170691 --- /dev/null +++ b/src/SMAPI.Web/wwwroot/Content/css/file-upload.css @@ -0,0 +1,25 @@ +#inputFile { + display: none; +} + +#input { + width: 100%; + height: 20em; + max-height: 70%; + margin: auto; + box-sizing: border-box; + border-radius: 5px; + border: 1px solid #000088; + outline: none; + box-shadow: inset 0px 0px 1px 1px rgba(0, 0, 192, .2); +} + +#submit { + font-size: 1.5em; + border-radius: 5px; + outline: none; + box-shadow: inset 0 0 1px 1px rgba(0, 0, 0, .2); + cursor: pointer; + border: 1px solid #008800; + background-color: #cfc; +} diff --git a/src/SMAPI.Web/wwwroot/Content/css/json-validator.css b/src/SMAPI.Web/wwwroot/Content/css/json-validator.css index 18195098..de0f8fed 100644 --- a/src/SMAPI.Web/wwwroot/Content/css/json-validator.css +++ b/src/SMAPI.Web/wwwroot/Content/css/json-validator.css @@ -90,28 +90,3 @@ .footer-tip a { color: gray; } - -/********* -** Upload form -*********/ -#input { - width: 100%; - height: 20em; - max-height: 70%; - margin: auto; - box-sizing: border-box; - border-radius: 5px; - border: 1px solid #000088; - outline: none; - box-shadow: inset 0px 0px 1px 1px rgba(0, 0, 192, .2); -} - -#submit { - font-size: 1.5em; - border-radius: 5px; - outline: none; - box-shadow: inset 0 0 1px 1px rgba(0, 0, 0, .2); - cursor: pointer; - border: 1px solid #008800; - background-color: #cfc; -} diff --git a/src/SMAPI.Web/wwwroot/Content/css/log-parser.css b/src/SMAPI.Web/wwwroot/Content/css/log-parser.css index 4d4ab326..bfbc8982 100644 --- a/src/SMAPI.Web/wwwroot/Content/css/log-parser.css +++ b/src/SMAPI.Web/wwwroot/Content/css/log-parser.css @@ -301,24 +301,3 @@ div[data-os] { display: none; } -#input { - width: 100%; - height: 20em; - max-height: 70%; - margin: auto; - box-sizing: border-box; - border-radius: 5px; - border: 1px solid #000088; - outline: none; - box-shadow: inset 0px 0px 1px 1px rgba(0, 0, 192, .2); -} - -#submit { - font-size: 1.5em; - border-radius: 5px; - outline: none; - box-shadow: inset 0 0 1px 1px rgba(0, 0, 0, .2); - cursor: pointer; - border: 1px solid #008800; - background-color: #cfc; -} diff --git a/src/SMAPI.Web/wwwroot/Content/js/file-upload.js b/src/SMAPI.Web/wwwroot/Content/js/file-upload.js new file mode 100644 index 00000000..411efad3 --- /dev/null +++ b/src/SMAPI.Web/wwwroot/Content/js/file-upload.js @@ -0,0 +1,71 @@ +/* globals $ */ +var smapi = smapi || {}; + +/** + * Implements the logic for a log/JSON file upload form. + * + * @param {object} opts The file upload form options. + * @param {jQuery} opts.chooseFileLink The clickable link which shows the file chooser. + * @param {jQuery} opts.chooseFileInput The file input element. + * @param {jQuery} opts.contentArea The file content area. + * @param {jQuery} opts.submitButton The submit button. + */ +smapi.fileUpload = function (opts) { + /** + * Toggle the submit button if the form has content. + */ + var toggleSubmit = function () { + var hasText = !!opts.contentArea.val().trim(); + opts.submitButton.prop("disabled", !hasText); + }; + + /** + * Paste the content of a file into the content area. + * @param {File} file The file whose content to paste. + */ + var pasteFile = function (file) { + var reader = new FileReader(); + reader.onload = $.proxy(function (file, $input, event) { + $input.val(event.target.result); + toggleSubmit(); + }, this, file, $("#input")); + reader.readAsText(file); + }; + + // initialize + if (opts.contentArea.length) { + // disable submit button if it's empty + opts.contentArea.on("input", toggleSubmit); + toggleSubmit(); + + // drag & drop file + opts.contentArea.on({ + "dragover dragenter": function (e) { + e.preventDefault(); + }, + "drop": function (e) { + e.preventDefault(); + + var transfer = e.originalEvent.dataTransfer; + if (transfer && transfer.files.length) + pasteFile(transfer.files[0]); + } + }); + + // choose file + opts.chooseFileLink.on({ + "click": function (e) { + e.preventDefault(); + opts.chooseFileInput.click(); + } + }); + opts.chooseFileInput.on({ + "change": function (e) { + if (!e.target.files || !e.target.files.length) + return; + + pasteFile(e.target.files[0]); + } + }); + } +}; diff --git a/src/SMAPI.Web/wwwroot/Content/js/json-validator.js b/src/SMAPI.Web/wwwroot/Content/js/json-validator.js index 72b8192b..e9f72226 100644 --- a/src/SMAPI.Web/wwwroot/Content/js/json-validator.js +++ b/src/SMAPI.Web/wwwroot/Content/js/json-validator.js @@ -41,7 +41,7 @@ smapi.LineNumberRange = function (maxLines) { * Generate a URL hash for the current line range. * @returns {string} The generated URL hash. */ - self.buildHash = function() { + self.buildHash = function () { if (!self.minLine) return ""; else if (self.minLine === self.maxLine) @@ -54,7 +54,7 @@ smapi.LineNumberRange = function (maxLines) { * Get a list of all selected lines. * @returns {Array<int>} The selected line numbers. */ - self.getLinesSelected = function() { + self.getLinesSelected = function () { // format if (!self.minLine) return []; @@ -97,7 +97,7 @@ smapi.jsonValidator = function (urlFormat, fileId) { }); // fix line links - $(".sunlight-line-number-margin a").each(function() { + $(".sunlight-line-number-margin a").each(function () { var link = $(this); var lineNumber = parseInt(link.text()); link @@ -111,7 +111,7 @@ smapi.jsonValidator = function (urlFormat, fileId) { /** * Scroll the page so the selected range is visible. */ - var scrollToRange = function() { + var scrollToRange = function () { if (!selection.minLine) return; @@ -123,56 +123,33 @@ smapi.jsonValidator = function (urlFormat, fileId) { * Initialize the JSON validator page. */ var init = function () { + var input = $("#input"); + // set initial code formatting selection.parseFromUrlHash(location.hash); formatCode(); scrollToRange(); // update code formatting on hash change - $(window).on("hashchange", function() { + $(window).on("hashchange", function () { selection.parseFromUrlHash(location.hash); formatCode(); scrollToRange(); }); // change format - $("#output #format").on("change", function() { + $("#output #format").on("change", function () { var schemaName = $(this).val(); location.href = urlFormat.replace("$schemaName", schemaName).replace("$id", fileId); }); - // upload form - var submit = $("#submit"); - var input = $("#input"); if (input.length) { - // disable submit if it's empty - var toggleSubmit = function () { - var hasText = !!input.val().trim(); - submit.prop("disabled", !hasText); - }; - input.on("input", toggleSubmit); - toggleSubmit(); - - // drag & drop file - input.on({ - 'dragover dragenter': function (e) { - e.preventDefault(); - e.stopPropagation(); - }, - 'drop': function (e) { - var dataTransfer = e.originalEvent.dataTransfer; - if (dataTransfer && dataTransfer.files.length) { - e.preventDefault(); - e.stopPropagation(); - var file = dataTransfer.files[0]; - var reader = new FileReader(); - reader.onload = $.proxy(function (file, $input, event) { - $input.val(event.target.result); - toggleSubmit(); - }, this, file, $("#input")); - reader.readAsText(file); - } - } + // upload form + smapi.fileUpload({ + chooseFileLink: $("#choose-file-link"), + chooseFileInput: $("#inputFile"), + contentArea: input, + submitButton: $("#submit") }); } }; diff --git a/src/SMAPI.Web/wwwroot/Content/js/log-parser.js b/src/SMAPI.Web/wwwroot/Content/js/log-parser.js index e6c7591c..6ae1707e 100644 --- a/src/SMAPI.Web/wwwroot/Content/js/log-parser.js +++ b/src/SMAPI.Web/wwwroot/Content/js/log-parser.js @@ -115,12 +115,10 @@ smapi.logParser = function (data, sectionUrl) { *********/ var input = $("#input"); if (input.length) { - // get elements + // instructions per OS var systemOptions = $("input[name='os']"); var systemInstructions = $("div[data-os]"); - var submit = $("#submit"); - // instruction OS chooser var chooseSystem = function () { systemInstructions.hide(); systemInstructions.filter("[data-os='" + $("input[name='os']:checked").val() + "']").show(); @@ -128,34 +126,12 @@ smapi.logParser = function (data, sectionUrl) { systemOptions.on("click", chooseSystem); chooseSystem(); - // disable submit if it's empty - var toggleSubmit = function () { - var hasText = !!input.val().trim(); - submit.prop("disabled", !hasText); - } - input.on("input", toggleSubmit); - toggleSubmit(); - - // drag & drop file - input.on({ - 'dragover dragenter': function (e) { - e.preventDefault(); - e.stopPropagation(); - }, - 'drop': function (e) { - var dataTransfer = e.originalEvent.dataTransfer; - if (dataTransfer && dataTransfer.files.length) { - e.preventDefault(); - e.stopPropagation(); - var file = dataTransfer.files[0]; - var reader = new FileReader(); - reader.onload = $.proxy(function (file, $input, event) { - $input.val(event.target.result); - toggleSubmit(); - }, this, file, $("#input")); - reader.readAsText(file); - } - } + // file upload + smapi.fileUpload({ + chooseFileLink: $("#choose-file-link"), + chooseFileInput: $("#inputFile"), + contentArea: input, + submitButton: $("#submit") }); } }; |