b1575fa321
Dialogs (with a refresh option) appear whenever the SignalR client disconnects or encounters an error. Nonsensical error messages replaced. Page refresh technique changed to allow for urls containing fragment hashes.
157 lines
7.5 KiB
Plaintext
157 lines
7.5 KiB
Plaintext
@model Disco.Web.Areas.Config.Models.Shared.LogEventsModel
|
|
@{
|
|
Authorization.Require(Claims.Config.Logging.Show);
|
|
|
|
Html.BundleDeferred("~/ClientScripts/Modules/Knockout");
|
|
Html.BundleDeferred("~/ClientScripts/Modules/jQuery-SignalR");
|
|
var uniqueId = Guid.NewGuid().ToString("N");
|
|
}
|
|
<div id="LogEvents_@(uniqueId)" class="logEventsViewport">
|
|
<table class="logEventsViewport">
|
|
<thead>
|
|
<tr>
|
|
<th class="icon">
|
|
</th>
|
|
<th class="timestamp">Date/Time
|
|
</th>
|
|
<th class="eventType">Event Type
|
|
</th>
|
|
<th class="message">Message
|
|
</th>
|
|
</tr>
|
|
</thead>
|
|
</table>
|
|
<div class="logEventsViewportContainer" style="@(Model.ViewPortWidth.HasValue ? string.Format("width:{0}px;", Model.ViewPortWidth.Value) : null)@(Model.ViewPortHeight.HasValue ? string.Format("height:{0}px;", Model.ViewPortHeight.Value - 18) : null)">
|
|
<div class="logEventsViewportNoLogs" data-bind="visible: EventLogs().length == 0"
|
|
style="display: none">
|
|
No logs
|
|
</div>
|
|
<table class="logEventsViewport" data-bind="visible: EventLogs().length > 0" style="display: none">
|
|
<tbody data-bind="foreach: EventLogs">
|
|
<tr>
|
|
<td class="icon"><i class="fa" data-bind="css: {'fa-info-circle': EventTypeSeverity == 0, 'fa-exclamation-triangle': EventTypeSeverity == 1, 'fa-exclamation-circle': EventTypeSeverity == 2}"></i></td>
|
|
<td class="timestamp" data-bind="text: FormattedTimestamp"></td>
|
|
<td class="eventType" data-bind="text: EventTypeName, attr: {title: ModuleDescription}"></td>
|
|
<td class="message" data-bind="text: FormattedMessage, attr: {title: $parent.LogArguments($data)}"></td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
@{
|
|
var eventTypesFilterJson = (Model.EventTypesFilter != null) ? Newtonsoft.Json.JsonConvert.SerializeObject(Model.EventTypesFilter.Select(et => et.Id).ToArray()) : "null";
|
|
}
|
|
<script type="text/javascript">
|
|
$(function () {
|
|
var logEventsHost = $('LogEvents_@(uniqueId)');
|
|
var logModuleId = '@(Model.ModuleFilter != null ? Model.ModuleFilter.ModuleId.ToString() : null)';
|
|
var logModuleLiveGroupName = '@(Model.ModuleFilter != null ? Model.ModuleFilter.LiveLogGroupName : Disco.Services.Logging.LogNotificationsHub.AllLoggingNotification)';
|
|
var logEventTypeFiltered = @(eventTypesFilterJson);
|
|
var logStartFiler = @(AjaxHelpers.JsonDate(Model.StartFilter));
|
|
var logEndFiler = @(AjaxHelpers.JsonDate(Model.EndFilter));
|
|
var logTakeFiler = '@(Model.TakeFilter)';
|
|
var logHub = null;
|
|
var liveEventReceivedFunction = '@(Model.JavascriptLiveEventFunctionName)';
|
|
var useLive = ('True'==='@(Model.IsLive)');
|
|
|
|
// View Model
|
|
var logsViewModel;
|
|
function LogsViewModel(initialLogs){
|
|
var self = this;
|
|
|
|
self.EventLogs = ko.observableArray(initialLogs);
|
|
self.LogArguments = function(log){
|
|
if (log.Arguments)
|
|
return log.Arguments.join('\n');
|
|
else
|
|
return null;
|
|
};
|
|
}
|
|
function formatDate(d){
|
|
if (d){
|
|
return d.getFullYear() + '-' + (d.getMonth() + 1) + '-' + d.getDate() + ' ' + d.getHours() + ':'+d.getMinutes()+':'+d.getSeconds();
|
|
}else{
|
|
return null;
|
|
}
|
|
}
|
|
function loadInitialData(){
|
|
// Load Data
|
|
var loadData = {
|
|
Format: "json",
|
|
Start: formatDate(logStartFiler),
|
|
End: logEndFiler,
|
|
ModuleId: logModuleId,
|
|
Take: logTakeFiler
|
|
};
|
|
if (logEventTypeFiltered)
|
|
loadData["EventTypeIds"] = logEventTypeFiltered;
|
|
$.ajax({
|
|
url: '@(Url.Action(MVC.API.Logging.RetrieveEvents()))',
|
|
dataType: 'json',
|
|
type: 'POST',
|
|
data: loadData,
|
|
success: function (d) {
|
|
initLogs(d);
|
|
},
|
|
error: function (jqXHR, textStatus, errorThrown) {
|
|
alert('Unable to retrieve logs: ' + textStatus);
|
|
}
|
|
});
|
|
}
|
|
|
|
function initLogs(loadedLogs){
|
|
logsViewModel = new LogsViewModel(loadedLogs);
|
|
ko.applyBindings(logsViewModel, logEventsHost.get(0));
|
|
|
|
if (useLive){
|
|
if (liveEventReceivedFunction){
|
|
if (!document.DiscoFunctions) document.DiscoFunctions = {};
|
|
if (!document.DiscoFunctions.LogEventsFunctions) document.DiscoFunctions.LogEventsFunctions = {};
|
|
if (document.DiscoFunctions.LogEventsFunctions[liveEventReceivedFunction]){
|
|
liveEventReceivedFunction = document.DiscoFunctions.LogEventsFunctions[liveEventReceivedFunction];
|
|
}else{
|
|
liveEventReceivedFunction = null;
|
|
}
|
|
}
|
|
|
|
logHub = $.connection.logNotifications;
|
|
logHub.client.receiveLog = function(message){
|
|
if (message.UseDisplay) logsViewModel.EventLogs.unshift(message);
|
|
if (liveEventReceivedFunction) liveEventReceivedFunction(message);
|
|
};
|
|
|
|
$.connection.hub.qs = {LogModules: logModuleLiveGroupName};
|
|
$.connection.hub.error(onHubFailed);
|
|
|
|
$.connection.hub.start().fail(onHubFailed);
|
|
|
|
function onHubFailed(error) {
|
|
// Show Dialog Message
|
|
if ($('.disconnected-dialog').length == 0) {
|
|
$('<div>')
|
|
.addClass('dialog disconnected-dialog')
|
|
.html('<h3><span class="fa-stack fa-lg"><i class="fa fa-wifi fa-stack-1x"></i><i class="fa fa-ban fa-stack-2x error"></i></span>Disconnected from the Disco ICT Server</h3><div>This page is not receiving live updates. Please ensure you are connected to the server, then refresh this page to enable features.</div>')
|
|
.dialog({
|
|
resizable: false,
|
|
title: 'Disconnected',
|
|
width: 400,
|
|
modal: true,
|
|
buttons: {
|
|
'Refresh Now': function () {
|
|
$(this).dialog('option', 'buttons', null);
|
|
window.location.reload(true);
|
|
},
|
|
'Close': function () {
|
|
$(this).dialog('destroy');
|
|
}
|
|
}
|
|
});
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
loadInitialData();
|
|
});
|
|
</script>
|
|
</div>
|