From b5ceb782f40fc1e402d1e58bc1ced2e4038fd787 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Sat, 6 Mar 2021 17:10:15 +0100 Subject: adding project CRUD editor --- animism-align/frontend/app/actions.js | 1 + animism-align/frontend/app/store.js | 2 + animism-align/frontend/app/types.js | 1 + animism-align/frontend/app/views/index.js | 1 + .../app/views/project/components/project.form.js | 216 +++++++++++++++++++++ .../app/views/project/components/project.menu.js | 57 ++++++ .../app/views/project/containers/project.edit.js | 52 +++++ .../app/views/project/containers/project.index.js | 71 +++++++ .../app/views/project/containers/project.new.js | 62 ++++++ .../app/views/project/project.container.js | 23 +++ .../frontend/app/views/project/project.css | 13 ++ .../frontend/app/views/project/project.reducer.js | 18 ++ 12 files changed, 517 insertions(+) create mode 100644 animism-align/frontend/app/views/project/components/project.form.js create mode 100644 animism-align/frontend/app/views/project/components/project.menu.js create mode 100644 animism-align/frontend/app/views/project/containers/project.edit.js create mode 100644 animism-align/frontend/app/views/project/containers/project.index.js create mode 100644 animism-align/frontend/app/views/project/containers/project.new.js create mode 100644 animism-align/frontend/app/views/project/project.container.js create mode 100644 animism-align/frontend/app/views/project/project.css create mode 100644 animism-align/frontend/app/views/project/project.reducer.js (limited to 'animism-align/frontend/app') diff --git a/animism-align/frontend/app/actions.js b/animism-align/frontend/app/actions.js index 67cbf85..4b75fce 100644 --- a/animism-align/frontend/app/actions.js +++ b/animism-align/frontend/app/actions.js @@ -15,6 +15,7 @@ const crudActions = [ 'annotation', 'upload', 'media', + 'project', 'episode', 'venue', 'user', diff --git a/animism-align/frontend/app/store.js b/animism-align/frontend/app/store.js index 3f30abd..980437a 100644 --- a/animism-align/frontend/app/store.js +++ b/animism-align/frontend/app/store.js @@ -10,6 +10,7 @@ import annotationReducer from 'app/views/annotation/annotation.reducer' import siteReducer from 'app/views/site/site.reducer' import mediaReducer from 'app/views/media/media.reducer' import episodeReducer from 'app/views/episode/episode.reducer' +import projectReducer from 'app/views/project/project.reducer' import venueReducer from 'app/views/venue/venue.reducer' import authReducer from 'app/views/auth/auth.reducer' import userReducer from 'app/views/user/user.reducer' @@ -31,6 +32,7 @@ const createRootReducer = history => ( annotation: annotationReducer, media: mediaReducer, episode: episodeReducer, + project: projectReducer, venue: venueReducer, user: userReducer, auth: authReducer, diff --git a/animism-align/frontend/app/types.js b/animism-align/frontend/app/types.js index d4d701a..5f625d1 100644 --- a/animism-align/frontend/app/types.js +++ b/animism-align/frontend/app/types.js @@ -7,6 +7,7 @@ export const peaks = crud_type('peaks', []) export const text = crud_type('text', []) export const annotation = crud_type('annotation', []) export const episode = crud_type('episode', []) +export const project = crud_type('project', []) export const venue = crud_type('venue', []) export const user = crud_type('user', []) export const paragraph = crud_type('paragraph', [ diff --git a/animism-align/frontend/app/views/index.js b/animism-align/frontend/app/views/index.js index ba16ae1..6f86af0 100644 --- a/animism-align/frontend/app/views/index.js +++ b/animism-align/frontend/app/views/index.js @@ -4,5 +4,6 @@ export { default as upload } from './upload/upload.container' export { default as media } from './media/media.container' export { default as viewer } from './viewer/viewer.container' export { default as episode } from './episode/episode.container' +export { default as project } from './project/project.container' export { default as venue } from './venue/venue.container' export { default as users } from './user/user.container' diff --git a/animism-align/frontend/app/views/project/components/project.form.js b/animism-align/frontend/app/views/project/components/project.form.js new file mode 100644 index 0000000..7a2ef2e --- /dev/null +++ b/animism-align/frontend/app/views/project/components/project.form.js @@ -0,0 +1,216 @@ +import React, { Component } from 'react' +import { Link } from 'react-router-dom' + +import { capitalize } from 'app/utils' + +import { TextInput, TextArea, NumberInput, LabelDescription, Select, Checkbox, SubmitButton, Loader } from 'app/common' + +const newProject = () => ({ + title: '', + is_live: false, + settings: { + description: "", + base_href: "", + ftp_url: "", + ftp_base_path: "", + }, +}) + +export default class ProjectForm extends Component { + state = { + title: "", + submitTitle: "", + data: { ...newProject() }, + errorFields: new Set([]), + } + + constructor(props) { + super(props) + this.handleKeyDown = this.handleKeyDown.bind(this) + this.handleSelect = this.handleSelect.bind(this) + this.handleChange = this.handleChange.bind(this) + this.handleSettingsChange = this.handleSettingsChange.bind(this) + this.handleSettingsChangeEvent = this.handleSettingsChangeEvent.bind(this) + this.handleSubmit = this.handleSubmit.bind(this) + } + + componentDidMount() { + const { data, isNew } = this.props + const title = isNew ? 'New project' : 'Editing ' + data.title + const submitTitle = isNew ? "Add Project" : "Save Changes" + this.setState({ + title, + submitTitle, + errorFields: new Set([]), + data: { + ...newProject(), + ...data + }, + }) + window.addEventListener('keydown', this.handleKeyDown) + } + + componentWillUnmount() { + window.removeEventListener('keydown', this.handleKeyDown) + } + + handleKeyDown(e) { + // console.log(e, e.keyCode) + if ((e.ctrlKey || e.metaKey) && e.keyCode === 83) { + if (e) { + e.preventDefault() + } + this.handleSubmit() + } + } + + handleChange(e) { + const { name, value } = e.target + this.handleSelect(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, + } + }) + } + + handleSettingsChangeEvent(e) { + const { name, value } = e.target + this.handleSettingsChange(name, value) + } + + handleSettingsChange(name, value) { + // console.log(name, value) + if (name !== 'multiple') { + value = { [name]: value } + } + this.setState({ + data: { + ...this.state.data, + settings: { + ...this.state.data.settings, + ...value, + } + } + }) + } + + handleSubmit(e) { + if (e) { + e.preventDefault() + } + const { isNew, onSubmit } = this.props + const { data } = this.state + const requiredKeys = "title is_live".split(" ") + const validKeys = "title is_live settings".split(" ") + const validData = validKeys.reduce((a,b) => { a[b] = data[b]; return a }, {}) + if (!data.title) { + data.title = "TBD" + } + const errorFields = requiredKeys.filter(key => !validData[key]) + if (errorFields.length) { + console.log('error', errorFields, validData) + this.setState({ errorFields: new Set(errorFields) }) + } else { + if (isNew) { + // + } else { + validData.id = data.id + } + console.log('submit', validData) + onSubmit(validData) + } + } + + render() { + const { isNew } = this.props + const { title, submitTitle, errorFields, data } = this.state + // console.log(data) + return ( +
+

{title}

+
+ + + + +