forked from vergnet/application-amicale
Update dialogs to use TypeScript
This commit is contained in:
parent
f95635136e
commit
98518c46b6
5 changed files with 149 additions and 166 deletions
|
@ -17,36 +17,31 @@
|
||||||
* along with Campus INSAT. If not, see <https://www.gnu.org/licenses/>.
|
* along with Campus INSAT. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// @flow
|
|
||||||
|
|
||||||
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 PropsType = {
|
type PropsType = {
|
||||||
visible: boolean,
|
visible: boolean;
|
||||||
onDismiss: () => void,
|
onDismiss: () => void;
|
||||||
title: string | React.Node,
|
title: string | React.ReactNode;
|
||||||
message: string | React.Node,
|
message: string | React.ReactNode;
|
||||||
};
|
};
|
||||||
|
|
||||||
class AlertDialog extends React.PureComponent<PropsType> {
|
function AlertDialog(props: PropsType) {
|
||||||
render(): React.Node {
|
return (
|
||||||
const {props} = this;
|
<Portal>
|
||||||
return (
|
<Dialog visible={props.visible} onDismiss={props.onDismiss}>
|
||||||
<Portal>
|
<Dialog.Title>{props.title}</Dialog.Title>
|
||||||
<Dialog visible={props.visible} onDismiss={props.onDismiss}>
|
<Dialog.Content>
|
||||||
<Dialog.Title>{props.title}</Dialog.Title>
|
<Paragraph>{props.message}</Paragraph>
|
||||||
<Dialog.Content>
|
</Dialog.Content>
|
||||||
<Paragraph>{props.message}</Paragraph>
|
<Dialog.Actions>
|
||||||
</Dialog.Content>
|
<Button onPress={props.onDismiss}>{i18n.t('dialog.ok')}</Button>
|
||||||
<Dialog.Actions>
|
</Dialog.Actions>
|
||||||
<Button onPress={props.onDismiss}>{i18n.t('dialog.ok')}</Button>
|
</Dialog>
|
||||||
</Dialog.Actions>
|
</Portal>
|
||||||
</Dialog>
|
);
|
||||||
</Portal>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default AlertDialog;
|
export default AlertDialog;
|
|
@ -1,90 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2019 - 2020 Arnaud Vergnet.
|
|
||||||
*
|
|
||||||
* This file is part of Campus INSAT.
|
|
||||||
*
|
|
||||||
* Campus INSAT is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* Campus INSAT is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with Campus INSAT. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// @flow
|
|
||||||
|
|
||||||
import * as React from 'react';
|
|
||||||
import i18n from 'i18n-js';
|
|
||||||
import {ERROR_TYPE} from '../../utils/WebData';
|
|
||||||
import AlertDialog from './AlertDialog';
|
|
||||||
|
|
||||||
type PropsType = {
|
|
||||||
visible: boolean,
|
|
||||||
onDismiss: () => void,
|
|
||||||
errorCode: number,
|
|
||||||
};
|
|
||||||
|
|
||||||
class ErrorDialog extends React.PureComponent<PropsType> {
|
|
||||||
title: string;
|
|
||||||
|
|
||||||
message: string;
|
|
||||||
|
|
||||||
generateMessage() {
|
|
||||||
const {props} = this;
|
|
||||||
this.title = i18n.t('errors.title');
|
|
||||||
switch (props.errorCode) {
|
|
||||||
case ERROR_TYPE.BAD_CREDENTIALS:
|
|
||||||
this.message = i18n.t('errors.badCredentials');
|
|
||||||
break;
|
|
||||||
case ERROR_TYPE.BAD_TOKEN:
|
|
||||||
this.message = i18n.t('errors.badToken');
|
|
||||||
break;
|
|
||||||
case ERROR_TYPE.NO_CONSENT:
|
|
||||||
this.message = i18n.t('errors.noConsent');
|
|
||||||
break;
|
|
||||||
case ERROR_TYPE.TOKEN_SAVE:
|
|
||||||
this.message = i18n.t('errors.tokenSave');
|
|
||||||
break;
|
|
||||||
case ERROR_TYPE.TOKEN_RETRIEVE:
|
|
||||||
this.message = i18n.t('errors.unknown');
|
|
||||||
break;
|
|
||||||
case ERROR_TYPE.BAD_INPUT:
|
|
||||||
this.message = i18n.t('errors.badInput');
|
|
||||||
break;
|
|
||||||
case ERROR_TYPE.FORBIDDEN:
|
|
||||||
this.message = i18n.t('errors.forbidden');
|
|
||||||
break;
|
|
||||||
case ERROR_TYPE.CONNECTION_ERROR:
|
|
||||||
this.message = i18n.t('errors.connectionError');
|
|
||||||
break;
|
|
||||||
case ERROR_TYPE.SERVER_ERROR:
|
|
||||||
this.message = i18n.t('errors.serverError');
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
this.message = i18n.t('errors.unknown');
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
this.message += `\n\nCode ${props.errorCode}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
render(): React.Node {
|
|
||||||
this.generateMessage();
|
|
||||||
const {props} = this;
|
|
||||||
return (
|
|
||||||
<AlertDialog
|
|
||||||
visible={props.visible}
|
|
||||||
onDismiss={props.onDismiss}
|
|
||||||
title={this.title}
|
|
||||||
message={this.message}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default ErrorDialog;
|
|
80
src/components/Dialogs/ErrorDialog.tsx
Normal file
80
src/components/Dialogs/ErrorDialog.tsx
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2019 - 2020 Arnaud Vergnet.
|
||||||
|
*
|
||||||
|
* This file is part of Campus INSAT.
|
||||||
|
*
|
||||||
|
* Campus INSAT is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Campus INSAT is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with Campus INSAT. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import * as React from 'react';
|
||||||
|
import i18n from 'i18n-js';
|
||||||
|
import {ERROR_TYPE} from '../../utils/WebData';
|
||||||
|
import AlertDialog from './AlertDialog';
|
||||||
|
|
||||||
|
type PropsType = {
|
||||||
|
visible: boolean;
|
||||||
|
onDismiss: () => void;
|
||||||
|
errorCode: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
function ErrorDialog(props: PropsType) {
|
||||||
|
let title: string;
|
||||||
|
let message: string;
|
||||||
|
|
||||||
|
title = i18n.t('errors.title');
|
||||||
|
switch (props.errorCode) {
|
||||||
|
case ERROR_TYPE.BAD_CREDENTIALS:
|
||||||
|
message = i18n.t('errors.badCredentials');
|
||||||
|
break;
|
||||||
|
case ERROR_TYPE.BAD_TOKEN:
|
||||||
|
message = i18n.t('errors.badToken');
|
||||||
|
break;
|
||||||
|
case ERROR_TYPE.NO_CONSENT:
|
||||||
|
message = i18n.t('errors.noConsent');
|
||||||
|
break;
|
||||||
|
case ERROR_TYPE.TOKEN_SAVE:
|
||||||
|
message = i18n.t('errors.tokenSave');
|
||||||
|
break;
|
||||||
|
case ERROR_TYPE.TOKEN_RETRIEVE:
|
||||||
|
message = i18n.t('errors.unknown');
|
||||||
|
break;
|
||||||
|
case ERROR_TYPE.BAD_INPUT:
|
||||||
|
message = i18n.t('errors.badInput');
|
||||||
|
break;
|
||||||
|
case ERROR_TYPE.FORBIDDEN:
|
||||||
|
message = i18n.t('errors.forbidden');
|
||||||
|
break;
|
||||||
|
case ERROR_TYPE.CONNECTION_ERROR:
|
||||||
|
message = i18n.t('errors.connectionError');
|
||||||
|
break;
|
||||||
|
case ERROR_TYPE.SERVER_ERROR:
|
||||||
|
message = i18n.t('errors.serverError');
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
message = i18n.t('errors.unknown');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
message += `\n\nCode ${props.errorCode}`;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<AlertDialog
|
||||||
|
visible={props.visible}
|
||||||
|
onDismiss={props.onDismiss}
|
||||||
|
title={title}
|
||||||
|
message={message}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ErrorDialog;
|
|
@ -17,8 +17,6 @@
|
||||||
* along with Campus INSAT. If not, see <https://www.gnu.org/licenses/>.
|
* along with Campus INSAT. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// @flow
|
|
||||||
|
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import {
|
import {
|
||||||
ActivityIndicator,
|
ActivityIndicator,
|
||||||
|
@ -30,20 +28,23 @@ import {
|
||||||
import i18n from 'i18n-js';
|
import i18n from 'i18n-js';
|
||||||
|
|
||||||
type PropsType = {
|
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 StateType = {
|
type StateType = {
|
||||||
loading: boolean,
|
loading: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
class LoadingConfirmDialog extends React.PureComponent<PropsType, StateType> {
|
export default class LoadingConfirmDialog extends React.PureComponent<
|
||||||
|
PropsType,
|
||||||
|
StateType
|
||||||
|
> {
|
||||||
static defaultProps = {
|
static defaultProps = {
|
||||||
onDismiss: () => {},
|
onDismiss: () => {},
|
||||||
onAccept: (): Promise<void> => {
|
onAccept: (): Promise<void> => {
|
||||||
|
@ -71,14 +72,16 @@ class LoadingConfirmDialog extends React.PureComponent<PropsType, StateType> {
|
||||||
onClickAccept = () => {
|
onClickAccept = () => {
|
||||||
const {props} = this;
|
const {props} = this;
|
||||||
this.setState({loading: true});
|
this.setState({loading: true});
|
||||||
if (props.onAccept != null) 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 {NodeJS.Timeout}
|
||||||
*/
|
*/
|
||||||
hideLoading = (): TimeoutID =>
|
hideLoading = (): NodeJS.Timeout =>
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.setState({loading: false});
|
this.setState({loading: false});
|
||||||
}, 200);
|
}, 200);
|
||||||
|
@ -88,10 +91,12 @@ class LoadingConfirmDialog extends React.PureComponent<PropsType, StateType> {
|
||||||
*/
|
*/
|
||||||
onDismiss = () => {
|
onDismiss = () => {
|
||||||
const {state, props} = this;
|
const {state, props} = this;
|
||||||
if (!state.loading && props.onDismiss != null) props.onDismiss();
|
if (!state.loading && props.onDismiss != null) {
|
||||||
|
props.onDismiss();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
render(): React.Node {
|
render() {
|
||||||
const {state, props} = this;
|
const {state, props} = this;
|
||||||
return (
|
return (
|
||||||
<Portal>
|
<Portal>
|
||||||
|
@ -121,5 +126,3 @@ class LoadingConfirmDialog extends React.PureComponent<PropsType, StateType> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default LoadingConfirmDialog;
|
|
|
@ -17,28 +17,26 @@
|
||||||
* along with Campus INSAT. If not, see <https://www.gnu.org/licenses/>.
|
* along with Campus INSAT. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// @flow
|
|
||||||
|
|
||||||
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 OptionsDialogButtonType = {
|
export type OptionsDialogButtonType = {
|
||||||
title: string,
|
title: string;
|
||||||
icon?: string,
|
icon?: string;
|
||||||
onPress: () => void,
|
onPress: () => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
type PropsType = {
|
type PropsType = {
|
||||||
visible: boolean,
|
visible: boolean;
|
||||||
title: string,
|
title: string;
|
||||||
message: string,
|
message: string;
|
||||||
buttons: Array<OptionsDialogButtonType>,
|
buttons: Array<OptionsDialogButtonType>;
|
||||||
onDismiss: () => void,
|
onDismiss: () => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
class OptionsDialog extends React.PureComponent<PropsType> {
|
function OptionsDialog(props: PropsType) {
|
||||||
getButtonRender = ({item}: {item: OptionsDialogButtonType}): React.Node => {
|
const getButtonRender = ({item}: {item: OptionsDialogButtonType}) => {
|
||||||
return (
|
return (
|
||||||
<Button onPress={item.onPress} icon={item.icon}>
|
<Button onPress={item.onPress} icon={item.icon}>
|
||||||
{item.title}
|
{item.title}
|
||||||
|
@ -46,35 +44,32 @@ class OptionsDialog extends React.PureComponent<PropsType> {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
keyExtractor = (item: OptionsDialogButtonType): string => {
|
const keyExtractor = (item: OptionsDialogButtonType): string => {
|
||||||
if (item.icon != null) {
|
if (item.icon != null) {
|
||||||
return item.title + item.icon;
|
return item.title + item.icon;
|
||||||
}
|
}
|
||||||
return item.title;
|
return item.title;
|
||||||
};
|
};
|
||||||
|
|
||||||
render(): React.Node {
|
return (
|
||||||
const {props} = this;
|
<Portal>
|
||||||
return (
|
<Dialog visible={props.visible} onDismiss={props.onDismiss}>
|
||||||
<Portal>
|
<Dialog.Title>{props.title}</Dialog.Title>
|
||||||
<Dialog visible={props.visible} onDismiss={props.onDismiss}>
|
<Dialog.Content>
|
||||||
<Dialog.Title>{props.title}</Dialog.Title>
|
<Paragraph>{props.message}</Paragraph>
|
||||||
<Dialog.Content>
|
</Dialog.Content>
|
||||||
<Paragraph>{props.message}</Paragraph>
|
<Dialog.Actions>
|
||||||
</Dialog.Content>
|
<FlatList
|
||||||
<Dialog.Actions>
|
data={props.buttons}
|
||||||
<FlatList
|
renderItem={getButtonRender}
|
||||||
data={props.buttons}
|
keyExtractor={keyExtractor}
|
||||||
renderItem={this.getButtonRender}
|
horizontal
|
||||||
keyExtractor={this.keyExtractor}
|
inverted
|
||||||
horizontal
|
/>
|
||||||
inverted
|
</Dialog.Actions>
|
||||||
/>
|
</Dialog>
|
||||||
</Dialog.Actions>
|
</Portal>
|
||||||
</Dialog>
|
);
|
||||||
</Portal>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default OptionsDialog;
|
export default OptionsDialog;
|
Loading…
Reference in a new issue