diff options
| author | Jules Laplace <julescarbon@gmail.com> | 2021-03-08 22:11:55 +0100 |
|---|---|---|
| committer | Jules Laplace <julescarbon@gmail.com> | 2021-03-08 22:11:55 +0100 |
| commit | d2cb17038b8537a609be06be2ed7013dbe27117e (patch) | |
| tree | 028ceac9edddafc03ce80c49d5a05981bec3fcbe /animism-align/frontend/app/views/media | |
| parent | b5ceb782f40fc1e402d1e58bc1ced2e4038fd787 (diff) | |
beginning the BIG refactor. moving editor stuff into per-episode hierarchy
Diffstat (limited to 'animism-align/frontend/app/views/media')
16 files changed, 0 insertions, 1915 deletions
diff --git a/animism-align/frontend/app/views/media/components/media.form.js b/animism-align/frontend/app/views/media/components/media.form.js deleted file mode 100644 index 2d21838..0000000 --- a/animism-align/frontend/app/views/media/components/media.form.js +++ /dev/null @@ -1,287 +0,0 @@ -import React, { Component } from 'react' -import { Link } from 'react-router-dom' - -import { capitalize } from 'app/utils' - -import { TextInput, LabelDescription, Select, TextArea, Checkbox, SubmitButton, Loader } from 'app/common' - -import MediaImageForm from './media.formImage' -import MediaVideoForm from './media.formVideo' -import MediaFileForm from './media.formFile' -import MediaGalleryForm from './media.formGallery' - -const newMedia = () => ({ - type: 'gallery', - tag: 'media', - url: '', - title: '', - author: '', - pre_title: '', - post_title: '', - translated_title: '', - date: '', - source: '', - medium: '', - start_ts: 0, - settings: {}, -}) - -const MEDIA_UPLOAD_TYPES = [ - 'image', 'video', 'file', 'gallery', -].map(name => ({ name, label: capitalize(name) })) - -export default class MediaForm extends Component { - state = { - title: "", - submitTitle: "", - data: { ...newMedia() }, - 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 media' : 'Editing ' + data.title - const submitTitle = isNew ? "Add Media" : "Save Changes" - this.setState({ - title, - submitTitle, - errorFields: new Set([]), - data: { - ...newMedia(), - ...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 = "author title date".split(" ") - const validKeys = "type tag url title author pre_title post_title translated_title date source medium start_ts settings".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) { - // - } 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 ( - <div className='form'> - <h1>{title}</h1> - <form onSubmit={this.handleSubmit}> - <Select - title='Media Type' - name='type' - selected={data.type} - options={MEDIA_UPLOAD_TYPES} - onChange={this.handleSelect} - /> - - {data.type === 'image' && - <MediaImageForm - data={data} - onChange={this.handleSelect} - onSettingsChange={this.handleSettingsChange} - /> - } - - {data.type === 'video' && - <MediaVideoForm - data={data} - onChange={this.handleSelect} - onSettingsChange={this.handleSettingsChange} - /> - } - - {data.type === 'file' && - <MediaFileForm - data={data} - onChange={this.handleSelect} - onSettingsChange={this.handleSettingsChange} - /> - } - - {data.type === 'gallery' && - <MediaGalleryForm - data={data} - onChange={this.handleSelect} - onSettingsChange={this.handleSettingsChange} - /> - } - - <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="Title Prefix" - name="pre_title" - data={data} - onChange={this.handleChange} - autoComplete="off" - /> - <TextInput - title="Title Suffix" - name="post_title" - data={data} - onChange={this.handleChange} - autoComplete="off" - /> - <TextInput - title="Translated Title" - name="translated_title" - data={data} - onChange={this.handleChange} - autoComplete="off" - /> - <TextInput - title="Date" - name="date" - required - data={data} - onChange={this.handleChange} - autoComplete="off" - /> - <TextInput - title="Medium" - name="medium" - required - data={data} - onChange={this.handleChange} - /> - <TextInput - title="Source" - name="source" - placeholder="Courtesy of / Copyright" - required - data={data} - onChange={this.handleChange} - autoComplete="off" - /> - <TextArea - title="Citation" - name="bibliography" - placeholder="Use if special HTML formatting needed" - data={data.settings} - onChange={this.handleSettingsChangeEvent} - /> - <Checkbox - label="Hide in checklist" - name="hide_in_bibliography" - checked={data.settings.hide_in_bibliography} - onChange={this.handleSettingsChange} - /> - <TextArea - title="Description" - name="description" - data={data} - onChange={this.handleChange} - /> - <SubmitButton - title={submitTitle} - onClick={this.handleSubmit} - /> - {!!errorFields.size && - <label> - <span></span> - <span>Please complete the required fields</span> - </label> - } - </form> - </div> - ) - } -} diff --git a/animism-align/frontend/app/views/media/components/media.formFile.js b/animism-align/frontend/app/views/media/components/media.formFile.js deleted file mode 100644 index d3b1ae8..0000000 --- a/animism-align/frontend/app/views/media/components/media.formFile.js +++ /dev/null @@ -1,67 +0,0 @@ -import React, { Component } from 'react' -import { Link } from 'react-router-dom' - -import { session } from 'app/session' -import actions from 'app/actions' -import { capitalize } from 'app/utils' - -import { TextInput, LabelDescription, Select, TextArea, Checkbox, SubmitButton, Loader, FileInputField } from 'app/common' - -export default class MediaFileForm extends Component { - state = { - img: null, - } - - constructor(props) { - super(props) - this.handleSelect = this.handleSelect.bind(this) - this.handleChange = this.handleChange.bind(this) - this.handleSettingsChange = this.handleSettingsChange.bind(this) - this.handleUpload = this.handleUpload.bind(this) - } - - handleChange(e) { - const { name, value } = e.target - this.handleSelect(name, value) - } - - handleSelect(name, value) { - this.props.onSelect(name, value) - } - - handleSettingsChange(name, value) { - this.props.onSettingsChange(name, value) - } - - handleUpload(file) { - console.log('uploading file') - const uploadData = { - image: file, - tag: "file", - username: 'animism', - } - // uploadData['__image_filename'] = file.filename - return actions.upload.upload(uploadData).then(data => { - this.handleSettingsChange("file", data.res) - }) - } - - render() { - const { data } = this.props - console.log(data.settings) - return ( - <div className='fileForm'> - <FileInputField - title="Upload file" - mime="*/*" - onChange={this.handleUpload} - /> - {data.settings.file && - <LabelDescription> - {data.settings.file.url} - </LabelDescription> - } - </div> - ) - } -} diff --git a/animism-align/frontend/app/views/media/components/media.formGallery.js b/animism-align/frontend/app/views/media/components/media.formGallery.js deleted file mode 100644 index 2cf894b..0000000 --- a/animism-align/frontend/app/views/media/components/media.formGallery.js +++ /dev/null @@ -1,338 +0,0 @@ -import React, { Component } from 'react' -import { Link } from 'react-router-dom' -import { ReactSortable } from "react-sortablejs" - -import actions from 'app/actions' -import { capitalize, simpleArraysEqual } from 'app/utils' -import { preloadImage } from 'app/utils/image.utils' -import { DISPLAY_SIZE, DISPLAY_QUALITY, THUMBNAIL_SIZE, THUMBNAIL_QUALITY } from 'app/constants' - -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) { - super(props) - this.handleSelect = this.handleSelect.bind(this) - this.handleChange = this.handleChange.bind(this) - this.handleSettingsChange = this.handleSettingsChange.bind(this) - this.handleUpload = this.handleUpload.bind(this) - this.uploadSize = this.uploadSize.bind(this) - this.handleSaveItem = this.handleSaveItem.bind(this) - this.handleUploadGalleryThumbnail = this.handleUploadGalleryThumbnail.bind(this) - this.handleDestroyGalleryThumbnail = this.handleDestroyGalleryThumbnail.bind(this) - } - - componentDidMount() { - const { data } = this.props - this.handleSettingsChange('multiple', { - image_order: data.settings.image_order || [], - image_lookup: data.settings.image_lookup || {}, - caption_lookup: data.settings.caption_lookup || {}, - thumbnail_lookup: data.settings.thumbnail_lookup || {}, - }) - } - - handleChange(e) { - const { name, value } = e.target - this.handleSelect(name, value) - } - - handleSelect(name, value) { - this.props.onSelect(name, value) - } - - handleSettingsChange(name, value) { - this.props.onSettingsChange(name, value) - } - - handleUpload(files) { - const { data } = this.props - this.setState({ loading: true }) - this.uploadFullsize(files) - .then(() => { - this.setState({ loading: false }) - }) - } - - handleUploadGalleryThumbnail(file) { - this.setState({ loading: true }) - if (this.props.data.thumbnail) { - this.handleDestroyGalleryThumbnail() - } - this.uploadThumbnail(file, 'thumbnail', THUMBNAIL_SIZE, THUMBNAIL_QUALITY) - .then(thumbnail => { - this.uploadThumbnail(file, 'display', DISPLAY_SIZE, DISPLAY_QUALITY) - .then(display => { - console.log(thumbnail, display) - this.handleSettingsChange('multiple', { - thumbnail, display, - }) - this.setState({ loading: false }) - }) - }) - } - - handleDestroyGalleryThumbnail(e) { - if (e) { - e.preventDefault() - e.stopPropagation() - } - console.log(this.props.data) - actions.upload.destroy({ id: this.props.data.settings.thumbnail.id }) - } - - uploadFullsize(files) { - const { data } = this.props - // first, upload all the fullsize files - let fullsizeUploadPromises = files.map(file => { - return this.uploadSize(file, 'fullsize') - }) - // when these are done - return Promise.all(fullsizeUploadPromises).then(results => { - // get the added IDs in order - const added_image_order = results.map(result => result.id) - // append the new IDs to the image order - const new_image_order = (data.settings.image_order || []).concat(added_image_order) - // add the images to the lookup - const image_lookup = results.reduce((a,b) => { - a[b.id] = b - return a - }, (data.settings.image_lookup || {})) - // add these images to the settings object - this.handleSettingsChange('multiple', { - image_order: new_image_order, - image_lookup: image_lookup, - caption_lookup: data.settings.caption_lookup || {}, - thumbnail_lookup: data.settings.thumbnail_lookup || {}, - }) - return this.uploadResizedFiles(files, added_image_order) - }) - } - - uploadResizedFiles(files, added_image_order) { - return ( - this.uploadThumbnails(files, added_image_order, 'thumbnail', THUMBNAIL_SIZE, THUMBNAIL_QUALITY) - .then(() => { - return this.uploadThumbnails(files, added_image_order, 'display', DISPLAY_SIZE, DISPLAY_QUALITY) - }) - ) - } - - uploadThumbnails(files, added_image_order, tag, maxSide, quality) { - const { data } = this.props - // construct thumbnails and upload these - const thumbnailUploadPromises = files.map(file => { - return this.uploadThumbnail(file, tag, maxSide, quality) - }) - // once the thumbnails are done uploading... - return Promise.all(thumbnailUploadPromises).then(thumbnail_results => { - // decide which lookup we're adding to - const tag_lookup_name = tag + '_lookup' - const tag_lookup = data.settings[tag_lookup_name] || {} - // add them to the thumbnail lookup, keyed off the ID of the fullsize image - const thumbnail_lookup = thumbnail_results.reduce((a, b, i) => { - const id = added_image_order[i] - a[id] = b - return a - }, tag_lookup) - // update the settings object - this.handleSettingsChange('multiple', { - [tag_lookup_name]: thumbnail_lookup, - }) - }) - } - - uploadThumbnail(file, tag, maxSide, quality) { - return new Promise((resolve, reject) => { - const type = (file.name.match('.png') !== -1) ? 'image/png' : 'image/jpg' - const fr = new FileReader() - fr.onload = fileReaderEvent => { - fr.onload = null - const image = new Image() - image.onload = () => { - image.onload = null - const thumbnailCanvas = renderThumbnail(image, { maxSide }) - thumbnailCanvas.toBlob(thumbnail => { - this.uploadSize(thumbnail, tag, file.name) - .then(res => { - resolve(res) - }) - .catch(err => { - reject(err) - }) - }, type, quality) - } - image.src = fileReaderEvent.target.result - } - fr.readAsDataURL(file) - }) - } - - uploadSize(image, tag, fn) { - // console.log('uploading size', tag) - const uploadData = { - image, - tag, - username: 'animism', - } - if (fn) { - uploadData['__image_filename'] = fn - } - // console.log(uploadData) - return actions.upload.upload(uploadData).then(data => { - // console.log(data) - return data.res - }) - } - - handleOrderChanged(new_image_order) { - // console.log(new_image_order) - const image_order = new_image_order.map(el => el.id) - if (!simpleArraysEqual(image_order, this.props.data.settings.image_order)) { - this.handleSettingsChange('image_order', image_order) - } - } - - handleSaveItem(id, item, editNext) { - if (!id) { - this.setState({ edit_image_id: null }) - } - const caption_lookup = this.props.data.settings.caption_lookup || {} - caption_lookup[id] = item - this.handleSettingsChange('caption_lookup', caption_lookup) - if (editNext) { - const image_order = this.props.data.settings.image_order - const index = image_order.indexOf(id) + 1 - if (index < image_order.length) { - this.setState({ edit_image_id: image_order[index] }) - } else { - this.setState({ edit_image_id: null }) - } - } else { - this.setState({ edit_image_id: null }) - } - } - - handleDeleteItem(id) { - let { image_order, image_lookup, thumbnail_lookup, display_lookup, caption_lookup } = this.props.data.settings - const new_image_order = image_order.filter(n => n !== id) - caption_lookup = caption_lookup || {} - const image_lookup_upload_id = ((image_lookup && image_lookup[id]) || {}).id - if (image_lookup_upload_id) { - actions.upload.destroy({ id: image_lookup_upload_id }) - } - const thumbnail_lookup_upload_id = ((thumbnail_lookup && thumbnail_lookup[id]) || {}).id - if (thumbnail_lookup_upload_id) { - actions.upload.destroy({ id: thumbnail_lookup_upload_id }) - } - const display_lookup_upload_id = ((display_lookup && display_lookup[id]) || {}).id - if (display_lookup_upload_id) { - actions.upload.destroy({ id: display_lookup_upload_id }) - } - image_lookup && delete image_lookup[id] - thumbnail_lookup && delete thumbnail_lookup[id] - display_lookup && delete display_lookup[id] - caption_lookup && delete caption_lookup[id] - this.handleSettingsChange('multiple', { - image_order: new_image_order, - image_lookup: { ...image_lookup }, - thumbnail_lookup: { ...thumbnail_lookup }, - display_lookup: { ...display_lookup }, - caption_lookup: { ...caption_lookup }, - }) - } - - render() { - const { data } = this.props - 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'> - <FileInputField - multiple - title="Upload images" - mime="*/*" - onChange={this.handleUpload} - /> - {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 => ( - <GalleryListItem - id={image_id} - key={image_id} - image={image_lookup[image_id]} - thumbnail={thumbnail_lookup[image_id]} - onEdit={e => { - e.preventDefault() - e.stopPropagation() - this.setState({ edit_image_id: image_id }) - }} - onDestroy={e => { - e.preventDefault() - e.stopPropagation() - this.handleDeleteItem(image_id) - }} - /> - ))} - </ReactSortable> - } - {edit_image_id && - <GalleryImageForm - id={edit_image_id} - initialData={initialCaptionData(caption_lookup, edit_image_id)} - thumbnail={thumbnail_lookup[edit_image_id]} - onSave={this.handleSaveItem} - /> - } - <FileInputField - title="Upload thumbnail" - mime="*/*" - onChange={this.handleUploadGalleryThumbnail} - /> - {data.settings.thumbnail && - <div className='label'> - <span>Thumbnail</span> - <img src={data.settings.thumbnail.url} /> - <button onClick={this.handleDestroyGalleryThumbnail}>x</button> - </div> - } - </div> - ) - } -} - -const initialCaptionData = (caption_lookup, image_id) => { - caption_lookup = caption_lookup || {} - return caption_lookup[image_id] || {} -} - -const GalleryListItem = ({ id, key, image, thumbnail, onEdit, onDestroy }) => { - // console.log(image, thumbnail) - return ( - <div className='galleryListItem'> - {thumbnail - ? ( - <div> - <div><img src={thumbnail.url} /></div> - <button onClick={onEdit}>Edit</button> - <button onClick={onDestroy}>x</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 deleted file mode 100644 index 4d2b99c..0000000 --- a/animism-align/frontend/app/views/media/components/media.formGalleryImage.js +++ /dev/null @@ -1,129 +0,0 @@ -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) - this.handleSubmit = this.handleSubmit.bind(this) - this.handleSubmitAndEditNext = this.handleSubmitAndEditNext.bind(this) - this.handleCancel = this.handleCancel.bind(this) - } - componentDidMount() { - this.setState({ - loaded: true, - data: { ...this.props.initialData }, - }) - } - componentDidUpdate(prevProps) { - if (this.props.id !== prevProps.id) { - this.setState({ - 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, - } - }) - } - handleSubmit(e) { - e.preventDefault() - e.stopPropagation() - this.props.onSave(this.props.id, this.state.data) - } - handleSubmitAndEditNext(e) { - e.preventDefault() - e.stopPropagation() - this.props.onSave(this.props.id, this.state.data, true) - } - handleCancel(e) { - e.preventDefault() - e.stopPropagation() - this.props.onSave(null) - } - render() { - const { thumbnail } = this.props - const { loaded, data } = this.state - if (!loaded) return <div /> - return ( - <div className='modal visible'> - <div className='row'> - <div> - <img src={thumbnail.url} /> - </div> - <div> - <TextInput - title="Author" - name="author" - data={data} - onChange={this.handleChange} - autoComplete="off" - /> - <TextInput - title="Title" - name="title" - data={data} - onChange={this.handleChange} - autoComplete="off" - /> - <TextInput - title="Date" - name="date" - data={data} - onChange={this.handleChange} - autoComplete="off" - /> - <TextInput - title="Medium" - name="medium" - data={data} - onChange={this.handleChange} - autoComplete="off" - /> - <Checkbox - label="Include in checklist" - name="in_checklist" - checked={data.in_checklist} - onChange={this.handleSelect} - /> - <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} - /> - <div className='label'> - <span></span> - <div className='buttons'> - <button onClick={this.handleSubmit}>Save and close</button> - <button onClick={this.handleSubmitAndEditNext}>Save and edit next</button> - </div> - </div> - </div> - </div> - </div> - ) - } -} diff --git a/animism-align/frontend/app/views/media/components/media.formImage.js b/animism-align/frontend/app/views/media/components/media.formImage.js deleted file mode 100644 index dbbf69f..0000000 --- a/animism-align/frontend/app/views/media/components/media.formImage.js +++ /dev/null @@ -1,169 +0,0 @@ -import React, { Component } from 'react' -import { Link } from 'react-router-dom' - -import { session } from 'app/session' -import actions from 'app/actions' -import { capitalize } from 'app/utils' -import { preloadImage, cropImage } from 'app/utils/image.utils' -import { DISPLAY_SIZE, DISPLAY_QUALITY, THUMBNAIL_SIZE, THUMBNAIL_QUALITY } from 'app/constants' - -import { TextInput, LabelDescription, UploadImage, Select, TextArea, Checkbox, SubmitButton, Loader } from 'app/common' -import { renderThumbnail } from 'app/common/upload.helpers' - -import ImageSelection from './media.formImageSelection' - -export default class MediaImageForm extends Component { - state = { - img: null, - } - - constructor(props) { - super(props) - this.handleSelect = this.handleSelect.bind(this) - this.handleChange = this.handleChange.bind(this) - this.handleSettingsChange = this.handleSettingsChange.bind(this) - this.handleUpload = this.handleUpload.bind(this) - this.handleCrop = this.handleCrop.bind(this) - this.replaceTaggedSize = this.replaceTaggedSize.bind(this) - this.uploadTaggedSize = this.uploadTaggedSize.bind(this) - } - - componentDidMount() { - // this.setState({ }) - if (this.props.data.settings.fullsize) { - preloadImage(this.props.data.settings.fullsize.url) - .then(img => this.setState({ img })) - } - } - - handleChange(e) { - const { name, value } = e.target - this.handleSelect(name, value) - } - - handleSelect(name, value) { - this.props.onSelect(name, value) - } - - handleSettingsChange(name, value) { - this.props.onSettingsChange(name, value) - } - - handleUpload({ file, img, canvas, blob }) { - // sizes: fullsize, display, thumbnail - this.replaceTaggedSize(file, 'fullsize') - .then(data => { - this.setState({ img }) - this.props.onSettingsChange('multiple', { - fullsize: data, - crop: {}, - }) - return this.replaceTaggedSize(blob, 'display', file.name) - }).then(data => { - this.props.onSettingsChange('multiple', { - display: data, - }) - this.uploadThumbnail(img) - }) - } - - uploadThumbnail(img) { - const { fn } = this.props.data.settings.fullsize - const thumbnailCanvas = renderThumbnail(img, { maxSide: THUMBNAIL_SIZE }) - thumbnailCanvas.toBlob(thumbnail => { - this.replaceTaggedSize(thumbnail, 'thumbnail', fn).then(data => { - this.props.onSettingsChange('multiple', { - thumbnail: data, - }) - }) - }, 'image/jpeg', THUMBNAIL_QUALITY) - } - - replaceTaggedSize(image, tag, fn) { - // when we upload an image, if the image already exists in this "position" - // on the record, we should also delete it - if (this.props.data.settings[tag] && this.props.data.settings[tag].id) { - return new Promise((resolve, reject) => { - actions.upload.destroy(this.props.data.settings[tag]) - .then(() => { - console.log('destroy successful') - this.uploadTaggedSize(image, tag, fn).then(data => resolve(data)) - }) - .catch(() => { - console.log('error deleting the image') - this.uploadTaggedSize(image, tag, fn).then(data => resolve(data)) - }) - }) - } - return this.uploadTaggedSize(image, tag, fn) - } - - uploadTaggedSize(image, tag, fn) { - console.log('uploading size', tag) - const uploadData = { - image, - tag, - username: 'animism', - } - if (fn) { - uploadData['__image_filename'] = fn - } - // console.log(uploadData) - return actions.upload.upload(uploadData).then(data => { - // console.log(data) - return data.res - }) - } - - handleCrop(crop) { - // when cropping an image, re-upload the display image and thumbnail - // console.log(crop) - cropImage(this.state.img, crop, DISPLAY_SIZE) - .then(canvas => { - canvas.toBlob(blob => { - // console.log(canvas, canvas.width, canvas.height, blob) - this.replaceTaggedSize(blob, 'display', this.props.data.settings.fullsize.fn) - .then(data => { - this.props.onSettingsChange('multiple', { - crop, - display: data, - }) - this.uploadThumbnail(canvas) - }) - }, 'image/jpeg', DISPLAY_QUALITY) - }) - } - - render() { - const { data } = this.props - // console.log(data) - return ( - <div className='imageForm'> - {!data.url && - <label className={'text fileInput'}> - <span>{"Upload image"}</span> - <div className="row"> - <button> - {"Choose image"} - </button> - <UploadImage - onUpload={this.handleUpload} - maxSide={DISPLAY_SIZE} - quality={DISPLAY_QUALITY} - /> - </div> - </label> - } - {data.settings.fullsize && - <div> - <ImageSelection - url={data.settings.fullsize.url} - crop={data.settings.crop} - onCrop={this.handleCrop} - /> - </div> - } - </div> - ) - } -} diff --git a/animism-align/frontend/app/views/media/components/media.formImageSelection.js b/animism-align/frontend/app/views/media/components/media.formImageSelection.js deleted file mode 100644 index 966eb58..0000000 --- a/animism-align/frontend/app/views/media/components/media.formImageSelection.js +++ /dev/null @@ -1,213 +0,0 @@ -import React, { Component } from 'react' -import { Link } from 'react-router-dom' -import { bindActionCreators } from 'redux' -import { connect } from 'react-redux' -import toBlob from 'data-uri-to-blob' - -import { clamp } from 'app/utils' -import { Loader } from 'app/common' - -const defaultState = { - dragging: false, - draggingBox: false, - bounds: null, - mouseX: 0, - mouseY: 0, - box: { - x: 0, - y: 0, - w: 0, - h: 0, - } -} - -export default class ImageSelection extends Component { - state = { - ...defaultState - } - - constructor() { - super() - // bind these events in the constructor, so we can remove event listeners later - this.handleMouseDown = this.handleMouseDown.bind(this) - this.handleMouseDownOnBox = this.handleMouseDownOnBox.bind(this) - this.handleMouseMove = this.handleMouseMove.bind(this) - this.handleMouseUp = this.handleMouseUp.bind(this) - this.handleWindowResize = this.handleWindowResize.bind(this) - } - - componentDidMount() { - document.body.addEventListener('mousemove', this.handleMouseMove) - document.body.addEventListener('mouseup', this.handleMouseUp) - window.addEventListener('resize', this.handleWindowResize) - } - - componentDidUpdate(prevProps) { - if (this.state.bounds && this.props.url !== prevProps.url) { - this.setState({ - ...defaultState, - bounds: this.getBoundingClientRect(), - box: this.props.crop || defaultState.box, - }) - } - } - - componentWillUnmount() { - document.body.removeEventListener('mousemove', this.handleMouseMove) - document.body.removeEventListener('mouseup', this.handleMouseUp) - window.removeEventListener('resize', this.handleWindowResize) - } - - getBoundingClientRect() { - if (!this.imgRef) return null - const rect = this.imgRef.getBoundingClientRect() - const scrollTop = document.body.scrollTop || document.body.parentNode.scrollTop - const scrollLeft = document.body.scrollLeft || document.body.parentNode.scrollLeft - const bounds = { - top: rect.top + scrollTop, - left: rect.left + scrollLeft, - width: rect.width, - height: rect.height, - } - return bounds - } - - handleLoad() { - const bounds = this.getBoundingClientRect() - const box = this.props.crop || defaultState.box - this.setState({ bounds, box }) - } - - handleWindowResize() { - if (!this.imgRef) return - const bounds = this.getBoundingClientRect() - this.setState({ bounds }) - } - - handleMouseDown(e) { - e.preventDefault() - const bounds = this.getBoundingClientRect() - const mouseX = e.pageX - const mouseY = e.pageY - const x = (mouseX - bounds.left) / bounds.width - const y = (mouseY - bounds.top) / bounds.height - const w = 1 / bounds.width - const h = 1 / bounds.height - this.setState({ - dragging: true, - bounds, - mouseX, - mouseY, - box: { - x, y, w, h, - } - }) - } - - handleMouseDownOnBox(e) { - const bounds = this.getBoundingClientRect() - const mouseX = e.pageX - const mouseY = e.pageY - this.setState({ - draggingBox: true, - bounds, - mouseX, - mouseY, - initialBox: { - ...this.state.box - }, - box: { - ...this.state.box - } - }) - } - - handleMouseMove(e) { - const { - dragging, draggingBox, - bounds, mouseX, mouseY, initialBox, box - } = this.state - if (dragging) { - e.preventDefault() - let { x, y } = box - let dx = (e.pageX - mouseX) / bounds.width - let dy = (e.pageY - mouseY) / bounds.height - let w = clamp(dx, 0.0, 1.0 - x) - let h = clamp(dy, 0.0, 1.0 - y) - this.setState({ - box: { - x, y, w, h, - } - }) - } else if (draggingBox) { - e.preventDefault() - let { x, y, w, h } = initialBox - let dx = (e.pageX - mouseX) / bounds.width - let dy = (e.pageY - mouseY) / bounds.height - this.setState({ - box: { - x: clamp(x + dx, 0, 1.0 - w), - y: clamp(y + dy, 0, 1.0 - h), - w, - h, - } - }) - } - } - - handleMouseUp(e) { - const { onCrop } = this.props - const { dragging, draggingBox, bounds, box } = this.state - if (!dragging && !draggingBox) return - e.preventDefault() - const { x, y, w, h } = box - let url = window.location.pathname - this.setState({ - dragging: false, - draggingBox: false, - }) - if (w < 10 / bounds.width || h < 10 / bounds.height) { - this.setState({ box: { ...defaultState.box }}) - onCrop({}) - } else { - // pass the box dimensions up - do the search again - onCrop(box) - } - } - - render() { - const { url } = this.props - const { bounds, box } = this.state - const { x, y, w, h } = box - return ( - <div className="imageSelection"> - <img - src={url} - ref={ref => this.imgRef = ref} - onMouseDown={this.handleMouseDown} - onLoad={this.handleLoad.bind(this)} - crossOrigin='anonymous' - /> - {!!w && - <div - className="box" - style={{ - left: x * bounds.width, - top: y * bounds.height, - width: w * bounds.width, - height: h * bounds.height, - }} - onMouseDown={this.handleMouseDownOnBox} - /> - } - </div> - ) - } -} - -const boxToFixed = ({ x, y, w, h }) => ({ - x: x.toFixed(3), - y: y.toFixed(3), - w: w.toFixed(3), - h: h.toFixed(3), -}) diff --git a/animism-align/frontend/app/views/media/components/media.formVideo.js b/animism-align/frontend/app/views/media/components/media.formVideo.js deleted file mode 100644 index 35cee2d..0000000 --- a/animism-align/frontend/app/views/media/components/media.formVideo.js +++ /dev/null @@ -1,118 +0,0 @@ -import React, { Component } from 'react' -import { Link } from 'react-router-dom' -import VimeoPlayer from '@u-wave/react-vimeo' - -import actions from 'app/actions' -import { capitalize } from 'app/utils' -import { posterURL } from 'app/utils/annotation.utils' -import { TextInput, LabelDescription, Select, TextArea, Checkbox, SubmitButton, Loader, FileInputField } from 'app/common' - -import { getVimeoMetadata } from 'app/views/media/media.actions' - -export default class MediaVideoForm extends Component { - state = { - } - - constructor(props) { - super(props) - this.handleSelect = this.handleSelect.bind(this) - this.handleChange = this.handleChange.bind(this) - this.handleSettingsChange = this.handleSettingsChange.bind(this) - this.handleUpload = this.handleUpload.bind(this) - } - - handleChange(e) { - let { name, value } = e.target - return this.handleSelect(name, value) - } - - handleSelect(name, value) { - value = value.trim() - if (name === 'url') { - getVimeoMetadata(value) - .then(data => { - console.log('video metadata', data) - this.props.onChange(name, value) - setTimeout(() => { - this.props.onSettingsChange('video', { - thumbnail_url: data.thumbnail_url, - duration: data.duration, - video_id: data.video_id, - }) - }, 20) - }) - } else { - this.props.onChange(name, value) - } - } - - handleSettingsChange(e) { - let { name, value } = e.target - this.props.onSettingsChange(name, value) - } - - handleSettingsSelect(name, value) { - this.props.onSettingsChange(name, value) - } - - handleUpload(file) { - console.log('uploading poster image') - const uploadData = { - image: file, - tag: "poster", - username: 'animism', - } - // uploadData['__image_filename'] = file.filename - return actions.upload.upload(uploadData).then(data => { - this.handleSettingsSelect("poster", data.res) - }) - } - - render() { - const { data } = this.props - const poster_url = posterURL(data) - return ( - <div className='videoForm'> - <TextInput - title="Video URL" - name="url" - required - data={data} - onChange={this.handleChange} - autoComplete="off" - /> - - {data.url && ( - <div> - <LabelDescription className='video'> - <VimeoPlayer video={data.url} /> - </LabelDescription> - - {poster_url && - <LabelDescription className='thumbnail'> - <a href={poster_url} target="_blank"> - <img src={poster_url} /> - </a> - </LabelDescription> - } - - <FileInputField - title="Poster image" - mime="*/*" - onChange={this.handleUpload} - /> - - <TextArea - title="Subtitles" - name="subtitles" - required - data={data.settings} - onChange={this.handleSettingsChange} - autoComplete="off" - /> - </div> - )} - </div> - ) - } -} diff --git a/animism-align/frontend/app/views/media/components/media.indexOptions.js b/animism-align/frontend/app/views/media/components/media.indexOptions.js deleted file mode 100644 index d8187c9..0000000 --- a/animism-align/frontend/app/views/media/components/media.indexOptions.js +++ /dev/null @@ -1,59 +0,0 @@ -import React, { Component } from 'react' -import { Link } from 'react-router-dom' -import { bindActionCreators } from 'redux' -import { connect } from 'react-redux' - -import actions from 'app/actions' - -import { Select, Checkbox } from 'app/common' - -const thumbnailOptions = [ - { name: 'th', label: 'Thumbnails', }, - { name: 'sm', label: 'Small', }, - { name: 'md', label: 'Medium', }, - { name: 'lg', label: 'Large', }, - { name: 'orig', label: 'Original', }, -] - -const sortOptions = [ - { name: 'id-asc', label: 'Most recent' }, - { name: 'id-desc', label: 'Oldest first' }, - { name: 'username-asc', label: 'Username (A-Z)' }, - { name: 'username-desc', label: 'Username (Z-A)' }, - { name: 'author-asc', label: 'Author (A-Z)' }, - { name: 'author-desc', label: 'Author (Z-A)' }, - { name: 'title-asc', label: 'Title (A-Z)' }, - { name: 'title-desc', label: 'Title (Z-A)' }, - // { name: '-asc', label: '' }, - // { name: '-desc', label: '' }, - // { name: '-asc', label: '' }, - // { name: '-desc', label: '' }, - // { name: '-asc', label: '' }, - // { name: '-desc', label: '' }, -] - -class IndexOptions extends Component { - render() { - const { options } = this.props - return ( - <div className='row menubar'> - <div /> - <Select - name={'sort'} - options={sortOptions} - selected={options.sort} - onChange={actions.upload.updateOption} - /> - </div> - ) - } -} - -const mapStateToProps = state => ({ - options: state.upload.options, -}) - -const mapDispatchToProps = dispatch => ({ -}) - -export default connect(mapStateToProps, mapDispatchToProps)(IndexOptions) diff --git a/animism-align/frontend/app/views/media/components/media.menu.js b/animism-align/frontend/app/views/media/components/media.menu.js deleted file mode 100644 index b782cdc..0000000 --- a/animism-align/frontend/app/views/media/components/media.menu.js +++ /dev/null @@ -1,58 +0,0 @@ -import React, { Component } from 'react' -import { Route, Link } from 'react-router-dom' -import { connect } from 'react-redux' - -import { history } from 'app/store' -import actions from 'app/actions' -import { MenuButton, FileInput } from 'app/common' - -const mapStateToProps = state => ({ - media: state.media, -}) - -export default class MediaMenu extends Component { - render() { - return ( - <div className='menuButtons'> - <Route exact path='/media/:id/show/' component={MediaShowMenu} /> - <Route exact path='/media/:id/edit/' component={MediaEditMenu} /> - <Route exact path='/media/new/' component={MediaNewMenu} /> - <Route exact path='/media/' component={MediaIndexMenu} /> - </div> - ) - } -} - -const MediaIndexMenu = () => ([ - <MenuButton key='new' name="new" href="/media/new/" />, -]) - -const MediaShowMenu = connect(mapStateToProps)((props) => ([ - <MenuButton key='back' name="back" href="/media/" />, - <MenuButton key='edit' name="edit" href={"/media/" + props.match.params.id + "/edit/"} />, - <MenuButton key='delete' name="delete" onClick={() => { - const { res: media } = props.media.show - if (confirm("Really delete this media?")) { - actions.media.destroy(media).then(() => { - history.push('/media/') - }) - } - }} />, -])) - -const MediaNewMenu = (props) => ([ - <MenuButton key='back' name="back" href="/media/" />, -]) - -const MediaEditMenu = connect(mapStateToProps)((props) => ([ - <MenuButton key='back' name="back" href="/media/" />, - <MenuButton key='copy' name="copy" href={"/media/" + props.match.params.id + '/copy/'} label="Make a copy" />, - <MenuButton key='delete' name="delete" onClick={() => { - const { res: media } = props.media.show - if (confirm("Really delete this media?")) { - actions.media.destroy(media).then(() => { - history.push('/media/') - }) - } - }} />, -])) diff --git a/animism-align/frontend/app/views/media/containers/media.edit.js b/animism-align/frontend/app/views/media/containers/media.edit.js deleted file mode 100644 index cf5f671..0000000 --- a/animism-align/frontend/app/views/media/containers/media.edit.js +++ /dev/null @@ -1,57 +0,0 @@ -import React, { Component } from 'react' -import { Link } from 'react-router-dom' -import { connect } from 'react-redux' - -import { history } from 'app/store' -import actions from 'app/actions' - -import { Loader } from 'app/common' - -import MediaForm from '../components/media.form' -import MediaMenu from '../components/media.menu' - -class MediaEdit extends Component { - componentDidMount() { - console.log(this.props.match.params.id) - actions.media.show(this.props.match.params.id) - } - - handleSubmit(data) { - actions.media.update(data) - .then(response => { - // response - console.log(response) - history.push('/media/') - }) - } - - render() { - const { show } = this.props.media - if (show.loading || !show.res) { - return ( - <div className='form'> - <Loader /> - </div> - ) - } - return ( - <div className='row formContainer'> - <MediaMenu mediaActions={this.props.mediaActions} /> - <MediaForm - data={show.res} - onSubmit={this.handleSubmit.bind(this)} - /> - </div> - ) - } -} - -const mapStateToProps = state => ({ - media: state.media, -}) - -const mapDispatchToProps = dispatch => ({ - // mediaActions: bindActionCreators({ ...mediaActions }, dispatch), -}) - -export default connect(mapStateToProps, mapDispatchToProps)(MediaEdit) diff --git a/animism-align/frontend/app/views/media/containers/media.index.js b/animism-align/frontend/app/views/media/containers/media.index.js deleted file mode 100644 index da94d3c..0000000 --- a/animism-align/frontend/app/views/media/containers/media.index.js +++ /dev/null @@ -1,160 +0,0 @@ -import React, { Component } from 'react' -import { Link } from 'react-router-dom' -import { bindActionCreators } from 'redux' -import { connect } from 'react-redux' - -import { formatDateTime } from 'app/utils' -import { MenuButton, SmallMenuButton, Loader } from 'app/common' -import actions from 'app/actions' - -import { thumbnailURL } from 'app/utils/annotation.utils' - -import MediaIndexOptions from '../components/media.indexOptions' -import MediaMenu from '../components/media.menu' - -// const { result, collectionLookup } = this.props - -class MediaIndex extends Component { - componentDidMount() { - // this.fetch(false) - } - - componentDidUpdate(prevProps) { - if (this.props.media.options.sort !== prevProps.media.options.sort) { - this.fetch(false) - } - } - - fetch(load_more) { - const { options, index } = this.props.media - const { order: index_order } = index - const [ sort, order ] = options.sort.split(' ') - actions.media.index({ - sort, order, limit: 5000, // offset: load_more ? index_order.length : 0, - }, load_more) - } - - render() { - const { mediaActions } = this.props - const { options } = this.props.media - const { loading, lookup, order } = this.props.media.index - if (loading) { - return ( - <section> - <MediaIndexOptions /> - <div className="row"> - {order && !!order.length && - <div className={'results ' + options.thumbnailSize}> - {order.map(id => <MediaItem key={id} data={lookup[id]} />)} - </div> - } - </div> - <Loader /> - </section> - ) - } - if (!lookup || !order.length) { - return ( - <section> - <MediaIndexOptions /> - <div className="row"> - <MediaMenu /> - <p className='gray'> - {"No media"} - </p> - </div> - </section> - ) - } - return ( - <section> - <MediaIndexOptions /> - <div className="row"> - <MediaMenu /> - <div className={'results ' + options.thumbnailSize}> - <h2>Images</h2> - {order.filter(id => lookup[id].type === 'image').map(id => <MediaItem key={id} data={lookup[id]} />)} - <h2>Galleries</h2> - {order.filter(id => lookup[id].type === 'gallery').map(id => <GalleryItem key={id} data={lookup[id]} />)} - <h2>Videos</h2> - {order.filter(id => lookup[id].type === 'video' && !lookup[id].medium.match(/book/i)).map(id => <MediaItem key={id} data={lookup[id]} />)} - <h2>Books</h2> - {order.filter(id => lookup[id].type === 'video' && lookup[id].medium.match(/book/i)).map(id => <MediaItem key={id} data={lookup[id]} />)} - <h2>Files</h2> - {order.filter(id => lookup[id].type === 'file').map(id => <FileItem key={id} data={lookup[id]} />)} - </div> - </div> - {order.length >= 50 && <button className='loadMore' onClick={() => this.fetch(true)}>Load More</button>} - </section> - ) - } -} - -const MediaItem = ({ data }) => { - // console.log(data) - return ( - <div className='cell'> - <div className='img'> - <Link to={"/media/" + data.id + "/edit/"}> - <img src={thumbnailURL(data)} alt={data.title} /> - </Link> - </div> - <div className='meta center'> - <div> - <i>{data.title}</i><br /> - {data.author}<br /> - {data.date} - </div> - </div> - </div> - ) -} - -const GalleryItem = ({ data }) => { - // console.log(data) - return ( - <div className='cell'> - <div className='meta center'> - <div className='img'> - <Link to={"/media/" + data.id + "/edit/"}> - <img src={thumbnailURL(data)} alt={data.title} /> - </Link> - </div> - <Link to={"/media/" + data.id + "/edit/"}> - <div> - <i>{data.title}</i><br /> - {data.author}<br /> - {data.date} - </div> - </Link> - </div> - </div> - ) -} - -const FileItem = ({ data }) => { - // console.log(data) - return ( - <div className='cell'> - <div className='meta center'> - <Link to={"/media/" + data.id + "/edit/"}> - <div> - <i>{data.title}</i><br /> - {data.settings.file.url}<br /> - </div> - </Link> - </div> - </div> - ) -} - - -const mapStateToProps = state => ({ - media: state.media, -}) - -const mapDispatchToProps = dispatch => ({ - // uploadActions: bindActionCreators({ ...uploadActions }, dispatch), -}) - -export default connect(mapStateToProps, mapDispatchToProps)(MediaIndex) diff --git a/animism-align/frontend/app/views/media/containers/media.new.js b/animism-align/frontend/app/views/media/containers/media.new.js deleted file mode 100644 index c193c2f..0000000 --- a/animism-align/frontend/app/views/media/containers/media.new.js +++ /dev/null @@ -1,81 +0,0 @@ -import React, { Component } from 'react' -import { Link } from 'react-router-dom' -import { connect } from 'react-redux' - -import { history } from 'app/store' -import actions from 'app/actions' - -import MediaForm from '../components/media.form' -import MediaMenu from '../components/media.menu' - -class MediaNew extends Component { - state = { - loading: true, - initialData: {}, - } - - componentDidMount() { - // console.log(this.props.match.params.id) - if (this.props.match.params && this.props.match.params.id) { - actions.media.show(this.props.match.params.id) - .then(data => { - const { id, ...initialData } = data.res - delete initialData.settings.video - delete initialData.settings.crop - delete initialData.settings.display - delete initialData.settings.fullsize - delete initialData.settings.thumbnail - delete initialData.settings.bibliography - console.log("copying", id) - this.setState({ - loading: false, - initialData, - }) - }) - } else { - this.setState({ loading: false }) - } - } - - handleSubmit(data) { - console.log(data) - actions.media.create(data) - .then(res => { - console.log(res) - if (res.res && res.res.id) { - history.push('/media/') - } - }) - .catch(err => { - console.error('error') - }) - } - - render() { - if (this.state.loading) { - return ( - <div className='row formContainer' /> - ) - } - return ( - <div className='row formContainer'> - <MediaMenu /> - <MediaForm - isNew - data={this.state.initialData} - onSubmit={this.handleSubmit.bind(this)} - /> - </div> - ) - } -} - -const mapStateToProps = state => ({ - media: state.media, -}) - -const mapDispatchToProps = dispatch => ({ - // uploadActions: bindActionCreators({ ...uploadActions }, dispatch), -}) - -export default connect(mapStateToProps, mapDispatchToProps)(MediaNew) diff --git a/animism-align/frontend/app/views/media/media.actions.js b/animism-align/frontend/app/views/media/media.actions.js deleted file mode 100644 index 9919e46..0000000 --- a/animism-align/frontend/app/views/media/media.actions.js +++ /dev/null @@ -1,9 +0,0 @@ -import * as types from 'app/types' -import { api } from 'app/utils' - -export const getVimeoMetadata = url => { - return api(() => {}, types.vimeo, 'vimeo', 'https://vimeo.com/api/oembed.json', { url }) - .then(data => { - return data - }) -} diff --git a/animism-align/frontend/app/views/media/media.container.js b/animism-align/frontend/app/views/media/media.container.js deleted file mode 100644 index b597a6c..0000000 --- a/animism-align/frontend/app/views/media/media.container.js +++ /dev/null @@ -1,38 +0,0 @@ -import React, { Component } from 'react' -import { Route, Link } from 'react-router-dom' -import { bindActionCreators } from 'redux' -import { connect } from 'react-redux' - -import './media.css' - -import actions from 'app/actions' - -import MediaIndex from './containers/media.index' -// import MediaShow from './containers/media.show' -import MediaNew from './containers/media.new' -import MediaEdit from './containers/media.edit' - -class Container extends Component { - render() { - return ( - <div className='media'> - <Route exact path='/media/:id/copy/' component={MediaNew} /> - <Route exact path='/media/:id/edit/' component={MediaEdit} /> - <Route exact path='/media/new/' component={MediaNew} /> - <Route exact path='/media/' component={MediaIndex} /> - </div> - ) - } -} -/* - <Route exact path='/media/:id/show/' component={MediaShow} /> -*/ -const mapStateToProps = state => ({ - media: state.media, -}) - -const mapDispatchToProps = dispatch => ({ - // uploadActions: bindActionCreators({ ...uploadActions }, dispatch), -}) - -export default connect(mapStateToProps, mapDispatchToProps)(Container) diff --git a/animism-align/frontend/app/views/media/media.css b/animism-align/frontend/app/views/media/media.css deleted file mode 100644 index ebf8c33..0000000 --- a/animism-align/frontend/app/views/media/media.css +++ /dev/null @@ -1,110 +0,0 @@ -.app > .media { - width: 100%; - height: calc(100% - 3.125rem); - overflow: scroll; -} - -.results .cell { - margin-bottom: 1rem; - margin-right: 1rem; - max-width: 295px; -} -.results h2 { - display: block; - width: 100%; -} -.media .results .meta > div { - max-width: 100%; -} -.media .results .img img { - max-width: 295px; -} - -/* new / edit media forms */ - -.formContainer { - padding-top: 1rem; -} - -.imageForm, -.videoForm { - padding: 1rem 1rem 0.5rem 1rem; - margin: 1rem 0; - position: relative; - left: -1rem; - border-radius: 10px; -} - -/* image form */ - -.imageForm { - background: #315; -} -.imageForm .fileInput .row { - position: relative; -} - -/* video form */ - -.videoForm { - background: #314; -} -.videoForm .thumbnail img { - max-height: 200px; -} -.videoForm iframe { - pointer-events: auto; -} - -/* image crop */ - -.imageSelection { - width: 30rem; - position: relative; -} -.imageSelection img { - display: block; - max-width: 100%; -} -.imageSelection img.loading { - opacity: 0.5; -} -.imageSelection .box { - position: absolute; - 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; -} diff --git a/animism-align/frontend/app/views/media/media.reducer.js b/animism-align/frontend/app/views/media/media.reducer.js deleted file mode 100644 index f13f9de..0000000 --- a/animism-align/frontend/app/views/media/media.reducer.js +++ /dev/null @@ -1,22 +0,0 @@ -import * as types from 'app/types' -import { session, getDefault, getDefaultInt } from 'app/session' - -import { crudState, crudReducer } from 'app/api/crud.reducer' - -const initialState = crudState('media', { - options: { - sort: 'author asc', - thumbnailSize: getDefault('upload.thumbnailSize', 'small'), - } -}) - -const reducer = crudReducer('media') - -export default function mediaReducer(state = initialState, action) { - // console.log(action.type, action) - state = reducer(state, action) - switch (action.type) { - default: - return state - } -} |
