Browse Source

fixed routing and initialization data loading for sidebar

Skylsmoi 6 years ago
parent
commit
0713817e8e

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

21
 
21
 
22
     <div className='activity__wrapper'>
22
     <div className='activity__wrapper'>
23
       {props.recentActivityList.map(content => {
23
       {props.recentActivityList.map(content => {
24
-        const contentType = props.contentTypeList.find(ct => ct.slug === content.type)
24
+        const contentType = props.contentTypeList.find(ct => ct.slug === content.type) || {hexcolor: '', faIcon: ''}
25
         return (
25
         return (
26
           <div
26
           <div
27
             className={classnames('activity__workspace', {'read': props.readByUserList.includes(content.id)})}
27
             className={classnames('activity__workspace', {'read': props.readByUserList.includes(content.id)})}

+ 5 - 10
frontend/src/container/Account.jsx View File

29
         name: 'personalData',
29
         name: 'personalData',
30
         menuLabel: 'Mon profil',
30
         menuLabel: 'Mon profil',
31
         active: true
31
         active: true
32
-      },
33
-      {
32
+      }, {
34
         name: 'notification',
33
         name: 'notification',
35
         menuLabel: 'Espace de travail & Notifications',
34
         menuLabel: 'Espace de travail & Notifications',
36
         active: false
35
         active: false
37
-      },
38
-      {
36
+      }, {
39
         name: 'password',
37
         name: 'password',
40
         menuLabel: 'Mot de passe',
38
         menuLabel: 'Mot de passe',
41
         active: false
39
         active: false
42
-      },
43
-      {
40
+      }, {
44
         name: 'timezone',
41
         name: 'timezone',
45
         menuLabel: 'Fuseau Horaire',
42
         menuLabel: 'Fuseau Horaire',
46
         active: false
43
         active: false
79
     const subComponent = (() => {
76
     const subComponent = (() => {
80
       switch (this.state.subComponentMenu.find(({active}) => active).name) {
77
       switch (this.state.subComponentMenu.find(({active}) => active).name) {
81
         case 'personalData':
78
         case 'personalData':
82
-          return <PersonalData
83
-          />
79
+          return <PersonalData />
84
 
80
 
85
         // case 'calendar':
81
         // case 'calendar':
86
         //   return <Calendar user={this.props.user} />
82
         //   return <Calendar user={this.props.user} />
92
           />
88
           />
93
 
89
 
94
         case 'password':
90
         case 'password':
95
-          return <Password
96
-          />
91
+          return <Password />
97
 
92
 
98
         case 'timezone':
93
         case 'timezone':
99
           return <Timezone timezone={this.props.timezone} onChangeTimezone={this.handleChangeTimezone} />
94
           return <Timezone timezone={this.props.timezone} onChangeTimezone={this.handleChangeTimezone} />

+ 51 - 6
frontend/src/container/Login.jsx View File

1
 import React from 'react'
1
 import React from 'react'
2
 import { connect } from 'react-redux'
2
 import { connect } from 'react-redux'
3
-import { Redirect } from 'react-router'
3
+import { withRouter, Redirect } from 'react-router'
4
 import { translate } from 'react-i18next'
4
 import { translate } from 'react-i18next'
5
 import Cookies from 'js-cookie'
5
 import Cookies from 'js-cookie'
6
 import LoginLogo from '../component/Login/LoginLogo.jsx'
6
 import LoginLogo from '../component/Login/LoginLogo.jsx'
7
 import LoginLogoImg from '../img/logoTracimWhite.svg'
7
 import LoginLogoImg from '../img/logoTracimWhite.svg'
8
-import { postUserLogin } from '../action-creator.async.js'
9
 import Card from '../component/common/Card/Card.jsx'
8
 import Card from '../component/common/Card/Card.jsx'
10
 import CardHeader from '../component/common/Card/CardHeader.jsx'
9
 import CardHeader from '../component/common/Card/CardHeader.jsx'
11
 import CardBody from '../component/common/Card/CardBody.jsx'
10
 import CardBody from '../component/common/Card/CardBody.jsx'
14
 import LoginBtnForgotPw from '../component/Login/LoginBtnForgotPw.jsx'
13
 import LoginBtnForgotPw from '../component/Login/LoginBtnForgotPw.jsx'
15
 import {
14
 import {
16
   newFlashMessage,
15
   newFlashMessage,
17
-  setUserConnected
16
+  setUserConnected,
17
+  updateWorkspaceListData,
18
+  setWorkspaceListIsOpenInSidebar,
19
+  setContentTypeList,
20
+  setAppList
18
 } from '../action-creator.sync.js'
21
 } from '../action-creator.sync.js'
22
+import {
23
+  getAppList,
24
+  getContentTypeList,
25
+  getWorkspaceList,
26
+  postUserLogin
27
+} from '../action-creator.async.js'
19
 import { COOKIE, PAGE } from '../helper.js'
28
 import { COOKIE, PAGE } from '../helper.js'
20
 import { Checkbox } from 'tracim_frontend_lib'
29
 import { Checkbox } from 'tracim_frontend_lib'
21
 
30
 
51
     const userAuth = btoa(`${inputLogin.value}:${inputPassword.value}`)
60
     const userAuth = btoa(`${inputLogin.value}:${inputPassword.value}`)
52
 
61
 
53
     if (fetchPostUserLogin.status === 200) {
62
     if (fetchPostUserLogin.status === 200) {
54
-      dispatch(setUserConnected({
63
+      const loggedUser = {
55
         ...fetchPostUserLogin.json,
64
         ...fetchPostUserLogin.json,
56
         auth: userAuth,
65
         auth: userAuth,
57
         logged: true
66
         logged: true
58
-      }))
67
+      }
68
+
69
+      dispatch(setUserConnected(loggedUser))
70
+
71
+      this.loadAppConfig(loggedUser)
72
+      this.loadWorkspaceList(loggedUser)
59
 
73
 
60
       if (inputRememberMe) {
74
       if (inputRememberMe) {
61
         Cookies.set(COOKIE.USER_LOGIN, inputLogin.value, {expires: 365})
75
         Cookies.set(COOKIE.USER_LOGIN, inputLogin.value, {expires: 365})
71
     }
85
     }
72
   }
86
   }
73
 
87
 
88
+  // @FIXME Côme - 2018/08/22 - this function is duplicated from Tracim.jsx
89
+  loadAppConfig = async user => {
90
+    const { props } = this
91
+
92
+    const fetchGetAppList = await props.dispatch(getAppList(user))
93
+    if (fetchGetAppList.status === 200) props.dispatch(setAppList(fetchGetAppList.json))
94
+
95
+    const fetchGetContentTypeList = await props.dispatch(getContentTypeList(user))
96
+    if (fetchGetContentTypeList.status === 200) props.dispatch(setContentTypeList(fetchGetContentTypeList.json))
97
+  }
98
+
99
+  // @FIXME Côme - 2018/08/22 - this function is duplicated from Tracim.jsx
100
+  loadWorkspaceList = async user => {
101
+    const { props } = this
102
+
103
+    const fetchGetWorkspaceList = await props.dispatch(getWorkspaceList(user))
104
+
105
+    if (fetchGetWorkspaceList.status === 200) {
106
+      props.dispatch(updateWorkspaceListData(fetchGetWorkspaceList.json))
107
+
108
+      const idWorkspaceToOpen = (() =>
109
+        props.match && props.match.params.idws !== undefined && !isNaN(props.match.params.idws)
110
+          ? parseInt(props.match.params.idws)
111
+          : fetchGetWorkspaceList.json[0].workspace_id
112
+      )()
113
+
114
+      props.dispatch(setWorkspaceListIsOpenInSidebar(idWorkspaceToOpen, true))
115
+    }
116
+  }
117
+
74
   render () {
118
   render () {
75
     if (this.props.user.logged) return <Redirect to={{pathname: '/'}} />
119
     if (this.props.user.logged) return <Redirect to={{pathname: '/'}} />
76
     else {
120
     else {
118
                             <Checkbox
162
                             <Checkbox
119
                               name='inputRememberMe'
163
                               name='inputRememberMe'
120
                               checked={this.state.inputRememberMe}
164
                               checked={this.state.inputRememberMe}
165
+                              onClickCheckbox={() => {}}
121
                             />
166
                             />
122
                             Se souvenir de moi
167
                             Se souvenir de moi
123
                           </div>
168
                           </div>
161
 }
206
 }
162
 
207
 
163
 const mapStateToProps = ({ user }) => ({ user })
208
 const mapStateToProps = ({ user }) => ({ user })
164
-export default connect(mapStateToProps)(translate()(Login))
209
+export default withRouter(connect(mapStateToProps)(translate()(Login)))

+ 15 - 58
frontend/src/container/Sidebar.jsx View File

6
 import appFactory from '../appFactory.js'
6
 import appFactory from '../appFactory.js'
7
 import WorkspaceListItem from '../component/Sidebar/WorkspaceListItem.jsx'
7
 import WorkspaceListItem from '../component/Sidebar/WorkspaceListItem.jsx'
8
 import {
8
 import {
9
-  setAppList,
10
-  setContentTypeList,
11
-  setWorkspaceListIsOpenInSidebar,
12
-  updateWorkspaceFilter,
13
-  updateWorkspaceListData
9
+  setWorkspaceListIsOpenInSidebar
14
 } from '../action-creator.sync.js'
10
 } from '../action-creator.sync.js'
15
-import {
16
-  getAppList, getContentTypeList,
17
-  getWorkspaceList
18
-} from '../action-creator.async.js'
19
 import { PAGE, workspaceConfig } from '../helper.js'
11
 import { PAGE, workspaceConfig } from '../helper.js'
20
 
12
 
21
 const qs = require('query-string')
13
 const qs = require('query-string')
25
     super(props)
17
     super(props)
26
     this.state = {
18
     this.state = {
27
       sidebarClose: false,
19
       sidebarClose: false,
20
+      workspaceListLoaded: false,
28
       workspaceIdInUrl: props.match && props.match.params.idws ? parseInt(props.match.params.idws) : null
21
       workspaceIdInUrl: props.match && props.match.params.idws ? parseInt(props.match.params.idws) : null
29
     }
22
     }
30
 
23
 
40
     }
33
     }
41
   }
34
   }
42
 
35
 
43
-  componentDidMount () {
44
-    // console.log('Sidebar Did Mount', this.props)
45
-    this.loadAppConfigAndWorkspaceList()
46
-  }
47
-
48
   componentDidUpdate (prevProps, prevState) {
36
   componentDidUpdate (prevProps, prevState) {
49
     const { props } = this
37
     const { props } = this
50
 
38
 
51
-    // console.log('%c<Sidebar> Did Update', 'color: #c17838')
52
-    if (!props.match || props.match.params.idws === undefined || isNaN(props.match.params.idws)) return
53
-
54
-    const newWorkspaceId = parseInt(props.match.params.idws)
55
-    if (prevState.workspaceIdInUrl !== newWorkspaceId) this.setState({workspaceIdInUrl: newWorkspaceId})
56
-  }
57
-
58
-  loadAppConfigAndWorkspaceList = async () => {
59
-    const { workspaceIdInUrl } = this.state
60
-    const { user, dispatch } = this.props
61
-
62
-    if (user.user_id !== -1) {
63
-      const fetchGetAppList = await dispatch(getAppList(user))
64
-      if (fetchGetAppList.status === 200) dispatch(setAppList(fetchGetAppList.json))
65
-
66
-      const fetchGetContentTypeList = await dispatch(getContentTypeList(user))
67
-      if (fetchGetContentTypeList.status === 200) dispatch(setContentTypeList(fetchGetContentTypeList.json))
68
-
69
-      const fetchGetWorkspaceList = await dispatch(getWorkspaceList(user))
39
+    if (!this.shouldDisplaySidebar()) return
70
 
40
 
71
-      if (fetchGetWorkspaceList.status === 200) {
72
-        dispatch(updateWorkspaceListData(fetchGetWorkspaceList.json))
73
-        dispatch(setWorkspaceListIsOpenInSidebar(workspaceIdInUrl || fetchGetWorkspaceList.json[0].workspace_id, true))
74
-      }
41
+    // console.log('%c<Sidebar> Did Update', 'color: #c17838')
42
+    if (props.match && props.match.params.idws !== undefined && !isNaN(props.match.params.idws)) {
43
+      const newWorkspaceId = parseInt(props.match.params.idws)
44
+      if (prevState.workspaceIdInUrl !== newWorkspaceId) this.setState({workspaceIdInUrl: newWorkspaceId})
75
     }
45
     }
76
   }
46
   }
77
 
47
 
78
-  handleClickWorkspace = (idWs, newIsOpenInSidebar) => this.props.dispatch(setWorkspaceListIsOpenInSidebar(idWs, newIsOpenInSidebar))
79
-
80
-  handleClickAllContent = idWs => {
81
-    this.props.dispatch(updateWorkspaceFilter([]))
82
-
83
-    this.props.history.push(PAGE.WORKSPACE.CONTENT_LIST(idWs))
48
+  shouldDisplaySidebar = () => {
49
+    const pageWithoutSidebar = [PAGE.LOGIN]
50
+    return !pageWithoutSidebar.includes(this.props.location.pathname)
84
   }
51
   }
85
 
52
 
86
-  // @DEPRECATED
87
-  // not used, right now, link on sidebar filters is a <Link>
88
-  handleClickContentFilter = (idWs, filter) => {
89
-    const { workspace, history } = this.props
90
-
91
-    const newFilter = workspace.filter.includes(filter) ? [] : [filter] // use an array to allow multiple filters (NYI)
92
-
93
-    history.push(`${PAGE.WORKSPACE.CONTENT_LIST(idWs)}?type=${newFilter.join(';')}`) // workspace.filter gets updated on react redraw from match.params
53
+  handleClickWorkspace = (idWs, newIsOpenInSidebar) => this.props.dispatch(setWorkspaceListIsOpenInSidebar(idWs, newIsOpenInSidebar))
94
 
54
 
95
-    // obviously, it's ugly to use custom event to tell WorkspaceContentList to refresh, but since WorkspaceContentList
96
-    // will end up being an App, it'll have to be that way. So it's fine
97
-    GLOBAL_dispatchEvent({ type: 'refreshContentList', data: {} })
98
-  }
55
+  handleClickAllContent = idWs => this.props.history.push(PAGE.WORKSPACE.CONTENT_LIST(idWs))
99
 
56
 
100
   handleClickToggleSidebar = () => this.setState(prev => ({sidebarClose: !prev.sidebarClose}))
57
   handleClickToggleSidebar = () => this.setState(prev => ({sidebarClose: !prev.sidebarClose}))
101
 
58
 
105
     const { sidebarClose, workspaceIdInUrl } = this.state
62
     const { sidebarClose, workspaceIdInUrl } = this.state
106
     const { activeLang, workspaceList, t } = this.props
63
     const { activeLang, workspaceList, t } = this.props
107
 
64
 
65
+    if (!this.shouldDisplaySidebar()) return null
66
+
108
     return (
67
     return (
109
       <div className={classnames('sidebar primaryColorBgDarken', {'sidebarclose': sidebarClose})}>
68
       <div className={classnames('sidebar primaryColorBgDarken', {'sidebarclose': sidebarClose})}>
110
 
69
 
125
                   isOpenInSidebar={ws.isOpenInSidebar}
84
                   isOpenInSidebar={ws.isOpenInSidebar}
126
                   onClickTitle={() => this.handleClickWorkspace(ws.id, !ws.isOpenInSidebar)}
85
                   onClickTitle={() => this.handleClickWorkspace(ws.id, !ws.isOpenInSidebar)}
127
                   onClickAllContent={this.handleClickAllContent}
86
                   onClickAllContent={this.handleClickAllContent}
128
-                  // onClickContentFilter={this.handleClickContentFilter}
129
                   key={ws.id}
87
                   key={ws.id}
130
                 />
88
                 />
131
               )}
89
               )}
156
   }
114
   }
157
 }
115
 }
158
 
116
 
159
-const mapStateToProps = ({ lang, user, workspace, workspaceList }) => ({
117
+const mapStateToProps = ({ lang, user, workspaceList }) => ({
160
   activeLang: lang.find(l => l.active) || {id: 'en'},
118
   activeLang: lang.find(l => l.active) || {id: 'en'},
161
   user,
119
   user,
162
-  workspace,
163
   workspaceList
120
   workspaceList
164
 })
121
 })
165
 export default withRouter(connect(mapStateToProps)(appFactory(translate()(Sidebar))))
122
 export default withRouter(connect(mapStateToProps)(appFactory(translate()(Sidebar))))

+ 81 - 51
frontend/src/container/Tracim.jsx View File

14
 } from 'react-router-dom'
14
 } from 'react-router-dom'
15
 import { COOKIE, PAGE } from '../helper.js'
15
 import { COOKIE, PAGE } from '../helper.js'
16
 import {
16
 import {
17
-  getUserIsConnected
17
+  getAppList,
18
+  getContentTypeList,
19
+  getUserIsConnected, getWorkspaceList
18
 } from '../action-creator.async.js'
20
 } from '../action-creator.async.js'
19
 import {
21
 import {
20
   newFlashMessage,
22
   newFlashMessage,
21
   removeFlashMessage,
23
   removeFlashMessage,
22
-  setUserConnected
24
+  setAppList,
25
+  setContentTypeList,
26
+  setUserConnected, setWorkspaceListIsOpenInSidebar, updateWorkspaceListData
23
 } from '../action-creator.sync.js'
27
 } from '../action-creator.sync.js'
24
 import Cookies from 'js-cookie'
28
 import Cookies from 'js-cookie'
25
 import Dashboard from './Dashboard.jsx'
29
 import Dashboard from './Dashboard.jsx'
61
           auth: userFromCookies.auth,
65
           auth: userFromCookies.auth,
62
           logged: true
66
           logged: true
63
         }))
67
         }))
68
+        this.loadAppConfig()
69
+        this.loadWorkspaceList()
64
         break
70
         break
65
       case 401:
71
       case 401:
66
         dispatch(setUserConnected({logged: false})); break
72
         dispatch(setUserConnected({logged: false})); break
69
     }
75
     }
70
   }
76
   }
71
 
77
 
78
+  loadAppConfig = async () => {
79
+    const { props } = this
80
+
81
+    const fetchGetAppList = await props.dispatch(getAppList(props.user))
82
+    if (fetchGetAppList.status === 200) props.dispatch(setAppList(fetchGetAppList.json))
83
+
84
+    const fetchGetContentTypeList = await props.dispatch(getContentTypeList(props.user))
85
+    if (fetchGetContentTypeList.status === 200) props.dispatch(setContentTypeList(fetchGetContentTypeList.json))
86
+  }
87
+
88
+  loadWorkspaceList = async () => {
89
+    const { props } = this
90
+
91
+    const fetchGetWorkspaceList = await props.dispatch(getWorkspaceList(props.user))
92
+
93
+    if (fetchGetWorkspaceList.status === 200) {
94
+      this.setState({workspaceListLoaded: true})
95
+
96
+      props.dispatch(updateWorkspaceListData(fetchGetWorkspaceList.json))
97
+
98
+      const idWorkspaceToOpen = (() =>
99
+        props.match && props.match.params.idws !== undefined && !isNaN(props.match.params.idws)
100
+          ? parseInt(props.match.params.idws)
101
+          : fetchGetWorkspaceList.json[0].workspace_id
102
+      )()
103
+
104
+      props.dispatch(setWorkspaceListIsOpenInSidebar(idWorkspaceToOpen, true))
105
+    }
106
+  }
107
+
72
   handleRemoveFlashMessage = msg => this.props.dispatch(removeFlashMessage(msg))
108
   handleRemoveFlashMessage = msg => this.props.dispatch(removeFlashMessage(msg))
73
 
109
 
74
   render () {
110
   render () {
85
         <Header />
121
         <Header />
86
         <FlashMessage flashMessage={props.flashMessage} removeFlashMessage={this.handleRemoveFlashMessage} t={props.t} />
122
         <FlashMessage flashMessage={props.flashMessage} removeFlashMessage={this.handleRemoveFlashMessage} t={props.t} />
87
 
123
 
88
-        <div className='tracim__content'>
89
-          <Route path={PAGE.LOGIN} component={Login} />
90
-
91
-          <Route exact path='/' component={() => {
92
-            switch (props.user.logged) {
93
-              case true:
94
-                return <Redirect to={{pathname: PAGE.WORKSPACE.ROOT, state: {from: props.location}}} />
95
-              case false:
96
-                return <Redirect to={{pathname: '/login', state: {from: props.location}}} />
97
-              case null:
98
-                return null
99
-            }
100
-          }} />
101
-
102
-          <Route path='/workspaces/:idws?' render={() => // Workspace Router
103
-            <div className='sidebarpagecontainer'>
104
-              <Sidebar />
105
-
106
-              <Route exact path={PAGE.WORKSPACE.ROOT} render={() => props.workspaceList.length === 0 // handle '/' and redirect to first workspace
107
-                ? null // @FIXME this needs to be handled in case of new user that has no workspace
108
-                : <Redirect to={{pathname: PAGE.WORKSPACE.DASHBOARD(props.workspaceList[0].id), state: {from: props.location}}} />
109
-              } />
110
-
111
-              <Route exact path={`${PAGE.WORKSPACE.ROOT}/:idws`} render={props2 => // handle '/workspaces/:id' and add '/contents'
112
-                <Redirect to={{pathname: PAGE.WORKSPACE.CONTENT_LIST(props2.match.params.idws), state: {from: props.location}}} />
113
-              } />
114
-
115
-              <Route path={PAGE.WORKSPACE.DASHBOARD(':idws')} component={Dashboard} />
116
-              <Route path={PAGE.WORKSPACE.CALENDAR(':idws')} component={() => <div><br /><br /><br /><br />NYI</div>} />
117
-              <Route path={PAGE.WORKSPACE.CONTENT(':idws', ':type', ':idcts')} component={WorkspaceContent} />
118
-              <Route exact path={PAGE.WORKSPACE.CONTENT_LIST(':idws')} component={WorkspaceContent} />
119
-            </div>
120
-          } />
121
-
122
-          <Route path={PAGE.ACCOUNT} render={() =>
123
-            <div className='sidebarpagecontainer'>
124
-              <Sidebar />
124
+        <div className='sidebarpagecontainer'>
125
+          <Sidebar />
126
+
127
+          <div className='tracim__content'>
128
+            <Route path={PAGE.LOGIN} component={Login} />
129
+
130
+            <Route exact path='/' component={() => {
131
+              switch (props.user.logged) {
132
+                case true:
133
+                  return <Redirect to={{pathname: PAGE.WORKSPACE.ROOT, state: {from: props.location}}} />
134
+                case false:
135
+                  return <Redirect to={{pathname: '/login', state: {from: props.location}}} />
136
+                case null:
137
+                  return null
138
+              }
139
+            }} />
140
+
141
+            <Route path='/workspaces/:idws?' render={() => // Workspace Router
142
+              <div>
143
+                <Route exact path={PAGE.WORKSPACE.ROOT} render={() => props.workspaceList.length === 0 // handle '/' and redirect to first workspace
144
+                  ? null // @FIXME this needs to be handled in case of new user that has no workspace
145
+                  : <Redirect to={{pathname: PAGE.WORKSPACE.DASHBOARD(props.workspaceList[0].id), state: {from: props.location}}} />
146
+                } />
147
+
148
+                <Route exact path={`${PAGE.WORKSPACE.ROOT}/:idws`} render={props2 => // handle '/workspaces/:id' and add '/contents'
149
+                  <Redirect to={{pathname: PAGE.WORKSPACE.CONTENT_LIST(props2.match.params.idws), state: {from: props.location}}} />
150
+                } />
151
+
152
+                <Route path={PAGE.WORKSPACE.DASHBOARD(':idws')} component={Dashboard} />
153
+                <Route path={PAGE.WORKSPACE.CALENDAR(':idws')} component={() => <div><br /><br /><br /><br />NYI</div>} />
154
+                <Route path={PAGE.WORKSPACE.CONTENT(':idws', ':type', ':idcts')} component={WorkspaceContent} />
155
+                <Route exact path={PAGE.WORKSPACE.CONTENT_LIST(':idws')} component={WorkspaceContent} />
156
+              </div>
157
+            } />
158
+
159
+            <Route path={PAGE.ACCOUNT} render={() =>
125
               <Account />
160
               <Account />
126
-            </div>
127
-          } />
128
-
129
-          <Route path={PAGE.ADMIN.ROOT} render={() =>
130
-            <div className='sidebarpagecontainer'>
131
-              <Sidebar />
161
+            } />
132
 
162
 
163
+            <Route path={PAGE.ADMIN.ROOT} render={() =>
133
               <AppFullscreenRouter />
164
               <AppFullscreenRouter />
134
-            </div>
135
-          } />
165
+            } />
136
 
166
 
137
-          <Route path={'/wip/:cp'} component={WIPcomponent} /> {/* for testing purpose only */}
167
+            <Route path={'/wip/:cp'} component={WIPcomponent} /> {/* for testing purpose only */}
138
 
168
 
139
-          <div id='appFeatureContainer' />
140
-          <div id='popupCreateContentContainer' />
169
+            <div id='appFeatureContainer' />
170
+            <div id='popupCreateContentContainer' />
171
+          </div>
141
         </div>
172
         </div>
142
-
143
       </div>
173
       </div>
144
     )
174
     )
145
   }
175
   }

+ 1 - 0
frontend/src/css/Generic.styl View File

8
   height 100%
8
   height 100%
9
   &__content
9
   &__content
10
     height 100%
10
     height 100%
11
+    width 100%
11
 
12
 
12
 .btn-primary
13
 .btn-primary
13
   background-color thirdColor
14
   background-color thirdColor