summaryrefslogtreecommitdiff
path: root/animism-align/frontend/app/views/media
diff options
context:
space:
mode:
authorJules Laplace <julescarbon@gmail.com>2021-03-08 22:11:55 +0100
committerJules Laplace <julescarbon@gmail.com>2021-03-08 22:11:55 +0100
commitd2cb17038b8537a609be06be2ed7013dbe27117e (patch)
tree028ceac9edddafc03ce80c49d5a05981bec3fcbe /animism-align/frontend/app/views/media
parentb5ceb782f40fc1e402d1e58bc1ced2e4038fd787 (diff)
beginning the BIG refactor. moving editor stuff into per-episode hierarchy
Diffstat (limited to 'animism-align/frontend/app/views/media')
-rw-r--r--animism-align/frontend/app/views/media/components/media.form.js287
-rw-r--r--animism-align/frontend/app/views/media/components/media.formFile.js67
-rw-r--r--animism-align/frontend/app/views/media/components/media.formGallery.js338
-rw-r--r--animism-align/frontend/app/views/media/components/media.formGalleryImage.js129
-rw-r--r--animism-align/frontend/app/views/media/components/media.formImage.js169
-rw-r--r--animism-align/frontend/app/views/media/components/media.formImageSelection.js213
-rw-r--r--animism-align/frontend/app/views/media/components/media.formVideo.js118
-rw-r--r--animism-align/frontend/app/views/media/components/media.indexOptions.js59
-rw-r--r--animism-align/frontend/app/views/media/components/media.menu.js58
-rw-r--r--animism-align/frontend/app/views/media/containers/media.edit.js57
-rw-r--r--animism-align/frontend/app/views/media/containers/media.index.js160
-rw-r--r--animism-align/frontend/app/views/media/containers/media.new.js81
-rw-r--r--animism-align/frontend/app/views/media/media.actions.js9
-rw-r--r--animism-align/frontend/app/views/media/media.container.js38
-rw-r--r--animism-align/frontend/app/views/media/media.css110
-rw-r--r--animism-align/frontend/app/views/media/media.reducer.js22
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
- }
-}