Add label calor support

This commit is contained in:
Paulo Gustavo Veiga 2021-02-04 17:40:41 -08:00
parent 858050096f
commit 9596852c90
5 changed files with 86 additions and 58 deletions

View File

@ -6,11 +6,19 @@ export type NewUser = {
recaptcha: string | null; recaptcha: string | null;
} }
export type Label = {
id: number;
title: string;
color: string;
iconName: string;
}
export type MapInfo = { export type MapInfo = {
id: number; id: number;
starred: boolean; starred: boolean;
title: string; title: string;
labels: string[]; labels: number[];
creator: string; creator: string;
modified: string; modified: string;
description: string; description: string;
@ -41,16 +49,17 @@ export type ErrorInfo = {
interface Client { interface Client {
createMap(map: BasicMapInfo): Promise<number>; createMap(map: BasicMapInfo): Promise<number>;
deleteLabel(label: string): Promise<void>;
registerNewUser(user: NewUser): Promise<void>; registerNewUser(user: NewUser): Promise<void>;
resetPassword(email: string): Promise<void>; resetPassword(email: string): Promise<void>;
fetchAllMaps(): Promise<MapInfo[]>; fetchAllMaps(): Promise<MapInfo[]>;
fetchLabels(): Promise<string[]>;
deleteMap(id: number): Promise<void>; deleteMap(id: number): Promise<void>;
renameMap(id: number, basicInfo: BasicMapInfo): Promise<void>; renameMap(id: number, basicInfo: BasicMapInfo): Promise<void>;
duplicateMap(id: number, basicInfo: BasicMapInfo): Promise<number>; duplicateMap(id: number, basicInfo: BasicMapInfo): Promise<number>;
loadMapInfo(id: number): Promise<BasicMapInfo>; loadMapInfo(id: number): Promise<BasicMapInfo>;
changeStarred(id: number, starred: boolean): Promise<void>; changeStarred(id: number, starred: boolean): Promise<void>;
fetchLabels(): Promise<Label[]>;
deleteLabel(id: number): Promise<void>;
} }

View File

@ -1,8 +1,8 @@
import Client, { BasicMapInfo, MapInfo, NewUser } from '..'; import Client, { BasicMapInfo, Label, MapInfo, NewUser } from '..';
class MockClient implements Client { class MockClient implements Client {
private maps: MapInfo[] = []; private maps: MapInfo[] = [];
private labels: string[] = []; private labels: Label[] = [];
constructor() { constructor() {
@ -11,7 +11,7 @@ class MockClient implements Client {
id: number, id: number,
starred: boolean, starred: boolean,
title: string, title: string,
labels: string[], labels: number[],
creator: string, creator: string,
modified: string, modified: string,
description: string, description: string,
@ -20,21 +20,24 @@ class MockClient implements Client {
return { id, title, labels, creator, modified, starred, description, isPublic }; return { id, title, labels, creator, modified, starred, description, isPublic };
} }
this.maps = [ this.maps = [
createMapInfo(1, true, "El Mapa", [""], "Paulo", "2008-06-02T00:00:00Z", "", true), createMapInfo(1, true, "El Mapa", [], "Paulo", "2008-06-02T00:00:00Z", "", true),
createMapInfo(2, false, "El Mapa2", [""], "Paulo2", "2008-06-02T00:00:00Z", "", false), createMapInfo(2, false, "El Mapa2", [], "Paulo2", "2008-06-02T00:00:00Z", "", false),
createMapInfo(3, false, "El Mapa3", [""], "Paulo3", "2008-06-02T00:00:00Z", "", false), createMapInfo(3, false, "El Mapa3", [], "Paulo3", "2008-06-02T00:00:00Z", "", false),
createMapInfo(4, false, "El Mapa3", [""], "Paulo3", "2008-06-02T00:00:00Z", "", false), createMapInfo(4, false, "El Mapa3", [], "Paulo3", "2008-06-02T00:00:00Z", "", false),
createMapInfo(5, false, "El Mapa3", [""], "Paulo3", "2008-06-02T00:00:00Z", "", false), createMapInfo(5, false, "El Mapa3", [], "Paulo3", "2008-06-02T00:00:00Z", "", false),
createMapInfo(6, false, "El Mapa3", [""], "Paulo3", "2008-06-02T00:00:00Z", "", false), createMapInfo(6, false, "El Mapa3", [], "Paulo3", "2008-06-02T00:00:00Z", "", false),
createMapInfo(7, false, "El Mapa3", [""], "Paulo3", "2008-06-02T00:00:00Z", "", false), createMapInfo(7, false, "El Mapa3", [], "Paulo3", "2008-06-02T00:00:00Z", "", false),
createMapInfo(8, false, "El Mapa3", [""], "Paulo3", "2008-06-02T00:00:00Z", "", false), createMapInfo(8, false, "El Mapa3", [], "Paulo3", "2008-06-02T00:00:00Z", "", false),
createMapInfo(9, false, "El Mapa3", [""], "Paulo3", "2008-06-02T00:00:00Z", "", false), createMapInfo(9, false, "El Mapa3", [], "Paulo3", "2008-06-02T00:00:00Z", "", false),
createMapInfo(10, false, "El Mapa3", [""], "Paulo3", "2008-06-02T00:00:00Z", "", false), createMapInfo(10, false, "El Mapa3", [], "Paulo3", "2008-06-02T00:00:00Z", "", false),
createMapInfo(11, false, "El Mapa3", ["label 3", "label3"], "Paulo3", "2008-06-02T00:00:00Z", "", false), createMapInfo(11, false, "El Mapa3", [1, 2, 3], "Paulo3", "2008-06-02T00:00:00Z", "", false),
createMapInfo(12, false, "El Mapa3", ["label 2"], "Paulo3", "2008-06-02T00:00:00Z", "", false) createMapInfo(12, false, "El Mapa3", [1, 2, 3], "Paulo3", "2008-06-02T00:00:00Z", "", false)
]; ];
this.labels = ["label 1,", "label 2", "label 3"]; this.labels = [
{ id: 1, title: "Red Label", iconName: "", color: 'red' },
{ id: 1, title: "Blue Label", iconName: "", color: 'blue' }
];
} }
@ -42,7 +45,7 @@ class MockClient implements Client {
throw new Error("Method not implemented."); throw new Error("Method not implemented.");
} }
fetchLabels(): Promise<string[]> { fetchLabels(): Promise<Label[]> {
console.log("Fetching labels from server") console.log("Fetching labels from server")
return Promise.resolve(this.labels); return Promise.resolve(this.labels);
} }
@ -63,10 +66,6 @@ class MockClient implements Client {
return Promise.resolve({ title: 'My Map', description: 'My Description' }); return Promise.resolve({ title: 'My Map', description: 'My Description' });
} }
fetchLabes(id: number): Promise<BasicMapInfo> {
return Promise.resolve({ title: 'My Map', description: 'My Description' });
}
renameMap(id: number, basicInfo: BasicMapInfo): Promise<void> { renameMap(id: number, basicInfo: BasicMapInfo): Promise<void> {
const exists = this.maps.find(m => m.title == basicInfo.title) != undefined; const exists = this.maps.find(m => m.title == basicInfo.title) != undefined;
@ -121,9 +120,9 @@ class MockClient implements Client {
}; };
} }
deleteLabel(label: string): Promise<void> { deleteLabel(id: number): Promise<void> {
this.labels = this.labels.filter(l => l != label); this.labels = this.labels.filter(l => l.id != id);
console.log("Label delete:" + label); console.log("Label delete:" + this.labels);
return Promise.resolve(); return Promise.resolve();
} }

View File

@ -1,5 +1,5 @@
import axios from 'axios'; import axios from 'axios';
import { ErrorInfo, MapInfo, BasicMapInfo, NewUser } from '..'; import { ErrorInfo, MapInfo, BasicMapInfo, NewUser, Label } from '..';
import MockClient from '../mock-client/'; import MockClient from '../mock-client/';
//@Remove inheritance once is it completed. //@Remove inheritance once is it completed.
@ -196,5 +196,10 @@ export default class RestClient extends MockClient {
} }
return new Promise(handler); return new Promise(handler);
} }
deleteLabel(id: number): Promise<void> {
console.log("Fetching labels from server")
return Promise.resolve();
}
} }

View File

@ -8,14 +8,14 @@ import IconButton from '@material-ui/core/IconButton';
import ListItem from '@material-ui/core/ListItem'; import ListItem from '@material-ui/core/ListItem';
import ListItemIcon from '@material-ui/core/ListItemIcon'; import ListItemIcon from '@material-ui/core/ListItemIcon';
import { useStyles } from './style'; import { useStyles } from './style';
import { AccountCircle, AddCircleTwoTone, CloudUploadTwoTone, DeleteOutlineTwoTone, EmailOutlined, EmojiPeopleOutlined, ExitToAppOutlined, FeedbackOutlined, Help, PolicyOutlined, PublicTwoTone, SettingsApplicationsOutlined } from '@material-ui/icons'; import { AccountCircle, AcUnitTwoTone, AddCircleTwoTone, CloudUploadTwoTone, DeleteOutlineTwoTone, EmailOutlined, EmojiPeopleOutlined, ExitToAppOutlined, FeedbackOutlined, Help, LabelTwoTone, PeopleAltTwoTone, PersonAddTwoTone, PersonOutlineTwoTone, PersonTwoTone, PolicyOutlined, PublicTwoTone, SettingsApplicationsOutlined, ShareTwoTone, StarTwoTone } from '@material-ui/icons';
import { Button, Link, ListItemSecondaryAction, ListItemText, Menu, MenuItem, Tooltip } from '@material-ui/core'; import { Button, Link, ListItemSecondaryAction, ListItemText, Menu, MenuItem, Tooltip } from '@material-ui/core';
import { MapsList } from './maps-list'; import { MapsList } from './maps-list';
import { FormattedMessage } from 'react-intl'; import { FormattedMessage } from 'react-intl';
import { useQuery, useMutation, useQueryClient } from 'react-query'; import { useQuery, useMutation, useQueryClient } from 'react-query';
import { activeInstance } from '../../reducers/serviceSlice'; import { activeInstance } from '../../reducers/serviceSlice';
import { useSelector } from 'react-redux'; import { useSelector } from 'react-redux';
import Client from '../../client'; 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';
@ -30,12 +30,13 @@ export interface GenericFilter {
export interface LabelFilter { export interface LabelFilter {
type: 'label', type: 'label',
label: string label: Label
} }
interface ToolbarButtonInfo { interface ToolbarButtonInfo {
filter: GenericFilter | LabelFilter, filter: GenericFilter | LabelFilter,
label: string label: string
icon: any;
} }
const MapsPage = () => { const MapsPage = () => {
@ -52,7 +53,7 @@ const MapsPage = () => {
const mutation = useMutation( const mutation = useMutation(
(label: string) => client.deleteLabel(label), (id: number) => client.deleteLabel(id),
{ {
onSuccess: () => queryClient.invalidateQueries('labels') onSuccess: () => queryClient.invalidateQueries('labels')
} }
@ -64,34 +65,44 @@ const MapsPage = () => {
setFilter(filter); setFilter(filter);
}; };
const handleLabelDelete = (label: string) => { const handleLabelDelete = (id: number) => {
mutation.mutate(label); mutation.mutate(id);
}; };
const { data } = useQuery<unknown, ErrorInfo, string[]>('labels', async () => { const { data } = useQuery<unknown, ErrorInfo, Label[]>('labels', async () => {
return await client.fetchLabels(); return await client.fetchLabels();
}); });
const labels: string[] = data ? data : []; const labels: Label[] = data ? data : [];
const filterButtons: ToolbarButtonInfo[] = [{ const filterButtons: ToolbarButtonInfo[] = [{
filter: { type: 'all' }, filter: { type: 'all' },
label: 'All' label: 'All',
icon: <AcUnitTwoTone color="secondary" />
}, { }, {
filter: { type: 'owned' }, filter: { type: 'owned' },
label: 'Owned' label: 'Owned',
icon: <PersonOutlineTwoTone color="secondary" />
}, { }, {
filter: { type: 'starred' }, filter: { type: 'starred' },
label: 'Starred' label: 'Starred',
icon: <StarTwoTone color="secondary" />
}, { }, {
filter: { type: 'shared' }, filter: { type: 'shared' },
label: 'Shared with me' label: 'Shared with me',
icon: <ShareTwoTone color="secondary" />
}, { }, {
filter: { type: 'public' }, filter: { type: 'public' },
label: 'Public' label: 'Public',
icon: <PublicTwoTone color="secondary" />
}]; }];
labels.forEach(l => filterButtons.push({ filter: { type: 'label', label: l }, label: l })) labels.forEach(l => filterButtons.push({
filter: { type: 'label', label: l },
label: l.title,
icon: <LabelTwoTone style={{ color: l.color ? l.color : 'inherit' }} />
}))
return ( return (
<div className={classes.root}> <div className={classes.root}>
@ -147,8 +158,9 @@ const MapsPage = () => {
</div> </div>
<List component="nav"> <List component="nav">
{filterButtons.map(buttonInfo => (<StyleListItem {filterButtons.map(buttonInfo => {
icon={<PublicTwoTone color="secondary" />} return (<StyleListItem
icon={buttonInfo.icon}
label={buttonInfo.label} label={buttonInfo.label}
filter={buttonInfo.filter} filter={buttonInfo.filter}
active={filter} active={filter}
@ -156,6 +168,7 @@ const MapsPage = () => {
onDelete={handleLabelDelete} onDelete={handleLabelDelete}
key={`${buttonInfo.filter.type}:${(buttonInfo.filter as LabelFilter).label}`} key={`${buttonInfo.filter.type}:${(buttonInfo.filter as LabelFilter).label}`}
/>) />)
}
)} )}
</List> </List>
@ -179,7 +192,7 @@ interface ListItemProps {
filter: Filter, filter: Filter,
active?: Filter active?: Filter
onClick: (filter: Filter) => void; onClick: (filter: Filter) => void;
onDelete?: (label: string) => void; onDelete?: (id: number) => void;
} }
const StyleListItem = (props: ListItemProps) => { const StyleListItem = (props: ListItemProps) => {
@ -204,7 +217,7 @@ const StyleListItem = (props: ListItemProps) => {
if (!onDeleteLabel) { if (!onDeleteLabel) {
throw "Illegal state exeption"; throw "Illegal state exeption";
} }
onDeleteLabel((filter as LabelFilter).label); onDeleteLabel((filter as LabelFilter).label.id);
} }
return ( return (

View File

@ -47,7 +47,7 @@ type Order = 'asc' | 'desc';
function getComparator<Key extends keyof any>( function getComparator<Key extends keyof any>(
order: Order, order: Order,
orderBy: Key, orderBy: Key,
): (a: { [key in Key]: number | string | boolean | string[] | undefined }, b: { [key in Key]: number | string | string[] | boolean }) => number { ): (a: { [key in Key]: number | string | boolean | number[] | undefined }, b: { [key in Key]: number | string | number[] | boolean }) => number {
return order === 'desc' return order === 'desc'
? (a, b) => descendingComparator(a, b, orderBy) ? (a, b) => descendingComparator(a, b, orderBy)
: (a, b) => -descendingComparator(a, b, orderBy); : (a, b) => -descendingComparator(a, b, orderBy);
@ -162,6 +162,8 @@ const mapsFilter = (filter: Filter, search: string): ((mapInfo: MapInfo) => bool
result = mapInfo.starred; result = mapInfo.starred;
break; break;
case 'owned': case 'owned':
//@todo: complete ...
result = mapInfo.starred; result = mapInfo.starred;
break; break;
case 'shared': case 'shared':
@ -169,8 +171,7 @@ const mapsFilter = (filter: Filter, search: string): ((mapInfo: MapInfo) => bool
result = mapInfo.starred; result = mapInfo.starred;
break; break;
case 'label': case 'label':
//@todo: complete ... result = !mapInfo.labels || mapInfo.labels.includes((filter as LabelFilter).label.id)
result = !mapInfo.labels || mapInfo.labels.includes((filter as LabelFilter).label)
break; break;
default: default:
result = false; result = false;
@ -284,6 +285,7 @@ export const MapsList = (props: MapsListProps) => {
queryClient.invalidateQueries('maps'); queryClient.invalidateQueries('maps');
}, },
onError: (error) => { onError: (error) => {
// @todo ...
// setError(error); // setError(error);
} }
} }