Gisle Aune
6 years ago
12 changed files with 275 additions and 40 deletions
-
12marko/page/story-content/components/chapter-meta/component.js
-
22marko/page/story-content/components/chapter/component.js
-
77marko/page/story-content/components/chapter/components/edit-chapter-modal/component.js
-
11marko/page/story-content/components/chapter/components/edit-chapter-modal/index.marko
-
54marko/page/story-content/components/chapter/components/remove-chapter-modal/component.js
-
9marko/page/story-content/components/chapter/components/remove-chapter-modal/index.marko
-
23marko/page/story-content/components/chapter/index.marko
-
20marko/page/story-content/components/chapter/style.less
-
31marko/page/story-content/components/page/component.js
-
8marko/page/story-content/components/page/index.marko
-
37marko/page/story-content/components/story-content-menu/component.js
-
11marko/page/story-content/components/story-content-menu/index.marko
@ -1,5 +1,25 @@ |
|||||
module.exports = class { |
module.exports = class { |
||||
onCreate(input) { |
onCreate(input) { |
||||
this.state = Object.assign({}, input.chapter) |
|
||||
|
this.state = { |
||||
|
modal: null, |
||||
|
removed: false, |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
updateChapter(data) { |
||||
|
this.emit("edit", data) |
||||
|
} |
||||
|
|
||||
|
removeChapter() { |
||||
|
this.state.removed = true |
||||
|
this.emit("remove") |
||||
|
} |
||||
|
|
||||
|
open(modal) { |
||||
|
this.state.modal = modal |
||||
|
} |
||||
|
|
||||
|
close() { |
||||
|
this.state.modal = null |
||||
} |
} |
||||
} |
} |
@ -0,0 +1,77 @@ |
|||||
|
const moment = require("moment") |
||||
|
|
||||
|
const {chapterApi} = require("../../../../../../../rpdata/api/Chapter") |
||||
|
|
||||
|
module.exports = class { |
||||
|
onCreate(input) { |
||||
|
this.state = { |
||||
|
error: null, |
||||
|
loading: false, |
||||
|
values: { |
||||
|
title: "", |
||||
|
source: "", |
||||
|
fictionalDate: "", |
||||
|
}, |
||||
|
} |
||||
|
|
||||
|
this.first = false |
||||
|
} |
||||
|
|
||||
|
onInput(input) { |
||||
|
if (input.chapter && !this.first) { |
||||
|
let {fictionalDate, title, source} = input.chapter |
||||
|
|
||||
|
if (fictionalDate != null) { |
||||
|
fictionalDate = moment.utc(fictionalDate).format("MMM D, YYYY") |
||||
|
} |
||||
|
|
||||
|
this.state.values = {fictionalDate, title, source} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
change(key, ev) { |
||||
|
this.state.values[key] = ev.target.value |
||||
|
} |
||||
|
|
||||
|
open() { |
||||
|
|
||||
|
} |
||||
|
|
||||
|
close() { |
||||
|
this.first = false |
||||
|
this.emit("close") |
||||
|
} |
||||
|
|
||||
|
save() { |
||||
|
const values = this.state.values |
||||
|
|
||||
|
let fictionalDate = new Date(values.fictionalDate + " UTC") |
||||
|
if (values.fictionalDate != "") { |
||||
|
if (Number.isNaN(fictionalDate)) { |
||||
|
this.state.error = `Could not parse ${values.fictionalDate} as date` |
||||
|
return |
||||
|
} |
||||
|
} else { |
||||
|
fictionalDate = null |
||||
|
} |
||||
|
|
||||
|
const input = {id: this.input.chapter.id, title: values.title, source: values.source} |
||||
|
|
||||
|
if (fictionalDate != null) { |
||||
|
input.fictionalDate = fictionalDate |
||||
|
} else { |
||||
|
input.clearFictionalDate = true |
||||
|
} |
||||
|
|
||||
|
chapterApi.editChapter(input).then(data => { |
||||
|
this.emit("edit", data) |
||||
|
this.emit("close") |
||||
|
}).catch(errs => { |
||||
|
console.warn("Failed to edit:", errs) |
||||
|
|
||||
|
this.state.error = "Failed to edit: " + errs[0].message |
||||
|
}).then(() => { |
||||
|
this.state.loading = false |
||||
|
}) |
||||
|
} |
||||
|
} |
@ -0,0 +1,11 @@ |
|||||
|
<modal class="modal color-text nolabel" key="modal" enabled=(input.enabled) closable on-close("close") on-open("open") > |
||||
|
<h1>Edit Chapter</h1> |
||||
|
|
||||
|
<p key="error" class="color-error">${state.error}</p> |
||||
|
|
||||
|
<input key="title" placeholder="Title" class="big" on-change("change", "title") value=state.values.title /> |
||||
|
<input key="icdate" placeholder="IC Date" on-change("change", "fictionalDate") value=state.values.fictionalDate /> |
||||
|
<textarea key="source" placeholder="Content" class="tall" on-change("change", "source") value=state.values.source /> |
||||
|
|
||||
|
<button disabled=state.loading on-click("save")>Save</button> |
||||
|
</modal> |
@ -0,0 +1,54 @@ |
|||||
|
const moment = require("moment") |
||||
|
|
||||
|
const {chapterApi} = require("../../../../../../../rpdata/api/Chapter") |
||||
|
|
||||
|
module.exports = class { |
||||
|
onCreate(input) { |
||||
|
this.state = { |
||||
|
error: null, |
||||
|
loading: false, |
||||
|
values: { |
||||
|
title: "", |
||||
|
source: "", |
||||
|
fictionalDate: "", |
||||
|
}, |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
onInput(input) { |
||||
|
if (input.chapter && !this.first) { |
||||
|
let {fictionalDate, title, source} = input.chapter |
||||
|
|
||||
|
if (fictionalDate != null) { |
||||
|
fictionalDate = moment.utc(fictionalDate).format("MMM D, YYYY") |
||||
|
} |
||||
|
|
||||
|
this.state.values = {fictionalDate, title, source} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
change(key, ev) { |
||||
|
this.state.values[key] = ev.target.value |
||||
|
} |
||||
|
|
||||
|
open() { |
||||
|
|
||||
|
} |
||||
|
|
||||
|
close() { |
||||
|
this.emit("close") |
||||
|
} |
||||
|
|
||||
|
doIt() { |
||||
|
chapterApi.removeChapter({id: this.input.chapter.id}).then(() => { |
||||
|
this.emit("remove") |
||||
|
this.emit("close") |
||||
|
}).catch(errs => { |
||||
|
console.warn("Failed to delete:", errs) |
||||
|
|
||||
|
this.state.error = "Failed to delete: " + errs.message || errs[0].message |
||||
|
}).then(() => { |
||||
|
this.state.loading = false |
||||
|
}) |
||||
|
} |
||||
|
} |
@ -0,0 +1,9 @@ |
|||||
|
<modal class="modal color-text nolabel" key="modal" enabled=(input.enabled) notification closable on-close("close") on-open("open") > |
||||
|
<h1>Delete Chapter</h1> |
||||
|
|
||||
|
<p class="color-error">${state.error}</p> |
||||
|
|
||||
|
<p class="color-danger">This is irreversible!</p> |
||||
|
|
||||
|
<button disabled=state.loading on-click("doIt")>Yes, do it!</button> |
||||
|
</modal> |
@ -1,10 +1,19 @@ |
|||||
<div class="story-chapter"> |
|
||||
<a class="anchor" id=state.id /> |
|
||||
|
import moment from "moment" |
||||
|
|
||||
|
<div class="story-chapter" if(!state.removed)> |
||||
|
<a class="anchor" id=input.chapter.id /> |
||||
<div class="metadata"> |
<div class="metadata"> |
||||
<chapter-meta kind="title" value=state.title /> |
|
||||
<chapter-meta kind="date" value=state.fictionalDate /> |
|
||||
<chapter-meta weak kind="date" value=state.createdDate /> |
|
||||
<chapter-meta weak kind="author" value=state.author /> |
|
||||
|
<div class="options color-menu"> |
||||
|
<a on-click("open", "edit") >Edit</a> |
||||
|
<a on-click("open", "remove") >Remove</a> |
||||
|
</div> |
||||
|
<chapter-meta kind="title" value=input.chapter.title /> |
||||
|
<chapter-meta kind="date" value=input.chapter.fictionalDate /> |
||||
|
<chapter-meta weak kind="date" value=input.chapter.createdDate /> |
||||
|
<chapter-meta weak kind="author" value=input.chapter.author /> |
||||
</div> |
</div> |
||||
<markdown class="chapter-content" source=state.source /> |
|
||||
|
<markdown class="chapter-content" source=input.chapter.source /> |
||||
|
|
||||
|
<edit-chapter-modal enabled=(state.modal === "edit") chapter=input.chapter on-close("close") on-edit("updateChapter") /> |
||||
|
<remove-chapter-modal enabled=(state.modal === "remove") chapter=input.chapter on-close("close") on-remove("removeChapter") /> |
||||
</div> |
</div> |
@ -0,0 +1,31 @@ |
|||||
|
module.exports = class { |
||||
|
onCreate(input) { |
||||
|
this.state = { |
||||
|
story: input.story |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
updateChapter(id, data) { |
||||
|
const index = this.state.story.chapters.findIndex(ch => ch.id === id) |
||||
|
if (index === -1) { |
||||
|
return |
||||
|
} |
||||
|
|
||||
|
for (const key in data) { |
||||
|
if (!data.hasOwnProperty(key)) { |
||||
|
continue |
||||
|
} |
||||
|
|
||||
|
this.state.story.chapters[index][key] = data[key] |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
removeChapter(id) { |
||||
|
const index = this.state.story.chapters.findIndex(ch => ch.id === id) |
||||
|
if (index === -1) { |
||||
|
return |
||||
|
} |
||||
|
|
||||
|
this.state.story.chapters.splice(index, 1) |
||||
|
} |
||||
|
} |
@ -1,8 +1,8 @@ |
|||||
<story-content-menu story=input.story selected=(input.selected || {}) user=input.user /> |
|
||||
|
<story-content-menu key="menu" story=state.story selected=(input.selected || {}) user=input.user /> |
||||
<main> |
<main> |
||||
<div class="story-content"> |
<div class="story-content"> |
||||
<h1 class="color-primary">${input.story.name}</h1> |
|
||||
<story-tags tags=input.story.tags /> |
|
||||
<chapter for(chapter in input.story.chapters) key=chapter.id chapter=chapter /> |
|
||||
|
<h1 class="color-primary">${state.story.name}</h1> |
||||
|
<story-tags tags=state.story.tags /> |
||||
|
<chapter for(chapter in state.story.chapters) key=chapter.id chapter=chapter on-edit("updateChapter", chapter.id) on-remove("removeChapter", chapter.id)/> |
||||
</div> |
</div> |
||||
</main> |
</main> |
@ -1,9 +1,6 @@ |
|||||
<menu user=input.user> |
<menu user=input.user> |
||||
<if(input.story.chapters.length > 1)> |
|
||||
<menu-header>${input.story.name}</menu-header> |
|
||||
<for(chapter in input.story.chapters | status-var=loop)> |
|
||||
<menu-link on-click("selectChapter", chapter.id) href=("#" + chapter.id) selected=(state.selectedChapter === chapter.id) icon=(loop.getIndex()+1)>${state.chapterTitles[chapter.id]}</menu-link> |
|
||||
</for> |
|
||||
<menu-gap /> |
|
||||
</if> |
|
||||
|
<menu-header>${input.story.name}</menu-header> |
||||
|
<for(chapter in input.story.chapters | status-var=loop)> |
||||
|
<menu-link key=chapter.id on-click("selectChapter", chapter.id) href=("#" + chapter.id) selected=(state.selectedChapter === chapter.id) icon=(loop.getIndex()+1)>${component.chapterTitle(chapter)}</menu-link> |
||||
|
</for> |
||||
</menu> |
</menu> |
Write
Preview
Loading…
Cancel
Save
Reference in new issue