Kaynağa Gözat

make thread dynamic

Skylsmoi 6 yıl önce
ebeveyn
işleme
09dadc1feb

+ 2 - 2
dist/index.html Dosyayı Görüntüle

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

+ 36 - 177
src/component/Thread.jsx Dosyayı Görüntüle

1
 import React from 'react'
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
   return (
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
             </div>
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
             </div>
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
             </div>
23
             </div>
53
           </li>
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
           </div>
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
     </div>
50
     </div>
192
   )
51
   )
193
 }
52
 }
194
 
53
 
195
-export default PageHtml
54
+export default Thread

+ 70 - 36
src/container/Thread.jsx Dosyayı Görüntüle

1
 import React from 'react'
1
 import React from 'react'
2
 import ThreadComponent from '../component/Thread.jsx'
2
 import ThreadComponent from '../component/Thread.jsx'
3
 import {
3
 import {
4
+  handleFetchResult,
4
   PopinFixed,
5
   PopinFixed,
5
   PopinFixedHeader,
6
   PopinFixedHeader,
6
   PopinFixedOption,
7
   PopinFixedOption,
7
-  PopinFixedContent,
8
-  Timeline
8
+  PopinFixedContent
9
 } from 'tracim_lib'
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
   constructor (props) {
42
   constructor (props) {
13
     super(props)
43
     super(props)
14
     this.state = {
44
     this.state = {
15
       appName: 'Thread',
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
   customEventReducer = ({detail}) => {
73
   customEventReducer = ({detail}) => {
42
   }
79
   }
43
 
80
 
44
   handleClickBtnCloseApp = () => {
81
   handleClickBtnCloseApp = () => {
45
-    GLOBAL_unmountApp(this.state.appName)
82
+    this.setState({ isVisible: false })
46
   }
83
   }
47
 
84
 
48
   render () {
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
     return (
90
     return (
52
-      <PopinFixed customClass={`${appData.customClass}`}>
91
+      <PopinFixed customClass={`${appConfig.customClass}`}>
53
         <PopinFixedHeader
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
           onClickCloseBtn={this.handleClickBtnCloseApp}
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
           <ThreadComponent
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
         </PopinFixedContent>
107
         </PopinFixedContent>
74
       </PopinFixed>
108
       </PopinFixed>
76
   }
110
   }
77
 }
111
 }
78
 
112
 
79
-export default pageHtml
113
+export default Thread

+ 38 - 3
src/css/index.styl Dosyayı Görüntüle

2
 
2
 
3
 .wsContentThread
3
 .wsContentThread
4
   width 550px
4
   width 550px
5
+  flex-grow 1
6
+  margin-bottom 0
7
+  border-bottom 1px solid grey
8
+  overflow-Y auto
5
   &__header
9
   &__header
6
     color white
10
     color white
7
     background-color threadColor
11
     background-color threadColor
14
     height calc(100% - 209px) /* height of chat__header + height of option + top of chat */
18
     height calc(100% - 209px) /* height of chat__header + height of option + top of chat */
15
   &__messagelist
19
   &__messagelist
16
     padding 15px 35px
20
     padding 15px 35px
21
+    list-style none
17
     &__item
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
       &__content
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
         color darkBlue
42
         color darkBlue
43
+
20
   &__texteditor
44
   &__texteditor
21
     &__simpletext
45
     &__simpletext
22
       &__input
46
       &__input
27
       &__btn
51
       &__btn
28
         color darkBlue
52
         color darkBlue
29
 
53
 
54
+.sended
55
+  .wsFileGeneric__messagelist__item__content
56
+    margin-right 25%
57
+
30
 .received
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
 .activeEditionTitle
70
 .activeEditionTitle
36
   .wsFileThread
71
   .wsFileThread

BIN
src/img/imgProfil.png Dosyayı Görüntüle


+ 87 - 0
src/listMessageDebugData.js Dosyayı Görüntüle

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 Dosyayı Görüntüle

5
 console.log('isProduction : ', isProduction)
5
 console.log('isProduction : ', isProduction)
6
 
6
 
7
 module.exports = {
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
   output: {
11
   output: {
10
     path: path.resolve(__dirname, 'dist'),
12
     path: path.resolve(__dirname, 'dist'),
11
     filename: isProduction ? 'thread.app.js' : 'thread.app.dev.js',
13
     filename: isProduction ? 'thread.app.js' : 'thread.app.dev.js',