| @@ -1,4 +0,0 @@ | |||
| { | |||
| "interval": 8000, | |||
| "disabled": true | |||
| } | |||
| @@ -159,6 +159,51 @@ var methods = { | |||
| }); | |||
| }, | |||
| // 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 | |||
| // Lots of synchronous fs stuff, we don't want races | |||
| slide_create: function(query, conf, req, respond) { | |||
| @@ -174,9 +219,15 @@ var methods = { | |||
| var newId = pad((parseInt(biggest) + 1).toString(), biggest.length); | |||
| var path = pathlib.join(conf.slides, newId); | |||
| var meta = JSON.stringify({ | |||
| disabled: true | |||
| }, null, 4) + "\n"; | |||
| try { | |||
| fs.mkdirSync(path); | |||
| fs.writeFileSync(pathlib.join(path, "index.md"), ""); | |||
| fs.writeFileSync(pathlib.join(path, "meta.json"), meta); | |||
| } catch (err) { | |||
| return respond(err); | |||
| } | |||
| @@ -13,17 +13,17 @@ marked.setOptions({ | |||
| var htmlPre = | |||
| "<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 = | |||
| "<script src='/slide.js'></script>"+ | |||
| "</div>"+ | |||
| "</body>"+ | |||
| "<script src='/slide.js'></script>"+ | |||
| "</div>"+ | |||
| "</body>"+ | |||
| "</html>"; | |||
| function sendFile(path, res) { | |||
| @@ -102,7 +102,7 @@ function Slide(dir) { | |||
| }); | |||
| res.end(); | |||
| // Serve index if it's already /{name}/ | |||
| // Serve index if it's already /{name}/ | |||
| } else { | |||
| self.sendIndex(res); | |||
| } | |||
| @@ -164,7 +164,7 @@ function Slideshow(dir, changeInterval) { | |||
| // Return if the current slide is enabled and valid | |||
| function currentEnabled() { | |||
| return currentSlide.indexExists() && !currentSlide.disabled; | |||
| return currentSlide.indexExists() && !currentSlide.meta.disabled; | |||
| } | |||
| self.getSlideName = getSlideName; | |||
| @@ -74,7 +74,7 @@ | |||
| e.on = function(name, fn) { | |||
| e.addEventListener(name, function(evt) { | |||
| fn.call(e, evt); | |||
| fn(evt, e); | |||
| }, false); | |||
| return e; | |||
| } | |||
| @@ -50,9 +50,11 @@ | |||
| text-align: center; | |||
| height: 24px; | |||
| margin-bottom: 12px; | |||
| position: relative; | |||
| } | |||
| #root.edit #topBar a { | |||
| float: left; | |||
| position: absolute; | |||
| left: 0px; | |||
| display: inline-block; | |||
| } | |||
| #root.edit #topBar span { | |||
| @@ -88,12 +90,17 @@ | |||
| } | |||
| #root.edit #fileList, | |||
| #root.edit #slide > .uploader, | |||
| #root.edit #slide > .delete, | |||
| #root.edit #controls, | |||
| #root.edit #html { | |||
| margin-bottom: 24px; | |||
| } | |||
| #root.edit #controls > * { | |||
| display: inline-block; | |||
| margin-left: 4px; | |||
| margin-right: 4px; | |||
| } | |||
| #root.edit #html { | |||
| height: 200px; | |||
| resize: vertical; | |||
| @@ -114,6 +114,7 @@ | |||
| var fileListEl; | |||
| var htmlTextEl; | |||
| var previewEl; | |||
| var metaDisabledEl; | |||
| function populateFileList() { | |||
| api("slide_file_list", { slide: slide }, (err, res) => { | |||
| @@ -162,6 +163,15 @@ | |||
| }); | |||
| } | |||
| 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: "topBar" }, [ | |||
| elem("a", { | |||
| @@ -177,29 +187,42 @@ | |||
| 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", { | |||
| id: "html" | |||
| }).on("keydown", debounce(() => { | |||
| console.log(htmlTextEl.value); | |||
| api("slide_content_update", { | |||
| slide: slide, | |||
| text: htmlTextEl.value | |||
| @@ -218,6 +241,7 @@ | |||
| ]).appendTo(root); | |||
| populateFileList(); | |||
| populateMeta(); | |||
| api("slide_meta", { slide: slide }, (err, res) => { | |||
| if (err) { | |||
| @@ -255,6 +279,8 @@ | |||
| root.className = name; | |||
| views[name].apply(null, args); | |||
| window.scrollTo(0, 0); | |||
| } | |||
| route(); | |||