11import PropTypes from 'prop-types' ;
22import classNames from 'classnames' ;
33import React , { useState , useRef } from 'react' ;
4- import { useDispatch , useSelector } from 'react-redux' ;
4+ import { connect } 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' ;
109import DownArrowIcon from '../../../images/down-filled-triangle.svg' ;
1110import FolderRightIcon from '../../../images/triangle-arrow-right.svg' ;
1211import FolderDownIcon from '../../../images/triangle-arrow-down.svg' ;
1312import FileTypeIcon from './FileTypeIcon' ;
1413
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+
1541function FileName ( { name } ) {
1642 const {
1743 baseName,
@@ -36,35 +62,40 @@ FileName.propTypes = {
3662 name : PropTypes . string . isRequired
3763} ;
3864
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-
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+ } ) => {
5686 const [ isOptionsOpen , setIsOptionsOpen ] = useState ( false ) ;
5787 const [ isEditingName , setIsEditingName ] = useState ( false ) ;
5888 const [ isDeleting , setIsDeleting ] = useState ( false ) ;
5989 const [ updatedName , setUpdatedName ] = useState ( name ) ;
6090
91+ const { t } = useTranslation ( ) ;
6192 const fileNameInput = useRef ( null ) ;
6293 const fileOptionsRef = useRef ( null ) ;
6394
6495 const handleFileClick = ( event ) => {
6596 event . stopPropagation ( ) ;
6697 if ( name !== 'root' && ! isDeleting ) {
67- dispatch ( IDEActions . setSelectedFile ( id ) ) ;
98+ setSelectedFile ( id ) ;
6899 }
69100 if ( onClickFile ) {
70101 onClickFile ( ) ;
@@ -91,17 +122,17 @@ const FileNode = ({ id, canEdit, onClickFile }) => {
91122 } ;
92123
93124 const handleClickAddFile = ( ) => {
94- dispatch ( IDEActions . newFile ( id ) ) ;
125+ newFile ( id ) ;
95126 setTimeout ( ( ) => hideFileOptions ( ) , 0 ) ;
96127 } ;
97128
98129 const handleClickAddFolder = ( ) => {
99- dispatch ( IDEActions . newFolder ( id ) ) ;
130+ newFolder ( id ) ;
100131 setTimeout ( ( ) => hideFileOptions ( ) , 0 ) ;
101132 } ;
102133
103134 const handleClickUploadFile = ( ) => {
104- dispatch ( IDEActions . openUploadFileModal ( id ) ) ;
135+ openUploadFileModal ( id ) ;
105136 setTimeout ( hideFileOptions , 0 ) ;
106137 } ;
107138
@@ -110,8 +141,8 @@ const FileNode = ({ id, canEdit, onClickFile }) => {
110141
111142 if ( window . confirm ( prompt ) ) {
112143 setIsDeleting ( true ) ;
113- dispatch ( IDEActions . resetSelectedFile ( id ) ) ;
114- setTimeout ( ( ) => dispatch ( FileActions . deleteFile ( id , parentId ) , 100 ) ) ;
144+ resetSelectedFile ( id ) ;
145+ setTimeout ( ( ) => deleteFile ( id , parentId ) , 100 ) ;
115146 }
116147 } ;
117148
@@ -127,7 +158,7 @@ const FileNode = ({ id, canEdit, onClickFile }) => {
127158
128159 const saveUpdatedFileName = ( ) => {
129160 if ( updatedName !== name ) {
130- dispatch ( FileActions . updateFileName ( id , updatedName ) ) ;
161+ updateFileName ( id , updatedName ) ;
131162 }
132163 } ;
133164
@@ -212,7 +243,7 @@ const FileNode = ({ id, canEdit, onClickFile }) => {
212243 < div className = "sidebar__file-item--folder" >
213244 < button
214245 className = "sidebar__file-item-closed"
215- onClick = { ( ) => dispatch ( FileActions . showFolderChildren ( id ) ) }
246+ onClick = { ( ) => showFolderChildren ( id ) }
216247 aria-label = { t ( 'FileNode.OpenFolderARIA' ) }
217248 title = { t ( 'FileNode.OpenFolderARIA' ) }
218249 >
@@ -224,7 +255,7 @@ const FileNode = ({ id, canEdit, onClickFile }) => {
224255 </ button >
225256 < button
226257 className = "sidebar__file-item-open"
227- onClick = { ( ) => dispatch ( FileActions . hideFolderChildren ( id ) ) }
258+ onClick = { ( ) => hideFolderChildren ( id ) }
228259 aria-label = { t ( 'FileNode.CloseFolderARIA' ) }
229260 title = { t ( 'FileNode.CloseFolderARIA' ) }
230261 >
@@ -322,7 +353,7 @@ const FileNode = ({ id, canEdit, onClickFile }) => {
322353 < ul className = "file-item__children" >
323354 { children . map ( ( childId ) => (
324355 < li key = { childId } >
325- < FileNode
356+ < ConnectedFileNode
326357 id = { childId }
327358 parentId = { id }
328359 canEdit = { canEdit }
@@ -338,12 +369,50 @@ const FileNode = ({ id, canEdit, onClickFile }) => {
338369
339370FileNode . propTypes = {
340371 id : PropTypes . string . isRequired ,
372+ parentId : PropTypes . string ,
373+ children : PropTypes . arrayOf ( PropTypes . string . isRequired ) . isRequired ,
374+ name : PropTypes . string . isRequired ,
375+ fileType : PropTypes . string . isRequired ,
376+ isSelectedFile : PropTypes . bool ,
377+ isFolderClosed : PropTypes . bool ,
378+ setSelectedFile : PropTypes . func . isRequired ,
379+ deleteFile : PropTypes . func . isRequired ,
380+ updateFileName : PropTypes . func . isRequired ,
381+ resetSelectedFile : PropTypes . func . isRequired ,
382+ newFile : PropTypes . func . isRequired ,
383+ newFolder : PropTypes . func . isRequired ,
384+ showFolderChildren : PropTypes . func . isRequired ,
385+ hideFolderChildren : PropTypes . func . isRequired ,
341386 canEdit : PropTypes . bool . isRequired ,
387+ openUploadFileModal : PropTypes . func . isRequired ,
388+ authenticated : PropTypes . bool . isRequired ,
342389 onClickFile : PropTypes . func
343390} ;
344391
345392FileNode . defaultProps = {
346- onClickFile : null
393+ onClickFile : null ,
394+ parentId : '0' ,
395+ isSelectedFile : false ,
396+ isFolderClosed : false
347397} ;
348398
349- export default FileNode ;
399+ function mapStateToProps ( state , ownProps ) {
400+ // this is a hack, state is updated before ownProps
401+ const fileNode = state . files . find ( ( file ) => file . id === ownProps . id ) || {
402+ name : 'test' ,
403+ fileType : 'file'
404+ } ;
405+ return Object . assign ( { } , fileNode , {
406+ authenticated : state . user . authenticated
407+ } ) ;
408+ }
409+
410+ const mapDispatchToProps = { ...FileActions , ...IDEActions } ;
411+
412+ const ConnectedFileNode = connect (
413+ mapStateToProps ,
414+ mapDispatchToProps
415+ ) ( FileNode ) ;
416+
417+ export { FileNode } ;
418+ export default ConnectedFileNode ;
0 commit comments