From 04f7efe6c05153cbd1613e7b0c78b3b6478ae39b Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Tue, 2 Jun 2020 20:25:23 +0200 Subject: new page form --- frontend/app.js | 17 ++- frontend/common/app.css | 21 +++- frontend/types.js | 4 +- frontend/views/graph/components/graph.editor.js | 35 ++++++ frontend/views/graph/components/graph.header.js | 31 ++++++ frontend/views/graph/components/page.edit.js | 55 ++++++++++ frontend/views/graph/components/page.form.js | 138 ++++++++++++++++++++++++ frontend/views/graph/components/page.new.js | 46 ++++++++ frontend/views/graph/graph.actions.js | 9 ++ frontend/views/graph/graph.container.js | 28 +++-- frontend/views/graph/graph.css | 53 ++++++++- frontend/views/index/graph.reducer.js | 21 ++++ frontend/views/index/index.container.js | 12 ++- frontend/views/site/site.actions.js | 11 +- 14 files changed, 445 insertions(+), 36 deletions(-) create mode 100644 frontend/views/graph/components/graph.editor.js create mode 100644 frontend/views/graph/components/graph.header.js create mode 100644 frontend/views/graph/components/page.edit.js create mode 100644 frontend/views/graph/components/page.form.js create mode 100644 frontend/views/graph/components/page.new.js create mode 100644 frontend/views/graph/graph.actions.js (limited to 'frontend') diff --git a/frontend/app.js b/frontend/app.js index 5be0c0f..d6bbcb8 100644 --- a/frontend/app.js +++ b/frontend/app.js @@ -2,8 +2,6 @@ import React, { Component } from 'react' import { ConnectedRouter } from 'connected-react-router' import { Route } from 'react-router' -import { Header } from './common' - // import actions from './actions' import * as views from './views' @@ -31,15 +29,12 @@ export default class App extends Component { return (
-
-
- {viewList} - { - // redirect to index!! - setTimeout(() => this.props.history.push('/index'), 10) - return null - }} /> -
+ {viewList} + { + // redirect to index!! + setTimeout(() => this.props.history.push('/index'), 10) + return null + }} />
) diff --git a/frontend/common/app.css b/frontend/common/app.css index 08b2408..a02d0e3 100644 --- a/frontend/common/app.css +++ b/frontend/common/app.css @@ -24,7 +24,8 @@ body { height: 100%; width: 100%; } -.app { +.app, +.app > div { display: flex; flex-direction: column; height: 100%; @@ -33,6 +34,7 @@ body { .app .body { display: flex; flex-grow: 1; + position: relative; } .row { @@ -87,12 +89,24 @@ header a { font-weight: 500; } header > div:first-child { - font-weight: bold; display: flex; justify-content: flex-start; align-items: center; padding-left: 1.5rem; } +header > div:last-child { + padding-right: 1.5rem; +} +header > div > button { + padding: 0.25rem; + margin: 0 0 0 0.5rem; + border-color: #8df; + color: #8df; +} +header > div > button:hover { + border-color: #fff; + color: #fff; +} header .vcat-btn { font-size: 0.875rem; padding-left: 0.5rem; @@ -125,9 +139,6 @@ header a.navbar-brand { font-size: .8rem; } -header > div:last-child { - padding-right: 8px; -} header .username { cursor: pointer; } diff --git a/frontend/types.js b/frontend/types.js index b326994..d7119fc 100644 --- a/frontend/types.js +++ b/frontend/types.js @@ -1,7 +1,9 @@ import { with_type, crud_type } from './api/crud.types' export const api = crud_type('api', []) -export const graph = crud_type('graph', []) +export const graph = crud_type('graph', [ + 'show_add_page_form', 'hide_add_page_form', +]) export const page = crud_type('page', []) export const tile = crud_type('tile', []) export const upload = crud_type('upload', []) diff --git a/frontend/views/graph/components/graph.editor.js b/frontend/views/graph/components/graph.editor.js new file mode 100644 index 0000000..aa5d751 --- /dev/null +++ b/frontend/views/graph/components/graph.editor.js @@ -0,0 +1,35 @@ +import React, { Component } from 'react' +import { Route } from 'react-router-dom' +import { bindActionCreators } from 'redux' +import { connect } from 'react-redux' + +import { session } from '../../../session' + +import { Loader } from '../../../common' + +class GraphEditor extends Component { + state = { + } + + render(){ + console.log(this.props.graph) + const { res } = this.props.graph.show + return ( +
+ {res.pages.map(page => { + console.log(page) + })} +
+ ) + } +} + +const mapStateToProps = state => ({ + graph: state.graph, +}) + +const mapDispatchToProps = dispatch => ({ + // uploadActions: bindActionCreators({ ...uploadActions }, dispatch), +}) + +export default connect(mapStateToProps, mapDispatchToProps)(GraphEditor) diff --git a/frontend/views/graph/components/graph.header.js b/frontend/views/graph/components/graph.header.js new file mode 100644 index 0000000..6a927ec --- /dev/null +++ b/frontend/views/graph/components/graph.header.js @@ -0,0 +1,31 @@ +import React from 'react' +import { bindActionCreators } from 'redux' +import { connect } from 'react-redux' +import { Link } from 'react-router-dom' + +import * as graphActions from '../graph.actions' + +function GraphHeader(props) { + return ( +
+
+ {props.site.siteTitle} +
+
+ +
+
+ ) +} + +const mapStateToProps = (state) => ({ + // auth: state.auth, + site: state.site, + // isAuthenticated: state.auth.isAuthenticated, +}) + +const mapDispatchToProps = (dispatch) => ({ + graphActions: bindActionCreators({ ...graphActions }, dispatch), +}) + +export default connect(mapStateToProps, mapDispatchToProps)(GraphHeader) diff --git a/frontend/views/graph/components/page.edit.js b/frontend/views/graph/components/page.edit.js new file mode 100644 index 0000000..f4f351b --- /dev/null +++ b/frontend/views/graph/components/page.edit.js @@ -0,0 +1,55 @@ +import React, { Component } from 'react' +import { Link } from 'react-router-dom' +import { connect } from 'react-redux' + +import { history } from '../../../store' +import actions from '../../../actions' + +import { Loader } from '../../../common' + +import PageForm from '../components/page.form' + +class PageEdit extends Component { + componentDidMount() { + console.log(this.props.match.params.id) + actions.page.show(this.props.match.params.id) + } + + handleSubmit(data) { + actions.page.update(data) + .then(response => { + // response + console.log(response) + history.push('/' + data.path) + }) + } + + render() { + const { show } = this.props.page + if (show.loading || !show.res) { + return ( +
+ +
+ ) + } + return ( + + ) + } +} + +const mapStateToProps = state => ({ + graph: state.graph, + page: state.page, +}) + +const mapDispatchToProps = dispatch => ({ + // searchActions: bindActionCreators({ ...searchActions }, dispatch), +}) + +export default connect(mapStateToProps, mapDispatchToProps)(PageEdit) diff --git a/frontend/views/graph/components/page.form.js b/frontend/views/graph/components/page.form.js new file mode 100644 index 0000000..abaf934 --- /dev/null +++ b/frontend/views/graph/components/page.form.js @@ -0,0 +1,138 @@ +import React, { Component } from 'react' +import { Link } from 'react-router-dom' + +import { session } from '../../../session' + +import { TextInput, LabelDescription, TextArea, Checkbox, SubmitButton, Loader } from '../../../common' + +const newPage = () => ({ + path: '', + title: '', + username: session('username'), + description: '', +}) + +export default class PageForm extends Component { + state = { + title: "", + submitTitle: "", + data: { ...newPage() }, + errorFields: new Set([]), + } + + componentDidMount() { + const { data, isNew } = this.props + const title = isNew ? 'new page' : 'editing ' + data.title + const submitTitle = isNew ? "Create Page" : "Save Changes" + this.setState({ + title, + submitTitle, + errorFields: new Set([]), + data: { + ...newPage(), + ...data + }, + }) + } + + handleChange(e) { + const { errorFields } = this.state + const { name, value } = e.target + if (errorFields.has(name)) { + errorFields.delete(name) + } + this.setState({ + errorFields, + data: { + ...this.state.data, + [name]: value, + } + }) + } + + handleSelect(name, value) { + const { errorFields } = this.state + if (errorFields.has(name)) { + errorFields.delete(name) + } + this.setState({ + errorFields, + data: { + ...this.state.data, + [name]: value, + } + }) + } + + handleSubmit(e) { + e.preventDefault() + const { isNew, onSubmit } = this.props + const { data } = this.state + const requiredKeys = "title username path description".split(" ") + const validKeys = "title username path description".split(" ") + const validData = validKeys.reduce((a,b) => { a[b] = data[b]; return a }, {}) + const errorFields = requiredKeys.filter(key => !validData[key]) + if (errorFields.length) { + console.log('error', errorFields, validData) + this.setState({ errorFields: new Set(errorFields) }) + } else { + if (isNew) { + // side effect: set username if we're creating a new page + // session.set('username', data.username) + } else { + validData.id = data.id + } + console.log('submit', validData) + onSubmit(validData) + } + } + + render() { + const { graph, isNew } = this.props + const { title, submitTitle, errorFields, data } = this.state + return ( +
+

{title}

+
+ + + {'Page URL: /' + graph.path + '/'}{data.path} + + +