Browse Source

added login and workspace content loading from mockapi

Skylsmoi 7 years ago
parent
commit
a95fc01416

+ 5 - 4
dist/index.html View File

34
         var jsScript = document.createElement("script");
34
         var jsScript = document.createElement("script");
35
         jsScript.type = "text/javascript";
35
         jsScript.type = "text/javascript";
36
         jsScript.src = "https://cloud.tinymce.com/stable/tinymce.min.js?apiKey=dfdhxdokxj2wagzkbxfgysgh86d6rr9m3dln0172vo3shipc";
36
         jsScript.src = "https://cloud.tinymce.com/stable/tinymce.min.js?apiKey=dfdhxdokxj2wagzkbxfgysgh86d6rr9m3dln0172vo3shipc";
37
-        console.log("load the lib");
38
 
37
 
39
         jsScript.onload = function() {
38
         jsScript.onload = function() {
40
           function base64EncodeAndTinyMceInsert (files) {
39
           function base64EncodeAndTinyMceInsert (files) {
91
                 icon: 'mce-ico mce-i-image',
90
                 icon: 'mce-ico mce-i-image',
92
                 title: 'Image',
91
                 title: 'Image',
93
                 onclick: function () {
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
                   fileTag = document.createElement('input')
97
                   fileTag = document.createElement('input')
97
                   fileTag.id = 'hidden_tinymce_fileinput'
98
                   fileTag.id = 'hidden_tinymce_fileinput'
98
                   fileTag.type = 'file'
99
                   fileTag.type = 'file'
99
                   $('body').append(fileTag)
100
                   $('body').append(fileTag)
100
 
101
 
101
-                  $('#hidden_tinymce_fileinput').on('change', function () {
102
+                  hiddenTinyMceInput.on('change', function () {
102
                     base64EncodeAndTinyMceInsert($(this)[0].files)
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
 // res.jsonp(req.query)
11
 // res.jsonp(req.query)
12
 server.get('/echo', (req, res) => res.jsonp('gg'))
12
 server.get('/echo', (req, res) => res.jsonp('gg'))
13
 server.get('/login', (req, res) => res.jsonp(jsonDb.login))
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
 server.get('/user_logged', (req, res) => res.jsonp(jsonDb.user_logged))
14
 server.get('/user_logged', (req, res) => res.jsonp(jsonDb.user_logged))
19
 server.delete('/deletenodata', (req,res) => res.status(204).jsonp(''))
15
 server.delete('/deletenodata', (req,res) => res.status(204).jsonp(''))
20
 server.patch('/user', (req, res) => res.jsonp({lang: 'fr'}))
16
 server.patch('/user', (req, res) => res.jsonp({lang: 'fr'}))
21
-
22
 // server.put('/api/data/raw_materials_vendors/:vendorid', (req, res) => {
17
 // server.put('/api/data/raw_materials_vendors/:vendorid', (req, res) => {
23
 //  res.jsonp(jsonVendorColorData.vendorVariableData)
18
 //  res.jsonp(jsonVendorColorData.vendorVariableData)
24
 //   console.log(req.body)
19
 //   console.log(req.body)
25
 //   res.jsonp('gg')
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
 server.use(router)
29
 server.use(router)
29
 server.listen(GLOBAL_PORT, () => {
30
 server.listen(GLOBAL_PORT, () => {
30
   console.log('JSON Server is running on port : ' + GLOBAL_PORT)
31
   console.log('JSON Server is running on port : ' + GLOBAL_PORT)

+ 38 - 0
jsonserver/static_db.json View File

6
     "firstname": "Côme",
6
     "firstname": "Côme",
7
     "lastname": "Stoilenom",
7
     "lastname": "Stoilenom",
8
     "email": "osef@algoo.fr"
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
   USER_DATA,
4
   USER_DATA,
5
   USER_CONNECTED,
5
   USER_CONNECTED,
6
   updateUserConnected,
6
   updateUserConnected,
7
-  updateUserData
7
+  updateUserData,
8
+  WORKSPACE,
9
+  updateWorkspaceData
8
 } from './action-creator.sync.js'
10
 } from './action-creator.sync.js'
9
 
11
 
10
 /*
12
 /*
53
   return fetchResult
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
   const fetchUserLogin = await fetchWrapper({
65
   const fetchUserLogin = await fetchWrapper({
58
     url: 'http://localhost:3001/user/login',
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
     actionName: USER_LOGIN,
72
     actionName: USER_LOGIN,
61
     dispatch
73
     dispatch
62
   })
74
   })
92
 //   })
104
 //   })
93
 //   console.log('jsonResponseNoData', fetchResponseNoData)
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
 export const USER_CONNECTED = 'User/Connected'
4
 export const USER_CONNECTED = 'User/Connected'
5
 export const updateUserConnected = user => ({ type: `Update/${USER_CONNECTED}`, user })
5
 export const updateUserConnected = user => ({ type: `Update/${USER_CONNECTED}`, user })
6
 export const updateUserData = userData => ({ type: `Update/${USER_DATA}`, data: userData })
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
 
14
 
15
         <li className={classnames(`${props.customClass}__messagelist__item`, 'timeline__messagelist__item sended')}>
15
         <li className={classnames(`${props.customClass}__messagelist__item`, 'timeline__messagelist__item sended')}>
16
           <div className={classnames(`${props.customClass}__messagelist__item__avatar`, 'timeline__messagelist__item__avatar')}>
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
           </div>
18
           </div>
19
           <div
19
           <div
20
             className={classnames(`${props.customClass}__messagelist__item__createhour`, 'timeline__messagelist__item__createhour')}>
20
             className={classnames(`${props.customClass}__messagelist__item__createhour`, 'timeline__messagelist__item__createhour')}>
28
 
28
 
29
         <li className={classnames(`${props.customClass}__messagelist__item`, 'timeline__messagelist__item received')}>
29
         <li className={classnames(`${props.customClass}__messagelist__item`, 'timeline__messagelist__item received')}>
30
           <div className={classnames(`${props.customClass}__messagelist__item__avatar`, 'timeline__messagelist__item__avatar')}>
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
           </div>
32
           </div>
33
           <div
33
           <div
34
             className={classnames(`${props.customClass}__messagelist__item__createhour`, 'timeline__messagelist__item__createhour')}>
34
             className={classnames(`${props.customClass}__messagelist__item__createhour`, 'timeline__messagelist__item__createhour')}>
46
 
46
 
47
         <li className={classnames(`${props.customClass}__messagelist__version`, 'timeline__messagelist__version')}>
47
         <li className={classnames(`${props.customClass}__messagelist__version`, 'timeline__messagelist__version')}>
48
           <div className={classnames(`${props.customClass}__messagelist__version__btn`, 'timeline__messagelist__version__btn btn')}>
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
             version 3
50
             version 3
51
           </div>
51
           </div>
52
           <div className={classnames(`${props.customClass}__messagelist__version__date`, 'timeline__messagelist__version__date')}>
52
           <div className={classnames(`${props.customClass}__messagelist__version__date`, 'timeline__messagelist__version__date')}>
56
 
56
 
57
         <li className={classnames(`${props.customClass}__messagelist__item`, 'timeline__messagelist__item sended')}>
57
         <li className={classnames(`${props.customClass}__messagelist__item`, 'timeline__messagelist__item sended')}>
58
           <div className={classnames(`${props.customClass}__messagelist__item__avatar`, 'timeline__messagelist__item__avatar')}>
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
           </div>
60
           </div>
61
           <div
61
           <div
62
             className={classnames(`${props.customClass}__messagelist__item__createhour`, 'timeline__messagelist__item__createhour')}>
62
             className={classnames(`${props.customClass}__messagelist__item__createhour`, 'timeline__messagelist__item__createhour')}>
70
 
70
 
71
         <li className={classnames(`${props.customClass}__messagelist__item`, 'timeline__messagelist__item received')}>
71
         <li className={classnames(`${props.customClass}__messagelist__item`, 'timeline__messagelist__item received')}>
72
           <div className={classnames(`${props.customClass}__messagelist__item__avatar`, 'timeline__messagelist__item__avatar')}>
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
           </div>
74
           </div>
75
           <div
75
           <div
76
             className={classnames(`${props.customClass}__messagelist__item__createhour`, 'timeline__messagelist__item__createhour')}>
76
             className={classnames(`${props.customClass}__messagelist__item__createhour`, 'timeline__messagelist__item__createhour')}>
90
       <form className={classnames(`${props.customClass}__texteditor`, 'timeline__texteditor')}>
90
       <form className={classnames(`${props.customClass}__texteditor`, 'timeline__texteditor')}>
91
         <div
91
         <div
92
           className={classnames(`${props.customClass}__texteditor__simpletext`, 'timeline__texteditor__simpletext input-group')}>
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
           <div
98
           <div
97
             className={classnames(`${props.customClass}__texteditor__simpletext__icon`, 'timeline__texteditor__simpletext__icon input-group-addon')}>
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
           </div>
101
           </div>
100
         </div>
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
         </div>
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
           <button
107
           <button
108
             type='submit'
108
             type='submit'
109
             className={classnames(`${props.customClass}__texteditor__submit__btn`, 'timeline__texteditor__submit__btn btn')}
109
             className={classnames(`${props.customClass}__texteditor__submit__btn`, 'timeline__texteditor__submit__btn btn')}
110
           >
110
           >
111
             Envoyer
111
             Envoyer
112
             <div className={classnames(`${props.customClass}__texteditor__submit__btn__icon`, 'timeline__texteditor__submit__btn__icon')}>
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
             </div>
114
             </div>
115
           </button>
115
           </button>
116
         </div>
116
         </div>

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

1
 import React from 'react'
1
 import React from 'react'
2
 import PropTypes from 'prop-types'
2
 import PropTypes from 'prop-types'
3
 import classnames from 'classnames'
3
 import classnames from 'classnames'
4
+import { FILE_TYPE } from '../../helper.js'
4
 
5
 
5
 const FileItem = props => {
6
 const FileItem = props => {
6
   const iconType = (() => {
7
   const iconType = (() => {
7
     switch (props.type) {
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
         return 'fa fa-file-text-o docandfile-color'
14
         return 'fa fa-file-text-o docandfile-color'
10
-      case 'chat':
15
+      case FILE_TYPE.THREAD:
11
         return 'fa fa-comments talk-color'
16
         return 'fa fa-comments talk-color'
12
-      case 'task':
17
+      case FILE_TYPE.TASK:
13
         return 'fa fa-list-ul task-color'
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
 import React, { Component } from 'react'
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
 class Folder extends Component {
8
 class Folder extends Component {
8
   constructor (props) {
9
   constructor (props) {
20
   }
21
   }
21
 
22
 
22
   render () {
23
   render () {
24
+    const { title, content } = this.props.folderData
23
     return (
25
     return (
24
-      <div className={'folder' + (this.state.open ? ' active' : '')}>
26
+      <div className={classnames('folder', {'active': this.state.open})}>
25
         <div className='folder__header' onClick={this.handleClickToggleFolder}>
27
         <div className='folder__header' onClick={this.handleClickToggleFolder}>
26
           <div className='folder__header__triangleborder'>
28
           <div className='folder__header__triangleborder'>
27
             <div className='folder__header__triangleborder__triangle' />
29
             <div className='folder__header__triangleborder__triangle' />
31
               <i className='fa fa-folder-open-o' />
33
               <i className='fa fa-folder-open-o' />
32
             </div>
34
             </div>
33
             <div className='folder__header__name__text'>
35
             <div className='folder__header__name__text'>
34
-              Dossier Facture
36
+              { title }
35
             </div>
37
             </div>
36
             <div className='folder__header__name__addbtn' onClick={this.handleClickNewFile}>
38
             <div className='folder__header__name__addbtn' onClick={this.handleClickNewFile}>
37
               <div className='folder__header__name__addbtn__text btn btn-primary'>
39
               <div className='folder__header__name__addbtn__text btn btn-primary'>
52
         </div>
54
         </div>
53
 
55
 
54
         <div className='folder__content'>
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
         </div>
67
         </div>
57
       </div>
68
       </div>
58
     )
69
     )
60
 }
71
 }
61
 
72
 
62
 export default Folder
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
 const PopinFixedContent = props => {
5
 const PopinFixedContent = props => {
6
   return (
6
   return (
7
     <div className={classnames('wsFileGeneric__contentpage', `${props.customClass}`)}>
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
       <div className={classnames('wsFileGeneric__wrapper', `${props.customClass}__wrapper`)}>
10
       <div className={classnames('wsFileGeneric__wrapper', `${props.customClass}__wrapper`)}>
12
         {props.children}
11
         {props.children}
18
 export default PopinFixedContent
17
 export default PopinFixedContent
19
 
18
 
20
 PopinFixedContent.propTypes = {
19
 PopinFixedContent.propTypes = {
21
-
20
+  customClass: PropTypes.string
22
 }
21
 }

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

1
 import React from 'react'
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
 const PopinFixedOption = props => {
5
 const PopinFixedOption = props => {
6
   return (
6
   return (

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

27
 
27
 
28
   handleClickSubmit = () => {
28
   handleClickSubmit = () => {
29
     const { history, dispatch } = this.props
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
     .then(() => history.push('/'))
33
     .then(() => history.push('/'))
34
   }
34
   }
35
 
35
 

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

5
 import Sidebar from './Sidebar.jsx'
5
 import Sidebar from './Sidebar.jsx'
6
 import Login from './Login.jsx'
6
 import Login from './Login.jsx'
7
 import Page from './Page.jsx'
7
 import Page from './Page.jsx'
8
-import Workspace from './Workspace.jsx'
8
+import WorkspaceContent from './WorkspaceContent.jsx'
9
 import {
9
 import {
10
   Route,
10
   Route,
11
   withRouter
11
   withRouter
12
 } from 'react-router-dom'
12
 } from 'react-router-dom'
13
 import PrivateRoute from './PrivateRoute.jsx'
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
 class Tracim extends React.Component {
26
 class Tracim extends React.Component {
16
   render () {
27
   render () {
17
     const { location } = this.props
28
     const { location } = this.props
21
 
32
 
22
         <Route path='/login' component={Login} />
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
           <PrivateRoute path='/page' component={Page} />
38
           <PrivateRoute path='/page' component={Page} />
31
 
39
 
32
-        </div>
40
+        </SidebarWrapper>
33
 
41
 
34
         <Footer />
42
         <Footer />
35
       </div>
43
       </div>

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

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

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
     'Content-Type': 'application/json'
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
 import { combineReducers } from 'redux'
1
 import { combineReducers } from 'redux'
2
 import user from './user.js'
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
 export default rootReducer
7
 export default rootReducer

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

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

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

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
+}