Browse Source

refactored app interface to allow popupCreateContent

Skylsmoi 5 years ago
parent
commit
03cd6b2531

+ 33 - 23
dist/index.html View File

@@ -40,22 +40,24 @@
40 40
     <script type='text/javascript'>
41 41
       let prevSelectedApp = {name: ''} // default value
42 42
 
43
+      getSelectedApp = name => {
44
+        switch (name) {
45
+          case 'PageHtml':
46
+            return appPageHtml
47
+          case 'Thread':
48
+            return appThread
49
+          case 'File':
50
+            return appFile
51
+        }
52
+      }
53
+
43 54
       GLOBAL_renderApp = app => {
44
-        console.log('GLOBAL_renderApp => ', app)
45
-        const selectedApp = (() => {
46
-          switch (app.config.name) {
47
-            case 'PageHtml':
48
-              return appPageHtml
49
-            case 'Thread':
50
-              return appThread
51
-            case 'File':
52
-              console.log('spoted')
53
-              return appFile
54
-          }
55
-        })()
55
+        console.log('GLOBAL_renderApp', app)
56
+
57
+        const selectedApp = getSelectedApp(app.config.name)
56 58
 
57 59
         if (selectedApp.isRendered) {
58
-          GLOBAL_dispatchEvent(`${app.config.name}_showApp`, app)
60
+          GLOBAL_dispatchEvent({type: `${app.config.name}_showApp`, data: app})
59 61
         } else {
60 62
           selectedApp.renderApp(app)
61 63
           selectedApp.isRendered = true
@@ -64,21 +66,29 @@
64 66
         }
65 67
       }
66 68
 
67
-      GLOBAL_dispatchEvent = (type, data) => {
68
-        var event = new CustomEvent('appCustomEvent', {detail: {type, data}})
69
+      GLOBAL_renderCreateContentApp = app => {
70
+        console.log('GLOBAL_renderCreateContentApp', app)
71
+
72
+        getSelectedApp(app.config.name).renderPopupCreation(app)
73
+      }
74
+
75
+      GLOBAL_dispatchEvent = ({ type, data }) => {
76
+        console.log('GLOBAL_dispatchEvent', type, data)
77
+
78
+        const event = new CustomEvent('appCustomEvent', { detail: { type, data } })
69 79
         document.dispatchEvent(event)
70 80
       }
71 81
 
72
-      GLOBAL_hideApp = appName => {
73
-        switch (appName) {
74
-          case 'PageHtml':
75
-            GLOBAL_dispatchEvent('PageHtml_hideApp', {}); break
76
-          case 'Thread':
77
-            GLOBAL_dispatchEvent('Thread_hideApp', {}); break
78
-          case 'File':
79
-            GLOBAL_dispatchEvent('File_hideApp', {}); break
82
+      GLOBAL_eventReducer = ({ detail: { type, data } }) => {
83
+        console.log('GLOBAL_eventReducer', type, data)
84
+
85
+        switch (type) {
86
+          case 'hide_popupCreateContent':
87
+            getSelectedApp(data.name).hideApp('popupCreateContentContainer')
88
+            break
80 89
         }
81 90
       }
91
+      document.addEventListener('appCustomEvent', GLOBAL_eventReducer)
82 92
     </script>
83 93
 
84 94
     <script type='text/javascript'>

+ 1 - 0
package.json View File

@@ -60,6 +60,7 @@
60 60
       "fetch",
61 61
       "history",
62 62
       "GLOBAL_renderApp",
63
+      "GLOBAL_renderCreateContentApp",
63 64
       "GLOBAL_dispatchEvent",
64 65
       "GLOBAL_hideApp"
65 66
     ],

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

@@ -15,8 +15,7 @@ import {
15 15
   WORKSPACE_LIST,
16 16
   FOLDER,
17 17
   setFolderData,
18
-  APP_LIST,
19
-  setAppList
18
+  APP_LIST
20 19
 } from './action-creator.sync.js'
21 20
 
22 21
 /*
@@ -87,7 +86,7 @@ export const getTimezone = () => async dispatch => {
87 86
 
88 87
 export const postUserLogin = (login, password, rememberMe) => async dispatch => {
89 88
   return fetchWrapper({
90
-    url: `${FETCH_CONFIG.mockApiUrl}/sessions/login`,
89
+    url: `${FETCH_CONFIG.mockApiUrl}/sessions/login`, // FETCH_CONFIG.apiUrl
91 90
     param: {
92 91
       headers: {...FETCH_CONFIG.headers},
93 92
       method: 'POST',
@@ -104,7 +103,7 @@ export const postUserLogin = (login, password, rememberMe) => async dispatch =>
104 103
 
105 104
 export const postUserLogout = () => async dispatch => {
106 105
   return fetchWrapper({
107
-    url: `${FETCH_CONFIG.mockApiUrl}/sessions/logout`,
106
+    url: `${FETCH_CONFIG.mockApiUrl}/sessions/logout`, // FETCH_CONFIG.apiUrl
108 107
     param: {
109 108
       headers: {...FETCH_CONFIG.headers},
110 109
       method: 'POST'
@@ -116,7 +115,7 @@ export const postUserLogout = () => async dispatch => {
116 115
 
117 116
 export const getUserIsConnected = () => async dispatch => {
118 117
   return fetchWrapper({
119
-    url: `${FETCH_CONFIG.mockApiUrl}/sessions/whoami`,
118
+    url: `${FETCH_CONFIG.mockApiUrl}/sessions/whoami`, // FETCH_CONFIG.apiUrl
120 119
     param: {...FETCH_CONFIG.header, method: 'GET'},
121 120
     actionName: USER_CONNECTED,
122 121
     dispatch
@@ -181,12 +180,11 @@ export const getFolderContent = (workspaceId, folderId) => async dispatch => {
181 180
   if (fetchGetFolderContent.status === 200) dispatch(setFolderData(folderId, fetchGetFolderContent.json))
182 181
 }
183 182
 
184
-export const getAppList = () => async dispatch => {
185
-  const fetchGetAppList = await fetchWrapper({
183
+export const getAppList = () => dispatch => {
184
+  return fetchWrapper({
186 185
     url: `${FETCH_CONFIG.mockApiUrl}/app/config`,
187 186
     param: {...FETCH_CONFIG.header, method: 'GET'},
188 187
     actionName: APP_LIST,
189 188
     dispatch
190 189
   })
191
-  if (fetchGetAppList.status === 200) dispatch(setAppList(fetchGetAppList.json))
192 190
 }

+ 12 - 2
src/appFactory.js View File

@@ -13,15 +13,25 @@ export function appFactory (WrappedComponent) {
13 13
       content
14 14
     })
15 15
 
16
-    emitEventApp = (type, data) => GLOBAL_dispatchEvent(type, data)
16
+    renderCreateContentApp = (appConfig, user, folder) => GLOBAL_renderCreateContentApp({
17
+      loggedUser: user.logged ? user : {},
18
+      config: {
19
+        ...appConfig,
20
+        domContainer: 'popupCreateContentContainer',
21
+        apiUrl: FETCH_CONFIG.apiUrl,
22
+        mockApiUrl: FETCH_CONFIG.mockApiUrl
23
+      },
24
+      folder
25
+    })
17 26
 
18
-    hideApp = appName => GLOBAL_hideApp(appName)
27
+    emitEventApp = (type, data) => GLOBAL_dispatchEvent(type, data)
19 28
 
20 29
     render () {
21 30
       return (
22 31
         <WrappedComponent
23 32
           {...this.props}
24 33
           renderApp={this.renderApp}
34
+          renderCreateContentApp={this.renderCreateContentApp}
25 35
           emitEventApp={this.emitEventApp}
26 36
           hideApp={this.hideApp}
27 37
         />

+ 5 - 1
src/component/PopupCreateContent/PopupCreateContainer.jsx View File

@@ -1,12 +1,16 @@
1 1
 import React from 'react'
2 2
 import PropTypes from 'prop-types'
3
-import CardPopup from '../common/CardPopup/CardPopup.jsx'
3
+// import CardPopup from '../common/CardPopup/CardPopup.jsx'
4
+import { CardPopup } from 'tracim_lib'
4 5
 import GenericContent from './ContentType/GenericContent.jsx'
5 6
 import FileContent from './ContentType/FileContent.jsx'
6 7
 import WsContent from './ContentType/WsContent.jsx'
7 8
 
8 9
 require('./PopupCreateContainer.styl')
9 10
 
11
+console.log('cardPopp', CardPopup)
12
+console.log('Warning: PopupCreateContainer is deprecated')
13
+
10 14
 const PopupCreateContainer = props => {
11 15
   const FormCreateContent = (() => {
12 16
     switch (props.type) {

+ 2 - 0
src/component/PopupCreateContent/README.md View File

@@ -0,0 +1,2 @@
1
+# DEPRECATED
2
+this folder is deprecated, every popup to create a new content is now handled by apps

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

@@ -20,6 +20,7 @@ class Folder extends React.Component {
20 20
   }
21 21
 
22 22
   handleClickCreateContent = (e, folder, type) => {
23
+    e.preventDefault()
23 24
     e.stopPropagation() // because we have a link inside a link (togler and newFile)
24 25
     this.props.onClickCreateContent(folder, type)
25 26
   }

+ 0 - 37
src/component/common/CardPopup/CardPopup.jsx View File

@@ -1,37 +0,0 @@
1
-import React from 'react'
2
-import PropTypes from 'prop-types'
3
-import classnames from 'classnames'
4
-
5
-require('./CardPopup.styl')
6
-
7
-const CardPopup = props => {
8
-  return (
9
-    <div className={classnames(props.customClass, 'cardPopup')}>
10
-      <div className='cardPopup__container'>
11
-        <div className='cardPopup__header' />
12
-
13
-        <div className='nopadding'>
14
-          <div className='cardPopup__close' onClick={props.onClose}>
15
-            <i className='fa fa-times' />
16
-          </div>
17
-
18
-          <div className='cardPopup__body'>
19
-            { props.children }
20
-          </div>
21
-        </div>
22
-      </div>
23
-    </div>
24
-  )
25
-}
26
-
27
-export default CardPopup
28
-
29
-CardPopup.propTypes = {
30
-  customClass: PropTypes.string,
31
-  onClose: PropTypes.func
32
-}
33
-
34
-CardPopup.defaultProps = {
35
-  customClass: 'defaultCustomClass',
36
-  onClose: () => {}
37
-}

+ 0 - 39
src/component/common/CardPopup/CardPopup.styl View File

@@ -1,39 +0,0 @@
1
-@import '../../../css/Variable.styl'
2
-
3
-.cardPopup
4
-  position fixed
5
-  display flex
6
-  justify-content center
7
-  width 100%
8
-  z-index 10
9
-  &__container
10
-    margin-top 50px
11
-    border 0
12
-    border-radius 10px
13
-    width 800px
14
-    background lightGrey
15
-    box-shadow shadow-all
16
-  &__header
17
-    border-top-right-radius 10px
18
-    border-top-left-radius 10px
19
-    width 100%
20
-    height 8px
21
-  &__close
22
-    display flex
23
-    justify-content flex-end
24
-    margin 5px
25
-    cursor pointer
26
-  &__body
27
-    display flex
28
-    align-items center
29
-    margin 10px 0 25px 0
30
-    &__icon
31
-      padding 0 30px
32
-      font-size 40px
33
-    &__text
34
-      &__title
35
-        font-size 20px
36
-        font-weight 600
37
-      &__message
38
-        padding-right 20px
39
-        font-weight 500

+ 1 - 5
src/container/WIPcomponent.jsx View File

@@ -1,17 +1,13 @@
1 1
 import React from 'react'
2 2
 import { connect } from 'react-redux'
3
-import PopupCreateContainer from '../component/PopupCreateContent/PopupCreateContainer.jsx'
4 3
 import ProgressBar from './ProgressBar.jsx'
5 4
 import Home from './Home.jsx'
6
-import CardPopup from '../component/common/CardPopup/CardPopup.jsx'
7 5
 
8 6
 export class WIPcomponent extends React.Component {
9 7
   render () {
10 8
     const MyComponent = {
11
-      PopupCreateContainer,
12 9
       ProgressBar,
13
-      Home,
14
-      CardPopup
10
+      Home
15 11
     }
16 12
 
17 13
     // this.props.dispatch(newFlashMessage('TEST', 'info', 0))

+ 38 - 40
src/container/WorkspaceContent.jsx View File

@@ -10,7 +10,6 @@ import PageWrapper from '../component/common/layout/PageWrapper.jsx'
10 10
 import PageTitle from '../component/common/layout/PageTitle.jsx'
11 11
 import PageContent from '../component/common/layout/PageContent.jsx'
12 12
 import DropdownCreateButton from '../component/common/Input/DropdownCreateButton.jsx'
13
-import PopupCreateContent from '../component/PopupCreateContent/PopupCreateContainer.jsx'
14 13
 import {
15 14
   getAppList,
16 15
   getWorkspaceContent,
@@ -18,7 +17,7 @@ import {
18 17
   getWorkspaceList
19 18
 } from '../action-creator.async.js'
20 19
 import {
21
-  newFlashMessage,
20
+  newFlashMessage, setAppList,
22 21
   setWorkspaceData,
23 22
   setWorkspaceListIsOpenInSidebar,
24 23
   updateWorkspaceListData
@@ -37,13 +36,29 @@ class WorkspaceContent extends React.Component {
37 36
       },
38 37
       workspaceIdInUrl: props.match.params.idws ? parseInt(props.match.params.idws) : null
39 38
     }
39
+
40
+    document.addEventListener('appCustomEvent', this.customEventReducer)
41
+  }
42
+
43
+  customEventReducer = ({ detail: { type, data } }) => {
44
+    switch (type) {
45
+      case 'openContentUrl':
46
+        this.props.history.push(PAGE.WORKSPACE.CONTENT(data.idWorkspace, data.idContent))
47
+        break
48
+      case 'appClosed':
49
+        this.props.history.push(PAGE.WORKSPACE.CONTENT(this.props.workspace.id, ''))
50
+        break
51
+    }
40 52
   }
41 53
 
42 54
   async componentDidMount () {
43 55
     const { workspaceIdInUrl } = this.state
44 56
     const { user, workspaceList, app, match, location, dispatch } = this.props
45 57
 
46
-    if (Object.keys(app).length === 0) dispatch(getAppList()) // async but no need await
58
+    if (Object.keys(app).length === 0) {
59
+      const fetchGetAppList = await dispatch(getAppList())
60
+      if (fetchGetAppList.status === 200) dispatch(setAppList(fetchGetAppList.json))
61
+    }
47 62
 
48 63
     let wsToLoad = null
49 64
     if (match.params.idws !== undefined) wsToLoad = match.params.idws
@@ -64,34 +79,35 @@ class WorkspaceContent extends React.Component {
64 79
     if (wsToLoad === null) return // ws already loaded
65 80
 
66 81
     const wsContent = await dispatch(getWorkspaceContent(wsToLoad))
67
-    if (wsContent.status === 200) {
68
-      dispatch(setWorkspaceData(wsContent.json, qs.parse(location.search).type))
69
-
70
-      if (match.params.idcts) { // if a content id is in url, open it
71
-        const contentToOpen = wsContent.json.content.find(wsc => wsc.id === parseInt(match.params.idcts))
72
-        if (contentToOpen === undefined) return
73 82
 
74
-        this.handleClickContentItem(contentToOpen)
75
-      }
76
-    } else dispatch(newFlashMessage('Error while loading workspace', 'danger'))
83
+    if (wsContent.status === 200) dispatch(setWorkspaceData(wsContent.json, qs.parse(location.search).type))
84
+    else dispatch(newFlashMessage('Error while loading workspace', 'danger'))
77 85
   }
78 86
 
79 87
   componentDidUpdate (prevProps, prevState) {
80
-    const { user, match, dispatch } = this.props
88
+    const { app, workspace, user, renderApp, match, dispatch } = this.props
81 89
 
82 90
     if (this.state.workspaceIdInUrl === null) return
83 91
 
84 92
     const newWorkspaceId = parseInt(match.params.idws)
85
-    prevState.workspaceIdInUrl !== newWorkspaceId && this.setState({workspaceIdInUrl: newWorkspaceId})
93
+    if (prevState.workspaceIdInUrl !== newWorkspaceId) this.setState({workspaceIdInUrl: newWorkspaceId})
86 94
 
87 95
     if (user.id !== -1 && prevProps.user.id !== user.id) dispatch(getWorkspaceList(user.user_id, newWorkspaceId))
88
-  }
89 96
 
90
-  handleClickContentItem = content => {
91
-    this.props.history.push(`${PAGE.WORKSPACE.CONTENT(content.workspace_id, content.id)}${this.props.location.search}`)
92
-    this.props.renderApp(this.props.app[content.type], this.props.user, {...content, workspace: this.props.workspace})
97
+    if (match.params.idcts) { // if a content id is in url, open it
98
+      const contentToOpen = workspace.content.find(wsc => wsc.id === parseInt(match.params.idcts))
99
+      if (contentToOpen === undefined) return
100
+
101
+      renderApp(
102
+        app[contentToOpen.type],
103
+        user,
104
+        {...contentToOpen, workspace: workspace}
105
+      )
106
+    }
93 107
   }
94 108
 
109
+  handleClickContentItem = content => this.props.history.push(`${PAGE.WORKSPACE.CONTENT(content.workspace_id, content.id)}${this.props.location.search}`)
110
+
95 111
   handleClickEditContentItem = (e, content) => {
96 112
     e.stopPropagation()
97 113
     console.log('edit nyi', content)
@@ -121,21 +137,9 @@ class WorkspaceContent extends React.Component {
121 137
     this.props.dispatch(getFolderContent(this.props.workspace.id, folderId))
122 138
   }
123 139
 
124
-  handleClickCreateContent = (folder, contentType) => this.setState({
125
-    popupCreateContent: {
126
-      display: true,
127
-      type: contentType,
128
-      folder: folder
129
-    }
130
-  })
131
-
132
-  handleClosePopupCreateContent = () => this.setState({
133
-    popupCreateContent: {
134
-      display: false,
135
-      type: undefined,
136
-      folder: undefined
137
-    }
138
-  })
140
+  handleClickCreateContent = (folder, contentType) => {
141
+    this.props.renderCreateContentApp(this.props.app[contentType], this.props.user, folder)
142
+  }
139 143
 
140 144
   render () {
141 145
     const { workspace, app } = this.props
@@ -162,13 +166,7 @@ class WorkspaceContent extends React.Component {
162 166
           </PageTitle>
163 167
 
164 168
           <PageContent parentClass='workspace__content'>
165
-            { this.state.popupCreateContent.display &&
166
-              <PopupCreateContent
167
-                type={this.state.popupCreateContent.type}
168
-                folder={this.state.popupCreateContent.folder}
169
-                onClose={this.handleClosePopupCreateContent}
170
-              />
171
-            }
169
+            <div id='popupCreateContentContainer' />
172 170
 
173 171
             <div className='workspace__content__fileandfolder folder__content active'>
174 172
               <ContentItemHeader />