From 22d142204d85e02e6d97baa82cd367da14a2a86a Mon Sep 17 00:00:00 2001 From: "chris.watts90@outlook.com" Date: Fri, 18 Oct 2019 09:51:24 +0100 Subject: [PATCH] Add policy editor to the admin screen WIP - Adding save dialog to enter description of change, version, author etc. admin.js Added Markdown custom renderer Added policy reload and policy save --- .../WindowsDataCenter/www/Admin.html | 276 ++++++++------ .../WindowsDataCenter/www/admin.js | 343 +++++++++++------- 2 files changed, 386 insertions(+), 233 deletions(-) diff --git a/DataCenter_Windows/WindowsDataCenter/WindowsDataCenter/www/Admin.html b/DataCenter_Windows/WindowsDataCenter/WindowsDataCenter/www/Admin.html index b6667d0..675c057 100644 --- a/DataCenter_Windows/WindowsDataCenter/WindowsDataCenter/www/Admin.html +++ b/DataCenter_Windows/WindowsDataCenter/WindowsDataCenter/www/Admin.html @@ -1,109 +1,169 @@ - - - - - - Flexitime Admin page - - - - - - - - - - -
-
-

Groups

- -
-
-
-
- - - - - - - - - - - - - - - -
NameUser Count
-
-
- -
- - -
- - - -
-
-
-
-
-

Unassigned Cards

- -
-
-
- - - - - - - - - - - - - -
Card Unique IdLast Used Date
-
-
-
- - - + + + + + + Flexitime Admin page + + + + + + + + + + + + +
+
+

Groups

+ +
+
+
+
+ + + + + + + + + + + + + + + +
NameUser Count
+
+
+ +
+ + +
+ + + +
+
+
+
+
+

Unassigned Cards

+ +
+
+
+ + + + + + + + + + + + + +
Card Unique IdLast Used Date
+
+
+
+
+
+ +
+
+ +
+
+
+
+
+ + +
+
+ + + + + + + + + \ No newline at end of file diff --git a/DataCenter_Windows/WindowsDataCenter/WindowsDataCenter/www/admin.js b/DataCenter_Windows/WindowsDataCenter/WindowsDataCenter/www/admin.js index b912835..71b08ad 100644 --- a/DataCenter_Windows/WindowsDataCenter/WindowsDataCenter/www/admin.js +++ b/DataCenter_Windows/WindowsDataCenter/WindowsDataCenter/www/admin.js @@ -1,126 +1,219 @@ -function AdminVM() { - var self = this; - self.groupsList = ko.observable(null); - self.groupEditItem = ko.observable(null); - self.unassignedCardList = ko.observable(null); - self.helpers = new Helpers(); - self.uiPages = { - overview: "overview", - group: "groups", - home: function () { return this.overview; } - }; - self.apiEndpoints = { - deleteGroups:"/api/groups/delete", - getGroups: "/api/groups", - editGroup: "/api/groups/edit", - getUnassignedCards: "/api/cards/unassigned", - clearUnassignedCards: "/api/cards/unassigned" - }; - self.clearGroupForm = function () { - self.helpers.goToMenuOption(self.uiPages.group); - self.groupEditItem(null); - }; - self.hideGroupForm = function () { - self.groupEditItem(null); - }; - self.newGroupForm = function () { - self.groupEditItem({ Id: -1, Name: "" }); - self.helpers.goToMenuOption(self.uiPages.group); - }; - self.groupFormHidden = ko.computed(function () { - return self.groupEditItem() == null; - }, self); - self.editGroupClick = function (data) { - self.helpers.goToMenuOption(self.uiPages.group); - self.groupEditItem(data); - }; - self.getGroups = function () { - var url = self.helpers.createRequestUrl(self.apiEndpoints.getGroups, null, false); - $.getJSON(url, function (res) { - self.groupsList(res); - }).fail(function (resp, status, error) { - console.log("error - getGroups"); - var errorObj = self.helpers.processRequestFailure(resp, status, error); - }); - }; - self.deleteGroup = function (groupId) { - var url = self.helpers.createRequestUrl(self.apiEndpoints.deleteGroups, - [{ key: "groupId", value: groupId }], - false, - false); - $.ajax({ - url: url, - type: 'DELETE', - success: function () { - console.log("deleted " + groupId); - self.hideGroupForm(); - self.helpers.goToMenuOption(self.uiPages.home()); - } - }); - console.log("delete: " + groupId); - }; - self.submitGroupEdit = function(group) { - var url = self.helpers.createRequestUrl(self.apiEndpoints.editGroup, null, false); - $.post(url, group, function () { - }, "json") - .done(function () { - self.groupEditItem(null); - self.helpers.goToMenuOption(self.uiPages.home()); - }) - .fail(function (resp, status, error) { - self.helpers.goToMenuOption(self.uiPages.home()); - var errorObj = self.helpers.processRequestFailure(resp, status, error); - }); - }; - self.getUnassignedCardData = function() { - var url = self.helpers.createRequestUrl(self.apiEndpoints.getUnassignedCards, null, false); - $.getJSON(url, - function(res) { - self.unassignedCardList(res); - }).fail(function(resp, status, error) { - console.log("error - getUnassignedCards"); - var errorObj = self.helpers.processRequestFailure(resp, status, error); - }); - }; - self.clearUnassignedCards = function() { - var url = self.helpers.createRequestUrl(self.apiEndpoints.clearUnassignedCards, null, false); - $.ajax({ - type: "DELETE", - url: url, - data: "", - success: function() { - self.getUnassignedCardData(); //update - }, - error: function(jqxhr, status, error) { - console.log("error - clearUnassignedCards"); - var errorObj = self.helpers.processRequestFailure(resp, status, error); - } - }); - }; - self.padNumber = function (number) { - return (number < 10 ? "0" : "") + number; - }; - self.convertToDisplayDateTime = function (dateValue) { - var date = new Date(dateValue); // dd MM YY HH:mm:ss e.g.: 01 Mar 17 17:34:02 - return date.getDate() + " " - + date.toLocaleString("en-us", { month: "long" }) + " " - + (date.getYear()-100) + " " - + self.padNumber(date.getHours()) + ":" - + self.padNumber(date.getMinutes()) + ":" - + self.padNumber(date.getSeconds()); - }; - Sammy(function () { - this.disable_push_state = true; - this.get("#overview", function () { - self.getGroups(); - self.getUnassignedCardData(); - }); - this.post("#editgroup", function () { - self.submitGroupEdit(self.groupEditItem()); - return false; - }); - //default route (home page) - this.get("", function () { this.app.runRoute("get", "#" + self.uiPages.home()) }); - }).run(); -}; +function AdminVM() { + var self = this; + self.groupsList = ko.observable(null); + self.groupEditItem = ko.observable(null); + self.unassignedCardList = ko.observable(null); + self.helpers = new Helpers(); + self.policyMarkdown = ""; + self.previewHtml = ko.observable(""); + self.renderer = new marked.Renderer(); + self.renderer.blockquote = function(quote) { + return "
" + quote + "
"; + }; + self.renderer.heading = function (text, level) { + + var parserHandler = new Tautologistics.NodeHtmlParser.DefaultHandler(function (error) { + if (error) + throw new Error("Cannot parse \"" + text + "\" in markdown file."); + }); + var parser = new Tautologistics.NodeHtmlParser.Parser(parserHandler); + + parser.parseComplete(text); + var escaped = "unknown"; + + if (parserHandler.dom.length > 0) { + escaped = parserHandler.dom[0].raw.toLowerCase().trim().replace(/ /g, "-"); + } + + return "" + // NOTE: We're setting display none INLINE, so you have + // to override with !important if you want it to show. + + " ' + + " " + + " " + + text + + ""; + }; + self.renderer.table = function(header, body) { + return "" + + "" + + header + + "" + + "" + + body + + "" + + "
"; + }; + /* + * Adds highlight.js classes to `code` blocks + */ + self.renderer.code = function(code, language) { + + var valid = !!(language && hljs.getLanguage(language)); + var highlighted = valid ? hljs.highlight(language, code).value : code + + return "
" + highlighted + "
"; + }; + self.editor = new EasyMDE({ + element: document.getElementById("policyEditor"), + showIcons: ["bold", "italic", "strikethrough", "heading", "heading-smaller", "heading-bigger", "heading-1", "heading-2", "heading-3", "code", "quote", "unordered-list", "ordered-list", "clean-block", "link", "table", "horizontal-rule", "guide", "table"], + hideIcons: ["preview", "side-by-side", "fullscreen"], + renderingConfig: { + markedOptions: { + renderer: self.renderer + } + } + }); + self.editor.codemirror.on("changes", + function () { + self.previewHtml(self.editor.options.previewRender(self.editor.value())); + }); + self.uiPages = { + overview: "overview", + group: "groups", + home: function () { return this.overview; } + }; + self.apiEndpoints = { + deleteGroups:"/api/groups/delete", + getGroups: "/api/groups", + editGroup: "/api/groups/edit", + getUnassignedCards: "/api/cards/unassigned", + clearUnassignedCards: "/api/cards/unassigned", + getPolicy:"/api/app/policy", + savePolicy:"/api/app/policy" + }; + self.clearGroupForm = function () { + self.helpers.goToMenuOption(self.uiPages.group); + self.groupEditItem(null); + }; + self.hideGroupForm = function () { + self.groupEditItem(null); + }; + self.newGroupForm = function () { + self.groupEditItem({ Id: -1, Name: "" }); + self.helpers.goToMenuOption(self.uiPages.group); + }; + self.groupFormHidden = ko.computed(function () { + return self.groupEditItem() == null; + }, self); + self.editGroupClick = function (data) { + self.helpers.goToMenuOption(self.uiPages.group); + self.groupEditItem(data); + }; + self.getGroups = function () { + var url = self.helpers.createRequestUrl(self.apiEndpoints.getGroups, null, false); + $.getJSON(url, function (res) { + self.groupsList(res); + }).fail(function (resp, status, error) { + console.log("error - getGroups"); + var errorObj = self.helpers.processRequestFailure(resp, status, error); + }); + }; + self.deleteGroup = function (groupId) { + var url = self.helpers.createRequestUrl(self.apiEndpoints.deleteGroups, + [{ key: "groupId", value: groupId }], + false, + false); + $.ajax({ + url: url, + type: "DELETE", + success: function () { + console.log("deleted " + groupId); + self.hideGroupForm(); + self.helpers.goToMenuOption(self.uiPages.home()); + } + }); + console.log("delete: " + groupId); + }; + self.submitGroupEdit = function(group) { + var url = self.helpers.createRequestUrl(self.apiEndpoints.editGroup, null, false); + $.post(url, group, function () { + }, "json") + .done(function () { + self.groupEditItem(null); + self.helpers.goToMenuOption(self.uiPages.home()); + }) + .fail(function (resp, status, error) { + self.helpers.goToMenuOption(self.uiPages.home()); + var errorObj = self.helpers.processRequestFailure(resp, status, error); + }); + }; + self.getUnassignedCardData = function() { + var url = self.helpers.createRequestUrl(self.apiEndpoints.getUnassignedCards, null, false); + $.getJSON(url, + function(res) { + self.unassignedCardList(res); + }).fail(function(resp, status, error) { + console.log("error - getUnassignedCards"); + var errorObj = self.helpers.processRequestFailure(resp, status, error); + }); + }; + self.clearUnassignedCards = function() { + var url = self.helpers.createRequestUrl(self.apiEndpoints.clearUnassignedCards, null, false); + $.ajax({ + type: "DELETE", + url: url, + data: "", + success: function() { + self.getUnassignedCardData(); //update + }, + error: function(jqxhr, status, error) { + console.log("error - clearUnassignedCards"); + var errorObj = self.helpers.processRequestFailure(resp, status, error); + } + }); + }; + self.padNumber = function (number) { + return (number < 10 ? "0" : "") + number; + }; + self.policySave = function () { + var url = self.helpers.createRequestUrl(self.apiEndpoints.savePolicy, null, false); + var policy = { markdown: self.editor.value(), html: self.previewHtml() }; + console.log(policy); + $.post(url, policy, function() { + }, "json") + .done(function() { + self.policyReload(); + }).fail(function(resp, status, error) { + var errorObj = self.helpers.processRequestFailure(resp, status, error); + console.log(errorObj); + }); + }; + self.policyReload = function() { + var url = self.helpers.createRequestUrl(self.apiEndpoints.getPolicy, + [], false, false); + $.getJSON(url, function (res) { + console.log(res); + self.editor.value(res.Markdown); + self.previewHtml(res.Html); + }).fail(function (resp, status, error) { + console.log("error - policyReload"); + var errObj = self.helpers.processRequestFailure(resp, status, error); + self.assignErrorObject(errObj.errorCode, errObj.errorMessage, "policyReload"); + }); + }; + self.convertToDisplayDateTime = function (dateValue) { + var date = new Date(dateValue); // dd MM YY HH:mm:ss e.g.: 01 Mar 17 17:34:02 + return date.getDate() + " " + + date.toLocaleString("en-us", { month: "long" }) + " " + + (date.getYear()-100) + " " + + self.padNumber(date.getHours()) + ":" + + self.padNumber(date.getMinutes()) + ":" + + self.padNumber(date.getSeconds()); + }; + Sammy(function () { + this.disable_push_state = true; + this.get("#overview", function () { + self.getGroups(); + self.getUnassignedCardData(); + self.policyReload(); + }); + this.post("#editgroup", function () { + self.submitGroupEdit(self.groupEditItem()); + return false; + }); + //default route (home page) + this.get("", function () { this.app.runRoute("get", "#" + self.uiPages.home()) }); + }).run(); +}; ko.applyBindings(new AdminVM()); \ No newline at end of file