Browse Source

added app Admin Workspace User + refactor for app Fullscreen

Skylsmoi 5 years ago
parent
commit
e92507b8c0
46 changed files with 641 additions and 86 deletions
  1. 18 0
      build_full_frontend.sh
  2. 1 1
      frontend/README.md
  3. 22 5
      frontend/dist/appInterface.js
  4. 1 0
      frontend/dist/index.html
  5. 6 6
      frontend/jsonserver/static_db.json
  6. 2 1
      frontend/package.json
  7. 19 6
      frontend/src/appFactory.js
  8. 6 5
      frontend/src/component/Workspace/OpenContentApp.jsx
  9. 1 0
      frontend/src/component/Workspace/OpenCreateContentApp.jsx
  10. 6 4
      frontend/src/container/Account.jsx
  11. 47 0
      frontend/src/container/AppFullscreenManager.jsx
  12. 1 1
      frontend/src/container/Header.jsx
  13. 19 1
      frontend/src/container/Sidebar.jsx
  14. 16 3
      frontend/src/container/Tracim.jsx
  15. 15 42
      frontend/src/container/WorkspaceContent.jsx
  16. 6 1
      frontend/src/helper.js
  17. 13 0
      frontend_app_admin_workspace_user/.editorconfig
  18. 5 0
      frontend_app_admin_workspace_user/.gitignore
  19. 1 0
      frontend_app_admin_workspace_user/README.md
  20. 17 0
      frontend_app_admin_workspace_user/build_admin_workspace_user.sh
  21. 22 0
      frontend_app_admin_workspace_user/dist/index.html
  22. 14 0
      frontend_app_admin_workspace_user/i18next.scanner.js
  23. 1 0
      frontend_app_admin_workspace_user/i18next.scanner/en/translation.json
  24. 1 0
      frontend_app_admin_workspace_user/i18next.scanner/fr/translation.json
  25. 63 0
      frontend_app_admin_workspace_user/package.json
  26. 1 0
      frontend_app_admin_workspace_user/src/action.async.js
  27. 86 0
      frontend_app_admin_workspace_user/src/container/AdminWorkspaceUser.jsx
  28. 1 0
      frontend_app_admin_workspace_user/src/css/index.styl
  29. 53 0
      frontend_app_admin_workspace_user/src/helper.js
  30. 21 0
      frontend_app_admin_workspace_user/src/i18n.js
  31. 16 0
      frontend_app_admin_workspace_user/src/index.dev.js
  32. 24 0
      frontend_app_admin_workspace_user/src/index.js
  33. 87 0
      frontend_app_admin_workspace_user/webpack.config.js
  34. 1 1
      frontend_app_html-document/package.json
  35. 1 1
      frontend_app_html-document/src/container/PopupCreateHtmlDocument.jsx
  36. 1 1
      frontend_app_html-document/src/helper.js
  37. 1 1
      frontend_app_html-document/src/index.js
  38. 1 1
      frontend_app_thread/package.json
  39. 1 1
      frontend_app_thread/src/container/PopupCreateThread.jsx
  40. 1 1
      frontend_app_thread/src/helper.js
  41. 1 1
      frontend_app_thread/src/index.js
  42. 0 0
      frontend_lib/src/component/Layout/PageContent.jsx
  43. 3 2
      frontend_lib/src/component/Layout/PageTitle.jsx
  44. 0 0
      frontend_lib/src/component/Layout/PageWrapper.jsx
  45. 8 0
      frontend_lib/src/index.js
  46. 10 0
      install_frontend_dependencies.sh

+ 18 - 0
build_full_frontend.sh View File

@@ -52,3 +52,21 @@ cp i18next.scanner/en/translation.json ../frontend/dist/app/thread_en_translatio
52 52
 log "cp i18next.scanner/fr/translation.json ../frontend/dist/app/thread_fr_translation.json"
53 53
 cp i18next.scanner/fr/translation.json ../frontend/dist/app/thread_fr_translation.json
54 54
 cd -
55
+
56
+# app Admin Workspace User
57
+
58
+log "cd frontend_app_admin_workspace_user"
59
+cd frontend_app_admin_workspace_user
60
+
61
+log "npm run build$windoz # for frontend_app_thread"
62
+npm run build$windoz
63
+
64
+log "cp dist/admin_workspace_user.app.js"
65
+cp dist/admin_workspace_user.app.js ../frontend/dist/app
66
+
67
+log "cp i18next.scanner/en/translation.json ../frontend/dist/app/admin_workspace_user_en_translation.json"
68
+cp i18next.scanner/en/translation.json ../frontend/dist/app/admin_workspace_user_en_translation.json
69
+
70
+log "cp i18next.scanner/fr/translation.json ../frontend/dist/app/admin_workspace_user_fr_translation.json"
71
+cp i18next.scanner/fr/translation.json ../frontend/dist/app/admin_workspace_user_fr_translation.json
72
+cd -

+ 1 - 1
frontend/README.md View File

@@ -58,7 +58,7 @@ To test them inside Tracim, you need to build them and copast them to tracim_fro
58 58
 You also need to make the mock api able to tell tracim_frontend that it handle you app :
59 59
 - add an entry for you App in tracim_frontend/jsonserver/static_db.json in the `app_config` property
60 60
 - reload your mock api server
61
-- add the source of your app in tracim_frontend/dist/index.html and an entry to the switch case of the function `GLOBAL_renderAppFull`. All of this will be handled by backend later on, this is all work in progress stuffs.
61
+- add the source of your app in tracim_frontend/dist/index.html and an entry to the switch case of the function `GLOBAL_renderAppFeature`. All of this will be handled by backend later on, this is all work in progress stuffs.
62 62
 
63 63
 
64 64
 #### Urls list

+ 22 - 5
frontend/dist/appInterface.js View File

@@ -9,6 +9,8 @@
9 9
         return appThread
10 10
       case 'file':
11 11
         return appFile
12
+      case 'admin_workspace_user':
13
+        return appAdminWorkspaceUser
12 14
       default:
13 15
         return null
14 16
     }
@@ -19,15 +21,30 @@
19 21
   // use module.export and require
20 22
   // doesn't work, cant resolve a file outside of the build dir
21 23
 
22
-  GLOBAL_renderAppFull = app => {
23
-    console.log('%cGLOBAL_renderAppFull', 'color: #5cebeb', app)
24
+  GLOBAL_renderAppFeature = app => {
25
+    console.log('%cGLOBAL_renderAppFeature', 'color: #5cebeb', app)
24 26
 
25 27
     const selectedApp = getSelectedApp(app.config.slug)
26 28
 
27 29
     if (selectedApp.isRendered) {
28
-      GLOBAL_dispatchEvent({type: `${app.config.slug}_showApp`, data: app}) // handled by html-documents:src/container/HtmlDocument.jsx
30
+      GLOBAL_dispatchEvent({type: `${app.config.slug}_showApp`, data: app}) // handled by html-documents:src/container/AdminWorkspaceUser.jsx
29 31
     } else {
30
-      selectedApp.renderAppFull(app)
32
+      selectedApp.renderAppFeature(app)
33
+      selectedApp.isRendered = true
34
+      prevSelectedApp.isRendered = false
35
+      prevSelectedApp = selectedApp
36
+    }
37
+  }
38
+
39
+  GLOBAL_renderAppFullscreen = app => {
40
+    console.log('%cGLOBAL_renderAppFullscreen', 'color: #5cebeb', app)
41
+
42
+    const selectedApp = getSelectedApp(app.config.slug)
43
+
44
+    if (selectedApp.isRendered) {
45
+      GLOBAL_dispatchEvent({type: `${app.config.slug}_showApp`, data: app}) // handled by html-documents:src/container/AdminWorkspaceUser.jsx
46
+    } else {
47
+      selectedApp.renderAppFullscreen(app)
31 48
       selectedApp.isRendered = true
32 49
       prevSelectedApp.isRendered = false
33 50
       prevSelectedApp = selectedApp
@@ -64,7 +81,7 @@
64 81
         console.log('%cGLOBAL_eventReducer Custom Event', 'color: #28a745', type, data)
65 82
         if (prevSelectedApp.name === '') return
66 83
 
67
-        prevSelectedApp.unmountApp('appContainer')
84
+        prevSelectedApp.unmountApp('appFeatureContainer')
68 85
         prevSelectedApp.unmountApp('popupCreateContentContainer')
69 86
         prevSelectedApp.isRendered = false
70 87
         break

+ 1 - 0
frontend/dist/index.html View File

@@ -54,6 +54,7 @@
54 54
     <script src='/app/html-document.app.js'></script>
55 55
     <script src='/app/thread.app.js'></script>
56 56
     <!-- <script src='/app/file.app.js'></script> -->
57
+    <script src='/app/admin_workspace_user.app.js'></script>
57 58
 
58 59
     <script src="/dev/jquery-3.2.1.js"></script>
59 60
     <script src="/dev/popper-1.12.3.js"></script>

+ 6 - 6
frontend/jsonserver/static_db.json View File

@@ -35,7 +35,7 @@
35 35
     "customClass": "wsContentPageHtml",
36 36
     "icon": "fa fa-fw fa-file-text-o",
37 37
     "color": "#3f52e3",
38
-    "domContainer": "appContainer"
38
+    "domContainer": "appFeatureContainer"
39 39
   }, {
40 40
     "name": "PageMarkdown",
41 41
     "label": {
@@ -47,7 +47,7 @@
47 47
     "customClass": "wsContentPageMarkdown",
48 48
     "icon": "fa fa-fw fa-file-code-o",
49 49
     "color": "#e0082b",
50
-    "domContainer": "appContainer"
50
+    "domContainer": "appFeatureContainer"
51 51
   }, {
52 52
     "name": "File",
53 53
     "label": {
@@ -59,7 +59,7 @@
59 59
     "customClass": "wsContentFile",
60 60
     "icon": "fa fa-fw fa-file-image-o",
61 61
     "color": "#263462",
62
-    "domContainer": "appContainer"
62
+    "domContainer": "appFeatureContainer"
63 63
   }, {
64 64
     "name": "Thread",
65 65
     "label": {
@@ -71,7 +71,7 @@
71 71
     "customClass": "wsContentThread",
72 72
     "icon": "fa fa-fw fa-comments-o",
73 73
     "color": "#2674d3",
74
-    "domContainer": "appContainer"
74
+    "domContainer": "appFeatureContainer"
75 75
   }, {
76 76
     "name": "Task",
77 77
     "label": {
@@ -83,7 +83,7 @@
83 83
     "customClass": "wsContentTask",
84 84
     "icon": "fa fa-fw fa-list-ul",
85 85
     "color": "#2d5a88",
86
-    "domContainer": "appContainer"
86
+    "domContainer": "appFeatureContainer"
87 87
   }, {
88 88
     "name": "Issue",
89 89
     "label": {
@@ -95,7 +95,7 @@
95 95
     "customClass": "wsContentIssue",
96 96
     "icon": "fa fa-fw fa-ticket",
97 97
     "color": "#a4835e",
98
-    "domContainer": "appContainer"
98
+    "domContainer": "appFeatureContainer"
99 99
   }],
100 100
   "workspace_detail": {
101 101
     "id": 1,

+ 2 - 1
frontend/package.json View File

@@ -63,7 +63,8 @@
63 63
       "fetch",
64 64
       "btoa",
65 65
       "history",
66
-      "GLOBAL_renderAppFull",
66
+      "GLOBAL_renderAppFeature",
67
+      "GLOBAL_renderAppFullscreen",
67 68
       "GLOBAL_renderAppPopupCreation",
68 69
       "GLOBAL_dispatchEvent",
69 70
       "GLOBAL_hideApp"

+ 19 - 6
frontend/src/appFactory.js View File

@@ -4,13 +4,25 @@ import i18n from './i18n.js'
4 4
 
5 5
 export function appFactory (WrappedComponent) {
6 6
   return class AppFactory extends React.Component {
7
-    renderAppFull = (appConfig, user, content) => GLOBAL_renderAppFull({
7
+    renderAppFeature = (appConfig, user, content) => GLOBAL_renderAppFeature({
8 8
       loggedUser: user.logged ? user : {},
9 9
       config: {
10 10
         ...appConfig,
11
-        domContainer: 'appContainer',
11
+        domContainer: 'appFeatureContainer',
12
+        apiUrl: FETCH_CONFIG.apiUrl,
13
+        mockApiUrl: FETCH_CONFIG.mockApiUrl, // Côme - 2018/07/31 - this should not be used, I deprecate it
14
+        apiHeader: FETCH_CONFIG.headers,
15
+        translation: i18n.store.data
16
+      },
17
+      content
18
+    })
19
+
20
+    renderAppFullscreen = (appConfig, user, content) => GLOBAL_renderAppFullscreen({
21
+      loggedUser: user.logged ? user : {},
22
+      config: {
23
+        ...appConfig,
24
+        domContainer: 'appFullscreenContainer',
12 25
         apiUrl: FETCH_CONFIG.apiUrl,
13
-        mockApiUrl: FETCH_CONFIG.mockApiUrl,
14 26
         apiHeader: FETCH_CONFIG.headers,
15 27
         translation: i18n.store.data
16 28
       },
@@ -31,15 +43,16 @@ export function appFactory (WrappedComponent) {
31 43
       idFolder: idFolder === 'null' ? null : idFolder
32 44
     })
33 45
 
34
-    emitEventApp = (type, data) => GLOBAL_dispatchEvent({ type, data })
46
+    dispatchCustomEvent = (type, data) => GLOBAL_dispatchEvent({ type, data })
35 47
 
36 48
     render () {
37 49
       return (
38 50
         <WrappedComponent
39 51
           {...this.props}
40
-          renderAppFull={this.renderAppFull}
52
+          renderAppFeature={this.renderAppFeature}
53
+          renderAppFullscreen={this.renderAppFullscreen}
41 54
           renderAppPopupCreation={this.renderAppPopupCreation}
42
-          emitEventApp={this.emitEventApp}
55
+          dispatchCustomEvent={this.dispatchCustomEvent}
43 56
           // hideApp={this.hideApp}
44 57
         />
45 58
       )

+ 6 - 5
frontend/src/component/Workspace/OpenContentApp.jsx View File

@@ -3,9 +3,10 @@ import { connect } from 'react-redux'
3 3
 import { withRouter } from 'react-router'
4 4
 import appFactory from '../../appFactory.js'
5 5
 
6
+// @FIXME Côme - 2018/07/31 - should this be in a component like AppFeatureManager ?
6 7
 export class OpenContentApp extends React.Component {
7 8
   openContentApp = () => {
8
-    const { idWorkspace, appOpenedType, user, workspaceContent, contentType, renderAppFull, match } = this.props
9
+    const { idWorkspace, appOpenedType, user, workspaceContent, contentType, renderAppFeature, dispatchCustomEvent, match } = this.props
9 10
 
10 11
     if (isNaN(idWorkspace) || idWorkspace === -1) return
11 12
 
@@ -21,15 +22,15 @@ export class OpenContentApp extends React.Component {
21 22
       console.log('%c<OpenContentApp> contentToOpen', 'color: #dcae84', contentToOpen)
22 23
 
23 24
       if (appOpenedType === contentToOpen.type) { // app already open
24
-        GLOBAL_dispatchEvent({
25
-          type: `${contentToOpen.type}_reloadContent`, // handled by html-document:src/container/HtmlDocument.jsx
25
+        dispatchCustomEvent({
26
+          type: `${contentToOpen.type}_reloadContent`, // handled by html-document:src/container/AdminWorkspaceUser.jsx
26 27
           data: contentToOpen
27 28
         })
28 29
       } else { // open another app
29 30
         // if another app is already visible, hide it
30
-        if (appOpenedType !== false) GLOBAL_dispatchEvent({type: `${appOpenedType}_hideApp`})
31
+        if (appOpenedType !== false) dispatchCustomEvent({type: `${appOpenedType}_hideApp`})
31 32
         // open app
32
-        renderAppFull(
33
+        renderAppFeature(
33 34
           contentType.find(ct => ct.slug === contentToOpen.type),
34 35
           user,
35 36
           contentToOpen

+ 1 - 0
frontend/src/component/Workspace/OpenCreateContentApp.jsx View File

@@ -5,6 +5,7 @@ import appFactory from '../../appFactory.js'
5 5
 
6 6
 const qs = require('query-string')
7 7
 
8
+// @FIXME Côme - 2018/07/31 - should this be in a component like AppFeatureManager ? (or AppCreateContentManager)
8 9
 export class OpenCreateContentApp extends React.Component {
9 10
   openCreateContentApp = () => {
10 11
     const { idWorkspace, user, contentType, renderAppPopupCreation, match, location } = this.props

+ 6 - 4
frontend/src/container/Account.jsx View File

@@ -1,9 +1,6 @@
1 1
 import React from 'react'
2 2
 import { connect } from 'react-redux'
3 3
 import Sidebar from './Sidebar.jsx'
4
-import PageWrapper from '../component/common/layout/PageWrapper.jsx'
5
-import PageTitle from '../component/common/layout/PageTitle.jsx'
6
-import PageContent from '../component/common/layout/PageContent.jsx'
7 4
 import UserInfo from '../component/Account/UserInfo.jsx'
8 5
 import MenuSubComponent from '../component/Account/MenuSubComponent.jsx'
9 6
 import PersonalData from '../component/Account/PersonalData.jsx'
@@ -11,7 +8,12 @@ import PersonalData from '../component/Account/PersonalData.jsx'
11 8
 import Notification from '../component/Account/Notification.jsx'
12 9
 import Password from '../component/Account/Password.jsx'
13 10
 import Timezone from '../component/Account/Timezone.jsx'
14
-import { Delimiter } from 'tracim_frontend_lib'
11
+import {
12
+  Delimiter,
13
+  PageWrapper,
14
+  PageTitle,
15
+  PageContent
16
+} from 'tracim_frontend_lib'
15 17
 import { updateUserWorkspaceSubscriptionNotif } from '../action-creator.sync.js'
16 18
 import {
17 19
   getTimezone,

+ 47 - 0
frontend/src/container/AppFullscreenManager.jsx View File

@@ -0,0 +1,47 @@
1
+import React from 'react'
2
+import { connect } from 'react-redux'
3
+import { withRouter } from 'react-router'
4
+import { Route } from 'react-router-dom'
5
+import { PAGE } from '../helper.js'
6
+import appFactory from '../appFactory.js'
7
+import Sidebar from './Sidebar.jsx'
8
+
9
+class AppFullscreenManager extends React.Component {
10
+  constructor (props) {
11
+    super(props)
12
+    this.state = {
13
+      AmIMounted: false
14
+    }
15
+  }
16
+
17
+  componentDidMount = () => this.setState({AmIMounted: true})
18
+
19
+  render () {
20
+    const { user, renderAppFullscreen } = this.props
21
+
22
+    return (
23
+      <div className='sidebarpagecontainer'>
24
+        <Sidebar />
25
+
26
+        <div id='appFullscreenContainer' />
27
+
28
+        {this.state.AmIMounted && (// we must wait for the component to be fully mounted to be sure the div#appFullscreenContainer exists in DOM
29
+          <div className='emptyDiForRoute'>
30
+            <Route path={PAGE.ADMIN.WORKSPACE} render={() => {
31
+              renderAppFullscreen({slug: 'admin_workspace_user', hexcolor: '#7d4e24', type: 'workspace'}, user, {})
32
+              return null
33
+            }} />
34
+
35
+            <Route path={PAGE.ADMIN.USER} render={() => {
36
+              renderAppFullscreen({slug: 'admin_workspace_user', hexcolor: '#7d4e24', type: 'user'}, user, {})
37
+              return null
38
+            }} />
39
+          </div>
40
+        )}
41
+      </div>
42
+    )
43
+  }
44
+}
45
+
46
+const mapStateToProps = ({ user }) => ({ user })
47
+export default connect(mapStateToProps)(withRouter(appFactory(AppFullscreenManager)))

+ 1 - 1
frontend/src/container/Header.jsx View File

@@ -37,7 +37,7 @@ class Header extends React.Component {
37 37
   handleChangeLang = idLang => {
38 38
     this.props.dispatch(setUserLang(idLang))
39 39
     i18n.changeLanguage(idLang)
40
-    this.props.emitEventApp('allApp_changeLang', idLang)
40
+    this.props.dispatchCustomEvent('allApp_changeLang', idLang)
41 41
   }
42 42
 
43 43
   handleClickHelp = () => {}

+ 19 - 1
frontend/src/container/Sidebar.jsx View File

@@ -6,8 +6,12 @@ import { translate } from 'react-i18next'
6 6
 import WorkspaceListItem from '../component/Sidebar/WorkspaceListItem.jsx'
7 7
 import {
8 8
   setWorkspaceListIsOpenInSidebar,
9
-  updateWorkspaceFilter
9
+  updateWorkspaceFilter,
10
+  updateWorkspaceListData
10 11
 } from '../action-creator.sync.js'
12
+import {
13
+  getWorkspaceList
14
+} from '../action-creator.async.js'
11 15
 import { PAGE } from '../helper.js'
12 16
 
13 17
 const qs = require('query-string')
@@ -21,6 +25,20 @@ class Sidebar extends React.Component {
21 25
     }
22 26
   }
23 27
 
28
+  async componentDidMount () {
29
+    const { workspaceIdInUrl } = this.state
30
+    const { user, workspaceList, dispatch } = this.props
31
+
32
+    if (user.user_id !== -1 && workspaceList.length === 0) {
33
+      const fetchGetWorkspaceList = await dispatch(getWorkspaceList(user))
34
+
35
+      if (fetchGetWorkspaceList.status === 200) {
36
+        dispatch(updateWorkspaceListData(fetchGetWorkspaceList.json))
37
+        dispatch(setWorkspaceListIsOpenInSidebar(workspaceIdInUrl || fetchGetWorkspaceList.json[0].workspace_id, true))
38
+      }
39
+    }
40
+  }
41
+
24 42
   componentDidUpdate (prevProps, prevState) {
25 43
     // console.log('%c<Sidebar> Did Update', 'color: #c17838')
26 44
     if (this.props.match.params.idws === undefined || isNaN(this.props.match.params.idws)) return

+ 16 - 3
frontend/src/container/Tracim.jsx View File

@@ -5,6 +5,7 @@ import Header from './Header.jsx'
5 5
 import Login from './Login.jsx'
6 6
 import Dashboard from './Dashboard.jsx'
7 7
 import Account from './Account.jsx'
8
+import AppFullscreenManager from './AppFullscreenManager.jsx'
8 9
 import FlashMessage from '../component/FlashMessage.jsx'
9 10
 import WorkspaceContent from './WorkspaceContent.jsx'
10 11
 import WIPcomponent from './WIPcomponent.jsx'
@@ -14,10 +15,12 @@ import {
14 15
 import PrivateRoute from './PrivateRoute.jsx'
15 16
 import { COOKIE, PAGE } from '../helper.js'
16 17
 import {
18
+  getAppList,
17 19
   getUserIsConnected
18 20
 } from '../action-creator.async.js'
19 21
 import {
20 22
   removeFlashMessage,
23
+  setAppList,
21 24
   setUserConnected
22 25
 } from '../action-creator.sync.js'
23 26
 import Cookies from 'js-cookie'
@@ -34,14 +37,21 @@ class Tracim extends React.Component {
34 37
     const fetchGetUserIsConnected = await dispatch(getUserIsConnected(userFromCookies))
35 38
     switch (fetchGetUserIsConnected.status) {
36 39
       case 200:
37
-        dispatch(setUserConnected({
40
+        const userLogged = {
38 41
           ...fetchGetUserIsConnected.json,
39 42
           auth: userFromCookies.auth,
40 43
           logged: true
41
-        }))
44
+        }
45
+
46
+        dispatch(setUserConnected(userLogged))
47
+
48
+        const fetchGetAppList = await dispatch(getAppList(userLogged))
49
+        if (fetchGetAppList.status === 200) dispatch(setAppList(fetchGetAppList.json))
42 50
         break
51
+
43 52
       case 401:
44 53
         dispatch(setUserConnected({logged: false})); break
54
+
45 55
       default:
46 56
         dispatch(setUserConnected({logged: null})); break
47 57
     }
@@ -69,7 +79,10 @@ class Tracim extends React.Component {
69 79
           </Switch>
70 80
 
71 81
           <PrivateRoute path={PAGE.ACCOUNT} component={Account} />
82
+          <PrivateRoute path={PAGE.ADMIN.ROOT} component={AppFullscreenManager} />
72 83
           <PrivateRoute path={'/wip/:cp'} component={WIPcomponent} /> {/* for testing purpose only */}
84
+
85
+          <div id='appFeatureContainer' />
73 86
         </div>
74 87
 
75 88
       </div>
@@ -77,5 +90,5 @@ class Tracim extends React.Component {
77 90
   }
78 91
 }
79 92
 
80
-const mapStateToProps = ({ flashMessage, user }) => ({ flashMessage, user })
93
+const mapStateToProps = ({ flashMessage }) => ({ flashMessage })
81 94
 export default withRouter(connect(mapStateToProps)(translate()(Tracim)))

+ 15 - 42
frontend/src/container/WorkspaceContent.jsx View File

@@ -7,26 +7,23 @@ import Sidebar from './Sidebar.jsx'
7 7
 import Folder from '../component/Workspace/Folder.jsx'
8 8
 import ContentItem from '../component/Workspace/ContentItem.jsx'
9 9
 import ContentItemHeader from '../component/Workspace/ContentItemHeader.jsx'
10
-import PageWrapper from '../component/common/layout/PageWrapper.jsx'
11
-import PageTitle from '../component/common/layout/PageTitle.jsx'
12
-import PageContent from '../component/common/layout/PageContent.jsx'
13 10
 import DropdownCreateButton from '../component/common/Input/DropdownCreateButton.jsx'
14 11
 import OpenContentApp from '../component/Workspace/OpenContentApp.jsx'
15 12
 import OpenCreateContentApp from '../component/Workspace/OpenCreateContentApp.jsx'
16 13
 import {
17
-  getAppList,
14
+  PageWrapper,
15
+  PageTitle,
16
+  PageContent
17
+} from 'tracim_frontend_lib'
18
+import {
18 19
   getContentTypeList,
19 20
   getWorkspaceContentList,
20
-  getFolderContent,
21
-  getWorkspaceList
21
+  getFolderContent
22 22
 } from '../action-creator.async.js'
23 23
 import {
24 24
   newFlashMessage,
25
-  setAppList,
26 25
   setContentTypeList,
27
-  setWorkspaceContent,
28
-  setWorkspaceListIsOpenInSidebar,
29
-  updateWorkspaceListData
26
+  setWorkspaceContent
30 27
 } from '../action-creator.sync.js'
31 28
 
32 29
 const qs = require('query-string')
@@ -35,11 +32,6 @@ class WorkspaceContent extends React.Component {
35 32
   constructor (props) {
36 33
     super(props)
37 34
     this.state = {
38
-      popupCreateContent: {
39
-        display: false,
40
-        type: undefined,
41
-        folder: undefined
42
-      },
43 35
       workspaceIdInUrl: props.match.params.idws ? parseInt(props.match.params.idws) : null, // this is used to avoid handling the parseInt every time
44 36
       appOpenedType: false
45 37
     }
@@ -69,38 +61,21 @@ class WorkspaceContent extends React.Component {
69 61
   }
70 62
 
71 63
   async componentDidMount () {
72
-    const { workspaceIdInUrl } = this.state
73
-    const { user, workspaceList, app, contentType, match, dispatch } = this.props
64
+    const { user, workspaceList, contentType, match, dispatch } = this.props
74 65
 
75 66
     console.log('%c<WorkspaceContent> componentDidMount', 'color: #c17838')
76 67
 
77
-    if (app.length === 0) { // @fixme shouldn't this be done by <Sidebar> ?
78
-      const fetchGetAppList = await dispatch(getAppList(user))
79
-      if (fetchGetAppList.status === 200) dispatch(setAppList(fetchGetAppList.json))
80
-    }
81
-
82 68
     if (contentType.length === 0) {
83 69
       const fetchGetContentTypeList = await dispatch(getContentTypeList(user))
84 70
       if (fetchGetContentTypeList.status === 200) dispatch(setContentTypeList(fetchGetContentTypeList.json))
85 71
     }
86 72
 
87 73
     let wsToLoad = null
88
-    if (match.params.idws !== undefined) wsToLoad = match.params.idws
89 74
 
90
-    if (user.user_id !== -1 && workspaceList.length === 0) {
91
-      const fetchGetWorkspaceList = await dispatch(getWorkspaceList(user))
92
-
93
-      if (fetchGetWorkspaceList.status === 200) {
94
-        dispatch(updateWorkspaceListData(fetchGetWorkspaceList.json))
95
-        dispatch(setWorkspaceListIsOpenInSidebar(workspaceIdInUrl || fetchGetWorkspaceList.json[0].workspace_id, true))
96
-
97
-        if (match.params.idws === undefined && fetchGetWorkspaceList.json.length > 0) {
98
-          wsToLoad = fetchGetWorkspaceList.json[0].workspace_id // load first ws if none specified
99
-        }
100
-      }
101
-    }
102
-
103
-    if (wsToLoad === null) return // ws already loaded
75
+    if (match.params.idws === undefined) {
76
+      if (workspaceList.length > 0) wsToLoad = workspaceList[0].id
77
+      else return
78
+    } else wsToLoad = match.params.idws
104 79
 
105 80
     this.loadContentList(wsToLoad)
106 81
   }
@@ -111,7 +86,6 @@ class WorkspaceContent extends React.Component {
111 86
     if (this.state.workspaceIdInUrl === null) return
112 87
 
113 88
     const idWorkspace = parseInt(this.props.match.params.idws)
114
-
115 89
     if (isNaN(idWorkspace)) return
116 90
 
117 91
     const prevFilter = qs.parse(prevProps.location.search).type
@@ -126,7 +100,7 @@ class WorkspaceContent extends React.Component {
126 100
   }
127 101
 
128 102
   componentWillUnmount () {
129
-    this.props.emitEventApp('unmount_app')
103
+    this.props.dispatchCustomEvent('unmount_app')
130 104
     document.removeEventListener('appCustomEvent', this.customEventReducer)
131 105
   }
132 106
 
@@ -221,7 +195,8 @@ class WorkspaceContent extends React.Component {
221 195
           <PageTitle
222 196
             parentClass='workspace__header'
223 197
             customClass='justify-content-between'
224
-            title={workspaceContent.label ? workspaceContent.label : ''}
198
+            title='Liste des Contenus'
199
+            subtitle={workspaceContent.label ? workspaceContent.label : ''}
225 200
           >
226 201
             <DropdownCreateButton
227 202
               parentClass='workspace__header__btnaddworkspace'
@@ -285,8 +260,6 @@ class WorkspaceContent extends React.Component {
285 260
               onClickCreateContent={this.handleClickCreateContent}
286 261
               availableApp={contentType}
287 262
             />
288
-
289
-            <div id='appContainer' />
290 263
           </PageContent>
291 264
 
292 265
         </PageWrapper>

+ 6 - 1
frontend/src/helper.js View File

@@ -26,7 +26,12 @@ export const PAGE = {
26 26
     ADMIN: (idws = ':idws') => `/workspaces/${idws}/admin`
27 27
   },
28 28
   LOGIN: '/login',
29
-  ACCOUNT: '/account'
29
+  ACCOUNT: '/account',
30
+  ADMIN: {
31
+    ROOT: '/admin',
32
+    WORKSPACE: '/admin/workspace',
33
+    USEr: '/admin/user'
34
+  }
30 35
 }
31 36
 
32 37
 export const ROLE = [{

+ 13 - 0
frontend_app_admin_workspace_user/.editorconfig View File

@@ -0,0 +1,13 @@
1
+# doc here : https://github.com/editorconfig/editorconfig/wiki/EditorConfig-Properties
2
+root = true
3
+
4
+[*]
5
+indent_style = space
6
+indent_size = 2
7
+end_of_line = lf
8
+charset = utf-8
9
+insert_final_newline = true
10
+trim_trailing_whitespace = true
11
+
12
+[*.py]
13
+indent_size = 4

+ 5 - 0
frontend_app_admin_workspace_user/.gitignore View File

@@ -0,0 +1,5 @@
1
+# Created by .ignore support plugin (hsz.mobi)
2
+.idea/
3
+.git/
4
+dist/admin_workspace_user.app.js
5
+node_modules/

+ 1 - 0
frontend_app_admin_workspace_user/README.md View File

@@ -0,0 +1 @@
1
+# app Admin Workspace User

+ 17 - 0
frontend_app_admin_workspace_user/build_admin_workspace_user.sh View File

@@ -0,0 +1,17 @@
1
+#!/bin/bash
2
+
3
+. ../bash_library.sh # source bash_library.sh
4
+
5
+windoz=""
6
+if [[ $1 = "-w" ]]; then
7
+    windoz="windoz"
8
+fi
9
+
10
+log "npm run build$windoz"
11
+npm run build$windoz
12
+log "cp dist/admin_workspace_user.app.js ../frontend/dist/app"
13
+cp dist/admin_workspace_user.app.js ../frontend/dist/app
14
+log "cp i18next.scanner/en/translation.json ../frontend/dist/app/admin_workspace_user_en_translation.json"
15
+cp i18next.scanner/en/translation.json ../frontend/dist/app/admin_workspace_user_en_translation.json
16
+log "cp i18next.scanner/fr/translation.json ../frontend/dist/app/admin_workspace_user_fr_translation.json"
17
+cp i18next.scanner/fr/translation.json ../frontend/dist/app/admin_workspace_user_fr_translation.json

+ 22 - 0
frontend_app_admin_workspace_user/dist/index.html View File

@@ -0,0 +1,22 @@
1
+<!DOCTYPE html>
2
+<html>
3
+<head>
4
+  <meta charset='utf-8' />
5
+  <meta name="viewport" content="width=device-width, user-scalable=no" />
6
+  <title>Html-document App Tracim</title>
7
+  <link rel='shortcut icon' href='favicon.ico'>
8
+
9
+  <link rel="stylesheet" type="text/css" href="./font/font-awesome-4.7.0/css/font-awesome.css">
10
+  <link href="https://fonts.googleapis.com/css?family=Quicksand:300,400,500,700" rel="stylesheet">
11
+  <link rel="stylesheet" type="text/css" href="./dev/bootstrap-4.0.0-beta.css">
12
+</head>
13
+<body>
14
+  <script src="./dev/jquery-3.2.1.js"></script>
15
+  <script src="./dev/popper-1.12.3.js"></script>
16
+  <script src="./dev/bootstrap-4.0.0-beta.2.js"></script>
17
+
18
+  <div id='content'></div>
19
+
20
+  <script src='./admin_workspace_user.app.dev.js'></script>
21
+</body>
22
+</html>

+ 14 - 0
frontend_app_admin_workspace_user/i18next.scanner.js View File

@@ -0,0 +1,14 @@
1
+const scanner = require('i18next-scanner')
2
+const vfs = require('vinyl-fs')
3
+
4
+const option = require('../i18next.option.js')
5
+
6
+// --------------------
7
+// 2018/07/27 - currently, last version is 2.6.5 but a bug is spaming log with errors. So I'm using 2.6.1
8
+// this issue seems related : https://github.com/i18next/i18next-scanner/issues/88
9
+// --------------------
10
+
11
+vfs.src(['./src/**/*.jsx'])
12
+// .pipe(sort()) // Sort files in stream by path
13
+  .pipe(scanner(option))
14
+  .pipe(vfs.dest('./i18next.scanner'))

+ 1 - 0
frontend_app_admin_workspace_user/i18next.scanner/en/translation.json View File

@@ -0,0 +1 @@
1
+{}

+ 1 - 0
frontend_app_admin_workspace_user/i18next.scanner/fr/translation.json View File

@@ -0,0 +1 @@
1
+{}

+ 63 - 0
frontend_app_admin_workspace_user/package.json View File

@@ -0,0 +1,63 @@
1
+{
2
+  "name": "tracim_app_admin_workspace_user",
3
+  "version": "1.1.2",
4
+  "description": "",
5
+  "main": "index.js",
6
+  "scripts": {
7
+    "servdev": "NODE_ENV=development webpack-dev-server --watch --colors --inline --hot --progress",
8
+    "servdevwindoz": "set NODE_ENV=development&& webpack-dev-server --watch --colors --inline --hot --progress",
9
+    "servdev-dashboard": "NODE_ENV=development webpack-dashboard -m -p 9873 -- webpack-dev-server --watch --colors --inline --hot --progress",
10
+    "build": "NODE_ENV=production webpack -p",
11
+    "build-translation": "node i18next.scanner.js",
12
+    "buildwindoz": "set NODE_ENV=production&& webpack -p",
13
+    "test": "echo \"Error: no test specified\" && exit 1"
14
+  },
15
+  "author": "",
16
+  "license": "ISC",
17
+  "dependencies": {
18
+    "babel-core": "^6.26.0",
19
+    "babel-eslint": "^8.2.1",
20
+    "babel-loader": "^7.1.2",
21
+    "babel-plugin-transform-class-properties": "^6.24.1",
22
+    "babel-plugin-transform-object-assign": "^6.22.0",
23
+    "babel-plugin-transform-object-rest-spread": "^6.26.0",
24
+    "babel-polyfill": "^6.26.0",
25
+    "babel-preset-env": "^1.6.1",
26
+    "babel-preset-react": "^6.24.1",
27
+    "classnames": "^2.2.5",
28
+    "css-loader": "^0.28.7",
29
+    "file-loader": "^1.1.5",
30
+    "i18next": "^10.5.0",
31
+    "prop-types": "^15.6.0",
32
+    "react": "^16.0.0",
33
+    "react-dom": "^16.0.0",
34
+    "react-i18next": "^7.5.0",
35
+    "standard": "^11.0.0",
36
+    "standard-loader": "^6.0.1",
37
+    "style-loader": "^0.19.0",
38
+    "stylus": "^0.54.5",
39
+    "stylus-loader": "^3.0.1",
40
+    "url-loader": "^0.6.2",
41
+    "webpack": "^3.8.1",
42
+    "whatwg-fetch": "^2.0.3"
43
+  },
44
+  "devDependencies": {
45
+    "i18next-scanner": "^2.6.1",
46
+    "webpack-dashboard": "^1.1.1",
47
+    "webpack-dev-server": "^2.9.2"
48
+  },
49
+  "standard": {
50
+    "globals": [
51
+      "fetch",
52
+      "history",
53
+      "btoa",
54
+      "wysiwyg",
55
+      "tinymce",
56
+      "GLOBAL_renderAppFeature",
57
+      "GLOBAL_unmountApp",
58
+      "GLOBAL_dispatchEvent"
59
+    ],
60
+    "parser": "babel-eslint",
61
+    "ignore": []
62
+  }
63
+}

+ 1 - 0
frontend_app_admin_workspace_user/src/action.async.js View File

@@ -0,0 +1 @@
1
+// import { FETCH_CONFIG } from './helper.js'

+ 86 - 0
frontend_app_admin_workspace_user/src/container/AdminWorkspaceUser.jsx View File

@@ -0,0 +1,86 @@
1
+import React from 'react'
2
+import { translate } from 'react-i18next'
3
+import i18n from '../i18n.js'
4
+import {
5
+  addAllResourceI18n,
6
+  // handleFetchResult,
7
+  PageWrapper,
8
+  PageTitle,
9
+  PageContent
10
+} from 'tracim_frontend_lib'
11
+import { debug } from '../helper.js'
12
+import {
13
+} from '../action.async.js'
14
+
15
+class AdminWorkspaceUser extends React.Component {
16
+  constructor (props) {
17
+    super(props)
18
+    this.state = {
19
+      appName: 'admin_workspace_user',
20
+      isVisible: true,
21
+      config: props.data ? props.data.config : debug.config,
22
+      loggedUser: props.data ? props.data.loggedUser : debug.loggedUser,
23
+      content: props.data ? props.data.content : debug.content
24
+    }
25
+
26
+    // i18n has been init, add resources from frontend
27
+    addAllResourceI18n(i18n, this.state.config.translation)
28
+    i18n.changeLanguage(this.state.loggedUser.lang)
29
+
30
+    document.addEventListener('appCustomEvent', this.customEventReducer)
31
+  }
32
+
33
+  customEventReducer = ({ detail: { type, data } }) => { // action: { type: '', data: {} }
34
+    switch (type) {
35
+      // console.log('%c<AdminWorkspaceUser> Custom event', 'color: #28a745', type, data)
36
+      default:
37
+        break
38
+    }
39
+  }
40
+
41
+  componentDidMount () {
42
+    console.log('%c<AdminWorkspaceUser> did mount', `color: ${this.state.config.hexcolor}`)
43
+
44
+    this.loadContent()
45
+  }
46
+
47
+  componentDidUpdate (prevProps, prevState) {
48
+    const { state } = this
49
+
50
+    console.log('%c<AdminWorkspaceUser> did update', `color: ${this.state.config.hexcolor}`, prevState, state)
51
+  }
52
+
53
+  componentWillUnmount () {
54
+    console.log('%c<AdminWorkspaceUser> will Unmount', `color: ${this.state.config.hexcolor}`)
55
+    document.removeEventListener('appCustomEvent', this.customEventReducer)
56
+  }
57
+
58
+  loadContent = () => {
59
+    return null
60
+  }
61
+
62
+  render () {
63
+    const { isVisible } = this.state
64
+    // const { t } = this.props
65
+
66
+    if (!isVisible) return null
67
+
68
+    return (
69
+      <div>
70
+        <PageWrapper customeClass='admin'>
71
+          <PageTitle
72
+            parentClass='admin__header'
73
+            customClass='justify-content-between'
74
+            title={'Admin'}
75
+          />
76
+
77
+          <PageContent parentClass='workspace__content'>
78
+            woot { this.state.config.type }
79
+          </PageContent>
80
+        </PageWrapper>
81
+      </div>
82
+    )
83
+  }
84
+}
85
+
86
+export default translate()(AdminWorkspaceUser)

+ 1 - 0
frontend_app_admin_workspace_user/src/css/index.styl View File

@@ -0,0 +1 @@
1
+@import "../../node_modules/tracim_frontend_lib/src/css/Variable.styl"

+ 53 - 0
frontend_app_admin_workspace_user/src/helper.js View File

@@ -0,0 +1,53 @@
1
+export const FETCH_CONFIG = {
2
+  headers: {
3
+    'Accept': 'application/json',
4
+    'Content-Type': 'application/json'
5
+  }
6
+}
7
+
8
+export const debug = {
9
+  config: {
10
+    label: 'Admin workspace user',
11
+    slug: 'admin_workspace_user',
12
+    faIcon: 'file-text-o',
13
+    hexcolor: '#7d4e24',
14
+    type: 'workspace'
15
+  },
16
+  loggedUser: { // @FIXME this object is outdated
17
+    user_id: 5,
18
+    username: 'Smoi',
19
+    firstname: 'Côme',
20
+    lastname: 'Stoilenom',
21
+    email: 'osef@algoo.fr',
22
+    lang: 'en',
23
+    avatar_url: 'https://avatars3.githubusercontent.com/u/11177014?s=460&v=4',
24
+    auth: btoa(`${'admin@admin.admin'}:${'admin@admin.admin'}`)
25
+  },
26
+  content: {
27
+    author: {
28
+      avatar_url: null,
29
+      public_name: 'Global manager',
30
+      user_id: 1 // -1 or 1 for debug
31
+    },
32
+    content_id: 22, // 1 or 22 for debug
33
+    content_type: 'html-document',
34
+    created: '2018-06-18T14:59:26Z',
35
+    current_revision_id: 11,
36
+    is_archived: false,
37
+    is_deleted: false,
38
+    label: 'Current Menu',
39
+    last_modifier: {
40
+      avatar_url: null,
41
+      public_name: 'Global manager',
42
+      user_id: 1
43
+    },
44
+    modified: '2018-06-18T14:59:26Z',
45
+    parent_id: 2,
46
+    raw_content: '<div>bonjour, je suis un lapin.</div>',
47
+    show_in_ui: true,
48
+    slug: 'current-menu',
49
+    status: 'open',
50
+    sub_content_types: ['thread', 'html-document', 'file', 'folder'],
51
+    workspace_id: 1
52
+  }
53
+}

+ 21 - 0
frontend_app_admin_workspace_user/src/i18n.js View File

@@ -0,0 +1,21 @@
1
+import i18n from 'i18next'
2
+import { reactI18nextModule } from 'react-i18next'
3
+
4
+i18n
5
+  .use(reactI18nextModule)
6
+  .init({
7
+    fallbackLng: 'fr',
8
+    // have a common namespace used around the full app
9
+    ns: ['translation'], // namespace
10
+    defaultNS: 'translation',
11
+    debug: true,
12
+    // interpolation: {
13
+    //   escapeValue: false, // not needed for react!!
14
+    // },
15
+    react: {
16
+      wait: true
17
+    },
18
+    resources: {} // init with empty resources, they will come from frontend in app constructor
19
+  })
20
+
21
+export default i18n

+ 16 - 0
frontend_app_admin_workspace_user/src/index.dev.js View File

@@ -0,0 +1,16 @@
1
+import React from 'react'
2
+import ReactDOM from 'react-dom'
3
+import AdminWorkspaceUser from './container/AdminWorkspaceUser.jsx'
4
+// import PopupCreateHtmlDocument from './container/PopupCreateHtmlDocument.jsx'
5
+
6
+require('./css/index.styl')
7
+
8
+ReactDOM.render(
9
+  <AdminWorkspaceUser data={undefined} />
10
+  , document.getElementById('content')
11
+)
12
+
13
+// ReactDOM.render(
14
+//   <PopupCreateHtmlDocument />
15
+//   , document.getElementById('content')
16
+// )

+ 24 - 0
frontend_app_admin_workspace_user/src/index.js View File

@@ -0,0 +1,24 @@
1
+import React from 'react'
2
+import ReactDOM from 'react-dom'
3
+import AdminWorkspaceUser from './container/AdminWorkspaceUser.jsx'
4
+
5
+require('./css/index.styl')
6
+
7
+const appInterface = {
8
+  name: 'admin_workspace_user',
9
+  isRendered: false,
10
+  renderAppFullscreen: data => {
11
+    return ReactDOM.render(
12
+      <AdminWorkspaceUser data={data} />
13
+      , document.getElementById(data.config.domContainer)
14
+    )
15
+  },
16
+  unmountApp: domId => {
17
+    return ReactDOM.unmountComponentAtNode(document.getElementById(domId)) // returns bool
18
+  }
19
+  // renderAppPopupCreation: data => {
20
+  //   return null
21
+  // }
22
+}
23
+
24
+module.exports = appInterface

+ 87 - 0
frontend_app_admin_workspace_user/webpack.config.js View File

@@ -0,0 +1,87 @@
1
+const webpack = require('webpack')
2
+const path = require('path')
3
+const isProduction = process.env.NODE_ENV === 'production'
4
+
5
+console.log('isProduction : ', isProduction)
6
+
7
+module.exports = {
8
+  entry: isProduction
9
+    ? './src/index.js' // only one instance of babel-polyfill is allowed
10
+    : ['babel-polyfill', './src/index.dev.js'],
11
+  output: {
12
+    path: path.resolve(__dirname, 'dist'),
13
+    filename: isProduction ? 'admin_workspace_user.app.js' : 'admin_workspace_user.app.dev.js',
14
+    pathinfo: !isProduction,
15
+    library: isProduction ? 'appAdminWorkspaceUser' : undefined,
16
+    libraryTarget: isProduction ? 'var' : undefined
17
+  },
18
+  externals: {},
19
+  // isProduction ? { // Côme - since plugins are imported through <script>, cannot externalize libraries
20
+  //   react: {commonjs: 'react', commonjs2: 'react', amd: 'react', root: '_'},
21
+  //   'react-dom': {commonjs: 'react-dom', commonjs2: 'react-dom', amd: 'react-dom', root: '_'},
22
+  //   classnames: {commonjs: 'classnames', commonjs2: 'classnames', amd: 'classnames', root: '_'},
23
+  //   'prop-types': {commonjs: 'prop-types', commonjs2: 'prop-types', amd: 'prop-types', root: '_'},
24
+  //   tracim_lib: {commonjs: 'tracim_lib', commonjs2: 'tracim_lib', amd: 'tracim_lib', root: '_'}
25
+  // }
26
+  // : {},
27
+  devServer: {
28
+    contentBase: path.join(__dirname, 'dist/'),
29
+    port: 8073,
30
+    hot: true,
31
+    noInfo: true,
32
+    overlay: {
33
+      warnings: false,
34
+      errors: true
35
+    },
36
+    historyApiFallback: true
37
+    // headers: {
38
+    //   'Access-Control-Allow-Origin': '*'
39
+    // }
40
+  },
41
+  devtool: isProduction ? false : 'cheap-module-source-map',
42
+  module: {
43
+    rules: [{
44
+      test: /\.jsx?$/,
45
+      enforce: 'pre',
46
+      use: 'standard-loader',
47
+      exclude: [/node_modules/]
48
+    }, {
49
+      test: [/\.js$/, /\.jsx$/],
50
+      loader: 'babel-loader',
51
+      options: {
52
+        presets: ['env', 'react'],
53
+        plugins: ['transform-object-rest-spread', 'transform-class-properties', 'transform-object-assign']
54
+      },
55
+      exclude: [/node_modules/]
56
+    }, {
57
+      test: /\.css$/,
58
+      use: ['style-loader', 'css-loader']
59
+    }, {
60
+      test: /\.styl$/,
61
+      use: ['style-loader', 'css-loader', 'stylus-loader']
62
+    }, {
63
+      test: /\.(jpg|png|svg)$/,
64
+      loader: 'url-loader',
65
+      options: {
66
+        limit: 25000
67
+      }
68
+    }]
69
+  },
70
+  resolve: {
71
+    extensions: ['.js', '.jsx']
72
+  },
73
+  plugins: [
74
+    ...[], // generic plugins always present
75
+    ...(isProduction
76
+      ? [ // production specific plugins
77
+        new webpack.DefinePlugin({
78
+          'process.env': { 'NODE_ENV': JSON.stringify('production') }
79
+        }),
80
+        new webpack.optimize.UglifyJsPlugin({
81
+          compress: { warnings: false }
82
+        })
83
+      ]
84
+      : [] // development specific plugins
85
+    )
86
+  ]
87
+}

+ 1 - 1
frontend_app_html-document/package.json View File

@@ -53,7 +53,7 @@
53 53
       "btoa",
54 54
       "wysiwyg",
55 55
       "tinymce",
56
-      "GLOBAL_renderAppFull",
56
+      "GLOBAL_renderAppFeature",
57 57
       "GLOBAL_unmountApp",
58 58
       "GLOBAL_dispatchEvent"
59 59
     ],

+ 1 - 1
frontend_app_html-document/src/container/PopupCreateHtmlDocument.jsx View File

@@ -15,7 +15,7 @@ const debug = { // outdated
15 15
     faIcon: 'file-text-o',
16 16
     hexcolor: '#3f52e3',
17 17
     creationLabel: 'Write a document',
18
-    domContainer: 'appContainer',
18
+    domContainer: 'appFeatureContainer',
19 19
     apiUrl: 'http://localhost:3001',
20 20
     apiHeader: {
21 21
       'Accept': 'application/json',

+ 1 - 1
frontend_app_html-document/src/helper.js View File

@@ -20,7 +20,7 @@ export const debug = {
20 20
     faIcon: 'file-text-o',
21 21
     hexcolor: '#3f52e3',
22 22
     creationLabel: 'Write a document',
23
-    domContainer: 'appContainer',
23
+    domContainer: 'appFeatureContainer',
24 24
     apiUrl: 'http://localhost:6543/api/v2',
25 25
     apiHeader: {
26 26
       'Accept': 'application/json',

+ 1 - 1
frontend_app_html-document/src/index.js View File

@@ -12,7 +12,7 @@ require('./css/index.styl')
12 12
 const appInterface = {
13 13
   name: 'html-document',
14 14
   isRendered: false,
15
-  renderAppFull: data => {
15
+  renderAppFeature: data => {
16 16
     return ReactDOM.render(
17 17
       <HtmlDocument data={data} />
18 18
       , document.getElementById(data.config.domContainer)

+ 1 - 1
frontend_app_thread/package.json View File

@@ -53,7 +53,7 @@
53 53
       "btoa",
54 54
       "wysiwyg",
55 55
       "tinymce",
56
-      "GLOBAL_renderAppFull",
56
+      "GLOBAL_renderAppFeature",
57 57
       "GLOBAL_unmountApp",
58 58
       "GLOBAL_dispatchEvent"
59 59
     ],

+ 1 - 1
frontend_app_thread/src/container/PopupCreateThread.jsx View File

@@ -15,7 +15,7 @@ const debug = { // outdated
15 15
     faIcon: 'file-text-o',
16 16
     hexcolor: '#ad4cf9',
17 17
     creationLabel: 'Write a thread',
18
-    domContainer: 'appContainer',
18
+    domContainer: 'appFeatureContainer',
19 19
     apiUrl: 'http://localhost:3001',
20 20
     mockApiUrl: 'http://localhost:8071',
21 21
     apiHeader: {

+ 1 - 1
frontend_app_thread/src/helper.js View File

@@ -12,7 +12,7 @@ export const debug = { // copied from html-document => outdated
12 12
     faIcon: 'comments-o',
13 13
     hexcolor: '#ad4cf9',
14 14
     creationLabel: 'Write a thread',
15
-    domContainer: 'appContainer',
15
+    domContainer: 'appFeatureContainer',
16 16
     apiUrl: 'http://localhost:6543/api/v2',
17 17
     mockApiUrl: 'http://localhost:3001',
18 18
     apiHeader: {

+ 1 - 1
frontend_app_thread/src/index.js View File

@@ -8,7 +8,7 @@ require('./css/index.styl')
8 8
 const appInterface = {
9 9
   name: 'thread',
10 10
   isRendered: false,
11
-  renderAppFull: data => {
11
+  renderAppFeature: data => {
12 12
     return ReactDOM.render(
13 13
       <Thread data={data} />
14 14
       , document.getElementById(data.config.domContainer)

frontend/src/component/common/layout/PageContent.jsx → frontend_lib/src/component/Layout/PageContent.jsx View File


frontend/src/component/common/layout/PageTitle.jsx → frontend_lib/src/component/Layout/PageTitle.jsx View File

@@ -8,9 +8,9 @@ const PageTitle = props => {
8 8
       <div className={classnames(`${props.parentClass}__title`, 'pageTitleGeneric__title d-flex align-items-center')}>
9 9
         <div className='pageTitleGeneric__title__icon mr-3'>
10 10
           <i className='fa fa-fw fa-th mr-3' />
11
-          Liste des Contenus
11
+          {props.title}
12 12
         </div>
13
-        {props.title}
13
+        {props.subtitle}
14 14
       </div>
15 15
       {props.children}
16 16
     </div>
@@ -19,6 +19,7 @@ const PageTitle = props => {
19 19
 
20 20
 PageTitle.propTypes = {
21 21
   title: PropTypes.string.isRequired,
22
+  subtitle: PropTypes.string,
22 23
   parentClass: PropTypes.string,
23 24
   customClass: PropTypes.string
24 25
 }

frontend/src/component/common/layout/PageWrapper.jsx → frontend_lib/src/component/Layout/PageWrapper.jsx View File


+ 8 - 0
frontend_lib/src/index.js View File

@@ -14,6 +14,10 @@ import libTimeline from './component/Timeline/Timeline.jsx'
14 14
 import libTextAreaApp from './component/Input/TextAreaApp/TextAreaApp.jsx'
15 15
 import libBtnSwitch from './component/Input/BtnSwitch/BtnSwitch.jsx'
16 16
 
17
+import libPageWrapper from './component/Layout/PageWrapper.jsx'
18
+import libPageTitle from './component/Layout/PageTitle.jsx'
19
+import libPageContent from './component/Layout/PageContent.jsx'
20
+
17 21
 import libDelimiter from './component/Delimiter/Delimiter.jsx'
18 22
 
19 23
 import libCardPopup from './component/CardPopup/CardPopup.jsx'
@@ -40,6 +44,10 @@ export const Timeline = libTimeline
40 44
 export const TextAreaApp = libTextAreaApp
41 45
 export const BtnSwitch = libBtnSwitch
42 46
 
47
+export const PageWrapper = libPageWrapper
48
+export const PageTitle = libPageTitle
49
+export const PageContent = libPageContent
50
+
43 51
 export const Delimiter = libDelimiter
44 52
 
45 53
 export const CardPopup = libCardPopup

+ 10 - 0
install_frontend_dependencies.sh View File

@@ -32,6 +32,16 @@ log "npm link tracim_frontend_lib"
32 32
 npm link tracim_frontend_lib
33 33
 cd -
34 34
 
35
+# install app Admin Workspace User
36
+
37
+log "cd frontend_app_admin_workspace_user"
38
+cd frontend_app_admin_workspace_user
39
+log "npm i"
40
+npm i
41
+log "npm link tracim_frontend_lib"
42
+npm link tracim_frontend_lib
43
+cd -
44
+
35 45
 # install Tracim Frontend
36 46
 
37 47
 log "cd frontend"