diff options
4 files changed, 178 insertions, 14 deletions
diff --git a/animism-align/frontend/app/common/modal.css b/animism-align/frontend/app/common/modal.css index 5e95a09..98e2d05 100644 --- a/animism-align/frontend/app/common/modal.css +++ b/animism-align/frontend/app/common/modal.css @@ -5,7 +5,7 @@ width: 100%; height: 100%; z-index: 100; - background: rgba(0,0,0,0.2); + background: rgba(0,0,0,0.8); display: none; } .modal.visible { @@ -14,7 +14,7 @@ align-items: center; } .modal > div { - background: #fff; + background: #338; padding: 1rem; - box-shadow: 0 2px 4px rgba(0,0,0,0.5); + box-shadow: 0 2px 4px rgba(0,0,0,0.8); } diff --git a/animism-align/frontend/app/views/media/components/media.formGallery.js b/animism-align/frontend/app/views/media/components/media.formGallery.js index f785b40..fb4f73a 100644 --- a/animism-align/frontend/app/views/media/components/media.formGallery.js +++ b/animism-align/frontend/app/views/media/components/media.formGallery.js @@ -2,7 +2,6 @@ import React, { Component } from 'react' import { Link } from 'react-router-dom' import { ReactSortable } from "react-sortablejs" -import { session } from 'app/session' import actions from 'app/actions' import { capitalize, preloadImage, simpleArraysEqual } from 'app/utils' import { DISPLAY_SIZE, DISPLAY_QUALITY, THUMBNAIL_SIZE, THUMBNAIL_QUALITY } from 'app/constants' @@ -10,9 +9,12 @@ import { DISPLAY_SIZE, DISPLAY_QUALITY, THUMBNAIL_SIZE, THUMBNAIL_QUALITY } from import { TextInput, LabelDescription, FileInputField, Select, TextArea, Checkbox, SubmitButton, Loader } from 'app/common' import { renderThumbnail } from 'app/common/upload.helpers' +import GalleryImageForm from './media.formGalleryImage' + export default class MediaGalleryForm extends Component { state = { loading: false, + edit_image_id: null, } constructor(props) { @@ -22,6 +24,7 @@ export default class MediaGalleryForm extends Component { this.handleSettingsChange = this.handleSettingsChange.bind(this) this.handleUpload = this.handleUpload.bind(this) this.uploadSize = this.uploadSize.bind(this) + this.handleSaveItem = this.handleSaveItem.bind(this) } handleChange(e) { @@ -158,9 +161,17 @@ export default class MediaGalleryForm extends Component { } } + handleSaveItem(id, item) { + const caption_lookup = data.settings.caption_lookup || {} + caption_lookup[id] = item + this.handleSettingsChange('caption_lookup', caption_lookup) + this.setState({ edit_image_id: null }) + } + render() { const { data } = this.props - const { image_order, image_lookup, thumbnail_lookup } = data.settings + const { image_order, image_lookup, thumbnail_lookup, caption_lookup } = data.settings + const { loading, edit_image_id } = this.state // console.log(data) return ( <div className='galleryForm'> @@ -170,38 +181,61 @@ export default class MediaGalleryForm extends Component { mime="*/*" onChange={this.handleUpload} /> - {this.state.loading && <Loader />} + {loading && <Loader />} {image_order && image_order.length && <ReactSortable + className='galleryList' list={image_order.map(id => ({ id }))} setList={new_order => this.handleOrderChanged(new_order)} > {image_order.map(image_id => ( - <GalleryImageForm + <GalleryListItem id={image_id} key={image_id} image={image_lookup[image_id]} thumbnail={thumbnail_lookup[image_id]} + onClick={e => { + e.preventDefault() + e.stopPropagation() + this.setState({ edit_image_id: image_id }) + }} /> ))} </ReactSortable> } + {edit_image_id && + <GalleryImageForm + id={edit_image_id} + initalData={initialCaptionData(caption_lookup, edit_image_id)} + thumbnail={thumbnail_lookup[edit_image_id]} + onSave={this.handleSaveItem} + /> + } </div> ) } } -const GalleryImageForm = ({ id, key, image, thumbnail }) => { +const initialCaptionData = (caption_lookup, image_id) => { + caption_lookup = caption_lookup || {} + const initialData = caption_lookup[image_id] || {} + return { + ...initialData, + } +} + +const GalleryListItem = ({ id, key, image, thumbnail, onClick }) => { // console.log(image, thumbnail) return ( - <div> + <div className='galleryListItem'> {thumbnail - ? <img src={thumbnail.url} /> - : <Loader /> + ? ( + <div> + <div><img src={thumbnail.url} /></div> + <button onClick={onClick}>Edit</button> + </div> + ) : <Loader /> } </div> ) } - -/* -*/ diff --git a/animism-align/frontend/app/views/media/components/media.formGalleryImage.js b/animism-align/frontend/app/views/media/components/media.formGalleryImage.js new file mode 100644 index 0000000..1dbf1f2 --- /dev/null +++ b/animism-align/frontend/app/views/media/components/media.formGalleryImage.js @@ -0,0 +1,96 @@ +import React, { Component } from 'react' + +import { TextInput, LabelDescription, FileInputField, Select, TextArea, Checkbox, SubmitButton, Loader } from 'app/common' + +export default class GalleryImageForm extends Component { + state = { + loaded: false, + data: {}, + } + constructor(props){ + super(props) + this.handleChange = this.handleChange.bind(this) + this.handleSelect = this.handleSelect.bind(this) + } + componentDidMount() { + console.log(this.props) + this.setState({ + loaded: true, + data: { ...this.props.initialData }, + }) + } + handleChange(e) { + const { name, value } = e.target + this.handleSelect(name, value) + } + handleSelect(name, value) { + this.setState({ + data: { + ...this.state.data, + [name]: value, + } + }) + } + handleSave() { + this.props.onSave(this.props.id, this.state.data) + } + render() { + const { thumbnail } = this.props + const { loaded, data } = this.state + if (!loaded) return <div /> + console.log(data) + return ( + <div className='modal visible'> + <div className='row'> + <div> + <img src={thumbnail.url} /> + </div> + <div> + <TextInput + title="Author" + name="author" + required + data={data} + onChange={this.handleChange} + autoComplete="off" + /> + <TextInput + title="Title" + name="title" + required + data={data} + onChange={this.handleChange} + autoComplete="off" + /> + <TextInput + title="Date" + name="date" + required + data={data} + onChange={this.handleChange} + autoComplete="off" + /> + <TextArea + title="Short caption" + name="caption" + placeholder="Used on inline galleries" + data={data} + onChange={this.handleChange} + /> + <TextArea + title="Long caption" + name="long_caption" + placeholder="Used on detail views of the item, suitable for longer texts" + data={data} + onChange={this.handleChange} + /> + <SubmitButton + title={"Save"} + onClick={this.handleSubmit} + /> + </div> + </div> + </div> + ) + } +} diff --git a/animism-align/frontend/app/views/media/media.css b/animism-align/frontend/app/views/media/media.css index 81eae26..1e20f6d 100644 --- a/animism-align/frontend/app/views/media/media.css +++ b/animism-align/frontend/app/views/media/media.css @@ -67,3 +67,37 @@ background: rgba(255,32,64,0.05); border: 1px solid #f24; } + +/* image galleries */ + +.galleryListItem > div { + display: flex; + flex-direction: row; + justify-content: center; + align-items: center; + margin-bottom: 0.25rem; +} +.galleryListItem:nth-child(odd) > div > div { + background: #333; +} +.galleryListItem:nth-child(even) > div > div { + background: #444; +} +.galleryListItem > div > div { + display: flex; + justify-content: center; + align-items: center; + width: 5rem; + height: 5rem; + padding: 0.5rem; +} +.galleryListItem img { + max-height: 100%; + cursor: grab; + max-width: 100%; +} +.galleryListItem button { + margin-left: 1rem; + background: #000; + color: #88d; +}
\ No newline at end of file |
