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
This commit is contained in:
parent
d5c822c143
commit
22d142204d
@ -11,6 +11,8 @@
|
|||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.0.0/knockout-min.js" type="text/javascript"></script>
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.0.0/knockout-min.js" type="text/javascript"></script>
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/sammy.js/0.7.6/sammy.js" type="text/javascript"></script>
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/sammy.js/0.7.6/sammy.js" type="text/javascript"></script>
|
||||||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
|
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
|
||||||
|
<link rel="stylesheet" href="css/easymde.min.css" />
|
||||||
|
<link rel="stylesheet" href="css/highlightjs.min.css" />
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<nav class="navbar navbar-default">
|
<nav class="navbar navbar-default">
|
||||||
@ -37,14 +39,14 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
<div id="GroupAdminPage" class="container">
|
<div id="GroupAdminPage" class="container">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<h2 class="col-md-4">Groups</h2>
|
<h2 class="col-md-4">Groups</h2>
|
||||||
<button class="col-md-1 btn btn-default pull-right" style="margin-top: 20px;" data-bind="click: $root.newGroupForm">
|
<button class="col-md-1 btn btn-default pull-right" style="margin-top: 20px;" data-bind="click: $root.newGroupForm">
|
||||||
<span class="glyphicon glyphicon-plus"></span>
|
<span class="glyphicon glyphicon-plus"></span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<hr/>
|
<hr />
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div data-bind="with: groupsList, css:{'col-md-8': !$root.groupFormHidden(), 'col-md-12':$root.groupFormHidden()}">
|
<div data-bind="with: groupsList, css:{'col-md-8': !$root.groupFormHidden(), 'col-md-12':$root.groupFormHidden()}">
|
||||||
<table class="table table-striped">
|
<table class="table table-striped">
|
||||||
@ -68,15 +70,17 @@
|
|||||||
<input type="hidden" name="id" data-bind="value: Id">
|
<input type="hidden" name="id" data-bind="value: Id">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="groupNameEdit">Group Name</label>
|
<label for="groupNameEdit">Group Name</label>
|
||||||
<input for="Name" type="text" class="form-control" id="groupNameEdit" placeholder="Group Name" data-bind="value: Name"/>
|
<input for="Name" type="text" class="form-control" id="groupNameEdit" placeholder="Group Name" data-bind="value: Name" />
|
||||||
</div>
|
</div>
|
||||||
<button pageDestination="Users" class="btn btn-secondary" type="button"
|
<button pageDestination="Users" class="btn btn-secondary" type="button"
|
||||||
data-bind="click: $root.hideGroupForm">Cancel</button>
|
data-bind="click: $root.hideGroupForm">
|
||||||
|
Cancel
|
||||||
|
</button>
|
||||||
|
|
||||||
<button type="submit" class="btn btn-primary">Submit</button>
|
<button type="submit" class="btn btn-primary">Submit</button>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="CardManagement" class="container">
|
<div id="CardManagement" class="container">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<h2 class="col-md-4">Unassigned Cards</h2>
|
<h2 class="col-md-4">Unassigned Cards</h2>
|
||||||
@ -103,7 +107,63 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<script src="Helpers.min.js" type="text/javascript"></script>
|
<div id="PolicyManagement" class="container">
|
||||||
|
<div id="row">
|
||||||
|
<ul class="nav nav-tabs">
|
||||||
|
<li class="active"><a href="#edit" data-toggle="tab" >Edit</a></li>
|
||||||
|
<li ><a href="#preview" data-toggle="tab" >Preview</a></li>
|
||||||
|
</ul>
|
||||||
|
<div class="tab-content" style="max-height: 500px; min-height: 400px;overflow-y: auto">
|
||||||
|
<div id="edit" class="tab-pane fade in active">
|
||||||
|
<textarea id="policyEditor"></textarea>
|
||||||
|
</div>
|
||||||
|
<div id="preview" class="tab-pane fade in">
|
||||||
|
<div data-bind="html: previewHtml" class="well-lg"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<button class="btn btn-primary pull-right" data-bind="click: $root.policySave">Save</button>
|
||||||
|
<button class="btn btn-secondary pull-right" data-bind="click: $root.policyReload">Cancel</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="saveDialog" class="modal fade" role="dialog" data-bind="with: policyData">
|
||||||
|
<div class="modal-dialog">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<button type="button" class="close" data-dismiss="modal">×</button>
|
||||||
|
<h4 data-bind="text: ApplicationName"></h4>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<table class="table">
|
||||||
|
<tr>
|
||||||
|
<th>Change Author</th>
|
||||||
|
<td data-bind="text: ChangeAuthor"></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>Change Date</th>
|
||||||
|
<td><input id="changeDatePicker" type="datetime" data-bind="value: ChangeDate"/></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>Version</th>
|
||||||
|
<td data-bind="text: Version"></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>Database Provider</th>
|
||||||
|
<td data-bind="text: DataBaseProvider"></td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script src="Helpers.min.js" type="text/javascript"></script>
|
||||||
|
<script src="js/easymde.min.js" type="text/javascript"></script>
|
||||||
|
<script src="js/highlightjs.min.js" type="text/javascript"></script>
|
||||||
|
<script src="js/htmlparser.min.js" type="text/javascript"></script>
|
||||||
|
<script src="js/marked.min.js"></script>
|
||||||
<script src="admin.js" type="text/javascript"></script>
|
<script src="admin.js" type="text/javascript"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
@ -4,6 +4,70 @@
|
|||||||
self.groupEditItem = ko.observable(null);
|
self.groupEditItem = ko.observable(null);
|
||||||
self.unassignedCardList = ko.observable(null);
|
self.unassignedCardList = ko.observable(null);
|
||||||
self.helpers = new Helpers();
|
self.helpers = new Helpers();
|
||||||
|
self.policyMarkdown = "";
|
||||||
|
self.previewHtml = ko.observable("");
|
||||||
|
self.renderer = new marked.Renderer();
|
||||||
|
self.renderer.blockquote = function(quote) {
|
||||||
|
return "<blockquote class=\"blockquote\">" + quote + "</blockquote>";
|
||||||
|
};
|
||||||
|
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 "<h" + level + " id=\"" + escaped + "\">"
|
||||||
|
// NOTE: We're setting display none INLINE, so you have
|
||||||
|
// to override with !important if you want it to show.
|
||||||
|
+ " <a class=\"heading-anchor\" style=\"display:none;\" href=\"#" + escaped + '">'
|
||||||
|
+ " <i class=\"oi oi-link-intact\"></i>"
|
||||||
|
+ " </a>"
|
||||||
|
+ text
|
||||||
|
+ "</h" + level + ">";
|
||||||
|
};
|
||||||
|
self.renderer.table = function(header, body) {
|
||||||
|
return "<table class=\"table\">" +
|
||||||
|
"<thead class=\"thead-default\">" +
|
||||||
|
header +
|
||||||
|
"</thead>" +
|
||||||
|
"<tbody>" +
|
||||||
|
body +
|
||||||
|
"</tbody>" +
|
||||||
|
"</table>";
|
||||||
|
};
|
||||||
|
/*
|
||||||
|
* 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 "<pre><code class=\"hljs lang-" + language + "\">" + highlighted + "</code></pre>";
|
||||||
|
};
|
||||||
|
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 = {
|
self.uiPages = {
|
||||||
overview: "overview",
|
overview: "overview",
|
||||||
group: "groups",
|
group: "groups",
|
||||||
@ -14,7 +78,9 @@
|
|||||||
getGroups: "/api/groups",
|
getGroups: "/api/groups",
|
||||||
editGroup: "/api/groups/edit",
|
editGroup: "/api/groups/edit",
|
||||||
getUnassignedCards: "/api/cards/unassigned",
|
getUnassignedCards: "/api/cards/unassigned",
|
||||||
clearUnassignedCards: "/api/cards/unassigned"
|
clearUnassignedCards: "/api/cards/unassigned",
|
||||||
|
getPolicy:"/api/app/policy",
|
||||||
|
savePolicy:"/api/app/policy"
|
||||||
};
|
};
|
||||||
self.clearGroupForm = function () {
|
self.clearGroupForm = function () {
|
||||||
self.helpers.goToMenuOption(self.uiPages.group);
|
self.helpers.goToMenuOption(self.uiPages.group);
|
||||||
@ -50,7 +116,7 @@
|
|||||||
false);
|
false);
|
||||||
$.ajax({
|
$.ajax({
|
||||||
url: url,
|
url: url,
|
||||||
type: 'DELETE',
|
type: "DELETE",
|
||||||
success: function () {
|
success: function () {
|
||||||
console.log("deleted " + groupId);
|
console.log("deleted " + groupId);
|
||||||
self.hideGroupForm();
|
self.hideGroupForm();
|
||||||
@ -100,6 +166,32 @@
|
|||||||
self.padNumber = function (number) {
|
self.padNumber = function (number) {
|
||||||
return (number < 10 ? "0" : "") + 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) {
|
self.convertToDisplayDateTime = function (dateValue) {
|
||||||
var date = new Date(dateValue); // dd MM YY HH:mm:ss e.g.: 01 Mar 17 17:34:02
|
var date = new Date(dateValue); // dd MM YY HH:mm:ss e.g.: 01 Mar 17 17:34:02
|
||||||
return date.getDate() + " "
|
return date.getDate() + " "
|
||||||
@ -114,6 +206,7 @@
|
|||||||
this.get("#overview", function () {
|
this.get("#overview", function () {
|
||||||
self.getGroups();
|
self.getGroups();
|
||||||
self.getUnassignedCardData();
|
self.getUnassignedCardData();
|
||||||
|
self.policyReload();
|
||||||
});
|
});
|
||||||
this.post("#editgroup", function () {
|
this.post("#editgroup", function () {
|
||||||
self.submitGroupEdit(self.groupEditItem());
|
self.submitGroupEdit(self.groupEditItem());
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user