Browse Source

pluged in dashboard

Skylsmoi 5 years ago
parent
commit
c54e260a61

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

@@ -6,11 +6,13 @@ import {
6 6
   USER_LOGOUT,
7 7
   USER_ROLE,
8 8
   USER_CONNECTED,
9
+  USER_KNOWN_MEMBER_LIST,
9 10
   setUserRole,
10 11
   WORKSPACE,
11 12
   WORKSPACE_LIST,
12 13
   WORKSPACE_DETAIL,
13 14
   WORKSPACE_MEMBER_LIST,
15
+  WORKSPACE_MEMBER_ADD,
14 16
   FOLDER,
15 17
   setFolderData,
16 18
   APP_LIST,
@@ -148,6 +150,36 @@ export const getUserRole = user => async dispatch => {
148 150
   if (fetchGetUserRole.status === 200) dispatch(setUserRole(fetchGetUserRole.json))
149 151
 }
150 152
 
153
+export const getUserKnownMember = (user, userNameToSearch) => dispatch => {
154
+  return fetchWrapper({
155
+    url: `${FETCH_CONFIG.apiUrl}/users/${user.user_id}/known_members?acp=${userNameToSearch}`,
156
+    param: {
157
+      headers: {
158
+        ...FETCH_CONFIG.headers,
159
+        'Authorization': 'Basic ' + user.auth
160
+      },
161
+      method: 'GET'
162
+    },
163
+    actionName: USER_KNOWN_MEMBER_LIST,
164
+    dispatch
165
+  })
166
+}
167
+
168
+export const putUserWorkspaceRead = (user, idWorkspace) => dispatch => {
169
+  return fetchWrapper({
170
+    url: `${FETCH_CONFIG.apiUrl}/users/${user.user_id}/workspaces/${idWorkspace}/read`,
171
+    param: {
172
+      headers: {
173
+        ...FETCH_CONFIG.headers,
174
+        'Authorization': 'Basic ' + user.auth
175
+      },
176
+      method: 'PUT'
177
+    },
178
+    actionName: USER_KNOWN_MEMBER_LIST,
179
+    dispatch
180
+  })
181
+}
182
+
151 183
 export const getWorkspaceList = user => dispatch => {
152 184
   return fetchWrapper({
153 185
     url: `${FETCH_CONFIG.apiUrl}/users/${user.user_id}/workspaces`,
@@ -238,6 +270,26 @@ export const getWorkspaceReadStatusList = (user, idWorkspace) => dispatch => {
238 270
   })
239 271
 }
240 272
 
273
+export const postWorkspaceMember = (user, idWorkspace, newMember) => dispatch => {
274
+  return fetchWrapper({
275
+    url: `${FETCH_CONFIG.apiUrl}/workspaces/${idWorkspace}/members`,
276
+    param: {
277
+      headers: {
278
+        ...FETCH_CONFIG.headers,
279
+        'Authorization': 'Basic ' + user.auth
280
+      },
281
+      method: 'POST',
282
+      body: JSON.stringify({
283
+        user_id: newMember.id,
284
+        user_email_or_public_name: newMember.name,
285
+        role: newMember.role
286
+      })
287
+    },
288
+    actionName: WORKSPACE_MEMBER_ADD,
289
+    dispatch
290
+  })
291
+}
292
+
241 293
 export const getFolderContent = (idWorkspace, idFolder) => async dispatch => {
242 294
   const fetchGetFolderContent = await fetchWrapper({
243 295
     url: `${FETCH_CONFIG.apiUrl}/workspaces/${idWorkspace}/contents/?parent_id=${idFolder}`,
@@ -252,7 +304,6 @@ export const getFolderContent = (idWorkspace, idFolder) => async dispatch => {
252 304
 }
253 305
 
254 306
 export const getAppList = user => dispatch => {
255
-  console.log(user)
256 307
   return fetchWrapper({
257 308
     url: `${FETCH_CONFIG.apiUrl}/system/applications`,
258 309
     param: {
@@ -260,8 +311,7 @@ export const getAppList = user => dispatch => {
260 311
         ...FETCH_CONFIG.headers,
261 312
         'Authorization': 'Basic ' + user.auth
262 313
       },
263
-      method: 'GET',
264
-      'Authorization': 'Basic ' + user.auth
314
+      method: 'GET'
265 315
     },
266 316
     actionName: APP_LIST,
267 317
     dispatch

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

@@ -17,18 +17,20 @@ export const removeFlashMessage = msg => ({ type: `${REMOVE}/${FLASH_MESSAGE}`,
17 17
 export const USER = 'User'
18 18
 export const USER_LOGIN = `${USER}/Login`
19 19
 export const USER_LOGOUT = `${USER}/Logout`
20
-export const USER_DATA = `${USER}/Data`
21
-export const USER_ROLE = `${USER}/Role`
22 20
 export const USER_CONNECTED = `${USER}/Connected`
23 21
 export const USER_DISCONNECTED = `${USER}/Disconnected`
24
-export const USER_LANG = `${USER}/Lang`
25 22
 export const setUserConnected = user => ({ type: `${SET}/${USER}/Connected`, user })
26 23
 export const setUserDisconnected = () => ({ type: `${SET}/${USER}/Disconnected` })
24
+export const USER_DATA = `${USER}/Data`
27 25
 export const updateUserData = userData => ({ type: `${UPDATE}/${USER}/Data`, data: userData })
26
+export const USER_ROLE = `${USER}/Role`
28 27
 export const setUserRole = userRole => ({ type: `${SET}/${USER}/Role`, userRole }) // this actually update workspaceList state
29
-export const setUserLang = lang => ({ type: `${SET}/${USER}/Lang`, lang })
30 28
 export const updateUserWorkspaceSubscriptionNotif = (workspaceId, subscriptionNotif) =>
31 29
   ({ type: `${UPDATE}/${USER_ROLE}/SubscriptionNotif`, workspaceId, subscriptionNotif })
30
+export const USER_LANG = `${USER}/Lang`
31
+export const setUserLang = lang => ({ type: `${SET}/${USER}/Lang`, lang })
32
+export const USER_KNOWN_MEMBER = `${USER}/KnownMember`
33
+export const USER_KNOWN_MEMBER_LIST = `${USER_KNOWN_MEMBER}/List`
32 34
 
33 35
 export const WORKSPACE = 'Workspace'
34 36
 export const WORKSPACE_CONTENT = `${WORKSPACE}/Content`
@@ -45,10 +47,13 @@ export const setWorkspaceDetail = workspaceDetail => ({ type: `${SET}/${WORKSPAC
45 47
 export const WORKSPACE_MEMBER = `${WORKSPACE}/Member`
46 48
 export const WORKSPACE_MEMBER_LIST = `${WORKSPACE_MEMBER}/List`
47 49
 export const setWorkspaceMemberList = workspaceMemberList => ({ type: `${SET}/${WORKSPACE_MEMBER_LIST}`, workspaceMemberList })
50
+export const WORKSPACE_MEMBER_ADD = `${WORKSPACE_MEMBER}/${ADD}`
48 51
 
49 52
 export const WORKSPACE_RECENT_ACTIVITY = `${WORKSPACE}/RecentActivity/List`
50 53
 export const WORKSPACE_RECENT_ACTIVITY_LIST = `${WORKSPACE_RECENT_ACTIVITY}/List`
51 54
 export const setWorkspaceRecentActivityList = workspaceRecentActivityList => ({ type: `${SET}/${WORKSPACE_RECENT_ACTIVITY_LIST}`, workspaceRecentActivityList })
55
+export const WORKSPACE_RECENT_ACTIVITY_FOR_USER_LIST = `${WORKSPACE_RECENT_ACTIVITY}/ForUser/List`
56
+export const setWorkspaceRecentActivityForUserList = workspaceRecentActivityForUserList => ({ type: `${SET}/${WORKSPACE_RECENT_ACTIVITY_FOR_USER_LIST}`, workspaceRecentActivityForUserList })
52 57
 
53 58
 export const WORKSPACE_READ_STATUS = `${WORKSPACE}/ReadStatus`
54 59
 export const WORKSPACE_READ_STATUS_LIST = `${WORKSPACE_READ_STATUS}/List`

+ 3 - 1
frontend/src/component/Dashboard/ContentTypeBtn.styl View File

@@ -1,8 +1,10 @@
1
+@import "../../../node_modules/tracim_frontend_lib/src/css/Variable.styl"
2
+
1 3
 .contentTypeBtn
2 4
   display flex
3 5
   flex-direction column
4 6
   justify-content center
5
-  margin 0 15px
7
+  margin 15px
6 8
   border-radius 10px
7 9
   padding 15px
8 10
   width 230px

+ 58 - 21
frontend/src/component/Dashboard/MemberList.jsx View File

@@ -1,16 +1,14 @@
1 1
 import React from 'react'
2 2
 import PropTypes from 'prop-types'
3
-import { Checkbox } from 'tracim_frontend_lib'
3
+// import { Checkbox } from 'tracim_frontend_lib'
4 4
 
5 5
 require('./MemberList.styl')
6 6
 
7 7
 export class MemberList extends React.Component {
8 8
   constructor (props) {
9 9
     super(props)
10
-
11 10
     this.state = {
12
-      displayNewMemberList: true,
13
-      createAccountCheckbox: false
11
+      displayNewMemberList: true
14 12
     }
15 13
   }
16 14
 
@@ -21,7 +19,12 @@ export class MemberList extends React.Component {
21 19
   handleClickCheckboxCreateAccount = e => {
22 20
     e.preventDefault()
23 21
     e.stopPropagation()
24
-    this.setState(prev => ({createAccountCheckbox: !prev.createAccountCheckbox}))
22
+    this.props.onChangeCreateAccount(!this.props.createAccount)
23
+  }
24
+
25
+  handleClickBtnValidate = () => {
26
+    this.props.onClickValidateNewMember()
27
+    this.setState({displayNewMemberList: true})
25 28
   }
26 29
 
27 30
   render () {
@@ -40,7 +43,7 @@ export class MemberList extends React.Component {
40 43
               <div>
41 44
                 <ul className='memberlist__list'>
42 45
                   {props.memberList.map(m =>
43
-                    <li className='memberlist__list__item primaryColorBgLightenHover' key={m.id}>
46
+                    <li className='memberlist__list__item' key={m.id}>
44 47
                       <div className='memberlist__list__item__avatar'>
45 48
                         {m.avatarUrl ? <img src={m.avatarUrl} /> : <img src='NYI' />}
46 49
                       </div>
@@ -78,7 +81,7 @@ export class MemberList extends React.Component {
78 81
               </div>
79 82
             )
80 83
             : (
81
-              <form className='memberlist__form'>
84
+              <div className='memberlist__form'>
82 85
                 <div className='memberlist__form__close d-flex justify-content-end'>
83 86
                   <i className='fa fa-times' onClick={this.handleClickCloseAddMemberBtn} />
84 87
                 </div>
@@ -94,10 +97,34 @@ export class MemberList extends React.Component {
94 97
                       className='name__input form-control'
95 98
                       id='addmember'
96 99
                       placeholder='Nom ou Email'
97
-                      onChange={props.onChangeName}
100
+                      value={props.nameOrEmail}
101
+                      onChange={e => props.onChangeNameOrEmail(e.target.value)}
102
+                      autoComplete='off'
98 103
                     />
104
+
105
+                    {props.searchedKnownMemberList.length > 0 &&
106
+                      <div className='autocomplete primaryColorBorder'>
107
+                        {props.searchedKnownMemberList.filter((u, i) => i < 5).map(u => // only displays the first 5
108
+                          <div
109
+                            className='autocomplete__item primaryColorBgHover'
110
+                            onClick={() => props.onClickKnownMember(u)}
111
+                            key={u.user_id}
112
+                          >
113
+                            <div className='autocomplete__item__avatar primaryColorBorder'>
114
+                              <img src={u.avatar_url} />
115
+                            </div>
116
+
117
+                            <div className='autocomplete__item__name'>
118
+                              {u.public_name}
119
+                            </div>
120
+                          </div>
121
+                        )}
122
+                      </div>
123
+                    }
99 124
                   </div>
100 125
 
126
+                  {/*
127
+                  // @TODO validate with DA that this checkbox is useless since the backend handle everything
101 128
                   <div className='memberlist__form__member__create'>
102 129
                     <div className='memberlist__form__member__create__checkbox mr-3'>
103 130
                       <Checkbox
@@ -111,6 +138,7 @@ export class MemberList extends React.Component {
111 138
                       {props.t('Create an account')}
112 139
                     </div>
113 140
                   </div>
141
+                  */}
114 142
                 </div>
115 143
 
116 144
                 <div className='memberlist__form__role'>
@@ -120,20 +148,29 @@ export class MemberList extends React.Component {
120 148
 
121 149
                   <ul className='memberlist__form__role__list'>
122 150
                     {props.roleList.map(r =>
123
-                      <li className='memberlist__form__role__list__item' key={r.slug}>
124
-                        <div className='item__radiobtn mr-3'>
125
-                          <input type='radio' name='role' value={r.slug} />
126
-                        </div>
127
-
128
-                        <div className='item__text'>
129
-                          <div className='item_text_icon mr-2' style={{color: r.hexcolor}}>
130
-                            <i className={`fa fa-${r.faIcon}`} />
151
+                      <li key={r.slug}>
152
+                        <label className='memberlist__form__role__list__item' htmlFor={r.slug}>
153
+                          <div className='item__radiobtn mr-3'>
154
+                            <input
155
+                              id={r.slug}
156
+                              type='radio'
157
+                              name='role'
158
+                              value={r.slug}
159
+                              checked={r.slug === props.role}
160
+                              onChange={() => props.onChangeRole(r.slug)}
161
+                            />
131 162
                           </div>
132 163
 
133
-                          <div className='item__text__name'>
134
-                            {r.label}
164
+                          <div className='item__text'>
165
+                            <div className='item__text__icon mr-2' style={{color: r.hexcolor}}>
166
+                              <i className={`fa fa-${r.faIcon}`} />
167
+                            </div>
168
+
169
+                            <div className='item__text__name'>
170
+                              {r.label}
171
+                            </div>
135 172
                           </div>
136
-                        </div>
173
+                        </label>
137 174
                       </li>
138 175
                     )}
139 176
 
@@ -141,11 +178,11 @@ export class MemberList extends React.Component {
141 178
                 </div>
142 179
 
143 180
                 <div className='memberlist__form__submitbtn'>
144
-                  <button className='btn btn-outline-primary'>
181
+                  <button className='btn btn-outline-primary' onClick={this.handleClickBtnValidate}>
145 182
                     {props.t('Validate')}
146 183
                   </button>
147 184
                 </div>
148
-              </form>
185
+              </div>
149 186
             )
150 187
           }
151 188
         </div>

+ 56 - 1
frontend/src/component/Dashboard/MemberList.styl View File

@@ -1,3 +1,5 @@
1
+@import "../../../node_modules/tracim_frontend_lib/src/css/Variable.styl"
2
+
1 3
 .memberlist
2 4
   margin 0 0 50px 0
3 5
   width 35%
@@ -76,11 +78,38 @@
76 78
         cursor pointer
77 79
     &__member
78 80
       &__name
81
+        position relative
82
+        margin 0 0 20px 0
79 83
         .name__label
80 84
           margin 30px 0 20px 0
81 85
           label()
86
+        .autocomplete
87
+          position absolute
88
+          min-width 300px
89
+          background-color off-white
90
+          border-radius 10px
91
+          border-width 1px
92
+          border-style solid
93
+          &__item
94
+            display flex
95
+            align-items center
96
+            cursor pointer
97
+            padding 5px 8px
98
+            &:first-child
99
+              border-top-left-radius 10px
100
+              border-top-right-radius 10px
101
+            &:last-child
102
+              border-bottom-left-radius 10px
103
+              border-bottom-right-radius 10px
104
+            &__avatar
105
+              width 45px
106
+              height 45px
107
+              border-radius 50%
108
+              border-width 1px
109
+              border-style solid
110
+            &__name
111
+              margin-left 15px
82 112
       .name__input
83
-        margin-bottom 20px
84 113
         border 1px solid grey
85 114
         border-radius 10px
86 115
         padding 10px
@@ -106,6 +135,7 @@
106 135
           display flex
107 136
           align-items center
108 137
           margin 10px 25px 10px 0
138
+          cursor pointer
109 139
           .item
110 140
             &__text
111 141
               display flex
@@ -115,3 +145,28 @@
115 145
       & > button
116 146
         padding 8px 30px
117 147
         cursor pointer
148
+
149
+@media (min-width min-sm) and (max-width: max-lg)
150
+  .memberlist
151
+    width 50%
152
+
153
+@media (min-width: min-sm) and (max-width: max-sm)
154
+  .memberlist
155
+    margin 50px 0
156
+    width 90%
157
+
158
+@media (max-width: max-xs)
159
+  .memberlist
160
+    margin 50px 0
161
+    width 100%
162
+    &__title
163
+      margin-left 10px
164
+    &__wrapper
165
+      height auto
166
+    &__list
167
+      height auto
168
+      overflow-Y visible
169
+      &__item:nth-last-child(1)
170
+        border-bottom 1px solid grey
171
+    &__btnadd
172
+      border-top 0

+ 66 - 0
frontend/src/component/Dashboard/MoreInfo.jsx View File

@@ -0,0 +1,66 @@
1
+import React from 'react'
2
+
3
+require('./MoreInfo.styl')
4
+
5
+export const MoreInfo = props =>
6
+  <div className='moreinfo'>
7
+    <div className='moreinfo__webdav genericBtnInfoDashboard'>
8
+      <div
9
+        className='moreinfo__webdav__btn genericBtnInfoDashboard__btn'
10
+        onClick={props.onClickToggleWebdav}
11
+      >
12
+        <div className='moreinfo__webdav__btn__icon genericBtnInfoDashboard__btn__icon'>
13
+          <i className='fa fa-windows' />
14
+        </div>
15
+
16
+        <div className='moreinfo__webdav__btn__text genericBtnInfoDashboard__btn__text'>
17
+          {props.t('Implement Tracim in your explorer')}
18
+        </div>
19
+      </div>
20
+
21
+      {props.displayWebdavBtn === true &&
22
+      <div className='moreinfo__webdav__information genericBtnInfoDashboard__info'>
23
+        <div className='moreinfo__webdav__information__text genericBtnInfoDashboard__info__text'>
24
+          {props.t('Find all your documents deposited online directly on your computer via the workstation, without going through the software.')}'
25
+        </div>
26
+
27
+        <div className='moreinfo__webdav__information__link genericBtnInfoDashboard__info__link'>
28
+          http://algoo.trac.im/webdav/
29
+        </div>
30
+      </div>
31
+      }
32
+    </div>
33
+
34
+    <div className='moreinfo__calendar genericBtnInfoDashboard'>
35
+      <div className='moreinfo__calendar__wrapperBtn'>
36
+        <div
37
+          className='moreinfo__calendar__btn genericBtnInfoDashboard__btn'
38
+          onClick={props.onClickToggleCalendar}
39
+        >
40
+          <div className='moreinfo__calendar__btn__icon genericBtnInfoDashboard__btn__icon'>
41
+            <i className='fa fa-calendar' />
42
+          </div>
43
+
44
+          <div className='moreinfo__calendar__btn__text genericBtnInfoDashboard__btn__text'>
45
+            {props.t('Workspace Calendar')}
46
+          </div>
47
+        </div>
48
+      </div>
49
+
50
+      <div className='moreinfo__calendar__wrapperText'>
51
+        {props.displayCalendarBtn === true &&
52
+        <div className='moreinfo__calendar__information genericBtnInfoDashboard__info'>
53
+          <div className='moreinfo__calendar__information__text genericBtnInfoDashboard__info__text'>
54
+            {props.t('Each workspace has its own calendar.')}
55
+          </div>
56
+
57
+          <div className='moreinfo__calendar__information__link genericBtnInfoDashboard__info__link'>
58
+            http://algoo.trac.im/calendar/
59
+          </div>
60
+        </div>
61
+        }
62
+      </div>
63
+    </div>
64
+  </div>
65
+
66
+export default MoreInfo

+ 29 - 0
frontend/src/component/Dashboard/MoreInfo.styl View File

@@ -0,0 +1,29 @@
1
+.moreinfo
2
+  display flex
3
+  justify-content space-between
4
+  flexwrap wrap
5
+  &__webdav
6
+    margin 0 15px 40px 0
7
+    &__btn
8
+      width 300px
9
+    &__information
10
+      width 300px
11
+  &__calendar
12
+    margin-bottom 100px
13
+    &__wrapperBtn
14
+      margin-right 290px
15
+    &__btn
16
+      width 300px
17
+    &__information
18
+      width 300px
19
+
20
+@media (min-width: min-sm) and (max-width: max-sm)
21
+  .moreinfo__webdav__information
22
+    width 500px
23
+
24
+@media (max-width: max-xs)
25
+  .moreinfo
26
+    &__webdav
27
+      margin-left 10px
28
+      &__information
29
+        width 350px

+ 19 - 10
frontend/src/component/Dashboard/RecentActivity.jsx View File

@@ -2,36 +2,45 @@ import React from 'react'
2 2
 import PropTypes from 'prop-types'
3 3
 import classnames from 'classnames'
4 4
 
5
+require('./RecentActivity.styl')
6
+
5 7
 export const RecentActivity = props =>
6
-  <div className={props.customClass}>
7
-    <div className={`${props.customClass}__header`}>
8
-      <div className={classnames(`${props.customClass}__header__title`, 'subTitle')}>
8
+  <div className='activity'>
9
+    <div className='activity__header'>
10
+      <div className={classnames('activity__header__title', 'subTitle')}>
9 11
         {props.t('Recent activity')}
10 12
       </div>
11 13
 
12
-      <div className={classnames(`${props.customClass}__header__allread`, 'btn btn-outline-primary')}>
14
+      <div
15
+        className={classnames('activity__header__allread', 'btn btn-outline-primary')}
16
+        onClick={props.onClickEverythingAsRead}
17
+      >
13 18
         {props.t('Mark everything as read')}
14 19
       </div>
15 20
     </div>
16 21
 
17
-    <div className={`${props.customClass}__wrapper`}>
22
+    <div className='activity__wrapper'>
18 23
       {props.recentActivityFilteredForUser.map(content => {
19 24
         const contentType = props.contentTypeList.find(ct => ct.slug === content.type)
20 25
         return (
21
-          <div className={`${props.customClass}__workspace`} key={content.id}>
22
-            <div className={`${props.customClass}__workspace__icon`} style={{color: contentType.hexcolor}}>
26
+          <div
27
+            className='activity__workspace'
28
+            onClick={() => props.onClickRecentContent(content.id, content.type)}
29
+            key={content.id}
30
+          >
31
+            <div className='activity__workspace__icon' style={{color: contentType.hexcolor}}>
23 32
               <i className={`fa fa-${contentType.faIcon}`} />
24 33
             </div>
25
-            <div className={`${props.customClass}__workspace__name`}>
34
+            <div className='activity__workspace__name'>
26 35
               {content.label}
27 36
             </div>
28 37
           </div>
29 38
         )
30 39
       })}
31 40
 
32
-      <div className={classnames(`${props.customClass}__more`, 'd-flex flex-row-reverse')}>
41
+      <div className={classnames('activity__more', 'd-flex flex-row-reverse')}>
33 42
         <div
34
-          className={classnames(`${props.customClass}__more__btn`, 'btn btn-outline-primary')}
43
+          className={classnames('activity__more__btn', 'btn btn-outline-primary')}
35 44
           onClick={props.onClickSeeMore}
36 45
         >
37 46
           {props.t('See more')}

+ 67 - 0
frontend/src/component/Dashboard/RecentActivity.styl View File

@@ -0,0 +1,67 @@
1
+@import "../../../node_modules/tracim_frontend_lib/src/css/Variable.styl"
2
+
3
+.activity
4
+  margin 0 35px 50px 0
5
+  width 60%
6
+  &__wrapper
7
+    border 1px solid grey
8
+    height 480px
9
+    overflow-y scroll
10
+  &__header
11
+    display flex
12
+    justify-content space-between
13
+    align-items center
14
+    margin-bottom 20px
15
+    height 44px
16
+    &__allread
17
+      padding 10px 25px
18
+      font-size 18px
19
+      cursor pointer
20
+  &__workspace
21
+    display flex
22
+    align-items center
23
+    border-bottom 1px solid grey
24
+    padding 15px
25
+    cursor pointer
26
+    &:hover
27
+      background-color fourthColor
28
+    &:nth-child(even)
29
+      background-color grey-hover
30
+      &:hover
31
+        background-color fourthColor
32
+    &__icon
33
+      margin 0 25px
34
+      font-size 25px
35
+    &__name
36
+      font-size 18px
37
+      font-weight 500
38
+      span
39
+        font-weight 400
40
+  &__more
41
+    &__btn
42
+      margin 15px
43
+      padding 10px 25px
44
+      cursor pointer
45
+
46
+@media (min-width min-sm) and (max-width: max-lg)
47
+  .activity
48
+    width 100%
49
+
50
+@media (min-width: min-md) and (max-width: max-md)
51
+  .activity
52
+    margin 25px 15px 25px 0
53
+
54
+@media (min-width: min-sm) and (max-width: max-sm)
55
+  .activity
56
+    margin 25px 15px 25px 0
57
+
58
+@media (max-width: max-xs)
59
+  .activity
60
+    margin 25px 0
61
+    width 100%
62
+    &__header
63
+      display block
64
+      height auto
65
+      margin 0 15px 20px 15px
66
+      &__title
67
+        margin-bottom 20px

+ 75 - 0
frontend/src/component/Dashboard/UserStatus.jsx View File

@@ -0,0 +1,75 @@
1
+import React from 'react'
2
+import {ROLE} from '../../helper.js'
3
+
4
+require('./UserStatus.styl')
5
+
6
+// @TODO Côme - 2018/08/07 - since api yet doesn't handle notification subscriptions, this file is WIP
7
+export const UserStatus = props =>
8
+  <div className='userstatus'>
9
+    <div className='userstatus__role'>
10
+      <div className='userstatus__role__msg'>
11
+        {props.t('Hi {{name}} ! Currently, you are ', {name: props.user.public_name})}
12
+      </div>
13
+
14
+      {(() => {
15
+        const myself = props.curWs.memberList.find(m => m.id === props.user.user_id)
16
+        if (myself === undefined) return
17
+
18
+        const myRole = ROLE.find(r => r.slug === myself.role)
19
+
20
+        return (
21
+          <div className='userstatus__role__definition'>
22
+            <div className='userstatus__role__definition__icon'>
23
+              <i className={`fa fa-${myRole.faIcon}`} />
24
+            </div>
25
+
26
+            <div className='userstatus__role__definition__text'>
27
+              {myRole.label}
28
+            </div>
29
+          </div>
30
+        )
31
+      })()}
32
+    </div>
33
+
34
+    <div className='userstatus__notification'>
35
+      <div className='userstatus__notification__text'>
36
+        {props.t("You have subscribed to this workspace's notifications")} (NYI)
37
+      </div>
38
+
39
+      {props.displayNotifBtn
40
+        ? (
41
+          <div className='userstatus__notification__subscribe dropdown'>
42
+            <button
43
+              className='userstatus__notification__subscribe__btn btn btn-outline-primary dropdown-toggle'
44
+              type='button'
45
+              id='dropdownMenuButton'
46
+              data-toggle='dropdown'
47
+              aria-haspopup='true'
48
+              aria-expanded='false'
49
+            >
50
+              {props.t('subscribed')}
51
+            </button>
52
+
53
+            <div className='userstatus__notification__subscribe__submenu dropdown-menu'>
54
+              <div className='userstatus__notification__subscribe__submenu__item dropdown-item'>
55
+                {props.t('subscriber')}
56
+              </div>
57
+              <div className='userstatus__notification__subscribe__submenu__item dropdown-item dropdown-item'>
58
+                {props.t('unsubscribed')}
59
+              </div>
60
+            </div>
61
+          </div>
62
+        )
63
+        : (
64
+          <div
65
+            className='userstatus__notification__btn btn btn-outline-primary'
66
+            onClick={props.onClickToggleNotifBtn}
67
+          >
68
+            {props.t('Change your status')}
69
+          </div>
70
+        )
71
+      }
72
+    </div>
73
+  </div>
74
+
75
+export default UserStatus

+ 30 - 0
frontend/src/component/Dashboard/UserStatus.styl View File

@@ -0,0 +1,30 @@
1
+@import "../../../node_modules/tracim_frontend_lib/src/css/Variable.styl"
2
+
3
+.userstatus
4
+  width 35%
5
+  &__role
6
+    margin 20px 0
7
+    font-size 18px
8
+    &__msg
9
+      margin-right 15px
10
+    &__definition
11
+      display flex
12
+      &__icon
13
+        margin-right 15px
14
+        color gestionnaire
15
+  &__notification
16
+    font-size 18px
17
+    &__btn
18
+      margin 20px 0
19
+      border 1px solid thirdColor
20
+      padding 10px 15px
21
+      cursor pointer
22
+    &__subscribe
23
+      &__btn
24
+        margin 20px 0
25
+        border 1px solid thirdColor
26
+        padding 10px 15px
27
+      &__submenu
28
+        padding 0
29
+        &__item
30
+          padding 10px

+ 144 - 157
frontend/src/container/Dashboard.jsx View File

@@ -10,25 +10,39 @@ import {
10 10
   getWorkspaceDetail,
11 11
   getWorkspaceMemberList,
12 12
   getWorkspaceRecentActivityList,
13
-  getWorkspaceReadStatusList
13
+  getWorkspaceReadStatusList,
14
+  getUserKnownMember,
15
+  postWorkspaceMember,
16
+  putUserWorkspaceRead
14 17
 } from '../action-creator.async.js'
15 18
 import {
16 19
   newFlashMessage,
17 20
   setWorkspaceDetail,
18 21
   setWorkspaceMemberList,
19 22
   setWorkspaceRecentActivityList,
23
+  setWorkspaceRecentActivityForUserList,
20 24
   setWorkspaceReadStatusList
21 25
 } from '../action-creator.sync.js'
22
-import { ROLE } from '../helper.js'
26
+import { ROLE, PAGE } from '../helper.js'
27
+import UserStatus from '../component/Dashboard/UserStatus.jsx'
23 28
 import ContentTypeBtn from '../component/Dashboard/ContentTypeBtn.jsx'
24 29
 import RecentActivity from '../component/Dashboard/RecentActivity.jsx'
25 30
 import MemberList from '../component/Dashboard/MemberList.jsx'
31
+import MoreInfo from '../component/Dashboard/MoreInfo.jsx'
26 32
 
27 33
 class Dashboard extends React.Component {
28 34
   constructor (props) {
29 35
     super(props)
30 36
     this.state = {
31 37
       workspaceIdInUrl: props.match.params.idws ? parseInt(props.match.params.idws) : null, // this is used to avoid handling the parseInt everytime
38
+      newMember: {
39
+        id: '',
40
+        avatarUrl: '',
41
+        nameOrEmail: '',
42
+        // createAccount: false, // @TODO ask DA about this checkbox if it is still usefull (since backend handles it all)
43
+        role: ''
44
+      },
45
+      searchedKnownMemberList: [],
32 46
       displayNewMemberDashboard: false,
33 47
       displayNotifBtn: false,
34 48
       displayWebdavBtn: false,
@@ -41,52 +55,126 @@ class Dashboard extends React.Component {
41 55
 
42 56
     const fetchWorkspaceDetail = await props.dispatch(getWorkspaceDetail(props.user, state.workspaceIdInUrl))
43 57
     switch (fetchWorkspaceDetail.status) {
44
-      case 200:
45
-        props.dispatch(setWorkspaceDetail(fetchWorkspaceDetail.json)); break
46
-      default:
47
-        props.dispatch(newFlashMessage(props.t('An error has happened while fetching workspace detail'), 'warning')); break
58
+      case 200: props.dispatch(setWorkspaceDetail(fetchWorkspaceDetail.json)); break
59
+      default: props.dispatch(newFlashMessage(`${props.t('An error has happened while fetching')} ${props.t('workspace detail')}`, 'warning')); break
48 60
     }
61
+    this.loadMemberList()
62
+    this.loadRecentActivity()
63
+  }
64
+
65
+  loadMemberList = async () => {
66
+    const { props, state } = this
49 67
 
50 68
     const fetchWorkspaceMemberList = await props.dispatch(getWorkspaceMemberList(props.user, state.workspaceIdInUrl))
51 69
     switch (fetchWorkspaceMemberList.status) {
52
-      case 200:
53
-        props.dispatch(setWorkspaceMemberList(fetchWorkspaceMemberList.json)); break
54
-      default:
55
-        props.dispatch(newFlashMessage(props.t('An error has happened while fetching member list'), 'warning')); break
70
+      case 200: props.dispatch(setWorkspaceMemberList(fetchWorkspaceMemberList.json)); break
71
+      default: props.dispatch(newFlashMessage(`${props.t('An error has happened while fetching')} ${props.t('member list')}`, 'warning')); break
56 72
     }
73
+  }
74
+
75
+  loadRecentActivity = async () => {
76
+    const { props, state } = this
57 77
 
58 78
     const fetchWorkspaceRecentActivityList = await props.dispatch(getWorkspaceRecentActivityList(props.user, state.workspaceIdInUrl))
79
+    const fetchWorkspaceReadStatusList = await props.dispatch(getWorkspaceReadStatusList(props.user, state.workspaceIdInUrl))
80
+
59 81
     switch (fetchWorkspaceRecentActivityList.status) {
60
-      case 200:
61
-        props.dispatch(setWorkspaceRecentActivityList(fetchWorkspaceRecentActivityList.json)); break
62
-      default:
63
-        props.dispatch(newFlashMessage(props.t('An error has happened while fetching recent activity list'), 'warning')); break
82
+      case 200: props.dispatch(setWorkspaceRecentActivityList(fetchWorkspaceRecentActivityList.json)); break
83
+      default: props.dispatch(newFlashMessage(`${props.t('An error has happened while fetching')} ${props.t('recent activity list')}`, 'warning')); break
64 84
     }
65 85
 
66
-    const fetchWorkspaceReadStatusList = await props.dispatch(getWorkspaceReadStatusList(props.user, state.workspaceIdInUrl))
67 86
     switch (fetchWorkspaceReadStatusList.status) {
87
+      case 200: props.dispatch(setWorkspaceReadStatusList(fetchWorkspaceReadStatusList.json)); break
88
+      default: props.dispatch(newFlashMessage(`${props.t('An error has happened while fetching')} ${props.t('read status list')}`, 'warning')); break
89
+    }
90
+
91
+    const readStatusForUserList = fetchWorkspaceReadStatusList.json.filter(c => c.read_by_user).map(c => c.content_id)
92
+    const recentActivityForUserList = fetchWorkspaceRecentActivityList.json.filter(content => !readStatusForUserList.includes(content.content_id))
93
+
94
+    props.dispatch(setWorkspaceRecentActivityForUserList(recentActivityForUserList))
95
+  }
96
+
97
+  handleToggleNewMemberDashboard = () => this.setState(prevState => ({displayNewMemberDashboard: !prevState.displayNewMemberDashboard}))
98
+
99
+  handleToggleNotifBtn = () => this.setState(prevState => ({displayNotifBtn: !prevState.displayNotifBtn}))
100
+
101
+  handleToggleWebdavBtn = () => this.setState(prevState => ({displayWebdavBtn: !prevState.displayWebdavBtn}))
102
+
103
+  handleToggleCalendarBtn = () => this.setState(prevState => ({displayCalendarBtn: !prevState.displayCalendarBtn}))
104
+
105
+  handleClickRecentContent = (idContent, typeContent) => this.props.history.push(PAGE.WORKSPACE.CONTENT(this.props.curWs.id, typeContent, idContent))
106
+
107
+  handleClickMarkRecentActivityAsRead = async () => {
108
+    const { props } = this
109
+    const fetchUserWorkspaceAllRead = await props.dispatch(putUserWorkspaceRead(props.user, props.curWs.id))
110
+    switch (fetchUserWorkspaceAllRead.status) {
111
+      case 204: this.loadRecentActivity(); break
112
+      default: props.dispatch(newFlashMessage(`${props.t('An error has happened while fetching "mark all as read"')}`, 'warning')); break
113
+    }
114
+  }
115
+
116
+  handleClickSeeMore = async () => {
117
+    console.log('nyi')
118
+  }
119
+
120
+  handleSearchUser = async userNameToSearch => {
121
+    const { props } = this
122
+    const fetchUserKnownMemberList = await props.dispatch(getUserKnownMember(props.user, userNameToSearch))
123
+    switch (fetchUserKnownMemberList.status) {
68 124
       case 200:
69
-        props.dispatch(setWorkspaceReadStatusList(fetchWorkspaceReadStatusList.json)); break
125
+        this.setState({searchedKnownMemberList: fetchUserKnownMemberList.json}); break
70 126
       default:
71
-        props.dispatch(newFlashMessage(props.t('An error has happened while fetching read status list'), 'warning')); break
127
+        props.dispatch(newFlashMessage(`${props.t('An error has happened while fetching')} ${props.t('known members list')}`, 'warning')); break
72 128
     }
73 129
   }
74 130
 
75
-  handleToggleNewMemberDashboard = () => this.setState(prevState => ({
76
-    displayNewMemberDashboard: !prevState.displayNewMemberDashboard
77
-  }))
131
+  handleChangeNewMemberNameOrEmail = newNameOrEmail => {
132
+    if (newNameOrEmail.length >= 2) this.handleSearchUser(newNameOrEmail)
133
+    this.setState(prev => ({newMember: {...prev.newMember, nameOrEmail: newNameOrEmail}}))
134
+  }
135
+
136
+  handleClickKnownMember = knownMember => {
137
+    this.setState(prev => ({
138
+      newMember: {
139
+        ...prev.newMember,
140
+        id: knownMember.user_id,
141
+        nameOrEmail: knownMember.public_name,
142
+        avatarUrl: knownMember.avatar_url
143
+      },
144
+      searchedKnownMemberList: []
145
+    }))
146
+  }
147
+
148
+  // handleChangeNewMemberCreateAccount = newCreateAccount => this.setState(prev => ({newMember: {...prev.newMember, createAccount: newCreateAccount}}))
149
+
150
+  handleChangeNewMemberRole = newRole => this.setState(prev => ({newMember: {...prev.newMember, role: newRole}}))
151
+
152
+  handleClickValidateNewMember = async () => {
153
+    const { props, state } = this
154
+
155
+    if (state.newMember.nameOrEmail === '') {
156
+      props.dispatch(newFlashMessage(props.t('Please set a name or email'), 'warning'))
157
+      return
158
+    }
78 159
 
79
-  handleToggleNotifBtn = () => this.setState(prevState => ({
80
-    displayNotifBtn: !prevState.displayNotifBtn
81
-  }))
160
+    if (state.newMember.role === '') {
161
+      props.dispatch(newFlashMessage(props.t('Please set a role'), 'warning'))
162
+      return
163
+    }
82 164
 
83
-  handleToggleWebdavBtn = () => this.setState(prevState => ({
84
-    displayWebdavBtn: !prevState.displayWebdavBtn
85
-  }))
165
+    const fetchWorkspaceNewMember = await props.dispatch(postWorkspaceMember(props.user, props.curWs.id, {
166
+      id: state.newMember.id,
167
+      name: state.newMember.nameOrEmail,
168
+      role: state.newMember.role
169
+    }))
86 170
 
87
-  handleToggleCalendarBtn = () => this.setState(prevState => ({
88
-    displayCalendarBtn: !prevState.displayCalendarBtn
89
-  }))
171
+    switch (fetchWorkspaceNewMember.status) {
172
+      case 200:
173
+        this.loadMemberList(); break
174
+      default:
175
+        props.dispatch(newFlashMessage(props.t('An error has happened while adding the member'), 'warning')); break
176
+    }
177
+  }
90 178
 
91 179
   render () {
92 180
     const { props, state } = this
@@ -118,72 +206,13 @@ class Dashboard extends React.Component {
118 206
                 </div>
119 207
               </div>
120 208
 
121
-              <div className='dashboard__userstatut'>
122
-                <div className='dashboard__userstatut__role'>
123
-                  <div className='dashboard__userstatut__role__msg'>
124
-                    {props.t('Hi {{name}} ! Currently, you are ', {name: props.user.public_name})}
125
-                  </div>
126
-
127
-                  {(() => {
128
-                    const myself = props.curWs.memberList.find(m => m.id === props.user.user_id)
129
-                    if (myself === undefined) return
130
-
131
-                    const myRole = ROLE.find(r => r.slug === myself.role)
132
-
133
-                    return (
134
-                      <div className='dashboard__userstatut__role__definition'>
135
-                        <div className='dashboard__userstatut__role__definition__icon'>
136
-                          <i className={`fa fa-${myRole.faIcon}`} />
137
-                        </div>
138
-
139
-                        <div className='dashboard__userstatut__role__definition__text'>
140
-                          {myRole.label}
141
-                        </div>
142
-                      </div>
143
-                    )
144
-                  })()}
145
-                </div>
146
-
147
-                <div className='dashboard__userstatut__notification'>
148
-                  <div className='dashboard__userstatut__notification__text'>
149
-                    {props.t("You have subscribed to this workspace's notifications")} (nyi)
150
-                  </div>
151
-
152
-                  {state.displayNotifBtn
153
-                    ? (
154
-                      <div className='dashboard__userstatut__notification__subscribe dropdown'>
155
-                        <button
156
-                          className='dashboard__userstatut__notification__subscribe__btn btn btn-outline-primary dropdown-toggle'
157
-                          type='button'
158
-                          id='dropdownMenuButton'
159
-                          data-toggle='dropdown'
160
-                          aria-haspopup='true'
161
-                          aria-expanded='false'
162
-                        >
163
-                          {props.t('subscriber')}
164
-                        </button>
165
-
166
-                        <div className='dashboard__userstatut__notification__subscribe__submenu dropdown-menu'>
167
-                          <div className='dashboard__userstatut__notification__subscribe__submenu__item dropdown-item'>
168
-                            {props.t('subscriber')}
169
-                          </div>
170
-                          <div className='dashboard__userstatut__notification__subscribe__submenu__item dropdown-item dropdown-item'>
171
-                            {props.t('unsubscribed')}
172
-                          </div>
173
-                        </div>
174
-                      </div>
175
-                    )
176
-                    : (
177
-                      <div
178
-                        className='dashboard__userstatut__notification__btn btn btn-outline-primary'
179
-                        onClick={this.handleToggleNotifBtn}
180
-                      >
181
-                        {props.t('Change your status')}
182
-                      </div>
183
-                    )
184
-                  }
185
-                </div>
186
-              </div>
209
+              <UserStatus
210
+                user={props.user}
211
+                curWs={props.curWs}
212
+                displayNotifBtn={state.displayNotifBtn}
213
+                onClickToggleNotifBtn={this.handleToggleNotifBtn}
214
+                t={props.t}
215
+              />
187 216
             </div>
188 217
 
189 218
             <div className='dashboard__calltoaction justify-content-xl-center'>
@@ -202,9 +231,11 @@ class Dashboard extends React.Component {
202 231
             <div className='dashboard__workspaceInfo'>
203 232
               <RecentActivity
204 233
                 customClass='dashboard__activity'
205
-                recentActivityFilteredForUser={props.curWs.recentActivityList.filter(content => !props.curWs.contentReadStatusList.includes(content.id))}
234
+                recentActivityFilteredForUser={props.curWs.recentActivityForUserList}
206 235
                 contentTypeList={props.contentType}
207
-                onClickSeeMore={() => {}}
236
+                onClickRecentContent={this.handleClickRecentContent}
237
+                onClickEverythingAsRead={this.handleClickMarkRecentActivityAsRead}
238
+                onClickSeeMore={this.handleClickSeeMore}
208 239
                 t={props.t}
209 240
               />
210 241
 
@@ -212,70 +243,26 @@ class Dashboard extends React.Component {
212 243
                 customClass='dashboard__memberlist'
213 244
                 memberList={props.curWs.memberList}
214 245
                 roleList={ROLE}
246
+                searchedKnownMemberList={state.searchedKnownMemberList}
247
+                nameOrEmail={state.newMember.nameOrEmail}
248
+                onChangeNameOrEmail={this.handleChangeNewMemberNameOrEmail}
249
+                onClickKnownMember={this.handleClickKnownMember}
250
+                // createAccount={state.newMember.createAccount}
251
+                // onChangeCreateAccount={this.handleChangeNewMemberCreateAccount}
252
+                role={state.newMember.role}
253
+                onChangeRole={this.handleChangeNewMemberRole}
254
+                onClickValidateNewMember={this.handleClickValidateNewMember}
215 255
                 t={props.t}
216 256
               />
217 257
             </div>
218 258
 
219
-            <div className='dashboard__moreinfo'>
220
-              <div className='dashboard__moreinfo__webdav genericBtnInfoDashboard'>
221
-                <div
222
-                  className='dashboard__moreinfo__webdav__btn genericBtnInfoDashboard__btn'
223
-                  onClick={this.handleToggleWebdavBtn}
224
-                >
225
-                  <div className='dashboard__moreinfo__webdav__btn__icon genericBtnInfoDashboard__btn__icon'>
226
-                    <i className='fa fa-windows' />
227
-                  </div>
228
-
229
-                  <div className='dashboard__moreinfo__webdav__btn__text genericBtnInfoDashboard__btn__text'>
230
-                    {this.props.t('Implement Tracim in your explorer')}
231
-                  </div>
232
-                </div>
233
-                {this.state.displayWebdavBtn === true &&
234
-                <div>
235
-                  <div className='dashboard__moreinfo__webdav__information genericBtnInfoDashboard__info'>
236
-                    <div className='dashboard__moreinfo__webdav__information__text genericBtnInfoDashboard__info__text'>
237
-                      {this.props.t('Find all your documents deposited online directly on your computer via the workstation, without going through the software.')}'
238
-                    </div>
239
-
240
-                    <div className='dashboard__moreinfo__webdav__information__link genericBtnInfoDashboard__info__link'>
241
-                      http://algoo.trac.im/webdav/
242
-                    </div>
243
-                  </div>
244
-                </div>
245
-                }
246
-              </div>
247
-              <div className='dashboard__moreinfo__calendar genericBtnInfoDashboard'>
248
-                <div className='dashboard__moreinfo__calendar__wrapperBtn'>
249
-                  <div
250
-                    className='dashboard__moreinfo__calendar__btn genericBtnInfoDashboard__btn'
251
-                    onClick={this.handleToggleCalendarBtn}
252
-                  >
253
-                    <div className='dashboard__moreinfo__calendar__btn__icon genericBtnInfoDashboard__btn__icon'>
254
-                      <i className='fa fa-calendar' />
255
-                    </div>
256
-
257
-                    <div className='dashboard__moreinfo__calendar__btn__text genericBtnInfoDashboard__btn__text'>
258
-                      {this.props.t('Workspace Calendar')}
259
-                    </div>
260
-                  </div>
261
-                </div>
262
-                <div className='dashboard__moreinfo__calendar__wrapperText'>
263
-                  {this.state.displayCalendarBtn === true &&
264
-                  <div>
265
-                    <div className='dashboard__moreinfo__calendar__information genericBtnInfoDashboard__info'>
266
-                      <div className='dashboard__moreinfo__calendar__information__text genericBtnInfoDashboard__info__text'>
267
-                        {this.props.t('Each workspace has its own calendar.')}
268
-                      </div>
269
-
270
-                      <div className='dashboard__moreinfo__calendar__information__link genericBtnInfoDashboard__info__link'>
271
-                        http://algoo.trac.im/calendar/
272
-                      </div>
273
-                    </div>
274
-                  </div>
275
-                  }
276
-                </div>
277
-              </div>
278
-            </div>
259
+            <MoreInfo
260
+              onClickToggleWebdav={this.handleToggleWebdavBtn}
261
+              displayWebdavBtn={state.displayWebdavBtn}
262
+              onClickToggleCalendar={this.handleToggleCalendarBtn}
263
+              displayCalendarBtn={state.displayCalendarBtn}
264
+              t={props.t}
265
+            />
279 266
           </PageContent>
280 267
         </PageWrapper>
281 268
       </div>

+ 6 - 163
frontend/src/css/Dashboard.styl View File

@@ -1,35 +1,9 @@
1
+@import "../../node_modules/tracim_frontend_lib/src/css/Variable.styl"
2
+
1 3
 flexwrap()
2 4
   display flex
3 5
   flex-wrap wrap
4 6
 
5
-btnNotification()
6
-  margin 20px 0
7
-  border 1px solid thirdColor
8
-  padding 10px 15px
9
-
10
-hoverfocus()
11
-  background-color thirdColor
12
-  color white
13
-
14
-bgandcolor()
15
-  background-color transparent
16
-  color thirdColor
17
-
18
-label()
19
-  font-weight 500
20
-  font-size 18px
21
-  color thirdColor
22
-
23
-coloricon()
24
-  .fa-gavel
25
-    color responsable
26
-  .fa-graduation-cap
27
-    color gestionnaire
28
-  .fa-pencil
29
-    color contributeur
30
-  .fa-eye
31
-    color lecteur
32
-
33 7
 .dashboard
34 8
   width 100%
35 9
   &__header
@@ -55,30 +29,6 @@ coloricon()
55 29
     &__detail
56 30
       margin-bottom 20px
57 31
       font-size 18px
58
-  &__userstatut
59
-    width 35%
60
-    &__role
61
-      margin 20px 0
62
-      font-size 18px
63
-      &__msg
64
-        margin-right 15px
65
-      &__definition
66
-        display flex
67
-        &__icon
68
-          margin-right 15px
69
-          color gestionnaire
70
-    &__notification
71
-      font-size 18px
72
-      &__btn
73
-        btnNotification()
74
-        cursor pointer
75
-      &__subscribe
76
-        &__btn
77
-          btnNotification()
78
-        &__submenu
79
-          padding 0
80
-          &__item
81
-            padding 10px
82 32
   &__calltoaction
83 33
     flexwrap()
84 34
     margin 100px 0
@@ -93,66 +43,6 @@ coloricon()
93 43
           font-size 18px
94 44
   &__workspaceInfo
95 45
     flexwrap()
96
-  &__activity
97
-    margin 0 35px 50px 0
98
-    width 60%
99
-    &__wrapper
100
-      border 1px solid grey
101
-      height 480px
102
-      overflow-y scroll
103
-    &__header
104
-      display flex
105
-      justify-content space-between
106
-      align-items center
107
-      margin-bottom 20px
108
-      height 44px
109
-      &__allread
110
-        padding 10px 25px
111
-        font-size 18px
112
-        cursor pointer
113
-    &__workspace
114
-      display flex
115
-      align-items center
116
-      border-bottom 1px solid grey
117
-      padding 15px
118
-      cursor pointer
119
-      &:hover
120
-        background-color fourthColor
121
-      &:nth-child(even)
122
-        background-color grey-hover
123
-        &:hover
124
-          background-color fourthColor
125
-      &__icon
126
-        margin 0 25px
127
-        font-size 25px
128
-      &__name
129
-        font-size 18px
130
-        font-weight 500
131
-        span
132
-          font-weight 400
133
-    &__more
134
-      &__btn
135
-        margin 15px
136
-        padding 10px 25px
137
-        cursor pointer
138
-  &__moreinfo
139
-    display flex
140
-    justify-content space-between
141
-    flexwrap wrap
142
-    &__webdav
143
-      margin 0 15px 40px 0
144
-      &__btn
145
-        width 300px
146
-      &__information
147
-        width 300px
148
-    &__calendar
149
-      margin-bottom 100px
150
-      &__wrapperBtn
151
-        margin-right 290px
152
-      &__btn
153
-        width 300px
154
-      &__information
155
-        width 300px
156 46
 
157 47
 /**** MEDIAQUERIES *****/
158 48
 
@@ -169,10 +59,6 @@ coloricon()
169 59
       width auto
170 60
     &__calltoaction
171 61
       justify-content center
172
-    &__activity
173
-      width 100%
174
-    &__memberlist
175
-      width 50%
176 62
 
177 63
 /**** MEDIA 992px & 1199px ****/
178 64
 
@@ -181,14 +67,6 @@ coloricon()
181 67
   .dashboard
182 68
     margin-left 15px
183 69
 
184
-/**** MEDIA 768px & 991px ****/
185
-
186
-@media (min-width: min-md) and (max-width: max-md)
187
-
188
-  .dashboard
189
-    &__activity
190
-      margin 25px 15px 25px 0
191
-
192 70
 /**** MEDIA 576px & 767px ****/
193 71
 
194 72
 @media (min-width: min-sm) and (max-width: max-sm)
@@ -196,57 +74,22 @@ coloricon()
196 74
   .dashboard
197 75
     &__activity
198 76
       margin 25px 15px 25px 0
199
-    &__memberlist
200
-      margin 50px 0
201
-      width 90%
202
-    &__moreinfo__webdav__information
203
-      width 500px
204 77
 
205 78
 /**** MEDIA 575px ****/
206 79
 
207 80
 @media (max-width: max-xs)
208 81
 
209
-  position()
210
-    margin-left 10px
211
-    width auto
212
-
213 82
   .dashboard
214 83
     margin-left 0
215 84
     &__title
216 85
       margin-left 10px
217 86
     &__workspace
218
-      position()
87
+      margin-left 10px
88
+      width auto
219 89
     &__userstatut
220
-     position()
90
+      margin-left 10px
91
+      width auto
221 92
     &__calltoaction
222 93
       justify-content center
223 94
       &__button
224 95
         margin 10px
225
-    &__activity
226
-      margin 25px 0
227
-      width 100%
228
-      &__header
229
-        display block
230
-        height auto
231
-        margin 0 15px 20px 15px
232
-        &__title
233
-          margin-bottom 20px
234
-    &__memberlist
235
-      margin 50px 0
236
-      width 100%
237
-      &__title
238
-        margin-left 10px
239
-      &__wrapper
240
-        height auto
241
-      &__list
242
-        height auto
243
-        overflow-Y visible
244
-        &__item:nth-last-child(1)
245
-          border-bottom 1px solid grey
246
-      &__btnadd
247
-        border-top 0
248
-    &__moreinfo
249
-      &__webdav
250
-        margin-left 10px
251
-        &__information
252
-          width 350px

+ 19 - 1
frontend/src/reducer/currentWorkspace.js View File

@@ -2,7 +2,7 @@ import {
2 2
   SET,
3 3
   WORKSPACE_DETAIL,
4 4
   WORKSPACE_MEMBER_LIST,
5
-  WORKSPACE_READ_STATUS_LIST,
5
+  WORKSPACE_READ_STATUS_LIST, WORKSPACE_RECENT_ACTIVITY_FOR_USER_LIST,
6 6
   WORKSPACE_RECENT_ACTIVITY_LIST
7 7
 } from '../action-creator.sync.js'
8 8
 import { handleRouteFromApi } from '../helper.js'
@@ -15,6 +15,7 @@ const defaultWorkspace = {
15 15
   sidebarEntryList: [],
16 16
   memberList: [],
17 17
   recentActivityList: [],
18
+  recentActivityForUserList: [],
18 19
   contentReadStatusList: []
19 20
 }
20 21
 
@@ -65,6 +66,23 @@ export default function currentWorkspace (state = defaultWorkspace, action) {
65 66
         }))
66 67
       }
67 68
 
69
+    case `${SET}/${WORKSPACE_RECENT_ACTIVITY_FOR_USER_LIST}`:
70
+      return {
71
+        ...state,
72
+        recentActivityForUserList: action.workspaceRecentActivityForUserList.map(ra => ({
73
+          id: ra.content_id,
74
+          slug: ra.slug,
75
+          label: ra.label,
76
+          type: ra.content_type,
77
+          idParent: ra.parent_id,
78
+          showInUi: ra.show_in_ui,
79
+          isArchived: ra.is_archived,
80
+          isDeleted: ra.is_deleted,
81
+          statusSlug: ra.status,
82
+          subContentTypeSlug: ra.sub_content_types
83
+        }))
84
+      }
85
+
68 86
     case `${SET}/${WORKSPACE_READ_STATUS_LIST}`:
69 87
       return {
70 88
         ...state,