improved UX in Event Log by preserving criteria when viewing Details, added RowClass and ColumnClass parameters to Pager component, added initial-scale=1.0 to viewport specification in _host, added default visitor tracking filter, fixed "The given key 'level' was not present in the dictionary" issue in Visitor Management - Details by ensuring data was fully loaded
This commit is contained in:
		| @ -9,86 +9,88 @@ | ||||
| @inject IStringLocalizer<Detail> Localizer | ||||
| @inject IStringLocalizer<SharedResources> SharedLocalizer | ||||
|  | ||||
|     <div class="container"> | ||||
|        <div class="row mb-1 align-items-center"> | ||||
|             <Label Class="col-sm-3" For="dateTime" HelpText="The date and time of this log" ResourceKey="DateTime">Date/Time: </Label> | ||||
|             <div class="col-sm-9"> | ||||
|                 <input id="dateTime" class="form-control" @bind="@_logDate" readonly /> | ||||
|             </div> | ||||
|        </div> | ||||
|        <div class="row mb-1 align-items-center"> | ||||
|             <Label Class="col-sm-3" For="level" HelpText="The level of this log" ResourceKey="Level">Level: </Label> | ||||
|             <div class="col-sm-9"> | ||||
|                 <input id="level" class="form-control" @bind="@_level" readonly /> | ||||
|             </div> | ||||
|        </div> | ||||
|        <div class="row mb-1 align-items-center"> | ||||
|             <Label Class="col-sm-3" For="feature" HelpText="The feature that was affected" ResourceKey="Feature">Feature: </Label> | ||||
|             <div class="col-sm-9"> | ||||
|                 <input id="feature" class="form-control" @bind="@_feature" readonly /> | ||||
|             </div> | ||||
|        </div> | ||||
|        <div class="row mb-1 align-items-center"> | ||||
|             <Label Class="col-sm-3" For="function" HelpText="The function that was performed" ResourceKey="Function">Function: </Label> | ||||
|             <div class="col-sm-9"> | ||||
|                 <input id="function" class="form-control" @bind="@_function" readonly /> | ||||
|             </div> | ||||
|        </div> | ||||
|        <div class="row mb-1 align-items-center"> | ||||
|             <Label Class="col-sm-3" For="category" HelpText="The categories that were affected" ResourceKey="Category">Category: </Label> | ||||
|             <div class="col-sm-9"> | ||||
|                 <input id="category" class="form-control" @bind="@_category" readonly /> | ||||
|             </div> | ||||
|        </div> | ||||
|         @if (_pageName != string.Empty) | ||||
|         { | ||||
|            <div class="row mb-1 align-items-center"> | ||||
|                 <Label Class="col-sm-3" For="page" HelpText="The page that was affected" ResourceKey="Page">Page: </Label> | ||||
|                 <div class="col-sm-9"> | ||||
|                     <input id="page" class="form-control" @bind="@_pageName" readonly /> | ||||
|                 </div> | ||||
|            </div> | ||||
|         } | ||||
|         @if (_moduleTitle != string.Empty) | ||||
|         { | ||||
|            <div class="row mb-1 align-items-center"> | ||||
|                 <Label Class="col-sm-3" For="module" HelpText="The module that was affected" ResourceKey="Module">Module: </Label> | ||||
|                 <div class="col-sm-9"> | ||||
|                     <input id="module" class="form-control" @bind="@_moduleTitle" readonly /> | ||||
|                 </div> | ||||
|            </div> | ||||
|         } | ||||
|         @if (_username != string.Empty) | ||||
|         { | ||||
|            <div class="row mb-1 align-items-center"> | ||||
|                 <Label Class="col-sm-3" For="user" HelpText="The user that caused this log" ResourceKey="User">User: </Label> | ||||
|                  <div class="col-sm-9"> | ||||
|                     <input id="user" class="form-control" @bind="@_username" readonly /> | ||||
|                 </div> | ||||
|            </div> | ||||
|         } | ||||
|        <div class="row mb-1 align-items-center"> | ||||
|             <Label Class="col-sm-3" For="url" HelpText="The url the log comes from" ResourceKey="Url">Url: </Label> | ||||
|             <div class="col-sm-9"> | ||||
|                 <input id="url" class="form-control" @bind="@_url" readonly /> | ||||
|             </div> | ||||
|        </div> | ||||
|        <div class="row mb-1 align-items-center"> | ||||
|             <Label Class="col-sm-3" For="template" HelpText="What the log is about" ResourceKey="Template">Template: </Label> | ||||
|             <div class="col-sm-9"> | ||||
|                 <input id="template" class="form-control" @bind="@_template" readonly /> | ||||
|             </div> | ||||
|        </div> | ||||
|        <div class="row mb-1 align-items-center"> | ||||
|             <Label Class="col-sm-3" For="message" HelpText="The message that the system generated" ResourceKey="Message">Message: </Label> | ||||
|             <div class="col-sm-9"> | ||||
|                 <textarea id="message" class="form-control" @bind="@_message" rows="5" readonly></textarea> | ||||
|             </div> | ||||
|        </div> | ||||
|         @if (!string.IsNullOrEmpty(_exception)) | ||||
|         { | ||||
|            <div class="row mb-1 align-items-center"> | ||||
|                 <Label Class="col-sm-3" For="exception" HelpText="The exceptions generated by the system" ResourceKey="Exception">Exception: </Label> | ||||
| @if (_initialized) | ||||
| { | ||||
| 	<div class="container"> | ||||
| 		<div class="row mb-1 align-items-center"> | ||||
| 			<Label Class="col-sm-3" For="dateTime" HelpText="The date and time of this log" ResourceKey="DateTime">Date/Time: </Label> | ||||
| 			<div class="col-sm-9"> | ||||
| 				<input id="dateTime" class="form-control" @bind="@_logDate" readonly /> | ||||
| 			</div> | ||||
| 		</div> | ||||
| 		<div class="row mb-1 align-items-center"> | ||||
| 			<Label Class="col-sm-3" For="level" HelpText="The level of this log" ResourceKey="Level">Level: </Label> | ||||
| 			<div class="col-sm-9"> | ||||
| 				<input id="level" class="form-control" @bind="@_level" readonly /> | ||||
| 			</div> | ||||
| 		</div> | ||||
| 		<div class="row mb-1 align-items-center"> | ||||
| 			<Label Class="col-sm-3" For="feature" HelpText="The feature that was affected" ResourceKey="Feature">Feature: </Label> | ||||
| 			<div class="col-sm-9"> | ||||
| 				<input id="feature" class="form-control" @bind="@_feature" readonly /> | ||||
| 			</div> | ||||
| 		</div> | ||||
| 		<div class="row mb-1 align-items-center"> | ||||
| 			<Label Class="col-sm-3" For="function" HelpText="The function that was performed" ResourceKey="Function">Function: </Label> | ||||
| 			<div class="col-sm-9"> | ||||
| 				<input id="function" class="form-control" @bind="@_function" readonly /> | ||||
| 			</div> | ||||
| 		</div> | ||||
| 		<div class="row mb-1 align-items-center"> | ||||
| 			<Label Class="col-sm-3" For="category" HelpText="The categories that were affected" ResourceKey="Category">Category: </Label> | ||||
| 			<div class="col-sm-9"> | ||||
| 				<input id="category" class="form-control" @bind="@_category" readonly /> | ||||
| 			</div> | ||||
| 		</div> | ||||
| 		@if (_pageName != string.Empty) | ||||
| 		{ | ||||
| 			<div class="row mb-1 align-items-center"> | ||||
| 				<Label Class="col-sm-3" For="page" HelpText="The page that was affected" ResourceKey="Page">Page: </Label> | ||||
| 				<div class="col-sm-9"> | ||||
| 					<input id="page" class="form-control" @bind="@_pageName" readonly /> | ||||
| 				</div> | ||||
| 			</div> | ||||
| 		} | ||||
| 		@if (_moduleTitle != string.Empty) | ||||
| 		{ | ||||
| 			<div class="row mb-1 align-items-center"> | ||||
| 				<Label Class="col-sm-3" For="module" HelpText="The module that was affected" ResourceKey="Module">Module: </Label> | ||||
| 				<div class="col-sm-9"> | ||||
| 					<input id="module" class="form-control" @bind="@_moduleTitle" readonly /> | ||||
| 				</div> | ||||
| 			</div> | ||||
| 		} | ||||
| 		@if (_username != string.Empty) | ||||
| 		{ | ||||
| 			<div class="row mb-1 align-items-center"> | ||||
| 				<Label Class="col-sm-3" For="user" HelpText="The user that caused this log" ResourceKey="User">User: </Label> | ||||
| 				<div class="col-sm-9"> | ||||
| 					<input id="user" class="form-control" @bind="@_username" readonly /> | ||||
| 				</div> | ||||
| 			</div> | ||||
| 		} | ||||
| 		<div class="row mb-1 align-items-center"> | ||||
| 			<Label Class="col-sm-3" For="url" HelpText="The url the log comes from" ResourceKey="Url">Url: </Label> | ||||
| 			<div class="col-sm-9"> | ||||
| 				<input id="url" class="form-control" @bind="@_url" readonly /> | ||||
| 			</div> | ||||
| 		</div> | ||||
| 		<div class="row mb-1 align-items-center"> | ||||
| 			<Label Class="col-sm-3" For="template" HelpText="What the log is about" ResourceKey="Template">Template: </Label> | ||||
| 			<div class="col-sm-9"> | ||||
| 				<input id="template" class="form-control" @bind="@_template" readonly /> | ||||
| 			</div> | ||||
| 		</div> | ||||
| 		<div class="row mb-1 align-items-center"> | ||||
| 			<Label Class="col-sm-3" For="message" HelpText="The message that the system generated" ResourceKey="Message">Message: </Label> | ||||
| 			<div class="col-sm-9"> | ||||
| 				<textarea id="message" class="form-control" @bind="@_message" rows="5" readonly></textarea> | ||||
| 			</div> | ||||
| 		</div> | ||||
| 		@if (!string.IsNullOrEmpty(_exception)) | ||||
| 		{ | ||||
| 			<div class="row mb-1 align-items-center"> | ||||
| 				<Label Class="col-sm-3" For="exception" HelpText="The exceptions generated by the system" ResourceKey="Exception">Exception: </Label> | ||||
| 				<div class="col-sm-9"> | ||||
|                     <textarea id="exception" class="form-control" @bind="@_exception" rows="5" readonly></textarea> | ||||
|                 </div> | ||||
| @ -107,81 +109,83 @@ | ||||
|             </div> | ||||
|         </div> | ||||
|     </div> | ||||
| } | ||||
| <NavLink class="btn btn-secondary" href="@NavigateUrl(PageState.Page.Path, "level=" + PageState.QueryString["level"] + "&function=" + PageState.QueryString["function"] + "&rows=" + PageState.QueryString["rows"] + "&page=" + PageState.QueryString["page"])">@SharedLocalizer["Cancel"]</NavLink> | ||||
|  | ||||
|     <NavLink class="btn btn-secondary" href="@NavigateUrl()">@SharedLocalizer["Cancel"]</NavLink> | ||||
| @code { | ||||
| 	private bool _initialized = false; | ||||
|     private int _logId; | ||||
|     private string _logDate = string.Empty; | ||||
|     private string _level = string.Empty; | ||||
|     private string _feature = string.Empty; | ||||
|     private string _function = string.Empty; | ||||
|     private string _category = string.Empty; | ||||
|     private string _pageName = string.Empty; | ||||
|     private string _moduleTitle = string.Empty; | ||||
|     private string _username = string.Empty; | ||||
|     private string _url = string.Empty; | ||||
|     private string _template = string.Empty; | ||||
|     private string _message = string.Empty; | ||||
|     private string _exception = string.Empty; | ||||
|     private string _properties = string.Empty; | ||||
|     private string _server = string.Empty; | ||||
|  | ||||
|     @code { | ||||
|         private int _logId; | ||||
|         private string _logDate = string.Empty; | ||||
|         private string _level = string.Empty; | ||||
|         private string _feature = string.Empty; | ||||
|         private string _function = string.Empty; | ||||
|         private string _category = string.Empty; | ||||
|         private string _pageName = string.Empty; | ||||
|         private string _moduleTitle = string.Empty; | ||||
|         private string _username = string.Empty; | ||||
|         private string _url = string.Empty; | ||||
|         private string _template = string.Empty; | ||||
|         private string _message = string.Empty; | ||||
|         private string _exception = string.Empty; | ||||
|         private string _properties = string.Empty; | ||||
|         private string _server = string.Empty; | ||||
|     public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Host; | ||||
|  | ||||
|         public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Host; | ||||
|  | ||||
|         protected override async Task OnInitializedAsync() | ||||
|     protected override async Task OnInitializedAsync() | ||||
|     { | ||||
|         try | ||||
|         { | ||||
|             try | ||||
|             _logId = Int32.Parse(PageState.QueryString["id"]); | ||||
|             var log = await LogService.GetLogAsync(_logId); | ||||
|             if (log != null) | ||||
|             { | ||||
|                 _logId = Int32.Parse(PageState.QueryString["id"]); | ||||
|                 var log = await LogService.GetLogAsync(_logId); | ||||
|                 if (log != null) | ||||
|                 _logDate = log.LogDate.ToString(CultureInfo.CurrentCulture); | ||||
|                 _level = log.Level; | ||||
|                 _feature = log.Feature; | ||||
|                 _function = log.Function; | ||||
|                 _category = log.Category; | ||||
|  | ||||
|                 if (log.PageId != null) | ||||
|                 { | ||||
|                     _logDate = log.LogDate.ToString(CultureInfo.CurrentCulture); | ||||
|                     _level = log.Level; | ||||
|                     _feature = log.Feature; | ||||
|                     _function = log.Function; | ||||
|                     _category = log.Category; | ||||
|  | ||||
|                     if (log.PageId != null) | ||||
|                     var page = await PageService.GetPageAsync(log.PageId.Value); | ||||
|                     if (page != null) | ||||
|                     { | ||||
|                         var page = await PageService.GetPageAsync(log.PageId.Value); | ||||
|                         if (page != null) | ||||
|                         { | ||||
|                             _pageName = page.Name; | ||||
|                         } | ||||
|                         _pageName = page.Name; | ||||
|                     } | ||||
|  | ||||
|                     if (log.PageId != null && log.ModuleId != null) | ||||
|                     { | ||||
|                         var pagemodule = await PageModuleService.GetPageModuleAsync(log.PageId.Value, log.ModuleId.Value); | ||||
|                         if (pagemodule != null) | ||||
|                         { | ||||
|                             _moduleTitle = pagemodule.Title; | ||||
|                         } | ||||
|                     } | ||||
|  | ||||
|                     if (log.UserId != null) | ||||
|                     { | ||||
|                         var user = await UserService.GetUserAsync(log.UserId.Value, PageState.Site.SiteId); | ||||
|                         if (user != null) | ||||
|                         { | ||||
|                             _username = user.Username; | ||||
|                         } | ||||
|                     } | ||||
|  | ||||
|                     _url = log.Url; | ||||
|                     _template = log.MessageTemplate; | ||||
|                     _message = log.Message; | ||||
|                     _exception = log.Exception; | ||||
|                     _properties = log.Properties; | ||||
|                     _server = log.Server; | ||||
|                 } | ||||
|             } | ||||
|             catch (Exception ex) | ||||
|             { | ||||
|                 await logger.LogError(ex, "Error Loading Log {LogId} {Error}", _logId, ex.Message); | ||||
|                 AddModuleMessage(Localizer["Error.Log.Load"], MessageType.Error); | ||||
|  | ||||
|                 if (log.PageId != null && log.ModuleId != null) | ||||
|                 { | ||||
|                     var pagemodule = await PageModuleService.GetPageModuleAsync(log.PageId.Value, log.ModuleId.Value); | ||||
|                     if (pagemodule != null) | ||||
|                     { | ||||
|                         _moduleTitle = pagemodule.Title; | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|                 if (log.UserId != null) | ||||
|                 { | ||||
|                     var user = await UserService.GetUserAsync(log.UserId.Value, PageState.Site.SiteId); | ||||
|                     if (user != null) | ||||
|                     { | ||||
|                         _username = user.Username; | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|                 _url = log.Url; | ||||
|                 _template = log.MessageTemplate; | ||||
|                 _message = log.Message; | ||||
|                 _exception = log.Exception; | ||||
|                 _properties = log.Properties; | ||||
|                 _server = log.Server; | ||||
| 				_initialized = true; | ||||
|             } | ||||
|         } | ||||
|         catch (Exception ex) | ||||
|         { | ||||
|             await logger.LogError(ex, "Error Loading Log {LogId} {Error}", _logId, ex.Message); | ||||
|             AddModuleMessage(Localizer["Error.Log.Load"], MessageType.Error); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -17,7 +17,7 @@ else | ||||
| 				<div class="row mb-1 align-items-center"> | ||||
| 					<div class="col-sm-4"> | ||||
| 						<Label For="level" HelpText="Select the log level for event log items" ResourceKey="Level">Level: </Label><br /><br /> | ||||
| 						<select id="level" class="form-select" @onchange="(e => LevelChanged(e))"> | ||||
| 						<select id="level" class="form-select" value="@_level" @onchange="(e => LevelChanged(e))"> | ||||
| 							<option value="-"><@Localizer["AllLevels"]></option> | ||||
| 							<option value="Trace">@Localizer["Trace"]</option> | ||||
| 							<option value="Debug">@Localizer["Debug"]</option> | ||||
| @ -29,7 +29,7 @@ else | ||||
| 					</div>             | ||||
| 					<div class="col-sm-4"> | ||||
| 						<Label For="function" HelpText="Select the function for event log items" ResourceKey="Function">Function: </Label><br /><br /> | ||||
| 						<select id="function" class="form-select" @onchange="(e => FunctionChanged(e))"> | ||||
| 						<select id="function" class="form-select" value="@_function" @onchange="(e => FunctionChanged(e))"> | ||||
| 							<option value="-"><@Localizer["AllFunctions"]></option> | ||||
| 							<option value="Create">@Localizer["Create"]</option> | ||||
| 							<option value="Read">@Localizer["Read"]</option> | ||||
| @ -41,7 +41,7 @@ else | ||||
| 					</div>             | ||||
| 					<div class="col-sm-4"> | ||||
| 						<Label For="rows" HelpText="Select the maximum number of event log items to review. Please note that if you choose more than 10 items the information will be split into pages." ResourceKey="Rows">Maximum Items: </Label><br /><br /> | ||||
| 						<select id="rows" class="form-select" @onchange="(e => RowsChanged(e))"> | ||||
| 						<select id="rows" class="form-select" value="@_rows" @onchange="(e => RowsChanged(e))"> | ||||
| 							<option value="10">10</option> | ||||
| 							<option value="50">50</option> | ||||
| 							<option value="100">100</option> | ||||
| @ -53,7 +53,7 @@ else | ||||
|  | ||||
| 			@if (_logs.Any()) | ||||
| 			{ | ||||
| 				<Pager Items="@_logs"> | ||||
| 				<Pager Items="@_logs" CurrentPage="@_page.ToString()" OnPageChange="OnPageChange"> | ||||
| 					<Header> | ||||
| 						<th style="width: 1px;"> </th> | ||||
| 						<th>@Localizer["Date"]</th> | ||||
| @ -62,7 +62,7 @@ else | ||||
| 						<th>@Localizer["Function"]</th> | ||||
| 					</Header> | ||||
| 					<Row> | ||||
| 						<td class="@GetClass(context.Function)"><ActionLink Action="Detail" Parameters="@($"id=" + context.LogId.ToString())" ResourceKey="LogDetails" /></td> | ||||
| 						<td class="@GetClass(context.Function)"><ActionLink Action="Detail" Parameters="@($"id=" + context.LogId.ToString() + "&level=" + _level + "&function=" + _function + "&rows=" + _rows + "&page=" + _page.ToString())" ResourceKey="LogDetails" /></td> | ||||
| 						<td class="@GetClass(context.Function)">@context.LogDate</td> | ||||
| 						<td class="@GetClass(context.Function)">@context.Level</td> | ||||
| 						<td class="@GetClass(context.Function)">@context.Feature</td> | ||||
| @ -94,6 +94,7 @@ else | ||||
|     private string _level = "-"; | ||||
|     private string _function = "-"; | ||||
|     private string _rows = "10"; | ||||
| 	private int _page = 1; | ||||
|     private List<Log> _logs; | ||||
|     private string _retention = ""; | ||||
|  | ||||
| @ -103,8 +104,27 @@ else | ||||
|     { | ||||
|         try | ||||
|         { | ||||
| 			if (PageState.QueryString.ContainsKey("level")) | ||||
| 			{ | ||||
| 				_level = PageState.QueryString["level"]; | ||||
| 			} | ||||
| 			if (PageState.QueryString.ContainsKey("function")) | ||||
| 			{ | ||||
| 				_function = PageState.QueryString["function"]; | ||||
| 			} | ||||
| 			if (PageState.QueryString.ContainsKey("rows")) | ||||
| 			{ | ||||
| 				_rows = PageState.QueryString["rows"]; | ||||
| 			} | ||||
| 			if (PageState.QueryString.ContainsKey("page") && int.TryParse(PageState.QueryString["page"], out int page)) | ||||
| 			{ | ||||
| 				_page = page; | ||||
| 			} | ||||
|  | ||||
|             await GetLogs(); | ||||
| 			_retention = SettingService.GetSetting(PageState.Site.Settings, "LogRetention", "30"); | ||||
|  | ||||
| 			var settings = await SettingService.GetSiteSettingsAsync(PageState.Site.SiteId); | ||||
| 			_retention = SettingService.GetSetting(settings, "LogRetention", "30"); | ||||
|         } | ||||
|         catch (Exception ex) | ||||
|         { | ||||
| @ -208,4 +228,9 @@ else | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	private void OnPageChange(int page) | ||||
| 	{ | ||||
| 		_page = page;	 | ||||
| 	} | ||||
|  | ||||
| } | ||||
|  | ||||
		Reference in New Issue
	
	Block a user
	 Shaun Walker
					Shaun Walker