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:
virtuacoplenny 2017-08-15 12:30:57 -07:00 committed by yanas
parent 830ec3d097
commit 1b7973a28e
5 changed files with 177 additions and 50 deletions

View File

@ -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 {

View File

@ -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.
*

View File

@ -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));

View File

@ -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.

View File

@ -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;
}
}