2016-03-20 09:29:20 -04:00
|
|
|
"use strict";
|
|
|
|
|
2016-08-20 13:05:10 -04:00
|
|
|
//! {"category": "work in progress", "require": ["libdocument", "liblist", "ui"]}
|
2016-06-02 19:33:01 -04:00
|
|
|
|
2016-08-20 13:05:10 -04:00
|
|
|
let libdocument = require("libdocument");
|
|
|
|
let liblist = require("liblist");
|
|
|
|
let libui = require("ui");
|
2016-03-20 09:29:20 -04:00
|
|
|
|
2016-08-20 13:05:10 -04:00
|
|
|
class Blog {
|
|
|
|
constructor() {
|
|
|
|
this._list = liblist.ListStore("blog:list");
|
|
|
|
this._documents = libdocument.DocumentStore("blog:posts");
|
2016-03-20 09:29:20 -04:00
|
|
|
}
|
|
|
|
|
2016-08-20 13:05:10 -04:00
|
|
|
async renderIndex() {
|
|
|
|
terminal.cork();
|
|
|
|
try {
|
|
|
|
terminal.split([{name: "terminal"}]);
|
|
|
|
terminal.clear();
|
|
|
|
let posts = await this._list.get(-1, -10);
|
|
|
|
for (let i = 0; i < posts.length; i++) {
|
|
|
|
let post = await this._documents.get(posts[i]);
|
|
|
|
if (post) {
|
|
|
|
let formatted = this.formatPost(post);
|
|
|
|
for (let j in formatted) {
|
|
|
|
terminal.print(formatted[j]);
|
|
|
|
}
|
|
|
|
}
|
2016-03-20 09:29:20 -04:00
|
|
|
}
|
2016-08-20 13:05:10 -04:00
|
|
|
if (core.user.credentials.permissions.administration) {
|
|
|
|
terminal.print({command: JSON.stringify({action: "new"}), value: "new post"});
|
|
|
|
}
|
|
|
|
} finally {
|
|
|
|
terminal.uncork();
|
|
|
|
}
|
2016-03-20 09:29:20 -04:00
|
|
|
}
|
|
|
|
|
2016-08-20 13:05:10 -04:00
|
|
|
formatPost(post) {
|
|
|
|
let result = [
|
|
|
|
[{style: "font-size: xx-large", value: post.title}],
|
|
|
|
[{style: "font-size: x-small", value: post.author}, " ", {style: "font-size: x-small", value: post.created}],
|
|
|
|
post.body,
|
|
|
|
];
|
|
|
|
if (core.user.credentials.permissions.administration) {
|
|
|
|
result[0].push({command: JSON.stringify({action: "edit", post: post.name}), value: "edit"});
|
2016-03-20 09:29:20 -04:00
|
|
|
}
|
2016-08-20 13:05:10 -04:00
|
|
|
return result;
|
|
|
|
}
|
2016-03-20 09:29:20 -04:00
|
|
|
|
2016-08-20 13:05:10 -04:00
|
|
|
async submitPost(post) {
|
|
|
|
let now = new Date();
|
|
|
|
let oldPost = await this._documents.get(post.name);
|
2016-08-22 10:46:12 -04:00
|
|
|
if (!await this._list.getByKey(post.name)) {
|
2016-08-20 13:05:10 -04:00
|
|
|
this._list.push(post.name);
|
2016-08-22 10:46:12 -04:00
|
|
|
}
|
|
|
|
for (let key in oldPost) {
|
|
|
|
if (!post[key]) {
|
|
|
|
post[key] = oldPost[key];
|
2016-08-20 13:05:10 -04:00
|
|
|
}
|
2016-03-20 09:29:20 -04:00
|
|
|
}
|
2016-08-22 10:46:12 -04:00
|
|
|
if (!post.created) {
|
|
|
|
post.created = now;
|
|
|
|
}
|
|
|
|
if (!post.author) {
|
|
|
|
post.author = core.user.name;
|
|
|
|
}
|
2016-08-20 13:05:10 -04:00
|
|
|
post.modified = now;
|
|
|
|
await this._documents.set(post.name, post);
|
2016-03-20 09:29:20 -04:00
|
|
|
}
|
|
|
|
|
2016-08-20 13:05:10 -04:00
|
|
|
async deletePost(name) {
|
|
|
|
await this._documents.set(name, null);
|
2016-03-20 09:29:20 -04:00
|
|
|
}
|
|
|
|
|
2016-08-20 13:05:10 -04:00
|
|
|
async handleCommand(command) {
|
|
|
|
if (command.action == "edit") {
|
|
|
|
await this.edit(command.post);
|
|
|
|
} else if (command.action == "new") {
|
|
|
|
await this.edit(null);
|
|
|
|
} else if (command.action == "delete") {
|
|
|
|
await this.deletePost(command.post);
|
2016-03-20 09:29:20 -04:00
|
|
|
}
|
2016-08-20 13:05:10 -04:00
|
|
|
}
|
2016-03-20 09:29:20 -04:00
|
|
|
|
2016-08-20 13:05:10 -04:00
|
|
|
async edit(page) {
|
|
|
|
terminal.cork();
|
|
|
|
try {
|
|
|
|
let self = this;
|
|
|
|
self._post = await this._documents.get(page);
|
|
|
|
|
|
|
|
if (!this._onWindowMessage) {
|
|
|
|
this._onWindowMessage = function(event) {
|
|
|
|
let message = event.message;
|
|
|
|
if (message == "load") {
|
|
|
|
terminal.postMessageToIframe("iframe", self._post);
|
|
|
|
} else if (message.action == "save") {
|
|
|
|
self.submitPost(message.post).then(self.renderIndex.bind(self)).catch(terminal.print);
|
|
|
|
} else if (message.action == "delete") {
|
|
|
|
self.deletePost(message.post).then(self.renderIndex.bind(self)).catch(terminal.print);
|
|
|
|
} else if (message.action == "back") {
|
|
|
|
self.renderIndex.bind(self)().catch(terminal.print);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
core.register("onWindowMessage", this._onWindowMessage);
|
|
|
|
}
|
2016-03-20 09:29:20 -04:00
|
|
|
|
2016-08-20 13:05:10 -04:00
|
|
|
terminal.split([{name: "terminal", type: "vertical"}]);
|
|
|
|
terminal.clear();
|
|
|
|
terminal.print({iframe: `
|
|
|
|
<!DOCTYPE html>
|
|
|
|
<html>
|
|
|
|
<head>
|
|
|
|
<script src="//cdnjs.cloudflare.com/ajax/libs/codemirror/5.13.2/codemirror.min.js"></script>
|
|
|
|
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/codemirror/5.13.2/codemirror.min.css"></link>
|
2016-03-20 09:29:20 -04:00
|
|
|
<style>
|
2016-08-20 13:05:10 -04:00
|
|
|
html, body, #contents {
|
2016-03-20 09:29:20 -04:00
|
|
|
height: 100%;
|
|
|
|
margin: 0;
|
|
|
|
padding: 0;
|
|
|
|
}
|
2016-08-20 13:05:10 -04:00
|
|
|
body {
|
|
|
|
display: flex;
|
|
|
|
flex-direction: column;
|
|
|
|
color: #fff;
|
|
|
|
}
|
|
|
|
.CodeMirror {
|
|
|
|
width: 100%;
|
|
|
|
height: 100%;
|
|
|
|
}
|
|
|
|
.CodeMirror-scroll {
|
2016-03-20 09:29:20 -04:00
|
|
|
}
|
|
|
|
</style>
|
2016-08-20 13:05:10 -04:00
|
|
|
</head>
|
|
|
|
<body>
|
|
|
|
<div>
|
|
|
|
<input type="button" id="back" value="Back" onclick="back()">
|
|
|
|
<input type="button" id="save" value="Save" onclick="save()">
|
|
|
|
<input type="button" id="delete" value="Delete" onclick="deletePost()">
|
|
|
|
</div>
|
|
|
|
<div><label for="name">Name:</label> <input type="text" id="name"></div>
|
|
|
|
<div><label for="title">Title:</label> <input type="text" id="title"></div>
|
|
|
|
<textarea id="contents" style="width: 100%; height: 100%"></textarea>
|
|
|
|
<script>
|
|
|
|
var gEditor;
|
|
|
|
window.addEventListener("message", function(event) {
|
|
|
|
var message = event.data;
|
|
|
|
console.debug(message);
|
|
|
|
gEditor.setValue(message.body || "");
|
|
|
|
document.getElementById("name").value = message.name || "untitled";
|
|
|
|
document.getElementById("title").value = message.title || "untitled";
|
|
|
|
});
|
|
|
|
window.addEventListener("load", function() {
|
|
|
|
gEditor = CodeMirror.fromTextArea(document.getElementById("contents"), {
|
|
|
|
lineNumbers: true
|
|
|
|
});
|
|
|
|
//gEditor.on("change", textChanged);
|
|
|
|
parent.postMessage("load", "*");
|
|
|
|
});
|
|
|
|
function back() {
|
|
|
|
parent.postMessage({action: "back"}, "*");
|
|
|
|
}
|
|
|
|
function save() {
|
|
|
|
parent.postMessage({
|
|
|
|
action: "save",
|
|
|
|
post: {
|
|
|
|
name: document.getElementById("name").value,
|
2016-03-20 09:29:20 -04:00
|
|
|
title: document.getElementById("title").value,
|
2016-08-20 13:05:10 -04:00
|
|
|
body: gEditor.getValue(),
|
|
|
|
},
|
|
|
|
}, "*");
|
|
|
|
}
|
|
|
|
function deletePost() {
|
|
|
|
parent.postMessage({
|
|
|
|
action: "delete",
|
|
|
|
post: document.getElementById("name").value,
|
|
|
|
}, "*");
|
|
|
|
}
|
|
|
|
</script>
|
|
|
|
</body>
|
|
|
|
</html>
|
|
|
|
`, name: "iframe", style: "flex: 1 1 auto; width: 100%; margin: 0; border: 0; padding: 0;"});
|
|
|
|
} finally {
|
|
|
|
terminal.uncork();
|
|
|
|
}
|
|
|
|
}
|
2016-03-20 09:29:20 -04:00
|
|
|
}
|
|
|
|
|
2016-08-20 13:05:10 -04:00
|
|
|
terminal.setEcho(false);
|
|
|
|
let blog = new Blog();
|
|
|
|
blog.renderIndex().catch(terminal.print);
|
|
|
|
|
|
|
|
core.register("onInput", async function(input) {
|
|
|
|
try {
|
|
|
|
await blog.handleCommand(JSON.parse(input));
|
|
|
|
} catch (error) {
|
|
|
|
terminal.print(error);
|
|
|
|
}
|
|
|
|
});
|