Adds support for 'radio' type in interactive dialogs (#3212)
This commit is contained in:
parent
e9db272a9e
commit
2bd67deeea
8 changed files with 507 additions and 18 deletions
|
|
@ -0,0 +1,189 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`components/widgets/settings/RadioSetting should match snapshot when error is present 1`] = `
|
||||
<View>
|
||||
<View
|
||||
style={
|
||||
Object {
|
||||
"flexDirection": "row",
|
||||
"marginBottom": 10,
|
||||
"marginTop": 15,
|
||||
}
|
||||
}
|
||||
>
|
||||
<Text
|
||||
style={
|
||||
Object {
|
||||
"color": "#3d3c40",
|
||||
"fontSize": 14,
|
||||
"marginLeft": 15,
|
||||
}
|
||||
}
|
||||
>
|
||||
some label
|
||||
</Text>
|
||||
<Text
|
||||
style={
|
||||
Object {
|
||||
"color": "#fd5960",
|
||||
"fontSize": 14,
|
||||
}
|
||||
}
|
||||
>
|
||||
*
|
||||
</Text>
|
||||
</View>
|
||||
<View
|
||||
style={
|
||||
Array [
|
||||
Object {
|
||||
"backgroundColor": "#ffffff",
|
||||
"borderBottomColor": "rgba(61,60,64,0.1)",
|
||||
"borderBottomWidth": 1,
|
||||
"borderTopColor": "rgba(61,60,64,0.1)",
|
||||
"borderTopWidth": 1,
|
||||
},
|
||||
null,
|
||||
]
|
||||
}
|
||||
>
|
||||
<TouchableOpacity
|
||||
activeOpacity={0.2}
|
||||
onPress={[Function]}
|
||||
>
|
||||
<View
|
||||
style={
|
||||
Array [
|
||||
Object {
|
||||
"alignItems": "center",
|
||||
"flexDirection": "row",
|
||||
"paddingHorizontal": 15,
|
||||
},
|
||||
null,
|
||||
]
|
||||
}
|
||||
>
|
||||
<View
|
||||
style={
|
||||
Object {
|
||||
"alignItems": "center",
|
||||
"flex": 1,
|
||||
"flexDirection": "row",
|
||||
"height": 45,
|
||||
}
|
||||
}
|
||||
>
|
||||
<Text>
|
||||
this is engineering
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
<View
|
||||
style={
|
||||
Object {
|
||||
"backgroundColor": "rgba(61,60,64,0.1)",
|
||||
"flex": 1,
|
||||
"height": 1,
|
||||
"marginLeft": 15,
|
||||
}
|
||||
}
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity
|
||||
activeOpacity={0.2}
|
||||
onPress={[Function]}
|
||||
>
|
||||
<View
|
||||
style={
|
||||
Array [
|
||||
Object {
|
||||
"alignItems": "center",
|
||||
"flexDirection": "row",
|
||||
"paddingHorizontal": 15,
|
||||
},
|
||||
null,
|
||||
]
|
||||
}
|
||||
>
|
||||
<View
|
||||
style={
|
||||
Object {
|
||||
"alignItems": "center",
|
||||
"flex": 1,
|
||||
"flexDirection": "row",
|
||||
"height": 45,
|
||||
}
|
||||
}
|
||||
>
|
||||
<Text>
|
||||
this is sales
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
<View
|
||||
style={
|
||||
Object {
|
||||
"backgroundColor": "rgba(61,60,64,0.1)",
|
||||
"flex": 1,
|
||||
"height": 1,
|
||||
"marginLeft": 15,
|
||||
}
|
||||
}
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity
|
||||
activeOpacity={0.2}
|
||||
onPress={[Function]}
|
||||
>
|
||||
<View
|
||||
style={
|
||||
Array [
|
||||
Object {
|
||||
"alignItems": "center",
|
||||
"flexDirection": "row",
|
||||
"paddingHorizontal": 15,
|
||||
},
|
||||
null,
|
||||
]
|
||||
}
|
||||
>
|
||||
<View
|
||||
style={
|
||||
Object {
|
||||
"alignItems": "center",
|
||||
"flex": 1,
|
||||
"flexDirection": "row",
|
||||
"height": 45,
|
||||
}
|
||||
}
|
||||
>
|
||||
<Text>
|
||||
this is administration
|
||||
</Text>
|
||||
</View>
|
||||
<CheckMark
|
||||
color="#2389d7"
|
||||
height={12}
|
||||
width={12}
|
||||
/>
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
<View
|
||||
style={null}
|
||||
>
|
||||
<Text
|
||||
style={
|
||||
Object {
|
||||
"color": "#fd5960",
|
||||
"fontSize": 12,
|
||||
"marginHorizontal": 15,
|
||||
"marginTop": 10,
|
||||
}
|
||||
}
|
||||
>
|
||||
some error message
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
`;
|
||||
191
app/components/widgets/settings/radio_setting.js
Normal file
191
app/components/widgets/settings/radio_setting.js
Normal file
|
|
@ -0,0 +1,191 @@
|
|||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import React, {PureComponent} from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import {Text, TouchableOpacity, View} from 'react-native';
|
||||
import CheckMark from 'app/components/checkmark';
|
||||
import {paddingHorizontal as padding} from 'app/components/safe_area_view/iphone_x_spacing';
|
||||
import {makeStyleSheetFromTheme, changeOpacity} from 'app/utils/theme';
|
||||
|
||||
export default class RadioSetting extends PureComponent {
|
||||
static propTypes = {
|
||||
id: PropTypes.string.isRequired,
|
||||
label: PropTypes.node.isRequired,
|
||||
options: PropTypes.array.isRequired,
|
||||
default: PropTypes.string,
|
||||
onChange: PropTypes.func.isRequired,
|
||||
theme: PropTypes.object.isRequired,
|
||||
isLandscape: PropTypes.bool.isRequired,
|
||||
helpText: PropTypes.node,
|
||||
errorText: PropTypes.node,
|
||||
};
|
||||
|
||||
static defaultProps = {
|
||||
isLandscape: false,
|
||||
};
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
value: typeof props.default === 'undefined' ? props.options[0] : props.default,
|
||||
};
|
||||
}
|
||||
|
||||
handleChange = (item) => {
|
||||
const {onChange, id} = this.props;
|
||||
onChange(id, item);
|
||||
this.setState({value: item});
|
||||
}
|
||||
|
||||
renderCheckMark = (value, {width, height, color}) => {
|
||||
if (value === this.state.value) {
|
||||
return (
|
||||
<CheckMark
|
||||
width={width}
|
||||
height={height}
|
||||
color={color}
|
||||
/>
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
renderRowSeparator = (idx, separatorStyle) => {
|
||||
const {options} = this.props;
|
||||
if (idx === options.length - 1) {
|
||||
return null;
|
||||
}
|
||||
return <View style={separatorStyle}/>;
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
theme,
|
||||
label,
|
||||
helpText,
|
||||
errorText,
|
||||
isLandscape,
|
||||
} = this.props;
|
||||
const style = getStyleSheet(theme);
|
||||
|
||||
let helpTextContent;
|
||||
if (helpText) {
|
||||
helpTextContent = (
|
||||
<Text style={style.helpText}>
|
||||
{helpText}
|
||||
</Text>
|
||||
);
|
||||
}
|
||||
let errorTextContent;
|
||||
if (errorText) {
|
||||
errorTextContent = (
|
||||
<Text style={style.errorText}>
|
||||
{errorText}
|
||||
</Text>
|
||||
);
|
||||
}
|
||||
|
||||
let additionalTextContent;
|
||||
if (errorText || helpText) {
|
||||
additionalTextContent = (
|
||||
<View style={padding(isLandscape)}>
|
||||
{helpTextContent}
|
||||
{errorTextContent}
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
const options = [];
|
||||
for (const [i, {value, text}] of this.props.options.entries()) {
|
||||
options.push(
|
||||
<TouchableOpacity
|
||||
onPress={() => this.handleChange(value)}
|
||||
key={value}
|
||||
>
|
||||
<View style={[style.container, padding(isLandscape)]}>
|
||||
<View style={style.rowContainer}>
|
||||
<Text>{text}</Text>
|
||||
</View>
|
||||
{this.renderCheckMark(value, style.checkMark)}
|
||||
</View>
|
||||
{this.renderRowSeparator(i, style.separator)}
|
||||
</TouchableOpacity>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<View>
|
||||
<View style={style.titleContainer}>
|
||||
<Text style={style.title}>{label}</Text>
|
||||
<Text style={style.asterisk}>{' *'}</Text>
|
||||
</View>
|
||||
|
||||
<View style={[style.items, padding(isLandscape)]}>
|
||||
{options}
|
||||
</View>
|
||||
{additionalTextContent}
|
||||
</View>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const getStyleSheet = makeStyleSheetFromTheme((theme) => {
|
||||
return {
|
||||
container: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
paddingHorizontal: 15,
|
||||
},
|
||||
rowContainer: {
|
||||
alignItems: 'center',
|
||||
flex: 1,
|
||||
flexDirection: 'row',
|
||||
height: 45,
|
||||
},
|
||||
items: {
|
||||
backgroundColor: theme.centerChannelBg,
|
||||
borderTopWidth: 1,
|
||||
borderBottomWidth: 1,
|
||||
borderTopColor: changeOpacity(theme.centerChannelColor, 0.1),
|
||||
borderBottomColor: changeOpacity(theme.centerChannelColor, 0.1),
|
||||
},
|
||||
helpText: {
|
||||
fontSize: 12,
|
||||
color: changeOpacity(theme.centerChannelColor, 0.5),
|
||||
marginHorizontal: 15,
|
||||
marginVertical: 10,
|
||||
},
|
||||
errorText: {
|
||||
fontSize: 12,
|
||||
color: theme.errorTextColor,
|
||||
marginHorizontal: 15,
|
||||
marginTop: 10,
|
||||
},
|
||||
asterisk: {
|
||||
color: theme.errorTextColor,
|
||||
fontSize: 14,
|
||||
},
|
||||
title: {
|
||||
fontSize: 14,
|
||||
color: theme.centerChannelColor,
|
||||
marginLeft: 15,
|
||||
},
|
||||
titleContainer: {
|
||||
flexDirection: 'row',
|
||||
marginTop: 15,
|
||||
marginBottom: 10,
|
||||
},
|
||||
separator: {
|
||||
backgroundColor: changeOpacity(theme.centerChannelColor, 0.1),
|
||||
flex: 1,
|
||||
height: 1,
|
||||
marginLeft: 15,
|
||||
},
|
||||
checkMark: {
|
||||
width: 12,
|
||||
height: 12,
|
||||
color: theme.linkColor,
|
||||
},
|
||||
};
|
||||
});
|
||||
69
app/components/widgets/settings/radio_setting.test.js
Normal file
69
app/components/widgets/settings/radio_setting.test.js
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
import React from 'react';
|
||||
import {shallow} from 'enzyme';
|
||||
|
||||
import Preferences from 'mattermost-redux/constants/preferences';
|
||||
import {TouchableOpacity} from 'react-native';
|
||||
import RadioSetting from './radio_setting.js';
|
||||
import CheckMark from 'app/components/checkmark';
|
||||
|
||||
describe('components/widgets/settings/RadioSetting', () => {
|
||||
const theme = Preferences.THEMES.default;
|
||||
const options = [
|
||||
{text: 'this is engineering', value: 'Engineering'},
|
||||
{text: 'this is sales', value: 'Sales'},
|
||||
{text: 'this is administration', value: 'Administration'},
|
||||
];
|
||||
|
||||
test('onChange', () => {
|
||||
const onChange = jest.fn();
|
||||
const wrapper = shallow(
|
||||
<RadioSetting
|
||||
id='string.id'
|
||||
label='some label'
|
||||
options={options}
|
||||
default={'Administration'}
|
||||
onChange={onChange}
|
||||
theme={theme}
|
||||
/>
|
||||
);
|
||||
wrapper.find(TouchableOpacity).at(1).props().onPress();
|
||||
|
||||
expect(onChange).toHaveBeenCalledTimes(1);
|
||||
expect(onChange).toHaveBeenCalledWith('string.id', 'Sales');
|
||||
});
|
||||
|
||||
test('should match snapshot when error is present', () => {
|
||||
const onChange = jest.fn();
|
||||
const wrapper = shallow(
|
||||
<RadioSetting
|
||||
id='string.id'
|
||||
label='some label'
|
||||
options={options}
|
||||
errorText={'some error message'}
|
||||
default={'Administration'}
|
||||
onChange={onChange}
|
||||
theme={theme}
|
||||
/>
|
||||
);
|
||||
|
||||
expect(wrapper.getElement()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('no option should be checked when the value is not in provided options', () => {
|
||||
const onChange = jest.fn();
|
||||
const wrapper = shallow(
|
||||
<RadioSetting
|
||||
id='string.id'
|
||||
label='some label'
|
||||
options={options}
|
||||
default={'invalid-option-value'}
|
||||
onChange={onChange}
|
||||
theme={theme}
|
||||
/>
|
||||
);
|
||||
|
||||
expect(wrapper.find(CheckMark)).toHaveLength(0);
|
||||
});
|
||||
});
|
||||
|
|
@ -39,7 +39,6 @@ export default class TextSetting extends PureComponent {
|
|||
onChange: PropTypes.func.isRequired,
|
||||
value: PropTypes.string.isRequired,
|
||||
multiline: PropTypes.bool,
|
||||
showRequiredAsterisk: PropTypes.bool,
|
||||
isLandscape: PropTypes.bool.isRequired,
|
||||
keyboardType: PropTypes.oneOf([
|
||||
'default',
|
||||
|
|
@ -57,7 +56,6 @@ export default class TextSetting extends PureComponent {
|
|||
optional: false,
|
||||
disabled: false,
|
||||
multiline: false,
|
||||
showRequiredAsterisk: false,
|
||||
keyboardType: 'default',
|
||||
isLandscape: false,
|
||||
secureTextEntry: false,
|
||||
|
|
@ -80,7 +78,6 @@ export default class TextSetting extends PureComponent {
|
|||
errorText,
|
||||
value,
|
||||
multiline,
|
||||
showRequiredAsterisk,
|
||||
isLandscape,
|
||||
secureTextEntry,
|
||||
} = this.props;
|
||||
|
|
@ -109,7 +106,7 @@ export default class TextSetting extends PureComponent {
|
|||
defaultMessage='(optional)'
|
||||
/>
|
||||
);
|
||||
} else if (showRequiredAsterisk) {
|
||||
} else {
|
||||
asterisk = <Text style={style.asterisk}>{' *'}</Text>;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import PropTypes from 'prop-types';
|
|||
import BoolSetting from 'app/components/widgets/settings/bool_setting';
|
||||
import TextSetting from 'app/components/widgets/settings/text_setting';
|
||||
import AutocompleteSelector from 'app/components/autocomplete_selector';
|
||||
import RadioSetting from 'app/components/widgets/settings/radio_setting';
|
||||
|
||||
const TEXT_DEFAULT_MAX_LENGTH = 150;
|
||||
const TEXTAREA_DEFAULT_MAX_LENGTH = 3000;
|
||||
|
|
@ -136,6 +137,19 @@ export default class DialogElement extends PureComponent {
|
|||
roundedBorders={false}
|
||||
/>
|
||||
);
|
||||
} else if (type === 'radio') {
|
||||
return (
|
||||
<RadioSetting
|
||||
id={name}
|
||||
label={displayName}
|
||||
helpText={helpText}
|
||||
errorText={errorText}
|
||||
options={options}
|
||||
theme={theme}
|
||||
default={value}
|
||||
onChange={this.onChange}
|
||||
/>
|
||||
);
|
||||
} else if (type === 'bool') {
|
||||
return (
|
||||
<BoolSetting
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import React from 'react';
|
|||
import {shallow} from 'enzyme';
|
||||
|
||||
import Preferences from 'mattermost-redux/constants/preferences';
|
||||
|
||||
import RadioSetting from 'app/components/widgets/settings/radio_setting';
|
||||
import DialogElement from './dialog_element.js';
|
||||
|
||||
describe('DialogElement', () => {
|
||||
|
|
@ -15,6 +15,7 @@ describe('DialogElement', () => {
|
|||
type: 'text',
|
||||
isLandscape: false,
|
||||
};
|
||||
|
||||
const theme = Preferences.THEMES.default;
|
||||
test('secureTextEntry is true and multiline is false when subtype is password', () => {
|
||||
const wrapper = shallow(
|
||||
|
|
@ -37,4 +38,24 @@ describe('DialogElement', () => {
|
|||
);
|
||||
expect(wrapper.find({secureTextEntry: false}).exists()).toBe(true);
|
||||
});
|
||||
|
||||
describe('radioSetting', () => {
|
||||
const radioOptions = [
|
||||
{value: 'foo', text: 'foo-text'},
|
||||
{value: 'bar', text: 'bar-text'},
|
||||
];
|
||||
|
||||
test('The default value can be specified from the list', () => {
|
||||
const wrapper = shallow(
|
||||
<DialogElement
|
||||
{...baseDialogProps}
|
||||
theme={theme}
|
||||
type='radio'
|
||||
options={radioOptions}
|
||||
value={radioOptions[1].value}
|
||||
/>
|
||||
);
|
||||
expect(wrapper.find(RadioSetting).find({options: radioOptions, default: radioOptions[1].value}).exists()).toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
32
package-lock.json
generated
32
package-lock.json
generated
|
|
@ -4490,7 +4490,7 @@
|
|||
},
|
||||
"ansi-escapes": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.1.0.tgz",
|
||||
"resolved": "http://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.1.0.tgz",
|
||||
"integrity": "sha512-UgAb8H9D41AQnu/PbWlCofQVcnV4Gs2bBJi9eZPxfU/hgglFh3SMDMENRIqdr7H6XFnXdoknctFByVsCOotTVw=="
|
||||
},
|
||||
"ansi-gray": {
|
||||
|
|
@ -7473,7 +7473,7 @@
|
|||
},
|
||||
"external-editor": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.2.0.tgz",
|
||||
"resolved": "http://registry.npmjs.org/external-editor/-/external-editor-2.2.0.tgz",
|
||||
"integrity": "sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A==",
|
||||
"requires": {
|
||||
"chardet": "^0.4.0",
|
||||
|
|
@ -7673,7 +7673,7 @@
|
|||
"dependencies": {
|
||||
"json5": {
|
||||
"version": "0.5.1",
|
||||
"resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz",
|
||||
"resolved": "http://registry.npmjs.org/json5/-/json5-0.5.1.tgz",
|
||||
"integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=",
|
||||
"dev": true
|
||||
}
|
||||
|
|
@ -14056,8 +14056,8 @@
|
|||
"integrity": "sha512-rUxjysqif/BZQH2yhd5Aaq7vXMSx9NdEsQcyA07uEzIvxgI7zIr33gGsh+RU0/XjmQpCW7RsVof1vlkvQVCK5A=="
|
||||
},
|
||||
"mattermost-redux": {
|
||||
"version": "github:mattermost/mattermost-redux#6ea71dc77808041d7e953ac15cbc12e1c483ac69",
|
||||
"from": "github:mattermost/mattermost-redux#6ea71dc77808041d7e953ac15cbc12e1c483ac69",
|
||||
"version": "github:mattermost/mattermost-redux#9800f16a94b46fd77e95132c1c33f18752bf8a98",
|
||||
"from": "github:mattermost/mattermost-redux#9800f16a94b46fd77e95132c1c33f18752bf8a98",
|
||||
"requires": {
|
||||
"deep-equal": "1.0.1",
|
||||
"eslint-plugin-header": "3.0.0",
|
||||
|
|
@ -14070,7 +14070,7 @@
|
|||
"redux": "4.0.4",
|
||||
"redux-action-buffer": "1.2.0",
|
||||
"redux-batched-actions": "0.4.1",
|
||||
"redux-offline": "git+https://github.com/enahum/redux-offline.git#4bd85e7e3b279a2b11fb4d587808d583d2b5e7b5",
|
||||
"redux-offline": "git+https://github.com/enahum/redux-offline.git#885024de96b6ec73650c340c8928066585c413df",
|
||||
"redux-persist": "4.9.1",
|
||||
"redux-thunk": "2.3.0",
|
||||
"reselect": "4.0.0",
|
||||
|
|
@ -17064,7 +17064,7 @@
|
|||
},
|
||||
"readable-stream": {
|
||||
"version": "2.3.6",
|
||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
|
||||
"resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
|
||||
"integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
|
||||
"requires": {
|
||||
"core-util-is": "~1.0.0",
|
||||
|
|
@ -17451,10 +17451,18 @@
|
|||
}
|
||||
},
|
||||
"redux-offline": {
|
||||
"version": "git+https://github.com/enahum/redux-offline.git#4bd85e7e3b279a2b11fb4d587808d583d2b5e7b5",
|
||||
"from": "git+https://github.com/enahum/redux-offline.git#4bd85e7e3b279a2b11fb4d587808d583d2b5e7b5",
|
||||
"version": "git+https://github.com/enahum/redux-offline.git#885024de96b6ec73650c340c8928066585c413df",
|
||||
"from": "git+https://github.com/enahum/redux-offline.git#885024de96b6ec73650c340c8928066585c413df",
|
||||
"requires": {
|
||||
"@react-native-community/netinfo": "^4.1.3",
|
||||
"redux-persist": "^4.5.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@react-native-community/netinfo": {
|
||||
"version": "4.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@react-native-community/netinfo/-/netinfo-4.2.1.tgz",
|
||||
"integrity": "sha512-kAnmYp8vXpZToPw8rgE7uO+MqmqHSR9VEDPkuZT0DnFMBJmIXCSD2NLAD28HGKVY/kujVWCknC/FuVWr5/A3uA=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"redux-persist": {
|
||||
|
|
@ -18263,7 +18271,7 @@
|
|||
"dependencies": {
|
||||
"async": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/async/-/async-2.0.0.tgz",
|
||||
"resolved": "http://registry.npmjs.org/async/-/async-2.0.0.tgz",
|
||||
"integrity": "sha1-0JAK04WvE4BFQKEJxCFm4657K50=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
|
|
@ -18685,7 +18693,7 @@
|
|||
},
|
||||
"inquirer": {
|
||||
"version": "5.2.0",
|
||||
"resolved": "https://registry.npmjs.org/inquirer/-/inquirer-5.2.0.tgz",
|
||||
"resolved": "http://registry.npmjs.org/inquirer/-/inquirer-5.2.0.tgz",
|
||||
"integrity": "sha512-E9BmnJbAKLPGonz0HeWHtbKf+EeSP93paWO3ZYoUpq/aowXvYGjjCSuashhXPpzbArIjBbji39THkxTz9ZeEUQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
|
|
@ -19110,7 +19118,7 @@
|
|||
},
|
||||
"strip-ansi": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
|
||||
"resolved": "http://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
|
||||
"integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
|
||||
"requires": {
|
||||
"ansi-regex": "^2.0.0"
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@
|
|||
"intl": "1.2.5",
|
||||
"jail-monkey": "2.2.0",
|
||||
"jsc-android": "241213.2.0",
|
||||
"mattermost-redux": "github:mattermost/mattermost-redux#6ea71dc77808041d7e953ac15cbc12e1c483ac69",
|
||||
"mattermost-redux": "github:mattermost/mattermost-redux#9800f16a94b46fd77e95132c1c33f18752bf8a98",
|
||||
"mime-db": "1.40.0",
|
||||
"moment-timezone": "0.5.25",
|
||||
"prop-types": "15.7.2",
|
||||
|
|
|
|||
Loading…
Reference in a new issue