|
|
@@ -1,5 +1,8 @@
|
|
1
|
|
-/* global APP, interfaceConfig */
|
|
|
1
|
+/* global interfaceConfig */
|
|
2
|
2
|
|
|
|
3
|
+import Button from '@atlaskit/button';
|
|
|
4
|
+import { FieldTextStateless } from '@atlaskit/field-text';
|
|
|
5
|
+import { AtlasKitThemeProvider } from '@atlaskit/theme';
|
|
3
|
6
|
import React from 'react';
|
|
4
|
7
|
import { connect } from 'react-redux';
|
|
5
|
8
|
|
|
|
@@ -26,15 +29,33 @@ class WelcomePage extends AbstractWelcomePage {
|
|
26
|
29
|
this.state = {
|
|
27
|
30
|
...this.state,
|
|
28
|
31
|
|
|
29
|
|
- enableWelcomePage: true,
|
|
30
|
32
|
generateRoomnames:
|
|
31
|
33
|
interfaceConfig.GENERATE_ROOMNAMES_ON_WELCOME_PAGE
|
|
32
|
34
|
};
|
|
33
|
35
|
|
|
|
36
|
+ /**
|
|
|
37
|
+ * The HTML Element used as the container for additional content. Used
|
|
|
38
|
+ * for directly appending the additional content template to the dom
|
|
|
39
|
+ *
|
|
|
40
|
+ * @private
|
|
|
41
|
+ * @type {HTMLTemplateElement|null}
|
|
|
42
|
+ */
|
|
|
43
|
+ this._additionalContentRef = null;
|
|
|
44
|
+
|
|
|
45
|
+ /**
|
|
|
46
|
+ * The template to use as the main content for the welcome page. If
|
|
|
47
|
+ * not found then only the welcome page head will display.
|
|
|
48
|
+ *
|
|
|
49
|
+ * @private
|
|
|
50
|
+ * @type {HTMLTemplateElement|null}
|
|
|
51
|
+ */
|
|
|
52
|
+ this._additionalContentTemplate = document.getElementById(
|
|
|
53
|
+ 'welcome-page-additional-content-template');
|
|
|
54
|
+
|
|
34
|
55
|
// Bind event handlers so they are only bound once per instance.
|
|
35
|
|
- this._onDisableWelcomeChange = this._onDisableWelcomeChange.bind(this);
|
|
36
|
|
- this._onKeyDown = this._onKeyDown.bind(this);
|
|
37
|
56
|
this._onRoomChange = this._onRoomChange.bind(this);
|
|
|
57
|
+ this._setAdditionalContentRef
|
|
|
58
|
+ = this._setAdditionalContentRef.bind(this);
|
|
38
|
59
|
}
|
|
39
|
60
|
|
|
40
|
61
|
/**
|
|
|
@@ -48,6 +69,11 @@ class WelcomePage extends AbstractWelcomePage {
|
|
48
|
69
|
if (this.state.generateRoomnames) {
|
|
49
|
70
|
this._updateRoomname();
|
|
50
|
71
|
}
|
|
|
72
|
+
|
|
|
73
|
+ if (this._shouldShowAdditionalContent()) {
|
|
|
74
|
+ this._additionalContentRef.appendChild(
|
|
|
75
|
+ this._additionalContentTemplate.content.cloneNode(true));
|
|
|
76
|
+ }
|
|
51
|
77
|
}
|
|
52
|
78
|
|
|
53
|
79
|
/**
|
|
|
@@ -57,63 +83,63 @@ class WelcomePage extends AbstractWelcomePage {
|
|
57
|
83
|
* @returns {ReactElement|null}
|
|
58
|
84
|
*/
|
|
59
|
85
|
render() {
|
|
|
86
|
+ const { t } = this.props;
|
|
|
87
|
+ const { APP_NAME } = interfaceConfig;
|
|
|
88
|
+ const showAdditionalContent = this._shouldShowAdditionalContent();
|
|
|
89
|
+
|
|
60
|
90
|
return (
|
|
61
|
|
- <div id = 'welcome_page'>
|
|
62
|
|
- {
|
|
63
|
|
- this._renderHeader()
|
|
64
|
|
- }
|
|
65
|
|
- {
|
|
66
|
|
- this._renderMain()
|
|
67
|
|
- }
|
|
68
|
|
- </div>
|
|
|
91
|
+ <AtlasKitThemeProvider mode = 'light'>
|
|
|
92
|
+ <div
|
|
|
93
|
+ className = { `welcome ${showAdditionalContent
|
|
|
94
|
+ ? 'with-content' : 'without-content'}` }
|
|
|
95
|
+ id = 'new_welcome_page'>
|
|
|
96
|
+ <div className = 'header'>
|
|
|
97
|
+ <div className = 'header-image' />
|
|
|
98
|
+ <Watermarks />
|
|
|
99
|
+ <div className = 'header-text'>
|
|
|
100
|
+ <h1 className = 'header-text-title'>
|
|
|
101
|
+ { t('welcomepage.title') }
|
|
|
102
|
+ </h1>
|
|
|
103
|
+ <p className = 'header-text-description'>
|
|
|
104
|
+ { t('welcomepage.appDescription',
|
|
|
105
|
+ { app: APP_NAME }) }
|
|
|
106
|
+ </p>
|
|
|
107
|
+ </div>
|
|
|
108
|
+ <div id = 'new_enter_room'>
|
|
|
109
|
+ <form
|
|
|
110
|
+ className = 'enter-room-input'
|
|
|
111
|
+ onSubmit = { this._onJoin }>
|
|
|
112
|
+ <FieldTextStateless
|
|
|
113
|
+ autoFocus = { true }
|
|
|
114
|
+ id = 'enter_room_field'
|
|
|
115
|
+ isLabelHidden = { true }
|
|
|
116
|
+ label = 'enter_room_field'
|
|
|
117
|
+ onChange = { this._onRoomChange }
|
|
|
118
|
+ placeholder = { this.state.roomPlaceholder }
|
|
|
119
|
+ shouldFitContainer = { true }
|
|
|
120
|
+ type = 'text'
|
|
|
121
|
+ value = { this.state.room } />
|
|
|
122
|
+ </form>
|
|
|
123
|
+ <Button
|
|
|
124
|
+ appearance = 'primary'
|
|
|
125
|
+ className = 'welcome-page-button'
|
|
|
126
|
+ id = 'enter_room_button'
|
|
|
127
|
+ onClick = { this._onJoin }
|
|
|
128
|
+ type = 'button'>
|
|
|
129
|
+ { t('welcomepage.go') }
|
|
|
130
|
+ </Button>
|
|
|
131
|
+ </div>
|
|
|
132
|
+ </div>
|
|
|
133
|
+ { showAdditionalContent
|
|
|
134
|
+ ? <div
|
|
|
135
|
+ className = 'welcome-page-content'
|
|
|
136
|
+ ref = { this._setAdditionalContentRef } />
|
|
|
137
|
+ : null }
|
|
|
138
|
+ </div>
|
|
|
139
|
+ </AtlasKitThemeProvider>
|
|
69
|
140
|
);
|
|
70
|
141
|
}
|
|
71
|
142
|
|
|
72
|
|
- /**
|
|
73
|
|
- * Returns the URL of this WelcomePage for display purposes. For
|
|
74
|
|
- * historic/legacy reasons, the return value is referred to as domain.
|
|
75
|
|
- *
|
|
76
|
|
- * @private
|
|
77
|
|
- * @returns {string} The URL of this WelcomePage for display purposes.
|
|
78
|
|
- */
|
|
79
|
|
- _getDomain() {
|
|
80
|
|
- // As the returned URL is for display purposes, do not return the
|
|
81
|
|
- // userinfo, query and fragment URI parts.
|
|
82
|
|
- const wl = window.location;
|
|
83
|
|
-
|
|
84
|
|
- return `${wl.protocol}//${wl.host}${wl.pathname}`;
|
|
85
|
|
- }
|
|
86
|
|
-
|
|
87
|
|
- /**
|
|
88
|
|
- * Handles {@code change} event of the checkbox which allows specifying
|
|
89
|
|
- * whether the WelcomePage is disabled.
|
|
90
|
|
- *
|
|
91
|
|
- * @param {Event} event - The (HTML) Event which details the change such as
|
|
92
|
|
- * the EventTarget.
|
|
93
|
|
- * @returns {void}
|
|
94
|
|
- */
|
|
95
|
|
- _onDisableWelcomeChange(event) {
|
|
96
|
|
- this.setState({
|
|
97
|
|
- enableWelcomePage: !event.target.checked
|
|
98
|
|
- }, () => {
|
|
99
|
|
- APP.settings.setWelcomePageEnabled(this.state.enableWelcomePage);
|
|
100
|
|
- });
|
|
101
|
|
- }
|
|
102
|
|
-
|
|
103
|
|
- /**
|
|
104
|
|
- * Handles 'keydown' event to initiate joining the room when the
|
|
105
|
|
- * 'Enter/Return' button is pressed.
|
|
106
|
|
- *
|
|
107
|
|
- * @param {Event} event - Key down event object.
|
|
108
|
|
- * @private
|
|
109
|
|
- * @returns {void}
|
|
110
|
|
- */
|
|
111
|
|
- _onKeyDown(event) {
|
|
112
|
|
- if (event.keyCode === /* Enter */ 13) {
|
|
113
|
|
- this._onJoin();
|
|
114
|
|
- }
|
|
115
|
|
- }
|
|
116
|
|
-
|
|
117
|
143
|
/**
|
|
118
|
144
|
* Overrides the super to account for the differences in the argument types
|
|
119
|
145
|
* provided by HTML and React Native text inputs.
|
|
|
@@ -129,141 +155,30 @@ class WelcomePage extends AbstractWelcomePage {
|
|
129
|
155
|
}
|
|
130
|
156
|
|
|
131
|
157
|
/**
|
|
132
|
|
- * Renders a feature with a specific index.
|
|
133
|
|
- *
|
|
134
|
|
- * @param {number} index - The index of the feature to render.
|
|
135
|
|
- * @private
|
|
136
|
|
- * @returns {ReactElement}
|
|
137
|
|
- */
|
|
138
|
|
- _renderFeature(index) {
|
|
139
|
|
- const { t } = this.props;
|
|
140
|
|
- const tns = `welcomepage.feature${index}`;
|
|
141
|
|
-
|
|
142
|
|
- return (
|
|
143
|
|
- <div
|
|
144
|
|
- className = 'feature_holder'
|
|
145
|
|
- key = { index } >
|
|
146
|
|
- <div className = 'feature_icon'>
|
|
147
|
|
- { t(`${tns}.title`) }
|
|
148
|
|
- </div>
|
|
149
|
|
- <div className = 'feature_description'>
|
|
150
|
|
- { t(`${tns}.content`, { postProcess: 'resolveAppName' }) }
|
|
151
|
|
- </div>
|
|
152
|
|
- </div>
|
|
153
|
|
- );
|
|
154
|
|
- }
|
|
155
|
|
-
|
|
156
|
|
- /**
|
|
157
|
|
- * Renders a row of features.
|
|
158
|
|
- *
|
|
159
|
|
- * @param {number} beginIndex - The inclusive feature index to begin the row
|
|
160
|
|
- * with.
|
|
161
|
|
- * @param {number} endIndex - The exclusive feature index to end the row
|
|
162
|
|
- * with.
|
|
163
|
|
- * @private
|
|
164
|
|
- * @returns {ReactElement}
|
|
165
|
|
- */
|
|
166
|
|
- _renderFeatureRow(beginIndex, endIndex) {
|
|
167
|
|
- const features = [];
|
|
168
|
|
-
|
|
169
|
|
- for (let index = beginIndex; index < endIndex; ++index) {
|
|
170
|
|
- features.push(this._renderFeature(index));
|
|
171
|
|
- }
|
|
172
|
|
-
|
|
173
|
|
- return (
|
|
174
|
|
- <div className = 'feature_row'>
|
|
175
|
|
- {
|
|
176
|
|
- features
|
|
177
|
|
- }
|
|
178
|
|
- </div>
|
|
179
|
|
- );
|
|
180
|
|
- }
|
|
181
|
|
-
|
|
182
|
|
- /**
|
|
183
|
|
- * Renders the header part of this WelcomePage.
|
|
|
158
|
+ * Sets the internal reference to the HTMLDivElement used to hold the
|
|
|
159
|
+ * welcome page content.
|
|
184
|
160
|
*
|
|
|
161
|
+ * @param {HTMLDivElement} el - The HTMLElement for the div that is the root
|
|
|
162
|
+ * of the welcome page content.
|
|
185
|
163
|
* @private
|
|
186
|
|
- * @returns {ReactElement|null}
|
|
|
164
|
+ * @returns {void}
|
|
187
|
165
|
*/
|
|
188
|
|
- _renderHeader() {
|
|
189
|
|
- const { t } = this.props;
|
|
190
|
|
-
|
|
191
|
|
- return (
|
|
192
|
|
- <div id = 'welcome_page_header'>
|
|
193
|
|
- <Watermarks />
|
|
194
|
|
-
|
|
195
|
|
- <div id = 'enter_room_container'>
|
|
196
|
|
- <div id = 'enter_room_form'>
|
|
197
|
|
- <div className = 'domain-name'>
|
|
198
|
|
- {
|
|
199
|
|
- this._getDomain()
|
|
200
|
|
- }
|
|
201
|
|
- </div>
|
|
202
|
|
- <div id = 'enter_room'>
|
|
203
|
|
- <input
|
|
204
|
|
- autoFocus = { true }
|
|
205
|
|
- className = 'enter-room__field'
|
|
206
|
|
- data-room-name
|
|
207
|
|
- = { this.state.generatedRoomname }
|
|
208
|
|
- id = 'enter_room_field'
|
|
209
|
|
- onChange = { this._onRoomChange }
|
|
210
|
|
- onKeyDown = { this._onKeyDown }
|
|
211
|
|
- placeholder = { this.state.roomPlaceholder }
|
|
212
|
|
- type = 'text'
|
|
213
|
|
- value = { this.state.room } />
|
|
214
|
|
-
|
|
215
|
|
- { /* eslint-disable react/jsx-handler-names */ }
|
|
216
|
|
- <div
|
|
217
|
|
- className = 'icon-reload enter-room__reload'
|
|
218
|
|
- onClick = { this._updateRoomname } />
|
|
219
|
|
- { /* eslint-enable react/jsx-handler-names */ }
|
|
220
|
|
-
|
|
221
|
|
- <button
|
|
222
|
|
- className = 'enter-room__button'
|
|
223
|
|
- id = 'enter_room_button'
|
|
224
|
|
- onClick = { this._onJoin }
|
|
225
|
|
- type = 'button'>
|
|
226
|
|
- { t('welcomepage.go') }
|
|
227
|
|
- </button>
|
|
228
|
|
- </div>
|
|
229
|
|
- </div>
|
|
230
|
|
- </div>
|
|
231
|
|
- <div id = 'brand_header' />
|
|
232
|
|
- <input
|
|
233
|
|
- checked = { !this.state.enableWelcomePage }
|
|
234
|
|
- id = 'disable_welcome'
|
|
235
|
|
- name = 'checkbox'
|
|
236
|
|
- onChange = { this._onDisableWelcomeChange }
|
|
237
|
|
- type = 'checkbox' />
|
|
238
|
|
- <label
|
|
239
|
|
- className = 'disable_welcome_position'
|
|
240
|
|
- htmlFor = 'disable_welcome'>
|
|
241
|
|
- { t('welcomepage.disable') }
|
|
242
|
|
- </label>
|
|
243
|
|
- <div id = 'header_text' />
|
|
244
|
|
- </div>
|
|
245
|
|
- );
|
|
|
166
|
+ _setAdditionalContentRef(el) {
|
|
|
167
|
+ this._additionalContentRef = el;
|
|
246
|
168
|
}
|
|
247
|
169
|
|
|
248
|
170
|
/**
|
|
249
|
|
- * Renders the main part of this WelcomePage.
|
|
|
171
|
+ * Returns whether or not additional content should be displayed belowed
|
|
|
172
|
+ * the welcome page's header for entering a room name.
|
|
250
|
173
|
*
|
|
251
|
174
|
* @private
|
|
252
|
|
- * @returns {ReactElement|null}
|
|
|
175
|
+ * @returns {boolean}
|
|
253
|
176
|
*/
|
|
254
|
|
- _renderMain() {
|
|
255
|
|
- return (
|
|
256
|
|
- <div id = 'welcome_page_main'>
|
|
257
|
|
- <div id = 'features'>
|
|
258
|
|
- {
|
|
259
|
|
- this._renderFeatureRow(1, 5)
|
|
260
|
|
- }
|
|
261
|
|
- {
|
|
262
|
|
- this._renderFeatureRow(5, 9)
|
|
263
|
|
- }
|
|
264
|
|
- </div>
|
|
265
|
|
- </div>
|
|
266
|
|
- );
|
|
|
177
|
+ _shouldShowAdditionalContent() {
|
|
|
178
|
+ return interfaceConfig.DISPLAY_WELCOME_PAGE_CONTENT
|
|
|
179
|
+ && this._additionalContentTemplate
|
|
|
180
|
+ && this._additionalContentTemplate.content
|
|
|
181
|
+ && this._additionalContentTemplate.innerHTML.trim();
|
|
267
|
182
|
}
|
|
268
|
183
|
}
|
|
269
|
184
|
|