diff options
Diffstat (limited to 'animism-align/frontend')
20 files changed, 402 insertions, 12 deletions
diff --git a/animism-align/frontend/api/index.js b/animism-align/frontend/api/index.js index cb6f22a..96c4e5c 100644 --- a/animism-align/frontend/api/index.js +++ b/animism-align/frontend/api/index.js @@ -17,5 +17,7 @@ so you can do ... export { util } export const actions = [ + 'paragraph', + 'timestamp', 'upload', ].reduce((a,b) => (a[b] = crud_actions(b)) && a, {}) diff --git a/animism-align/frontend/app.js b/animism-align/frontend/app.js index 1ce80c2..7c68c61 100644 --- a/animism-align/frontend/app.js +++ b/animism-align/frontend/app.js @@ -2,7 +2,7 @@ import React, { Component } from 'react' import { ConnectedRouter } from 'connected-react-router' import { Route } from 'react-router' -// import actions from './actions' +import actions from './actions' import * as views from './views' @@ -17,6 +17,8 @@ const viewList = Object.keys(views).map(name => { export default class App extends Component { componentDidMount() { + actions.site.loadText() + actions.site.loadPeaks() } render() { return ( diff --git a/animism-align/frontend/types.js b/animism-align/frontend/types.js index 6f566b8..c14a8b1 100644 --- a/animism-align/frontend/types.js +++ b/animism-align/frontend/types.js @@ -3,6 +3,8 @@ import { with_type, crud_type } from './api/crud.types' export const api = crud_type('api', []) export const upload = crud_type('upload', []) +export const peaks = crud_type('peaks', []) +export const text = crud_type('text', []) export const site = with_type('site', [ ]) diff --git a/animism-align/frontend/views/align/align.actions.js b/animism-align/frontend/views/align/align.actions.js new file mode 100644 index 0000000..10dec44 --- /dev/null +++ b/animism-align/frontend/views/align/align.actions.js @@ -0,0 +1,5 @@ +import * as types from '../../types' +import { store, history } from '../../store' +import { api, post, pad, preloadImage } from '../../util' +import actions from '../../actions' +import { session } from '../../session' diff --git a/animism-align/frontend/views/index/index.container.js b/animism-align/frontend/views/align/align.container.js index c6cb819..af966c5 100644 --- a/animism-align/frontend/views/index/index.container.js +++ b/animism-align/frontend/views/align/align.container.js @@ -3,19 +3,18 @@ import { Route } from 'react-router-dom' import { bindActionCreators } from 'redux' import { connect } from 'react-redux' -import './index.css' +import './align.css' import actions from '../../actions' import { Header } from '../../common' // import * as uploadActions from './upload.actions' -import GraphIndex from './containers/graph.index' -import GraphNew from './containers/graph.new' -import GraphEdit from './containers/graph.edit' +// import GraphIndex from './containers/graph.index' +// import GraphNew from './containers/graph.new' +// import GraphEdit from './containers/graph.edit' class Container extends Component { componentDidMount() { - actions.site.setSiteTitle("swimmer") } render() { return ( @@ -23,9 +22,6 @@ class Container extends Component { <Header /> <div className='body'> <div className='index'> - <Route exact path='/index/new' component={GraphNew} /> - <Route exact path='/index/:id/edit' component={GraphEdit} /> - <Route exact path='/index' component={GraphIndex} /> </div> </div> </div> @@ -34,3 +30,7 @@ class Container extends Component { } export default Container + + // <Route exact path='/index/new' component={GraphNew} /> + // <Route exact path='/index/:id/edit' component={GraphEdit} /> + // <Route exact path='/index' component={GraphIndex} /> diff --git a/animism-align/frontend/views/index/index.css b/animism-align/frontend/views/align/align.css index 028f6c2..028f6c2 100644 --- a/animism-align/frontend/views/index/index.css +++ b/animism-align/frontend/views/align/align.css diff --git a/animism-align/frontend/views/align/align.reducer.js b/animism-align/frontend/views/align/align.reducer.js new file mode 100644 index 0000000..d1e8889 --- /dev/null +++ b/animism-align/frontend/views/align/align.reducer.js @@ -0,0 +1,17 @@ +import * as types from '../../types' +import { session, getDefault, getDefaultInt } from '../../session' + +import { crudState, crudReducer } from '../../api/crud.reducer' + +const initialState = { + options: { + } +} + +export default function alignReducer(state = initialState, action) { + // console.log(action.type, action) + switch (action.type) { + default: + return state + } +} diff --git a/animism-align/frontend/views/index.js b/animism-align/frontend/views/index.js index c50ab80..9af42ce 100644 --- a/animism-align/frontend/views/index.js +++ b/animism-align/frontend/views/index.js @@ -1,4 +1,2 @@ -export { default as index } from './index/index.container' -export { default as graph } from './graph/graph.container' -export { default as page } from './page/page.container' +export { default as align } from './align/align.container' export { default as upload } from './upload/upload.container' diff --git a/animism-align/frontend/views/index/components/graph.form.js b/animism-align/frontend/views/paragraph/components/paragraph.form.js index d90b663..d90b663 100644 --- a/animism-align/frontend/views/index/components/graph.form.js +++ b/animism-align/frontend/views/paragraph/components/paragraph.form.js diff --git a/animism-align/frontend/views/index/containers/graph.edit.js b/animism-align/frontend/views/paragraph/containers/paragraph.edit.js index ce1b404..ce1b404 100644 --- a/animism-align/frontend/views/index/containers/graph.edit.js +++ b/animism-align/frontend/views/paragraph/containers/paragraph.edit.js diff --git a/animism-align/frontend/views/index/containers/graph.index.js b/animism-align/frontend/views/paragraph/containers/paragraph.index.js index 35c2d82..35c2d82 100644 --- a/animism-align/frontend/views/index/containers/graph.index.js +++ b/animism-align/frontend/views/paragraph/containers/paragraph.index.js diff --git a/animism-align/frontend/views/index/containers/graph.new.js b/animism-align/frontend/views/paragraph/containers/paragraph.new.js index be96bf5..be96bf5 100644 --- a/animism-align/frontend/views/index/containers/graph.new.js +++ b/animism-align/frontend/views/paragraph/containers/paragraph.new.js diff --git a/animism-align/frontend/views/paragraph/paragraph.reducer.js b/animism-align/frontend/views/paragraph/paragraph.reducer.js new file mode 100644 index 0000000..263aa07 --- /dev/null +++ b/animism-align/frontend/views/paragraph/paragraph.reducer.js @@ -0,0 +1,20 @@ +import * as types from '../../types' +import { session, getDefault, getDefaultInt } from '../../session' + +import { crudState, crudReducer } from '../../api/crud.reducer' + +const initialState = crudState('paragraph', { + options: { + } +}) + +const reducer = crudReducer('paragraph') + +export default function paragraphReducer(state = initialState, action) { + // console.log(action.type, action) + state = reducer(state, action) + switch (action.type) { + default: + return state + } +} diff --git a/animism-align/frontend/views/site/site.actions.js b/animism-align/frontend/views/site/site.actions.js index a5b4b55..03a6a2b 100644 --- a/animism-align/frontend/views/site/site.actions.js +++ b/animism-align/frontend/views/site/site.actions.js @@ -1,3 +1,12 @@ import * as types from '../../types' // import actions from '../../actions' // import { session } from '../../session' +import { api, post, pad, preloadImage } from '../../util' + +export const loadPeaks = () => dispatch => ( + api(dispatch, types.peaks, 'peaks', '/static/data_store/peaks/peaks.json') +) + +export const loadText = () => dispatch => ( + api(dispatch, types.text, 'text', '/static/data_store/peaks/text.txt') +) diff --git a/animism-align/frontend/views/site/site.reducer.js b/animism-align/frontend/views/site/site.reducer.js index e9e5ebc..b1b4503 100644 --- a/animism-align/frontend/views/site/site.reducer.js +++ b/animism-align/frontend/views/site/site.reducer.js @@ -2,11 +2,23 @@ import * as types from '../../types' // import { session, getDefault, getDefaultInt } from '../../session' const initialState = { + peaks: { loading: true }, + text: { loading: true }, } export default function siteReducer(state = initialState, action) { // console.log(action.type, action) switch (action.type) { + case types.peaks.loaded: + return { + ...state, + peaks: action.data, + } + case types.text.loaded: + return { + ...state, + text: action.data, + } default: return state } diff --git a/animism-align/frontend/views/timestamp/components/timestamp.form.js b/animism-align/frontend/views/timestamp/components/timestamp.form.js new file mode 100644 index 0000000..d90b663 --- /dev/null +++ b/animism-align/frontend/views/timestamp/components/timestamp.form.js @@ -0,0 +1,153 @@ +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 newGraph = () => ({ + path: '', + title: '', + username: session('username'), + description: '', +}) + +export default class GraphForm extends Component { + state = { + title: "", + submitTitle: "", + data: { ...newGraph() }, + errorFields: new Set([]), + } + + componentDidMount() { + const { data, isNew } = this.props + const title = isNew ? 'new project' : 'editing ' + data.title + const submitTitle = isNew ? "Create Graph" : "Save Changes" + this.setState({ + title, + submitTitle, + errorFields: new Set([]), + data: { + ...newGraph(), + ...data + }, + }) + } + + handleChange(e) { + const { errorFields } = this.state + const { name, value } = e.target + if (errorFields.has(name)) { + errorFields.delete(name) + } + let sanitizedValue = value + if (name === 'path') { + sanitizedValue = sanitizedValue.toLowerCase().replace(/ /, '-').replace(/[!@#$%^&*()[\]{}]/, '-').replace(/-+/, '-') + } + this.setState({ + errorFields, + data: { + ...this.state.data, + [name]: sanitizedValue, + } + }) + } + + 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 graph + session.set('username', data.username) + } else { + validData.id = data.id + } + console.log('submit', validData) + onSubmit(validData) + } + } + + render() { + const { isNew } = this.props + const { title, submitTitle, errorFields, data } = this.state + return ( + <div className='form'> + <h1>{title}</h1> + <form onSubmit={this.handleSubmit.bind(this)}> + <TextInput + title="Path" + name="path" + required + data={data} + error={errorFields.has('path')} + onChange={this.handleChange.bind(this)} + autoComplete="off" + /> + <LabelDescription> + {data.path + ? 'Project URLs will be: /' + data.path + '/example' + : 'Enter the base path for this project.'} + </LabelDescription> + <TextInput + title="Title" + name="title" + required + data={data} + error={errorFields.has('title')} + onChange={this.handleChange.bind(this)} + autoComplete="off" + /> + <TextInput + title="Author" + name="username" + required + data={data} + error={errorFields.has('username')} + onChange={this.handleChange.bind(this)} + autoComplete="off" + /> + <TextArea + title="Description" + name="description" + data={data} + onChange={this.handleChange.bind(this)} + /> + <SubmitButton + title={submitTitle} + onClick={this.handleSubmit.bind(this)} + /> + {!!errorFields.size && + <label> + <span></span> + <span>Please complete the required fields =)</span> + </label> + } + </form> + </div> + ) + } +} diff --git a/animism-align/frontend/views/timestamp/containers/timestamp.edit.js b/animism-align/frontend/views/timestamp/containers/timestamp.edit.js new file mode 100644 index 0000000..ce1b404 --- /dev/null +++ b/animism-align/frontend/views/timestamp/containers/timestamp.edit.js @@ -0,0 +1,53 @@ +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 GraphForm from '../components/graph.form' + +class GraphEdit extends Component { + componentDidMount() { + console.log(this.props.match.params.id) + actions.graph.show(this.props.match.params.id) + } + + handleSubmit(data) { + actions.graph.update(data) + .then(response => { + // response + console.log(response) + history.push('/' + data.path) + }) + } + + render() { + const { show } = this.props.graph + if (show.loading || !show.res) { + return ( + <div className='form'> + <Loader /> + </div> + ) + } + return ( + <GraphForm + data={show.res} + onSubmit={this.handleSubmit.bind(this)} + /> + ) + } +} + +const mapStateToProps = state => ({ + graph: state.graph, +}) + +const mapDispatchToProps = dispatch => ({ + // searchActions: bindActionCreators({ ...searchActions }, dispatch), +}) + +export default connect(mapStateToProps, mapDispatchToProps)(GraphEdit) diff --git a/animism-align/frontend/views/timestamp/containers/timestamp.index.js b/animism-align/frontend/views/timestamp/containers/timestamp.index.js new file mode 100644 index 0000000..35c2d82 --- /dev/null +++ b/animism-align/frontend/views/timestamp/containers/timestamp.index.js @@ -0,0 +1,53 @@ +import React, { Component } from 'react' +import { Link } from 'react-router-dom' +import { bindActionCreators } from 'redux' +import { connect } from 'react-redux' + +import { Loader } from '../../../common' +import actions from '../../../actions' +// import * as uploadActions from './upload.actions' + +class GraphIndex extends Component { + componentDidMount() { + actions.graph.index() + } + render() { + const { index } = this.props + // console.log(this.props) + if (!index.order) { + return ( + <div className='graphIndex'> + <Loader /> + </div> + ) + } + // console.log(state) + return ( + <div className='graphIndex'> + <div> + <b>welcome, swimmer</b> + <Link to='/index/new'>+ new project</Link> + </div> + {index.order.map(id => { + const graph = index.lookup[id] + return ( + <div key={id}> + <Link to={'/' + graph.path}>{graph.title}</Link> + <Link to={'/index/' + id + '/edit'}>{'edit project'}</Link> + </div> + ) + })} + </div> + ) + } +} + +const mapStateToProps = state => ({ + index: state.graph.index, +}) + +const mapDispatchToProps = dispatch => ({ + // uploadActions: bindActionCreators({ ...uploadActions }, dispatch), +}) + +export default connect(mapStateToProps, mapDispatchToProps)(GraphIndex) diff --git a/animism-align/frontend/views/timestamp/containers/timestamp.new.js b/animism-align/frontend/views/timestamp/containers/timestamp.new.js new file mode 100644 index 0000000..be96bf5 --- /dev/null +++ b/animism-align/frontend/views/timestamp/containers/timestamp.new.js @@ -0,0 +1,44 @@ +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 GraphForm from '../components/graph.form' + +class GraphNew extends Component { + handleSubmit(data) { + console.log(data) + actions.graph.create(data) + .then(res => { + console.log(res) + if (res.res && res.res.id) { + history.push('/' + res.res.path) + } + }) + .catch(err => { + console.error('error') + }) + } + + render() { + return ( + <GraphForm + isNew + data={{}} + onSubmit={this.handleSubmit.bind(this)} + /> + ) + } +} + +const mapStateToProps = state => ({ + graph: state.graph, +}) + +const mapDispatchToProps = dispatch => ({ + // searchActions: bindActionCreators({ ...searchActions }, dispatch), +}) + +export default connect(mapStateToProps, mapDispatchToProps)(GraphNew) diff --git a/animism-align/frontend/views/timestamp/timestamp.reducer.js b/animism-align/frontend/views/timestamp/timestamp.reducer.js new file mode 100644 index 0000000..cf18966 --- /dev/null +++ b/animism-align/frontend/views/timestamp/timestamp.reducer.js @@ -0,0 +1,20 @@ +import * as types from '../../types' +import { session, getDefault, getDefaultInt } from '../../session' + +import { crudState, crudReducer } from '../../api/crud.reducer' + +const initialState = crudState('timestamp', { + options: { + } +}) + +const reducer = crudReducer('timestamp') + +export default function timestampReducer(state = initialState, action) { + // console.log(action.type, action) + state = reducer(state, action) + switch (action.type) { + default: + return state + } +} |
