diff --git a/SaBusinessMgrCoreWebControl/Views/Shared/_Layout.cshtml b/SaBusinessMgrCoreWebControl/Views/Shared/_Layout.cshtml
index 12a3738..3654e9a 100644
--- a/SaBusinessMgrCoreWebControl/Views/Shared/_Layout.cshtml
+++ b/SaBusinessMgrCoreWebControl/Views/Shared/_Layout.cshtml
@@ -128,7 +128,8 @@
@@ -148,7 +149,7 @@
@Localiser["label.system"]
diff --git a/SaBusinessMgrCoreWebControl/Views/System/Logs.cshtml b/SaBusinessMgrCoreWebControl/Views/System/Logs.cshtml
new file mode 100644
index 0000000..425dbe2
--- /dev/null
+++ b/SaBusinessMgrCoreWebControl/Views/System/Logs.cshtml
@@ -0,0 +1,120 @@
+@model Model_System
+@inject SbmLocaliser Localiser
+@{
+ ViewData["Title"] = "System - Logs";
+ Model.AdditionalFiles_JS.Add("js/sbc-sys-logs.js");
+}
+
+
+
+
+
+
+
+
+ @using (@Html.BeginForm(FormMethod.Post, new { @id = "frmLogsFilter", @class = "sbc-form", @onSubmit = "return false;" }))
+ {
+
+
+
+
@Localiser["label.root.folder"]
+
@(Model.LoggingRootFolder)
+
+
+
@Localiser["label.folder"]
+
+
+
+
@Localiser["label.year"]
+
+
+
+
@Localiser["label.month"]
+
+
+
+ }
+
+
+
+
+ @* Log file list. *@
+
+
+
+
+ | @Localiser["label.file"] |
+ @Localiser["label.updated"] |
+ @Localiser["label.size"] |
+
+
+
+
+
+ @* Log file template. *@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/SaBusinessMgrCoreWebControl/Views/_ViewImports.cshtml b/SaBusinessMgrCoreWebControl/Views/_ViewImports.cshtml
index fe268c1..745164b 100644
--- a/SaBusinessMgrCoreWebControl/Views/_ViewImports.cshtml
+++ b/SaBusinessMgrCoreWebControl/Views/_ViewImports.cshtml
@@ -6,4 +6,5 @@
@using Sarand.BusinessMgr.Web.Control.Models.Account
@using Sarand.BusinessMgr.Web.Control.Models.Instance
@using Sarand.BusinessMgr.Web.Control.Models.Param
+@using Sarand.BusinessMgr.Web.Control.Models.System
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
diff --git a/SaBusinessMgrCoreWebControl/wwwroot/js/sbc-home.js b/SaBusinessMgrCoreWebControl/wwwroot/js/sbc-home.js
index 29bd5e0..3cb94fd 100644
--- a/SaBusinessMgrCoreWebControl/wwwroot/js/sbc-home.js
+++ b/SaBusinessMgrCoreWebControl/wwwroot/js/sbc-home.js
@@ -27,7 +27,7 @@
var $msgs = $('.sbc-panel-messages', $pnlSchema).hide().empty().append($('
' + sbc.msg.dataQuerying + '
')).fadeIn(200);
}
$('.DatabaseInstance', $frm.dbSchema).val(instance);
- sbc.ajax.dbSchema = sbc.ajax.dbSchema || { url: sbc.url.base + 'System/Ajax/ValidateDatabaseSchema', formId: $frm.dbSchema.prop('id'), callbackFn: ch.handleDbSchemaResponse, noWaitIcon: true };
+ sbc.ajax.dbSchema = sbc.ajax.dbSchema || { url: sbc.url.base + 'System/Ajax/ValidateDatabaseSchema', formSel: $frm.dbSchema, callbackFn: ch.handleDbSchemaResponse, noWaitIcon: true };
sbc.doAjaxRequest(sbc.ajax.dbSchema, delay || 50);
ch.awaitingSchemaResponse = true;
}
diff --git a/SaBusinessMgrCoreWebControl/wwwroot/js/sbc-ins-coredb.js b/SaBusinessMgrCoreWebControl/wwwroot/js/sbc-ins-rep-db.js
similarity index 96%
rename from SaBusinessMgrCoreWebControl/wwwroot/js/sbc-ins-coredb.js
rename to SaBusinessMgrCoreWebControl/wwwroot/js/sbc-ins-rep-db.js
index 592c05e..1638b3f 100644
--- a/SaBusinessMgrCoreWebControl/wwwroot/js/sbc-ins-coredb.js
+++ b/SaBusinessMgrCoreWebControl/wwwroot/js/sbc-ins-rep-db.js
@@ -18,7 +18,7 @@
env.$pnl.table.find('tbody tr').remove();
env.$pnl.msgs.hide().empty().append($('
' + sbc.msg.dataQuerying + '
')).fadeIn(200);
}
- env.ajax.tables = env.ajax.tables || { url: sbc.url.base + 'Instance/CoreDatabase/Ajax/GetTables', formSel: env.$frm.filter, callbackFn: function (response) { cd.displayItems(env, response); } };
+ env.ajax.tables = env.ajax.tables || { url: sbc.url.base + 'Instance/Repository/Ajax/GetTables', formSel: env.$frm.filter, callbackFn: function (response) { cd.displayItems(env, response); } };
sbc.doAjaxRequest(env.ajax.tables, delay || 50);
cd.awaitingRefreshResponse = true;
}
diff --git a/SaBusinessMgrCoreWebControl/wwwroot/js/sbc-ins-rep-sch.js b/SaBusinessMgrCoreWebControl/wwwroot/js/sbc-ins-rep-sch.js
new file mode 100644
index 0000000..617f368
--- /dev/null
+++ b/SaBusinessMgrCoreWebControl/wwwroot/js/sbc-ins-rep-sch.js
@@ -0,0 +1,81 @@
+/*
+ * SBM - Control - Instance - Core Database.
+ */
+
+(function (win, doc, undef)
+{
+ "use strict";
+ let ds = sbc.mdl.repDbSchema = { env: {}, data: {} };
+ let $pnl = ds.$pnl = {}, $frm = ds.$frm = {}, $dlg = ds.$dlg = {};
+
+ //--------------------------------------------------------------
+ ds.refreshDbSchema = function (delay)
+ {
+ if (sbc.awaitingLogin) return;
+ if (!$frm.filter.find('.FilterContext').val()) return;
+ if (!ds.awaitingSchemaResponse)
+ {
+ $pnl.msgs.hide().empty().append($('
' + sbc.msg.dataQuerying + '
')).fadeIn(200);
+ }
+ ds.clearItems();
+ sbc.ajax.dbSchema = sbc.ajax.dbSchema || { url: sbc.url.base + 'System/Ajax/ValidateDatabaseSchema', formSel: $frm.filter, callbackFn: ds.handleDbSchemaResponse, noWaitIcon: true };
+ sbc.doAjaxRequest(sbc.ajax.dbSchema, delay || 50);
+ ds.awaitingSchemaResponse = true;
+ }
+ ds.handleDbSchemaResponse = function (response)
+ {
+ //sbc.debug('handleDbSchemaResponse', response);
+ delete ds.awaitingSchemaResponse;
+ $pnl.msgs.hide().empty();
+ var $table = $pnl.table.find('table.sbc-item-list');
+ ds.clearItems();
+ if (!response.success) return;
+ // Items.
+ var items = response.items;
+ if (!items.length)
+ return $pnl.msgs.append($('
' + sbc.msg.dbSchemaValid + '
')).fadeIn(500);
+ for (const item of items)
+ $table.append(ds.populateDbSchemaItem(ds.getDbSchemaRowTemplate(), item));
+ }
+ ds.getDbSchemaTableTemplate = function ()
+ {
+ return $pnl.tmpl.find('.sbc-panel-item-table.Schema').clone().hide();
+ }
+ ds.getDbSchemaRowTemplate = function ()
+ {
+ return $pnl.tmpl.find('.sbc-row-item.SchemaItem').clone();
+ }
+ ds.populateDbSchemaItem = function ($item, item)
+ {
+ if (!item) return;
+ $item.prop('id', sbc.itemIdPrefix + item.id);
+ $('.SchemaName', $item).text(item.schemaName);
+ $('.TableName', $item).text(item.tableName);
+ $('.IndexName', $item).text(item.indexName);
+ $('.ColumnName', $item).text(item.columnName);
+ $('.Comment', $item).text(item.comment);
+ return $item;
+ }
+ ds.clearItems = function ()
+ {
+ $pnl.table.find('table.sbc-item-list').find('tbody tr').remove();
+ }
+
+ //--------------------------------------------------------------
+ $(function ()
+ {
+ $pnl.items = $('.sbc-panel.Schema');
+ $frm.filter = $pnl.items.find('#frmSchemaFilter');
+ $frm.filter.on('change', '.FilterContext', ds.refreshDbSchema);
+ $frm.filter.on('input', '.FilterSearch', ds.refreshDbSchema);
+ $frm.filter.find('.FilterInstance').val('BusMgr');
+ $pnl.table = $pnl.items.find('.sbc-panel-item-table');
+ $pnl.msgs = $pnl.items.find('.sbc-panel-messages');
+ $pnl.tmpl = $pnl.items.find('.sbc-panel-item-template');
+ setTimeout(function () { ds.refreshDbSchema(); }, 500);
+ });
+
+ //--------------------------------------------------------------
+}(window, window.document));
+
+/* The End */
\ No newline at end of file
diff --git a/SaBusinessMgrCoreWebControl/wwwroot/js/sbc-sys-logs.js b/SaBusinessMgrCoreWebControl/wwwroot/js/sbc-sys-logs.js
new file mode 100644
index 0000000..2e25bae
--- /dev/null
+++ b/SaBusinessMgrCoreWebControl/wwwroot/js/sbc-sys-logs.js
@@ -0,0 +1,289 @@
+/*
+ * Admin - System Logs page scripts.
+ */
+
+(function (win, doc, undef)
+{
+ "use strict";
+ let sl = sbc.sysLogs = { data: {}, $pnl: {}, $frm: {}, $ctrl: {}, $dlg: {} };
+ let $pnl = sl.$pnl; let $frm = sl.$frm; let $ctrl = sl.$ctrl; let $dlg = sl.$dlg;
+
+ //--------------------------------------------------------------
+ sl.refreshFolders = function (delay)
+ {
+ if (!sl.data.awaitingRefreshFoldersResponse)
+ {
+ sl.clearFiles();
+ //$pnl.msgs.hide().empty().append($('
' + sbc.msg.dataQuerying + '
')).fadeIn(200);
+ }
+ sbc.ajax.refreshFolders = sbc.ajax.refreshFolders || { url: sbc.url.base + 'System/Ajax/Logs/GetFolders', formSel: sl.$frm.filter, callbackFn: sl.doRefreshFolders };
+ sbc.doAjaxRequest(sbc.ajax.refreshFolders, delay || 50);
+ sl.data.awaitingRefreshFoldersResponse = true;
+ }
+ sl.doRefreshFolders = function (response)
+ {
+ sbc.debug('doRefreshFolders', response);
+ delete sl.data.awaitingRefreshFoldersResponse;
+ sl.clearFilterFolders();
+ sbc.refreshControlValues(response.controlValues);
+ $pnl.msgs.hide().empty();
+ if (!response.success) return;
+ // Folders.
+ var items = response.folders;
+ if (!items.length)
+ return $pnl.msgs.append($('
' + sbc.msg.dataNoneFound + '
')).fadeIn(500);
+ for (const item of items)
+ $ctrl.cbFolders.append($('
'));
+ if (sbc.data.logFolder) $ctrl.cbFolders.val(sbc.data.logFolder);
+ if (!$ctrl.cbFolders.val()) $ctrl.cbFolders.val(items[0].name);
+ delete sbc.data.logFolder;
+ if ($ctrl.cbFolders.val()) $ctrl.cbFolders.trigger('change');
+ }
+
+ //--------------------------------------------------------------
+ sl.clearFilterFolders = function ()
+ {
+ sl.clearFilterYears();
+ $('option', $ctrl.cbFolders).remove();
+ }
+ sl.clearFilterYears = function ()
+ {
+ sl.clearFilterMonths();
+ $('option', $ctrl.cbYears).remove();
+ }
+ sl.clearFilterMonths = function ()
+ {
+ sl.clearFiles();
+ $('option', $ctrl.cbMonths).remove();
+ }
+ sl.clearFiles = function ()
+ {
+ $pnl.msgs.hide().empty();
+ $pnl.list.find('tbody tr').remove();
+ }
+
+ //--------------------------------------------------------------
+ sl.refreshYears = function (delay)
+ {
+ if (!sl.data.awaitingRefreshYearsResponse)
+ {
+ sl.clearFiles();
+ //$pnl.msgs.hide().empty().append($('
' + sbc.msg.dataQuerying + '
')).fadeIn(200);
+ }
+ sbc.ajax.refreshYears = sbc.ajax.refreshYears || { url: sbc.url.base + 'System/Ajax/Logs/GetYears', formSel: sl.$frm.filter, callbackFn: sl.doRefreshYears };
+ sbc.doAjaxRequest(sbc.ajax.refreshYears, delay || 50);
+ sl.data.awaitingRefreshYearsResponse = true;
+ }
+ sl.doRefreshYears = function (response)
+ {
+ //sbc.debug('doRefreshYears', response);
+ delete sl.data.awaitingRefreshYearsResponse;
+ sl.clearFilterYears();
+ sbc.refreshControlValues(response.controlValues);
+ $pnl.msgs.hide().empty();
+ if (!response.success) return;
+ // Years.
+ var items = response.years;
+ if (!items.length)
+ return $pnl.msgs.append($('
' + sbc.msg.dataNoneFound + '
')).fadeIn(500);
+ for (let itemIdx = 0; itemIdx < items.length; itemIdx++)
+ $ctrl.cbYears.append($('
'));
+ if (sbc.data.logYear) $ctrl.cbYears.val(sbc.data.logYear);
+ delete sbc.data.logYear;
+ if ($ctrl.cbYears.val()) $ctrl.cbYears.trigger('change');
+ }
+
+ //--------------------------------------------------------------
+ sl.refreshMonths = function (delay)
+ {
+ if (!sl.data.awaitingRefreshMonthsResponse)
+ {
+ sl.clearFiles();
+ //$pnl.msgs.hide().empty().append($('
' + sbc.msg.dataQuerying + '
')).fadeIn(200);
+ }
+ sbc.ajax.refreshMonths = sbc.ajax.refreshMonths || { url: sbc.url.base + 'System/Ajax/Logs/GetMonths', formSel: sl.$frm.filter, callbackFn: sl.doRefreshMonths };
+ sbc.doAjaxRequest(sbc.ajax.refreshMonths, delay || 50);
+ sl.data.awaitingRefreshMonthsResponse = true;
+ }
+ sl.doRefreshMonths = function (response)
+ {
+ //sbc.debug('doRefreshMonths', response);
+ delete sl.data.awaitingRefreshMonthsResponse;
+ sl.clearFilterMonths();
+ sbc.refreshControlValues(response.controlValues);
+ $pnl.msgs.hide().empty();
+ if (!response.success) return;
+ sbc.data.logYear = $ctrl.cbYears.val();
+ // Months.
+ var items = response.months;
+ if (!items.length)
+ return $pnl.msgs.append($('
' + sbc.msg.dataNoneFound + '
')).fadeIn(500);
+ for (let itemIdx = 0; itemIdx < items.length; itemIdx++)
+ $ctrl.cbMonths.append($('
'));
+ if (sbc.data.logMonth) $ctrl.cbMonths.val(sbc.data.logMonth);
+ if (!$ctrl.cbMonths.val() && items.length) $ctrl.cbMonths.val(items[0].name);
+ delete sbc.data.logMonth;
+ if ($ctrl.cbMonths.val()) $ctrl.cbMonths.trigger('change');
+ }
+
+ //--------------------------------------------------------------
+ sl.refreshFiles = function (delay)
+ {
+ if (!sl.data.awaitingRefreshFilesResponse)
+ {
+ sl.clearFiles();
+ //$pnl.msgs.hide().empty().append($('
' + sbc.msg.dataQuerying + '
')).fadeIn(200);
+ }
+ sbc.ajax.refreshFiles = sbc.ajax.refreshFiles || { url: sbc.url.base + 'System/Ajax/Logs/GetFiles', formSel: sl.$frm.filter, callbackFn: sl.doRefreshFiles };
+ sbc.doAjaxRequest(sbc.ajax.refreshFiles, delay || 50);
+ sl.data.awaitingRefreshFilesResponse = true;
+ }
+ sl.doRefreshFiles = function (response)
+ {
+ //sbc.debug('doRefreshFiles', response);
+ delete sl.data.awaitingRefreshFilesResponse;
+ sl.clearFiles();
+ sbc.refreshControlValues(response.controlValues);
+ if (!response.success) return;
+ sbc.data.logMonth = $ctrl.cbMonths.val();
+ // Files.
+ var items = response.files;
+ sl.data.files = response.files;
+ if (!(items || []).length)
+ return $pnl.msgs.append($('
' + sbc.msg.dataNoneFound + '
')).fadeIn(500);
+ for (let itemIdx = 0; itemIdx < items.length; itemIdx++)
+ $pnl.list.append(sl.populateItem(sl.getFileTemplate(), items[itemIdx]));
+ $pnl.list.fadeIn(50);
+ }
+ sl.populateItem = function ($item, item)
+ {
+ if (!item) return $item;
+ $item.off('click').on('click', function () { sl.showFile(item.name) });
+ $('.Filename', $item).text(item.name);
+ $('.Updated', $item).text(item.updateFmt);
+ $('.Size', $item).text(sbc.formatFileSize(item.size, 2));
+ return $item;
+ }
+ sl.getFileTemplate = function ()
+ {
+ return $('.sbc-panel-item-template .sbc-panel-item.LogFile', $pnl.results).clone();
+ }
+
+ //--------------------------------------------------------------
+ sl.showFile = function (filename, delay)
+ {
+ $('.FilterLogFilename', $frm.filter).val(filename);
+ sl.setFileTitle(filename);
+ if (!sl.data.awaitingGetFileResponse)
+ {
+ sl.setFileData($('
' + sbc.msg.dataQuerying + '
'));
+ sl.openFileDlg();
+ }
+ sbc.ajax.getFile = sbc.ajax.getFile || { url: sbc.url.base + 'System/Ajax/Logs/GetFile', formSel: sl.$frm.filter, callbackFn: sl.onShowFile };
+ sbc.doAjaxRequest(sbc.ajax.getFile, delay || 50);
+ sl.data.awaitingGetFileResponse = true;
+ }
+ sl.onShowFile = function (response)
+ {
+ //sbc.debug('doGetFiles', response);
+ delete sl.data.awaitingGetFileResponse;
+ $pnl.msgs.hide().empty();
+ if (!response.success) return;
+
+ // Configure file action buttons.
+ let files = sl.data.files;
+ let filename = response.file.name;
+ $ctrl.filePrev.prop('disabled', (files || []).length < 2 || !filename || files[0].name == filename);
+ $ctrl.fileNext.prop('disabled', (files || []).length < 2 || !filename || files[files.length - 1].name == filename);
+
+ // Display table details.
+ sl.setFileTitle(filename || response.popupTitle);
+ $('.LogFilename', $dlg.file).val(filename);
+ sl.setFileData(response.file.html);
+ sl.openFileDlg();
+ }
+ sl.openFileDlg = function ()
+ {
+ sbc.openDialog($dlg.file, $(win).width(), $(win).height());
+ }
+ sl.setFileTitle = function (filename)
+ {
+ $dlg.file.dialog('option', 'title', "File: " + filename);
+ }
+ sl.setFileData = function (data)
+ {
+ $('.FileData', $dlg.file).html(data);
+ }
+
+ //--------------------------------------------------------------
+ sl.onCreateLogFileDlg = function ()
+ {
+ let $btnPane = $('#dlgLogFile + div.ui-dialog-buttonpane');
+ $pnl.logFileActions = $('
');
+ $ctrl.filePrev = $('