Skip to content

Commit

Permalink
use media library for file and image widgets
Browse files Browse the repository at this point in the history
  • Loading branch information
erquhart committed Sep 18, 2017
1 parent 4b50eb6 commit 59d8702
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 171 deletions.
2 changes: 1 addition & 1 deletion src/components/MediaLibrary/MediaLibrary.js
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ class MediaLibrary extends React.Component {
const { files: fileList } = event.dataTransfer || event.target;
const files = [...fileList];
const file = files[0];
return createAssetProxy(file.name, file)
return createAssetProxy(file.name, file, false, this.props.field.get('private', false))
.then(assetProxy => {
dispatch(addAsset(assetProxy));
return dispatch(persistMedia([assetProxy]));
Expand Down
6 changes: 1 addition & 5 deletions src/components/Widgets/FileControl.css
Original file line number Diff line number Diff line change
@@ -1,16 +1,12 @@
@import "../UI/theme.css";

.input {
display: none !important;
}

.message {
padding: 20px;
display: block;
font-size: 12px;
}

.imageUpload {
.wrapper {
background-color: #fff;
text-align: center;
color: #999;
Expand Down
119 changes: 40 additions & 79 deletions src/components/Widgets/FileControl.js
Original file line number Diff line number Diff line change
@@ -1,116 +1,77 @@
import PropTypes from 'prop-types';
import React from 'react';
import ImmutablePropTypes from "react-immutable-proptypes";
import { get } from 'lodash';
import uuid from 'uuid';
import { truncateMiddle } from '../../lib/textHelper';
import { Loader } from '../UI';
import AssetProxy, { createAssetProxy } from '../../valueObjects/AssetProxy';
import styles from './FileControl.css';

const MAX_DISPLAY_LENGTH = 50;

export default class FileControl extends React.Component {
state = {
processing: false,
};
constructor(props) {
super(props);
this.controlID = uuid.v4();
}

promise = null;

isValid = () => {
if (this.promise) {
return this.promise;
shouldComponentUpdate(nextProps) {
/**
* Always update if the value changes.
*/
if (this.props.value !== nextProps.value) {
return true;
}
return { error: false };
};


handleFileInputRef = (el) => {
this._fileInput = el;
};

handleClick = (e) => {
this._fileInput.click();
};

handleDragEnter = (e) => {
e.stopPropagation();
e.preventDefault();
};

handleDragOver = (e) => {
e.stopPropagation();
e.preventDefault();
};

handleChange = (e) => {
e.stopPropagation();
e.preventDefault();

const fileList = e.dataTransfer ? e.dataTransfer.files : e.target.files;
const files = [...fileList];
const imageType = /^image\//;
/**
* If there is a media path for this control in the state object, and that
* path is different than the value in `nextProps`, update.
*/
const mediaPath = nextProps.mediaPaths.get(this.controlID);
if (mediaPath && (nextProps.value !== mediaPath)) {
return true;
}

// Return the first file on the list
const file = files[0];
return false;
}

this.props.onRemoveAsset(this.props.value);
if (file) {
this.setState({ processing: true });
this.promise = createAssetProxy(file.name, file, false, this.props.field.get('private', false))
.then((assetProxy) => {
this.setState({ processing: false });
this.props.onAddAsset(assetProxy);
this.props.onChange(assetProxy.public_path);
});
} else {
this.props.onChange(null);
componentWillReceiveProps(nextProps) {
const { mediaPaths, value } = nextProps;
const mediaPath = mediaPaths.get(this.controlID);
if (mediaPath && mediaPath !== value) {
this.props.onChange(mediaPath);
}
}

handleClick = (e) => {
const { field, onOpenMediaLibrary } = this.props;
return onOpenMediaLibrary({ controlID: this.controlID });
};

renderFileName = () => {
if (!this.props.value) return null;
if (this.value instanceof AssetProxy) {
return truncateMiddle(this.props.value.path, MAX_DISPLAY_LENGTH);
} else {
return truncateMiddle(this.props.value, MAX_DISPLAY_LENGTH);
}
const { value } = this.props;
return value ? truncateMiddle(value, MAX_DISPLAY_LENGTH) : null;
};

render() {
const { processing } = this.state;
const fileName = this.renderFileName();
if (processing) {
return (
<div className={styles.imageUpload}>
<span className={styles.message}>
<Loader active />
</span>
</div>
);
}
return (
<div
className={styles.imageUpload}
onDragEnter={this.handleDragEnter}
onDragOver={this.handleDragOver}
onDrop={this.handleChange}
>
<div className={styles.wrapper}>
<span className={styles.message} onClick={this.handleClick}>
{fileName ? fileName : 'Click here to upload a file from your computer, or drag and drop a file directly into this box'}
{fileName ? fileName : 'Click here to select an asset from the asset library'}
</span>
<input
type="file"
onChange={this.handleChange}
className={styles.input}
ref={this.handleFileInputRef}
/>
</div>
);
}
}

FileControl.propTypes = {
field: PropTypes.object.isRequired,
mediaPaths: ImmutablePropTypes.map.isRequired,
onAddAsset: PropTypes.func.isRequired,
onChange: PropTypes.func.isRequired,
onRemoveAsset: PropTypes.func.isRequired,
onOpenMediaLibrary: PropTypes.func.isRequired,
value: PropTypes.node,
field: PropTypes.object,
};
125 changes: 40 additions & 85 deletions src/components/Widgets/ImageControl.js
Original file line number Diff line number Diff line change
@@ -1,120 +1,75 @@
import PropTypes from 'prop-types';
import React from 'react';
import ImmutablePropTypes from "react-immutable-proptypes";
import uuid from 'uuid';
import { truncateMiddle } from '../../lib/textHelper';
import { Loader } from '../UI';
import AssetProxy, { createAssetProxy } from '../../valueObjects/AssetProxy';
import styles from './FileControl.css';

const MAX_DISPLAY_LENGTH = 50;

export default class ImageControl extends React.Component {
state = {
processing: false,
};
constructor(props) {
super(props);
this.controlID = uuid.v4();
}

promise = null;
shouldComponentUpdate(nextProps) {
/**
* Always update if the value changes.
*/
if (this.props.value !== nextProps.value) {
return true;
}

isValid = () => {
if (this.promise) {
return this.promise;
/**
* If there is a media path for this control in the state object, and that
* path is different than the value in `nextProps`, update.
*/
const mediaPath = nextProps.mediaPaths.get(this.controlID);
if (mediaPath && (nextProps.value !== mediaPath)) {
return true;
}
return { error: false };
};

return false;
}

handleFileInputRef = (el) => {
this._fileInput = el;
};
componentWillReceiveProps(nextProps) {
const { mediaPaths, value } = nextProps;
const mediaPath = mediaPaths.get(this.controlID);
if (mediaPath && mediaPath !== value) {
this.props.onChange(mediaPath);
}
}

handleClick = (e) => {
this._fileInput.click();
};

handleDragEnter = (e) => {
e.stopPropagation();
e.preventDefault();
const { field, onOpenMediaLibrary } = this.props;
return onOpenMediaLibrary({ controlID: this.controlID, forImage: true });
};

handleDragOver = (e) => {
e.stopPropagation();
e.preventDefault();
};

handleChange = (e) => {
e.stopPropagation();
e.preventDefault();

const fileList = e.dataTransfer ? e.dataTransfer.files : e.target.files;
const files = [...fileList];
const imageType = /^image\//;

// Iterate through the list of files and return the first image on the list
const file = files.find((currentFile) => {
if (imageType.test(currentFile.type)) {
return currentFile;
}
});

this.props.onRemoveAsset(this.props.value);
if (file) {
this.setState({ processing: true });
this.promise = createAssetProxy(file.name, file)
.then((assetProxy) => {
this.setState({ processing: false });
this.props.onAddAsset(assetProxy);
this.props.onChange(assetProxy.public_path);
});
} else {
this.props.onChange(null);
}
};

renderImageName = () => {
if (!this.props.value) return null;
if (this.value instanceof AssetProxy) {
return truncateMiddle(this.props.value.path, MAX_DISPLAY_LENGTH);
} else {
return truncateMiddle(this.props.value, MAX_DISPLAY_LENGTH);
}
renderFileName = () => {
const { value } = this.props;
return value ? truncateMiddle(value, MAX_DISPLAY_LENGTH) : null;
};

render() {
const { processing } = this.state;
const imageName = this.renderImageName();
if (processing) {
return (
<div className={styles.imageUpload}>
<span className={styles.message}>
<Loader active />
</span>
</div>
);
}
const fileName = this.renderFileName();
return (
<div
className={styles.imageUpload}
onDragEnter={this.handleDragEnter}
onDragOver={this.handleDragOver}
onDrop={this.handleChange}
>
<div className={styles.wrapper}>
<span className={styles.message} onClick={this.handleClick}>
{imageName ? imageName : 'Click here to upload an image from your computer, or drag and drop a file directly into this box'}
{fileName ? fileName : 'Click here to select an image from the image library'}
</span>
<input
type="file"
accept="image/*"
onChange={this.handleChange}
className={styles.input}
ref={this.handleFileInputRef}
/>
</div>
);
}
}

ImageControl.propTypes = {
field: PropTypes.object.isRequired,
mediaPaths: ImmutablePropTypes.map.isRequired,
onAddAsset: PropTypes.func.isRequired,
onChange: PropTypes.func.isRequired,
onRemoveAsset: PropTypes.func.isRequired,
onOpenMediaLibrary: PropTypes.func.isRequired,
value: PropTypes.node,
};
1 change: 0 additions & 1 deletion src/components/Widgets/MediaControl.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import React, { PropTypes } from 'react';
import ImmutablePropTypes from "react-immutable-proptypes";
import uuid from 'uuid';
import { truncateMiddle } from '../../lib/textHelper';
import AssetProxy from '../../valueObjects/AssetProxy';
import styles from './FileControl.css';

const MAX_DISPLAY_LENGTH = 50;
Expand Down

0 comments on commit 59d8702

Please sign in to comment.