-
-
Notifications
You must be signed in to change notification settings - Fork 829
/
ComposerBody.js
110 lines (99 loc) · 3.11 KB
/
ComposerBody.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
import Component from '../../common/Component';
import LoadingIndicator from '../../common/components/LoadingIndicator';
import ConfirmDocumentUnload from '../../common/components/ConfirmDocumentUnload';
import TextEditor from '../../common/components/TextEditor';
import listItems from '../../common/helpers/listItems';
import ItemList from '../../common/utils/ItemList';
import classList from '../../common/utils/classList';
import Avatar from '../../common/components/Avatar';
/**
* The `ComposerBody` component handles the body, or the content, of the
* composer. Subclasses should implement the `onsubmit` method and override
* `headerTimes`.
*
* ### Attrs
*
* - `composer`
* - `originalContent`
* - `submitLabel`
* - `placeholder`
* - `user`
* - `confirmExit`
* - `disabled`
*
* @abstract
*/
export default class ComposerBody extends Component {
oninit(vnode) {
super.oninit(vnode);
this.composer = this.attrs.composer;
/**
* Whether or not the component is loading.
*
* @type {Boolean}
*/
this.loading = false;
// Let the composer state know to ask for confirmation under certain
// circumstances, if the body supports / requires it and has a corresponding
// confirmation question to ask.
if (this.attrs.confirmExit) {
this.composer.preventClosingWhen(() => this.hasChanges(), this.attrs.confirmExit);
}
this.composer.fields.content(this.attrs.originalContent || '');
}
view() {
return (
<ConfirmDocumentUnload when={this.hasChanges.bind(this)}>
<div className={classList('ComposerBody', this.attrs.className)}>
<Avatar user={this.attrs.user} className="ComposerBody-avatar" />
<div className="ComposerBody-content">
<ul className="ComposerBody-header">{listItems(this.headerItems().toArray())}</ul>
<div className="ComposerBody-editor">
<TextEditor
submitLabel={this.attrs.submitLabel}
placeholder={this.attrs.placeholder}
disabled={this.loading || this.attrs.disabled}
composer={this.composer}
preview={this.jumpToPreview?.bind(this)}
onchange={this.composer.fields.content}
onsubmit={this.onsubmit.bind(this)}
value={this.composer.fields.content()}
/>
</div>
</div>
<LoadingIndicator display="unset" containerClassName={classList('ComposerBody-loading', this.loading && 'active')} size="large" />
</div>
</ConfirmDocumentUnload>
);
}
/**
* Check if there is any unsaved data.
*
* @return {boolean}
*/
hasChanges() {
const content = this.composer.fields.content();
return content && content !== this.attrs.originalContent;
}
/**
* Build an item list for the composer's header.
*
* @return {ItemList<import('mithril').Children>}
*/
headerItems() {
return new ItemList();
}
/**
* Handle the submit event of the text editor.
*
* @abstract
*/
onsubmit() {}
/**
* Stop loading.
*/
loaded() {
this.loading = false;
m.redraw();
}
}