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
This commit is contained in:
parent
830ec3d097
commit
1b7973a28e
|
@ -32,7 +32,7 @@
|
|||
|
||||
.dial-in-numbers-trigger-icon {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
right: 10px;
|
||||
top: 4px;
|
||||
}
|
||||
}
|
||||
|
@ -47,6 +47,22 @@
|
|||
|
||||
.form-control {
|
||||
padding: 0;
|
||||
|
||||
&__container {
|
||||
/**
|
||||
* Ensure contents display in a line and vertically centered.
|
||||
*/
|
||||
align-items: center;
|
||||
|
||||
button {
|
||||
font-size: $modalButtonFontSize;
|
||||
}
|
||||
}
|
||||
|
||||
&__input-container {
|
||||
flex: 1;
|
||||
margin-right: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.inviteLink {
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import { StatelessDropdownMenu } from '@atlaskit/dropdown-menu';
|
||||
import AKFieldText, { FieldText } from '@atlaskit/field-text';
|
||||
import ExpandIcon from '@atlaskit/icon/glyph/expand';
|
||||
import { noop as _onNoop } from 'lodash';
|
||||
import React, { Component } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
|
@ -96,6 +95,8 @@ class DialOutNumbersForm extends Component {
|
|||
this._dialInputElem = null;
|
||||
|
||||
// Bind event handlers so they are only bound once for every instance.
|
||||
this._onDropdownTriggerInputChange
|
||||
= this._onDropdownTriggerInputChange.bind(this);
|
||||
this._onInputChange = this._onInputChange.bind(this);
|
||||
this._onOpenChange = this._onOpenChange.bind(this);
|
||||
this._onSelect = this._onSelect.bind(this);
|
||||
|
@ -209,7 +210,7 @@ class DialOutNumbersForm extends Component {
|
|||
isLabelHidden = { true }
|
||||
isReadOnly = { true }
|
||||
label = 'dial-out-code'
|
||||
onChange = { _onNoop }
|
||||
onChange = { this._onDropdownTriggerInputChange }
|
||||
type = 'text'
|
||||
value = { dialCode || '' } />
|
||||
<span className = 'dropdown-trigger-icon'>
|
||||
|
@ -256,6 +257,18 @@ class DialOutNumbersForm extends Component {
|
|||
this.props.onChange(dialCode, this.state.dialInput);
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a no-op function used to stub out FieldText's onChange in order
|
||||
* to prevent FieldText from printing prop type validation errors. FieldText
|
||||
* is used as a trigger for the dropdown in {@code DialOutNumbersForm} to
|
||||
* get the desired AtlasKit input look for the UI.
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
_onDropdownTriggerInputChange() {
|
||||
// Intentionally left empty.
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the dialInput state when the input changes.
|
||||
*
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
import Button from '@atlaskit/button';
|
||||
import { FieldText } from '@atlaskit/field-text';
|
||||
import React, { Component } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
|
@ -52,10 +54,40 @@ class AddPasswordForm extends Component {
|
|||
password: ''
|
||||
};
|
||||
|
||||
/**
|
||||
* The internal reference to the React {@code component} for entering a
|
||||
* password.
|
||||
*
|
||||
* @private
|
||||
* @type {ReactComponent}
|
||||
*/
|
||||
this._inputComponent = null;
|
||||
|
||||
// Bind event handlers so they are only bound once for every instance.
|
||||
this._onKeyDown = this._onKeyDown.bind(this);
|
||||
this._onPasswordChange = this._onPasswordChange.bind(this);
|
||||
this._onSubmit = this._onSubmit.bind(this);
|
||||
this._setInput = this._setInput.bind(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Directly bind a handler to the input element. This is done in order to
|
||||
* intercept enter presses so any outer forms do not become submitted.
|
||||
* Atlaskit Button does not expose a way to hook onto keydown events.
|
||||
*
|
||||
* @inheritdoc
|
||||
*/
|
||||
componentDidMount() {
|
||||
this._inputComponent.input.onkeydown = this._onKeyDown;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove any handlers set directly on DOM elements.
|
||||
*
|
||||
* @inheritdoc
|
||||
*/
|
||||
componentWillUnmount() {
|
||||
this._inputComponent.input.onkeydown = null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -72,22 +104,28 @@ class AddPasswordForm extends Component {
|
|||
className = 'form-control'
|
||||
onSubmit = { this._onSubmit } >
|
||||
<div className = 'form-control__container'>
|
||||
<input
|
||||
autoFocus = { true }
|
||||
className = 'input-control'
|
||||
id = 'newPasswordInput'
|
||||
onChange = { this._onPasswordChange }
|
||||
onKeyDown = { this._onKeyDown }
|
||||
placeholder = { t('dialog.createPassword') }
|
||||
type = 'text' />
|
||||
<button
|
||||
className = 'button-control button-control_light'
|
||||
disabled = { !this.state.password }
|
||||
<div className = 'form-control__input-container'>
|
||||
<FieldText
|
||||
autoFocus = { true }
|
||||
compact = { true }
|
||||
id = 'newPasswordInput'
|
||||
isLabelHidden = { true }
|
||||
label = 'Enter Password'
|
||||
onChange = { this._onPasswordChange }
|
||||
onKeyDown = { this._onKeyDown }
|
||||
placeholder = { t('dialog.createPassword') }
|
||||
ref = { this._setInput }
|
||||
shouldFitContainer = { true }
|
||||
type = 'text' />
|
||||
</div>
|
||||
<Button
|
||||
id = 'addPasswordBtn'
|
||||
isDisabled = { !this.state.password }
|
||||
onClick = { this._onSubmit }
|
||||
shouldFitContainer = { true }
|
||||
type = 'button'>
|
||||
{ t('dialog.add') }
|
||||
</button>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
@ -141,6 +179,21 @@ class AddPasswordForm extends Component {
|
|||
|
||||
this.setState({ password: '' });
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the instance variable for the React Component used for entering a
|
||||
* password.
|
||||
*
|
||||
* @param {Object} inputComponent - The React Component for the input
|
||||
* field.
|
||||
* @private
|
||||
* @returns {void}
|
||||
*/
|
||||
_setInput(inputComponent) {
|
||||
if (inputComponent !== this._inputComponent) {
|
||||
this._inputComponent = inputComponent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default translate(connect()(AddPasswordForm));
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
import Button from '@atlaskit/button';
|
||||
import { StatelessDropdownMenu } from '@atlaskit/dropdown-menu';
|
||||
import { FieldText } from '@atlaskit/field-text';
|
||||
import ExpandIcon from '@atlaskit/icon/glyph/expand';
|
||||
import React, { Component } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
|
@ -92,6 +94,8 @@ class DialInNumbersForm extends Component {
|
|||
|
||||
// Bind event handlers so they are only bound once for every instance.
|
||||
this._onCopyClick = this._onCopyClick.bind(this);
|
||||
this._onDropdownTriggerInputChange
|
||||
= this._onDropdownTriggerInputChange.bind(this);
|
||||
this._onOpenChange = this._onOpenChange.bind(this);
|
||||
this._onSelect = this._onSelect.bind(this);
|
||||
this._setCopyElement = this._setCopyElement.bind(this);
|
||||
|
@ -154,12 +158,13 @@ class DialInNumbersForm extends Component {
|
|||
</label>
|
||||
<div className = 'form-control__container'>
|
||||
{ this._createDropdownMenu(items, selectedNumber.content) }
|
||||
<button
|
||||
className = 'button-control button-control_light'
|
||||
<Button
|
||||
appearance = 'default'
|
||||
onClick = { this._onCopyClick }
|
||||
shouldFitContainer = { true }
|
||||
type = 'button'>
|
||||
Copy
|
||||
</button>
|
||||
{ t('dialog.copy') }
|
||||
</Button>
|
||||
</div>
|
||||
<textarea
|
||||
className = 'dial-in-numbers-copy'
|
||||
|
@ -204,11 +209,18 @@ class DialInNumbersForm extends Component {
|
|||
_createDropdownTrigger(triggerText) {
|
||||
return (
|
||||
<div className = 'dial-in-numbers-trigger'>
|
||||
<input
|
||||
className = 'input-control'
|
||||
readOnly = { true }
|
||||
type = 'text'
|
||||
value = { triggerText || '' } />
|
||||
<div className = 'form-control__input-container'>
|
||||
<FieldText
|
||||
compact = { true }
|
||||
isLabelHidden = { true }
|
||||
isReadOnly = { true }
|
||||
label = 'Select Dial-In Number'
|
||||
onChange = { this._onDropdownTriggerInputChange }
|
||||
ref = { this._setInput }
|
||||
shouldFitContainer = { true }
|
||||
type = 'text'
|
||||
value = { triggerText || '' } />
|
||||
</div>
|
||||
<span className = 'dial-in-numbers-trigger-icon'>
|
||||
<ExpandIcon
|
||||
label = 'expand'
|
||||
|
@ -330,6 +342,18 @@ class DialInNumbersForm extends Component {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a no-op function used to stub out FieldText's onChange in order
|
||||
* to prevent FieldText from printing prop type validation errors. FieldText
|
||||
* is used as a trigger for the dropdown in {@code DialInNumbersForm} to
|
||||
* get the desired AtlasKit input look for the UI.
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
_onDropdownTriggerInputChange() {
|
||||
// Intentionally left empty.
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the internal state to either open or close the dropdown. If the
|
||||
* dropdown is disabled, the state will always be set to false.
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
import Button from '@atlaskit/button';
|
||||
import { FieldText } from '@atlaskit/field-text';
|
||||
import React, { Component } from 'react';
|
||||
|
||||
import { translate } from '../../base/i18n';
|
||||
|
@ -36,17 +38,18 @@ class ShareLinkForm extends Component {
|
|||
super(props);
|
||||
|
||||
/**
|
||||
* The internal reference to the DOM/HTML element backing the React
|
||||
* {@code Component} input with id {@code inviteLinkRef}. It is
|
||||
* necessary for the implementation of copying to the clipboard.
|
||||
* The internal reference to the React {@code component} for display
|
||||
* the meeting link in an input element.
|
||||
*
|
||||
* @private
|
||||
* @type {HTMLInputElement}
|
||||
* @type {ReactComponent}
|
||||
*/
|
||||
this._inputElement = null;
|
||||
this._inputComponent = null;
|
||||
|
||||
// Bind event handlers so they are only bound once for every instance.
|
||||
this._onClick = this._onClick.bind(this);
|
||||
this._onDropdownTriggerInputChange
|
||||
= this._onDropdownTriggerInputChange.bind(this);
|
||||
this._setInput = this._setInput.bind(this);
|
||||
}
|
||||
|
||||
|
@ -60,28 +63,32 @@ class ShareLinkForm extends Component {
|
|||
const { t } = this.props;
|
||||
const inputValue = this.props.toCopy || t('inviteUrlDefaultMsg');
|
||||
|
||||
// FIXME An input HTML element is used here instead of atlaskit's
|
||||
// field-text because the latter does not currently support readOnly.
|
||||
return (
|
||||
<div className = 'form-control'>
|
||||
<label className = 'form-control__label'>
|
||||
{ t('dialog.shareLink') }
|
||||
</label>
|
||||
<div className = 'form-control__container'>
|
||||
<input
|
||||
className = 'input-control inviteLink'
|
||||
id = 'inviteLinkRef'
|
||||
readOnly = { true }
|
||||
ref = { this._setInput }
|
||||
type = 'text'
|
||||
value = { inputValue } />
|
||||
<button
|
||||
className =
|
||||
'button-control button-control_light copyInviteLink'
|
||||
<div className = 'form-control__input-container'>
|
||||
<FieldText
|
||||
compact = { true }
|
||||
id = 'inviteLinkRef'
|
||||
isLabelHidden = { true }
|
||||
isReadOnly = { true }
|
||||
label = 'invite link'
|
||||
onChange = { this._onDropdownTriggerInputChange }
|
||||
ref = { this._setInput }
|
||||
shouldFitContainer = { true }
|
||||
type = 'text'
|
||||
value = { inputValue } />
|
||||
</div>
|
||||
<Button
|
||||
appearance = 'default'
|
||||
onClick = { this._onClick }
|
||||
shouldFitContainer = { true }
|
||||
type = 'button'>
|
||||
{ t('dialog.copy') }
|
||||
</button>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
@ -95,25 +102,39 @@ class ShareLinkForm extends Component {
|
|||
*/
|
||||
_onClick() {
|
||||
try {
|
||||
this._inputElement.select();
|
||||
const { input } = this._inputComponent;
|
||||
|
||||
input.select();
|
||||
document.execCommand('copy');
|
||||
this._inputElement.blur();
|
||||
input.blur();
|
||||
} catch (err) {
|
||||
logger.error('error when copying the text', err);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the internal reference to the DOM/HTML element backing the React
|
||||
* {@code Component} input with id {@code inviteLinkRef}.
|
||||
* This is a no-op function used to stub out FieldText's onChange in order
|
||||
* to prevent FieldText from printing prop type validation errors. FieldText
|
||||
* is used as a trigger for the dropdown in {@code ShareLinkForm} to get the
|
||||
* desired AtlasKit input look for the UI.
|
||||
*
|
||||
* @param {HTMLInputElement} element - The DOM/HTML element for this
|
||||
* {@code Component}'s input.
|
||||
* @returns {void}
|
||||
*/
|
||||
_onDropdownTriggerInputChange() {
|
||||
// Intentionally left empty.
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the internal reference to the React Component wrapping the input
|
||||
* with id {@code inviteLinkRef}.
|
||||
*
|
||||
* @param {ReactComponent} inputComponent - React Component for displaying
|
||||
* an input for displaying the meeting link.
|
||||
* @private
|
||||
* @returns {void}
|
||||
*/
|
||||
_setInput(element) {
|
||||
this._inputElement = element;
|
||||
_setInput(inputComponent) {
|
||||
this._inputComponent = inputComponent;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue