Browse Source

make thread dynamic

Skylsmoi 6 years ago
parent
commit
09dadc1feb
7 changed files with 236 additions and 219 deletions
  1. 2 2
      dist/index.html
  2. 36 177
      src/component/Thread.jsx
  3. 70 36
      src/container/Thread.jsx
  4. 38 3
      src/css/index.styl
  5. BIN
      src/img/imgProfil.png
  6. 87 0
      src/listMessageDebugData.js
  7. 3 1
      webpack.config.js

+ 2 - 2
dist/index.html View File

@@ -20,8 +20,8 @@
20 20
   <script src='./thread.app.dev.js'></script>
21 21
 
22 22
   <script type='text/javascript'>
23
-    GLOBAL_renderApp = appName => {
24
-      switch (appName) {
23
+    GLOBAL_renderApp = app => {
24
+      switch (app.appData.name) {
25 25
         case 'PageHtml':
26 26
           appPageHtml.renderApp('appContainer'); break
27 27
         case 'Thread':

+ 36 - 177
src/component/Thread.jsx View File

@@ -1,195 +1,54 @@
1 1
 import React from 'react'
2
-// import classnames from 'classnames'
3
-import imgProfil from '../img/imgProfil.png'
2
+import classnames from 'classnames'
4 3
 
5
-const PageHtml = props => {
4
+const Thread = props => {
6 5
   return (
7
-    <div className='wsFileThread wsFileGeneric'>
8
-      <div className='wsFileThread__header wsFileGeneric__header'>
9
-        <div className='wsFileGeneric__header__icon'>
10
-          <i className='fa fa-comments' />
11
-        </div>
12
-
13
-        <div className='wsFileGeneric__header__text mr-auto'>
14
-          Discussions à propos du nouveau système de facturation
15
-        </div>
16
-
17
-        <div className='wsFileGeneric__header__close'>
18
-          <i className='fa fa-times' />
19
-        </div>
20
-      </div>
21
-
22
-      <div className='wsFileGeneric__option'>
23
-        <div className='wsFileGeneric__option__menu'>
24
-          <div className='wsFileGeneric__option__menu__action'>
25
-            <i className='fa fa-pencil' />
26
-          </div>
27
-
28
-          <div className='wsFileGeneric__option__menu__action'>
29
-            <i className='fa fa-archive' />
30
-          </div>
31
-
32
-          <div className='wsFileGeneric__option__menu__action'>
33
-            <i className='fa fa-trash' />
34
-          </div>
35
-        </div>
36
-      </div>
37
-
38
-      <div className='wsFileThread__wrapper wsFileGeneric__wrapper'>
39
-        <ul className='wsFileThread__messagelist wsFileGeneric__messagelist'>
40
-
41
-          <li className='wsFileThread__messagelist__item wsFileGeneric__messagelist__item sended'>
42
-            <div className='wsFileGeneric__messagelist__item__avatar'>
43
-              <img src={imgProfil} alt='avatar' />
6
+    <div className='wsContentThread'>
7
+      <ul className='wsContentThread__messagelist wsFileGeneric__messagelist'>
8
+        { props.listMessage.map(msg =>
9
+          <li className={classnames('wsContentThread__messagelist__item', 'wsFileGeneric__messagelist__item', {
10
+            'sended': props.loggedUser.id === msg.author.id,
11
+            'received': !(props.loggedUser.id === msg.author.id)
12
+          })} key={msg.id}>
13
+            <div className='wsContentThread__messagelist__item__avatar wsFileGeneric__messagelist__item__avatar'>
14
+              <img src={msg.author.avatar} alt='avatar' />
44 15
             </div>
45 16
 
46
-            <div className='wsFileGeneric__messagelist__item__createhour'>
47
-              27/11/17 à 11h45
17
+            <div className='wsContentThread__messagelist__item__createhour wsFileGeneric__messagelist__item__createhour'>
18
+              {msg.createdAt.day} à {msg.createdAt.hour}
48 19
             </div>
49 20
 
50
-            <div className='wsFileThread__messagelist__item__content wsFileGeneric__messagelist__item__content'>
51
-              Proident esse laboris in sed officia exercitation ut anim ea.
21
+            <div className='wsContentThread__messagelist__item__content wsFileGeneric__messagelist__item__content'>
22
+              {msg.text}
52 23
             </div>
53 24
           </li>
25
+        )}
26
+      </ul>
54 27
 
55
-          <li className='wsFileGeneric__messagelist__item received'>
56
-            <div className='wsFileGeneric__messagelist__item__avatar'>
57
-              <img src={imgProfil} alt='avatar' />
58
-            </div>
59
-            <div className='wsFileGeneric__messagelist__item__createhour'>
60
-              27/11/17 à 11h47
61
-            </div>
62
-            <div className='wsFileThread__messagelist__item__content wsFileGeneric__messagelist__item__content'>
63
-              Proident esse laboris in sed officia exercitation ut anim ea.
64
-              Proident esse laboris in sed officia exercitation ut anim ea.
65
-              Proident esse laboris in sed officia exercitation ut anim ea.
66
-              Proident esse laboris in sed officia exercitation ut anim ea.
67
-              Proident esse laboris in sed officia exercitation ut anim ea.
68
-            </div>
69
-          </li>
70
-
71
-          <li className='wsFileGeneric__messagelist__item sended'>
72
-            <div className='wsFileGeneric__messagelist__item__avatar'>
73
-              <img src={imgProfil} alt='avatar' />
74
-            </div>
75
-            <div className='wsFileGeneric__messagelist__item__createhour'>
76
-              27/11/17 à 11h45
77
-            </div>
78
-            <div className='wsFileThread__messagelist__item__content wsFileGeneric__messagelist__item__content'>
79
-              Proident esse laboris in sed officia exercitation ut anim ea.
80
-            </div>
81
-          </li>
28
+      <form className='wsContentThread__texteditor wsFileGeneric__texteditor'>
29
+        <div className='wsContentThread__texteditor__simpletext wsFileGeneric__texteditor__simpletext input-group'>
30
+          <input type='text' className='wsContentThread__texteditor__simpletext__input wsFileGeneric__texteditor__simpletext__input form-control' placeholder='...' />
82 31
 
83
-          <li className='wsFileGeneric__messagelist__item sended'>
84
-            <div className='wsFileGeneric__messagelist__item__avatar'>
85
-              <img src={imgProfil} alt='avatar' />
86
-            </div>
87
-            <div className='wsFileGeneric__messagelist__item__createhour'>
88
-              27/11/17 à 11h45
89
-            </div>
90
-            <div className='wsFileThread__messagelist__item__content wsFileGeneric__messagelist__item__content'>
91
-              Proident esse laboris in sed officia exercitation ut anim ea.
92
-            </div>
93
-          </li>
94
-
95
-          <li className='wsFileGeneric__messagelist__item received'>
96
-            <div className='wsFileGeneric__messagelist__item__avatar'>
97
-              <img src={imgProfil} alt='avatar' />
98
-            </div>
99
-            <div className='wsFileGeneric__messagelist__item__createhour'>
100
-              27/11/17 à 11h47
101
-            </div>
102
-            <div className='wsFileThread__messagelist__item__content wsFileGeneric__messagelist__item__content'>
103
-              Proident esse laboris in sed officia exercitation ut anim ea.
104
-              Proident esse laboris in sed officia exercitation ut anim ea.
105
-              Proident esse laboris in sed officia exercitation ut anim ea.
106
-              Proident esse laboris in sed officia exercitation ut anim ea.
107
-              Proident esse laboris in sed officia exercitation ut anim ea.
108
-            </div>
109
-          </li>
110
-
111
-          <li className='wsFileGeneric__messagelist__item received'>
112
-            <div className='wsFileGeneric__messagelist__item__avatar'>
113
-              <img src={imgProfil} alt='avatar' />
114
-            </div>
115
-            <div className='wsFileGeneric__messagelist__item__createhour'>
116
-              27/11/17 à 11h47
117
-            </div>
118
-            <div className='wsFileThread__messagelist__item__content wsFileGeneric__messagelist__item__content'>
119
-              Proident esse laboris in sed officia exercitation ut anim ea.
120
-              Proident esse laboris in sed officia exercitation ut anim ea.
121
-              Proident esse laboris in sed officia exercitation ut anim ea.
122
-              Proident esse laboris in sed officia exercitation ut anim ea.
123
-              Proident esse laboris in sed officia exercitation ut anim ea.
124
-            </div>
125
-          </li>
126
-
127
-          <li className='wsFileGeneric__messagelist__item sended'>
128
-            <div className='wsFileGeneric__messagelist__item__avatar'>
129
-              <img src={imgProfil} alt='avatar' />
130
-            </div>
131
-            <div className='wsFileGeneric__messagelist__item__createhour'>
132
-              27/11/17 à 11h45
133
-            </div>
134
-            <div className='wsFileThread__messagelist__item__content wsFileGeneric__messagelist__item__content'>
135
-              Proident esse laboris in sed officia exercitation ut anim ea.
136
-            </div>
137
-          </li>
138
-
139
-          <li className='wsFileGeneric__messagelist__item received'>
140
-            <div className='wsFileGeneric__messagelist__item__avatar'>
141
-              <img src={imgProfil} alt='avatar' />
142
-            </div>
143
-            <div className='wsFileGeneric__messagelist__item__createhour'>
144
-              27/11/17 à 11h47
145
-            </div>
146
-            <div className='wsFileThread__messagelist__item__content wsFileGeneric__messagelist__item__content'>
147
-              Proident esse laboris in sed officia exercitation ut anim ea.
148
-              Proident esse laboris in sed officia exercitation ut anim ea.
149
-              Proident esse laboris in sed officia exercitation ut anim ea.
150
-              Proident esse laboris in sed officia exercitation ut anim ea.
151
-              Proident esse laboris in sed officia exercitation ut anim ea.
152
-            </div>
153
-          </li>
154
-
155
-          <li className='wsFileGeneric__messagelist__item sended'>
156
-            <div className='wsFileGeneric__messagelist__item__avatar'>
157
-              <img src={imgProfil} alt='avatar' />
158
-            </div>
159
-            <div className='wsFileGeneric__messagelist__item__createhour'>
160
-              27/11/17 à 11h45
161
-            </div>
162
-            <div className='wsFileThread__messagelist__item__content wsFileGeneric__messagelist__item__content'>
163
-              Proident esse laboris in sed officia exercitation ut anim ea.
164
-            </div>
165
-          </li>
166
-        </ul>
167
-
168
-        <form className='wsFileThread__texteditor wsFileGeneric__texteditor'>
169
-          <div className='wsFileThread__texteditor__simpletext wsFileGeneric__texteditor__simpletext input-group'>
170
-            <input type='text' className='wsFileThread__texteditor__simpletext__input wsFileGeneric__texteditor__simpletext__input form-control' placeholder='...' />
171
-
172
-            <div className='wsFileThread__texteditor__simpletext__icon wsFileGeneric__texteditor__simpletext__icon input-group-addon'>
173
-              <i className='fa fa-font' />
174
-            </div>
32
+          <div className='wsContentThread__texteditor__simpletext__icon wsFileGeneric__texteditor__simpletext__icon input-group-addon'>
33
+            <i className='fa fa-font' />
175 34
           </div>
35
+        </div>
176 36
 
177
-          <div className='wsFileGeneric__texteditor__wysiwyg d-none d-xl-block'>
178
-            <textarea />
179
-          </div>
37
+        <div className='wsFileGeneric__texteditor__wysiwyg d-none d-xl-block'>
38
+          <textarea />
39
+        </div>
180 40
 
181
-          <div className='wsFileThread__texteditor__submit wsFileGeneric__texteditor__submit d-xl-flex justify-content-xl-center'>
182
-            <button type='submit' className='wsFileThread__texteditor__submit__btn wsFileGeneric__texteditor__submit__btn btn btn-primary'>
183
-              Envoyer
184
-              <div className='wsFileThread__texteditor__submit__btn__icon wsFileGeneric__texteditor__submit__btn__icon'>
185
-                <i className='fa fa-paper-plane-o' />
186
-              </div>
187
-            </button>
188
-          </div>
189
-        </form>
190
-      </div>
41
+        <div className='wsContentThread__texteditor__submit wsFileGeneric__texteditor__submit d-xl-flex justify-content-xl-center'>
42
+          <button type='submit' className='wsContentThread__texteditor__submit__btn wsFileGeneric__texteditor__submit__btn btn btn-primary'>
43
+            Envoyer
44
+            <div className='wsContentThread__texteditor__submit__btn__icon wsFileGeneric__texteditor__submit__btn__icon'>
45
+              <i className='fa fa-paper-plane-o' />
46
+            </div>
47
+          </button>
48
+        </div>
49
+      </form>
191 50
     </div>
192 51
   )
193 52
 }
194 53
 
195
-export default PageHtml
54
+export default Thread

+ 70 - 36
src/container/Thread.jsx View File

@@ -1,36 +1,73 @@
1 1
 import React from 'react'
2 2
 import ThreadComponent from '../component/Thread.jsx'
3 3
 import {
4
+  handleFetchResult,
4 5
   PopinFixed,
5 6
   PopinFixedHeader,
6 7
   PopinFixedOption,
7
-  PopinFixedContent,
8
-  Timeline
8
+  PopinFixedContent
9 9
 } from 'tracim_lib'
10
+import { listMessageDebugData } from '../listMessageDebugData.js'
11
+import { FETCH_CONFIG } from '../helper.js'
10 12
 
11
-class pageHtml extends React.Component {
13
+const debug = {
14
+  loggedUser: {
15
+    id: 5,
16
+    username: 'Stoi',
17
+    firstname: 'John',
18
+    lastname: 'Doe',
19
+    email: 'osef@algoo.fr',
20
+    avatar: 'https://avatars3.githubusercontent.com/u/11177014?s=460&v=4'
21
+  },
22
+  workspace: {
23
+    id: 1,
24
+    title: 'Test debug workspace'
25
+  },
26
+  content: {
27
+    id: 2,
28
+    type: 'thread',
29
+    status: 'validated',
30
+    title: 'test debug title'
31
+  },
32
+  listMessage: listMessageDebugData,
33
+  appConfig: {
34
+    name: 'Thread',
35
+    customClass: 'wsContentThread',
36
+    icon: 'fa fa-comments-o',
37
+    apiUrl: 'http://localhost:3001'
38
+  }
39
+}
40
+
41
+class Thread extends React.Component {
12 42
   constructor (props) {
13 43
     super(props)
14 44
     this.state = {
15 45
       appName: 'Thread',
16
-      data: props.data
17
-        ? props.data
18
-        : { // for debugg purpose
19
-          file: {
20
-            version: '3',
21
-            text: 'Bonjour ?'
22
-          },
23
-          appData: {
24
-            name: 'Thread',
25
-            componentLeft: 'Thread',
26
-            componentRight: undefined,
27
-            customClass: 'wsFileThread',
28
-            icon: 'fa fa-comments-o'
29
-          }
30
-        }
46
+      isVisible: true,
47
+      loggedUser: props.app ? props.app.loggedUser : debug.loggedUser,
48
+      workspace: props.app ? props.app.workspace : debug.workspace,
49
+      content: props.app ? props.app.content : debug.content,
50
+      listMessage: props.app ? props.app.content.message_list : debug.listMessage,
51
+      appConfig: props.app ? props.app.appConfig : debug.appConfig
31 52
     }
32 53
 
33
-    document.addEventListener('appCustomEvent', this.customEventReducer, false)
54
+    document.addEventListener('appCustomEvent', this.customEventReducer)
55
+  }
56
+
57
+  async componentDidMount () {
58
+    const { workspace, content, appConfig } = this.state
59
+    if (content.id === '-1') return // debug case
60
+
61
+    const fetchResultThread = await fetch(`${appConfig.apiUrl}/workspace/${workspace.id}/content/${content.id}`, {
62
+      ...FETCH_CONFIG,
63
+      method: 'GET'
64
+    })
65
+
66
+    fetchResultThread.json = await handleFetchResult(fetchResultThread)
67
+
68
+    this.setState({
69
+      content: fetchResultThread.json
70
+    })
34 71
   }
35 72
 
36 73
   customEventReducer = ({detail}) => {
@@ -42,33 +79,30 @@ class pageHtml extends React.Component {
42 79
   }
43 80
 
44 81
   handleClickBtnCloseApp = () => {
45
-    GLOBAL_unmountApp(this.state.appName)
82
+    this.setState({ isVisible: false })
46 83
   }
47 84
 
48 85
   render () {
49
-    const { file, appData } = this.state.data
86
+    const { isVisible, loggedUser, content, listMessage, appConfig } = this.state
87
+
88
+    if (!isVisible) return null
50 89
 
51 90
     return (
52
-      <PopinFixed customClass={`${appData.customClass}`}>
91
+      <PopinFixed customClass={`${appConfig.customClass}`}>
53 92
         <PopinFixedHeader
54
-          customClass={`${appData.customClass}`}
55
-          icon={appData.icon}
56
-          name={file.title}
93
+          customClass={`${appConfig.customClass}`}
94
+          icon={appConfig.icon}
95
+          name={content.title}
57 96
           onClickCloseBtn={this.handleClickBtnCloseApp}
58 97
         />
59 98
 
60
-        <PopinFixedOption customClass={`${appData.customClass}`} />
99
+        <PopinFixedOption customClass={`${appConfig.customClass}`} />
61 100
 
62
-        <PopinFixedContent customClass={`${appData.customClass}__contentpage`}>
101
+        <PopinFixedContent customClass={`${appConfig.customClass}__contentpage`}>
63 102
           <ThreadComponent
64
-            // version={file.version}
65
-            // text={file.text}
66
-            key={'PageHtml'}
67
-          />
68
-
69
-          <Timeline
70
-            customClass={`${appData.customClass}__contentpage`}
71
-            key={'pageHtml__timeline'}
103
+            title={content.title}
104
+            listMessage={listMessage}
105
+            loggedUser={loggedUser}
72 106
           />
73 107
         </PopinFixedContent>
74 108
       </PopinFixed>
@@ -76,4 +110,4 @@ class pageHtml extends React.Component {
76 110
   }
77 111
 }
78 112
 
79
-export default pageHtml
113
+export default Thread

+ 38 - 3
src/css/index.styl View File

@@ -2,6 +2,10 @@
2 2
 
3 3
 .wsContentThread
4 4
   width 550px
5
+  flex-grow 1
6
+  margin-bottom 0
7
+  border-bottom 1px solid grey
8
+  overflow-Y auto
5 9
   &__header
6 10
     color white
7 11
     background-color threadColor
@@ -14,9 +18,29 @@
14 18
     height calc(100% - 209px) /* height of chat__header + height of option + top of chat */
15 19
   &__messagelist
16 20
     padding 15px 35px
21
+    list-style none
17 22
     &__item
23
+      &__avatar
24
+        position relative
25
+        top 43px
26
+        left -25px
27
+        & > img
28
+          width 45px
29
+          height 45px
30
+          border-radius 30px
31
+      &__createhour
32
+        margin-left 30px
33
+        opacity 0.7
34
+        font-size 14px
18 35
       &__content
36
+        border 1px solid grey
37
+        border-radius 5px
38
+        padding 15px
39
+        background-color off-white
40
+        font-size 15px
41
+        z-index -1
19 42
         color darkBlue
43
+
20 44
   &__texteditor
21 45
     &__simpletext
22 46
       &__input
@@ -27,10 +51,21 @@
27 51
       &__btn
28 52
         color darkBlue
29 53
 
54
+.sended
55
+  .wsFileGeneric__messagelist__item__content
56
+    margin-right 25%
57
+
30 58
 .received
31
-  .wsContentThread__messagelist__item__content
32
-    background-color darkBlue
33
-    color white
59
+  .wsFileGeneric__messagelist__item
60
+    &__avatar
61
+      left 93%
62
+    &__createhour
63
+      text-align right
64
+      margin-right 50px
65
+    &__content
66
+      margin-left 25%
67
+      background-color darkBlue
68
+      color white
34 69
 
35 70
 .activeEditionTitle
36 71
   .wsFileThread

BIN
src/img/imgProfil.png View File


+ 87 - 0
src/listMessageDebugData.js View File

@@ -0,0 +1,87 @@
1
+export const listMessageDebugData = [{
2
+  id: 0,
3
+  author: {
4
+    id: 5,
5
+    username: 'Peter',
6
+    avatar: 'https://avatars3.githubusercontent.com/u/1104637?s=460&v=4'
7
+  },
8
+  text: 'Tu aurais envie de manger quoi exactement ?',
9
+  createdAt: {
10
+    day: '05/03/18',
11
+    hour: '10h00'
12
+  }
13
+}, {
14
+  id: 1,
15
+  author: {
16
+    id: 3,
17
+    username: 'Steven',
18
+    avatar: 'https://avatars3.githubusercontent.com/u/705214?s=460&v=4'
19
+  },
20
+  createdAt: {
21
+    day: '05/03/18',
22
+    hour: '09h59'
23
+  },
24
+  text: 'Ben je sais pas, par exemple une quiche lorraine.'
25
+}, {
26
+  id: 2,
27
+  author: {
28
+    id: 5,
29
+    username: 'Peter',
30
+    avatar: 'https://avatars3.githubusercontent.com/u/1104637?s=460&v=4'
31
+  },
32
+  text: 'Une ouiche.',
33
+  createdAt: {
34
+    day: '05/03/18',
35
+    hour: '09h59'
36
+  }
37
+}, {
38
+  id: 3,
39
+  author: {
40
+    id: 3,
41
+    username: 'Steven',
42
+    avatar: 'https://avatars3.githubusercontent.com/u/705214?s=460&v=4'
43
+  },
44
+  createdAt: {
45
+    day: '05/03/18',
46
+    hour: '09h59'
47
+  },
48
+  text: 'Quoi ?'
49
+}, {
50
+  id: 4,
51
+  author: {
52
+    id: 5,
53
+    username: 'Peter',
54
+    avatar: 'https://avatars3.githubusercontent.com/u/1104637?s=460&v=4'
55
+  },
56
+  text: 'On dit « une ouiche lorraine ».',
57
+  createdAt: {
58
+    day: '05/03/18',
59
+    hour: '09h59'
60
+  }
61
+}, {
62
+  id: 5,
63
+  author: {
64
+    id: 3,
65
+    username: 'Steven',
66
+    avatar: 'https://avatars3.githubusercontent.com/u/705214?s=460&v=4'
67
+  },
68
+  createdAt: {
69
+    day: '05/03/18',
70
+    hour: '09h58'
71
+  },
72
+  text: 'Tu es sûr ?'
73
+}, {
74
+  id: 6,
75
+  author: {
76
+    id: 3,
77
+    username: 'Steven',
78
+    avatar: 'https://avatars3.githubusercontent.com/u/705214?s=460&v=4'
79
+  },
80
+  text: 'Ça fait bizarre, « ouiche lorraine ».',
81
+  createdAt: {
82
+    day: '05/03/18',
83
+    hour: '09h59'
84
+  }
85
+}]
86
+
87
+export default listMessageDebugData

+ 3 - 1
webpack.config.js View File

@@ -5,7 +5,9 @@ const isProduction = process.env.NODE_ENV === 'production'
5 5
 console.log('isProduction : ', isProduction)
6 6
 
7 7
 module.exports = {
8
-  entry: isProduction ? './src/index.js' : './src/index.dev.js',
8
+  entry: isProduction
9
+    ? './src/index.js' // only one instance of babel-polyfill is allowed
10
+    : ['babel-polyfill', './src/index.dev.js'],
9 11
   output: {
10 12
     path: path.resolve(__dirname, 'dist'),
11 13
     filename: isProduction ? 'thread.app.js' : 'thread.app.dev.js',