[#MM-12410] Custom Terms of Service (#2234)
* [#MM-12410] Custom Terms of Service Modal. - Create a new screen for terms of service - Register it in app navigation - Open it as a modal when login succeeds or app is opened when already logged in. - Get terms of service and render it as markdown * Refactor service terms to terms of service * Show terms modal when launching channel instead of componentDidMount * Remove footer text * Close modal before logging out * Use dismissAllModals instead od this.close * Update header styles * Update the back icon * Add left icon conditinally based on os * Update en.json * - Integrate Accept/Reject API - Refactor show navigator to util - Remove title - Code refactoring * Handle Accept/Reject API errors * Update package-lock * - Show Alert to handle API error - Handle API error for GetTerms error, Accept/Reject error and Reject success - Changes in en.json - Remove error banner - Open terms modal in sso and experimental certificate * Enable navigator buttons after getting terms * Rename Ok to OK in Alert * Add retry for API error * Fix check-style * Fix FailedNetworkAction Error Message * - Use Close button instead of back button - Update en.json * Remove unused import * Disable hashtags and atmentions in terms modal * Enable close button when terms text fails to load * Minor changes * Fix show terms on sso login * Handle restartApp event * Add test cases * Revert change to app/components/formatted_markdown_text.js * Show the terms modal on the channel page * Remove remaining references to showTermsOfService * Disable Hashtags, AtMentions and ChannelLinks * Update the props to markdown component * Pass the text as literal to renderText * Return the generated renderTexts * Fix lint * Render ~, #, @ with Channel link, Hashtags and At Mentions * Fix failing tests Revert unwanted changes * Hide the channel page content before the terms are accepted * Fix lint and failing tests * Revert changes to hide channel while terms are not accepted * Open modal in componentDidMount instead of constructor Code refactoring Disable back button on android * Remove unused import * No need to await for showModal * No need to await for accept and reject * Update flag for updateTermsOfServiceStatus to updateMyTermsOfServiceStatus - as phase 2 redux PR was mered. * Fix check-style * Change opacity in terms of service text - Fix tests * Revert package-lock.json changes
This commit is contained in:
parent
e1b1635cf1
commit
68eff30eda
15 changed files with 1336 additions and 1 deletions
|
|
@ -55,12 +55,18 @@ export default class Markdown extends PureComponent {
|
|||
textStyles: PropTypes.object,
|
||||
theme: PropTypes.object.isRequired,
|
||||
value: PropTypes.string.isRequired,
|
||||
disableHashtags: PropTypes.bool,
|
||||
disableAtMentions: PropTypes.bool,
|
||||
disableChannelLink: PropTypes.bool,
|
||||
};
|
||||
|
||||
static defaultProps = {
|
||||
textStyles: {},
|
||||
blockStyles: {},
|
||||
onLongPress: () => true,
|
||||
disableHashtags: false,
|
||||
disableAtMentions: false,
|
||||
disableChannelLink: false,
|
||||
};
|
||||
|
||||
constructor(props) {
|
||||
|
|
@ -191,6 +197,10 @@ export default class Markdown extends PureComponent {
|
|||
}
|
||||
|
||||
renderAtMention = ({context, mentionName}) => {
|
||||
if (this.props.disableAtMentions) {
|
||||
return this.renderText({context, literal: `@${mentionName}`});
|
||||
}
|
||||
|
||||
return (
|
||||
<AtMention
|
||||
mentionStyle={this.props.textStyles.mention}
|
||||
|
|
@ -205,6 +215,10 @@ export default class Markdown extends PureComponent {
|
|||
}
|
||||
|
||||
renderChannelLink = ({context, channelName}) => {
|
||||
if (this.props.disableChannelLink) {
|
||||
return this.renderText({context, literal: `~${channelName}`});
|
||||
}
|
||||
|
||||
return (
|
||||
<ChannelLink
|
||||
linkStyle={this.props.textStyles.link}
|
||||
|
|
@ -225,7 +239,11 @@ export default class Markdown extends PureComponent {
|
|||
);
|
||||
}
|
||||
|
||||
renderHashtag = ({hashtag}) => {
|
||||
renderHashtag = ({context, hashtag}) => {
|
||||
if (this.props.disableHashtags) {
|
||||
return this.renderText({context, literal: `#${hashtag}`});
|
||||
}
|
||||
|
||||
return (
|
||||
<Hashtag
|
||||
hashtag={hashtag}
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ import {
|
|||
View,
|
||||
} from 'react-native';
|
||||
|
||||
import MaterialIcon from 'react-native-vector-icons/MaterialIcons';
|
||||
import EventEmitter from 'mattermost-redux/utils/event_emitter';
|
||||
|
||||
import EmptyToolbar from 'app/components/start/empty_toolbar';
|
||||
|
|
@ -65,12 +66,18 @@ export default class Channel extends PureComponent {
|
|||
isLandscape: PropTypes.bool,
|
||||
navigator: PropTypes.object,
|
||||
theme: PropTypes.object.isRequired,
|
||||
showTermsOfService: PropTypes.bool,
|
||||
disableTermsModal: PropTypes.bool,
|
||||
};
|
||||
|
||||
static contextTypes = {
|
||||
intl: intlShape.isRequired,
|
||||
};
|
||||
|
||||
static defaultProps = {
|
||||
disableTermsModal: false,
|
||||
};
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
|
|
@ -98,6 +105,10 @@ export default class Channel extends PureComponent {
|
|||
this.props.actions.recordLoadTime('Start time', 'initialLoad');
|
||||
}
|
||||
|
||||
if (this.props.showTermsOfService && !this.props.disableTermsModal) {
|
||||
this.showTermsOfServiceModal();
|
||||
}
|
||||
|
||||
EventEmitter.emit('renderDrawer');
|
||||
}
|
||||
|
||||
|
|
@ -188,6 +199,29 @@ export default class Channel extends PureComponent {
|
|||
}
|
||||
};
|
||||
|
||||
showTermsOfServiceModal = async () => {
|
||||
const {navigator, theme} = this.props;
|
||||
const closeButton = await MaterialIcon.getImageSource('close', 20, theme.sidebarHeaderTextColor);
|
||||
navigator.showModal({
|
||||
screen: 'TermsOfService',
|
||||
animationType: 'slide-up',
|
||||
title: '',
|
||||
backButtonTitle: '',
|
||||
animated: true,
|
||||
navigatorStyle: {
|
||||
navBarTextColor: theme.centerChannelColor,
|
||||
navBarBackgroundColor: theme.centerChannelBg,
|
||||
navBarButtonColor: theme.buttonBg,
|
||||
screenBackgroundColor: theme.centerChannelBg,
|
||||
modalPresentationStyle: 'overCurrentContext',
|
||||
},
|
||||
overrideBackPress: true,
|
||||
passProps: {
|
||||
closeButton,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
goToChannelInfo = preventDoubleTap(() => {
|
||||
const {intl} = this.context;
|
||||
const {navigator, theme} = this.props;
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import {RequestStatus} from 'mattermost-redux/constants';
|
|||
import {getCurrentChannelId} from 'mattermost-redux/selectors/entities/channels';
|
||||
import {getCurrentTeamId} from 'mattermost-redux/selectors/entities/teams';
|
||||
import {getTheme} from 'mattermost-redux/selectors/entities/preferences';
|
||||
import {shouldShowTermsOfService} from 'mattermost-redux/selectors/entities/users';
|
||||
|
||||
import {
|
||||
loadChannelsIfNecessary,
|
||||
|
|
@ -32,6 +33,7 @@ function mapStateToProps(state) {
|
|||
currentChannelId: getCurrentChannelId(state),
|
||||
isLandscape: isLandscape(state),
|
||||
theme: getTheme(state),
|
||||
showTermsOfService: shouldShowTermsOfService(state),
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -63,6 +63,9 @@ export default class ErrorTeamsList extends PureComponent {
|
|||
statusBarHideWithNavBar: false,
|
||||
screenBackgroundColor: theme.centerChannelBg,
|
||||
},
|
||||
passProps: {
|
||||
disableTermsModal: true,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -57,6 +57,7 @@ export function registerScreens(store, Provider) {
|
|||
Navigation.registerComponent('SSO', () => wrapWithContextProvider(require('app/screens/sso').default), store, Provider);
|
||||
Navigation.registerComponent('Table', () => wrapWithContextProvider(require('app/screens/table').default), store, Provider);
|
||||
Navigation.registerComponent('TableImage', () => wrapWithContextProvider(require('app/screens/table_image').default), store, Provider);
|
||||
Navigation.registerComponent('TermsOfService', () => wrapWithContextProvider(require('app/screens/terms_of_service').default), store, Provider);
|
||||
Navigation.registerComponent('TextPreview', () => wrapWithContextProvider(require('app/screens/text_preview').default), store, Provider);
|
||||
Navigation.registerComponent('Thread', () => wrapWithContextProvider(require('app/screens/thread').default), store, Provider);
|
||||
Navigation.registerComponent('TimezoneSettings', () => wrapWithContextProvider(require('app/screens/timezone').default), store, Provider);
|
||||
|
|
|
|||
|
|
@ -253,6 +253,9 @@ export default class Permalink extends PureComponent {
|
|||
statusBarHideWithNavBar: false,
|
||||
screenBackgroundColor: theme.centerChannelBg,
|
||||
},
|
||||
passProps: {
|
||||
disableTermsModal: true,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -126,6 +126,9 @@ export default class SelectTeam extends PureComponent {
|
|||
statusBarHideWithNavBar: false,
|
||||
screenBackgroundColor: theme.centerChannelBg,
|
||||
},
|
||||
passProps: {
|
||||
disableTermsModal: true,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,783 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`TermsOfService should enable/disable navigator buttons on setNavigatorButtons true/false 1`] = `
|
||||
<React.Fragment>
|
||||
<Connect(StatusBar) />
|
||||
<ScrollView
|
||||
contentContainerStyle={
|
||||
Object {
|
||||
"paddingBottom": 50,
|
||||
}
|
||||
}
|
||||
style={
|
||||
Object {
|
||||
"backgroundColor": "#ffffff",
|
||||
"flex": 1,
|
||||
"padding": 30,
|
||||
}
|
||||
}
|
||||
>
|
||||
<Connect(Markdown)
|
||||
baseTextStyle={
|
||||
Object {
|
||||
"color": "#3d3c40",
|
||||
"fontSize": 15,
|
||||
"lineHeight": 20,
|
||||
}
|
||||
}
|
||||
blockStyles={
|
||||
Object {
|
||||
"adjacentParagraph": Object {
|
||||
"marginTop": 6,
|
||||
},
|
||||
"horizontalRule": Object {
|
||||
"backgroundColor": "#3d3c40",
|
||||
"flex": 1,
|
||||
"height": 0.5,
|
||||
"marginVertical": 10,
|
||||
},
|
||||
"quoteBlockIcon": Object {
|
||||
"color": undefined,
|
||||
"padding": 5,
|
||||
},
|
||||
}
|
||||
}
|
||||
disableAtMentions={true}
|
||||
disableChannelLink={true}
|
||||
disableHashtags={true}
|
||||
navigator={
|
||||
Object {
|
||||
"dismissAllModals": [MockFunction],
|
||||
"dismissModal": [MockFunction],
|
||||
"setButtons": [MockFunction] {
|
||||
"calls": Array [
|
||||
Array [
|
||||
Object {
|
||||
"leftButtons": Array [
|
||||
Object {
|
||||
"disabled": true,
|
||||
"icon": Object {},
|
||||
"id": "reject-terms-of-service",
|
||||
},
|
||||
],
|
||||
"rightButtons": Array [
|
||||
Object {
|
||||
"disabled": true,
|
||||
"id": "accept-terms-of-service",
|
||||
"showAsAction": "always",
|
||||
"title": undefined,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
Array [
|
||||
Object {
|
||||
"leftButtons": Array [
|
||||
Object {
|
||||
"disabled": true,
|
||||
"icon": Object {},
|
||||
"id": "reject-terms-of-service",
|
||||
},
|
||||
],
|
||||
"rightButtons": Array [
|
||||
Object {
|
||||
"disabled": true,
|
||||
"id": "accept-terms-of-service",
|
||||
"showAsAction": "always",
|
||||
"title": undefined,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
Array [
|
||||
Object {
|
||||
"leftButtons": Array [
|
||||
Object {
|
||||
"disabled": false,
|
||||
"icon": Object {},
|
||||
"id": "reject-terms-of-service",
|
||||
},
|
||||
],
|
||||
"rightButtons": Array [
|
||||
Object {
|
||||
"disabled": false,
|
||||
"id": "accept-terms-of-service",
|
||||
"showAsAction": "always",
|
||||
"title": undefined,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
],
|
||||
"results": Array [
|
||||
Object {
|
||||
"isThrow": false,
|
||||
"value": undefined,
|
||||
},
|
||||
Object {
|
||||
"isThrow": false,
|
||||
"value": undefined,
|
||||
},
|
||||
Object {
|
||||
"isThrow": false,
|
||||
"value": undefined,
|
||||
},
|
||||
],
|
||||
},
|
||||
"setOnNavigatorEvent": [MockFunction] {
|
||||
"calls": Array [
|
||||
Array [
|
||||
[Function],
|
||||
],
|
||||
],
|
||||
"results": Array [
|
||||
Object {
|
||||
"isThrow": false,
|
||||
"value": undefined,
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
}
|
||||
textStyles={
|
||||
Object {
|
||||
"code": Object {
|
||||
"alignSelf": "center",
|
||||
"backgroundColor": undefined,
|
||||
"fontFamily": "Menlo",
|
||||
},
|
||||
"codeBlock": Object {
|
||||
"fontFamily": "Menlo",
|
||||
},
|
||||
"del": Object {
|
||||
"textDecorationLine": "line-through",
|
||||
},
|
||||
"emph": Object {
|
||||
"fontStyle": "italic",
|
||||
},
|
||||
"error": Object {
|
||||
"color": "#fd5960",
|
||||
},
|
||||
"heading1": Object {
|
||||
"fontSize": 17,
|
||||
"fontWeight": "700",
|
||||
"lineHeight": 25,
|
||||
},
|
||||
"heading1Text": Object {
|
||||
"paddingBottom": 8,
|
||||
},
|
||||
"heading2": Object {
|
||||
"fontSize": 17,
|
||||
"fontWeight": "700",
|
||||
"lineHeight": 25,
|
||||
},
|
||||
"heading2Text": Object {
|
||||
"paddingBottom": 8,
|
||||
},
|
||||
"heading3": Object {
|
||||
"fontSize": 17,
|
||||
"fontWeight": "700",
|
||||
"lineHeight": 25,
|
||||
},
|
||||
"heading3Text": Object {
|
||||
"paddingBottom": 8,
|
||||
},
|
||||
"heading4": Object {
|
||||
"fontSize": 17,
|
||||
"fontWeight": "700",
|
||||
"lineHeight": 25,
|
||||
},
|
||||
"heading4Text": Object {
|
||||
"paddingBottom": 8,
|
||||
},
|
||||
"heading5": Object {
|
||||
"fontSize": 17,
|
||||
"fontWeight": "700",
|
||||
"lineHeight": 25,
|
||||
},
|
||||
"heading5Text": Object {
|
||||
"paddingBottom": 8,
|
||||
},
|
||||
"heading6": Object {
|
||||
"fontSize": 17,
|
||||
"fontWeight": "700",
|
||||
"lineHeight": 25,
|
||||
},
|
||||
"heading6Text": Object {
|
||||
"paddingBottom": 8,
|
||||
},
|
||||
"link": Object {
|
||||
"color": "#2389d7",
|
||||
},
|
||||
"mention": Object {
|
||||
"color": "#2389d7",
|
||||
},
|
||||
"mention_highlight": Object {
|
||||
"backgroundColor": "#ffe577",
|
||||
},
|
||||
"strong": Object {
|
||||
"fontWeight": "bold",
|
||||
},
|
||||
"table_header_row": Object {
|
||||
"fontWeight": "700",
|
||||
},
|
||||
}
|
||||
}
|
||||
value="Terms Text"
|
||||
/>
|
||||
</ScrollView>
|
||||
</React.Fragment>
|
||||
`;
|
||||
|
||||
exports[`TermsOfService should enable/disable navigator buttons on setNavigatorButtons true/false 2`] = `
|
||||
<React.Fragment>
|
||||
<Connect(StatusBar) />
|
||||
<ScrollView
|
||||
contentContainerStyle={
|
||||
Object {
|
||||
"paddingBottom": 50,
|
||||
}
|
||||
}
|
||||
style={
|
||||
Object {
|
||||
"backgroundColor": "#ffffff",
|
||||
"flex": 1,
|
||||
"padding": 30,
|
||||
}
|
||||
}
|
||||
>
|
||||
<Connect(Markdown)
|
||||
baseTextStyle={
|
||||
Object {
|
||||
"color": "#3d3c40",
|
||||
"fontSize": 15,
|
||||
"lineHeight": 20,
|
||||
}
|
||||
}
|
||||
blockStyles={
|
||||
Object {
|
||||
"adjacentParagraph": Object {
|
||||
"marginTop": 6,
|
||||
},
|
||||
"horizontalRule": Object {
|
||||
"backgroundColor": "#3d3c40",
|
||||
"flex": 1,
|
||||
"height": 0.5,
|
||||
"marginVertical": 10,
|
||||
},
|
||||
"quoteBlockIcon": Object {
|
||||
"color": undefined,
|
||||
"padding": 5,
|
||||
},
|
||||
}
|
||||
}
|
||||
disableAtMentions={true}
|
||||
disableChannelLink={true}
|
||||
disableHashtags={true}
|
||||
navigator={
|
||||
Object {
|
||||
"dismissAllModals": [MockFunction],
|
||||
"dismissModal": [MockFunction],
|
||||
"setButtons": [MockFunction] {
|
||||
"calls": Array [
|
||||
Array [
|
||||
Object {
|
||||
"leftButtons": Array [
|
||||
Object {
|
||||
"disabled": true,
|
||||
"icon": Object {},
|
||||
"id": "reject-terms-of-service",
|
||||
},
|
||||
],
|
||||
"rightButtons": Array [
|
||||
Object {
|
||||
"disabled": true,
|
||||
"id": "accept-terms-of-service",
|
||||
"showAsAction": "always",
|
||||
"title": undefined,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
Array [
|
||||
Object {
|
||||
"leftButtons": Array [
|
||||
Object {
|
||||
"disabled": true,
|
||||
"icon": Object {},
|
||||
"id": "reject-terms-of-service",
|
||||
},
|
||||
],
|
||||
"rightButtons": Array [
|
||||
Object {
|
||||
"disabled": true,
|
||||
"id": "accept-terms-of-service",
|
||||
"showAsAction": "always",
|
||||
"title": undefined,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
Array [
|
||||
Object {
|
||||
"leftButtons": Array [
|
||||
Object {
|
||||
"disabled": false,
|
||||
"icon": Object {},
|
||||
"id": "reject-terms-of-service",
|
||||
},
|
||||
],
|
||||
"rightButtons": Array [
|
||||
Object {
|
||||
"disabled": false,
|
||||
"id": "accept-terms-of-service",
|
||||
"showAsAction": "always",
|
||||
"title": undefined,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
Array [
|
||||
Object {
|
||||
"leftButtons": Array [
|
||||
Object {
|
||||
"disabled": true,
|
||||
"icon": Object {},
|
||||
"id": "reject-terms-of-service",
|
||||
},
|
||||
],
|
||||
"rightButtons": Array [
|
||||
Object {
|
||||
"disabled": true,
|
||||
"id": "accept-terms-of-service",
|
||||
"showAsAction": "always",
|
||||
"title": undefined,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
],
|
||||
"results": Array [
|
||||
Object {
|
||||
"isThrow": false,
|
||||
"value": undefined,
|
||||
},
|
||||
Object {
|
||||
"isThrow": false,
|
||||
"value": undefined,
|
||||
},
|
||||
Object {
|
||||
"isThrow": false,
|
||||
"value": undefined,
|
||||
},
|
||||
Object {
|
||||
"isThrow": false,
|
||||
"value": undefined,
|
||||
},
|
||||
],
|
||||
},
|
||||
"setOnNavigatorEvent": [MockFunction] {
|
||||
"calls": Array [
|
||||
Array [
|
||||
[Function],
|
||||
],
|
||||
],
|
||||
"results": Array [
|
||||
Object {
|
||||
"isThrow": false,
|
||||
"value": undefined,
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
}
|
||||
textStyles={
|
||||
Object {
|
||||
"code": Object {
|
||||
"alignSelf": "center",
|
||||
"backgroundColor": undefined,
|
||||
"fontFamily": "Menlo",
|
||||
},
|
||||
"codeBlock": Object {
|
||||
"fontFamily": "Menlo",
|
||||
},
|
||||
"del": Object {
|
||||
"textDecorationLine": "line-through",
|
||||
},
|
||||
"emph": Object {
|
||||
"fontStyle": "italic",
|
||||
},
|
||||
"error": Object {
|
||||
"color": "#fd5960",
|
||||
},
|
||||
"heading1": Object {
|
||||
"fontSize": 17,
|
||||
"fontWeight": "700",
|
||||
"lineHeight": 25,
|
||||
},
|
||||
"heading1Text": Object {
|
||||
"paddingBottom": 8,
|
||||
},
|
||||
"heading2": Object {
|
||||
"fontSize": 17,
|
||||
"fontWeight": "700",
|
||||
"lineHeight": 25,
|
||||
},
|
||||
"heading2Text": Object {
|
||||
"paddingBottom": 8,
|
||||
},
|
||||
"heading3": Object {
|
||||
"fontSize": 17,
|
||||
"fontWeight": "700",
|
||||
"lineHeight": 25,
|
||||
},
|
||||
"heading3Text": Object {
|
||||
"paddingBottom": 8,
|
||||
},
|
||||
"heading4": Object {
|
||||
"fontSize": 17,
|
||||
"fontWeight": "700",
|
||||
"lineHeight": 25,
|
||||
},
|
||||
"heading4Text": Object {
|
||||
"paddingBottom": 8,
|
||||
},
|
||||
"heading5": Object {
|
||||
"fontSize": 17,
|
||||
"fontWeight": "700",
|
||||
"lineHeight": 25,
|
||||
},
|
||||
"heading5Text": Object {
|
||||
"paddingBottom": 8,
|
||||
},
|
||||
"heading6": Object {
|
||||
"fontSize": 17,
|
||||
"fontWeight": "700",
|
||||
"lineHeight": 25,
|
||||
},
|
||||
"heading6Text": Object {
|
||||
"paddingBottom": 8,
|
||||
},
|
||||
"link": Object {
|
||||
"color": "#2389d7",
|
||||
},
|
||||
"mention": Object {
|
||||
"color": "#2389d7",
|
||||
},
|
||||
"mention_highlight": Object {
|
||||
"backgroundColor": "#ffe577",
|
||||
},
|
||||
"strong": Object {
|
||||
"fontWeight": "bold",
|
||||
},
|
||||
"table_header_row": Object {
|
||||
"fontWeight": "700",
|
||||
},
|
||||
}
|
||||
}
|
||||
value="Terms Text"
|
||||
/>
|
||||
</ScrollView>
|
||||
</React.Fragment>
|
||||
`;
|
||||
|
||||
exports[`TermsOfService should match snapshot 1`] = `
|
||||
<Loading
|
||||
color="grey"
|
||||
size="large"
|
||||
style={Object {}}
|
||||
/>
|
||||
`;
|
||||
|
||||
exports[`TermsOfService should match snapshot for fail of get terms 1`] = `
|
||||
<Component
|
||||
style={
|
||||
Object {
|
||||
"backgroundColor": "#ffffff",
|
||||
"flex": 1,
|
||||
}
|
||||
}
|
||||
>
|
||||
<Connect(StatusBar) />
|
||||
<FailedNetworkAction
|
||||
errorDescription={
|
||||
Object {
|
||||
"defaultMessage": "Make sure you have an active internet connection and try again. If this issue persists, contact your System Administrator.",
|
||||
"id": "mobile.terms_of_service.get_terms_error_description",
|
||||
}
|
||||
}
|
||||
errorTitle={
|
||||
Object {
|
||||
"defaultMessage": "Unable to load terms of service.",
|
||||
"id": "mobile.terms_of_service.get_terms_error_title",
|
||||
}
|
||||
}
|
||||
onRetry={[Function]}
|
||||
theme={
|
||||
Object {
|
||||
"awayIndicator": "#ffbc42",
|
||||
"buttonBg": "#166de0",
|
||||
"buttonColor": "#ffffff",
|
||||
"centerChannelBg": "#ffffff",
|
||||
"centerChannelColor": "#3d3c40",
|
||||
"codeTheme": "github",
|
||||
"dndIndicator": "#f74343",
|
||||
"errorTextColor": "#fd5960",
|
||||
"linkColor": "#2389d7",
|
||||
"mentionBj": "#ffffff",
|
||||
"mentionColor": "#145dbf",
|
||||
"mentionHighlightBg": "#ffe577",
|
||||
"mentionHighlightLink": "#166de0",
|
||||
"newMessageSeparator": "#ff8800",
|
||||
"onlineIndicator": "#06d6a0",
|
||||
"sidebarBg": "#145dbf",
|
||||
"sidebarHeaderBg": "#1153ab",
|
||||
"sidebarHeaderTextColor": "#ffffff",
|
||||
"sidebarText": "#ffffff",
|
||||
"sidebarTextActiveBorder": "#579eff",
|
||||
"sidebarTextActiveColor": "#ffffff",
|
||||
"sidebarTextHoverBg": "#4578bf",
|
||||
"sidebarUnreadText": "#ffffff",
|
||||
"type": "Mattermost",
|
||||
}
|
||||
}
|
||||
/>
|
||||
</Component>
|
||||
`;
|
||||
|
||||
exports[`TermsOfService should match snapshot for get terms 1`] = `
|
||||
<Loading
|
||||
color="grey"
|
||||
size="large"
|
||||
style={Object {}}
|
||||
/>
|
||||
`;
|
||||
|
||||
exports[`TermsOfService should match snapshot on enableNavigatorLogout 1`] = `
|
||||
<React.Fragment>
|
||||
<Connect(StatusBar) />
|
||||
<ScrollView
|
||||
contentContainerStyle={
|
||||
Object {
|
||||
"paddingBottom": 50,
|
||||
}
|
||||
}
|
||||
style={
|
||||
Object {
|
||||
"backgroundColor": "#ffffff",
|
||||
"flex": 1,
|
||||
"padding": 30,
|
||||
}
|
||||
}
|
||||
>
|
||||
<Connect(Markdown)
|
||||
baseTextStyle={
|
||||
Object {
|
||||
"color": "#3d3c40",
|
||||
"fontSize": 15,
|
||||
"lineHeight": 20,
|
||||
}
|
||||
}
|
||||
blockStyles={
|
||||
Object {
|
||||
"adjacentParagraph": Object {
|
||||
"marginTop": 6,
|
||||
},
|
||||
"horizontalRule": Object {
|
||||
"backgroundColor": "#3d3c40",
|
||||
"flex": 1,
|
||||
"height": 0.5,
|
||||
"marginVertical": 10,
|
||||
},
|
||||
"quoteBlockIcon": Object {
|
||||
"color": undefined,
|
||||
"padding": 5,
|
||||
},
|
||||
}
|
||||
}
|
||||
disableAtMentions={true}
|
||||
disableChannelLink={true}
|
||||
disableHashtags={true}
|
||||
navigator={
|
||||
Object {
|
||||
"dismissAllModals": [MockFunction],
|
||||
"dismissModal": [MockFunction],
|
||||
"setButtons": [MockFunction] {
|
||||
"calls": Array [
|
||||
Array [
|
||||
Object {
|
||||
"leftButtons": Array [
|
||||
Object {
|
||||
"disabled": true,
|
||||
"icon": Object {},
|
||||
"id": "reject-terms-of-service",
|
||||
},
|
||||
],
|
||||
"rightButtons": Array [
|
||||
Object {
|
||||
"disabled": true,
|
||||
"id": "accept-terms-of-service",
|
||||
"showAsAction": "always",
|
||||
"title": undefined,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
Array [
|
||||
Object {
|
||||
"leftButtons": Array [
|
||||
Object {
|
||||
"disabled": true,
|
||||
"icon": Object {},
|
||||
"id": "reject-terms-of-service",
|
||||
},
|
||||
],
|
||||
"rightButtons": Array [
|
||||
Object {
|
||||
"disabled": true,
|
||||
"id": "accept-terms-of-service",
|
||||
"showAsAction": "always",
|
||||
"title": undefined,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
Array [
|
||||
Object {
|
||||
"leftButtons": Array [
|
||||
Object {
|
||||
"disabled": false,
|
||||
"icon": Object {},
|
||||
"id": "close-terms-of-service",
|
||||
},
|
||||
],
|
||||
"rightButtons": Array [
|
||||
Object {
|
||||
"disabled": true,
|
||||
"id": "accept-terms-of-service",
|
||||
"showAsAction": "always",
|
||||
"title": undefined,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
],
|
||||
"results": Array [
|
||||
Object {
|
||||
"isThrow": false,
|
||||
"value": undefined,
|
||||
},
|
||||
Object {
|
||||
"isThrow": false,
|
||||
"value": undefined,
|
||||
},
|
||||
Object {
|
||||
"isThrow": false,
|
||||
"value": undefined,
|
||||
},
|
||||
],
|
||||
},
|
||||
"setOnNavigatorEvent": [MockFunction] {
|
||||
"calls": Array [
|
||||
Array [
|
||||
[Function],
|
||||
],
|
||||
],
|
||||
"results": Array [
|
||||
Object {
|
||||
"isThrow": false,
|
||||
"value": undefined,
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
}
|
||||
textStyles={
|
||||
Object {
|
||||
"code": Object {
|
||||
"alignSelf": "center",
|
||||
"backgroundColor": undefined,
|
||||
"fontFamily": "Menlo",
|
||||
},
|
||||
"codeBlock": Object {
|
||||
"fontFamily": "Menlo",
|
||||
},
|
||||
"del": Object {
|
||||
"textDecorationLine": "line-through",
|
||||
},
|
||||
"emph": Object {
|
||||
"fontStyle": "italic",
|
||||
},
|
||||
"error": Object {
|
||||
"color": "#fd5960",
|
||||
},
|
||||
"heading1": Object {
|
||||
"fontSize": 17,
|
||||
"fontWeight": "700",
|
||||
"lineHeight": 25,
|
||||
},
|
||||
"heading1Text": Object {
|
||||
"paddingBottom": 8,
|
||||
},
|
||||
"heading2": Object {
|
||||
"fontSize": 17,
|
||||
"fontWeight": "700",
|
||||
"lineHeight": 25,
|
||||
},
|
||||
"heading2Text": Object {
|
||||
"paddingBottom": 8,
|
||||
},
|
||||
"heading3": Object {
|
||||
"fontSize": 17,
|
||||
"fontWeight": "700",
|
||||
"lineHeight": 25,
|
||||
},
|
||||
"heading3Text": Object {
|
||||
"paddingBottom": 8,
|
||||
},
|
||||
"heading4": Object {
|
||||
"fontSize": 17,
|
||||
"fontWeight": "700",
|
||||
"lineHeight": 25,
|
||||
},
|
||||
"heading4Text": Object {
|
||||
"paddingBottom": 8,
|
||||
},
|
||||
"heading5": Object {
|
||||
"fontSize": 17,
|
||||
"fontWeight": "700",
|
||||
"lineHeight": 25,
|
||||
},
|
||||
"heading5Text": Object {
|
||||
"paddingBottom": 8,
|
||||
},
|
||||
"heading6": Object {
|
||||
"fontSize": 17,
|
||||
"fontWeight": "700",
|
||||
"lineHeight": 25,
|
||||
},
|
||||
"heading6Text": Object {
|
||||
"paddingBottom": 8,
|
||||
},
|
||||
"link": Object {
|
||||
"color": "#2389d7",
|
||||
},
|
||||
"mention": Object {
|
||||
"color": "#2389d7",
|
||||
},
|
||||
"mention_highlight": Object {
|
||||
"backgroundColor": "#ffe577",
|
||||
},
|
||||
"strong": Object {
|
||||
"fontWeight": "bold",
|
||||
},
|
||||
"table_header_row": Object {
|
||||
"fontWeight": "700",
|
||||
},
|
||||
}
|
||||
}
|
||||
value="Terms Text"
|
||||
/>
|
||||
</ScrollView>
|
||||
</React.Fragment>
|
||||
`;
|
||||
32
app/screens/terms_of_service/index.js
Normal file
32
app/screens/terms_of_service/index.js
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import {bindActionCreators} from 'redux';
|
||||
import {connect} from 'react-redux';
|
||||
|
||||
import {getTermsOfService, logout, updateMyTermsOfServiceStatus} from 'mattermost-redux/actions/users';
|
||||
import {getConfig} from 'mattermost-redux/selectors/entities/general';
|
||||
import {getTheme} from 'mattermost-redux/selectors/entities/preferences';
|
||||
|
||||
import TermsOfService from './terms_of_service.js';
|
||||
|
||||
function mapStateToProps(state) {
|
||||
const config = getConfig(state);
|
||||
|
||||
return {
|
||||
siteName: config.SiteName,
|
||||
theme: getTheme(state),
|
||||
};
|
||||
}
|
||||
|
||||
function mapDispatchToProps(dispatch) {
|
||||
return {
|
||||
actions: bindActionCreators({
|
||||
getTermsOfService,
|
||||
logout,
|
||||
updateMyTermsOfServiceStatus,
|
||||
}, dispatch),
|
||||
};
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(TermsOfService);
|
||||
305
app/screens/terms_of_service/terms_of_service.js
Normal file
305
app/screens/terms_of_service/terms_of_service.js
Normal file
|
|
@ -0,0 +1,305 @@
|
|||
// 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 {
|
||||
Alert,
|
||||
ScrollView,
|
||||
View,
|
||||
} from 'react-native';
|
||||
import {intlShape} from 'react-intl';
|
||||
|
||||
import FailedNetworkAction from 'app/components/failed_network_action';
|
||||
import Loading from 'app/components/loading';
|
||||
import Markdown from 'app/components/markdown';
|
||||
import StatusBar from 'app/components/status_bar';
|
||||
|
||||
import {t} from 'app/utils/i18n';
|
||||
import {getMarkdownTextStyles, getMarkdownBlockStyles} from 'app/utils/markdown';
|
||||
import {makeStyleSheetFromTheme, setNavigatorStyles} from 'app/utils/theme';
|
||||
|
||||
const errorTitle = {
|
||||
id: t('mobile.terms_of_service.get_terms_error_title'),
|
||||
defaultMessage: 'Unable to load terms of service.',
|
||||
};
|
||||
|
||||
const errorDescription = {
|
||||
id: t('mobile.terms_of_service.get_terms_error_description'),
|
||||
defaultMessage: 'Make sure you have an active internet connection and try again. If this issue persists, contact your System Administrator.',
|
||||
};
|
||||
|
||||
export default class TermsOfService extends PureComponent {
|
||||
static propTypes = {
|
||||
actions: PropTypes.shape({
|
||||
logout: PropTypes.func.isRequired,
|
||||
getTermsOfService: PropTypes.func.isRequired,
|
||||
updateMyTermsOfServiceStatus: PropTypes.func.isRequired,
|
||||
}).isRequired,
|
||||
closeButton: PropTypes.object,
|
||||
navigator: PropTypes.object,
|
||||
siteName: PropTypes.string,
|
||||
theme: PropTypes.object,
|
||||
};
|
||||
|
||||
static contextTypes = {
|
||||
intl: intlShape,
|
||||
};
|
||||
|
||||
static defaultProps = {
|
||||
siteName: 'Mattermost',
|
||||
};
|
||||
|
||||
leftButton = {
|
||||
id: 'reject-terms-of-service',
|
||||
};
|
||||
|
||||
rightButton = {
|
||||
id: 'accept-terms-of-service',
|
||||
showAsAction: 'always',
|
||||
};
|
||||
|
||||
constructor(props, context) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
getTermsError: false,
|
||||
loading: true,
|
||||
termsId: '',
|
||||
termsText: '',
|
||||
};
|
||||
|
||||
this.rightButton.title = context.intl.formatMessage({id: 'terms_of_service.agreeButton', defaultMessage: 'I Agree'});
|
||||
this.leftButton.icon = props.closeButton;
|
||||
|
||||
props.navigator.setOnNavigatorEvent(this.onNavigatorEvent);
|
||||
this.setNavigatorButtons(false);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.getTerms();
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps) {
|
||||
if (this.props.theme !== prevProps.theme) {
|
||||
setNavigatorStyles(this.props.navigator, this.props.theme);
|
||||
}
|
||||
}
|
||||
|
||||
onNavigatorEvent = (event) => {
|
||||
if (event.type === 'NavBarButtonPress') {
|
||||
switch (event.id) {
|
||||
case 'close-terms-of-service':
|
||||
this.closeTermsAndLogout();
|
||||
break;
|
||||
|
||||
case 'reject-terms-of-service':
|
||||
this.handleRejectTerms();
|
||||
break;
|
||||
|
||||
case 'accept-terms-of-service':
|
||||
this.handleAcceptTerms();
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
setNavigatorButtons = (enabled = true) => {
|
||||
const buttons = {
|
||||
leftButtons: [{...this.leftButton, disabled: !enabled}],
|
||||
rightButtons: [{...this.rightButton, disabled: !enabled}],
|
||||
};
|
||||
|
||||
this.props.navigator.setButtons(buttons);
|
||||
};
|
||||
|
||||
enableNavigatorLogout = () => {
|
||||
const buttons = {
|
||||
leftButtons: [{...this.leftButton, id: 'close-terms-of-service', disabled: false}],
|
||||
rightButtons: [{...this.rightButton, disabled: true}],
|
||||
};
|
||||
|
||||
this.props.navigator.setButtons(buttons);
|
||||
};
|
||||
|
||||
closeTermsAndLogout = () => {
|
||||
const {actions} = this.props;
|
||||
|
||||
this.props.navigator.dismissAllModals();
|
||||
actions.logout();
|
||||
};
|
||||
|
||||
getTerms = async () => {
|
||||
const {actions} = this.props;
|
||||
|
||||
this.setState({
|
||||
termsId: '',
|
||||
termsText: '',
|
||||
loading: true,
|
||||
getTermsError: false,
|
||||
});
|
||||
this.setNavigatorButtons(false);
|
||||
|
||||
const {data} = await actions.getTermsOfService();
|
||||
if (data) {
|
||||
this.setState({
|
||||
termsId: data.id,
|
||||
termsText: data.text,
|
||||
loading: false,
|
||||
}, () => {
|
||||
this.setNavigatorButtons(true);
|
||||
});
|
||||
} else {
|
||||
this.setState({
|
||||
loading: false,
|
||||
getTermsError: true,
|
||||
});
|
||||
this.enableNavigatorLogout();
|
||||
}
|
||||
};
|
||||
|
||||
handleAcceptTerms = () => {
|
||||
this.registerUserAction(
|
||||
true,
|
||||
() => {
|
||||
this.props.navigator.dismissModal({
|
||||
animationType: 'slide-down',
|
||||
});
|
||||
},
|
||||
this.handleAcceptTerms
|
||||
);
|
||||
};
|
||||
|
||||
handleRejectTerms = () => {
|
||||
const {siteName} = this.props;
|
||||
const {intl} = this.context;
|
||||
|
||||
this.registerUserAction(
|
||||
false,
|
||||
() => {
|
||||
Alert.alert(
|
||||
this.props.siteName,
|
||||
intl.formatMessage({
|
||||
id: 'mobile.terms_of_service.terms_rejected',
|
||||
defaultMessage: 'You must agree to the terms of service before accessing {siteName}. Please contact your System Administrator for more details.',
|
||||
}, {
|
||||
siteName,
|
||||
}),
|
||||
[{
|
||||
text: intl.formatMessage({id: 'mobile.terms_of_service.alert_ok', defaultMessage: 'Ok'}),
|
||||
onPress: this.closeTermsAndLogout,
|
||||
}],
|
||||
);
|
||||
},
|
||||
this.handleRejectTerms
|
||||
);
|
||||
};
|
||||
|
||||
registerUserAction = async (accepted, success, retry) => {
|
||||
const {actions} = this.props;
|
||||
const {intl} = this.context;
|
||||
|
||||
this.setNavigatorButtons(false);
|
||||
this.setState({
|
||||
loading: true,
|
||||
});
|
||||
|
||||
const {data} = await actions.updateMyTermsOfServiceStatus(this.state.termsId, accepted);
|
||||
|
||||
this.setState({
|
||||
loading: false,
|
||||
});
|
||||
|
||||
if (data) {
|
||||
success(data);
|
||||
this.setNavigatorButtons(true);
|
||||
} else {
|
||||
Alert.alert(
|
||||
this.props.siteName,
|
||||
intl.formatMessage({
|
||||
id: 'terms_of_service.api_error',
|
||||
defaultMessage: 'Unable to complete the request. If this issue persists, contact your System Administrator.',
|
||||
}),
|
||||
[{
|
||||
text: intl.formatMessage({id: 'mobile.terms_of_service.alert_retry', defaultMessage: 'Try Again'}),
|
||||
onPress: retry,
|
||||
}, {
|
||||
text: intl.formatMessage({id: 'mobile.terms_of_service.alert_cancel', defaultMessage: 'Cancel'}),
|
||||
onPress: this.closeTermsAndLogout,
|
||||
}],
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
const {navigator, theme} = this.props;
|
||||
const styles = getStyleSheet(theme);
|
||||
|
||||
const blockStyles = getMarkdownBlockStyles(theme);
|
||||
const textStyles = getMarkdownTextStyles(theme);
|
||||
|
||||
if (this.state.loading) {
|
||||
return <Loading/>;
|
||||
}
|
||||
|
||||
if (this.state.getTermsError) {
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<StatusBar/>
|
||||
<FailedNetworkAction
|
||||
onRetry={this.getTerms}
|
||||
theme={theme}
|
||||
errorTitle={errorTitle}
|
||||
errorDescription={errorDescription}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
<StatusBar/>
|
||||
<ScrollView
|
||||
style={styles.scrollView}
|
||||
contentContainerStyle={styles.scrollViewContent}
|
||||
>
|
||||
<Markdown
|
||||
baseTextStyle={styles.baseText}
|
||||
navigator={navigator}
|
||||
textStyles={textStyles}
|
||||
blockStyles={blockStyles}
|
||||
value={this.state.termsText}
|
||||
disableHashtags={true}
|
||||
disableAtMentions={true}
|
||||
disableChannelLink={true}
|
||||
/>
|
||||
</ScrollView>
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const getStyleSheet = makeStyleSheetFromTheme((theme) => {
|
||||
return {
|
||||
baseText: {
|
||||
color: theme.centerChannelColor,
|
||||
fontSize: 15,
|
||||
lineHeight: 20,
|
||||
},
|
||||
container: {
|
||||
backgroundColor: theme.centerChannelBg,
|
||||
flex: 1,
|
||||
},
|
||||
linkText: {
|
||||
color: theme.linkColor,
|
||||
},
|
||||
scrollView: {
|
||||
flex: 1,
|
||||
backgroundColor: theme.centerChannelBg,
|
||||
padding: 30,
|
||||
},
|
||||
scrollViewContent: {
|
||||
paddingBottom: 50,
|
||||
},
|
||||
};
|
||||
});
|
||||
134
app/screens/terms_of_service/terms_of_service.test.js
Normal file
134
app/screens/terms_of_service/terms_of_service.test.js
Normal file
|
|
@ -0,0 +1,134 @@
|
|||
// 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 TermsOfService from './terms_of_service.js';
|
||||
|
||||
jest.mock('react-intl');
|
||||
|
||||
jest.mock('app/utils/theme', () => {
|
||||
const original = require.requireActual('app/utils/theme');
|
||||
return {
|
||||
...original,
|
||||
changeOpacity: jest.fn(),
|
||||
};
|
||||
});
|
||||
|
||||
describe('TermsOfService', () => {
|
||||
const actions = {
|
||||
getTermsOfService: jest.fn(),
|
||||
updateMyTermsOfServiceStatus: jest.fn(),
|
||||
logout: jest.fn(),
|
||||
};
|
||||
|
||||
const baseProps = {
|
||||
actions,
|
||||
navigator: {
|
||||
dismissAllModals: jest.fn(),
|
||||
dismissModal: jest.fn(),
|
||||
setButtons: jest.fn(),
|
||||
setOnNavigatorEvent: jest.fn(),
|
||||
},
|
||||
theme: Preferences.THEMES.default,
|
||||
closeButton: {},
|
||||
siteName: 'Mattermost',
|
||||
};
|
||||
|
||||
test('should match snapshot', () => {
|
||||
const wrapper = shallow(
|
||||
<TermsOfService {...baseProps}/>,
|
||||
{context: {intl: {formatMessage: jest.fn()}}},
|
||||
);
|
||||
|
||||
expect(wrapper.getElement()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('should match snapshot for get terms', async () => {
|
||||
const wrapper = shallow(
|
||||
<TermsOfService {...baseProps}/>,
|
||||
{context: {intl: {formatMessage: jest.fn()}}},
|
||||
);
|
||||
await actions.getTermsOfService();
|
||||
wrapper.update();
|
||||
expect(wrapper.getElement()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('should match snapshot for fail of get terms', async () => {
|
||||
const getTermsOfService = async () => {
|
||||
return {
|
||||
error: {},
|
||||
};
|
||||
};
|
||||
|
||||
const props = {
|
||||
...baseProps,
|
||||
actions: {
|
||||
...actions,
|
||||
getTermsOfService,
|
||||
},
|
||||
};
|
||||
|
||||
const wrapper = shallow(
|
||||
<TermsOfService {...props}/>,
|
||||
{context: {intl: {formatMessage: jest.fn()}}},
|
||||
);
|
||||
expect(wrapper.state('loading')).toEqual(true);
|
||||
await getTermsOfService();
|
||||
expect(wrapper.state('loading')).toEqual(false);
|
||||
wrapper.update();
|
||||
expect(wrapper.getElement()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('should call props.navigator.setButtons on setNavigatorButtons', async () => {
|
||||
const wrapper = shallow(
|
||||
<TermsOfService {...baseProps}/>,
|
||||
{context: {intl: {formatMessage: jest.fn()}}},
|
||||
);
|
||||
wrapper.setState({loading: false, termsId: 1, termsText: 'Terms Text'});
|
||||
|
||||
expect(baseProps.navigator.setButtons).toHaveBeenCalledTimes(2);
|
||||
wrapper.instance().setNavigatorButtons(true);
|
||||
expect(baseProps.navigator.setButtons).toHaveBeenCalledTimes(3);
|
||||
wrapper.instance().setNavigatorButtons(false);
|
||||
expect(baseProps.navigator.setButtons).toHaveBeenCalledTimes(4);
|
||||
});
|
||||
|
||||
test('should enable/disable navigator buttons on setNavigatorButtons true/false', () => {
|
||||
const wrapper = shallow(
|
||||
<TermsOfService {...baseProps}/>,
|
||||
{context: {intl: {formatMessage: jest.fn()}}},
|
||||
);
|
||||
wrapper.setState({loading: false, termsId: 1, termsText: 'Terms Text'});
|
||||
|
||||
wrapper.instance().setNavigatorButtons(true);
|
||||
expect(wrapper.getElement()).toMatchSnapshot();
|
||||
wrapper.instance().setNavigatorButtons(false);
|
||||
expect(wrapper.getElement()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('should match snapshot on enableNavigatorLogout', () => {
|
||||
const wrapper = shallow(
|
||||
<TermsOfService {...baseProps}/>,
|
||||
{context: {intl: {formatMessage: jest.fn()}}},
|
||||
);
|
||||
|
||||
wrapper.setState({loading: false, termsId: 1, termsText: 'Terms Text'});
|
||||
wrapper.instance().enableNavigatorLogout();
|
||||
expect(wrapper.getElement()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('should call dismissAllModals on closeTermsAndLogout', () => {
|
||||
const wrapper = shallow(
|
||||
<TermsOfService {...baseProps}/>,
|
||||
{context: {intl: {formatMessage: jest.fn()}}},
|
||||
);
|
||||
|
||||
wrapper.setState({loading: false, termsId: 1, termsText: 'Terms Text'});
|
||||
wrapper.instance().closeTermsAndLogout();
|
||||
expect(baseProps.navigator.dismissAllModals).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
|
|
@ -120,6 +120,9 @@ export default class Thread extends PureComponent {
|
|||
statusBarHideWithNavBar: false,
|
||||
screenBackgroundColor: 'transparent',
|
||||
},
|
||||
passProps: {
|
||||
disableTermsModal: true,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -69,6 +69,9 @@ describe('thread', () => {
|
|||
statusBarHideWithNavBar: false,
|
||||
screenBackgroundColor: 'transparent',
|
||||
},
|
||||
passProps: {
|
||||
disableTermsModal: true,
|
||||
},
|
||||
};
|
||||
const newNavigator = {...navigator};
|
||||
const wrapper = shallow(
|
||||
|
|
|
|||
|
|
@ -65,6 +65,9 @@ export default class UserProfile extends PureComponent {
|
|||
statusBarHideWithNavBar: false,
|
||||
screenBackgroundColor: theme.centerChannelBg,
|
||||
},
|
||||
passProps: {
|
||||
disableTermsModal: true,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -415,6 +415,12 @@
|
|||
"mobile.share_extension.send": "Send",
|
||||
"mobile.share_extension.team": "Team",
|
||||
"mobile.suggestion.members": "Members",
|
||||
"mobile.terms_of_service.alert_cancel": "Cancel",
|
||||
"mobile.terms_of_service.alert_ok": "OK",
|
||||
"mobile.terms_of_service.alert_retry": "Try Again",
|
||||
"mobile.terms_of_service.get_terms_error_description": "Make sure you have an active internet connection and try again. If this issue persists, contact your System Administrator.",
|
||||
"mobile.terms_of_service.get_terms_error_title": "Unable to load terms of service.",
|
||||
"mobile.terms_of_service.terms_rejected": "You must agree to the terms of service before accessing {siteName}. Please contact your System Administrator for more details.",
|
||||
"mobile.timezone_settings.automatically": "Set automatically",
|
||||
"mobile.timezone_settings.manual": "Change timezone",
|
||||
"mobile.timezone_settings.select": "Select Timezone",
|
||||
|
|
@ -499,6 +505,8 @@
|
|||
"suggestion.search.direct": "Direct Messages",
|
||||
"suggestion.search.private": "Private Channels",
|
||||
"suggestion.search.public": "Public Channels",
|
||||
"terms_of_service.agreeButton": "I Agree",
|
||||
"terms_of_service.api_error": "Unable to complete the request. If this issue persists, contact your System Administrator.",
|
||||
"user.settings.display.clockDisplay": "Clock Display",
|
||||
"user.settings.display.militaryClock": "24-hour clock (example: 16:00)",
|
||||
"user.settings.display.normalClock": "12-hour clock (example: 4:00 PM)",
|
||||
|
|
|
|||
Loading…
Reference in a new issue