forked from vergnet/application-amicale
Created a loading dialog component to handle async requests
This commit is contained in:
parent
0b85b1630c
commit
b2891ddeea
4 changed files with 167 additions and 82 deletions
|
@ -1,9 +1,9 @@
|
|||
// @flow
|
||||
|
||||
import * as React from 'react';
|
||||
import {ActivityIndicator, Button, Dialog, Paragraph, Portal, withTheme} from 'react-native-paper';
|
||||
import ConnectionManager from "../../managers/ConnectionManager";
|
||||
import i18n from 'i18n-js';
|
||||
import LoadingConfirmDialog from "../Custom/LoadingConfirmDialog";
|
||||
import ConnectionManager from "../../managers/ConnectionManager";
|
||||
|
||||
type Props = {
|
||||
navigation: Object,
|
||||
|
@ -11,73 +11,35 @@ type Props = {
|
|||
onDismiss: Function,
|
||||
}
|
||||
|
||||
type State = {
|
||||
loading: boolean,
|
||||
}
|
||||
class LogoutDialog extends React.PureComponent<Props> {
|
||||
|
||||
class LogoutDialog extends React.PureComponent<Props, State> {
|
||||
|
||||
colors: Object;
|
||||
|
||||
state = {
|
||||
loading: false,
|
||||
};
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.colors = props.theme.colors;
|
||||
}
|
||||
|
||||
onClickAccept = () => {
|
||||
this.setState({loading: true});
|
||||
ConnectionManager.getInstance().disconnect()
|
||||
.then(() => {
|
||||
this.props.onDismiss();
|
||||
this.setState({loading: false});
|
||||
this.props.navigation.reset({
|
||||
index: 0,
|
||||
routes: [{name: 'Main'}],
|
||||
onClickAccept = async () => {
|
||||
return new Promise((resolve, reject) => {
|
||||
ConnectionManager.getInstance().disconnect()
|
||||
.then(() => {
|
||||
this.props.navigation.reset({
|
||||
index: 0,
|
||||
routes: [{name: 'Main'}],
|
||||
});
|
||||
this.props.onDismiss();
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
onDismiss = () => {
|
||||
if (!this.state.loading)
|
||||
this.props.onDismiss();
|
||||
});
|
||||
};
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Portal>
|
||||
<Dialog
|
||||
visible={this.props.visible}
|
||||
onDismiss={this.onDismiss}>
|
||||
<Dialog.Title>
|
||||
{this.state.loading
|
||||
? i18n.t("dialog.disconnect.titleLoading")
|
||||
: i18n.t("dialog.disconnect.title")}
|
||||
</Dialog.Title>
|
||||
<Dialog.Content>
|
||||
{this.state.loading
|
||||
? <ActivityIndicator
|
||||
animating={true}
|
||||
size={'large'}
|
||||
color={this.colors.primary}/>
|
||||
: <Paragraph>{i18n.t("dialog.disconnect.message")}</Paragraph>
|
||||
}
|
||||
</Dialog.Content>
|
||||
{this.state.loading
|
||||
? null
|
||||
: <Dialog.Actions>
|
||||
<Button onPress={this.onDismiss} style={{marginRight: 10}}>{i18n.t("dialog.cancel")}</Button>
|
||||
<Button onPress={this.onClickAccept}>{i18n.t("dialog.yes")}</Button>
|
||||
</Dialog.Actions>
|
||||
}
|
||||
|
||||
</Dialog>
|
||||
</Portal>
|
||||
<LoadingConfirmDialog
|
||||
{...this.props}
|
||||
visible={this.props.visible}
|
||||
onDismiss={this.props.onDismiss}
|
||||
onAccept={this.onClickAccept}
|
||||
title={i18n.t("dialog.disconnect.title")}
|
||||
titleLoading={i18n.t("dialog.disconnect.titleLoading")}
|
||||
message={i18n.t("dialog.disconnect.message")}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default withTheme(LogoutDialog);
|
||||
export default LogoutDialog;
|
||||
|
|
74
src/components/Custom/LoadingConfirmDialog.js
Normal file
74
src/components/Custom/LoadingConfirmDialog.js
Normal file
|
@ -0,0 +1,74 @@
|
|||
import * as React from 'react';
|
||||
import {ActivityIndicator, Button, Dialog, Paragraph, Portal} from 'react-native-paper';
|
||||
import i18n from "i18n-js";
|
||||
|
||||
type Props = {
|
||||
visible: boolean,
|
||||
onDismiss: Function,
|
||||
onAccept: Function, // async function to be executed
|
||||
title: string,
|
||||
titleLoading: string,
|
||||
message: string,
|
||||
}
|
||||
|
||||
type State = {
|
||||
loading: boolean,
|
||||
}
|
||||
|
||||
class LoadingConfirmDialog extends React.PureComponent<Props, State> {
|
||||
|
||||
state = {
|
||||
loading: false,
|
||||
};
|
||||
|
||||
onClickAccept = () => {
|
||||
this.setState({loading: true});
|
||||
this.props.onAccept()
|
||||
.then(() => {
|
||||
//Wait for fade out animations to finish before hiding loading
|
||||
setTimeout(() => {
|
||||
this.setState({loading: false})
|
||||
}, 200);
|
||||
|
||||
});
|
||||
};
|
||||
|
||||
onDismiss = () => {
|
||||
if (!this.state.loading)
|
||||
this.props.onDismiss();
|
||||
};
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Portal>
|
||||
<Dialog
|
||||
visible={this.props.visible}
|
||||
onDismiss={this.onDismiss}>
|
||||
<Dialog.Title>
|
||||
{this.state.loading
|
||||
? this.props.titleLoading
|
||||
: this.props.title}
|
||||
</Dialog.Title>
|
||||
<Dialog.Content>
|
||||
{this.state.loading
|
||||
? <ActivityIndicator
|
||||
animating={true}
|
||||
size={'large'}/>
|
||||
: <Paragraph>{this.props.message}</Paragraph>
|
||||
}
|
||||
</Dialog.Content>
|
||||
{this.state.loading
|
||||
? null
|
||||
: <Dialog.Actions>
|
||||
<Button onPress={this.onDismiss}
|
||||
style={{marginRight: 10}}>{i18n.t("dialog.cancel")}</Button>
|
||||
<Button onPress={this.onClickAccept}>{i18n.t("dialog.yes")}</Button>
|
||||
</Dialog.Actions>
|
||||
}
|
||||
</Dialog>
|
||||
</Portal>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default LoadingConfirmDialog;
|
|
@ -182,16 +182,31 @@ export default class ConnectionManager {
|
|||
return valid;
|
||||
}
|
||||
|
||||
async authenticatedRequest(path: string) {
|
||||
generatePostArguments(keys: Array<string>, values: Array<string>) {
|
||||
let data = {};
|
||||
for (let i = 0; i < keys.length; i++) {
|
||||
data[keys[i]] = values[i];
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
async authenticatedRequest(path: string, keys: Array<string>, values: Array<any>) {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (this.getToken() !== null) {
|
||||
let data = {};
|
||||
if (keys !== undefined && values !== undefined && keys.length === values.length)
|
||||
data = this.generatePostArguments(keys, values);
|
||||
console.log(data);
|
||||
fetch(API_ENDPOINT + path, {
|
||||
method: 'POST',
|
||||
headers: new Headers({
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
}),
|
||||
body: JSON.stringify({token: this.getToken()})
|
||||
body: JSON.stringify({
|
||||
token: this.getToken(),
|
||||
...data
|
||||
})
|
||||
}).then(async (response) => response.json())
|
||||
.then((response: response_format) => {
|
||||
console.log(response);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// @flow
|
||||
|
||||
import * as React from 'react';
|
||||
import {FlatList, StyleSheet} from "react-native";
|
||||
import {FlatList, StyleSheet, View} from "react-native";
|
||||
import {
|
||||
ActivityIndicator,
|
||||
Avatar,
|
||||
|
@ -16,19 +16,16 @@ import {
|
|||
} from 'react-native-paper';
|
||||
import AuthenticatedScreen from "../../components/Amicale/AuthenticatedScreen";
|
||||
import {getTimeOnlyString, stringToDate} from "../../utils/Planning";
|
||||
import LoadingConfirmDialog from "../../components/Custom/LoadingConfirmDialog";
|
||||
import ConnectionManager from "../../managers/ConnectionManager";
|
||||
|
||||
const ICON_AMICALE = require('../../../assets/amicale.png');
|
||||
|
||||
type Props = {
|
||||
navigation: Object,
|
||||
theme: Object,
|
||||
}
|
||||
|
||||
const FAKE_DATE = {
|
||||
"date_begin": "2020-04-06 21:50",
|
||||
"date_end": "2020-04-06 21:50",
|
||||
"date_result_begin": "2020-04-06 21:50",
|
||||
"date_result_end": "2020-04-06 21:50",
|
||||
"date_end": "2020-04-07 23:50",
|
||||
"date_result_begin": "2020-04-07 21:50",
|
||||
"date_result_end": "2020-04-07 21:50",
|
||||
};
|
||||
|
||||
const FAKE_DATE2 = {
|
||||
|
@ -67,14 +64,21 @@ const FAKE_TEAMS2 = {
|
|||
],
|
||||
};
|
||||
|
||||
type Props = {
|
||||
navigation: Object,
|
||||
theme: Object,
|
||||
}
|
||||
|
||||
type State = {
|
||||
selectedTeam: string,
|
||||
voteDialogVisible: boolean,
|
||||
}
|
||||
|
||||
class VoteScreen extends React.Component<Props, State> {
|
||||
|
||||
state = {
|
||||
selectedTeam: "none",
|
||||
voteDialogVisible: false,
|
||||
};
|
||||
|
||||
colors: Object;
|
||||
|
@ -120,18 +124,48 @@ class VoteScreen extends React.Component<Props, State> {
|
|||
}
|
||||
this.datesString = data[1];
|
||||
this.generateDateObject();
|
||||
console.log(this.teams);
|
||||
console.log(this.datesString);
|
||||
return (
|
||||
//$FlowFixMe
|
||||
<FlatList
|
||||
data={this.mainFlatListData}
|
||||
extraData={this.state.selectedTeam}
|
||||
renderItem={this.mainRenderItem}
|
||||
/>
|
||||
<View>
|
||||
{/*$FlowFixMe*/}
|
||||
<FlatList
|
||||
data={this.mainFlatListData}
|
||||
extraData={this.state.selectedTeam}
|
||||
renderItem={this.mainRenderItem}
|
||||
/>
|
||||
<LoadingConfirmDialog
|
||||
{...this.props}
|
||||
visible={this.state.voteDialogVisible}
|
||||
onDismiss={this.onVoteDialogDismiss}
|
||||
onAccept={this.onVoteDialogAccept}
|
||||
title={"VOTE?"}
|
||||
titleLoading={"SENDING VOTE..."}
|
||||
message={"SURE?"}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
onVoteDialogDismiss = () => this.setState({voteDialogVisible: false});
|
||||
|
||||
showVoteDialog = () => this.setState({voteDialogVisible: true});
|
||||
|
||||
onVoteDialogAccept = async () => {
|
||||
return new Promise((resolve, reject) => {
|
||||
ConnectionManager.getInstance().authenticatedRequest(
|
||||
"elections/vote",
|
||||
["vote"],
|
||||
[parseInt(this.state.selectedTeam)])
|
||||
.then(() => {
|
||||
this.onVoteDialogDismiss();
|
||||
resolve();
|
||||
})
|
||||
.catch(() => {
|
||||
this.onVoteDialogDismiss();
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
generateDateObject() {
|
||||
this.dates = {
|
||||
date_begin: stringToDate(this.datesString.date_begin),
|
||||
|
@ -208,7 +242,7 @@ class VoteScreen extends React.Component<Props, State> {
|
|||
};
|
||||
|
||||
onVotePress = () => {
|
||||
console.log("vote sent");
|
||||
this.showVoteDialog();
|
||||
};
|
||||
|
||||
voteKeyExtractor = (item: Object) => item.id.toString();
|
||||
|
|
Loading…
Reference in a new issue