瀏覽代碼

ref(invite): use AtlasKit for invite modal buttons and inputs (#1868)

* ref(invite): use AtlasKit for invite modal buttons and inputs

- Convert button to AK Button.
- Convert inputs to AK FieldText.

* remove noop, replace with custom empty func
master
virtuacoplenny 8 年之前
父節點
當前提交
1b7973a28e

+ 17
- 1
css/modals/invite/_invite.scss 查看文件

@@ -32,7 +32,7 @@
32 32
 
33 33
             .dial-in-numbers-trigger-icon {
34 34
                 position: absolute;
35
-                right: 0;
35
+                right: 10px;
36 36
                 top: 4px;
37 37
             }
38 38
         }
@@ -47,6 +47,22 @@
47 47
 
48 48
     .form-control {
49 49
         padding: 0;
50
+
51
+        &__container {
52
+            /**
53
+             * Ensure contents display in a line and vertically centered.
54
+             */
55
+            align-items: center;
56
+
57
+            button {
58
+                font-size: $modalButtonFontSize;
59
+            }
60
+        }
61
+
62
+        &__input-container {
63
+            flex: 1;
64
+            margin-right: 10px;
65
+        }
50 66
     }
51 67
 
52 68
     .inviteLink {

+ 15
- 2
react/features/dial-out/components/DialOutNumbersForm.web.js 查看文件

@@ -1,7 +1,6 @@
1 1
 import { StatelessDropdownMenu } from '@atlaskit/dropdown-menu';
2 2
 import AKFieldText, { FieldText } from '@atlaskit/field-text';
3 3
 import ExpandIcon from '@atlaskit/icon/glyph/expand';
4
-import { noop as _onNoop } from 'lodash';
5 4
 import React, { Component } from 'react';
6 5
 import { connect } from 'react-redux';
7 6
 
@@ -96,6 +95,8 @@ class DialOutNumbersForm extends Component {
96 95
         this._dialInputElem = null;
97 96
 
98 97
         // Bind event handlers so they are only bound once for every instance.
98
+        this._onDropdownTriggerInputChange
99
+            = this._onDropdownTriggerInputChange.bind(this);
99 100
         this._onInputChange = this._onInputChange.bind(this);
100 101
         this._onOpenChange = this._onOpenChange.bind(this);
101 102
         this._onSelect = this._onSelect.bind(this);
@@ -209,7 +210,7 @@ class DialOutNumbersForm extends Component {
209 210
                     isLabelHidden = { true }
210 211
                     isReadOnly = { true }
211 212
                     label = 'dial-out-code'
212
-                    onChange = { _onNoop }
213
+                    onChange = { this._onDropdownTriggerInputChange }
213 214
                     type = 'text'
214 215
                     value = { dialCode || '' } />
215 216
                 <span className = 'dropdown-trigger-icon'>
@@ -256,6 +257,18 @@ class DialOutNumbersForm extends Component {
256 257
         this.props.onChange(dialCode, this.state.dialInput);
257 258
     }
258 259
 
260
+    /**
261
+     * This is a no-op function used to stub out FieldText's onChange in order
262
+     * to prevent FieldText from printing prop type validation errors. FieldText
263
+     * is used as a trigger for the dropdown in {@code DialOutNumbersForm} to
264
+     * get the desired AtlasKit input look for the UI.
265
+     *
266
+     * @returns {void}
267
+     */
268
+    _onDropdownTriggerInputChange() {
269
+        // Intentionally left empty.
270
+    }
271
+
259 272
     /**
260 273
      * Updates the dialInput state when the input changes.
261 274
      *

+ 65
- 12
react/features/invite/components/AddPasswordForm.js 查看文件

@@ -1,3 +1,5 @@
1
+import Button from '@atlaskit/button';
2
+import { FieldText } from '@atlaskit/field-text';
1 3
 import React, { Component } from 'react';
2 4
 import { connect } from 'react-redux';
3 5
 
@@ -52,10 +54,40 @@ class AddPasswordForm extends Component {
52 54
             password: ''
53 55
         };
54 56
 
57
+        /**
58
+         * The internal reference to the React {@code component} for entering a
59
+         * password.
60
+         *
61
+         * @private
62
+         * @type {ReactComponent}
63
+         */
64
+        this._inputComponent = null;
65
+
55 66
         // Bind event handlers so they are only bound once for every instance.
56 67
         this._onKeyDown = this._onKeyDown.bind(this);
57 68
         this._onPasswordChange = this._onPasswordChange.bind(this);
58 69
         this._onSubmit = this._onSubmit.bind(this);
70
+        this._setInput = this._setInput.bind(this);
71
+    }
72
+
73
+    /**
74
+     * Directly bind a handler to the input element. This is done in order to
75
+     * intercept enter presses so any outer forms do not become submitted.
76
+     * Atlaskit Button does not expose a way to hook onto keydown events.
77
+     *
78
+     * @inheritdoc
79
+     */
80
+    componentDidMount() {
81
+        this._inputComponent.input.onkeydown = this._onKeyDown;
82
+    }
83
+
84
+    /**
85
+     * Remove any handlers set directly on DOM elements.
86
+     *
87
+     * @inheritdoc
88
+     */
89
+    componentWillUnmount() {
90
+        this._inputComponent.input.onkeydown = null;
59 91
     }
60 92
 
61 93
     /**
@@ -72,22 +104,28 @@ class AddPasswordForm extends Component {
72 104
                 className = 'form-control'
73 105
                 onSubmit = { this._onSubmit } >
74 106
                 <div className = 'form-control__container'>
75
-                    <input
76
-                        autoFocus = { true }
77
-                        className = 'input-control'
78
-                        id = 'newPasswordInput'
79
-                        onChange = { this._onPasswordChange }
80
-                        onKeyDown = { this._onKeyDown }
81
-                        placeholder = { t('dialog.createPassword') }
82
-                        type = 'text' />
83
-                    <button
84
-                        className = 'button-control button-control_light'
85
-                        disabled = { !this.state.password }
107
+                    <div className = 'form-control__input-container'>
108
+                        <FieldText
109
+                            autoFocus = { true }
110
+                            compact = { true }
111
+                            id = 'newPasswordInput'
112
+                            isLabelHidden = { true }
113
+                            label = 'Enter Password'
114
+                            onChange = { this._onPasswordChange }
115
+                            onKeyDown = { this._onKeyDown }
116
+                            placeholder = { t('dialog.createPassword') }
117
+                            ref = { this._setInput }
118
+                            shouldFitContainer = { true }
119
+                            type = 'text' />
120
+                    </div>
121
+                    <Button
86 122
                         id = 'addPasswordBtn'
123
+                        isDisabled = { !this.state.password }
87 124
                         onClick = { this._onSubmit }
125
+                        shouldFitContainer = { true }
88 126
                         type = 'button'>
89 127
                         { t('dialog.add') }
90
-                    </button>
128
+                    </Button>
91 129
                 </div>
92 130
             </div>
93 131
         );
@@ -141,6 +179,21 @@ class AddPasswordForm extends Component {
141 179
 
142 180
         this.setState({ password: '' });
143 181
     }
182
+
183
+    /**
184
+     * Sets the instance variable for the React Component used for entering a
185
+     * password.
186
+     *
187
+     * @param {Object} inputComponent - The React Component for the input
188
+     * field.
189
+     * @private
190
+     * @returns {void}
191
+     */
192
+    _setInput(inputComponent) {
193
+        if (inputComponent !== this._inputComponent) {
194
+            this._inputComponent = inputComponent;
195
+        }
196
+    }
144 197
 }
145 198
 
146 199
 export default translate(connect()(AddPasswordForm));

+ 33
- 9
react/features/invite/components/DialInNumbersForm.js 查看文件

@@ -1,4 +1,6 @@
1
+import Button from '@atlaskit/button';
1 2
 import { StatelessDropdownMenu } from '@atlaskit/dropdown-menu';
3
+import { FieldText } from '@atlaskit/field-text';
2 4
 import ExpandIcon from '@atlaskit/icon/glyph/expand';
3 5
 import React, { Component } from 'react';
4 6
 import { connect } from 'react-redux';
@@ -92,6 +94,8 @@ class DialInNumbersForm extends Component {
92 94
 
93 95
         // Bind event handlers so they are only bound once for every instance.
94 96
         this._onCopyClick = this._onCopyClick.bind(this);
97
+        this._onDropdownTriggerInputChange
98
+            = this._onDropdownTriggerInputChange.bind(this);
95 99
         this._onOpenChange = this._onOpenChange.bind(this);
96 100
         this._onSelect = this._onSelect.bind(this);
97 101
         this._setCopyElement = this._setCopyElement.bind(this);
@@ -154,12 +158,13 @@ class DialInNumbersForm extends Component {
154 158
                 </label>
155 159
                 <div className = 'form-control__container'>
156 160
                     { this._createDropdownMenu(items, selectedNumber.content) }
157
-                    <button
158
-                        className = 'button-control button-control_light'
161
+                    <Button
162
+                        appearance = 'default'
159 163
                         onClick = { this._onCopyClick }
164
+                        shouldFitContainer = { true }
160 165
                         type = 'button'>
161
-                        Copy
162
-                    </button>
166
+                        { t('dialog.copy') }
167
+                    </Button>
163 168
                 </div>
164 169
                 <textarea
165 170
                     className = 'dial-in-numbers-copy'
@@ -204,11 +209,18 @@ class DialInNumbersForm extends Component {
204 209
     _createDropdownTrigger(triggerText) {
205 210
         return (
206 211
             <div className = 'dial-in-numbers-trigger'>
207
-                <input
208
-                    className = 'input-control'
209
-                    readOnly = { true }
210
-                    type = 'text'
211
-                    value = { triggerText || '' } />
212
+                <div className = 'form-control__input-container'>
213
+                    <FieldText
214
+                        compact = { true }
215
+                        isLabelHidden = { true }
216
+                        isReadOnly = { true }
217
+                        label = 'Select Dial-In Number'
218
+                        onChange = { this._onDropdownTriggerInputChange }
219
+                        ref = { this._setInput }
220
+                        shouldFitContainer = { true }
221
+                        type = 'text'
222
+                        value = { triggerText || '' } />
223
+                </div>
212 224
                 <span className = 'dial-in-numbers-trigger-icon'>
213 225
                     <ExpandIcon
214 226
                         label = 'expand'
@@ -330,6 +342,18 @@ class DialInNumbersForm extends Component {
330 342
         }
331 343
     }
332 344
 
345
+    /**
346
+     * This is a no-op function used to stub out FieldText's onChange in order
347
+     * to prevent FieldText from printing prop type validation errors. FieldText
348
+     * is used as a trigger for the dropdown in {@code DialInNumbersForm} to
349
+     * get the desired AtlasKit input look for the UI.
350
+     *
351
+     * @returns {void}
352
+     */
353
+    _onDropdownTriggerInputChange() {
354
+        // Intentionally left empty.
355
+    }
356
+
333 357
     /**
334 358
      * Sets the internal state to either open or close the dropdown. If the
335 359
      * dropdown is disabled, the state will always be set to false.

+ 47
- 26
react/features/invite/components/ShareLinkForm.js 查看文件

@@ -1,3 +1,5 @@
1
+import Button from '@atlaskit/button';
2
+import { FieldText } from '@atlaskit/field-text';
1 3
 import React, { Component } from 'react';
2 4
 
3 5
 import { translate } from '../../base/i18n';
@@ -36,17 +38,18 @@ class ShareLinkForm extends Component {
36 38
         super(props);
37 39
 
38 40
         /**
39
-         * The internal reference to the DOM/HTML element backing the React
40
-         * {@code Component} input with id {@code inviteLinkRef}. It is
41
-         * necessary for the implementation of copying to the clipboard.
41
+         * The internal reference to the React {@code component} for display
42
+         * the meeting link in an input element.
42 43
          *
43 44
          * @private
44
-         * @type {HTMLInputElement}
45
+         * @type {ReactComponent}
45 46
          */
46
-        this._inputElement = null;
47
+        this._inputComponent = null;
47 48
 
48 49
         // Bind event handlers so they are only bound once for every instance.
49 50
         this._onClick = this._onClick.bind(this);
51
+        this._onDropdownTriggerInputChange
52
+            = this._onDropdownTriggerInputChange.bind(this);
50 53
         this._setInput = this._setInput.bind(this);
51 54
     }
52 55
 
@@ -60,28 +63,32 @@ class ShareLinkForm extends Component {
60 63
         const { t } = this.props;
61 64
         const inputValue = this.props.toCopy || t('inviteUrlDefaultMsg');
62 65
 
63
-        // FIXME An input HTML element is used here instead of atlaskit's
64
-        // field-text because the latter does not currently support readOnly.
65 66
         return (
66 67
             <div className = 'form-control'>
67 68
                 <label className = 'form-control__label'>
68 69
                     { t('dialog.shareLink') }
69 70
                 </label>
70 71
                 <div className = 'form-control__container'>
71
-                    <input
72
-                        className = 'input-control inviteLink'
73
-                        id = 'inviteLinkRef'
74
-                        readOnly = { true }
75
-                        ref = { this._setInput }
76
-                        type = 'text'
77
-                        value = { inputValue } />
78
-                    <button
79
-                        className =
80
-                            'button-control button-control_light copyInviteLink'
72
+                    <div className = 'form-control__input-container'>
73
+                        <FieldText
74
+                            compact = { true }
75
+                            id = 'inviteLinkRef'
76
+                            isLabelHidden = { true }
77
+                            isReadOnly = { true }
78
+                            label = 'invite link'
79
+                            onChange = { this._onDropdownTriggerInputChange }
80
+                            ref = { this._setInput }
81
+                            shouldFitContainer = { true }
82
+                            type = 'text'
83
+                            value = { inputValue } />
84
+                    </div>
85
+                    <Button
86
+                        appearance = 'default'
81 87
                         onClick = { this._onClick }
88
+                        shouldFitContainer = { true }
82 89
                         type = 'button'>
83 90
                         { t('dialog.copy') }
84
-                    </button>
91
+                    </Button>
85 92
                 </div>
86 93
             </div>
87 94
         );
@@ -95,25 +102,39 @@ class ShareLinkForm extends Component {
95 102
      */
96 103
     _onClick() {
97 104
         try {
98
-            this._inputElement.select();
105
+            const { input } = this._inputComponent;
106
+
107
+            input.select();
99 108
             document.execCommand('copy');
100
-            this._inputElement.blur();
109
+            input.blur();
101 110
         } catch (err) {
102 111
             logger.error('error when copying the text', err);
103 112
         }
104 113
     }
105 114
 
106 115
     /**
107
-     * Sets the internal reference to the DOM/HTML element backing the React
108
-     * {@code Component} input with id {@code inviteLinkRef}.
116
+     * This is a no-op function used to stub out FieldText's onChange in order
117
+     * to prevent FieldText from printing prop type validation errors. FieldText
118
+     * is used as a trigger for the dropdown in {@code ShareLinkForm} to get the
119
+     * desired AtlasKit input look for the UI.
120
+     *
121
+     * @returns {void}
122
+     */
123
+    _onDropdownTriggerInputChange() {
124
+        // Intentionally left empty.
125
+    }
126
+
127
+    /**
128
+     * Sets the internal reference to the React Component wrapping the input
129
+     * with id {@code inviteLinkRef}.
109 130
      *
110
-     * @param {HTMLInputElement} element - The DOM/HTML element for this
111
-     * {@code Component}'s input.
131
+     * @param {ReactComponent} inputComponent - React Component for displaying
132
+     * an input for displaying the meeting link.
112 133
      * @private
113 134
      * @returns {void}
114 135
      */
115
-    _setInput(element) {
116
-        this._inputElement = element;
136
+    _setInput(inputComponent) {
137
+        this._inputComponent = inputComponent;
117 138
     }
118 139
 }
119 140
 

Loading…
取消
儲存