Browse Source

added sidebar sub menu + bugfix

Skylsmoi 6 years ago
parent
commit
80fab14e27

+ 9 - 6
src/action-creator.async.js View File

@@ -12,11 +12,11 @@ import {
12 12
   updateUserData,
13 13
   setUserRole,
14 14
   WORKSPACE,
15
-  updateWorkspaceData,
15
+  setWorkspaceData,
16 16
   WORKSPACE_LIST,
17 17
   updateWorkspaceListData,
18 18
   APP_LIST,
19
-  setAppList
19
+  setAppList, setWorkspaceListIsOpenInSidebar
20 20
 } from './action-creator.sync.js'
21 21
 
22 22
 /*
@@ -143,24 +143,27 @@ export const updateUserLang = newLang => async dispatch => { // unused
143 143
 //   console.log('jsonResponseNoData', fetchResponseNoData)
144 144
 // }
145 145
 
146
-export const getWorkspaceList = userId => async dispatch => {
146
+export const getWorkspaceList = (userId, workspaceIdToOpen) => async dispatch => {
147 147
   const fetchGetWorkspaceList = await fetchWrapper({
148 148
     url: `${FETCH_CONFIG.apiUrl}/user/${userId}/workspace`,
149 149
     param: {...FETCH_CONFIG.header, method: 'GET'},
150 150
     actionName: WORKSPACE_LIST,
151 151
     dispatch
152 152
   })
153
-  if (fetchGetWorkspaceList.status === 200) dispatch(updateWorkspaceListData(fetchGetWorkspaceList.json))
153
+  if (fetchGetWorkspaceList.status === 200) {
154
+    dispatch(updateWorkspaceListData(fetchGetWorkspaceList.json))
155
+    dispatch(setWorkspaceListIsOpenInSidebar(workspaceIdToOpen, true))
156
+  }
154 157
 }
155 158
 
156
-export const getWorkspaceContent = workspaceId => async dispatch => {
159
+export const getWorkspaceContent = (workspaceId, filterStr) => async dispatch => {
157 160
   const fetchGetWorkspaceContent = await fetchWrapper({
158 161
     url: `${FETCH_CONFIG.apiUrl}/workspace/${workspaceId}`,
159 162
     param: {...FETCH_CONFIG.header, method: 'GET'},
160 163
     actionName: WORKSPACE,
161 164
     dispatch
162 165
   })
163
-  if (fetchGetWorkspaceContent.status === 200) dispatch(updateWorkspaceData(fetchGetWorkspaceContent.json))
166
+  if (fetchGetWorkspaceContent.status === 200) dispatch(setWorkspaceData(fetchGetWorkspaceContent.json, filterStr))
164 167
 }
165 168
 
166 169
 export const getAppList = () => async dispatch => {

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

@@ -12,11 +12,12 @@ export const updateUserWorkspaceSubscriptionNotif = (workspaceId, subscriptionNo
12 12
   ({ type: `Update/${USER_ROLE}/SubscriptionNotif`, workspaceId, subscriptionNotif })
13 13
 
14 14
 export const WORKSPACE = 'Workspace'
15
-export const updateWorkspaceData = workspace => ({ type: `Update/${WORKSPACE}`, workspace })
15
+export const setWorkspaceData = (workspace, filterStr = '') => ({ type: `Set/${WORKSPACE}`, workspace, filterStr })
16
+export const updateWorkspaceFilter = filterList => ({ type: `Update/${WORKSPACE}/Filter`, filterList })
16 17
 
17 18
 export const WORKSPACE_LIST = 'WorkspaceList'
18 19
 export const updateWorkspaceListData = workspaceList => ({ type: `Update/${WORKSPACE_LIST}`, workspaceList })
19
-export const setWorkspaceListisOpenInSidebar = (workspaceId, isOpenInSidebar) => ({ type: `Set/${WORKSPACE_LIST}/isOpenInSidebar`, workspaceId, isOpenInSidebar })
20
+export const setWorkspaceListIsOpenInSidebar = (workspaceId, isOpenInSidebar) => ({ type: `Set/${WORKSPACE_LIST}/isOpenInSidebar`, workspaceId, isOpenInSidebar })
20 21
 
21 22
 export const FILE_CONTENT = 'FileContent'
22 23
 export const setActiveFileContentActive = file => ({ type: `Set/${FILE_CONTENT}/Active`, file })

+ 20 - 59
src/component/Sidebar/WorkspaceListItem.jsx View File

@@ -1,5 +1,6 @@
1 1
 import React from 'react'
2
-// import classnames from 'classnames'
2
+import classnames from 'classnames'
3
+import { translate } from 'react-i18next'
3 4
 import PropTypes from 'prop-types'
4 5
 import AnimateHeight from 'react-animate-height'
5 6
 
@@ -72,7 +73,6 @@ const WorkspaceListItem = props => {
72 73
           </li>
73 74
 
74 75
           <li className='sidebar__navigation__workspace__item__submenu__dropdown'>
75
-
76 76
             <div className='dropdown__icon'>
77 77
               <i className='fa fa-signal dashboard-color' />
78 78
             </div>
@@ -86,61 +86,26 @@ const WorkspaceListItem = props => {
86 86
             </div>
87 87
           </li>
88 88
 
89
-          <li className='sidebar__navigation__workspace__item__submenu__dropdown'>
90
-
91
-            <div className='dropdown__icon'>
92
-              <i className='fa fa-list-ul task-color' />
93
-            </div>
94
-
95
-            <div className='sidebar__navigation__workspace__item__submenu__dropdown__showdropdown'>
96
-
97
-              <div className='dropdown__title' id='navbarDropdown'>
98
-                <div className='dropdown__title__text'>
99
-                  Liste de tâches
100
-                </div>
101
-              </div>
102
-            </div>
103
-          </li>
104
-
105
-          <li className='sidebar__navigation__workspace__item__submenu__dropdown'>
106
-
107
-            <div className='dropdown__icon'>
108
-              <i className='fa fa-folder-o docandfile-color' />
109
-            </div>
110
-
111
-            <div
112
-              className='sidebar__navigation__workspace__item__submenu__dropdown__showdropdown'
113
-              aria-haspopup='true'
114
-              aria-expanded='false'
89
+          { Object.keys(props.app).map(a =>
90
+            <li
91
+              className={classnames('sidebar__navigation__workspace__item__submenu__dropdown', {'activeFilter': props.activeFilterList.includes(a)})}
92
+              onClick={() => props.onClickContentFilter(props.wsId, a)}
93
+              key={a}
115 94
             >
116
-
117
-              <div className='dropdown__title' id='navbarDropdown'>
118
-                <div className='dropdown__title__text'>
119
-                  Documents & fichiers
120
-                </div>
95
+              <div className='dropdown__icon'>
96
+                <i className={classnames(props.app[a].icon)} style={{backgroudColor: props.app[a].color}} />
121 97
               </div>
122
-            </div>
123
-          </li>
124
-
125
-          <li className='sidebar__navigation__workspace__item__submenu__dropdown'>
126
-
127
-            <div className='dropdown__icon'>
128
-              <i className='fa fa-comments talk-color' />
129
-            </div>
130 98
 
131
-            <div
132
-              className='sidebar__navigation__workspace__item__submenu__dropdown__showdropdown'
133
-              aria-haspopup='true'
134
-              aria-expanded='false'
135
-            >
99
+              <div className='sidebar__navigation__workspace__item__submenu__dropdown__showdropdown'>
136 100
 
137
-              <div className='dropdown__title' id='navbarDropdown'>
138
-                <div className='dropdown__title__text'>
139
-                  Discussions
101
+                <div className='dropdown__title' id='navbarDropdown'>
102
+                  <div className='dropdown__title__text'>
103
+                    { props.app[a].label[props.lang.id] }
104
+                  </div>
140 105
                 </div>
141 106
               </div>
142
-            </div>
143
-          </li>
107
+            </li>
108
+          )}
144 109
 
145 110
           <li className='sidebar__navigation__workspace__item__submenu__dropdown'>
146 111
 
@@ -148,13 +113,8 @@ const WorkspaceListItem = props => {
148 113
               <i className='fa fa-calendar calendar-color' />
149 114
             </div>
150 115
 
151
-            <div
152
-              className='sidebar__navigation__workspace__item__submenu__dropdown__showdropdown'
153
-              aria-haspopup='true'
154
-              aria-expanded='false'
155
-            >
156
-
157
-              <div className='dropdown__title' id='navbarDropdown'>
116
+            <div className='sidebar__navigation__workspace__item__submenu__dropdown__showdropdown'>
117
+              <div className='dropdown__title'>
158 118
                 <div className='dropdown__title__text'>
159 119
                   Calendrier
160 120
                 </div>
@@ -167,11 +127,12 @@ const WorkspaceListItem = props => {
167 127
   )
168 128
 }
169 129
 
170
-export default WorkspaceListItem
130
+export default translate()(WorkspaceListItem)
171 131
 
172 132
 WorkspaceListItem.propTypes = {
173 133
   number: PropTypes.number.isRequired,
174 134
   name: PropTypes.string.isRequired,
135
+  app: PropTypes.object,
175 136
   onClickTitle: PropTypes.func,
176 137
   onClickAllContent: PropTypes.func,
177 138
   isOpenInSidebar: PropTypes.bool

+ 20 - 15
src/container/Account.jsx View File

@@ -1,5 +1,6 @@
1 1
 import React from 'react'
2 2
 import { connect } from 'react-redux'
3
+import Sidebar from './Sidebar.jsx'
3 4
 import PageWrapper from '../component/common/layout/PageWrapper.jsx'
4 5
 import PageTitle from '../component/common/layout/PageTitle.jsx'
5 6
 import PageContent from '../component/common/layout/PageContent.jsx'
@@ -73,27 +74,31 @@ class Account extends React.Component {
73 74
     })()
74 75
 
75 76
     return (
76
-      <PageWrapper customClass='account'>
77
-        <PageTitle
78
-          parentClass={'account'}
79
-          title={'Mon Compte'}
80
-        />
77
+      <div className='sidebarpagecontainer'>
78
+        <Sidebar />
81 79
 
82
-        <PageContent parentClass='account'>
83
-          <UserInfo user={this.props.user} />
80
+        <PageWrapper customClass='account'>
81
+          <PageTitle
82
+            parentClass={'account'}
83
+            title={'Mon Compte'}
84
+          />
85
+
86
+          <PageContent parentClass='account'>
87
+            <UserInfo user={this.props.user} />
84 88
 
85
-          <Delimiter customClass={'account__delimiter'} />
89
+            <Delimiter customClass={'account__delimiter'} />
86 90
 
87
-          <div className='account__userpreference'>
88
-            <MenuSubComponent subMenuList={this.state.subComponentMenu} onClickMenuItem={this.handleClickSubComponentMenuItem} />
91
+            <div className='account__userpreference'>
92
+              <MenuSubComponent subMenuList={this.state.subComponentMenu} onClickMenuItem={this.handleClickSubComponentMenuItem} />
89 93
 
90
-            <div className='account__userpreference__setting'>
91
-              { subComponent }
94
+              <div className='account__userpreference__setting'>
95
+                { subComponent }
96
+              </div>
92 97
             </div>
93
-          </div>
94 98
 
95
-        </PageContent>
96
-      </PageWrapper>
99
+          </PageContent>
100
+        </PageWrapper>
101
+      </div>
97 102
     )
98 103
   }
99 104
 }

+ 271 - 266
src/container/Dashboard.jsx View File

@@ -1,367 +1,372 @@
1 1
 import React, { Component } from 'react'
2
+import Sidebar from './Sidebar.jsx'
2 3
 import listMemberBtn from '../img/listmemberbtn.png'
3 4
 import imgProfil from '../img/imgProfil.png'
4 5
 
5 6
 class Dashboard extends Component {
6 7
   render () {
7 8
     return (
8
-      <div className='dashboard'>
9
-        <div className='container-fluid nopadding'>
10
-          <div className='pageTitleGeneric'>
11
-            <div className='pageTitleGeneric__title dashboard__title'>
12
-              Dashboard
13
-            </div>
14
-          </div>
15
-
16
-          <div className='dashboard__wkswrapper'>
17
-            <div className='dashboard__workspace'>
18
-              <div className='dashboard__workspace__title'>
19
-                Nouvelle ligne directive sur le nouveau design de Tracim
20
-              </div>
21
-
22
-              <div className='dashboard__workspace__detail'>
23
-                Ut in et sit adipisicing mollit amet ut exercitation proident laborum duis occaecat eu aute qui ut.
24
-                Dolore veniam eu consectetur occaecat est elit dolor nulla est ut amet do reprehenderit eiusmod tempor.
9
+      <div className='sidebarpagecontainer'>
10
+        <Sidebar />
11
+
12
+        <div className='dashboard'>
13
+          <div className='container-fluid nopadding'>
14
+            <div className='pageTitleGeneric'>
15
+              <div className='pageTitleGeneric__title dashboard__title'>
16
+                Dashboard
25 17
               </div>
26 18
             </div>
27
-            <div className='dashboard__userstatut'>
28 19
 
29
-              <div className='dashboard__userstatut__role'>
30
-                <div className='dashboard__userstatut__role__text'>
31
-                  Hi ! Alexi, vous êtes actuellement
32
-                </div>
33
-                <div className='dashboard__userstatut__role__rank'>
34
-                  <div className='dashboard__userstatut__role__rank__icon'>
35
-                    <i className='fa fa-graduation-cap' />
36
-                  </div>
37
-                  <div className='dashboard__userstatut__role__rank__rolename'>
38
-                    Gestionnaire de projet
39
-                  </div>
20
+            <div className='dashboard__wkswrapper'>
21
+              <div className='dashboard__workspace'>
22
+                <div className='dashboard__workspace__title'>
23
+                  Nouvelle ligne directive sur le nouveau design de Tracim
40 24
                 </div>
41
-              </div>
42 25
 
43
-              <div className='dashboard__userstatut__notification'>
44
-                <div className='dashboard__userstatut__notification__text'>
45
-                  Vous êtes abonné(e) aux notifications de ce workspace
46
-                </div>
47
-                <div className='dashboard__userstatut__notification__btn btn btn-primary'>
48
-                  Changer de statut
26
+                <div className='dashboard__workspace__detail'>
27
+                  Ut in et sit adipisicing mollit amet ut exercitation proident laborum duis occaecat eu aute qui ut.
28
+                  Dolore veniam eu consectetur occaecat est elit dolor nulla est ut amet do reprehenderit eiusmod tempor.
49 29
                 </div>
30
+              </div>
31
+              <div className='dashboard__userstatut'>
50 32
 
51
-                <div className='dashboard__userstatut__notification__subscribe dropdown'>
52
-                  <button className='dashboard__userstatut__notification__subscribe__btn btn btn-primary dropdown-toggle' type='button' id='dropdownMenuButton' data-toggle='dropdown' aria-haspopup='true' aria-expanded='false'>
53
-                    Abonné(e)
54
-                  </button>
55
-                  <div className='dashboard__userstatut__notification__subscribe__submenu dropdown-menu'>
56
-                    <div className='dashboard__userstatut__notification__subscribe__submenu__item dropdown-item'>Abonné(e)
33
+                <div className='dashboard__userstatut__role'>
34
+                  <div className='dashboard__userstatut__role__text'>
35
+                    Hi ! Alexi, vous êtes actuellement
36
+                  </div>
37
+                  <div className='dashboard__userstatut__role__rank'>
38
+                    <div className='dashboard__userstatut__role__rank__icon'>
39
+                      <i className='fa fa-graduation-cap' />
57 40
                     </div>
58
-                    <div className='dashboard__userstatut__notification__subscribe__submenu__item dropdown-item dropdown-item'>Non Abonné(e)
41
+                    <div className='dashboard__userstatut__role__rank__rolename'>
42
+                      Gestionnaire de projet
59 43
                     </div>
60 44
                   </div>
61 45
                 </div>
62
-              </div>
63
-            </div>
64
-          </div>
65 46
 
66
-          <div className='dashboard__calltoaction'>
67
-            <div className='dashboard__calltoaction__button btnaction thread'>
68
-              <div className='dashboard__calltoaction__button__text'>
69
-                <div className='dashboard__calltoaction__button__text__icon'>
70
-                  <i className='fa fa-comments-o' />
71
-                </div>
72
-                <div className='dashboard__calltoaction__button__text__title'>
73
-                  Débuter une nouvelle discussion
74
-                </div>
75
-              </div>
76
-            </div>
47
+                <div className='dashboard__userstatut__notification'>
48
+                  <div className='dashboard__userstatut__notification__text'>
49
+                    Vous êtes abonné(e) aux notifications de ce workspace
50
+                  </div>
51
+                  <div className='dashboard__userstatut__notification__btn btn btn-primary'>
52
+                    Changer de statut
53
+                  </div>
77 54
 
78
-            <div className='dashboard__calltoaction__button btnaction writefile'>
79
-              <div className='dashboard__calltoaction__button__text'>
80
-                <div className='dashboard__calltoaction__button__text__icon'>
81
-                  <i className='fa fa-file-text-o' />
82
-                </div>
83
-                <div className='dashboard__calltoaction__button__text__title'>
84
-                  Rédiger un document
55
+                  <div className='dashboard__userstatut__notification__subscribe dropdown'>
56
+                    <button className='dashboard__userstatut__notification__subscribe__btn btn btn-primary dropdown-toggle' type='button' id='dropdownMenuButton' data-toggle='dropdown' aria-haspopup='true' aria-expanded='false'>
57
+                      Abonné(e)
58
+                    </button>
59
+                    <div className='dashboard__userstatut__notification__subscribe__submenu dropdown-menu'>
60
+                      <div className='dashboard__userstatut__notification__subscribe__submenu__item dropdown-item'>Abonné(e)
61
+                      </div>
62
+                      <div className='dashboard__userstatut__notification__subscribe__submenu__item dropdown-item dropdown-item'>Non Abonné(e)
63
+                      </div>
64
+                    </div>
65
+                  </div>
85 66
                 </div>
86 67
               </div>
87 68
             </div>
88 69
 
89
-            <div className='dashboard__calltoaction__button btnaction importfile'>
90
-              <div className='dashboard__calltoaction__button__text'>
91
-                <div className='dashboard__calltoaction__button__text__icon'>
92
-                  <i className='fa fa-paperclip' />
93
-                </div>
94
-                <div className='dashboard__calltoaction__button__text__title'>
95
-                  Importer un fichier
70
+            <div className='dashboard__calltoaction'>
71
+              <div className='dashboard__calltoaction__button btnaction thread'>
72
+                <div className='dashboard__calltoaction__button__text'>
73
+                  <div className='dashboard__calltoaction__button__text__icon'>
74
+                    <i className='fa fa-comments-o' />
75
+                  </div>
76
+                  <div className='dashboard__calltoaction__button__text__title'>
77
+                    Débuter une nouvelle discussion
78
+                  </div>
96 79
                 </div>
97 80
               </div>
98
-            </div>
99 81
 
100
-            <div className='dashboard__calltoaction__button btnaction calendar'>
101
-              <div className='dashboard__calltoaction__button__text'>
102
-                <div className='dashboard__calltoaction__button__text__icon'>
103
-                  <i className='fa fa-calendar' />
104
-                </div>
105
-                <div className='dashboard__calltoaction__button__text__title'>
106
-                  Voir le Calendrier
82
+              <div className='dashboard__calltoaction__button btnaction writefile'>
83
+                <div className='dashboard__calltoaction__button__text'>
84
+                  <div className='dashboard__calltoaction__button__text__icon'>
85
+                    <i className='fa fa-file-text-o' />
86
+                  </div>
87
+                  <div className='dashboard__calltoaction__button__text__title'>
88
+                    Rédiger un document
89
+                  </div>
107 90
                 </div>
108 91
               </div>
109
-            </div>
110 92
 
111
-            <div className='dashboard__calltoaction__button btnaction explore'>
112
-              <div className='dashboard__calltoaction__button__text'>
113
-                <div className='dashboard__calltoaction__button__text__icon'>
114
-                  <i className='fa fa-folder-open-o' />
115
-                </div>
116
-                <div className='dashboard__calltoaction__button__text__title'>
117
-                  Explorer le Workspace
93
+              <div className='dashboard__calltoaction__button btnaction importfile'>
94
+                <div className='dashboard__calltoaction__button__text'>
95
+                  <div className='dashboard__calltoaction__button__text__icon'>
96
+                    <i className='fa fa-paperclip' />
97
+                  </div>
98
+                  <div className='dashboard__calltoaction__button__text__title'>
99
+                    Importer un fichier
100
+                  </div>
118 101
                 </div>
119 102
               </div>
120
-            </div>
121
-          </div>
122
-
123
-          <div className='dashboard__wksinfo'>
124
-            <div className='dashboard__activity'>
125
-              <div className='dashboard__activity__header'>
126
-                <div className='dashboard__activity__header__title subTitle'>
127
-                  Activité récente
128
-                </div>
129 103
 
130
-                <div className='dashboard__activity__header__allread btn btn-primary'>
131
-                  Tout marquer comme lu
132
-                </div>
133
-              </div>
134
-              <div className='dashboard__activity__wrapper'>
135
-                <div className='dashboard__activity__workspace'>
136
-                  <div className='dashboard__activity__workspace__icon'>
137
-                    <i className='fa fa-comments-o' />
104
+              <div className='dashboard__calltoaction__button btnaction calendar'>
105
+                <div className='dashboard__calltoaction__button__text'>
106
+                  <div className='dashboard__calltoaction__button__text__icon'>
107
+                    <i className='fa fa-calendar' />
138 108
                   </div>
139
-                  <div className='dashboard__activity__workspace__name'>
140
-                    <span>Workspace 1</span>
109
+                  <div className='dashboard__calltoaction__button__text__title'>
110
+                    Voir le Calendrier
141 111
                   </div>
142 112
                 </div>
113
+              </div>
143 114
 
144
-                <div className='dashboard__activity__workspace'>
145
-                  <div className='dashboard__activity__workspace__icon'>
146
-                    <i className='fa fa-list-ul' />
115
+              <div className='dashboard__calltoaction__button btnaction explore'>
116
+                <div className='dashboard__calltoaction__button__text'>
117
+                  <div className='dashboard__calltoaction__button__text__icon'>
118
+                    <i className='fa fa-folder-open-o' />
147 119
                   </div>
148
-                  <div className='dashboard__activity__workspace__name'>
149
-                    Workspace 2
120
+                  <div className='dashboard__calltoaction__button__text__title'>
121
+                    Explorer le Workspace
150 122
                   </div>
151 123
                 </div>
124
+              </div>
125
+            </div>
152 126
 
153
-                <div className='dashboard__activity__workspace'>
154
-                  <div className='dashboard__activity__workspace__icon'>
155
-                    <i className='fa fa-list-ul' />
127
+            <div className='dashboard__wksinfo'>
128
+              <div className='dashboard__activity'>
129
+                <div className='dashboard__activity__header'>
130
+                  <div className='dashboard__activity__header__title subTitle'>
131
+                    Activité récente
156 132
                   </div>
157
-                  <div className='dashboard__activity__workspace__name'>
158
-                    Workspace 3
133
+
134
+                  <div className='dashboard__activity__header__allread btn btn-primary'>
135
+                    Tout marquer comme lu
159 136
                   </div>
160 137
                 </div>
161
-
162
-                <div className='dashboard__activity__workspace'>
163
-                  <div className='dashboard__activity__workspace__icon'>
164
-                    <i className='fa fa-file-text-o' />
138
+                <div className='dashboard__activity__wrapper'>
139
+                  <div className='dashboard__activity__workspace'>
140
+                    <div className='dashboard__activity__workspace__icon'>
141
+                      <i className='fa fa-comments-o' />
142
+                    </div>
143
+                    <div className='dashboard__activity__workspace__name'>
144
+                      <span>Workspace 1</span>
145
+                    </div>
165 146
                   </div>
166
-                  <div className='dashboard__activity__workspace__name'>
167
-                    <span>Workspace 4</span>
147
+
148
+                  <div className='dashboard__activity__workspace'>
149
+                    <div className='dashboard__activity__workspace__icon'>
150
+                      <i className='fa fa-list-ul' />
151
+                    </div>
152
+                    <div className='dashboard__activity__workspace__name'>
153
+                      Workspace 2
154
+                    </div>
168 155
                   </div>
169
-                </div>
170 156
 
171
-                <div className='dashboard__activity__workspace'>
172
-                  <div className='dashboard__activity__workspace__icon'>
173
-                    <i className='fa fa-comments-o' />
157
+                  <div className='dashboard__activity__workspace'>
158
+                    <div className='dashboard__activity__workspace__icon'>
159
+                      <i className='fa fa-list-ul' />
160
+                    </div>
161
+                    <div className='dashboard__activity__workspace__name'>
162
+                      Workspace 3
163
+                    </div>
174 164
                   </div>
175
-                  <div className='dashboard__activity__workspace__name'>
176
-                    <span>Workspace 5</span>
165
+
166
+                  <div className='dashboard__activity__workspace'>
167
+                    <div className='dashboard__activity__workspace__icon'>
168
+                      <i className='fa fa-file-text-o' />
169
+                    </div>
170
+                    <div className='dashboard__activity__workspace__name'>
171
+                      <span>Workspace 4</span>
172
+                    </div>
177 173
                   </div>
178
-                </div>
179 174
 
180
-                <div className='dashboard__activity__workspace'>
181
-                  <div className='dashboard__activity__workspace__icon'>
182
-                    <i className='fa fa-file-text-o' />
175
+                  <div className='dashboard__activity__workspace'>
176
+                    <div className='dashboard__activity__workspace__icon'>
177
+                      <i className='fa fa-comments-o' />
178
+                    </div>
179
+                    <div className='dashboard__activity__workspace__name'>
180
+                      <span>Workspace 5</span>
181
+                    </div>
183 182
                   </div>
184
-                  <div className='dashboard__activity__workspace__name'>
185
-                    Workspace 6
183
+
184
+                  <div className='dashboard__activity__workspace'>
185
+                    <div className='dashboard__activity__workspace__icon'>
186
+                      <i className='fa fa-file-text-o' />
187
+                    </div>
188
+                    <div className='dashboard__activity__workspace__name'>
189
+                      Workspace 6
190
+                    </div>
186 191
                   </div>
187
-                </div>
188 192
 
189
-                <div className='dashboard__activity__more d-flex flex-row-reverse'>
190
-                  <div className='dashboard__activity__more__btn btn btn-primary'>
191
-                    Voir plus
193
+                  <div className='dashboard__activity__more d-flex flex-row-reverse'>
194
+                    <div className='dashboard__activity__more__btn btn btn-primary'>
195
+                      Voir plus
196
+                    </div>
192 197
                   </div>
193 198
                 </div>
194 199
               </div>
195
-            </div>
196 200
 
197
-            <div className='dashboard__memberlist'>
201
+              <div className='dashboard__memberlist'>
198 202
 
199
-              <div className='dashboard__memberlist__title subTitle'>
200
-                Liste des membres
201
-              </div>
203
+                <div className='dashboard__memberlist__title subTitle'>
204
+                  Liste des membres
205
+                </div>
202 206
 
203
-              <div className='dashboard__memberlist__wrapper'>
204
-                <ul className='dashboard__memberlist__list'>
205
-                  <li className='dashboard__memberlist__list__item'>
206
-                    <div className='dashboard__memberlist__list__item__avatar'>
207
-                      <img src={imgProfil} alt='avatar' />
208
-                    </div>
209
-                    <div className='dashboard__memberlist__list__item__info'>
210
-                      <div className='dashboard__memberlist__list__item__info__name'>
211
-                        Jean Dupont
207
+                <div className='dashboard__memberlist__wrapper'>
208
+                  <ul className='dashboard__memberlist__list'>
209
+                    <li className='dashboard__memberlist__list__item'>
210
+                      <div className='dashboard__memberlist__list__item__avatar'>
211
+                        <img src={imgProfil} alt='avatar' />
212 212
                       </div>
213
-                      <div className='dashboard__memberlist__list__item__info__role'>
214
-                        Responsable
213
+                      <div className='dashboard__memberlist__list__item__info'>
214
+                        <div className='dashboard__memberlist__list__item__info__name'>
215
+                          Jean Dupont
216
+                        </div>
217
+                        <div className='dashboard__memberlist__list__item__info__role'>
218
+                          Responsable
219
+                        </div>
215 220
                       </div>
216
-                    </div>
217
-                  </li>
221
+                    </li>
218 222
 
219
-                  <li className='dashboard__memberlist__list__item'>
220
-                    <div className='dashboard__memberlist__list__item__avatar'>
221
-                      <img src={imgProfil} alt='avatar' />
222
-                    </div>
223
-                    <div className='dashboard__memberlist__list__item__info'>
224
-                      <div className='dashboard__memberlist__list__item__info__name'>
225
-                        Aldwin Vinel
223
+                    <li className='dashboard__memberlist__list__item'>
224
+                      <div className='dashboard__memberlist__list__item__avatar'>
225
+                        <img src={imgProfil} alt='avatar' />
226 226
                       </div>
227
-                      <div className='dashboard__memberlist__list__item__info__role'>
228
-                        lecteur
227
+                      <div className='dashboard__memberlist__list__item__info'>
228
+                        <div className='dashboard__memberlist__list__item__info__name'>
229
+                          Aldwin Vinel
230
+                        </div>
231
+                        <div className='dashboard__memberlist__list__item__info__role'>
232
+                          lecteur
233
+                        </div>
229 234
                       </div>
230
-                    </div>
231
-                  </li>
235
+                    </li>
232 236
 
233
-                  <li className='dashboard__memberlist__list__item'>
234
-                    <div className='dashboard__memberlist__list__item__avatar'>
235
-                      <img src={imgProfil} alt='avatar' />
236
-                    </div>
237
-                    <div className='dashboard__memberlist__list__item__info'>
238
-                      <div className='dashboard__memberlist__list__item__info__name'>
239
-                        William Himme
237
+                    <li className='dashboard__memberlist__list__item'>
238
+                      <div className='dashboard__memberlist__list__item__avatar'>
239
+                        <img src={imgProfil} alt='avatar' />
240 240
                       </div>
241
-                      <div className='dashboard__memberlist__list__item__info__role'>
242
-                        contributeur
241
+                      <div className='dashboard__memberlist__list__item__info'>
242
+                        <div className='dashboard__memberlist__list__item__info__name'>
243
+                          William Himme
244
+                        </div>
245
+                        <div className='dashboard__memberlist__list__item__info__role'>
246
+                          contributeur
247
+                        </div>
243 248
                       </div>
244
-                    </div>
245
-                  </li>
249
+                    </li>
246 250
 
247
-                  <li className='dashboard__memberlist__list__item'>
248
-                    <div className='dashboard__memberlist__list__item__avatar'>
249
-                      <img src={imgProfil} alt='avatar' />
250
-                    </div>
251
-                    <div className='dashboard__memberlist__list__item__info'>
252
-                      <div className='dashboard__memberlist__list__item__info__name'>
253
-                        Yacine Lite
251
+                    <li className='dashboard__memberlist__list__item'>
252
+                      <div className='dashboard__memberlist__list__item__avatar'>
253
+                        <img src={imgProfil} alt='avatar' />
254 254
                       </div>
255
-                      <div className='dashboard__memberlist__list__item__info__role'>
256
-                        Gestionnaire de contenu
255
+                      <div className='dashboard__memberlist__list__item__info'>
256
+                        <div className='dashboard__memberlist__list__item__info__name'>
257
+                          Yacine Lite
258
+                        </div>
259
+                        <div className='dashboard__memberlist__list__item__info__role'>
260
+                          Gestionnaire de contenu
261
+                        </div>
257 262
                       </div>
258
-                    </div>
259
-                  </li>
263
+                    </li>
260 264
 
261
-                  <li className='dashboard__memberlist__list__item'>
262
-                    <div className='dashboard__memberlist__list__item__avatar'>
263
-                      <img src={imgProfil} alt='avatar' />
264
-                    </div>
265
-                    <div className='dashboard__memberlist__list__item__info'>
266
-                      <div className='dashboard__memberlist__list__item__info__name'>
267
-                        Yacine Lite
265
+                    <li className='dashboard__memberlist__list__item'>
266
+                      <div className='dashboard__memberlist__list__item__avatar'>
267
+                        <img src={imgProfil} alt='avatar' />
268 268
                       </div>
269
-                      <div className='dashboard__memberlist__list__item__info__role'>
270
-                        Gestionnaire de contenu
269
+                      <div className='dashboard__memberlist__list__item__info'>
270
+                        <div className='dashboard__memberlist__list__item__info__name'>
271
+                          Yacine Lite
272
+                        </div>
273
+                        <div className='dashboard__memberlist__list__item__info__role'>
274
+                          Gestionnaire de contenu
275
+                        </div>
271 276
                       </div>
272
-                    </div>
273
-                  </li>
277
+                    </li>
274 278
 
275
-                  <li className='dashboard__memberlist__list__item'>
276
-                    <div className='dashboard__memberlist__list__item__avatar'>
277
-                      <img src={imgProfil} alt='avatar' />
278
-                    </div>
279
-                    <div className='dashboard__memberlist__list__item__info'>
280
-                      <div className='dashboard__memberlist__list__item__info__name'>
281
-                        Yacine Lite
279
+                    <li className='dashboard__memberlist__list__item'>
280
+                      <div className='dashboard__memberlist__list__item__avatar'>
281
+                        <img src={imgProfil} alt='avatar' />
282 282
                       </div>
283
-                      <div className='dashboard__memberlist__list__item__info__role'>
284
-                        Gestionnaire de contenu
283
+                      <div className='dashboard__memberlist__list__item__info'>
284
+                        <div className='dashboard__memberlist__list__item__info__name'>
285
+                          Yacine Lite
286
+                        </div>
287
+                        <div className='dashboard__memberlist__list__item__info__role'>
288
+                          Gestionnaire de contenu
289
+                        </div>
285 290
                       </div>
286
-                    </div>
287
-                  </li>
291
+                    </li>
288 292
 
289
-                </ul>
290
-                <div className='dashboard__memberlist__btnadd'>
291
-                  <div className='dashboard__memberlist__btnadd__button'>
292
-                    <div className='dashboard__memberlist__btnadd__button__avatar'>
293
-                      <img src={listMemberBtn} alt='avatar' />
294
-                    </div>
295
-                    <div className='dashboard__memberlist__btnadd__button__text'>
296
-                       Ajouter un membre
293
+                  </ul>
294
+                  <div className='dashboard__memberlist__btnadd'>
295
+                    <div className='dashboard__memberlist__btnadd__button'>
296
+                      <div className='dashboard__memberlist__btnadd__button__avatar'>
297
+                        <img src={listMemberBtn} alt='avatar' />
298
+                      </div>
299
+                      <div className='dashboard__memberlist__btnadd__button__text'>
300
+                         Ajouter un membre
301
+                      </div>
297 302
                     </div>
298 303
                   </div>
299
-                </div>
300 304
 
301
-                <form className='dashboard__memberlist__addmember'>
302
-                  <input type='text' className='dashboard__memberlist__addmember__name form-control' placeholder='Name' />
303
-                  <div className='dashboard__memberlist__addmember__role'>
304
-                    <div className='dashboard__memberlist__addmember__role__dropdown dropdown'>
305
-                      <button className='dashboard__memberlist__addmember__role__dropdown__button btn btn-primary dropdown-toggle' type='button' id='dropdownMenuButton' data-toggle='dropdown' aria-haspopup='true' aria-expanded='false'>
306
-                        Rôle du membre
307
-                      </button>
308
-                      <div className='dashboard__memberlist__addmember__role__dropdown__submenu dropdown-menu'>
309
-                        <div className='dashboard__memberlist__addmember__role__dropdown__submenu__item dropdown-item'>
310
-                          <div className='dashboard__memberlist__addmember__role__dropdown__submenu__item__icon'>
311
-                            <i className='fa fa-eye' />
305
+                  <form className='dashboard__memberlist__addmember'>
306
+                    <input type='text' className='dashboard__memberlist__addmember__name form-control' placeholder='Name' />
307
+                    <div className='dashboard__memberlist__addmember__role'>
308
+                      <div className='dashboard__memberlist__addmember__role__dropdown dropdown'>
309
+                        <button className='dashboard__memberlist__addmember__role__dropdown__button btn btn-primary dropdown-toggle' type='button' id='dropdownMenuButton' data-toggle='dropdown' aria-haspopup='true' aria-expanded='false'>
310
+                          Rôle du membre
311
+                        </button>
312
+                        <div className='dashboard__memberlist__addmember__role__dropdown__submenu dropdown-menu'>
313
+                          <div className='dashboard__memberlist__addmember__role__dropdown__submenu__item dropdown-item'>
314
+                            <div className='dashboard__memberlist__addmember__role__dropdown__submenu__item__icon'>
315
+                              <i className='fa fa-eye' />
316
+                            </div>
317
+                            Lecteur
312 318
                           </div>
313
-                          Lecteur
314
-                        </div>
315
-                        <div className='dashboard__memberlist__addmember__role__dropdown__submenu__item dropdown-item'>
316
-                          <div className='dashboard__memberlist__addmember__role__dropdown__submenu__item__icon'>
317
-                            <i className='fa fa-pencil' />
319
+                          <div className='dashboard__memberlist__addmember__role__dropdown__submenu__item dropdown-item'>
320
+                            <div className='dashboard__memberlist__addmember__role__dropdown__submenu__item__icon'>
321
+                              <i className='fa fa-pencil' />
322
+                            </div>
323
+                            contributeur
318 324
                           </div>
319
-                          contributeur
320
-                        </div>
321
-                        <div className='dashboard__memberlist__addmember__role__dropdown__submenu__item dropdown-item'>
322
-                          <div className='dashboard__memberlist__addmember__role__dropdown__submenu__item__icon'>
323
-                            <i className='fa fa-graduation-cap' />
325
+                          <div className='dashboard__memberlist__addmember__role__dropdown__submenu__item dropdown-item'>
326
+                            <div className='dashboard__memberlist__addmember__role__dropdown__submenu__item__icon'>
327
+                              <i className='fa fa-graduation-cap' />
328
+                            </div>
329
+                            Gestionnaire de contenu
324 330
                           </div>
325
-                          Gestionnaire de contenu
326
-                        </div>
327
-                        <div className='dashboard__memberlist__addmember__role__dropdown__submenu__item dropdown-item'>
328
-                          <div className='dashboard__memberlist__addmember__role__dropdown__submenu__item__icon'>
329
-                            <i className='fa fa-gavel' />
331
+                          <div className='dashboard__memberlist__addmember__role__dropdown__submenu__item dropdown-item'>
332
+                            <div className='dashboard__memberlist__addmember__role__dropdown__submenu__item__icon'>
333
+                              <i className='fa fa-gavel' />
334
+                            </div>
335
+                            Responsable
330 336
                           </div>
331
-                          Responsable
332 337
                         </div>
333 338
                       </div>
334 339
                     </div>
335
-                  </div>
336
-                  <input type='submit' className='dashboard__memberlist__addmember__submitbtn' />
337
-                </form>
340
+                    <input type='submit' className='dashboard__memberlist__addmember__submitbtn' />
341
+                  </form>
338 342
 
343
+                </div>
339 344
               </div>
340 345
             </div>
341
-          </div>
342 346
 
343
-          <div className='dashboard__webdav genericWebdav'>
347
+            <div className='dashboard__webdav genericWebdav'>
344 348
 
345
-            <div className='dashboard__webdav__btn genericWebdav__btn'>
346
-              <div className='dashboard__webdav__btn__icon genericWebdav__btn__icon'>
347
-                <i className='fa fa-windows' />
348
-              </div>
349
+              <div className='dashboard__webdav__btn genericWebdav__btn'>
350
+                <div className='dashboard__webdav__btn__icon genericWebdav__btn__icon'>
351
+                  <i className='fa fa-windows' />
352
+                </div>
349 353
 
350
-              <div className='dashboard__webdav__btn__text genericWebdav__btn__text'>
351
-                Implémenter Tracim dans votre explorateur
354
+                <div className='dashboard__webdav__btn__text genericWebdav__btn__text'>
355
+                  Implémenter Tracim dans votre explorateur
356
+                </div>
352 357
               </div>
353
-            </div>
354 358
 
355
-            <div className='dashboard__webdav__information genericWebdav__info'>
356
-              <div className='dashboard__webdav__information__text genericWebdav__info__text'>
357
-                Lorem ipsum dolore dolore laborum exercitation et deserunt ad ullamco nostrud dolore magna in proident elit amet do eu ut officia anim magna dolore adipisicing aliqua qui reprehenderit laborum labore tempor consectetur ut pariatur deserunt nostrud.
358
-              </div>
359
+              <div className='dashboard__webdav__information genericWebdav__info'>
360
+                <div className='dashboard__webdav__information__text genericWebdav__info__text'>
361
+                  Lorem ipsum dolore dolore laborum exercitation et deserunt ad ullamco nostrud dolore magna in proident elit amet do eu ut officia anim magna dolore adipisicing aliqua qui reprehenderit laborum labore tempor consectetur ut pariatur deserunt nostrud.
362
+                </div>
359 363
 
360
-              <div className='dashboard__webdav__information__link genericWebdav__info__link'>
361
-                http://algoo.trac.im/webdav/
364
+                <div className='dashboard__webdav__information__link genericWebdav__info__link'>
365
+                  http://algoo.trac.im/webdav/
366
+                </div>
362 367
               </div>
363
-            </div>
364 368
 
369
+            </div>
365 370
           </div>
366 371
         </div>
367 372
       </div>

+ 45 - 9
src/container/Sidebar.jsx View File

@@ -4,35 +4,61 @@ import { withRouter } from 'react-router'
4 4
 import { translate } from 'react-i18next'
5 5
 import WorkspaceListItem from '../component/Sidebar/WorkspaceListItem.jsx'
6 6
 import { getWorkspaceList } from '../action-creator.async.js'
7
-import { setWorkspaceListisOpenInSidebar } from '../action-creator.sync.js'
7
+import {
8
+  setWorkspaceListIsOpenInSidebar,
9
+  updateWorkspaceFilter
10
+} from '../action-creator.sync.js'
8 11
 import { PAGE_NAME } from '../helper.js'
9 12
 
10 13
 class Sidebar extends React.Component {
11 14
   constructor (props) {
12 15
     super(props)
13 16
     this.state = {
14
-      firstWsOpen: false
17
+      firstWsOpen: false,
18
+      workspaceIdInUrl: parseInt(props.match.params.idws)
15 19
     }
16 20
   }
17 21
 
18 22
   componentDidMount () {
23
+    const { workspaceIdInUrl } = this.state
19 24
     const { user, workspaceList, dispatch } = this.props
20
-    user.id !== -1 && workspaceList.length === 0 && dispatch(getWorkspaceList(user.id))
25
+    user.id !== -1 && workspaceList.length === 0 && dispatch(getWorkspaceList(user.id, workspaceIdInUrl))
21 26
   }
22 27
 
23
-  componentDidUpdate (prevProps) {
24
-    const { user, dispatch } = this.props
25
-    user.id !== -1 && prevProps.user.id !== user.id && dispatch(getWorkspaceList(user.id))
28
+  componentDidUpdate (prevProps, prevState) {
29
+    const { user, match, dispatch } = this.props
30
+
31
+    const newWorkspaceId = parseInt(match.params.idws)
32
+    prevState.workspaceIdInUrl !== newWorkspaceId && this.setState({workspaceIdInUrl: newWorkspaceId})
33
+
34
+    user.id !== -1 && prevProps.user.id !== user.id && dispatch(getWorkspaceList(user.id, newWorkspaceId))
26 35
   }
27 36
 
28
-  handleClickWorkspace = (wsId, newisOpenInSidebar) => this.props.dispatch(setWorkspaceListisOpenInSidebar(wsId, newisOpenInSidebar))
37
+  handleClickWorkspace = (wsId, newIsOpenInSidebar) => this.props.dispatch(setWorkspaceListIsOpenInSidebar(wsId, newIsOpenInSidebar))
29 38
 
30 39
   handleClickAllContent = wsId => {
31 40
     this.props.history.push(`${PAGE_NAME.WS_CONTENT}/${wsId}`)
32 41
   }
33 42
 
43
+  handleClickContentFilter = (wsId, filter) => {
44
+    const { workspaceIdInUrl } = this.state
45
+    const { workspace, history, dispatch } = this.props
46
+
47
+    const filterList = (() => {
48
+      if (wsId !== workspaceIdInUrl) return [filter] // load a different workspace => reset filters
49
+
50
+      if (workspace.filter.includes(filter)) return workspace.filter.filter(f => f !== filter) // remove the filter
51
+      else return [...workspace.filter, filter] // add the filter
52
+    })()
53
+
54
+    dispatch(updateWorkspaceFilter(filterList))
55
+
56
+    history.push(`${PAGE_NAME.WS_CONTENT}/${wsId}/${filterList.join(';')}`) // workspace.filter gets updated on react redraw from match.params
57
+  }
58
+
34 59
   render () {
35
-    const { workspaceList, t } = this.props
60
+    const { workspaceIdInUrl } = this.state
61
+    const { activeLang, workspace, workspaceList, app, t } = this.props
36 62
 
37 63
     return (
38 64
       <div className='sidebar d-none d-lg-block'>
@@ -43,9 +69,13 @@ class Sidebar extends React.Component {
43 69
                 number={++i}
44 70
                 wsId={ws.id}
45 71
                 name={ws.title}
72
+                app={app}
73
+                lang={activeLang}
74
+                activeFilterList={ws.id === workspaceIdInUrl ? workspace.filter : []}
46 75
                 isOpenInSidebar={ws.isOpenInSidebar}
47 76
                 onClickTitle={() => this.handleClickWorkspace(ws.id, !ws.isOpenInSidebar)}
48 77
                 onClickAllContent={this.handleClickAllContent}
78
+                onClickContentFilter={this.handleClickContentFilter}
49 79
                 key={ws.id}
50 80
               />
51 81
             )}
@@ -62,5 +92,11 @@ class Sidebar extends React.Component {
62 92
   }
63 93
 }
64 94
 
65
-const mapStateToProps = ({ user, workspaceList }) => ({ user, workspaceList })
95
+const mapStateToProps = ({ lang, user, workspace, workspaceList, app }) => ({
96
+  activeLang: lang.find(l => l.active) || {id: 'en'},
97
+  user,
98
+  workspace,
99
+  workspaceList,
100
+  app
101
+})
66 102
 export default withRouter(connect(mapStateToProps)(translate()(Sidebar)))

+ 6 - 20
src/container/Tracim.jsx View File

@@ -2,7 +2,6 @@ import React from 'react'
2 2
 import { connect } from 'react-redux'
3 3
 import Footer from '../component/Footer.jsx'
4 4
 import Header from './Header.jsx'
5
-import Sidebar from './Sidebar.jsx'
6 5
 import Login from './Login.jsx'
7 6
 import Dashboard from './Dashboard.jsx'
8 7
 import Account from './Account.jsx'
@@ -20,22 +19,13 @@ import {
20 19
 } from '../action-creator.async.js'
21 20
 
22 21
 class Tracim extends React.Component {
23
-  componentDidMount = () => {
22
+  componentDidMount () {
24 23
     this.props.dispatch(getIsUserConnected())
25 24
     this.props.dispatch(getLangList())
26 25
   }
27 26
 
28 27
   render () {
29
-    const { user, location } = this.props
30
-
31
-    const SidebarWrapper = props => props.locationPath !== '/login'
32
-      ? (
33
-        <div className='sidebarpagecontainer'>
34
-          <Sidebar />
35
-          {props.children}
36
-        </div>
37
-      )
38
-      : props.children
28
+    const { user } = this.props
39 29
 
40 30
     return (
41 31
       <div className='tracim'>
@@ -47,14 +37,10 @@ class Tracim extends React.Component {
47 37
             <div className='tracim__content'>
48 38
               <Route path={PAGE_NAME.LOGIN} component={Login} />
49 39
 
50
-              <SidebarWrapper locationPath={location.pathname}>
51
-
52
-                <PrivateRoute exact path={PAGE_NAME.HOME} component={WorkspaceContent} />
53
-                <PrivateRoute path={`${PAGE_NAME.WS_CONTENT}/:idws`} component={WorkspaceContent} />
54
-                <PrivateRoute exact path={PAGE_NAME.ACCOUNT} component={Account} />
55
-                <PrivateRoute exact path={PAGE_NAME.DASHBOARD} component={Dashboard} />
56
-
57
-              </SidebarWrapper>
40
+              <PrivateRoute exact path={PAGE_NAME.HOME} component={WorkspaceContent} />
41
+              <PrivateRoute path={`${PAGE_NAME.WS_CONTENT}/:idws/:filter?`} component={WorkspaceContent} />
42
+              <PrivateRoute exact path={PAGE_NAME.ACCOUNT} component={Account} />
43
+              <PrivateRoute exact path={PAGE_NAME.DASHBOARD} component={Dashboard} />
58 44
 
59 45
               <Footer />
60 46
             </div>

+ 62 - 48
src/container/WorkspaceContent.jsx View File

@@ -1,6 +1,7 @@
1 1
 import React from 'react'
2 2
 import { connect } from 'react-redux'
3 3
 import appFactory from '../appFactory.js'
4
+import Sidebar from './Sidebar.jsx'
4 5
 import Folder from '../component/Workspace/Folder.jsx'
5 6
 import FileItem from '../component/Workspace/FileItem.jsx'
6 7
 import FileItemHeader from '../component/Workspace/FileItemHeader.jsx'
@@ -24,22 +25,23 @@ class WorkspaceContent extends React.Component {
24 25
   componentDidMount () {
25 26
     const { workspaceList, app, match, dispatch } = this.props
26 27
 
27
-    if (match.params.idws !== undefined) dispatch(getWorkspaceContent(match.params.idws))
28
-    else if (workspaceList.length > 0) dispatch(getWorkspaceContent(workspaceList[0].id)) // load first ws if none specified
28
+    if (match.params.idws !== undefined) dispatch(getWorkspaceContent(match.params.idws, match.params.filter))
29
+    else if (workspaceList.length > 0) dispatch(getWorkspaceContent(workspaceList[0].id, match.params.filter)) // load first ws if none specified
29 30
 
30
-    Object.keys(app).length === 0 && dispatch(getAppList())
31
+    if (Object.keys(app).length === 0) dispatch(getAppList())
31 32
   }
32 33
 
33 34
   componentDidUpdate (prevProps) {
34 35
     const { workspace, workspaceList, match, dispatch } = this.props
36
+    console.log('workspaceContent update', prevProps, this.props)
35 37
 
36 38
     // if a workspace is already loaded and the idws in url hasn't changed, do nothing
37 39
     if (workspace.id !== -1 && prevProps.match.params.idws === match.params.idws) return
38 40
 
39 41
     // if the idws in url has changed, load the new workspace
40
-    if (match.params.idws !== undefined) dispatch(getWorkspaceContent(match.params.idws))
42
+    if (match.params.idws !== undefined) dispatch(getWorkspaceContent(match.params.idws, match.params.filter))
41 43
     // else bellow is for loading url PAGE_NAME.HOME (without an idws), when workspaceList is loaded, load the first workspace
42
-    else if (match.params.idws === undefined && workspace.id === -1 && workspaceList.length > 0) dispatch(getWorkspaceContent(workspaceList[0].id))
44
+    else if (workspace.id === -1 && workspaceList.length > 0) dispatch(getWorkspaceContent(workspaceList[0].id))
43 45
   }
44 46
 
45 47
   handleClickContentItem = content => {
@@ -48,53 +50,65 @@ class WorkspaceContent extends React.Component {
48 50
     // dispatch(setActiveFileContentActive(content))
49 51
   }
50 52
 
53
+  filterWorkspaceContent = (contentList, filter) => filter.length === 0
54
+    ? contentList
55
+    : contentList.filter(c => c.type === 'folder' || filter.includes(c.type)) // keep unfiltered files and folders
56
+      .map(c => c.type !== 'folder' ? c : {...c, content: this.filterWorkspaceContent(c.content, filter)}) // recursively filter folder content
57
+      .filter(c => c.type !== 'folder' || c.content.length > 0) // remove empty folder
58
+
51 59
   render () {
52 60
     const { workspace, app } = this.props
53 61
 
62
+    const filteredWorkspaceContent = this.filterWorkspaceContent(workspace.content, workspace.filter)
63
+
54 64
     return (
55
-      <PageWrapper customeClass='workspace'>
56
-        <PageTitle
57
-          parentClass='workspace__header'
58
-          customClass='justify-content-between'
59
-          title={workspace.title}
60
-        >
61
-          <DropdownCreateButton parentClass='workspace__header__btnaddworkspace' />
62
-        </PageTitle>
63
-
64
-        <PageContent parentClass='workspace__content'>
65
-          <div className='workspace__content__fileandfolder folder__content active'>
66
-            <FileItemHeader />
67
-
68
-            { workspace.content.map((c, i) => c.type === 'folder'
69
-              ? (
70
-                <Folder
71
-                  app={app}
72
-                  folderData={c}
73
-                  onClickItem={this.handleClickContentItem}
74
-                  isLast={i === workspace.content.length - 1}
75
-                  key={c.id}
76
-                />
77
-              )
78
-              : (
79
-                <FileItem
80
-                  name={c.title}
81
-                  type={c.type}
82
-                  icon={(app[c.type] || {icon: ''}).icon}
83
-                  status={c.status}
84
-                  onClickItem={() => this.handleClickContentItem(c)}
85
-                  isLast={i === workspace.content.length - 1}
86
-                  key={c.id}
87
-                />
88
-              )
89
-            )}
90
-          </div>
91
-
92
-          <DropdownCreateButton customClass='workspace__content__button mb-5' />
93
-
94
-          <div id='appContainer' />
95
-        </PageContent>
96
-
97
-      </PageWrapper>
65
+      <div className='sidebarpagecontainer'>
66
+        <Sidebar />
67
+
68
+        <PageWrapper customeClass='workspace'>
69
+          <PageTitle
70
+            parentClass='workspace__header'
71
+            customClass='justify-content-between'
72
+            title={workspace.title}
73
+          >
74
+            <DropdownCreateButton parentClass='workspace__header__btnaddworkspace' />
75
+          </PageTitle>
76
+
77
+          <PageContent parentClass='workspace__content'>
78
+            <div className='workspace__content__fileandfolder folder__content active'>
79
+              <FileItemHeader />
80
+
81
+              { filteredWorkspaceContent.map((c, i) => c.type === 'folder'
82
+                ? (
83
+                  <Folder
84
+                    app={app}
85
+                    folderData={c}
86
+                    onClickItem={this.handleClickContentItem}
87
+                    isLast={i === filteredWorkspaceContent.length - 1}
88
+                    key={c.id}
89
+                  />
90
+                )
91
+                : (
92
+                  <FileItem
93
+                    name={c.title}
94
+                    type={c.type}
95
+                    icon={(app[c.type] || {icon: ''}).icon}
96
+                    status={c.status}
97
+                    onClickItem={() => this.handleClickContentItem(c)}
98
+                    isLast={i === filteredWorkspaceContent.length - 1}
99
+                    key={c.id}
100
+                  />
101
+                )
102
+              )}
103
+            </div>
104
+
105
+            <DropdownCreateButton customClass='workspace__content__button mb-5' />
106
+
107
+            <div id='appContainer' />
108
+          </PageContent>
109
+
110
+        </PageWrapper>
111
+      </div>
98 112
     )
99 113
   }
100 114
 }

+ 1 - 1
src/css/FileItem.styl View File

@@ -1,6 +1,7 @@
1 1
 .file
2 2
   display flex
3 3
   border-bottom 0
4
+  cursor pointer
4 5
   &:hover
5 6
     background-color files-hover
6 7
   &__type
@@ -10,7 +11,6 @@
10 11
     display flex
11 12
     justify-content space-between
12 13
     padding 15px 5px
13
-    cursor pointer
14 14
     &__text
15 15
       font-size 17px
16 16
     &__icons

+ 4 - 1
src/css/Sidebar.styl View File

@@ -28,7 +28,7 @@ leftside()
28 28
   flex-grow 0
29 29
   height 100%
30 30
   font-size 18px
31
-  background-color rgba(253,253,253,0.3)
31
+  background-color rgba(253, 253, 253, 0.3)
32 32
 
33 33
 .sidebar
34 34
   &__btnnewworkspace
@@ -96,3 +96,6 @@ leftside()
96 96
               padding 10px 15px
97 97
               min-width 50px
98 98
               leftside()
99
+            &.activeFilter
100
+              .dropdown__icon
101
+                background-color rgba(253, 253, 253, 0.8)

+ 10 - 3
src/reducer/workspace.js View File

@@ -13,11 +13,18 @@ export default function user (state = {
13 13
   id: -1,
14 14
   title: '',
15 15
   ownerId: '',
16
-  content: []
16
+  content: [],
17
+  filter: []
17 18
 }, action) {
18 19
   switch (action.type) {
19
-    case `Update/${WORKSPACE}`:
20
-      return serializeWorkspace(action.workspace)
20
+    case `Set/${WORKSPACE}`:
21
+      return {
22
+        ...serializeWorkspace(action.workspace),
23
+        filter: action.filterStr ? action.filterStr.split(';') : []
24
+      }
25
+
26
+    case `Update/${WORKSPACE}/Filter`:
27
+      return {...state, filter: action.filterList}
21 28
 
22 29
     default:
23 30
       return state