Browse Source

added login and workspace content loading from mockapi

Skylsmoi 6 years ago
parent
commit
a95fc01416

+ 5 - 4
dist/index.html View File

@@ -34,7 +34,6 @@
34 34
         var jsScript = document.createElement("script");
35 35
         jsScript.type = "text/javascript";
36 36
         jsScript.src = "https://cloud.tinymce.com/stable/tinymce.min.js?apiKey=dfdhxdokxj2wagzkbxfgysgh86d6rr9m3dln0172vo3shipc";
37
-        console.log("load the lib");
38 37
 
39 38
         jsScript.onload = function() {
40 39
           function base64EncodeAndTinyMceInsert (files) {
@@ -91,18 +90,20 @@
91 90
                 icon: 'mce-ico mce-i-image',
92 91
                 title: 'Image',
93 92
                 onclick: function () {
94
-                  if ($('#hidden_tinymce_fileinput').length > 0) $('#hidden_tinymce_fileinput').remove()
93
+                  var hiddenTinyMceInput = $('#hidden_tinymce_fileinput')
94
+
95
+                  if (hiddenTinyMceInput.length > 0) hiddenTinyMceInput.remove()
95 96
 
96 97
                   fileTag = document.createElement('input')
97 98
                   fileTag.id = 'hidden_tinymce_fileinput'
98 99
                   fileTag.type = 'file'
99 100
                   $('body').append(fileTag)
100 101
 
101
-                  $('#hidden_tinymce_fileinput').on('change', function () {
102
+                  hiddenTinyMceInput.on('change', function () {
102 103
                     base64EncodeAndTinyMceInsert($(this)[0].files)
103 104
                   })
104 105
 
105
-                  $('#hidden_tinymce_fileinput').click()
106
+                  hiddenTinyMceInput.click()
106 107
                 }
107 108
               })
108 109
 

+ 6 - 5
jsonserver/server.js View File

@@ -11,20 +11,21 @@ server.use(jsonServer.bodyParser)
11 11
 // res.jsonp(req.query)
12 12
 server.get('/echo', (req, res) => res.jsonp('gg'))
13 13
 server.get('/login', (req, res) => res.jsonp(jsonDb.login))
14
-server.post('/user/login', (req, res) => {
15
-  if (req.body.login !== '' && req.body.password !== '') return res.jsonp(jsonDb.user_logged)
16
-  else return res.jsonp('error')
17
-})
18 14
 server.get('/user_logged', (req, res) => res.jsonp(jsonDb.user_logged))
19 15
 server.delete('/deletenodata', (req,res) => res.status(204).jsonp(''))
20 16
 server.patch('/user', (req, res) => res.jsonp({lang: 'fr'}))
21
-
22 17
 // server.put('/api/data/raw_materials_vendors/:vendorid', (req, res) => {
23 18
 //  res.jsonp(jsonVendorColorData.vendorVariableData)
24 19
 //   console.log(req.body)
25 20
 //   res.jsonp('gg')
26 21
 // })
27 22
 
23
+server.post('/user/login', (req, res) => {
24
+  if (req.body.login !== '' && req.body.password !== '') return res.jsonp(jsonDb.user_logged)
25
+  else return res.jsonp('error')
26
+})
27
+server.get('/workspace/:id', (req, res) => res.jsonp(jsonDb.workspace_detail))
28
+
28 29
 server.use(router)
29 30
 server.listen(GLOBAL_PORT, () => {
30 31
   console.log('JSON Server is running on port : ' + GLOBAL_PORT)

+ 38 - 0
jsonserver/static_db.json View File

@@ -6,5 +6,43 @@
6 6
     "firstname": "Côme",
7 7
     "lastname": "Stoilenom",
8 8
     "email": "osef@algoo.fr"
9
+  },
10
+  "workspace_detail": {
11
+    "id": 1,
12
+    "title": "Mission interne - développement",
13
+    "owner_id": 5,
14
+    "content": [
15
+      {
16
+        "id": 1,
17
+        "title": "La programmation fonctionnelle",
18
+        "type": "pageHtml",
19
+        "status": "validated"
20
+      },
21
+      {
22
+        "id": 2,
23
+        "title": "La prommation fonctionnelle est-elle vraiment utile ?",
24
+        "type": "thread",
25
+        "status": "current"
26
+      },
27
+      {
28
+        "id": 3,
29
+        "title": "Programmation objet",
30
+        "type": "folder",
31
+        "content": [
32
+          {
33
+            "id": 4,
34
+            "title": "des trucs de backend",
35
+            "type": "file",
36
+            "status": "outdated"
37
+          },
38
+          {
39
+            "id": 5,
40
+            "title": "on s'emmerde",
41
+            "type": "pageHtml",
42
+            "status": "outdated"
43
+          }
44
+        ]
45
+      }
46
+    ]
9 47
   }
10 48
 }

+ 25 - 3
src/action-creator.async.js View File

@@ -4,7 +4,9 @@ import {
4 4
   USER_DATA,
5 5
   USER_CONNECTED,
6 6
   updateUserConnected,
7
-  updateUserData
7
+  updateUserData,
8
+  WORKSPACE,
9
+  updateWorkspaceData
8 10
 } from './action-creator.sync.js'
9 11
 
10 12
 /*
@@ -53,10 +55,20 @@ const fetchWrapper = async ({url, param, actionName, dispatch, debug = false}) =
53 55
   return fetchResult
54 56
 }
55 57
 
56
-export const userLogin = (login, password) => async dispatch => {
58
+export const userLogin = (login, password, rememberMe) => async dispatch => {
59
+  const jsonBody = JSON.stringify({
60
+    login,
61
+    password,
62
+    remember_me: rememberMe
63
+  })
64
+
57 65
   const fetchUserLogin = await fetchWrapper({
58 66
     url: 'http://localhost:3001/user/login',
59
-    param: {...FETCH_CONFIG, method: 'POST', body: JSON.stringify({login, password})},
67
+    param: {
68
+      ...FETCH_CONFIG,
69
+      method: 'POST',
70
+      body: jsonBody
71
+    },
60 72
     actionName: USER_LOGIN,
61 73
     dispatch
62 74
   })
@@ -92,3 +104,13 @@ export const updateUserLang = newLang => async dispatch => {
92 104
 //   })
93 105
 //   console.log('jsonResponseNoData', fetchResponseNoData)
94 106
 // }
107
+
108
+export const getWorkspaceContent = workspaceId => async dispatch => {
109
+  const fetchGetWorkspaceContent = await fetchWrapper({
110
+    url: `http://localhost:3001/workspace/${workspaceId}`,
111
+    param: {...FETCH_CONFIG, method: 'GET'},
112
+    actionName: WORKSPACE,
113
+    dispatch
114
+  })
115
+  if (fetchGetWorkspaceContent.status === 200) dispatch(updateWorkspaceData(fetchGetWorkspaceContent.json))
116
+}

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

@@ -4,3 +4,6 @@ export const USER_DATA = 'User/Data'
4 4
 export const USER_CONNECTED = 'User/Connected'
5 5
 export const updateUserConnected = user => ({ type: `Update/${USER_CONNECTED}`, user })
6 6
 export const updateUserData = userData => ({ type: `Update/${USER_DATA}`, data: userData })
7
+
8
+export const WORKSPACE = 'Workspace'
9
+export const updateWorkspaceData = workspace => ({ type: `Update/${WORKSPACE}`, workspace })

+ 15 - 15
src/component/Timeline.jsx View File

@@ -14,7 +14,7 @@ const Timeline = props => {
14 14
 
15 15
         <li className={classnames(`${props.customClass}__messagelist__item`, 'timeline__messagelist__item sended')}>
16 16
           <div className={classnames(`${props.customClass}__messagelist__item__avatar`, 'timeline__messagelist__item__avatar')}>
17
-            <img src={imgProfilOrange} alt='avatar'/>
17
+            <img src={imgProfilOrange} alt='avatar' />
18 18
           </div>
19 19
           <div
20 20
             className={classnames(`${props.customClass}__messagelist__item__createhour`, 'timeline__messagelist__item__createhour')}>
@@ -28,7 +28,7 @@ const Timeline = props => {
28 28
 
29 29
         <li className={classnames(`${props.customClass}__messagelist__item`, 'timeline__messagelist__item received')}>
30 30
           <div className={classnames(`${props.customClass}__messagelist__item__avatar`, 'timeline__messagelist__item__avatar')}>
31
-            <img src={imgProfilReverse} alt='avatar'/>
31
+            <img src={imgProfilReverse} alt='avatar' />
32 32
           </div>
33 33
           <div
34 34
             className={classnames(`${props.customClass}__messagelist__item__createhour`, 'timeline__messagelist__item__createhour')}>
@@ -46,7 +46,7 @@ const Timeline = props => {
46 46
 
47 47
         <li className={classnames(`${props.customClass}__messagelist__version`, 'timeline__messagelist__version')}>
48 48
           <div className={classnames(`${props.customClass}__messagelist__version__btn`, 'timeline__messagelist__version__btn btn')}>
49
-            <i className='fa fa-code-fork'/>
49
+            <i className='fa fa-code-fork' />
50 50
             version 3
51 51
           </div>
52 52
           <div className={classnames(`${props.customClass}__messagelist__version__date`, 'timeline__messagelist__version__date')}>
@@ -56,7 +56,7 @@ const Timeline = props => {
56 56
 
57 57
         <li className={classnames(`${props.customClass}__messagelist__item`, 'timeline__messagelist__item sended')}>
58 58
           <div className={classnames(`${props.customClass}__messagelist__item__avatar`, 'timeline__messagelist__item__avatar')}>
59
-            <img src={imgProfilOrange} alt='avatar'/>
59
+            <img src={imgProfilOrange} alt='avatar' />
60 60
           </div>
61 61
           <div
62 62
             className={classnames(`${props.customClass}__messagelist__item__createhour`, 'timeline__messagelist__item__createhour')}>
@@ -70,7 +70,7 @@ const Timeline = props => {
70 70
 
71 71
         <li className={classnames(`${props.customClass}__messagelist__item`, 'timeline__messagelist__item received')}>
72 72
           <div className={classnames(`${props.customClass}__messagelist__item__avatar`, 'timeline__messagelist__item__avatar')}>
73
-            <img src={imgProfilReverse} alt='avatar'/>
73
+            <img src={imgProfilReverse} alt='avatar' />
74 74
           </div>
75 75
           <div
76 76
             className={classnames(`${props.customClass}__messagelist__item__createhour`, 'timeline__messagelist__item__createhour')}>
@@ -90,27 +90,27 @@ const Timeline = props => {
90 90
       <form className={classnames(`${props.customClass}__texteditor`, 'timeline__texteditor')}>
91 91
         <div
92 92
           className={classnames(`${props.customClass}__texteditor__simpletext`, 'timeline__texteditor__simpletext input-group')}>
93
-          <input type='text'
94
-                 className={classnames(`${props.customClass}__texteditor__simpletext__input`, 'timeline__texteditor__simpletext__input form-control')}
95
-                 placeholder='...'/>
93
+          <input
94
+            type='text'
95
+            className={classnames(`${props.customClass}__texteditor__simpletext__input`, 'timeline__texteditor__simpletext__input form-control')}
96
+            placeholder='...'
97
+          />
96 98
           <div
97 99
             className={classnames(`${props.customClass}__texteditor__simpletext__icon`, 'timeline__texteditor__simpletext__icon input-group-addon')}>
98
-            <i className='fa fa-font'/>
100
+            <i className='fa fa-font' />
99 101
           </div>
100 102
         </div>
101
-        <div
102
-          className={classnames(`${props.customClass}__texteditor__wysiwyg`, 'timeline__texteditor__wysiwyg d-none d-xl-block')}>
103
-          <textarea/>
103
+        <div className={classnames(`${props.customClass}__texteditor__wysiwyg`, 'timeline__texteditor__wysiwyg d-none d-xl-block')}>
104
+          <textarea />
104 105
         </div>
105
-        <div
106
-          className={classnames(`${props.customClass}__texteditor__submit`, 'timeline__texteditor__submit d-xl-flex justify-content-xl-center')}>
106
+        <div className={classnames(`${props.customClass}__texteditor__submit`, 'timeline__texteditor__submit d-xl-flex justify-content-xl-center')}>
107 107
           <button
108 108
             type='submit'
109 109
             className={classnames(`${props.customClass}__texteditor__submit__btn`, 'timeline__texteditor__submit__btn btn')}
110 110
           >
111 111
             Envoyer
112 112
             <div className={classnames(`${props.customClass}__texteditor__submit__btn__icon`, 'timeline__texteditor__submit__btn__icon')}>
113
-              <i className='fa fa-paper-plane-o'/>
113
+              <i className='fa fa-paper-plane-o' />
114 114
             </div>
115 115
           </button>
116 116
         </div>

+ 10 - 3
src/component/Workspace/FileItem.jsx View File

@@ -1,16 +1,23 @@
1 1
 import React from 'react'
2 2
 import PropTypes from 'prop-types'
3 3
 import classnames from 'classnames'
4
+import { FILE_TYPE } from '../../helper.js'
4 5
 
5 6
 const FileItem = props => {
6 7
   const iconType = (() => {
7 8
     switch (props.type) {
8
-      case 'file':
9
+      case FILE_TYPE.PAGE_HTML:
10
+        return 'fa fa-exclamation-triangle'
11
+      case FILE_TYPE.PAGE_MARKDOWN:
12
+        return 'fa fa-exclamation-triangle'
13
+      case FILE_TYPE.FILE:
9 14
         return 'fa fa-file-text-o docandfile-color'
10
-      case 'chat':
15
+      case FILE_TYPE.THREAD:
11 16
         return 'fa fa-comments talk-color'
12
-      case 'task':
17
+      case FILE_TYPE.TASK:
13 18
         return 'fa fa-list-ul task-color'
19
+      case FILE_TYPE.ISSUE:
20
+        return 'fa fa-exclamation-triangle'
14 21
     }
15 22
   })()
16 23
 

+ 24 - 6
src/component/Workspace/Folder.jsx View File

@@ -1,8 +1,9 @@
1 1
 import React, { Component } from 'react'
2
-// import PropTypes from 'prop-types'
3
-// import classnames from 'classnames'
2
+import PropTypes from 'prop-types'
3
+import classnames from 'classnames'
4
+import FileItem from './FileItem.jsx'
4 5
 
5
-// @TODO set Folder as a component, state open will come from parent container (which will come from redux)
6
+// @TODO set Folder as a component, state open will come from parent container (which will come from redux) // update: or not ?
6 7
 
7 8
 class Folder extends Component {
8 9
   constructor (props) {
@@ -20,8 +21,9 @@ class Folder extends Component {
20 21
   }
21 22
 
22 23
   render () {
24
+    const { title, content } = this.props.folderData
23 25
     return (
24
-      <div className={'folder' + (this.state.open ? ' active' : '')}>
26
+      <div className={classnames('folder', {'active': this.state.open})}>
25 27
         <div className='folder__header' onClick={this.handleClickToggleFolder}>
26 28
           <div className='folder__header__triangleborder'>
27 29
             <div className='folder__header__triangleborder__triangle' />
@@ -31,7 +33,7 @@ class Folder extends Component {
31 33
               <i className='fa fa-folder-open-o' />
32 34
             </div>
33 35
             <div className='folder__header__name__text'>
34
-              Dossier Facture
36
+              { title }
35 37
             </div>
36 38
             <div className='folder__header__name__addbtn' onClick={this.handleClickNewFile}>
37 39
               <div className='folder__header__name__addbtn__text btn btn-primary'>
@@ -52,7 +54,16 @@ class Folder extends Component {
52 54
         </div>
53 55
 
54 56
         <div className='folder__content'>
55
-          { this.props.children }
57
+          { content.map(c => c.type === 'folder'
58
+            ? <Folder folderData={c} key={c.id} />
59
+            : <FileItem
60
+              name={c.title}
61
+              type={c.type}
62
+              status={c.status}
63
+              onClickItem={() => {}}
64
+              key={c.id}
65
+            />
66
+          )}
56 67
         </div>
57 68
       </div>
58 69
     )
@@ -60,3 +71,10 @@ class Folder extends Component {
60 71
 }
61 72
 
62 73
 export default Folder
74
+
75
+Folder.propTypes = {
76
+  folderData: PropTypes.shape({
77
+    title: PropTypes.string.isRequired,
78
+    content: PropTypes.array
79
+  })
80
+}

+ 2 - 3
src/component/common/PopinFixed/PopinFixedContent.jsx View File

@@ -5,8 +5,7 @@ import PropTypes from 'prop-types'
5 5
 const PopinFixedContent = props => {
6 6
   return (
7 7
     <div className={classnames('wsFileGeneric__contentpage', `${props.customClass}`)}>
8
-      <div className={classnames('wsFileGeneric__textnote', `${props.customClass}__textnote`)}>
9
-      </div>
8
+      <div className={classnames('wsFileGeneric__textnote', `${props.customClass}__textnote`)} />
10 9
 
11 10
       <div className={classnames('wsFileGeneric__wrapper', `${props.customClass}__wrapper`)}>
12 11
         {props.children}
@@ -18,5 +17,5 @@ const PopinFixedContent = props => {
18 17
 export default PopinFixedContent
19 18
 
20 19
 PopinFixedContent.propTypes = {
21
-
20
+  customClass: PropTypes.string
22 21
 }

+ 2 - 2
src/component/common/PopinFixed/PopinFixedOption.jsx View File

@@ -1,6 +1,6 @@
1 1
 import React from 'react'
2
-import classnames from 'classnames'
3
-import PropTypes from 'prop-types'
2
+// import classnames from 'classnames'
3
+// import PropTypes from 'prop-types'
4 4
 
5 5
 const PopinFixedOption = props => {
6 6
   return (

+ 2 - 2
src/container/Login.jsx View File

@@ -27,9 +27,9 @@ class Login extends React.Component {
27 27
 
28 28
   handleClickSubmit = () => {
29 29
     const { history, dispatch } = this.props
30
-    const { inputLogin, inputPassword } = this.state
30
+    const { inputLogin, inputPassword, inputRememberMe } = this.state
31 31
 
32
-    dispatch(userLogin(inputLogin, inputPassword))
32
+    dispatch(userLogin(inputLogin, inputPassword, inputRememberMe))
33 33
     .then(() => history.push('/'))
34 34
   }
35 35
 

+ 15 - 7
src/container/Tracim.jsx View File

@@ -5,13 +5,24 @@ import Header from './Header.jsx'
5 5
 import Sidebar from './Sidebar.jsx'
6 6
 import Login from './Login.jsx'
7 7
 import Page from './Page.jsx'
8
-import Workspace from './Workspace.jsx'
8
+import WorkspaceContent from './WorkspaceContent.jsx'
9 9
 import {
10 10
   Route,
11 11
   withRouter
12 12
 } from 'react-router-dom'
13 13
 import PrivateRoute from './PrivateRoute.jsx'
14 14
 
15
+const SidebarWrapper = props => {
16
+  if (props.locationPath !== '/login') {
17
+    return (
18
+      <div className='sidebarpagecontainer'>
19
+        <Sidebar />
20
+        {props.children}
21
+      </div>
22
+    )
23
+  } else return props.children
24
+}
25
+
15 26
 class Tracim extends React.Component {
16 27
   render () {
17 28
     const { location } = this.props
@@ -21,15 +32,12 @@ class Tracim extends React.Component {
21 32
 
22 33
         <Route path='/login' component={Login} />
23 34
 
24
-        <div className='sidebarpagecontainer'>
35
+        <SidebarWrapper locationPath={location.pathname}>
25 36
 
26
-          { location.pathname !== '/login' && // cant find "except" in <Route path />
27
-            <Sidebar />
28
-          }
29
-          <Route exact path='/' component={Workspace} />
37
+          <PrivateRoute exact path='/' component={WorkspaceContent} />
30 38
           <PrivateRoute path='/page' component={Page} />
31 39
 
32
-        </div>
40
+        </SidebarWrapper>
33 41
 
34 42
         <Footer />
35 43
       </div>

+ 0 - 91
src/container/Workspace.jsx View File

@@ -1,91 +0,0 @@
1
-import React from 'react'
2
-import { connect } from 'react-redux'
3
-import Folder from '../component/Workspace/Folder.jsx'
4
-import FileItem from '../component/Workspace/FileItem.jsx'
5
-import FileItemHeader from '../component/Workspace/FileItemHeader.jsx'
6
-import Thread from './Thread.jsx'
7
-import PageText from './PageText.jsx'
8
-import PageWrapper from '../component/common/layout/PageWrapper.jsx'
9
-import PageTitle from '../component/common/layout/PageTitle.jsx'
10
-import PageContent from '../component/common/layout/PageContent.jsx'
11
-import DropdownCreateButton from '../component/common/Input/DropdownCreateButton.jsx'
12
-
13
-class Workspace extends React.Component {
14
-  constructor (props) {
15
-    super(props)
16
-    this.state = {
17
-      activeFileType: ''
18
-    }
19
-  }
20
-
21
-  render () {
22
-    return (
23
-      <PageWrapper customeClass='workspace'>
24
-        <PageTitle
25
-          parentClass='workspace__header'
26
-          customClass='justify-content-between'
27
-          title='Documents & Fichiers'
28
-        >
29
-          <DropdownCreateButton parentClass='workspace__header__btnaddworkspace' />
30
-        </PageTitle>
31
-
32
-        <PageContent parentClass='workspace__content'>
33
-
34
-          <div className='workspace__content__fileandfolder folder__content active'>
35
-            <FileItemHeader />
36
-
37
-            <FileItem
38
-              name='Facture 57841 - Pierre Maurice - 06/06/2017'
39
-              type='file'
40
-              status='current'
41
-              onClickItem={() => this.setState({activeFileType: 'file'})}
42
-            />
43
-            <FileItem
44
-              name='Facture 57840 - Jean-michel Chevalier - 04/09/2017'
45
-              type='file'
46
-              status='validated'
47
-              onClickItem={() => this.setState({activeFileType: 'file'})}
48
-            />
49
-            <FileItem
50
-              name='Discussions à propos du nouveau système de facturation'
51
-              type='chat'
52
-              status='canceled'
53
-              onClickItem={() => this.setState({activeFileType: 'chat'})}
54
-            />
55
-
56
-            <Folder>
57
-              <FileItem type='file' name='Facture 57839 - Société ABC - 01/09/2017' status='current' />
58
-              <FileItem type='file' name='Facture 57839 - Société ABC - 01/09/2017' status='current' />
59
-              <FileItem type='task' name='Editer la facture pour Phillipe GIRARD' status='validated' />
60
-
61
-              <Folder>
62
-                <FileItem type='chat' name='Discussions à propos du nouveau système de facturation' status='canceled' />
63
-                <FileItem type='file' name='Facture 57537 - Claudia Martin - 14/08/2017' status='validated' />
64
-              </Folder>
65
-
66
-              <FileItem name='Facture 57841 - Pierre Maurice - 06/06/2017' type='file' status='current' />
67
-              <FileItem type='file' name='Facture 57840 - Jean-michel Chevalier - 04/09/2017' status='validated' />
68
-              <FileItem name='Facture 57841 - Pierre Maurice - 06/06/2017' type='file' status='current' />
69
-
70
-              <Folder>
71
-                <FileItem type='chat' name='Discussions à propos du nouveau système de facturation' status='canceled' />
72
-                <FileItem type='file' name='Facture 57537 - Claudia Martin - 14/08/2017' status='validated' />
73
-              </Folder>
74
-            </Folder>
75
-          </div>
76
-
77
-          <DropdownCreateButton customClass='workspace__content__button mb-5' />
78
-
79
-          <PageText visible={this.state.activeFileType === 'file'} />
80
-          {/*
81
-          <Thread visible={this.state.activeFileType === 'chat'} />
82
-          */}
83
-        </PageContent>
84
-
85
-      </PageWrapper>
86
-    )
87
-  }
88
-}
89
-
90
-const mapStateToProps = ({ user }) => ({ user })
91
-export default connect(mapStateToProps)(Workspace)

+ 70 - 0
src/container/WorkspaceContent.jsx View File

@@ -0,0 +1,70 @@
1
+import React from 'react'
2
+import { connect } from 'react-redux'
3
+import Folder from '../component/Workspace/Folder.jsx'
4
+import FileItem from '../component/Workspace/FileItem.jsx'
5
+import FileItemHeader from '../component/Workspace/FileItemHeader.jsx'
6
+// import Thread from './Thread.jsx'
7
+import PageText from './PageText.jsx'
8
+import PageWrapper from '../component/common/layout/PageWrapper.jsx'
9
+import PageTitle from '../component/common/layout/PageTitle.jsx'
10
+import PageContent from '../component/common/layout/PageContent.jsx'
11
+import DropdownCreateButton from '../component/common/Input/DropdownCreateButton.jsx'
12
+import { getWorkspaceContent } from '../action-creator.async.js'
13
+
14
+class WorkspaceContent extends React.Component {
15
+  constructor (props) {
16
+    super(props)
17
+    this.state = {
18
+      activeFileType: ''
19
+    }
20
+  }
21
+
22
+  componentDidMount () {
23
+    this.props.dispatch(getWorkspaceContent(/* this.props.workspace.id */1))
24
+  }
25
+
26
+  render () {
27
+    const { workspace } = this.props
28
+
29
+    return (
30
+      <PageWrapper customeClass='workspace'>
31
+        <PageTitle
32
+          parentClass='workspace__header'
33
+          customClass='justify-content-between'
34
+          title={workspace.title}
35
+        >
36
+          <DropdownCreateButton parentClass='workspace__header__btnaddworkspace' />
37
+        </PageTitle>
38
+
39
+        <PageContent parentClass='workspace__content'>
40
+
41
+          <div className='workspace__content__fileandfolder folder__content active'>
42
+            <FileItemHeader />
43
+
44
+            { workspace.content.map(c => c.type === 'folder'
45
+              ? <Folder folderData={c} key={c.id} />
46
+              : <FileItem
47
+                name={c.title}
48
+                type={c.type}
49
+                status={c.status}
50
+                onClickItem={() => this.setState({activeFileType: 'file'})}
51
+                key={c.id}
52
+              />
53
+            )}
54
+          </div>
55
+
56
+          <DropdownCreateButton customClass='workspace__content__button mb-5' />
57
+
58
+          <PageText visible={this.state.activeFileType === 'file'} />
59
+          {/*
60
+          <Thread visible={this.state.activeFileType === 'chat'} />
61
+          */}
62
+        </PageContent>
63
+
64
+      </PageWrapper>
65
+    )
66
+  }
67
+}
68
+
69
+const mapStateToProps = ({ workspace }) => ({ workspace })
70
+export default connect(mapStateToProps)(WorkspaceContent)

+ 9 - 0
src/helper.js View File

@@ -4,3 +4,12 @@ export const FETCH_CONFIG = {
4 4
     'Content-Type': 'application/json'
5 5
   }
6 6
 }
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
+}

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

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

+ 2 - 0
src/reducer/user.js View File

@@ -6,6 +6,8 @@ import {
6 6
 export default function user (state = {
7 7
   isLoggedIn: false,
8 8
   username: '',
9
+  firstname: '',
10
+  lastname: '',
9 11
   email: ''
10 12
 }, action) {
11 13
   switch (action.type) {

+ 23 - 0
src/reducer/workspace.js View File

@@ -0,0 +1,23 @@
1
+import {
2
+  WORKSPACE
3
+} from '../action-creator.sync.js'
4
+
5
+const serializeWorkspace = data => ({
6
+  ...data,
7
+  ownerId: data.owner_id
8
+})
9
+
10
+export default function user (state = {
11
+  id: 0,
12
+  title: '',
13
+  ownerId: '',
14
+  content: []
15
+}, action) {
16
+  switch (action.type) {
17
+    case `Update/${WORKSPACE}`:
18
+      return serializeWorkspace(action.workspace)
19
+
20
+    default:
21
+      return state
22
+  }
23
+}