UNPKG

@bigfishtv/cockpit

Version:

221 lines (198 loc) 6.08 kB
import PropTypes from 'prop-types' import React, { Component } from 'react' import { connect } from 'react-redux' import { createValue } from '@bigfishtv/react-forms' import { modalHandler } from '../modal/ModalHost' import { addFile, getUploader } from '../../api/tankUpload' import { openImageEditModal } from '../../utils/imageEditUtils' import FileDropzone from '../container/FileDropzone' import AssetAutoCell from '../asset/AssetAutoCell' import AssetEditModal from '../asset/AssetEditModal' import MediaPreviewModal from '../asset/MediaPreviewModal' import AssetSelectControls from '../asset/AssetSelectControls' import ReorderableAssetCell from '../asset/ReorderableAssetCell' import { AssetCellStandard } from '../asset/AssetCell' // we define this because react-docgen fails when defaultProp directly references an imported component const DefaultAssetSelectControls = props => <AssetSelectControls {...props} /> @connect(({ defaultAssetFolder, fileTypes }) => ({ defaultAssetFolder, fileTypes })) export default class AssetDropzoneInput extends Component { static propTypes = { onChange: PropTypes.func, onRemove: PropTypes.func, cellSize: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), } static defaultProps = { type: 'image', dropzoneSize: 'small', assetSize: 'cockpit-150', multiple: false, extensions: [], reorderable: true, // only applicable if multiple = true AssetSelectControls: DefaultAssetSelectControls, assetFolderId: null, readOnly: false, } constructor(props) { super(props) const extensions = props.extensions && props.extensions.length ? props.extensions : props.type in props.fileTypes ? props.fileTypes[props.type].join(', ') : '*' this.fileProps = { subject: props.type, multiple: props.multiple, extensions, } this.onEdit = props.onEdit || this.handleEdit this.onDetails = props.onDetails || this.handleDetailsEdit this.onPlay = props.onPlay || this.handlePlay this.onMove = props.onMove || this.handleMove } componentDidMount() { if (getUploader()) getUploader().bind('FileUploaded', this.handleFileUploaded, this) } componentWillUnmount() { if (getUploader()) getUploader().unbind('FileUploaded', this.handleFileUploaded) } handleEdit = asset => { openImageEditModal(asset, this.handleAssetUpdate) } handleDetailsEdit = asset => { modalHandler.add({ Component: AssetEditModal, props: { formValue: createValue({ schema: null, value: { asset }, }), onSave: formValue => this.handleAssetUpdate(formValue.select('asset').value, asset), onClose: () => {}, }, }) } handlePlay = asset => { modalHandler.add({ Component: MediaPreviewModal, props: { asset, onClose: () => {}, }, }) } handleAssetUpdate = (asset, previousAsset) => { let { value, multiple } = this.props if (multiple) { value = value.map(file => (file.id === previousAsset.id ? asset : file)) } else { value = asset } this.props.onChange(value) } // triggered upon global file upload handleFileUploaded = (uploader, file, response) => { const { value, multiple, onChange } = this.props if (response.status !== 200 || !value) return if (multiple) { const ids = (value || []).map(asset => asset.id) if (ids.indexOf(file.id) !== -1) { const newValue = (value || []).map(asset => (asset.id === file.id ? JSON.parse(response.response) : asset)) onChange(newValue) } } else { if (value && value.id === file.id) { onChange(JSON.parse(response.response)) } } } // called by browse button handleReceivedFiles = files => { const { value, multiple, onChange, defaultAssetFolder, assetFolderId } = this.props const newFiles = files.map(file => ({ id: addFile(file, defaultAssetFolder ? defaultAssetFolder.id : assetFolderId), })) onChange(multiple ? [...(value || []), ...newFiles] : newFiles[0]) } // called when media is selected from modal handleSelectedFiles = files => { const { value, multiple, onChange } = this.props onChange(multiple ? [...(value || []), ...files] : files[0]) } handleRemove(asset, i) { if (this.props.multiple) { this.props.onChange((this.props.value || []).filter(child => child !== asset)) } else { this.props.onChange(null) } } handleMove = (id, afterId) => { let Cells = this.props.value.slice() const cell = Cells.filter(c => c.id === id)[0] const afterCell = Cells.filter(c => c.id === afterId)[0] const cellIndex = Cells.indexOf(cell) const afterIndex = Cells.indexOf(afterCell) Cells.splice(cellIndex, 1) Cells.splice(afterIndex, 0, cell) this.props.onChange(Cells) } render() { const { value, text, multiple, dropzoneSize, assetSize, cellSize, onEdit, onRemove, AssetSelectControls, AssetCell, assetFolderId, ...rest } = this.props const assets = value ? (multiple ? value : [value]) : [] const _AssetCell = AssetCell || (multiple ? ReorderableAssetCell : undefined) if (this.props.readOnly) { return ( <div> {assets.map((asset, i) => { return <AssetCellStandard key={i} asset={asset} Toolbar={null} /> })} </div> ) } return ( <FileDropzone {...this.fileProps} files={assets} onReceivedFiles={this.handleReceivedFiles}> <div> {assets.length > 0 && assets.map((asset, i) => ( <AssetAutoCell key={i} size={assetSize} cellSize={cellSize} asset={asset} onRemove={() => (onRemove ? onRemove(i, asset) : this.handleRemove(asset, i))} onEdit={this.onEdit} onMove={this.onMove} onDetails={this.onDetails} onPlay={this.onPlay} {...rest} AssetCell={_AssetCell} /> ))} </div> {(multiple || !assets.length) && ( <AssetSelectControls {...rest} {...this.fileProps} size={dropzoneSize} files={assets} onReceivedFiles={this.handleReceivedFiles} onFilesSelected={this.handleSelectedFiles} /> )} </FileDropzone> ) } }