summaryrefslogtreecommitdiff
path: root/animism-align/frontend/app/views/media/components
diff options
context:
space:
mode:
Diffstat (limited to 'animism-align/frontend/app/views/media/components')
-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
9 files changed, 0 insertions, 1438 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/')
- })
- }
- }} />,
-]))