summaryrefslogtreecommitdiff
path: root/src/SMAPI.Web
diff options
context:
space:
mode:
authorJesse Plamondon-Willard <Pathoschild@users.noreply.github.com>2020-03-22 19:52:42 -0400
committerJesse Plamondon-Willard <Pathoschild@users.noreply.github.com>2020-03-22 19:52:42 -0400
commit7ca5efbbc576f3c6c43493654b2a0ac040fd4f31 (patch)
treefae7a4e06a14ff7f8d709e2f4d5b8b92b8784a37 /src/SMAPI.Web
parent5ae640dc91adff8dfb0827e2a3c3f6b54be7c612 (diff)
parent6d1494a56c5d04e7bc1ee406810a5a53dea2229a (diff)
downloadSMAPI-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.cs89
-rw-r--r--src/SMAPI.Web/Framework/LogParsing/LogParser.cs66
-rw-r--r--src/SMAPI.Web/Program.cs2
-rw-r--r--src/SMAPI.Web/SMAPI.Web.csproj12
-rw-r--r--src/SMAPI.Web/Startup.cs3
-rw-r--r--src/SMAPI.Web/Views/JsonValidator/Index.cshtml9
-rw-r--r--src/SMAPI.Web/Views/LogParser/Index.cshtml12
-rw-r--r--src/SMAPI.Web/wwwroot/Content/css/file-upload.css25
-rw-r--r--src/SMAPI.Web/wwwroot/Content/css/json-validator.css25
-rw-r--r--src/SMAPI.Web/wwwroot/Content/css/log-parser.css21
-rw-r--r--src/SMAPI.Web/wwwroot/Content/js/file-upload.js71
-rw-r--r--src/SMAPI.Web/wwwroot/Content/js/json-validator.js51
-rw-r--r--src/SMAPI.Web/wwwroot/Content/js/log-parser.js38
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")
});
}
};