Browse Source

added dynamic integration of pageHtml + beginning of Thread

Skylsmoi 6 years ago
parent
commit
ac0f4b0ea0

+ 6 - 5
jsonserver/static_db.json View File

@@ -18,7 +18,8 @@
18 18
         "id": 1,
19 19
         "title": "La programmation fonctionnelle",
20 20
         "type": "pageHtml",
21
-        "status": "validated"
21
+        "status": "validated",
22
+        "text": "<h1>Mon titre nul</h1>Je suis le contenu de cette fameuse <b>page HTML</b><br /> sur la programmation fonctionnelle"
22 23
       },
23 24
       {
24 25
         "id": 2,
@@ -28,25 +29,25 @@
28 29
       },
29 30
       {
30 31
         "id": 6,
31
-        "title": "La prommation fonctionnelle est-elle vraiment utile ?",
32
+        "title": "Une photo moche",
32 33
         "type": "file",
33 34
         "status": "current"
34 35
       },
35 36
       {
36 37
         "id": 10,
37
-        "title": "La prommation fonctionnelle est-elle vraiment utile ?",
38
+        "title": "le README.md d'un random repo github",
38 39
         "type": "pageMarkdown",
39 40
         "status": "current"
40 41
       },
41 42
       {
42 43
         "id": 7,
43
-        "title": "La prommation fonctionnelle est-elle vraiment utile ?",
44
+        "title": "Une liste de truc à faire que je ferai jamais",
44 45
         "type": "task",
45 46
         "status": "current"
46 47
       },
47 48
       {
48 49
         "id": 8,
49
-        "title": "La prommation fonctionnelle est-elle vraiment utile ?",
50
+        "title": "Ça, ça marche pas. Merci de le fix",
50 51
         "type": "issue",
51 52
         "status": "current"
52 53
       },

+ 4 - 0
src/action-creator.sync.js View File

@@ -7,3 +7,7 @@ export const updateUserData = userData => ({ type: `Update/${USER_DATA}`, data:
7 7
 
8 8
 export const WORKSPACE = 'Workspace'
9 9
 export const updateWorkspaceData = workspace => ({ type: `Update/${WORKSPACE}`, workspace })
10
+
11
+export const FILE_CONTENT = 'FileContent'
12
+export const setActiveFileContent = file => ({ type: `Set/${FILE_CONTENT}/Active`, file })
13
+export const hideActiveFileContent = () => ({ type: `Set/${FILE_CONTENT}/Hide` })

+ 56 - 0
src/component/Workspace/FileContentViewer.jsx View File

@@ -0,0 +1,56 @@
1
+import React from 'react'
2
+import PropTypes from 'prop-types'
3
+import PopinFixed from '../common/PopinFixed/PopinFixed'
4
+import PopinFixedHeader from '../common/PopinFixed/PopinFixedHeader.jsx'
5
+import PopinFixedOption from '../common/PopinFixed/PopinFixedOption.jsx'
6
+import PopinFixedContent from '../common/PopinFixed/PopinFixedContent.jsx'
7
+import PageHtml from './FileType/PageHtml.jsx'
8
+import Thread from './FileType/Thread.jsx'
9
+import Timeline from '../Timeline.jsx'
10
+import { FILE_TYPE } from '../../helper.js'
11
+
12
+const FileContentViewer = props => {
13
+  const { customClass, icon } = FILE_TYPE.find(f => f.name === props.file.type) || {customClass: '', icon: ''}
14
+
15
+  const [leftPart, rightPart] = (() => {
16
+    switch (props.file.type) {
17
+      case FILE_TYPE[0].name: // pageHtml
18
+        return [
19
+          <PageHtml version={props.file.version} text={props.file.text} />,
20
+          <Timeline customClass={`${customClass}__contentpage`} />
21
+        ]
22
+      case FILE_TYPE[3].name: // thread
23
+        return [
24
+          <Thread />
25
+        ]
26
+    }
27
+  })()
28
+
29
+  return (
30
+    <PopinFixed customClass={`${customClass}`}>
31
+      <PopinFixedHeader
32
+        customClass={`${customClass}`}
33
+        icon={icon}
34
+        name={props.file.title}
35
+        onClickCloseBtn={props.onClose}
36
+      />
37
+
38
+      <PopinFixedOption customClass={`${customClass}`} />
39
+
40
+      <PopinFixedContent customClass={`${customClass}__contentpage`}>
41
+        { leftPart }
42
+        { rightPart }
43
+      </PopinFixedContent>
44
+    </PopinFixed>
45
+  )
46
+}
47
+
48
+export default FileContentViewer
49
+
50
+FileContentViewer.PropTypes = {
51
+  file: PropTypes.shape({
52
+    type: PropTypes.oneOf(FILE_TYPE.map(f => f.name)).isRequired,
53
+    title: PropTypes.string.isRequired
54
+  }).isRequired,
55
+  onClose: PropTypes.func.isRequired
56
+}

+ 1 - 16
src/component/Workspace/FileItem.jsx View File

@@ -4,22 +4,7 @@ import classnames from 'classnames'
4 4
 import { FILE_TYPE } from '../../helper.js'
5 5
 
6 6
 const FileItem = props => {
7
-  const iconType = (() => {
8
-    switch (props.type) {
9
-      case FILE_TYPE.PAGE_HTML:
10
-        return 'fa fa-file-word-o'
11
-      case FILE_TYPE.PAGE_MARKDOWN:
12
-        return 'fa fa-file-code-o'
13
-      case FILE_TYPE.FILE:
14
-        return 'fa fa-file-text-o docandfile-color'
15
-      case FILE_TYPE.THREAD:
16
-        return 'fa fa-comments-o talk-color'
17
-      case FILE_TYPE.TASK:
18
-        return 'fa fa-list-ul task-color'
19
-      case FILE_TYPE.ISSUE:
20
-        return 'fa fa-ticket'
21
-    }
22
-  })()
7
+  const iconType = (FILE_TYPE.find(f => f.name === props.type) || {icon: ''}).icon
23 8
 
24 9
   const iconStatus = (() => {
25 10
     switch (props.status) {

+ 16 - 0
src/component/Workspace/FileType/PageHtml.jsx View File

@@ -0,0 +1,16 @@
1
+import React from 'react'
2
+
3
+const PageHtml = props => {
4
+  return (
5
+    <div className='wsFilePageHtml__contentpage__textnote'>
6
+      <div className='wsFilePageHtml__contentpage__textnote__latestversion'>
7
+        { props.version }
8
+      </div>
9
+      <div className='wsFilePageHtml__contentpage__textnote__text'>
10
+        { props.text }
11
+      </div>
12
+    </div>
13
+  )
14
+}
15
+
16
+export default PageHtml

src/container/FileType/Thread.jsx → src/component/Workspace/FileType/Thread.jsx View File

@@ -1,6 +1,6 @@
1 1
 import React, { Component } from 'react'
2 2
 import classnames from 'classnames'
3
-import imgProfil from '../../img/imgProfil.png'
3
+import imgProfil from '../../../img/imgProfil.png'
4 4
 
5 5
 class Thread extends Component {
6 6
   render () {

+ 29 - 8
src/component/common/PopinFixed/PopinFixedContent.jsx View File

@@ -1,21 +1,42 @@
1 1
 import React from 'react'
2 2
 import classnames from 'classnames'
3 3
 import PropTypes from 'prop-types'
4
+import PageHtml from '../../Workspace/FileType/PageHtml.jsx'
5
+import Thread from '../../Workspace/FileType/Thread.jsx'
6
+import Timeline from '../../Timeline.jsx'
4 7
 
5 8
 const PopinFixedContent = props => {
6
-  return (
7
-    <div className={classnames('wsFileGeneric__contentpage', `${props.customClass}`)}>
8
-      <div className={classnames('wsFileGeneric__textnote', `${props.customClass}__textnote`)} />
9
+  return props.children.length === 2
10
+    ? (
11
+      <div className={classnames('wsFileGeneric__contentpage', `${props.customClass}`)}>
12
+        {props.children[0]}
9 13
 
10
-      <div className={classnames('wsFileGeneric__wrapper', `${props.customClass}__wrapper`)}>
11
-        {props.children}
14
+        <div className={classnames('wsFileGeneric__wrapper', `${props.customClass}__wrapper`)}>
15
+          {props.children[1]}
16
+        </div>
12 17
       </div>
13
-    </div>
14
-  )
18
+    )
19
+    : (
20
+      <div className={classnames('wsFileGeneric__contentpage', `${props.customClass}`)}>
21
+        { props.children }
22
+      </div>
23
+    )
15 24
 }
16 25
 
17 26
 export default PopinFixedContent
18 27
 
19 28
 PopinFixedContent.propTypes = {
20
-  customClass: PropTypes.string
29
+  customClass: PropTypes.string,
30
+  // from http://www.mattzabriskie.com/blog/react-validating-children
31
+  children: PropTypes.arrayOf((children, key, componentName /* , location, propFullName */) => {
32
+    if (
33
+      (Array.isArray(children.length) && (
34
+        children.length > 2 ||
35
+        (children.length === 2 && children.some(c => ![PageHtml, Thread, Timeline].includes(c.type)))
36
+      )) ||
37
+      (children.type === Timeline)
38
+    ) {
39
+      return new Error(`PropType Error: childrens of ${componentName} must be one of [PageHtml, Thread, Timeline, undefined].`)
40
+    }
41
+  }).isRequired
21 42
 }

+ 5 - 1
src/component/common/PopinFixed/PopinFixedHeader.jsx View File

@@ -17,7 +17,10 @@ const PopinFixedHeader = props => {
17 17
         <i className='fa fa-pencil' />
18 18
       </div>
19 19
 
20
-      <div className={classnames('wsFileGeneric__header__close', `${props.customClass}__header__close`)}>
20
+      <div
21
+        className={classnames('wsFileGeneric__header__close', `${props.customClass}__header__close`)}
22
+        onClick={props.onClickCloseBtn}
23
+      >
21 24
         <i className='fa fa-times' />
22 25
       </div>
23 26
     </div>
@@ -28,6 +31,7 @@ export default PopinFixedHeader
28 31
 
29 32
 PopinFixedHeader.propTypes = {
30 33
   icon: PropTypes.string.isRequired,
34
+  onClickCloseBtn: PropTypes.func.isRequired,
31 35
   customClass: PropTypes.string,
32 36
   name: PropTypes.string
33 37
 }

+ 0 - 73
src/container/FileType/PageHtml.jsx View File

@@ -1,73 +0,0 @@
1
-import React, { Component } from 'react'
2
-import PopinFixed from '../../component/common/PopinFixed/PopinFixed'
3
-import PopinFixedHeader from '../../component/common/PopinFixed/PopinFixedHeader.jsx'
4
-import PopinFixedOption from '../../component/common/PopinFixed/PopinFixedOption.jsx'
5
-import PopinFixedContent from '../../component/common/PopinFixed/PopinFixedContent.jsx'
6
-import Timeline from '../../component/Timeline.jsx'
7
-
8
-class PageHtml extends Component {
9
-  render () {
10
-    return (
11
-      <PopinFixed customClass={'wsFileText'}>
12
-        <PopinFixedHeader
13
-          customClass='wsFileText'
14
-          icon='fa fa-file-word-o'
15
-          name='Facture 57840 - Jean-michel Chevalier - 04/09/2017'
16
-        />
17
-
18
-        <PopinFixedOption customClass={'wsFileText'} />
19
-
20
-        <PopinFixedContent customClass={'wsFileText__contentpage'}>
21
-          <Timeline customClass={'wsFileText__contentpage'} />
22
-        </PopinFixedContent>
23
-      </PopinFixed>
24
-    )
25
-  }
26
-}
27
-
28
-export default PageHtml
29
-
30
-/*
31
-      <div className={classnames('wsFileText wsFileGeneric', {'visible': this.props.visible})}>
32
-
33
-        <div className='wsFileText__contentpage wsFileGeneric__contentpage'>
34
-          <div className='wsFileText__contentpage__textnote'>
35
-            <div className='wsFileText__contentpage__textnote__latestversion'>
36
-              Dernière version : v3
37
-            </div>
38
-            <div className='wsFileText__contentpage__textnote__title'>
39
-              Titre de 30px de font size
40
-            </div>
41
-            <div className='wsFileText__contentpage__textnote__data'>
42
-              Labore tempor sunt id quis quis velit ut officia amet ut
43
-              adipisicing in in commodo exercitation cupidatat culpa
44
-              eiusmo dolor consectetur dolor ut proident proident culpamet
45
-              denim consequat in sit ex ullamco duis.
46
-              <br />
47
-              Labore tempor sunt id quis quis velit ut officia amet ut
48
-              adipisicing in in commodo exercitation cupidatat culpa
49
-              eiusmo dolor consectetur dolor ut proident proident culpamet
50
-              denim consequat in sit ex ullamco duis.
51
-              <br />
52
-              Labore tempor sunt id quis quis velit ut officia amet ut
53
-              adipisicing in in commodo exercitation cupidatat culpa
54
-              eiusmo dolor consectetur dolor ut proident proident culpamet
55
-              denim consequat in sit ex ullamco duis.
56
-              <br />
57
-              Labore tempor sunt id quis quis velit ut officia amet ut
58
-              adipisicing in in commodo exercitation cupidatat culpa
59
-              eiusmo dolor consectetur dolor ut proident proident culpamet
60
-              denim consequat in sit ex ullamco duis.
61
-            </div>
62
-          </div>
63
-          <div className='wsFileText__contentpage__wrapper wsFileGeneric__wrapper'>
64
-
65
-          </div>
66
-        </div>
67
-      </div>
68
-    )
69
-  }
70
-}
71
-
72
-export default PageText
73
-*/

+ 19 - 9
src/container/WorkspaceContent.jsx View File

@@ -3,13 +3,13 @@ import { connect } from 'react-redux'
3 3
 import Folder from '../component/Workspace/Folder.jsx'
4 4
 import FileItem from '../component/Workspace/FileItem.jsx'
5 5
 import FileItemHeader from '../component/Workspace/FileItemHeader.jsx'
6
-// import Thread from './FileType/Thread.jsx'
7
-import PageHtml from './FileType/PageHtml.jsx'
8 6
 import PageWrapper from '../component/common/layout/PageWrapper.jsx'
9 7
 import PageTitle from '../component/common/layout/PageTitle.jsx'
10 8
 import PageContent from '../component/common/layout/PageContent.jsx'
11 9
 import DropdownCreateButton from '../component/common/Input/DropdownCreateButton.jsx'
10
+import FileContentViewer from '../component/Workspace/FileContentViewer.jsx'
12 11
 import { getWorkspaceContent } from '../action-creator.async.js'
12
+import { setActiveFileContent, hideActiveFileContent } from '../action-creator.sync.js'
13 13
 
14 14
 class WorkspaceContent extends React.Component {
15 15
   constructor (props) {
@@ -23,8 +23,16 @@ class WorkspaceContent extends React.Component {
23 23
     this.props.dispatch(getWorkspaceContent(/* this.props.workspace.id */1))
24 24
   }
25 25
 
26
+  handleClickFileItem = file => {
27
+    this.props.dispatch(setActiveFileContent(file))
28
+  }
29
+
30
+  handleClickCloseBtn = () => {
31
+    this.props.dispatch(hideActiveFileContent())
32
+  }
33
+
26 34
   render () {
27
-    const { workspace } = this.props
35
+    const { workspace, activeFileContent } = this.props
28 36
 
29 37
     return (
30 38
       <PageWrapper customeClass='workspace'>
@@ -48,7 +56,7 @@ class WorkspaceContent extends React.Component {
48 56
                   name={c.title}
49 57
                   type={c.type}
50 58
                   status={c.status}
51
-                  onClickItem={() => this.setState({activeFileType: 'file'})}
59
+                  onClickItem={() => this.handleClickFileItem(c)}
52 60
                   key={c.id}
53 61
                 />
54 62
               )
@@ -57,10 +65,12 @@ class WorkspaceContent extends React.Component {
57 65
 
58 66
           <DropdownCreateButton customClass='workspace__content__button mb-5' />
59 67
 
60
-          <PageHtml visible={this.state.activeFileType === 'file'} />
61
-          {/*
62
-          <Thread visible={this.state.activeFileType === 'chat'} />
63
-          */}
68
+          { activeFileContent.display &&
69
+            <FileContentViewer
70
+              file={activeFileContent}
71
+              onClose={this.handleClickCloseBtn}
72
+            />
73
+          }
64 74
         </PageContent>
65 75
 
66 76
       </PageWrapper>
@@ -68,5 +78,5 @@ class WorkspaceContent extends React.Component {
68 78
   }
69 79
 }
70 80
 
71
-const mapStateToProps = ({ workspace }) => ({ workspace })
81
+const mapStateToProps = ({ workspace, activeFileContent }) => ({ workspace, activeFileContent })
72 82
 export default connect(mapStateToProps)(WorkspaceContent)

+ 10 - 47
src/css/PageHtml.styl View File

@@ -1,4 +1,4 @@
1
-.wsFileText
1
+.wsFilePageHtml
2 2
   width 1200px
3 3
   height calc(100% - 85px)
4 4
   overflow-Y auto
@@ -20,14 +20,8 @@
20 20
       &__latestversion
21 21
         text-align right
22 22
         opacity 0.7
23
-      &__title
24
-        margin 10px 0
25
-        font-size 30px
26
-        color htmlColor
27
-      &__data
28
-        flex-grow 1
29
-        flex-shrink 1
30
-        flex-basis 0
23
+      &__text
24
+        font-size 14px
31 25
     &__wrapper
32 26
       margin 10px
33 27
       border-radius 10px
@@ -86,28 +80,17 @@
86 80
             border-color htmlColor
87 81
             background-color htmlColor
88 82
 
89
-/***** CLASS MESSAGELISTSIZE *****/
90
-
91 83
 .messagelistOpen
92
-  .wsFileText__contentpage__messagelist
84
+  .wsFilePageHtml__contentpage__messagelist
93 85
     flex 0
94 86
     min-height 0
95 87
 
96
-/*********************************/
97
-
98
-/***** SENDER RECEIVER *****/
99
-
100 88
 .received
101
-  .wsFileText__contentpage__messagelist__item__content
89
+  .wsFilePageHtml__contentpage__messagelist__item__content
102 90
       background-color htmlColor
103 91
 
104
-/*****************************/
105
-
106
-/**** MEDIA QUERIES ****/
107
-
108 92
 @media (min-width: max-xs) and (max-width: max-lg)
109
-
110
-  .wsFileText
93
+  .wsFilePageHtml
111 94
     &__contentpage
112 95
       display block
113 96
       overflow-Y scroll
@@ -123,11 +106,9 @@
123 106
       &__texteditor
124 107
         &__simpletext
125 108
           display inline-flex
126
-          display ms-inline-flex
127 109
           width 60%
128 110
         &__submit
129 111
           display inline-flex
130
-          display ms-inline-flex
131 112
           margin 10px 0
132 113
           &__btn
133 114
             display flex
@@ -135,46 +116,28 @@
135 116
             &__icon
136 117
               margin-left 15px
137 118
 
138
-/**** MEDIA 992px & 1199px ****/
139
-
140 119
 @media (min-width: min-lg) and (max-width: max-lg)
141
-
142
-  .wsFileText
120
+  .wsFilePageHtml
143 121
     width 692px
144 122
     &__contentpage__texteditor__simpletext
145 123
       margin-left 15px
146 124
 
147
-/******************************/
148
-
149
-/**** MEDIA 768px & 991px ****/
150
-
151 125
 @media (min-width: min-md) and (max-width: max-md)
152
-
153
-  .wsFileText
126
+  .wsFilePageHtml
154 127
     width 768px
155 128
     &__contentpage__texteditor__simpletext
156 129
       margin-left 25px
157 130
 
158
-/******************************/
159
-
160
-/**** MEDIA 576px & 767px ****/
161
-
162 131
 @media (min-width: min-sm) and (max-width: max-sm)
163
-
164
-  .wsFileText
132
+  .wsFilePageHtml
165 133
       top 69px
166 134
       width 576px
167 135
       height calc(100% - 69px)
168 136
       &__contentpage__texteditor__simpletext
169 137
         margin-left 10px
170 138
 
171
-/******************************/
172
-
173
-/**** MEDIA 575px ****/
174
-
175 139
 @media (max-width: max-xs)
176
-
177
-  .wsFileText
140
+  .wsFilePageHtml
178 141
     top 70px
179 142
     height calc(100% - 70px)
180 143
     width 100%

+ 25 - 8
src/helper.js View File

@@ -5,11 +5,28 @@ export const FETCH_CONFIG = {
5 5
   }
6 6
 }
7 7
 
8
-export const FILE_TYPE = {
9
-  PAGE_HTML: 'pageHtml',
10
-  PAGE_MARKDOWN: 'pageMarkdown',
11
-  FILE: 'file',
12
-  THREAD: 'thread',
13
-  TASK: 'task',
14
-  ISSUE: 'issue'
15
-}
8
+export const FILE_TYPE = [{
9
+  name: 'pageHtml',
10
+  customClass: 'wsFilePageHtml',
11
+  icon: 'fa fa-file-word-o'
12
+}, {
13
+  name: 'pageMarkdown',
14
+  customClass: 'wsFilePageMarkdown',
15
+  icon: 'fa fa-file-code-o'
16
+}, {
17
+  name: 'file',
18
+  customClass: 'wsFileFile',
19
+  icon: 'fa fa-file-text-o'
20
+}, {
21
+  name: 'thread',
22
+  customClass: 'wsFileThread',
23
+  icon: 'fa fa-comments-o'
24
+}, {
25
+  name: 'task',
26
+  customClass: 'wsFileTask',
27
+  icon: 'fa fa-list-ul'
28
+}, {
29
+  name: 'issue',
30
+  customClass: 'wsFileIssue',
31
+  icon: 'fa fa-ticket'
32
+}]

+ 22 - 0
src/reducer/activeFileContent.js View File

@@ -0,0 +1,22 @@
1
+import { FILE_CONTENT } from '../action-creator.sync.js'
2
+
3
+export default function activeFileContent (state = {
4
+  display: false,
5
+  type: '',
6
+  title: '',
7
+  status: ''
8
+}, action) {
9
+  switch (action.type) {
10
+    case `Set/${FILE_CONTENT}/Active`:
11
+      return {
12
+        display: true,
13
+        ...action.file
14
+      }
15
+
16
+    case `Set/${FILE_CONTENT}/Hide`:
17
+      return {...state, display: false}
18
+
19
+    default:
20
+      return state
21
+  }
22
+}

+ 10 - 0
src/reducer/fileType/index.js View File

@@ -0,0 +1,10 @@
1
+import { combineReducers } from 'redux'
2
+
3
+// import color from './color.js'
4
+// import size from './size.js'
5
+// import price from './price.js'
6
+// import multicolor from './multicolor.js'
7
+
8
+export default combineReducers({
9
+
10
+})

+ 10 - 0
src/reducer/fileType/pageHtml.js View File

@@ -0,0 +1,10 @@
1
+export default function pageHtml (state = {
2
+  title: '',
3
+  version: 0,
4
+  text: ''
5
+}, action) {
6
+  switch (action.type) {
7
+    default:
8
+      return state
9
+  }
10
+}

+ 2 - 1
src/reducer/root.js View File

@@ -1,7 +1,8 @@
1 1
 import { combineReducers } from 'redux'
2 2
 import user from './user.js'
3 3
 import workspace from './workspace.js'
4
+import activeFileContent from './activeFileContent.js'
4 5
 
5
-const rootReducer = combineReducers({ user, workspace })
6
+const rootReducer = combineReducers({ user, workspace, activeFileContent })
6 7
 
7 8
 export default rootReducer