|
@@ -1,116 +1,102 @@
|
1
|
1
|
import React from 'react'
|
2
|
2
|
import PropTypes from 'prop-types'
|
3
|
3
|
import classnames from 'classnames'
|
|
4
|
+import Comment from './Comment.jsx'
|
|
5
|
+import Revision from './Revision.jsx'
|
4
|
6
|
|
5
|
7
|
require('./Timeline.styl')
|
6
|
8
|
|
7
|
|
-const Comment = props => (
|
8
|
|
- <li
|
9
|
|
- className={classnames(
|
10
|
|
- `${props.customClass}__messagelist__item`,
|
11
|
|
- 'timeline__messagelist__item', {
|
12
|
|
- 'sended': props.fromMe,
|
13
|
|
- 'received': !props.fromMe
|
14
|
|
- }
|
15
|
|
- )}
|
16
|
|
- >
|
17
|
|
- <div className={classnames(`${props.customClass}__messagelist__item__avatar`, 'timeline__messagelist__item__avatar')}>
|
18
|
|
- {props.avatar ? <img src={props.avatar} /> : ''}
|
19
|
|
- </div>
|
20
|
|
- <div
|
21
|
|
- className={classnames(`${props.customClass}__messagelist__item__createhour`, 'timeline__messagelist__item__createhour')}>
|
22
|
|
- {props.createdAt}
|
23
|
|
- </div>
|
24
|
|
- <div
|
25
|
|
- className={classnames(`${props.customClass}__messagelist__item__content`, 'timeline__messagelist__item__content')}>
|
26
|
|
- {props.text}
|
27
|
|
- </div>
|
28
|
|
- </li>
|
29
|
|
-)
|
30
|
|
-
|
31
|
|
-const Revision = props => (
|
32
|
|
- <li className={classnames(`${props.customClass}__messagelist__version`, 'timeline__messagelist__version')} >
|
33
|
|
- <div className={classnames(`${props.customClass}__messagelist__version__btn`, 'timeline__messagelist__version__btn btn')}>
|
34
|
|
- <i className='fa fa-code-fork' />
|
35
|
|
- version {props.number}
|
36
|
|
- </div>
|
37
|
|
- <div className={classnames(`${props.customClass}__messagelist__version__date`, 'timeline__messagelist__version__date')}>
|
38
|
|
- Créer le {props.createdAt}
|
39
|
|
- </div>
|
40
|
|
- </li>
|
41
|
|
-)
|
42
|
|
-
|
43
|
|
-const Timeline = props => {
|
44
|
|
- if (!Array.isArray(props.timelineData)) {
|
45
|
|
- console.log('Error in Timeline.jsx, props.timelineData is not an array. timelineData: ', props.timelineData)
|
46
|
|
- return null
|
|
9
|
+class Timeline extends React.Component {
|
|
10
|
+ componentDidMount () {
|
|
11
|
+ this.scrollToBottom()
|
47
|
12
|
}
|
48
|
13
|
|
49
|
|
- return (
|
50
|
|
- <div className='timeline'>
|
51
|
|
- <div className={classnames(`${props.customClass}__header`, 'timeline__header')}>
|
52
|
|
- Timeline
|
53
|
|
- </div>
|
|
14
|
+ componentDidUpdate () {
|
|
15
|
+ this.scrollToBottom()
|
|
16
|
+ }
|
54
|
17
|
|
55
|
|
- <ul className={classnames(`${props.customClass}__messagelist`, 'timeline__messagelist')}>
|
56
|
|
- { props.timelineData.map(content => {
|
57
|
|
- switch (content.timelineType) {
|
58
|
|
- case 'comment':
|
59
|
|
- return <Comment
|
60
|
|
- customClass={props.customClass}
|
61
|
|
- avatar={content.author.avatar_url}
|
62
|
|
- createdAt={content.created}
|
63
|
|
- text={content.raw_content}
|
64
|
|
- fromMe={props.loggedUser.user_id === content.author.user_id}
|
65
|
|
- key={`comment_${content.content_id}`}
|
66
|
|
- />
|
|
18
|
+ scrollToBottom = () => this.timelineBottom.scrollIntoView({behavior: 'instant'})
|
67
|
19
|
|
68
|
|
- case 'revision':
|
69
|
|
- return <Revision
|
70
|
|
- customClass={props.customClass}
|
71
|
|
- createdAt={content.created}
|
72
|
|
- number={props.timelineData.filter(c => c.timelineType === 'revision' && c.revision_id <= content.revision_id).length}
|
73
|
|
- key={`revision_${content.revision_id}`}
|
74
|
|
- />
|
75
|
|
- }
|
76
|
|
- })}
|
77
|
|
- </ul>
|
|
20
|
+ render () {
|
|
21
|
+ const { props } = this
|
78
|
22
|
|
79
|
|
- <form className={classnames(`${props.customClass}__texteditor`, 'timeline__texteditor d-flex align-items-center justify-content-between flex-wrap')}>
|
|
23
|
+ if (!Array.isArray(props.timelineData)) {
|
|
24
|
+ console.log('Error in Timeline.jsx, props.timelineData is not an array. timelineData: ', props.timelineData)
|
|
25
|
+ return null
|
|
26
|
+ }
|
80
|
27
|
|
81
|
|
- <div className={classnames(`${props.customClass}__texteditor__textinput`, 'timeline__texteditor__textinput')}>
|
82
|
|
- <textarea
|
83
|
|
- placeholder='Taper votre message ici'
|
84
|
|
- value={props.newComment}
|
85
|
|
- onChange={props.onChangeNewComment}
|
86
|
|
- />
|
|
28
|
+ return (
|
|
29
|
+ <div className='timeline'>
|
|
30
|
+ <div className={classnames(`${props.customClass}__header`, 'timeline__header')}>
|
|
31
|
+ Timeline
|
87
|
32
|
</div>
|
88
|
33
|
|
89
|
|
- <div className={classnames(`${props.customClass}__texteditor__wrapper`, 'timeline__texteditor__wrapper')}>
|
90
|
|
-
|
91
|
|
- <div className={classnames(`${props.customClass}__texteditor__advancedtext`, 'timeline__texteditor__advancedtext')}>
|
92
|
|
- <button type='button' className={classnames(`${props.customClass}__texteditor__advancedtext__btn`, 'timeline__texteditor__advancedtext__btn btn btn-outline-primary')}>
|
93
|
|
- Texte Avancé
|
94
|
|
- </button>
|
|
34
|
+ <ul className={classnames(`${props.customClass}__messagelist`, 'timeline__messagelist')}>
|
|
35
|
+ {props.timelineData.map(content => {
|
|
36
|
+ switch (content.timelineType) {
|
|
37
|
+ case 'comment':
|
|
38
|
+ return <Comment
|
|
39
|
+ customClass={props.customClass}
|
|
40
|
+ avatar={content.author.avatar_url}
|
|
41
|
+ createdAt={content.created}
|
|
42
|
+ text={content.raw_content}
|
|
43
|
+ fromMe={props.loggedUser.user_id === content.author.user_id}
|
|
44
|
+ key={`comment_${content.content_id}`}
|
|
45
|
+ />
|
|
46
|
+
|
|
47
|
+ case 'revision':
|
|
48
|
+ return <Revision
|
|
49
|
+ customClass={props.customClass}
|
|
50
|
+ createdAt={content.created}
|
|
51
|
+ number={props.timelineData.filter(c => c.timelineType === 'revision' && c.revision_id <= content.revision_id).length}
|
|
52
|
+ key={`revision_${content.revision_id}`}
|
|
53
|
+ />
|
|
54
|
+ }
|
|
55
|
+ })}
|
|
56
|
+ <li style={{visibility: 'hidden'}} ref={el => { this.timelineBottom = el }} />
|
|
57
|
+ </ul>
|
|
58
|
+
|
|
59
|
+ <form className={classnames(`${props.customClass}__texteditor`, 'timeline__texteditor d-flex align-items-center justify-content-between flex-wrap')}>
|
|
60
|
+ <div className={classnames(`${props.customClass}__texteditor__textinput`, 'timeline__texteditor__textinput')}>
|
|
61
|
+ <textarea
|
|
62
|
+ id='wysiwygTimelineComment'
|
|
63
|
+ placeholder='Taper votre message ici'
|
|
64
|
+ value={props.newComment}
|
|
65
|
+ onChange={props.onChangeNewComment}
|
|
66
|
+ />
|
95
|
67
|
</div>
|
96
|
68
|
|
97
|
|
- <div className={classnames(`${props.customClass}__texteditor__submit`, 'timeline__texteditor__submit mb-2')}>
|
98
|
|
- <button
|
99
|
|
- type='button'
|
100
|
|
- className={classnames(`${props.customClass}__texteditor__submit__btn`, 'timeline__texteditor__submit__btn btn')}
|
101
|
|
- onClick={props.onClickValidateNewCommentBtn}
|
102
|
|
- >
|
103
|
|
- Envoyer
|
104
|
|
- <div className={classnames(`${props.customClass}__texteditor__submit__btn__icon`, 'timeline__texteditor__submit__btn__icon')}>
|
105
|
|
- <i className='fa fa-paper-plane-o' />
|
106
|
|
- </div>
|
107
|
|
- </button>
|
|
69
|
+ <div className={classnames(`${props.customClass}__texteditor__wrapper`, 'timeline__texteditor__wrapper')}>
|
|
70
|
+ <div className={classnames(`${props.customClass}__texteditor__advancedtext`, 'timeline__texteditor__advancedtext')}>
|
|
71
|
+ <button
|
|
72
|
+ type='button'
|
|
73
|
+ className={classnames(
|
|
74
|
+ `${props.customClass}__texteditor__advancedtext__btn timeline__texteditor__advancedtext__btn btn btn-outline-primary`
|
|
75
|
+ )}
|
|
76
|
+ onClick={props.onClickWysiwygBtn}
|
|
77
|
+ >
|
|
78
|
+ {props.wysiwyg ? 'Text Simple' : 'Texte Avancé'}
|
|
79
|
+ </button>
|
|
80
|
+ </div>
|
|
81
|
+
|
|
82
|
+ <div className={classnames(`${props.customClass}__texteditor__submit`, 'timeline__texteditor__submit mb-2')}>
|
|
83
|
+ <button
|
|
84
|
+ type='button'
|
|
85
|
+ className={classnames(`${props.customClass}__texteditor__submit__btn`, 'timeline__texteditor__submit__btn btn')}
|
|
86
|
+ onClick={props.onClickValidateNewCommentBtn}
|
|
87
|
+ >
|
|
88
|
+ Envoyer
|
|
89
|
+ <div
|
|
90
|
+ className={classnames(`${props.customClass}__texteditor__submit__btn__icon`, 'timeline__texteditor__submit__btn__icon')}>
|
|
91
|
+ <i className='fa fa-paper-plane-o' />
|
|
92
|
+ </div>
|
|
93
|
+ </button>
|
|
94
|
+ </div>
|
108
|
95
|
</div>
|
109
|
|
-
|
110
|
|
- </div>
|
111
|
|
- </form>
|
112
|
|
- </div>
|
113
|
|
- )
|
|
96
|
+ </form>
|
|
97
|
+ </div>
|
|
98
|
+ )
|
|
99
|
+ }
|
114
|
100
|
}
|
115
|
101
|
|
116
|
102
|
export default Timeline
|
|
@@ -121,7 +107,9 @@ Timeline.propTypes = {
|
121
|
107
|
onChangeNewComment: PropTypes.func.isRequired,
|
122
|
108
|
onClickValidateNewCommentBtn: PropTypes.func.isRequired,
|
123
|
109
|
customClass: PropTypes.string,
|
124
|
|
- loggedUser: PropTypes.object
|
|
110
|
+ loggedUser: PropTypes.object,
|
|
111
|
+ wysiwyg: PropTypes.bool,
|
|
112
|
+ onClickWysiwygBtn: PropTypes.func
|
125
|
113
|
}
|
126
|
114
|
|
127
|
115
|
Timeline.defaultProps = {
|
|
@@ -131,5 +119,7 @@ Timeline.defaultProps = {
|
131
|
119
|
name: '',
|
132
|
120
|
avatar: ''
|
133
|
121
|
},
|
134
|
|
- timelineData: []
|
|
122
|
+ timelineData: [],
|
|
123
|
+ wysiwyg: false,
|
|
124
|
+ onClickWysiwygBtn: () => {}
|
135
|
125
|
}
|