diff options
-rw-r--r-- | docs/release-notes.md | 1 | ||||
-rw-r--r-- | src/SMAPI.Web/Controllers/LogParserController.cs | 11 | ||||
-rw-r--r-- | src/SMAPI.Web/ViewModels/LogParserModel.cs | 19 | ||||
-rw-r--r-- | src/SMAPI.Web/Views/LogParser/Index.cshtml | 79 | ||||
-rw-r--r-- | src/SMAPI.Web/wwwroot/Content/css/log-parser.css | 4 | ||||
-rw-r--r-- | src/SMAPI.Web/wwwroot/Content/js/log-parser.js | 14 |
6 files changed, 88 insertions, 40 deletions
diff --git a/docs/release-notes.md b/docs/release-notes.md index 5a9e4e92..329ea3ad 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -65,6 +65,7 @@ * Redesigned UI to be more mobile-friendly. * Added option to download from Nexus. * Changed log parser filters to show `DEBUG` messages by default. + * Added log parser option to view raw log. * Fixed log parser issue when content packs have no description. * Fixed log parser mangling crossplatform paths in some cases. diff --git a/src/SMAPI.Web/Controllers/LogParserController.cs b/src/SMAPI.Web/Controllers/LogParserController.cs index 2bff1392..354bdb06 100644 --- a/src/SMAPI.Web/Controllers/LogParserController.cs +++ b/src/SMAPI.Web/Controllers/LogParserController.cs @@ -52,21 +52,22 @@ namespace StardewModdingAPI.Web.Controllers ***/ /// <summary>Render the log parser UI.</summary> /// <param name="id">The paste ID.</param> + /// <param name="raw">Whether to display the raw unparsed log.</param> [HttpGet] [Route("log")] [Route("log/{id}")] - public async Task<ViewResult> Index(string id = null) + public async Task<ViewResult> Index(string id = null, bool raw = false) { // fresh page if (string.IsNullOrWhiteSpace(id)) - return this.View("Index", new LogParserModel(this.Config.LogParserUrl, id, null)); + return this.View("Index", new LogParserModel(this.Config.LogParserUrl, id)); // log page PasteInfo paste = await this.GetAsync(id); ParsedLog log = paste.Success ? new LogParser().Parse(paste.Content) : new ParsedLog { IsValid = false, Error = "Pastebin error: " + paste.Error }; - return this.View("Index", new LogParserModel(this.Config.LogParserUrl, id, log)); + return this.View("Index", new LogParserModel(this.Config.LogParserUrl, id, log, raw)); } /*** @@ -80,7 +81,7 @@ namespace StardewModdingAPI.Web.Controllers // get raw log text string input = this.Request.Form["input"].FirstOrDefault(); if (string.IsNullOrWhiteSpace(input)) - return this.View("Index", new LogParserModel(this.Config.LogParserUrl, null, null) { UploadError = "The log file seems to be empty." }); + return this.View("Index", new LogParserModel(this.Config.LogParserUrl, null) { UploadError = "The log file seems to be empty." }); // upload log input = this.CompressString(input); @@ -88,7 +89,7 @@ namespace StardewModdingAPI.Web.Controllers // handle errors if (!result.Success) - return this.View("Index", new LogParserModel(this.Config.LogParserUrl, result.ID, null) { UploadError = $"Pastebin error: {result.Error ?? "unknown error"}" }); + return this.View("Index", new LogParserModel(this.Config.LogParserUrl, result.ID) { UploadError = $"Pastebin error: {result.Error ?? "unknown error"}" }); // redirect to view UriBuilder uri = new UriBuilder(new Uri(this.Config.LogParserUrl)); diff --git a/src/SMAPI.Web/ViewModels/LogParserModel.cs b/src/SMAPI.Web/ViewModels/LogParserModel.cs index 0fbd8ad5..df36ca73 100644 --- a/src/SMAPI.Web/ViewModels/LogParserModel.cs +++ b/src/SMAPI.Web/ViewModels/LogParserModel.cs @@ -27,6 +27,9 @@ namespace StardewModdingAPI.Web.ViewModels /// <summary>The parsed log info.</summary> public ParsedLog ParsedLog { get; set; } + /// <summary>Whether to show the raw unparsed log.</summary> + public bool ShowRaw { get; set; } + /// <summary>An error which occurred while uploading the log to Pastebin.</summary> public string UploadError { get; set; } @@ -43,12 +46,24 @@ namespace StardewModdingAPI.Web.ViewModels /// <summary>Construct an instance.</summary> /// <param name="sectionUrl">The root URL for the log parser controller.</param> /// <param name="pasteID">The paste ID.</param> - /// <param name="parsedLog">The parsed log info.</param> - public LogParserModel(string sectionUrl, string pasteID, ParsedLog parsedLog) + public LogParserModel(string sectionUrl, string pasteID) { this.SectionUrl = sectionUrl; this.PasteID = pasteID; + this.ParsedLog = null; + this.ShowRaw = false; + } + + /// <summary>Construct an instance.</summary> + /// <param name="sectionUrl">The root URL for the log parser controller.</param> + /// <param name="pasteID">The paste ID.</param> + /// <param name="parsedLog">The parsed log info.</param> + /// <param name="showRaw">Whether to show the raw unparsed log.</param> + public LogParserModel(string sectionUrl, string pasteID, ParsedLog parsedLog, bool showRaw) + : this(sectionUrl, pasteID) + { this.ParsedLog = parsedLog; + this.ShowRaw = showRaw; } /// <summary>Get all content packs in the log grouped by the mod they're for.</summary> diff --git a/src/SMAPI.Web/Views/LogParser/Index.cshtml b/src/SMAPI.Web/Views/LogParser/Index.cshtml index 8151c502..f5501fed 100644 --- a/src/SMAPI.Web/Views/LogParser/Index.cshtml +++ b/src/SMAPI.Web/Views/LogParser/Index.cshtml @@ -17,17 +17,18 @@ { <meta name="robots" content="noindex" /> } - <link rel="stylesheet" href="~/Content/css/log-parser.css?r=20180611" /> + <link rel="stylesheet" href="~/Content/css/log-parser.css?r=20180627" /> <script src="https://cdn.jsdelivr.net/npm/vue"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js" crossorigin="anonymous"></script> - <script src="~/Content/js/log-parser.js?r=20180611"></script> + <script src="~/Content/js/log-parser.js?r=20180627"></script> <script> $(function() { smapi.logParser({ logStarted: new Date(@Json.Serialize(Model.ParsedLog?.Timestamp)), showPopup: @Json.Serialize(Model.ParsedLog == null), showMods: @Json.Serialize(Model.ParsedLog?.Mods?.Select(p => Model.GetSlug(p.Name)).Distinct().ToDictionary(slug => slug, slug => true), noFormatting), - showLevels: @Json.Serialize(defaultFilters, noFormatting) + showLevels: @Json.Serialize(defaultFilters, noFormatting), + enableFilters: @Json.Serialize(!Model.ShowRaw) }, '@Model.SectionUrl'); }); </script> @@ -138,12 +139,15 @@ else if (Model.ParsedLog?.IsValid == true) </tr> </table> <br /> - <table id="mods"> + <table id="mods" class="@(Model.ShowRaw ? "filters-disabled" : null)"> <caption> Installed mods: - <span class="notice txt"><i>click any mod to filter</i></span> - <span class="notice btn txt" v-on:click="showAllMods" v-show="stats.modsHidden > 0">show all</span> - <span class="notice btn txt" v-on:click="hideAllMods" v-show="stats.modsShown > 0 && stats.modsHidden > 0">hide all</span> + @if (!Model.ShowRaw) + { + <span class="notice txt"><i>click any mod to filter</i></span> + <span class="notice btn txt" v-on:click="showAllMods" v-show="stats.modsHidden > 0">show all</span> + <span class="notice btn txt" v-on:click="hideAllMods" v-show="stats.modsShown > 0 && stats.modsHidden > 0">hide all</span> + } </caption> @foreach (var mod in Model.ParsedLog.Mods.Where(p => p.ContentPackFor == null)) { @@ -177,36 +181,47 @@ else if (Model.ParsedLog?.IsValid == true) </tr> } </table> - <div id="filters"> - Filter messages: - <span v-bind:class="{ active: showLevels['trace'] }" v-on:click="toggleLevel('trace')">TRACE</span> | - <span v-bind:class="{ active: showLevels['debug'] }" v-on:click="toggleLevel('debug')">DEBUG</span> | - <span v-bind:class="{ active: showLevels['info'] }" v-on:click="toggleLevel('info')">INFO</span> | - <span v-bind:class="{ active: showLevels['alert'] }" v-on:click="toggleLevel('alert')">ALERT</span> | - <span v-bind:class="{ active: showLevels['warn'] }" v-on:click="toggleLevel('warn')">WARN</span> | - <span v-bind:class="{ active: showLevels['error'] }" v-on:click="toggleLevel('error')">ERROR</span> - </div> - <table id="log"> - @foreach (var message in Model.ParsedLog.Messages) - { - string levelStr = message.Level.ToString().ToLower(); + @if (!Model.ShowRaw) + { + <div id="filters"> + Filter messages: + <span v-bind:class="{ active: showLevels['trace'] }" v-on:click="toggleLevel('trace')">TRACE</span> | + <span v-bind:class="{ active: showLevels['debug'] }" v-on:click="toggleLevel('debug')">DEBUG</span> | + <span v-bind:class="{ active: showLevels['info'] }" v-on:click="toggleLevel('info')">INFO</span> | + <span v-bind:class="{ active: showLevels['alert'] }" v-on:click="toggleLevel('alert')">ALERT</span> | + <span v-bind:class="{ active: showLevels['warn'] }" v-on:click="toggleLevel('warn')">WARN</span> | + <span v-bind:class="{ active: showLevels['error'] }" v-on:click="toggleLevel('error')">ERROR</span> + </div> - <tr class="@levelStr mod" v-show="filtersAllow('@Model.GetSlug(message.Mod)', '@levelStr')"> - <td v-pre>@message.Time</td> - <td v-pre>@message.Level.ToString().ToUpper()</td> - <td v-pre data-title="@message.Mod">@message.Mod</td> - <td v-pre>@message.Text</td> - </tr> - if (message.Repeated > 0) + <table id="log"> + @foreach (var message in Model.ParsedLog.Messages) { - <tr class="@levelStr mod mod-repeat" v-show="filtersAllow('@Model.GetSlug(message.Mod)', '@levelStr')"> - <td colspan="3"></td> - <td v-pre><i>repeats [@message.Repeated] times.</i></td> + string levelStr = message.Level.ToString().ToLower(); + + <tr class="@levelStr mod" v-show="filtersAllow('@Model.GetSlug(message.Mod)', '@levelStr')"> + <td v-pre>@message.Time</td> + <td v-pre>@message.Level.ToString().ToUpper()</td> + <td v-pre data-title="@message.Mod">@message.Mod</td> + <td v-pre>@message.Text</td> </tr> + if (message.Repeated > 0) + { + <tr class="@levelStr mod mod-repeat" v-show="filtersAllow('@Model.GetSlug(message.Mod)', '@levelStr')"> + <td colspan="3"></td> + <td v-pre><i>repeats [@message.Repeated] times.</i></td> + </tr> + } } - } - </table> + </table> + + <small><a href="@(new Uri(new Uri(Model.SectionUrl), Model.PasteID))?raw=true">view raw log</a></small> + } + else + { + <pre v-pre>@Model.ParsedLog.RawText</pre> + <small><a href="@(new Uri(new Uri(Model.SectionUrl), Model.PasteID))">view parsed log</a></small> + } </div> } else if (Model.ParsedLog?.IsValid == false) diff --git a/src/SMAPI.Web/wwwroot/Content/css/log-parser.css b/src/SMAPI.Web/wwwroot/Content/css/log-parser.css index 09bb97f5..1fcd1bff 100644 --- a/src/SMAPI.Web/wwwroot/Content/css/log-parser.css +++ b/src/SMAPI.Web/wwwroot/Content/css/log-parser.css @@ -79,6 +79,10 @@ table#metadata, table#mods { cursor: pointer; } +#mods.filters-disabled tr { + cursor: default; +} + #metadata tr, #mods tr { background: #eee diff --git a/src/SMAPI.Web/wwwroot/Content/js/log-parser.js b/src/SMAPI.Web/wwwroot/Content/js/log-parser.js index 44c3ad5d..0c654205 100644 --- a/src/SMAPI.Web/wwwroot/Content/js/log-parser.js +++ b/src/SMAPI.Web/wwwroot/Content/js/log-parser.js @@ -39,11 +39,17 @@ smapi.logParser = function (data, sectionUrl) { } }, methods: { - toggleLevel: function(id) { + toggleLevel: function (id) { + if (!data.enableFilters) + return; + this.showLevels[id] = !this.showLevels[id]; }, toggleMod: function (id) { + if (!data.enableFilters) + return; + var curShown = this.showMods[id]; // first filter: only show this by default @@ -64,6 +70,9 @@ smapi.logParser = function (data, sectionUrl) { }, showAllMods: function () { + if (!data.enableFilters) + return; + for (var key in this.showMods) { if (this.showMods.hasOwnProperty(key)) { this.showMods[key] = true; @@ -73,6 +82,9 @@ smapi.logParser = function (data, sectionUrl) { }, hideAllMods: function () { + if (!data.enableFilters) + return; + for (var key in this.showMods) { if (this.showMods.hasOwnProperty(key)) { this.showMods[key] = false; |