@@ -10,6 +10,10 @@ module.exports = class {
|
|||||||
this.emit("edit", data)
|
this.emit("edit", data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
moveChapter(data) {
|
||||||
|
this.emit("move", data)
|
||||||
|
}
|
||||||
|
|
||||||
removeChapter() {
|
removeChapter() {
|
||||||
this.state.removed = true
|
this.state.removed = true
|
||||||
this.emit("remove")
|
this.emit("remove")
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
import moment from "moment"
|
|
||||||
|
|
||||||
<div class="story-chapter">
|
<div class="story-chapter">
|
||||||
<a class="anchor" id=input.chapter.id />
|
<a class="anchor" id=input.chapter.id />
|
||||||
<div class="metadata">
|
<div class="metadata">
|
||||||
@@ -7,6 +5,9 @@ import moment from "moment"
|
|||||||
<if-permitted user=input.user author=input.chapter.author permission="chapter.edit">
|
<if-permitted user=input.user author=input.chapter.author permission="chapter.edit">
|
||||||
<a on-click("open", "edit") >Edit</a>
|
<a on-click("open", "edit") >Edit</a>
|
||||||
</if-permitted>
|
</if-permitted>
|
||||||
|
<if-permitted user=input.user author=input.chapter.author permission="chapter.move">
|
||||||
|
<a on-click("open", "move") >Move</a>
|
||||||
|
</if-permitted>
|
||||||
<if-permitted user=input.user author=input.chapter.author permission="chapter.remove">
|
<if-permitted user=input.user author=input.chapter.author permission="chapter.remove">
|
||||||
<a on-click("open", "remove") >Remove</a>
|
<a on-click("open", "remove") >Remove</a>
|
||||||
</if-permitted>
|
</if-permitted>
|
||||||
@@ -19,5 +20,6 @@ import moment from "moment"
|
|||||||
<markdown class="chapter-content color-text" source=input.chapter.source />
|
<markdown class="chapter-content color-text" source=input.chapter.source />
|
||||||
|
|
||||||
<edit-chapter-modal enabled=(state.modal === "edit") chapter=input.chapter on-close("close") on-edit("updateChapter") />
|
<edit-chapter-modal enabled=(state.modal === "edit") chapter=input.chapter on-close("close") on-edit("updateChapter") />
|
||||||
|
<move-chapter-modal enabled=(state.modal === "move") chapter=input.chapter user=input.user on-close("close") on-move("moveChapter") />
|
||||||
<remove-chapter-modal enabled=(state.modal === "remove") chapter=input.chapter on-close("close") on-remove("removeChapter") />
|
<remove-chapter-modal enabled=(state.modal === "remove") chapter=input.chapter on-close("close") on-remove("removeChapter") />
|
||||||
</div>
|
</div>
|
||||||
@@ -0,0 +1,89 @@
|
|||||||
|
const {storyApi} = require("../../../../../rpdata/api/Story")
|
||||||
|
const {chapterApi} = require("../../../../../rpdata/api/Chapter")
|
||||||
|
|
||||||
|
module.exports = class {
|
||||||
|
onCreate(input) {
|
||||||
|
this.state = {
|
||||||
|
error: null,
|
||||||
|
loading: false,
|
||||||
|
loadingStories: true,
|
||||||
|
stories: [],
|
||||||
|
selected: null,
|
||||||
|
}
|
||||||
|
|
||||||
|
this.first = false
|
||||||
|
}
|
||||||
|
|
||||||
|
change(key, ev) {
|
||||||
|
const value = ev.target.value
|
||||||
|
|
||||||
|
switch (key) {
|
||||||
|
case "selected": {
|
||||||
|
this.state.selected = Object.assign({}, this.state.stories.find(s => s.id === value))
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
open() {
|
||||||
|
const promises = []
|
||||||
|
if ((this.input.user.permissions || []).includes("chapter.move")) {
|
||||||
|
promises.push(storyApi.list())
|
||||||
|
} else {
|
||||||
|
promises.push(storyApi.list({author: this.input.user.name}))
|
||||||
|
promises.push(storyApi.list({open: true}))
|
||||||
|
}
|
||||||
|
|
||||||
|
this.state.loadingStories = true
|
||||||
|
|
||||||
|
Promise.all(promises).then(lists => {
|
||||||
|
this.state.stories = unique(Array.prototype.concat.call(...lists))
|
||||||
|
this.state.selected = this.state.stories[0]
|
||||||
|
}).catch(err => {
|
||||||
|
console.warn(err)
|
||||||
|
}).then(() => {
|
||||||
|
this.state.loadingStories = false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
close() {
|
||||||
|
this.first = false
|
||||||
|
this.emit("close")
|
||||||
|
}
|
||||||
|
|
||||||
|
save() {
|
||||||
|
if (this.state.loading) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const input = {id: this.input.chapter.id, storyId: this.state.selected.id}
|
||||||
|
|
||||||
|
this.state.loading = true
|
||||||
|
chapterApi.moveChapter(input).then(data => {
|
||||||
|
this.emit("move", input)
|
||||||
|
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
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function unique(stories) {
|
||||||
|
const ids = {}
|
||||||
|
const results = []
|
||||||
|
|
||||||
|
for (const story of stories) {
|
||||||
|
if (ids[story.id]) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
ids[story.id] = true
|
||||||
|
results.push(story)
|
||||||
|
}
|
||||||
|
|
||||||
|
return results
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
$ const selected = (state.selected||{id:null});
|
||||||
|
|
||||||
|
<modal class="modal color-text nolabel" key="modal" enabled=(input.enabled) closable on-close("close") on-open("open") >
|
||||||
|
<h1>Move Chapter</h1>
|
||||||
|
|
||||||
|
<p key="error" class="color-error">${state.error}</p>
|
||||||
|
|
||||||
|
<label>Target story</label>
|
||||||
|
<select key="story" on-change("change", "selected") value=selected.id>
|
||||||
|
<option for(story in state.stories) value=story.id selected=(selected.id === story.id)>${story.name}</option>
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<if-permitted not permission="story.move">
|
||||||
|
<p>Only stories you are allowed to move the chapter to appear in the above list.</p>
|
||||||
|
</if-permitted>
|
||||||
|
|
||||||
|
<button disabled=state.loading on-click("save")>Move</button>
|
||||||
|
</modal>
|
||||||
@@ -24,6 +24,12 @@ module.exports = class {
|
|||||||
this.refreshStory()
|
this.refreshStory()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
moveChapter(chapter, data) {
|
||||||
|
if (data.storyId !== this.state.story.id) {
|
||||||
|
this.state.story = Object.assign({}, this.state.story, {chapters: this.state.story.chapters.filter(ch => ch.id !== chapter.id)})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
updateChapter(id, data) {
|
updateChapter(id, data) {
|
||||||
const index = this.state.story.chapters.findIndex(ch => ch.id === id)
|
const index = this.state.story.chapters.findIndex(ch => ch.id === id)
|
||||||
if (index === -1) {
|
if (index === -1) {
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
so you can still read it (or back it up) before leaving the page.
|
so you can still read it (or back it up) before leaving the page.
|
||||||
</p>
|
</p>
|
||||||
</annotation>
|
</annotation>
|
||||||
<chapter for(chapter in state.story.chapters) key=chapter.id chapter=chapter user=(!state.removed ? input.user : null) on-edit("updateChapter", chapter.id) on-remove("removeChapter", chapter.id)/>
|
<chapter for(chapter in state.story.chapters) key=chapter.id chapter=chapter user=(!state.removed ? input.user : null) on-edit("updateChapter", chapter.id) on-remove("removeChapter", chapter.id) on-move("moveChapter", chapter) />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<create-chapter-modal storyId=state.story.id enabled=(state.modal === "chapter.add") chapter=input.chapter on-close("close") on-add("addChapter") />
|
<create-chapter-modal storyId=state.story.id enabled=(state.modal === "chapter.add") chapter=input.chapter on-close("close") on-add("addChapter") />
|
||||||
|
|||||||
+23
-5
@@ -21,7 +21,7 @@ class Chapter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const chapterApi = {
|
class ChapterAPI {
|
||||||
/**
|
/**
|
||||||
* Call `addChapter(input)` mutation, returns the entire object.
|
* Call `addChapter(input)` mutation, returns the entire object.
|
||||||
*
|
*
|
||||||
@@ -46,7 +46,7 @@ const chapterApi = {
|
|||||||
|
|
||||||
return new Chapter(ac.id, ac.title, ac.author, ac.source, ac.createdDate, ac.fictionalDate, ac.editedDate)
|
return new Chapter(ac.id, ac.title, ac.author, ac.source, ac.createdDate, ac.fictionalDate, ac.editedDate)
|
||||||
})
|
})
|
||||||
},
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Call `editChapter(input)` mutation, returns editable fields
|
* Call `editChapter(input)` mutation, returns editable fields
|
||||||
@@ -70,7 +70,25 @@ const chapterApi = {
|
|||||||
|
|
||||||
return editChapter
|
return editChapter
|
||||||
})
|
})
|
||||||
},
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call `moveChapter(input)` mutation, returns the ID.
|
||||||
|
*
|
||||||
|
* @param {{id:string, storyId:string}} input
|
||||||
|
* @returns {Promise<{id:string}>}
|
||||||
|
*/
|
||||||
|
moveChapter(input) {
|
||||||
|
return query(`
|
||||||
|
mutation MoveChapter($input: ChapterMoveInput!) {
|
||||||
|
moveChapter(input: $input) {
|
||||||
|
id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`, {input}, {permissions: ["member", "story.move"]}).then(({moveChapter}) => {
|
||||||
|
return moveChapter
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Call `removeChapter(input)` mutation, returns only the id
|
* Call `removeChapter(input)` mutation, returns only the id
|
||||||
@@ -88,7 +106,7 @@ const chapterApi = {
|
|||||||
`, {input}, {permissions: ["member", "story.edit"]}).then(({removeChapter}) => {
|
`, {input}, {permissions: ["member", "story.edit"]}).then(({removeChapter}) => {
|
||||||
return removeChapter
|
return removeChapter
|
||||||
})
|
})
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {Chapter, chapterApi}
|
module.exports = {Chapter, chapterApi: new ChapterAPI}
|
||||||
Reference in New Issue
Block a user