Browse Source

story: Added add story modal, reorganized story page to allow modals and live updates.

1.0
Gisle Aune 6 years ago
parent
commit
ae31accd81
  1. 9
      marko/components/modal/style.less
  2. 2
      marko/components/story-tag-options/component.js
  3. 6
      marko/components/story-tag-options/index.marko
  4. 0
      marko/components/story-tag-options/style.less
  5. 4
      marko/page/story-content/components/edit-story-modal/index.marko
  6. 79
      marko/page/story/components/add-story-modal/component.js
  7. 33
      marko/page/story/components/add-story-modal/index.marko
  8. 16
      marko/page/story/components/page/component.js
  9. 5
      marko/page/story/components/page/index.marko
  10. 5
      marko/page/story/components/story-menu/component.js
  11. 1
      marko/page/story/components/story-menu/index.marko
  12. 5
      marko/page/story/list.marko
  13. 44
      rpdata/api/Story.js

9
marko/components/modal/style.less

@ -14,6 +14,15 @@ div.overlay {
h1 {
text-align: center;
}
h2 {
opacity: 0.5;
margin: 0;
margin-top: 1em;
border-bottom: 0.5px solid;
padding-bottom: 0.125em;
text-align: center;
}
div.modal {
width: 60ch;

2
marko/page/story-content/components/story-tag-options/component.js → marko/components/story-tag-options/component.js

@ -1,4 +1,4 @@
const {tagApi} = require("../../../../../rpdata/api/Tag")
const {tagApi} = require("../../../rpdata/api/Tag")
module.exports = class {
onCreate() {

6
marko/page/story-content/components/story-tag-options/index.marko → marko/components/story-tag-options/index.marko

@ -1,6 +1,8 @@
<div class="tag-options">
<input key="name" placeholder="Name" class="big" on-change("change", "name") value=state.values.name />
<select key="kind" placeholder="Kind" class="big" on-change("change", "kind") value=state.values.kind>
<label>Tag Name</label>
<input key="name" placeholder="Name" on-change("change", "name") value=state.values.name />
<label>Tag Kind</label>
<select key="kind" placeholder="Kind" on-change("change", "kind") value=state.values.kind>
<option value="Character" selected=(state.values.kind === "Character")>Character</option>
<option value="Event" selected=(state.values.kind === "Event")>Event</option>
<option value="Location" selected=(state.values.kind === "Location")>Location</option>

0
marko/page/story-content/components/story-tag-options/style.less → marko/components/story-tag-options/style.less

4
marko/page/story-content/components/edit-story-modal/index.marko

@ -3,6 +3,7 @@
<p key="error" class="color-error">${state.error}</p>
<h2>Meta</h2>
<label>Title</label>
<input key="name" placeholder="Name" class="big" on-change("change", "name") value=state.values.name />
@ -14,7 +15,7 @@
<option for(category in input.categories) value=category.name selected=(state.values.category === category.name)>${category.name}</option>
</select>
<label>Options</label>
<h2>Options</h2>
<toggle value=state.values.listed on="Listed" off="Unlisted"
onDesc="The story will be visible on the front page."
offDesc="A direct link is required to view this story."
@ -24,5 +25,6 @@
offDesc="Only you can add chapters to this story."
on-change("change", "open") />
<h2></h2>
<button disabled=state.loading on-click("save")>Save</button>
</modal>

79
marko/page/story/components/add-story-modal/component.js

@ -0,0 +1,79 @@
const moment = require("moment")
const {storyApi} = require("../../../../../rpdata/api/Story")
module.exports = class {
onCreate() {
this.state = {
error: null,
values: {
name: "",
fictionalDate: "",
category: "Info",
open: false,
listed: false,
},
tags: [],
loading: false,
}
this.filled = false
}
addTag(tag) {
if (tag.name == "" || tag.kind == "") {
return
}
this.state.tags = this.state.tags.filter(t => t.kind !== tag.kind || t.name !== tag.name).concat([tag])
}
removeTag(tag) {
this.state.tags = this.state.tags.filter(t => t.kind !== tag.kind || t.name !== tag.name)
}
change(key, ev) {
this.state.values[key] = ev.target.value
this.state.values = Object.assign({}, this.state.values)
}
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 = {name: values.name, category: values.category, open: values.open, listed: values.listed, tags: this.state.tags}
if (fictionalDate != null) {
input.fictionalDate = fictionalDate
}
console.log(input)
this.state.loading = true
storyApi.add(input).then(data => {
this.emit("add", data)
this.emit("close")
this.state.tags = []
this.state.values = {name: "", fictionalDate: "", category: "", open: "", listed: ""}
window.location = `/story/${data.id}/`
}).catch(errs => {
console.warn("Failed to edit:", errs)
this.state.error = "Failed to edit: " + errs[0].message
this.state.loading = false
})
}
close() {
this.emit("close")
}
}

33
marko/page/story/components/add-story-modal/index.marko

@ -0,0 +1,33 @@
<modal class="modal color-text nolabel" key="modal2" enabled=(input.enabled) closable on-close("close") >
<h1>Edit Story</h1>
<p key="error" class="color-error">${state.error}</p>
<h2>Meta</h2>
<label>Title</label>
<input key="name" placeholder="Name" class="big" on-change("change", "name") value=state.values.name />
<label>IC Date</label>
<input key="icdate" placeholder="IC Date" on-change("change", "fictionalDate") value=state.values.fictionalDate />
<label>Category</label>
<select key="category" placeholder="Kind" on-change("change", "category")>
<option for(category in input.categories) value=category.name selected=(state.values.category === category.name)>${category.name}</option>
</select>
<h2>Tags</h2>
<story-tag-options small tags=state.tags loading=state.loading on-remove("removeTag") on-add("addTag") />
<h2>Options</h2>
<toggle value=state.values.listed on="Listed" off="Unlisted"
onDesc="The story will be visible on the front page."
offDesc="A direct link is required to view this story."
on-change("change", "listed") />
<toggle value=state.values.open on="Open" off="Closed"
onDesc="Other authors can add chapters to this story."
offDesc="Only you can add chapters to this story."
on-change("change", "open") />
<h2></h2>
<button disabled=state.loading on-click("save")>Add Story</button>
</modal>

16
marko/page/story/components/page/component.js

@ -0,0 +1,16 @@
module.exports = class {
onCreate(input) {
this.state = {
stories: input.stories,
modal: null,
}
}
open(modal) {
this.state.modal = modal
}
close() {
this.state.modal = null
}
}

5
marko/page/story/components/page/index.marko

@ -0,0 +1,5 @@
<story-menu categories=input.categories selected=(input.selected || {}) menuTags=input.menuTags user=input.user on-open("open") />
<main>
<story-list stories=state.stories />
<add-story-modal enabled=(state.modal === "story.add") stories=input.stories categories=input.categories on-close("close") />
</main>

5
marko/page/story/components/story-menu/component.js

@ -0,0 +1,5 @@
module.exports = class {
open(modalName) {
this.emit("open", modalName)
}
}

1
marko/page/story/components/story-menu/index.marko

@ -1,6 +1,7 @@
<menu user=input.user>
<menu-header>Story</menu-header>
<menu-link key="index" selected=input.selected.index icon="S" href="/story/">Stories</menu-link>
<menu-link dark key="_create" on-click("open", "story.add") icon="+">Add Story</menu-link>
<menu-gap />
<menu-header>Categories</menu-header>
<menu-link for(category in (input.categories||[])) key=(category.name) selected=(input.selected.category == category.name) href=`/story/by-category/${category.name}` icon=category.name.charAt(0)>${category.name}</menu-link>

5
marko/page/story/list.marko

@ -1,9 +1,6 @@
<include("../layout", {title: "Stories", site: "story"})>
<@body>
<background src="/assets/images/bg.png" opacity=0.25 />
<story-menu categories=input.categories selected=(input.selected || {}) menuTags=input.menuTags user=input.user />
<main>
<story-list stories=input.stories />
</main>
<page user=input.user stories=input.stories categories=input.categories />
</@body>
</include>

44
rpdata/api/Story.js

@ -194,6 +194,50 @@ const storyApi = {
})
},
/**
* Call `addStory(input)` mutation, returns the ID.
*
* @param {{name:string, category:string, author:string, open:boolean, listed:boolean, fictionalDate:Date, tags:Tag[]}} input
* @returns {Promise<Story>}
*/
add(input) {
return query(`
mutation AddStory($input: StoryAddInput!) {
addStory(input:$input) {
id
name
author
category
tags {
kind
name
}
listed
open
createdDate
fictionalDate
updatedDate
chapters {
id
title
author
source
createdDate
fictionalDate
editedDate
}
}
}
`, {input}, {permissions: ["member", "story.edit"]}).then(({addStory}) => {
return new Story(
addStory.id, addStory.name, addStory.author, addStory.category,
addStory.listed, addStory.open,
addStory.createdDate, addStory.updatedDate, addStory.fictionalDate,
addStory.tags, addStory.chapters
)
})
},
/**
* Call `editStory(input)` mutation, returns the changable fields.
*

Loading…
Cancel
Save