Skip to content

Commit

Permalink
Edition works
Browse files Browse the repository at this point in the history
  • Loading branch information
Rackover committed Feb 9, 2020
1 parent e6aeb6f commit 2c8b8ba
Show file tree
Hide file tree
Showing 9 changed files with 173 additions and 24 deletions.
8 changes: 5 additions & 3 deletions app.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,11 +72,12 @@ global.WIKI_NAME = argv.name || process.env.GIT_REPO_URL.split("/").pop().replac
global.WIKI_CONTENTS_DIRECTORY_NAME = "_contents";

global.logger = require("./app/log/logger.js")
global.git = require("./app/git.js")
const gitStarter = require("./app/git.js") // Will become global.git
global.markdown = require("./app/markdown.js")
global.wikiMap = require("./app/map.js")
global.wikiPage = require("./app/page.js")
global.wikiContents = require('./app/content.js')
global.utility = require("./app/utility.js")

logger.debug("Using root path: "+APPLICATION_ROOT+" and wiki path: "+WIKI_PATH)
logger.debug("Parchment currently running as user: "+require('os').userInfo().username)
Expand All @@ -87,8 +88,9 @@ logger.debug("Parchment currently running as user: "+require('os').userInfo().us
if (argv._.includes('run')){

// Setup git
git()
.then(()=>{
gitStarter().then((git)=>{
global.git = git

// Scan wiki
return wikiMap.updateTree()
})
Expand Down
29 changes: 22 additions & 7 deletions app/express.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,22 @@
const fs = require("fs");
const path = require("path");
const bodyParser = require("body-parser");

const permissions = require("./permissions.js")

module.exports = function(port){
const express = require('express')
const app = express()

///////
// Middlewares
app.set('view engine', 'pug')
app.set('views', './app/views')

app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());

//////
// Routing
const routes = [
{name:"read/*", isProtected: false},
{name:"write/*", isProtected: true}
Expand Down Expand Up @@ -47,13 +54,21 @@ module.exports = function(port){
const apiRoutes = [
{name:"submit", isProtected: true}
]
for (k in routes){
const route = routes[k].name
const isProtected = routes[k].isProtected
for (k in apiRoutes){
const route = apiRoutes[k].name
const isProtected = apiRoutes[k].isProtected
const cleanName = route.replace("/*", "")
app.get('/'+route, async function (req, res, next) {

}
app.post('/'+route, async function (req, res, next) {
if (isProtected && !permissions.canWrite(req)){
res.status(403).send({ auth: false, message: 'This page requires identification.' });
logger.info("Refused access to POST "+req.path+" to "+req.ip+" because of insufficient permission")
}
else{
const response = await require('./routes/post/'+cleanName+'.js')(req.body);
res.status(response.code).json(response);
}
})
logger.debug('Registered '+(isProtected?"protected ":"")+'POST route '+route);
}

// CSS faking route
Expand Down
17 changes: 16 additions & 1 deletion app/page.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
const fs = require("fs")
const path = require("path")
const util = require('util');
const writeFile = util.promisify(fs.writeFile);

module.exports = {
getFormattedContents: getFormattedContents,
getContents: getContents
getContents: getContents,
add: addPage
}

function getFormattedContents(diskPath){
Expand All @@ -12,3 +16,14 @@ function getFormattedContents(diskPath){
function getContents(diskPath){
return fs.readFileSync(diskPath).toString()
}

async function addPage(virtualPath, contents){
const diskPath = path.join(WIKI_PATH, virtualPath)
const elems = virtualPath.split("/")
const fileName = elems[elems.length-1]
logger.info("Adding page "+fileName+"...")
await writeFile(diskPath, contents)
await wikiMap.updateTree()
await git.checkAndUploadModifications("Updated "+fileName)
logger.info("Done adding page "+fileName+"!")
}
19 changes: 19 additions & 0 deletions app/routes/post/submit.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
module.exports = async function(body){
let code = 200
let content = "OK"

const miss = utility.getMissingFields(body, ["data", "virtualPath"])

if (miss.length > 0){
code = 400
content = "The following fields are missing from the POST body: "+miss.join(", ");
}
else{
await wikiPage.add(body.virtualPath, body.data)
}

return {
code:code,
content:content
}
}
14 changes: 14 additions & 0 deletions app/utility.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
module.exports = {
getMissingFields: getMissingFields
}

function getMissingFields(obj, fields){
let missing = []
for (k in fields){
const field = fields[k]
if (undefined === (obj[field])){
missing.push(field)
}
}
return missing
}
1 change: 1 addition & 0 deletions app/views/write.pug
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ block head
link(rel="stylesheet", href="/res/css/simplemde.min.css")
link(rel="stylesheet", href="/res/css/editor.css")
script(src="/res/js/simplemde.min.js")
script(src="/res/js/jquery.min.js")
script(src="/res/js/editor.js")


Expand Down
18 changes: 13 additions & 5 deletions public/res/css/editor.css
Original file line number Diff line number Diff line change
@@ -1,20 +1,28 @@
a.saveButton:after{
content: "Save";
a.submitButton:after{
content: "Submit and go to...";
font-family: "Noto sans";
margin-left: 6px;
}

a.saveButton{
a.submitButton{
width:auto;
border:1px dotted grey;
padding-left: 6px;
padding-right: 6px;
background:linear-gradient(#00DD44, #006622);
color:white !important;
font-weight:bold;
}

a.saveButton:hover{
a.submitButton:hover{
border:1px solid grey;
background:linear-gradient(#00FF55, #00AA66);
}

a.saveButton.saving{
background:rgb(100, 100, 100);
}

.CodeMirror.saving{
color:grey !important;
background-color:lightgrey !important;
}
89 changes: 81 additions & 8 deletions public/res/js/editor.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,34 @@
let isSaving = false;
let textZone, simplemde;
const submissionURL = "/submit"

const toolbarFile = {
"name": "file",
"action": function(editor){

},
"title": "Insert file...",
"className": "fa fa-file"
}

const toolbarSave = {
"name": "save",
"action": function(editor){

"action": function (editor){
saveFunction(editor, false)
},
"title": "Save",
"className": "fa fa-save saveButton"
}

const toolbarSubmit = {
"name": "submit",
"action": function (editor){
saveFunction(editor, true)
},
"title": "Submit",
"className": "fa fa-step-forward saveButton submitButton"
}

const toolbar = [
"bold",
"italic" ,
Expand All @@ -33,20 +46,80 @@ const toolbar = [
"side-by-side",
"fullscreen",
"|",
toolbarSave
toolbarSave,
"|",
toolbarSubmit
]

window.addEventListener("DOMContentLoaded", (event) => {

const textZone = document.getElementById("editor");

const simplemde = new SimpleMDE(
textZone = document.getElementById("editor");
simplemde = new SimpleMDE(
{
element: textZone,
promptURLs: true,
autofocus: true,
toolbar: toolbar
}
);

const codemirror = simplemde.codemirror;
// get shortcuts list
const keys = codemirror.getOption("extraKeys");
keys["Ctrl-S"] = () => {
saveFunction(simplemde, false)
};
// update shortcuts list
codemirror.setOption("extraKeys", keys);

});

function saveFunction(editor, submit=false){
if (isSaving) return;

const element = editor.codemirror.getWrapperElement()

element.className += " saving";
editor.codemirror.options.readOnly = "nocursor"
isSaving = true;
const buttons = Array.from(document.getElementsByClassName("saveButton"));

buttons.forEach((e) => {
e.className += " saving";
})

$.post(submissionURL, {
virtualPath: window.location.pathname.replace("/write/", "/"),
data: editor.value()
}, function(data, txtStatus){
if (data.code === 200){
if (submit){
$(window).unbind('beforeunload')
window.location = window.location.pathname.replace("/write/", "/read/")
}
else{
isSaving = false;
editor.codemirror.options.readOnly = false
buttons.forEach((e) => {
e.className = e.className.replace("saving", "")
})
element.className = element.className.replace("saving", "")
}
}
else{
isSaving = false;
editor.codemirror.options.readOnly = false
buttons.forEach((e) => {
e.className = e.className.replace("saving", "")
})
element.className = element.className.replace("saving", "")
alert("There was an error saving the content. Code "+data.code+"\n"+data.content)
}
})
}

$(window).bind('beforeunload', function(){
return 'Are you sure you want to leave?';
});



2 changes: 2 additions & 0 deletions public/res/js/jquery.min.js

Large diffs are not rendered by default.

0 comments on commit 2c8b8ba

Please sign in to comment.