{ | |||||
"interval": 8000, | |||||
"disabled": true | |||||
} |
}); | }); | ||||
}, | }, | ||||
// Set a meta property for slide | |||||
// Synchronous fs stuff, we don't want races | |||||
slide_set_meta: function(query, conf, req, respond) { | |||||
if (!hasargs(query, respond, [ "slide", "key", "val" ])) return; | |||||
var metafile = pathlib.join(conf.slides, query.slide, "meta.json"); | |||||
var meta = {}; | |||||
try { | |||||
meta = JSON.parse(fs.readFileSync(metafile)); | |||||
} catch (err) { | |||||
if (err.code !== "ENOENT") | |||||
return respond(err); | |||||
} | |||||
meta[query.key] = JSON.parse(query.val); | |||||
try { | |||||
fs.writeFileSync(metafile, JSON.stringify(meta, null, 4)+"\n"); | |||||
} catch (err) { | |||||
respond(err); | |||||
} | |||||
slideshow.updateSlides(); | |||||
respond(); | |||||
}, | |||||
// Get meta properties | |||||
slide_get_meta: function(query, conf, req, respond) { | |||||
if (!hasargs(query, respond, [ "slide" ])) return; | |||||
var metafile = pathlib.join(conf.slides, query.slide, "meta.json"); | |||||
fs.readFile(metafile, (err, res) => { | |||||
if (err && err.code !== "ENOENT") | |||||
return respond(err); | |||||
var obj = {}; | |||||
if (!err) { | |||||
obj = JSON.parse(res); | |||||
} | |||||
respond(null, obj); | |||||
}); | |||||
}, | |||||
// Create a slide | // Create a slide | ||||
// Lots of synchronous fs stuff, we don't want races | // Lots of synchronous fs stuff, we don't want races | ||||
slide_create: function(query, conf, req, respond) { | slide_create: function(query, conf, req, respond) { | ||||
var newId = pad((parseInt(biggest) + 1).toString(), biggest.length); | var newId = pad((parseInt(biggest) + 1).toString(), biggest.length); | ||||
var path = pathlib.join(conf.slides, newId); | var path = pathlib.join(conf.slides, newId); | ||||
var meta = JSON.stringify({ | |||||
disabled: true | |||||
}, null, 4) + "\n"; | |||||
try { | try { | ||||
fs.mkdirSync(path); | fs.mkdirSync(path); | ||||
fs.writeFileSync(pathlib.join(path, "index.md"), ""); | fs.writeFileSync(pathlib.join(path, "index.md"), ""); | ||||
fs.writeFileSync(pathlib.join(path, "meta.json"), meta); | |||||
} catch (err) { | } catch (err) { | ||||
return respond(err); | return respond(err); | ||||
} | } |
var htmlPre = | var htmlPre = | ||||
"<html>"+ | "<html>"+ | ||||
"<head>"+ | |||||
"<link rel='stylesheet' href='/slide.css'>"+ | |||||
"<meta charset='utf-8'>"+ | |||||
"</head>"+ | |||||
"<body>"+ | |||||
"<div id='_wrapper'>"; | |||||
"<head>"+ | |||||
"<link rel='stylesheet' href='/slide.css'>"+ | |||||
"<meta charset='utf-8'>"+ | |||||
"</head>"+ | |||||
"<body>"+ | |||||
"<div id='_wrapper'>"; | |||||
var htmlPost = | var htmlPost = | ||||
"<script src='/slide.js'></script>"+ | |||||
"</div>"+ | |||||
"</body>"+ | |||||
"<script src='/slide.js'></script>"+ | |||||
"</div>"+ | |||||
"</body>"+ | |||||
"</html>"; | "</html>"; | ||||
function sendFile(path, res) { | function sendFile(path, res) { | ||||
}); | }); | ||||
res.end(); | res.end(); | ||||
// Serve index if it's already /{name}/ | |||||
// Serve index if it's already /{name}/ | |||||
} else { | } else { | ||||
self.sendIndex(res); | self.sendIndex(res); | ||||
} | } | ||||
// Return if the current slide is enabled and valid | // Return if the current slide is enabled and valid | ||||
function currentEnabled() { | function currentEnabled() { | ||||
return currentSlide.indexExists() && !currentSlide.disabled; | |||||
return currentSlide.indexExists() && !currentSlide.meta.disabled; | |||||
} | } | ||||
self.getSlideName = getSlideName; | self.getSlideName = getSlideName; |
e.on = function(name, fn) { | e.on = function(name, fn) { | ||||
e.addEventListener(name, function(evt) { | e.addEventListener(name, function(evt) { | ||||
fn.call(e, evt); | |||||
fn(evt, e); | |||||
}, false); | }, false); | ||||
return e; | return e; | ||||
} | } |
text-align: center; | text-align: center; | ||||
height: 24px; | height: 24px; | ||||
margin-bottom: 12px; | margin-bottom: 12px; | ||||
position: relative; | |||||
} | } | ||||
#root.edit #topBar a { | #root.edit #topBar a { | ||||
float: left; | |||||
position: absolute; | |||||
left: 0px; | |||||
display: inline-block; | display: inline-block; | ||||
} | } | ||||
#root.edit #topBar span { | #root.edit #topBar span { | ||||
} | } | ||||
#root.edit #fileList, | #root.edit #fileList, | ||||
#root.edit #slide > .uploader, | |||||
#root.edit #slide > .delete, | |||||
#root.edit #controls, | |||||
#root.edit #html { | #root.edit #html { | ||||
margin-bottom: 24px; | margin-bottom: 24px; | ||||
} | } | ||||
#root.edit #controls > * { | |||||
display: inline-block; | |||||
margin-left: 4px; | |||||
margin-right: 4px; | |||||
} | |||||
#root.edit #html { | #root.edit #html { | ||||
height: 200px; | height: 200px; | ||||
resize: vertical; | resize: vertical; |
var fileListEl; | var fileListEl; | ||||
var htmlTextEl; | var htmlTextEl; | ||||
var previewEl; | var previewEl; | ||||
var metaDisabledEl; | |||||
function populateFileList() { | function populateFileList() { | ||||
api("slide_file_list", { slide: slide }, (err, res) => { | api("slide_file_list", { slide: slide }, (err, res) => { | ||||
}); | }); | ||||
} | } | ||||
function populateMeta() { | |||||
api("slide_get_meta", { slide: slide }, (err, obj) => { | |||||
if (err) | |||||
return error(err); | |||||
metaDisabledEl.checked = !!obj.disabled; | |||||
}); | |||||
} | |||||
elem("div", { id: "slide" }, [ | elem("div", { id: "slide" }, [ | ||||
elem("div", { id: "topBar" }, [ | elem("div", { id: "topBar" }, [ | ||||
elem("a", { | elem("a", { | ||||
fileListEl = elem("div", { id: "fileList" }), | fileListEl = elem("div", { id: "fileList" }), | ||||
uploadEl({ | |||||
slide: slide | |||||
}, populateFileList), | |||||
elem("div", { id: "controls" }, [ | |||||
uploadEl({ | |||||
slide: slide | |||||
}, populateFileList), | |||||
elem("button", { | |||||
className: "delete", | |||||
innerHTML: "Delete" | |||||
}).on("click", () => { | |||||
if (!confirm("Are you sure you want to delete slide "+slide+"?")) | |||||
return; | |||||
elem("button", { | |||||
className: "delete", | |||||
innerHTML: "Delete" | |||||
}).on("click", () => { | |||||
if (!confirm("Are you sure you want to delete slide "+slide+"?")) | |||||
return; | |||||
api("slide_delete", { slide: slide }, err => { | |||||
if (err) | |||||
return error(err); | |||||
api("slide_delete", { slide: slide }, err => { | |||||
if (err) | |||||
return error(err); | |||||
setView("main"); | |||||
}); | |||||
}), | |||||
setView("main"); | |||||
}); | |||||
}), | |||||
elem("label", { innerHTML: "Disabled" }, [ | |||||
metaDisabledEl = elem("input", { | |||||
type: "checkbox" | |||||
}).on("change", (evt, el) => { | |||||
api("slide_set_meta", { | |||||
slide: slide, | |||||
key: "disabled", | |||||
val: JSON.stringify(!!el.checked) | |||||
}, populateMeta); | |||||
}) | |||||
]), | |||||
]), | |||||
htmlTextEl = elem("textarea", { | htmlTextEl = elem("textarea", { | ||||
id: "html" | id: "html" | ||||
}).on("keydown", debounce(() => { | }).on("keydown", debounce(() => { | ||||
console.log(htmlTextEl.value); | |||||
api("slide_content_update", { | api("slide_content_update", { | ||||
slide: slide, | slide: slide, | ||||
text: htmlTextEl.value | text: htmlTextEl.value | ||||
]).appendTo(root); | ]).appendTo(root); | ||||
populateFileList(); | populateFileList(); | ||||
populateMeta(); | |||||
api("slide_meta", { slide: slide }, (err, res) => { | api("slide_meta", { slide: slide }, (err, res) => { | ||||
if (err) { | if (err) { | ||||
root.className = name; | root.className = name; | ||||
views[name].apply(null, args); | views[name].apply(null, args); | ||||
window.scrollTo(0, 0); | |||||
} | } | ||||
route(); | route(); |