mirror of
				https://github.com/strapi/strapi.git
				synced 2025-10-31 09:56:44 +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.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.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.helmet": "Install plugins", | ||||||
|   "app.components.InstallPluginPage.title": "Install new plugins", |   "app.components.InstallPluginPage.title": "Install new plugins", | ||||||
|   "app.components.InstallPluginPage.description": "Extend your app with no efforts", |   "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.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.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.helmet": "Installez des plugins", | ||||||
|   "app.components.InstallPluginPage.title": "Installez des nouveaux plugins", |   "app.components.InstallPluginPage.title": "Installez des nouveaux plugins", | ||||||
|   "app.components.InstallPluginPage.description": "Améliorez votre app sans efforts", |   "app.components.InstallPluginPage.description": "Améliorez votre app sans efforts", | ||||||
|  | |||||||
| @ -7,7 +7,7 @@ | |||||||
| 
 | 
 | ||||||
| import React from 'react'; | import React from 'react'; | ||||||
| import PropTypes from 'prop-types'; | import PropTypes from 'prop-types'; | ||||||
| import { get, isEmpty, isObject } from 'lodash'; | import { cloneDeep, get, isEmpty, isObject, size } from 'lodash'; | ||||||
| import cn from 'classnames'; | import cn from 'classnames'; | ||||||
| 
 | 
 | ||||||
| import styles from './styles.scss'; | import styles from './styles.scss'; | ||||||
| @ -16,8 +16,10 @@ class ImgPreview extends React.Component { | |||||||
|   state = { imgURL: '', position: 0 }; |   state = { imgURL: '', position: 0 }; | ||||||
| 
 | 
 | ||||||
|   componentDidMount() { |   componentDidMount() { | ||||||
|  |     // We don't need the generateImgURL function here since the compo will
 | ||||||
|  |     // always have an init value here
 | ||||||
|     this.setState({ |     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); |     reader.readAsDataURL(file); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   handleClick = (operator) => { |   handleClick = (type) => { | ||||||
|     const { position } = this.state; |     const { position } = this.state; | ||||||
|     const { files } = this.props; |     const { files } = this.props; | ||||||
|     let file; |     let file; | ||||||
|     let nextPosition; |     let nextPosition; | ||||||
| 
 | 
 | ||||||
|     switch (operator) { |     switch (type) { | ||||||
|       case '+': |       case 'right': | ||||||
|         file = files[position + 1] || files[0]; |         file = files[position + 1] || files[0]; | ||||||
|         nextPosition = files[position + 1] ? position + 1 : 0; |         nextPosition = files[position + 1] ? position + 1 : 0; | ||||||
|         break; |         break; | ||||||
|       case '-': |       case 'left': | ||||||
|         file = files[position - 1] || files[files.length - 1]; |         file = files[position - 1] || files[files.length - 1]; | ||||||
|         nextPosition = files[position - 1] ? position - 1 : files.length - 1; |         nextPosition = files[position - 1] ? position - 1 : files.length - 1; | ||||||
|         break; |         break; | ||||||
| @ -74,16 +76,67 @@ class ImgPreview extends React.Component { | |||||||
|     this.setState({ position: nextPosition }); |     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() { |   render() { | ||||||
|  |     const { files, multiple } = this.props; | ||||||
|  | 
 | ||||||
|     return ( |     return ( | ||||||
|       <div> |       <div className={styles.imgPreviewContainer}> | ||||||
|  |         {!isEmpty(files) && this.renderIconRemove()} | ||||||
|         <img src={this.state.imgURL} /> |         <img src={this.state.imgURL} /> | ||||||
|         <button className="btn btn-primary" onClick={() => this.handleClick('+')}> |         { multiple && size(files) > 1 && this.renderArrow('right')} | ||||||
|           + |         { multiple && size(files) > 1 && this.renderArrow('left')} | ||||||
|         </button> |  | ||||||
|         <button className="btn btn-primary" onClick={() => this.handleClick('-')}> |  | ||||||
|           - |  | ||||||
|         </button> |  | ||||||
|       </div> |       </div> | ||||||
|     ); |     ); | ||||||
|   } |   } | ||||||
| @ -92,11 +145,17 @@ class ImgPreview extends React.Component { | |||||||
| ImgPreview.defaultProps = { | ImgPreview.defaultProps = { | ||||||
|   files: [{}], |   files: [{}], | ||||||
|   isUploading: false, |   isUploading: false, | ||||||
|  |   multiple: false, | ||||||
|  |   name: '', | ||||||
|  |   onChange: () => {}, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| ImgPreview.propTypes = { | ImgPreview.propTypes = { | ||||||
|   files: PropTypes.array, |   files: PropTypes.array, | ||||||
|   isUploading: PropTypes.bool, |   isUploading: PropTypes.bool, | ||||||
|  |   multiple: PropTypes.bool, | ||||||
|  |   name: PropTypes.string, | ||||||
|  |   onChange: PropTypes.func, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| export default ImgPreview; | 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 React from 'react'; | ||||||
| import PropTypes from 'prop-types'; | import PropTypes from 'prop-types'; | ||||||
|  | import { FormattedMessage } from 'react-intl'; | ||||||
| import { cloneDeep, isArray, isObject, isEmpty, last } from 'lodash'; | import { cloneDeep, isArray, isObject, isEmpty, last } from 'lodash'; | ||||||
| import cn from 'classnames'; | import cn from 'classnames'; | ||||||
| 
 | 
 | ||||||
| @ -44,16 +45,28 @@ class InputFile extends React.Component { | |||||||
| 
 | 
 | ||||||
|     return ( |     return ( | ||||||
|       <div> |       <div> | ||||||
|  |         <label | ||||||
|  |         > | ||||||
|           <ImgPreview |           <ImgPreview | ||||||
|             files={value} |             files={value} | ||||||
|             isUploading={this.state.isUploading} |             isUploading={this.state.isUploading} | ||||||
|  |             multiple={multiple} | ||||||
|  |             name={name} | ||||||
|  |             onChange={onChange} | ||||||
|           /> |           /> | ||||||
|           <input |           <input | ||||||
|  |             className={styles.inputFile} | ||||||
|             multiple={multiple} |             multiple={multiple} | ||||||
|             name={name} |             name={name} | ||||||
|             onChange={this.handleChange} |             onChange={this.handleChange} | ||||||
|             type="file" |             type="file" | ||||||
|           /> |           /> | ||||||
|  | 
 | ||||||
|  |           <div className={styles.buttonContainer}> | ||||||
|  |             <i className="fa fa-plus" /> | ||||||
|  |             <FormattedMessage id="app.components.InputFile.newFile" /> | ||||||
|  |           </div> | ||||||
|  |         </label> | ||||||
|       </div> |       </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() { |   render() { | ||||||
|     return ( |     return ( | ||||||
|       <div className={styles.homePage}> |       <div className={styles.homePage} style={{ paddingTop: '100px', marginLeft: '100px'}}> | ||||||
|  |         <form> | ||||||
|           <InputFile |           <InputFile | ||||||
|             name="test" |             name="test" | ||||||
|             value={this.state.value} |             value={this.state.value} | ||||||
|             onChange={this.onChange} |             onChange={this.onChange} | ||||||
|             /> |             /> | ||||||
|  |         </form> | ||||||
|       </div> |       </div> | ||||||
|     ); |     ); | ||||||
|   } |   } | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 cyril lopez
						cyril lopez