Browse Source

UI: Started on story content

1.0
Gisle Aune 6 years ago
parent
commit
8bb4dea358
  1. BIN
      rpdata-graphiql
  2. 2
      rpdata-ui/src/App.js
  3. 4
      rpdata-ui/src/common/Menu.js
  4. 6
      rpdata-ui/src/common/css/Menu.css
  5. 51
      rpdata-ui/src/routes/story-content/StoryContentMenu.js
  6. 44
      rpdata-ui/src/routes/story-content/StoryContentRoot.js
  7. 28
      rpdata-ui/src/routes/story-content/gql/StoryContentRoot.js
  8. 1
      rpdata-ui/src/routes/story/StoryRoot.js

BIN
rpdata-graphiql

2
rpdata-ui/src/App.js

@ -2,6 +2,7 @@ import React, { Component } from 'react'
import { Route, Redirect, Switch } from "react-router-dom"; import { Route, Redirect, Switch } from "react-router-dom";
import StoryRoot from './routes/story/StoryRoot' import StoryRoot from './routes/story/StoryRoot'
import StoryContentRoot from './routes/story-content/StoryContentRoot'
import LogsRoot from './routes/logs/LogsRoot' import LogsRoot from './routes/logs/LogsRoot'
export default class App extends Component { export default class App extends Component {
@ -10,6 +11,7 @@ export default class App extends Component {
<div className="App"> <div className="App">
<Switch> <Switch>
<Redirect exact path="/" to="/story/" /> <Redirect exact path="/" to="/story/" />
<Route path="/story/:id(S[0-9a-z]{15})" component={StoryContentRoot}/>
<Route path="/story/" component={StoryRoot}/> <Route path="/story/" component={StoryRoot}/>
<Route path="/logs/" component={LogsRoot}/> <Route path="/logs/" component={LogsRoot}/>
</Switch> </Switch>

4
rpdata-ui/src/common/Menu.js

@ -22,10 +22,10 @@ export default class Menu extends Component {
} }
} }
export function MenuLink({ icon, children, tagType, to, onClick }) {
export function MenuLink({ icon, children, tagKind, to, onClick }) {
const isSelected = window.location.pathname === to const isSelected = window.location.pathname === to
const className = isSelected ? "selected" : "not-selected" const className = isSelected ? "selected" : "not-selected"
const textClass = isSelected ? "color-primary" : `color-tag-${tagType||"none"}`
const textClass = isSelected ? "color-primary" : `color-tag-${(tagKind||"none").toLowerCase()}`
const body = ( const body = (
<div className={`MenuLink color-menu ${className}`} onClick={onClick}> <div className={`MenuLink color-menu ${className}`} onClick={onClick}>

6
rpdata-ui/src/common/css/Menu.css

@ -47,10 +47,16 @@
width: 3ch; width: 3ch;
padding: 0.15em 0.125em; padding: 0.15em 0.125em;
text-align: center; text-align: center;
vertical-align: middle;
} }
.MenuLink .text { .MenuLink .text {
display: inline-block; display: inline-block;
max-width: 22ch;
white-space: nowrap;
overflow-x: hidden;
text-overflow: ellipsis;
vertical-align: middle;
} }
.MenuGap { .MenuGap {

51
rpdata-ui/src/routes/story-content/StoryContentMenu.js

@ -0,0 +1,51 @@
import React, { Component } from "react"
import moment from "moment"
import Menu, { MenuHeader, MenuLink, MenuGap } from '../../common/Menu'
export default class StoryContentMenu extends Component {
render() {
const { story } = this.props
console.log(story.tags)
return (
<Menu>
<MenuHeader>Chapters</MenuHeader>
<ChapterMenu storyId={story.id} chapters={story.chapters} />
<MenuGap />
<MenuHeader>Tags</MenuHeader>
<TagMenu tags={story.tags} />
<MenuGap />
<MenuHeader>Story</MenuHeader>
<MonthMenuItem date={story.fictionalDate} />
<MenuLink to={`/story/author/${story.author}`} icon="A">{story.author}</MenuLink>
<MenuGap />
</Menu>
)
}
}
function ChapterMenu({chapters, storyId}) {
return chapters.map((chapter, index) => (
<MenuLink to={`/story/${storyId}/${chapter.id}`} icon={index + 1}>{chapter.title}</MenuLink>
))
}
function TagMenu({tags}) {
return tags.map(tag => (
<MenuLink tagKind={tag.kind} to={`/story/tag/${tag.kind}/${tag.name}`} icon={tag.kind.charAt(0)}>{tag.name}</MenuLink>
))
}
function MonthMenuItem({date}) {
const fictionalDate = moment.utc(date)
if (fictionalDate.year() < 100) {
return null
}
const monthKey = fictionalDate.format("YYYY-MM")
const monthText = fictionalDate.format("MMM D, YYYY")
return <MenuLink to={`/story/month/${monthKey}`} icon="D">{monthText}</MenuLink>
}

44
rpdata-ui/src/routes/story-content/StoryContentRoot.js

@ -0,0 +1,44 @@
import React, { Component } from "react"
import { Route, Switch, Redirect } from "react-router-dom";
import { Query } from "react-apollo"
import Background from "../../common/Background"
import { LoadingScreen } from "../../common/LoadingScreen"
import StoryContentMenu from "./StoryContentMenu"
import storyContentRoot from "./gql/StoryContentRoot";
class StoryContentRoot extends Component {
render() {
const story = this.props.story
const chapterRedirect = story.chapters.length > 0 ? (
<Redirect exact from={`/story/${story.id}/`} to={`/story/${story.id}/${story.chapters[0].id}`} />
) : null
return (
<div className="StoryContentRoot theme-story">
<Background />
<StoryContentMenu story={this.props.story} />
<Switch>
{chapterRedirect}
</Switch>
</div>
)
}
}
export default ({id, match}) => (
<Query query={storyContentRoot} variables={{id: id || match.params.id}}>
{({ loading, error, data }) => {
if (loading) {
return <LoadingScreen className="theme-story" />
}
if (error) {
return `Error! ${error.message}`
}
return <StoryContentRoot {...data} />
}}
</Query>
)

28
rpdata-ui/src/routes/story-content/gql/StoryContentRoot.js

@ -0,0 +1,28 @@
import gql from "graphql-tag"
export default gql`
query StoryContentRoot($id: String!) {
story(id: $id) {
id
name
author
category
createdDate
fictionalDate
updatedDate
tags {
kind
name
}
chapters {
id
title
author
source
createdDate
fictionalDate
editedDate
}
}
}
`

1
rpdata-ui/src/routes/story/StoryRoot.js

@ -23,6 +23,7 @@ export class StoryIndex extends Component {
<Route exact path="/story/" component={() => <StoryList filter={{}} />} /> <Route exact path="/story/" component={() => <StoryList filter={{}} />} />
<Route exact path="/story/open/" component={() => <StoryList filter={{open: true}} />} /> <Route exact path="/story/open/" component={() => <StoryList filter={{open: true}} />} />
<Route exact path="/story/tags/" component={StoryTags} /> <Route exact path="/story/tags/" component={StoryTags} />
<Route exact path="/story/tag/:kind/:name/" component={({match}) => <StoryList filter={{tags: [match.params]}} />} />
<Route exact path="/story/category/:category/" component={({match: {params: {category}}}) => <StoryList filter={{category}} />} /> <Route exact path="/story/category/:category/" component={({match: {params: {category}}}) => <StoryList filter={{category}} />} />
</Switch> </Switch>
</div> </div>

Loading…
Cancel
Save