11import PropTypes from 'prop-types' ;
22import classNames from 'classnames' ;
33import React , { useState , useRef } from 'react' ;
4- import { connect , useDispatch } from 'react-redux' ;
4+ import { useDispatch , useSelector } from 'react-redux' ;
55import { useTranslation } from 'react-i18next' ;
66
77import * as IDEActions from '../actions/ide' ;
88import * as FileActions from '../actions/files' ;
9+ import parseFileName from '../utils/parseFileName' ;
910import DownArrowIcon from '../../../images/down-filled-triangle.svg' ;
1011import FolderRightIcon from '../../../images/triangle-arrow-right.svg' ;
1112import FolderDownIcon from '../../../images/triangle-arrow-down.svg' ;
1213import FileTypeIcon from './FileTypeIcon' ;
1314
14- function parseFileName ( name ) {
15- const nameArray = name . split ( '.' ) ;
16- if ( nameArray . length > 1 ) {
17- const extension = `.${ nameArray [ nameArray . length - 1 ] } ` ;
18- const baseName = nameArray . slice ( 0 , - 1 ) . join ( '.' ) ;
19- const firstLetter = baseName [ 0 ] ;
20- const lastLetter = baseName [ baseName . length - 1 ] ;
21- const middleText = baseName . slice ( 1 , - 1 ) ;
22- return {
23- baseName,
24- firstLetter,
25- lastLetter,
26- middleText,
27- extension
28- } ;
29- }
30- const firstLetter = name [ 0 ] ;
31- const lastLetter = name [ name . length - 1 ] ;
32- const middleText = name . slice ( 1 , - 1 ) ;
33- return {
34- baseName : name ,
35- firstLetter,
36- lastLetter,
37- middleText
38- } ;
39- }
40-
4115function FileName ( { name } ) {
4216 const {
4317 baseName,
@@ -62,41 +36,35 @@ FileName.propTypes = {
6236 name : PropTypes . string . isRequired
6337} ;
6438
65- const FileNode = ( {
66- id,
67- parentId,
68- children,
69- name,
70- fileType,
71- isSelectedFile,
72- isFolderClosed,
73- setSelectedFile,
74- deleteFile,
75- updateFileName,
76- resetSelectedFile,
77- newFile,
78- newFolder,
79- showFolderChildren,
80- hideFolderChildren,
81- canEdit,
82- openUploadFileModal,
83- authenticated,
84- onClickFile
85- } ) => {
39+ const FileNode = ( { id, canEdit, onClickFile } ) => {
40+ const dispatch = useDispatch ( ) ;
41+ const { t } = useTranslation ( ) ;
42+
43+ const fileNode =
44+ useSelector ( ( state ) => state . files . find ( ( file ) => file . id === id ) ) || { } ;
45+ const authenticated = useSelector ( ( state ) => state . user . authenticated ) ;
46+
47+ const {
48+ name = '' ,
49+ parentId = null ,
50+ children = [ ] ,
51+ fileType = 'file' ,
52+ isSelectedFile = false ,
53+ isFolderClosed = false
54+ } = fileNode ;
55+
8656 const [ isOptionsOpen , setIsOptionsOpen ] = useState ( false ) ;
8757 const [ isEditingName , setIsEditingName ] = useState ( false ) ;
8858 const [ isDeleting , setIsDeleting ] = useState ( false ) ;
8959 const [ updatedName , setUpdatedName ] = useState ( name ) ;
90- const dispatch = useDispatch ( ) ;
9160
92- const { t } = useTranslation ( ) ;
9361 const fileNameInput = useRef ( null ) ;
9462 const fileOptionsRef = useRef ( null ) ;
9563
9664 const handleFileClick = ( event ) => {
9765 event . stopPropagation ( ) ;
9866 if ( name !== 'root' && ! isDeleting ) {
99- setSelectedFile ( id ) ;
67+ dispatch ( IDEActions . setSelectedFile ( id ) ) ;
10068 }
10169 if ( onClickFile ) {
10270 onClickFile ( ) ;
@@ -123,17 +91,17 @@ const FileNode = ({
12391 } ;
12492
12593 const handleClickAddFile = ( ) => {
126- dispatch ( newFile ( id ) ) ;
94+ dispatch ( IDEActions . newFile ( id ) ) ;
12795 setTimeout ( ( ) => hideFileOptions ( ) , 0 ) ;
12896 } ;
12997
13098 const handleClickAddFolder = ( ) => {
131- dispatch ( newFolder ( id ) ) ;
99+ dispatch ( IDEActions . newFolder ( id ) ) ;
132100 setTimeout ( ( ) => hideFileOptions ( ) , 0 ) ;
133101 } ;
134102
135103 const handleClickUploadFile = ( ) => {
136- dispatch ( openUploadFileModal ( id ) ) ;
104+ dispatch ( IDEActions . openUploadFileModal ( id ) ) ;
137105 setTimeout ( hideFileOptions , 0 ) ;
138106 } ;
139107
@@ -142,8 +110,8 @@ const FileNode = ({
142110
143111 if ( window . confirm ( prompt ) ) {
144112 setIsDeleting ( true ) ;
145- resetSelectedFile ( id ) ;
146- setTimeout ( ( ) => deleteFile ( id , parentId ) , 100 ) ;
113+ dispatch ( IDEActions . resetSelectedFile ( id ) ) ;
114+ setTimeout ( ( ) => dispatch ( FileActions . deleteFile ( id , parentId ) , 100 ) ) ;
147115 }
148116 } ;
149117
@@ -159,7 +127,7 @@ const FileNode = ({
159127
160128 const saveUpdatedFileName = ( ) => {
161129 if ( updatedName !== name ) {
162- updateFileName ( id , updatedName ) ;
130+ dispatch ( FileActions . updateFileName ( id , updatedName ) ) ;
163131 }
164132 } ;
165133
@@ -244,7 +212,7 @@ const FileNode = ({
244212 < div className = "sidebar__file-item--folder" >
245213 < button
246214 className = "sidebar__file-item-closed"
247- onClick = { ( ) => showFolderChildren ( id ) }
215+ onClick = { ( ) => dispatch ( FileActions . showFolderChildren ( id ) ) }
248216 aria-label = { t ( 'FileNode.OpenFolderARIA' ) }
249217 title = { t ( 'FileNode.OpenFolderARIA' ) }
250218 >
@@ -256,7 +224,7 @@ const FileNode = ({
256224 </ button >
257225 < button
258226 className = "sidebar__file-item-open"
259- onClick = { ( ) => hideFolderChildren ( id ) }
227+ onClick = { ( ) => dispatch ( FileActions . hideFolderChildren ( id ) ) }
260228 aria-label = { t ( 'FileNode.CloseFolderARIA' ) }
261229 title = { t ( 'FileNode.CloseFolderARIA' ) }
262230 >
@@ -354,7 +322,7 @@ const FileNode = ({
354322 < ul className = "file-item__children" >
355323 { children . map ( ( childId ) => (
356324 < li key = { childId } >
357- < ConnectedFileNode
325+ < FileNode
358326 id = { childId }
359327 parentId = { id }
360328 canEdit = { canEdit }
@@ -370,50 +338,12 @@ const FileNode = ({
370338
371339FileNode . propTypes = {
372340 id : PropTypes . string . isRequired ,
373- parentId : PropTypes . string ,
374- children : PropTypes . arrayOf ( PropTypes . string . isRequired ) . isRequired ,
375- name : PropTypes . string . isRequired ,
376- fileType : PropTypes . string . isRequired ,
377- isSelectedFile : PropTypes . bool ,
378- isFolderClosed : PropTypes . bool ,
379- setSelectedFile : PropTypes . func . isRequired ,
380- deleteFile : PropTypes . func . isRequired ,
381- updateFileName : PropTypes . func . isRequired ,
382- resetSelectedFile : PropTypes . func . isRequired ,
383- newFile : PropTypes . func . isRequired ,
384- newFolder : PropTypes . func . isRequired ,
385- showFolderChildren : PropTypes . func . isRequired ,
386- hideFolderChildren : PropTypes . func . isRequired ,
387341 canEdit : PropTypes . bool . isRequired ,
388- openUploadFileModal : PropTypes . func . isRequired ,
389- authenticated : PropTypes . bool . isRequired ,
390342 onClickFile : PropTypes . func
391343} ;
392344
393345FileNode . defaultProps = {
394- onClickFile : null ,
395- parentId : '0' ,
396- isSelectedFile : false ,
397- isFolderClosed : false
346+ onClickFile : null
398347} ;
399348
400- function mapStateToProps ( state , ownProps ) {
401- // this is a hack, state is updated before ownProps
402- const fileNode = state . files . find ( ( file ) => file . id === ownProps . id ) || {
403- name : 'test' ,
404- fileType : 'file'
405- } ;
406- return Object . assign ( { } , fileNode , {
407- authenticated : state . user . authenticated
408- } ) ;
409- }
410-
411- const mapDispatchToProps = { ...FileActions , ...IDEActions } ;
412-
413- const ConnectedFileNode = connect (
414- mapStateToProps ,
415- mapDispatchToProps
416- ) ( FileNode ) ;
417-
418- export { FileNode } ;
419- export default ConnectedFileNode ;
349+ export default FileNode ;
0 commit comments