mirror of
https://github.com/strapi/strapi.git
synced 2025-10-27 16:10:08 +00:00
Design ImgPReview slider and remoive dynamic
This commit is contained in:
parent
aaff3e8f87
commit
010c3f8072
@ -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",
|
||||
|
||||
@ -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",
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
@ -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>
|
||||
);
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@ -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>
|
||||
);
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user