Refactor account component and complete account loading

This commit is contained in:
Paulo Gustavo Veiga 2021-02-07 09:59:45 -08:00
parent 4b1c92757f
commit 40e89a58d4
7 changed files with 72 additions and 35 deletions

View File

@ -1,11 +1,11 @@
import { useSelector } from 'react-redux'; import { useSelector } from 'react-redux';
import React from "react"; import React from "react";
import { activeInstanceStatus, ClientStatus } from '../../../redux/clientSlice'; import { activeInstanceStatus, ClientStatus } from '../../redux/clientSlice';
import { Button, Dialog, DialogActions, DialogContent, DialogTitle } from '@material-ui/core'; import { Button, Dialog, DialogActions, DialogContent, DialogTitle } from '@material-ui/core';
import { FormattedMessage } from 'react-intl'; import { FormattedMessage } from 'react-intl';
import { Alert, AlertTitle } from '@material-ui/lab'; import { Alert, AlertTitle } from '@material-ui/lab';
const ClientHealthChecker = () => { const ClientHealthSentinel = () => {
const status: ClientStatus = useSelector(activeInstanceStatus); const status: ClientStatus = useSelector(activeInstanceStatus);
const handleOnClose = () => { const handleOnClose = () => {
@ -44,4 +44,4 @@ const ClientHealthChecker = () => {
</div> </div>
) )
}; };
export default ClientHealthChecker; export default ClientHealthSentinel;

View File

@ -24,7 +24,7 @@ export type MapInfo = {
lastModificationTime: string; lastModificationTime: string;
description: string; description: string;
isPublic: boolean; isPublic: boolean;
role: 'owner' | 'editor' | 'viewer' role: 'owner' | 'editor' | 'viewer'
} }
export type ChangeHistory = { export type ChangeHistory = {
@ -48,6 +48,11 @@ export type ErrorInfo = {
fields?: Map<String, String>; fields?: Map<String, String>;
} }
export type AccountInfo = {
firstName: string;
lastName: string;
email: string;
}
interface Client { interface Client {
createMap(map: BasicMapInfo): Promise<number>; createMap(map: BasicMapInfo): Promise<number>;
@ -57,18 +62,18 @@ interface Client {
fetchAllMaps(): Promise<MapInfo[]>; fetchAllMaps(): Promise<MapInfo[]>;
duplicateMap(id: number, basicInfo: BasicMapInfo): Promise<number>; duplicateMap(id: number, basicInfo: BasicMapInfo): Promise<number>;
changeStarred(id: number, starred: boolean): Promise<void>; updateStarred(id: number, starred: boolean): Promise<void>;
updateMapToPublic(id: number, starred: boolean): Promise<void>; updateMapToPublic(id: number, starred: boolean): Promise<void>;
fetchLabels(): Promise<Label[]>; fetchLabels(): Promise<Label[]>;
// createLabel(label: Label): Promise<void>;
deleteLabel(id: number): Promise<void>; deleteLabel(id: number): Promise<void>;
fetchAccountInfo():Promise<AccountInfo>;
registerNewUser(user: NewUser): Promise<void>; registerNewUser(user: NewUser): Promise<void>;
resetPassword(email: string): Promise<void>; resetPassword(email: string): Promise<void>;
fetchHistory(id:number):Promise<ChangeHistory[]>; fetchHistory(id: number): Promise<ChangeHistory[]>;
revertHistory(id:number,cid:number): Promise<void> revertHistory(id: number, cid: number): Promise<void>
} }

View File

@ -1,4 +1,4 @@
import Client, { BasicMapInfo, ChangeHistory, Label, MapInfo, NewUser } from '..'; import Client, { AccountInfo, BasicMapInfo, ChangeHistory, Label, MapInfo, NewUser } from '..';
class MockClient implements Client { class MockClient implements Client {
private maps: MapInfo[] = []; private maps: MapInfo[] = [];
@ -34,6 +34,13 @@ class MockClient implements Client {
]; ];
} }
fetchAccountInfo(): Promise<AccountInfo> {
return Promise.resolve({
firstName: 'Costme',
lastName: 'Fulanito',
email: 'test@example.com'
});
}
deleteMaps(ids: number[]): Promise<void> { deleteMaps(ids: number[]): Promise<void> {
ids.forEach(id => this.deleteMap(id)); ids.forEach(id => this.deleteMap(id));
return Promise.resolve(); return Promise.resolve();
@ -59,7 +66,7 @@ class MockClient implements Client {
return Promise.resolve(); return Promise.resolve();
} }
changeStarred(id: number, starred: boolean): Promise<void> { updateStarred(id: number, starred: boolean): Promise<void> {
const mapInfo = this.maps.find(m => m.id == id); const mapInfo = this.maps.find(m => m.id == id);
if (!mapInfo) { if (!mapInfo) {
console.log(`Could not find the map iwth id ${id}`); console.log(`Could not find the map iwth id ${id}`);

View File

@ -1,5 +1,5 @@
import axios from 'axios'; import axios from 'axios';
import Client, { ErrorInfo, MapInfo, BasicMapInfo, NewUser, Label, ChangeHistory } from '..'; import Client, { ErrorInfo, MapInfo, BasicMapInfo, NewUser, Label, ChangeHistory, AccountInfo } from '..';
export default class RestClient implements Client { export default class RestClient implements Client {
private baseUrl: string; private baseUrl: string;
@ -10,6 +10,28 @@ export default class RestClient implements Client {
this.sessionExpired = sessionExpired; this.sessionExpired = sessionExpired;
} }
fetchAccountInfo(): Promise<AccountInfo> {
const handler = (success: (account: AccountInfo) => void, reject: (error: ErrorInfo) => void) => {
axios.get(
this.baseUrl + '/c/restful/account',
{
headers: { 'Content-Type': 'application/json' }
}
).then(response => {
const account = response.data;
success({
lastName: account.lastName,
firstName: account.fistName,
email: account.email,
});
}).catch(error => {
const errorInfo = this.parseResponseOnError(error.response);
reject(errorInfo);
});
}
return new Promise(handler);
}
deleteMaps(ids: number[]): Promise<void> { deleteMaps(ids: number[]): Promise<void> {
const handler = (success: () => void, reject: (error: ErrorInfo) => void) => { const handler = (success: () => void, reject: (error: ErrorInfo) => void) => {
axios.delete(this.baseUrl + `/c/restful/maps/batch?ids=${ids.join()}`, axios.delete(this.baseUrl + `/c/restful/maps/batch?ids=${ids.join()}`,
@ -204,7 +226,7 @@ export default class RestClient implements Client {
return new Promise(handler); return new Promise(handler);
} }
changeStarred(id: number, starred: boolean): Promise<void> { updateStarred(id: number, starred: boolean): Promise<void> {
const handler = (success: () => void, reject: (error: ErrorInfo) => void) => { const handler = (success: () => void, reject: (error: ErrorInfo) => void) => {
axios.put(this.baseUrl + `/c/restful/maps/${id}/starred`, axios.put(this.baseUrl + `/c/restful/maps/${id}/starred`,
starred, starred,
@ -220,9 +242,7 @@ export default class RestClient implements Client {
return new Promise(handler); return new Promise(handler);
} }
fetchLabels(): Promise<Label[]> { fetchLabels(): Promise<Label[]> {
const handler = (success: (labels: Label[]) => void, reject: (error: ErrorInfo) => void) => { const handler = (success: (labels: Label[]) => void, reject: (error: ErrorInfo) => void) => {
axios.get( axios.get(
this.baseUrl + '/c/restful/labels/', this.baseUrl + '/c/restful/labels/',

View File

@ -1,9 +1,18 @@
import { Button, Link, ListItemIcon, Menu, MenuItem, Tooltip } from "@material-ui/core"; import { Button, IconButton, Link, ListItemIcon, Menu, MenuItem, Tooltip } from '@material-ui/core';
import { AccountCircle, ExitToAppOutlined, SettingsApplicationsOutlined } from "@material-ui/icons"; import { AccountCircle, ExitToAppOutlined, SettingsApplicationsOutlined } from '@material-ui/icons';
import React from "react"; import React from "react";
import { FormattedMessage } from "react-intl"; import { FormattedMessage } from "react-intl";
import { useQuery, useQueryClient } from "react-query";
import Client, { ErrorInfo, AccountInfo } from "../../../client";
import { useSelector } from 'react-redux';
import { activeInstance } from '../../../redux/clientSlice';
const AccountMenu = () => { const AccountMenu = () => {
const client: Client = useSelector(activeInstance);
const queryClient = useQueryClient();
const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null); const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null);
const open = Boolean(anchorEl); const open = Boolean(anchorEl);
@ -14,15 +23,18 @@ const AccountMenu = () => {
setAnchorEl(null); setAnchorEl(null);
}; };
const { isLoading, error, data } = useQuery<unknown, ErrorInfo, AccountInfo>('account', () => {
return client.fetchAccountInfo();
});
const account = data;
return ( return (
<span> <span>
<Tooltip title="Paulo Veiga <pveiga@gmail.com>"> <Tooltip title={`${account?.firstName} ${account?.lastName} <${account?.email}>`}>
<Button <IconButton
aria-haspopup="true"
onClick={handleMenu}> onClick={handleMenu}>
<AccountCircle fontSize="large" /> <AccountCircle fontSize="large" style={{color:'black'}}/>
Paulo Veiga </IconButton >
</Button >
</Tooltip> </Tooltip>
<Menu id="appbar-profile" <Menu id="appbar-profile"
anchorEl={anchorEl} anchorEl={anchorEl}

View File

@ -19,7 +19,7 @@ import Client, { Label } from '../../client';
import ActionDispatcher from './action-dispatcher'; import ActionDispatcher from './action-dispatcher';
import { ActionType } from './action-chooser'; import { ActionType } from './action-chooser';
import AccountMenu from './account-menu'; import AccountMenu from './account-menu';
import ClientHealthSentinel from './client-health-sentinel'; import ClientHealthSentinel from '../../client/client-health-sentinel';
import HelpMenu from '../help-menu'; import HelpMenu from '../help-menu';
const logoIcon = require('../../images/logo-small.svg'); const logoIcon = require('../../images/logo-small.svg');

View File

@ -1,4 +1,4 @@
import React, { useEffect } from 'react' import React, { useEffect,CSSProperties } from 'react';
import { useStyles } from './styled'; import { useStyles } from './styled';
import Table from '@material-ui/core/Table'; import Table from '@material-ui/core/Table';
@ -16,7 +16,6 @@ import IconButton from '@material-ui/core/IconButton';
import Tooltip from '@material-ui/core/Tooltip'; import Tooltip from '@material-ui/core/Tooltip';
import StarRateRoundedIcon from '@material-ui/icons/StarRateRounded'; import StarRateRoundedIcon from '@material-ui/icons/StarRateRounded';
import MoreHorizIcon from '@material-ui/icons/MoreHoriz'; import MoreHorizIcon from '@material-ui/icons/MoreHoriz';
import { CSSProperties } from 'react';
import { useSelector } from 'react-redux'; import { useSelector } from 'react-redux';
import { activeInstance } from '../../../redux/clientSlice'; import { activeInstance } from '../../../redux/clientSlice';
import { useMutation, useQuery, useQueryClient } from 'react-query'; import { useMutation, useQuery, useQueryClient } from 'react-query';
@ -30,7 +29,6 @@ import moment from 'moment'
import { Filter, LabelFilter } from '..'; import { Filter, LabelFilter } from '..';
import { FormattedMessage, useIntl } from 'react-intl'; import { FormattedMessage, useIntl } from 'react-intl';
import { DeleteOutlined, LabelTwoTone } from '@material-ui/icons'; import { DeleteOutlined, LabelTwoTone } from '@material-ui/icons';
import Alert from '@material-ui/lab/Alert';
function descendingComparator<T>(a: T, b: T, orderBy: keyof T) { function descendingComparator<T>(a: T, b: T, orderBy: keyof T) {
@ -213,7 +211,7 @@ export const MapsList = (props: MapsListProps) => {
}, [props.filter.type, (props.filter as LabelFilter).label]); }, [props.filter.type, (props.filter as LabelFilter).label]);
const { isLoading, error, data } = useQuery<unknown, ErrorInfo, MapInfo[]>('maps', async () => { const { isLoading, data } = useQuery<unknown, ErrorInfo, MapInfo[]>('maps', async () => {
return await client.fetchAllMaps(); return await client.fetchAllMaps();
}); });
const mapsInfo: MapInfo[] = data ? data.filter(mapsFilter(filter, searchCondition)) : []; const mapsInfo: MapInfo[] = data ? data.filter(mapsFilter(filter, searchCondition)) : [];
@ -284,13 +282,13 @@ export const MapsList = (props: MapsListProps) => {
const starredMultation = useMutation<void, ErrorInfo, number>((id: number) => { const starredMultation = useMutation<void, ErrorInfo, number>((id: number) => {
const map = mapsInfo.find(m => m.id == id); const map = mapsInfo.find(m => m.id == id);
return client.changeStarred(id, !Boolean(map?.starred)); return client.updateStarred(id, !Boolean(map?.starred));
}, },
{ {
onSuccess: () => { onSuccess: () => {
queryClient.invalidateQueries('maps'); queryClient.invalidateQueries('maps');
}, },
onError: (error) => { onError: () => {
// setError(error); // setError(error);
} }
} }
@ -317,7 +315,7 @@ export const MapsList = (props: MapsListProps) => {
setSearchCondition(e.target.value); setSearchCondition(e.target.value);
} }
const handleDeleteClick = (event: React.MouseEvent<HTMLButtonElement>) => { const handleDeleteClick = () => {
setActiveDialog({ setActiveDialog({
actionType: 'delete', actionType: 'delete',
mapsId: selected mapsId: selected
@ -496,8 +494,3 @@ export const MapsList = (props: MapsListProps) => {
); );
} }
const ErrorDialog = (props) => {
return (<Alert severity="error">This is an error alert check it out!</Alert>);
}