Improve dialog components to match linter

This commit is contained in:
Arnaud Vergnet 2020-08-03 16:28:03 +02:00
parent 3629c5730a
commit 925bded69b
5 changed files with 248 additions and 233 deletions

View file

@ -2,42 +2,43 @@
import * as React from 'react'; import * as React from 'react';
import i18n from 'i18n-js'; import i18n from 'i18n-js';
import LoadingConfirmDialog from "../Dialogs/LoadingConfirmDialog"; import {StackNavigationProp} from '@react-navigation/stack';
import ConnectionManager from "../../managers/ConnectionManager"; import LoadingConfirmDialog from '../Dialogs/LoadingConfirmDialog';
import {StackNavigationProp} from "@react-navigation/stack"; import ConnectionManager from '../../managers/ConnectionManager';
type Props = { type PropsType = {
navigation: StackNavigationProp, navigation: StackNavigationProp,
visible: boolean, visible: boolean,
onDismiss: () => void, onDismiss: () => void,
} };
class LogoutDialog extends React.PureComponent<Props> { class LogoutDialog extends React.PureComponent<PropsType> {
onClickAccept = async (): Promise<void> => {
onClickAccept = async () => { const {props} = this;
return new Promise((resolve) => { return new Promise((resolve: () => void) => {
ConnectionManager.getInstance().disconnect() ConnectionManager.getInstance()
.disconnect()
.then(() => { .then(() => {
this.props.navigation.reset({ props.navigation.reset({
index: 0, index: 0,
routes: [{name: 'main'}], routes: [{name: 'main'}],
}); });
this.props.onDismiss(); props.onDismiss();
resolve(); resolve();
}); });
}); });
}; };
render() { render(): React.Node {
const {props} = this;
return ( return (
<LoadingConfirmDialog <LoadingConfirmDialog
{...this.props} visible={props.visible}
visible={this.props.visible} onDismiss={props.onDismiss}
onDismiss={this.props.onDismiss}
onAccept={this.onClickAccept} onAccept={this.onClickAccept}
title={i18n.t("dialog.disconnect.title")} title={i18n.t('dialog.disconnect.title')}
titleLoading={i18n.t("dialog.disconnect.titleLoading")} titleLoading={i18n.t('dialog.disconnect.titleLoading')}
message={i18n.t("dialog.disconnect.message")} message={i18n.t('dialog.disconnect.message')}
/> />
); );
} }

View file

@ -2,29 +2,27 @@
import * as React from 'react'; import * as React from 'react';
import {Button, Dialog, Paragraph, Portal} from 'react-native-paper'; import {Button, Dialog, Paragraph, Portal} from 'react-native-paper';
import i18n from "i18n-js"; import i18n from 'i18n-js';
type Props = { type PropsType = {
visible: boolean, visible: boolean,
onDismiss: () => void, onDismiss: () => void,
title: string, title: string,
message: string, message: string,
} };
class AlertDialog extends React.PureComponent<Props> { class AlertDialog extends React.PureComponent<PropsType> {
render(): React.Node {
render() { const {props} = this;
return ( return (
<Portal> <Portal>
<Dialog <Dialog visible={props.visible} onDismiss={props.onDismiss}>
visible={this.props.visible} <Dialog.Title>{props.title}</Dialog.Title>
onDismiss={this.props.onDismiss}>
<Dialog.Title>{this.props.title}</Dialog.Title>
<Dialog.Content> <Dialog.Content>
<Paragraph>{this.props.message}</Paragraph> <Paragraph>{props.message}</Paragraph>
</Dialog.Content> </Dialog.Content>
<Dialog.Actions> <Dialog.Actions>
<Button onPress={this.props.onDismiss}>{i18n.t("dialog.ok")}</Button> <Button onPress={props.onDismiss}>{i18n.t('dialog.ok')}</Button>
</Dialog.Actions> </Dialog.Actions>
</Dialog> </Dialog>
</Portal> </Portal>

View file

@ -1,62 +1,69 @@
// @flow // @flow
import * as React from 'react'; import * as React from 'react';
import i18n from "i18n-js"; import i18n from 'i18n-js';
import {ERROR_TYPE} from "../../utils/WebData"; import {ERROR_TYPE} from '../../utils/WebData';
import AlertDialog from "./AlertDialog"; import AlertDialog from './AlertDialog';
type Props = { type PropsType = {
visible: boolean, visible: boolean,
onDismiss: () => void, onDismiss: () => void,
errorCode: number, errorCode: number,
} };
class ErrorDialog extends React.PureComponent<Props> {
class ErrorDialog extends React.PureComponent<PropsType> {
title: string; title: string;
message: string; message: string;
generateMessage() { generateMessage() {
this.title = i18n.t("errors.title"); const {props} = this;
switch (this.props.errorCode) { this.title = i18n.t('errors.title');
switch (props.errorCode) {
case ERROR_TYPE.BAD_CREDENTIALS: case ERROR_TYPE.BAD_CREDENTIALS:
this.message = i18n.t("errors.badCredentials"); this.message = i18n.t('errors.badCredentials');
break; break;
case ERROR_TYPE.BAD_TOKEN: case ERROR_TYPE.BAD_TOKEN:
this.message = i18n.t("errors.badToken"); this.message = i18n.t('errors.badToken');
break; break;
case ERROR_TYPE.NO_CONSENT: case ERROR_TYPE.NO_CONSENT:
this.message = i18n.t("errors.noConsent"); this.message = i18n.t('errors.noConsent');
break; break;
case ERROR_TYPE.TOKEN_SAVE: case ERROR_TYPE.TOKEN_SAVE:
this.message = i18n.t("errors.tokenSave"); this.message = i18n.t('errors.tokenSave');
break; break;
case ERROR_TYPE.TOKEN_RETRIEVE: case ERROR_TYPE.TOKEN_RETRIEVE:
this.message = i18n.t("errors.unknown"); this.message = i18n.t('errors.unknown');
break; break;
case ERROR_TYPE.BAD_INPUT: case ERROR_TYPE.BAD_INPUT:
this.message = i18n.t("errors.badInput"); this.message = i18n.t('errors.badInput');
break; break;
case ERROR_TYPE.FORBIDDEN: case ERROR_TYPE.FORBIDDEN:
this.message = i18n.t("errors.forbidden"); this.message = i18n.t('errors.forbidden');
break; break;
case ERROR_TYPE.CONNECTION_ERROR: case ERROR_TYPE.CONNECTION_ERROR:
this.message = i18n.t("errors.connectionError"); this.message = i18n.t('errors.connectionError');
break; break;
case ERROR_TYPE.SERVER_ERROR: case ERROR_TYPE.SERVER_ERROR:
this.message = i18n.t("errors.serverError"); this.message = i18n.t('errors.serverError');
break; break;
default: default:
this.message = i18n.t("errors.unknown"); this.message = i18n.t('errors.unknown');
break; break;
} }
this.message += "\n\nCode " + this.props.errorCode; this.message += `\n\nCode ${props.errorCode}`;
} }
render() { render(): React.Node {
this.generateMessage(); this.generateMessage();
const {props} = this;
return ( return (
<AlertDialog {...this.props} title={this.title} message={this.message}/> <AlertDialog
visible={props.visible}
onDismiss={props.onDismiss}
title={this.title}
message={this.message}
/>
); );
} }
} }

View file

@ -1,88 +1,102 @@
// @flow // @flow
import * as React from 'react'; import * as React from 'react';
import {ActivityIndicator, Button, Dialog, Paragraph, Portal} from 'react-native-paper'; import {
import i18n from "i18n-js"; ActivityIndicator,
Button,
Dialog,
Paragraph,
Portal,
} from 'react-native-paper';
import i18n from 'i18n-js';
type Props = { type PropsType = {
visible: boolean, visible: boolean,
onDismiss: () => void, onDismiss?: () => void,
onAccept: () => Promise<void>, // async function to be executed onAccept?: () => Promise<void>, // async function to be executed
title: string, title?: string,
titleLoading: string, titleLoading?: string,
message: string, message?: string,
startLoading: boolean, startLoading?: boolean,
}
type State = {
loading: boolean,
}
class LoadingConfirmDialog extends React.PureComponent<Props, State> {
static defaultProps = {
title: '',
message: '',
onDismiss: () => {},
onAccept: () => {return Promise.resolve()},
startLoading: false,
}
state = {
loading: this.props.startLoading,
}; };
type StateType = {
loading: boolean,
};
class LoadingConfirmDialog extends React.PureComponent<PropsType, StateType> {
static defaultProps = {
onDismiss: () => {},
onAccept: (): Promise<void> => {
return Promise.resolve();
},
title: '',
titleLoading: '',
message: '',
startLoading: false,
};
constructor(props: PropsType) {
super(props);
this.state = {
loading:
props.startLoading != null
? props.startLoading
: LoadingConfirmDialog.defaultProps.startLoading,
};
}
/** /**
* Set the dialog into loading state and closes it when operation finishes * Set the dialog into loading state and closes it when operation finishes
*/ */
onClickAccept = () => { onClickAccept = () => {
const {props} = this;
this.setState({loading: true}); this.setState({loading: true});
this.props.onAccept().then(this.hideLoading); if (props.onAccept != null) props.onAccept().then(this.hideLoading);
}; };
/** /**
* Waits for fade out animations to finish before hiding loading * Waits for fade out animations to finish before hiding loading
* @returns {TimeoutID} * @returns {TimeoutID}
*/ */
hideLoading = () => setTimeout(() => { hideLoading = (): TimeoutID =>
this.setState({loading: false}) setTimeout(() => {
this.setState({loading: false});
}, 200); }, 200);
/** /**
* Hide the dialog if it is not loading * Hide the dialog if it is not loading
*/ */
onDismiss = () => { onDismiss = () => {
if (!this.state.loading) const {state, props} = this;
this.props.onDismiss(); if (!state.loading && props.onDismiss != null) props.onDismiss();
}; };
render() { render(): React.Node {
const {state, props} = this;
return ( return (
<Portal> <Portal>
<Dialog <Dialog visible={props.visible} onDismiss={this.onDismiss}>
visible={this.props.visible}
onDismiss={this.onDismiss}>
<Dialog.Title> <Dialog.Title>
{this.state.loading {state.loading ? props.titleLoading : props.title}
? this.props.titleLoading
: this.props.title}
</Dialog.Title> </Dialog.Title>
<Dialog.Content> <Dialog.Content>
{this.state.loading {state.loading ? (
? <ActivityIndicator <ActivityIndicator animating size="large" />
animating={true} ) : (
size={'large'}/> <Paragraph>{props.message}</Paragraph>
: <Paragraph>{this.props.message}</Paragraph> )}
}
</Dialog.Content> </Dialog.Content>
{this.state.loading {state.loading ? null : (
? null <Dialog.Actions>
: <Dialog.Actions> <Button onPress={this.onDismiss} style={{marginRight: 10}}>
<Button onPress={this.onDismiss} {i18n.t('dialog.cancel')}
style={{marginRight: 10}}>{i18n.t("dialog.cancel")}</Button> </Button>
<Button onPress={this.onClickAccept}>{i18n.t("dialog.yes")}</Button> <Button onPress={this.onClickAccept}>
{i18n.t('dialog.yes')}
</Button>
</Dialog.Actions> </Dialog.Actions>
} )}
</Dialog> </Dialog>
</Portal> </Portal>
); );

View file

@ -2,49 +2,44 @@
import * as React from 'react'; import * as React from 'react';
import {Button, Dialog, Paragraph, Portal} from 'react-native-paper'; import {Button, Dialog, Paragraph, Portal} from 'react-native-paper';
import {FlatList} from "react-native"; import {FlatList} from 'react-native';
export type OptionsDialogButton = { export type OptionsDialogButtonType = {
title: string, title: string,
onPress: () => void, onPress: () => void,
} };
type Props = { type PropsType = {
visible: boolean, visible: boolean,
title: string, title: string,
message: string, message: string,
buttons: Array<OptionsDialogButton>, buttons: Array<OptionsDialogButtonType>,
onDismiss: () => void, onDismiss: () => void,
} };
class OptionsDialog extends React.PureComponent<Props> { class OptionsDialog extends React.PureComponent<PropsType> {
getButtonRender = ({item}: {item: OptionsDialogButtonType}): React.Node => {
return <Button onPress={item.onPress}>{item.title}</Button>;
};
getButtonRender = ({item}: { item: OptionsDialogButton }) => { keyExtractor = (item: OptionsDialogButtonType): string => item.title;
return <Button
onPress={item.onPress}>
{item.title}
</Button>;
}
keyExtractor = (item: OptionsDialogButton) => item.title; render(): React.Node {
const {props} = this;
render() {
return ( return (
<Portal> <Portal>
<Dialog <Dialog visible={props.visible} onDismiss={props.onDismiss}>
visible={this.props.visible} <Dialog.Title>{props.title}</Dialog.Title>
onDismiss={this.props.onDismiss}>
<Dialog.Title>{this.props.title}</Dialog.Title>
<Dialog.Content> <Dialog.Content>
<Paragraph>{this.props.message}</Paragraph> <Paragraph>{props.message}</Paragraph>
</Dialog.Content> </Dialog.Content>
<Dialog.Actions> <Dialog.Actions>
<FlatList <FlatList
data={this.props.buttons} data={props.buttons}
renderItem={this.getButtonRender} renderItem={this.getButtonRender}
keyExtractor={this.keyExtractor} keyExtractor={this.keyExtractor}
horizontal={true} horizontal
inverted={true} inverted
/> />
</Dialog.Actions> </Dialog.Actions>
</Dialog> </Dialog>