Design ImgPReview slider and remoive dynamic

This commit is contained in:
cyril lopez 2018-02-12 15:12:58 +01:00
parent aaff3e8f87
commit 010c3f8072
7 changed files with 203 additions and 29 deletions

View File

@ -11,6 +11,8 @@
"app.components.HomePage.button": "Create your first content type",
"app.components.HomePage.feedback": "Feel free to ask questions or give us feedback by using one of the support channels below.",
"app.components.InputFile.newFile": "ADD NEW FILE",
"app.components.InstallPluginPage.helmet": "Install plugins",
"app.components.InstallPluginPage.title": "Install new plugins",
"app.components.InstallPluginPage.description": "Extend your app with no efforts",

View File

@ -11,6 +11,8 @@
"app.components.HomePage.button": "Créez votre premier type de contenu",
"app.components.HomePage.feedback": "N'hésitez pas à utiliser un des channels ci-dessous pour poser vos questions ou nous donner vos retours.",
"app.components.InputFile.newFile": "AJOUTER UN NOUVEAU FICHIER",
"app.components.InstallPluginPage.helmet": "Installez des plugins",
"app.components.InstallPluginPage.title": "Installez des nouveaux plugins",
"app.components.InstallPluginPage.description": "Améliorez votre app sans efforts",

View File

@ -7,7 +7,7 @@
import React from 'react';
import PropTypes from 'prop-types';
import { get, isEmpty, isObject } from 'lodash';
import { cloneDeep, get, isEmpty, isObject, size } from 'lodash';
import cn from 'classnames';
import styles from './styles.scss';
@ -16,8 +16,10 @@ class ImgPreview extends React.Component {
state = { imgURL: '', position: 0 };
componentDidMount() {
// We don't need the generateImgURL function here since the compo will
// always have an init value here
this.setState({
imgURL: get(this.props.files, ['0', 'url']),
imgURL: get(this.props.files, ['0', 'url'], ''),
});
}
@ -46,18 +48,18 @@ class ImgPreview extends React.Component {
reader.readAsDataURL(file);
}
handleClick = (operator) => {
handleClick = (type) => {
const { position } = this.state;
const { files } = this.props;
let file;
let nextPosition;
switch (operator) {
case '+':
switch (type) {
case 'right':
file = files[position + 1] || files[0];
nextPosition = files[position + 1] ? position + 1 : 0;
break;
case '-':
case 'left':
file = files[position - 1] || files[files.length - 1];
nextPosition = files[position - 1] ? position - 1 : files.length - 1;
break;
@ -74,16 +76,67 @@ class ImgPreview extends React.Component {
this.setState({ position: nextPosition });
}
removeFile = (e) => {
e.preventDefault();
e.stopPropagation();
const value = cloneDeep(this.props.files);
value.splice(this.state.position, 1);
const nextPosition = this.state.position - 1 === -1 ? 0 : this.state.position - 1;
const nextFile = value[nextPosition];
if (!isEmpty(nextFile)) {
if (!nextFile.url) {
this.generateImgURL(nextFile);
} else {
this.setState({ imgURL: nextFile.url });
}
} else {
this.setState({ imgURL: '' });
}
const target = {
name: this.props.name,
type: 'file',
value,
};
this.setState({ position: nextPosition });
this.props.onChange({ target });
}
renderArrow = (type = 'left') => (
<div
className={cn(
styles.arrowContainer,
type === 'left' && styles.arrowLeft,
type !== 'left' && styles.arrowRight,
)}
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
this.handleClick(type);
}}
/>
)
renderIconRemove = () => (
<div className={styles.iconContainer} onClick={this.removeFile}>
<i className="fa fa-times" />
</div>
)
render() {
const { files, multiple } = this.props;
return (
<div>
<div className={styles.imgPreviewContainer}>
{!isEmpty(files) && this.renderIconRemove()}
<img src={this.state.imgURL} />
<button className="btn btn-primary" onClick={() => this.handleClick('+')}>
+
</button>
<button className="btn btn-primary" onClick={() => this.handleClick('-')}>
-
</button>
{ multiple && size(files) > 1 && this.renderArrow('right')}
{ multiple && size(files) > 1 && this.renderArrow('left')}
</div>
);
}
@ -92,11 +145,17 @@ class ImgPreview extends React.Component {
ImgPreview.defaultProps = {
files: [{}],
isUploading: false,
multiple: false,
name: '',
onChange: () => {},
};
ImgPreview.propTypes = {
files: PropTypes.array,
isUploading: PropTypes.bool,
multiple: PropTypes.bool,
name: PropTypes.string,
onChange: PropTypes.func,
};
export default ImgPreview;

View File

@ -0,0 +1,67 @@
.imgPreviewContainer {
display: table-cell;
height: 144px;
width: 358px;
position: relative;
border-top-left-radius: 2px;
border-top-right-radius: 2px;
text-align: center;
vertical-align: middle;
// background-color: red;
background-color: #F3F4F4;
white-space: nowrap;
> img {
max-width: 358px;
max-height: 144px;
}
}
.iconContainer {
position: absolute;
top: 5px;
right: 3px;
width: 20px;
height: 20px;
color: #fff;
font-size: 11px;
cursor: pointer;
}
.arrowContainer {
height: 32px;
width: 28px;
background: rgba(0,0,0,0.20);
border-radius: 2px 0 0 2px;
text-align: center;
color: #fff;
cursor: pointer;
}
.arrowRight {
position: absolute;
top: 56px;
right: 0;
&:before {
content: '\f105';
vertical-align: middle;
text-align: center;
font-family: 'FontAwesome';
font-size: 20px;
font-weight: 800;
}
}
.arrowLeft {
position: absolute;
top: 56px;
left: 0;
&:before {
content: '\f104';
vertical-align: middle;
text-align: center;
font-family: 'FontAwesome';
font-size: 20px;
font-weight: 800;
}
}

View File

@ -7,6 +7,7 @@
import React from 'react';
import PropTypes from 'prop-types';
import { FormattedMessage } from 'react-intl';
import { cloneDeep, isArray, isObject, isEmpty, last } from 'lodash';
import cn from 'classnames';
@ -44,16 +45,28 @@ class InputFile extends React.Component {
return (
<div>
<ImgPreview
files={value}
isUploading={this.state.isUploading}
/>
<input
multiple={multiple}
name={name}
onChange={this.handleChange}
type="file"
/>
<label
>
<ImgPreview
files={value}
isUploading={this.state.isUploading}
multiple={multiple}
name={name}
onChange={onChange}
/>
<input
className={styles.inputFile}
multiple={multiple}
name={name}
onChange={this.handleChange}
type="file"
/>
<div className={styles.buttonContainer}>
<i className="fa fa-plus" />
<FormattedMessage id="app.components.InputFile.newFile" />
</div>
</label>
</div>
);
}

View File

@ -0,0 +1,29 @@
.inputFile {
opacity: 0;
overflow: hidden;
position: absolute;
z-index: -1;
}
.buttonContainer {
width: 100%;
height: 34px;
text-align: center;
background-color: #FAFAFB;
border: 1px solid #E3E9F3;
border-top: 0;
border-bottom-left-radius: 2px;
border-bottom-right-radius: 2px;
color: #333740;
font-size: 12px;
font-weight: 700;
-webkit-font-smoothing: antialiased;
line-height: 34px;
cursor: pointer;
> i {
margin-right: 10px;
}
}

View File

@ -33,12 +33,14 @@ export class HomePage extends React.Component {
render() {
return (
<div className={styles.homePage}>
<InputFile
name="test"
value={this.state.value}
onChange={this.onChange}
/>
<div className={styles.homePage} style={{ paddingTop: '100px', marginLeft: '100px'}}>
<form>
<InputFile
name="test"
value={this.state.value}
onChange={this.onChange}
/>
</form>
</div>
);
}