Complete delete labels

This commit is contained in:
Paulo Gustavo Veiga 2021-02-01 22:15:32 -08:00
parent a1867168ec
commit 973290d6dd
21 changed files with 288 additions and 194 deletions

View File

@ -6,7 +6,7 @@
"defaultMessage": "Close" "defaultMessage": "Close"
}, },
"action.delete": { "action.delete": {
"defaultMessage": "History" "defaultMessage": "Delete"
}, },
"action.delete-description": { "action.delete-description": {
"defaultMessage": "Deleted mindmap can not be recovered. Do you want to continue ?." "defaultMessage": "Deleted mindmap can not be recovered. Do you want to continue ?."
@ -20,6 +20,12 @@
"action.export": { "action.export": {
"defaultMessage": "Export" "defaultMessage": "Export"
}, },
"action.history": {
"defaultMessage": "History"
},
"action.import": {
"defaultMessage": "Import"
},
"action.info": { "action.info": {
"defaultMessage": "Info" "defaultMessage": "Info"
}, },
@ -29,6 +35,9 @@
"action.label": { "action.label": {
"defaultMessage": "Add Label" "defaultMessage": "Add Label"
}, },
"action.new": {
"defaultMessage": "New Map"
},
"action.open": { "action.open": {
"defaultMessage": "Open" "defaultMessage": "Open"
}, },
@ -139,7 +148,7 @@
"defaultMessage": "Click 'Sign In' button below and start creating mind maps." "defaultMessage": "Click 'Sign In' button below and start creating mind maps."
}, },
"registration.termandconditions": { "registration.termandconditions": {
"defaultMessage": "Terms of Service: Please check the WiseMapping Account information you've entered above, and review the Terms of Service here. By clicking on 'Register' below you are agreeing to the Terms of Service above and the Privacy Policy" "defaultMessage": "Terms of Client: Please check the WiseMapping Account information you've entered above, and review the Terms of Client here. By clicking on 'Register' below you are agreeing to the Terms of Client above and the Privacy Policy"
}, },
"registration.title": { "registration.title": {
"defaultMessage": "Become a member" "defaultMessage": "Become a member"

View File

@ -32,11 +32,12 @@ export type ErrorInfo = {
fields?: Map<String, String>; fields?: Map<String, String>;
} }
interface Service { interface Client {
deleteLabel(label: string): Promise<unknown>;
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<void>; duplicateMap(id: number, basicInfo: BasicMapInfo): Promise<void>;
@ -45,4 +46,4 @@ interface Service {
} }
export default Service; export default Client;

View File

@ -1,11 +1,12 @@
import { BasicMapInfo, ErrorInfo, MapInfo, NewUser } from ".."; import { BasicMapInfo, ErrorInfo, MapInfo, NewUser } from "..";
import Service from ".."; import Client from "..";
import axios from "axios"; import axios from "axios";
class MockService implements Service { class MockClient implements Client {
private baseUrl: string; private baseUrl: string;
private authFailed: () => void private authFailed: () => void
private maps: MapInfo[] = []; private maps: MapInfo[] = [];
private labels: string[] = [];
constructor(baseUrl: string, authFailed: () => void) { constructor(baseUrl: string, authFailed: () => void) {
this.baseUrl = baseUrl; this.baseUrl = baseUrl;
@ -37,6 +38,14 @@ class MockService implements Service {
createMapInfo(11, false, "El Mapa3", [""], "Paulo3", 67, "", false), createMapInfo(11, false, "El Mapa3", [""], "Paulo3", 67, "", false),
createMapInfo(12, false, "El Mapa3", [""], "Paulo3", 67, "", false) createMapInfo(12, false, "El Mapa3", [""], "Paulo3", 67, "", false)
]; ];
this.labels = ["label 1,", "label 2", "label 3"];
}
fetchLabels(): Promise<string[]> {
return Promise.resolve(this.labels);
} }
changeStarred(id: number): Promise<void> { changeStarred(id: number): Promise<void> {
@ -55,6 +64,10 @@ class MockService implements Service {
return Promise.resolve({ name: 'My Map', description: 'My Description' }); return Promise.resolve({ name: 'My Map', description: 'My Description' });
} }
fetchLabes(id: number): Promise<BasicMapInfo> {
return Promise.resolve({ name: '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.name == basicInfo.name) != undefined; const exists = this.maps.find(m => m.name == basicInfo.name) != undefined;
@ -109,6 +122,12 @@ class MockService implements Service {
}; };
} }
deleteLabel(label: string): Promise<void> {
this.labels = this.labels.filter(l => l != label);
console.log("Label delete:" + label);
return Promise.resolve();
}
deleteMap(id: number): Promise<void> { deleteMap(id: number): Promise<void> {
this.maps = this.maps.filter(m => m.id != id); this.maps = this.maps.filter(m => m.id != id);
return Promise.resolve(); return Promise.resolve();
@ -200,4 +219,4 @@ class MockService implements Service {
} }
} }
export default MockService; export default MockClient;

View File

@ -14,7 +14,7 @@
"action.delete": [ "action.delete": [
{ {
"type": 0, "type": 0,
"value": "History" "value": "Delete"
} }
], ],
"action.delete-description": [ "action.delete-description": [
@ -41,6 +41,18 @@
"value": "Export" "value": "Export"
} }
], ],
"action.history": [
{
"type": 0,
"value": "History"
}
],
"action.import": [
{
"type": 0,
"value": "Import"
}
],
"action.info": [ "action.info": [
{ {
"type": 0, "type": 0,
@ -59,6 +71,12 @@
"value": "Add Label" "value": "Add Label"
} }
], ],
"action.new": [
{
"type": 0,
"value": "New Map"
}
],
"action.open": [ "action.open": [
{ {
"type": 0, "type": 0,
@ -278,7 +296,7 @@
"registration.termandconditions": [ "registration.termandconditions": [
{ {
"type": 0, "type": 0,
"value": "Terms of Service: Please check the WiseMapping Account information you've entered above, and review the Terms of Service here. By clicking on 'Register' below you are agreeing to the Terms of Service above and the Privacy Policy" "value": "Terms of Client: Please check the WiseMapping Account information you've entered above, and review the Terms of Client here. By clicking on 'Register' below you are agreeing to the Terms of Client above and the Privacy Policy"
} }
], ],
"registration.title": [ "registration.title": [

View File

@ -1,7 +1,7 @@
import React, { useState, useEffect } from 'react' import React, { useState, useEffect } from 'react'
import { FormattedMessage, useIntl } from 'react-intl' import { FormattedMessage, useIntl } from 'react-intl'
import { useHistory } from "react-router-dom" import { useHistory } from 'react-router-dom'
import Service, { ErrorInfo } from '../../services' import Client, { ErrorInfo } from '../../client'
import Header from '../layout/header' import Header from '../layout/header'
import Footer from '../layout/footer' import Footer from '../layout/footer'
@ -20,7 +20,7 @@ const ForgotPassword = () => {
const history = useHistory(); const history = useHistory();
const intl = useIntl(); const intl = useIntl();
const service: Service = useSelector(activeInstance); const service: Client = useSelector(activeInstance);
const mutation = useMutation<void, ErrorInfo, string>( const mutation = useMutation<void, ErrorInfo, string>(
(email: string) => service.resetPassword(email), (email: string) => service.resetPassword(email),
{ {

View File

@ -1,5 +1,5 @@
import React from "react"; import React from "react";
import { ErrorInfo } from "../../../services" import { ErrorInfo } from "../../../client"
import StyledAlert from "./styled"; import StyledAlert from "./styled";

View File

@ -1,7 +1,7 @@
import { TextField } from "@material-ui/core"; import { TextField } from "@material-ui/core";
import React, { ChangeEvent } from "react"; import React, { ChangeEvent } from "react";
import { MessageDescriptor, useIntl } from "react-intl"; import { MessageDescriptor, useIntl } from "react-intl";
import { ErrorInfo } from "../../../services"; import { ErrorInfo } from "../../../client";
type InputProps = { type InputProps = {
name: string; name: string;

View File

@ -115,7 +115,7 @@ const ActionChooser = (props: ActionProps) => {
<ListItemIcon> <ListItemIcon>
<DeleteOutlinedIcon /> <DeleteOutlinedIcon />
</ListItemIcon> </ListItemIcon>
<FormattedMessage id="action.delete" defaultMessage="History" /> <FormattedMessage id="action.history" defaultMessage="History" />
</MenuItem> </MenuItem>
</Menu>); </Menu>);
} }

View File

@ -1,7 +1,7 @@
import React from "react"; import React from "react";
import { Button, DialogContentText } from "@material-ui/core"; import { Button, DialogContentText } from "@material-ui/core";
import { FormattedMessage, useIntl } from "react-intl"; import { FormattedMessage, useIntl } from "react-intl";
import { ErrorInfo } from "../../../../services"; import { ErrorInfo } from "../../../../client";
import { StyledDialog, StyledDialogActions, StyledDialogContent, StyledDialogTitle } from "./style"; import { StyledDialog, StyledDialogActions, StyledDialogContent, StyledDialogTitle } from "./style";
import GlobalError from "../../../form/global-error"; import GlobalError from "../../../form/global-error";

View File

@ -3,7 +3,7 @@ import React from "react";
import { FormattedMessage, useIntl } from "react-intl"; import { FormattedMessage, useIntl } from "react-intl";
import { useMutation, useQueryClient } from "react-query"; import { useMutation, useQueryClient } from "react-query";
import { useSelector } from "react-redux"; import { useSelector } from "react-redux";
import Service from "../../../../services"; import Client from "../../../../client";
import { activeInstance } from '../../../../reducers/serviceSlice'; import { activeInstance } from '../../../../reducers/serviceSlice';
import { DialogProps, fetchMapById, handleOnMutationSuccess } from ".."; import { DialogProps, fetchMapById, handleOnMutationSuccess } from "..";
import BaseDialog from "../action-dialog"; import BaseDialog from "../action-dialog";
@ -12,7 +12,7 @@ import BaseDialog from "../action-dialog";
const DeleteDialog = (props: DialogProps) => { const DeleteDialog = (props: DialogProps) => {
const intl = useIntl(); const intl = useIntl();
const service: Service = useSelector(activeInstance); const service: Client = useSelector(activeInstance);
const queryClient = useQueryClient(); const queryClient = useQueryClient();
const mutation = useMutation((id: number) => service.deleteMap(id), const mutation = useMutation((id: number) => service.deleteMap(id),
{ {

View File

@ -4,7 +4,7 @@ import { useMutation, useQueryClient } from "react-query";
import { useSelector } from "react-redux"; import { useSelector } from "react-redux";
import { FormControl } from "@material-ui/core"; import { FormControl } from "@material-ui/core";
import Service, { BasicMapInfo, ErrorInfo } from "../../../../services"; import Client, { BasicMapInfo, ErrorInfo } from "../../../../client";
import { activeInstance } from '../../../../reducers/serviceSlice'; import { activeInstance } from '../../../../reducers/serviceSlice';
import Input from "../../../form/input"; import Input from "../../../form/input";
import { DialogProps, fetchMapById, handleOnMutationSuccess } from ".."; import { DialogProps, fetchMapById, handleOnMutationSuccess } from "..";
@ -18,7 +18,7 @@ export type DuplicateModel = {
const defaultModel: DuplicateModel = { name: '', description: '', id: -1 }; const defaultModel: DuplicateModel = { name: '', description: '', id: -1 };
const DuplicateDialog = (props: DialogProps) => { const DuplicateDialog = (props: DialogProps) => {
const service: Service = useSelector(activeInstance); const service: Client = useSelector(activeInstance);
const [model, setModel] = React.useState<DuplicateModel>(defaultModel); const [model, setModel] = React.useState<DuplicateModel>(defaultModel);
const [error, setError] = React.useState<ErrorInfo>(); const [error, setError] = React.useState<ErrorInfo>();
const { mapId, open } = props; const { mapId, open } = props;

View File

@ -2,8 +2,8 @@ import React from 'react';
import RenameDialog from './rename'; import RenameDialog from './rename';
import DeleteDialog from './delete'; import DeleteDialog from './delete';
import { ActionType } from '../action-chooser'; import { ActionType } from '../action-chooser';
import { ErrorInfo, MapInfo } from '../../../services'; import { ErrorInfo, MapInfo } from '../../../client';
import Service from '../../../services'; import Client from '../../../client';
import { useSelector } from 'react-redux'; import { useSelector } from 'react-redux';
import { QueryClient, useQuery } from 'react-query'; import { QueryClient, useQuery } from 'react-query';
import { activeInstance } from '../../../reducers/serviceSlice'; import { activeInstance } from '../../../reducers/serviceSlice';
@ -60,7 +60,7 @@ type MapLoadResult = {
export const fetchMapById = (id: number): MapLoadResult => { export const fetchMapById = (id: number): MapLoadResult => {
const service: Service = useSelector(activeInstance); const service: Client = useSelector(activeInstance);
const { isLoading, error, data } = useQuery<unknown, ErrorInfo, MapInfo[]>('maps', () => { const { isLoading, error, data } = useQuery<unknown, ErrorInfo, MapInfo[]>('maps', () => {
return service.fetchAllMaps(); return service.fetchAllMaps();
}); });

View File

@ -1,7 +1,7 @@
import React from "react"; import React from "react";
import { useQueryClient } from "react-query"; import { useQueryClient } from "react-query";
import { useSelector } from "react-redux"; import { useSelector } from "react-redux";
import Service from "../../../../services"; import Client from "../../../../client";
import { activeInstance } from '../../../../reducers/serviceSlice'; import { activeInstance } from '../../../../reducers/serviceSlice';
import { DialogProps, fetchMapById } from ".."; import { DialogProps, fetchMapById } from "..";
import BaseDialog from "../action-dialog"; import BaseDialog from "../action-dialog";
@ -9,7 +9,7 @@ import { useIntl } from "react-intl";
const InfoDialog = (props: DialogProps) => { const InfoDialog = (props: DialogProps) => {
const service: Service = useSelector(activeInstance); const service: Client = useSelector(activeInstance);
const queryClient = useQueryClient(); const queryClient = useQueryClient();
const intl = useIntl(); const intl = useIntl();

View File

@ -2,7 +2,7 @@ import React, { useEffect } from "react";
import { useIntl } from "react-intl"; import { useIntl } from "react-intl";
import { useMutation, useQueryClient } from "react-query"; import { useMutation, useQueryClient } from "react-query";
import { useSelector } from "react-redux"; import { useSelector } from "react-redux";
import Service, { BasicMapInfo, ErrorInfo } from "../../../../services"; import Client, { BasicMapInfo, ErrorInfo } from "../../../../client";
import { activeInstance } from '../../../../reducers/serviceSlice'; import { activeInstance } from '../../../../reducers/serviceSlice';
import { DialogProps, fetchMapById, handleOnMutationSuccess } from ".."; import { DialogProps, fetchMapById, handleOnMutationSuccess } from "..";
import Input from "../../../form/input"; import Input from "../../../form/input";
@ -17,7 +17,7 @@ export type RenameModel = {
const defaultModel: RenameModel = { name: '', description: '', id: -1 }; const defaultModel: RenameModel = { name: '', description: '', id: -1 };
const RenameDialog = (props: DialogProps) => { const RenameDialog = (props: DialogProps) => {
const service: Service = useSelector(activeInstance); const service: Client = useSelector(activeInstance);
const [model, setModel] = React.useState<RenameModel>(defaultModel); const [model, setModel] = React.useState<RenameModel>(defaultModel);
const [error, setError] = React.useState<ErrorInfo>(); const [error, setError] = React.useState<ErrorInfo>();
const { mapId, open } = props; const { mapId, open } = props;

View File

@ -1,4 +1,4 @@
import React, { useEffect } from 'react'; import React, { ErrorInfo, useEffect } from 'react';
import clsx from 'clsx'; import clsx from 'clsx';
import Drawer from '@material-ui/core/Drawer'; import Drawer from '@material-ui/core/Drawer';
import AppBar from '@material-ui/core/AppBar'; import AppBar from '@material-ui/core/AppBar';
@ -8,14 +8,19 @@ 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, BlurCircular, CloudUploadTwoTone, EmailOutlined, EmojiPeopleOutlined, ExitToAppOutlined, FeedbackOutlined, Help, LabelTwoTone, PolicyOutlined, PublicTwoTone, SettingsApplicationsOutlined, ShareTwoTone, StarRateTwoTone, Translate, TranslateTwoTone } from '@material-ui/icons'; import { AccountCircle, AddCircleTwoTone, BlurCircular, CloudUploadTwoTone, DeleteOutlineTwoTone, EmailOutlined, EmojiPeopleOutlined, ExitToAppOutlined, FeedbackOutlined, Help, PolicyOutlined, PublicTwoTone, SettingsApplicationsOutlined, ShareTwoTone, StarRateTwoTone, Translate, TranslateTwoTone } from '@material-ui/icons';
import InboxTwoToneIcon from '@material-ui/icons/InboxTwoTone'; import InboxTwoToneIcon from '@material-ui/icons/InboxTwoTone';
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 { useQueryClient } from 'react-query'; import { useQuery, useMutation, useQueryClient } from 'react-query';
const logoIcon = require('../../images/logo-small.svg') import { activeInstance } from '../../reducers/serviceSlice';
const poweredByIcon = require('../../images/pwrdby-white.svg') import { useSelector } from 'react-redux';
import Client from '../../client';
const logoIcon = require('../../images/logo-small.svg');
const poweredByIcon = require('../../images/pwrdby-white.svg');
export type Filter = GenericFilter | LabelFilter; export type Filter = GenericFilter | LabelFilter;
@ -28,19 +33,65 @@ interface LabelFilter {
label: string label: string
} }
interface ToolbarButtonInfo {
filter: GenericFilter | LabelFilter,
label: string
}
const MapsPage = (props: any) => { const MapsPage = (props: any) => {
const classes = useStyles(); const classes = useStyles();
const [filter, setFilter] = React.useState<Filter>({ type: 'all' }); const [filter, setFilter] = React.useState<Filter>({ type: 'all' });
const client: Client = useSelector(activeInstance);
const queryClient = useQueryClient(); const queryClient = useQueryClient();
useEffect(() => { useEffect(() => {
document.title = 'Maps | WiseMapping'; document.title = 'Maps | WiseMapping';
}, []); }, []);
const mutation = useMutation(
(label: string) => client.deleteLabel(label),
{
onSuccess: () => queryClient.invalidateQueries('labels')
}
);
const handleMenuClick = (filter: Filter) => { const handleMenuClick = (filter: Filter) => {
setFilter(filter); setFilter(filter);
}; };
const handleLabelDelete = (label: string) => {
mutation.mutate(label);
};
const { isLoading, error, data } = useQuery<unknown, ErrorInfo, string[]>('labels', async () => {
return await client.fetchLabels();
});
const labels: string[] = data ? data : [];
const filterButtons: ToolbarButtonInfo[] = [{
filter: { type: 'all' },
label: 'All'
}, {
filter: { type: 'owned' },
label: 'Owned'
}, {
filter: { type: 'starred' },
label: 'Starred'
}, {
filter: { type: 'shared' },
label: 'Shared with me'
}, {
filter: { type: 'public' },
label: 'Public'
}];
labels.forEach(l => filterButtons.push({ filter: { type: 'label', label: l }, label: l }))
return ( return (
<div className={classes.root}> <div className={classes.root}>
<AppBar <AppBar
@ -49,27 +100,20 @@ const MapsPage = (props: any) => {
[classes.appBarShift]: open, [classes.appBarShift]: open,
})} })}
variant='outlined' variant='outlined'
elevation={0} elevation={0}>
>
<Toolbar variant="regular"> <Toolbar style={{ minWidth: '600px' }}>
<Tooltip title="Create a New Map"> <Tooltip title="Create a New Map">
<Button color="primary" size="medium" variant="contained" type="button" <Button color="primary" size="medium" variant="contained" type="button"
disableElevation={true} startIcon={<AddCircleTwoTone />} className={classes.newMapButton}> disableElevation={true} startIcon={<AddCircleTwoTone />} className={classes.newMapButton}>
New Map <FormattedMessage id="action.new" defaultMessage="New Map" />
</Button> </Button>
</Tooltip> </Tooltip>
<Tooltip title="Import from external tools"> <Tooltip title="Import from external tools">
<Button color="primary" size="medium" variant="outlined" type="button" <Button color="primary" size="medium" variant="outlined" type="button"
disableElevation={true} startIcon={<CloudUploadTwoTone />} className={classes.importButton}> disableElevation={true} startIcon={<CloudUploadTwoTone />} className={classes.importButton}>
Import <FormattedMessage id="action.import" defaultMessage="Import" />
</Button>
</Tooltip>
<Tooltip title="Use labels to organize your maps">
<Button color="primary" size="medium" variant="outlined" type="button"
disableElevation={true} startIcon={<LabelTwoTone />} className={classes.importButton}>
Label
</Button> </Button>
</Tooltip> </Tooltip>
@ -82,13 +126,11 @@ const MapsPage = (props: any) => {
<Drawer <Drawer
variant="permanent" variant="permanent"
className={clsx(classes.drawer, { className={clsx(classes.drawer, {
[classes.drawerOpen]: open, [classes.drawerOpen]: open
[classes.drawerClose]: !open,
})} })}
classes={{ classes={{
paper: clsx({ paper: clsx({
[classes.drawerOpen]: open, [classes.drawerOpen]: open
[classes.drawerClose]: !open,
}), }),
}}> }}>
@ -97,41 +139,16 @@ const MapsPage = (props: any) => {
</div> </div>
<List component="nav"> <List component="nav">
<StyleListItem {filterButtons.map(buttonInfo => (<StyleListItem
icon={<InboxTwoToneIcon color="secondary" />}
label={"All"}
filter={{ type: 'all' }}
active={filter}
onClick={handleMenuClick}
/>
<StyleListItem
icon={<BlurCircular color="secondary" />}
label={"Owned"}
filter={{ type: 'owned' }}
active={filter}
onClick={handleMenuClick}
/>
<StyleListItem
icon={<StarRateTwoTone color="secondary" />}
label={"Starred"}
filter={{ type: 'starred' }}
active={filter}
onClick={handleMenuClick}
/>
<StyleListItem
icon={<ShareTwoTone color="secondary" />}
label={"Shared With Me"}
filter={{ type: 'shared' }}
active={filter}
onClick={handleMenuClick}
/>
<StyleListItem
icon={<PublicTwoTone color="secondary" />} icon={<PublicTwoTone color="secondary" />}
label={"Public"} label={buttonInfo.label}
filter={{ type: 'public' }} filter={buttonInfo.filter}
active={filter} active={filter}
onClick={handleMenuClick} onClick={handleMenuClick}
/> onDelete={handleLabelDelete}
key={`${buttonInfo.filter.type}:${(buttonInfo.filter as LabelFilter).label}`}
/>)
)}
</List> </List>
<div style={{ position: 'absolute', bottom: '10px', left: '20px' }}> <div style={{ position: 'absolute', bottom: '10px', left: '20px' }}>
@ -154,6 +171,7 @@ interface ListItemProps {
filter: Filter, filter: Filter,
active?: Filter active?: Filter
onClick: (filter: Filter) => void; onClick: (filter: Filter) => void;
onDelete?: (label: string) => void;
} }
const StyleListItem = (props: ListItemProps) => { const StyleListItem = (props: ListItemProps) => {
@ -162,26 +180,36 @@ const StyleListItem = (props: ListItemProps) => {
const filter = props.filter; const filter = props.filter;
const activeType = props.active?.type; const activeType = props.active?.type;
const onClick = props.onClick; const onClick = props.onClick;
const onDeleteLabel = props.onDelete;
const handleOnClick = (event: any, filter: Filter) => { const handleOnClick = (event: any, filter: Filter) => {
// Invalidate cache to provide a fresh load ...
event.stopPropagation(); event.stopPropagation();
onClick(filter); onClick(filter);
} }
const handleOnDelete = (event: any, filter: Filter) => {
event.stopPropagation();
if (!onDeleteLabel) {
throw "Illegal state exeption";
}
onDeleteLabel((filter as LabelFilter).label);
}
return ( return (
<ListItem button selected={activeType == filter.type} onClick={e => { handleOnClick(e, filter) }}> <ListItem button
selected={activeType == filter.type}
onClick={e => handleOnClick(e, filter)}>
<ListItemIcon> <ListItemIcon>
{icon} {icon}
</ListItemIcon> </ListItemIcon>
<ListItemText style={{ color: 'white' }} primary={label} /> <ListItemText style={{ color: 'white' }} primary={label} />
{filter.type == 'label' ?
{/* <ListItemSecondaryAction> (<ListItemSecondaryAction>
<IconButton edge="end" aria-label="delete"> <IconButton edge="end" aria-label="delete" onClick={e => handleOnDelete(e, filter)}>
<DeleteOutlineTwoTone color="secondary" /> <DeleteOutlineTwoTone color="secondary" />
</IconButton> </IconButton>
</ListItemSecondaryAction> */} </ListItemSecondaryAction>) : null}
</ListItem> </ListItem>
); );
} }

View File

@ -14,21 +14,22 @@ import Paper from '@material-ui/core/Paper';
import Checkbox from '@material-ui/core/Checkbox'; import Checkbox from '@material-ui/core/Checkbox';
import IconButton from '@material-ui/core/IconButton'; import IconButton from '@material-ui/core/IconButton';
import Tooltip from '@material-ui/core/Tooltip'; import Tooltip from '@material-ui/core/Tooltip';
import DeleteIcon from '@material-ui/icons/Delete';
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 { CSSProperties } from 'react';
import { useSelector } from 'react-redux'; import { useSelector } from 'react-redux';
import { activeInstance } from '../../../reducers/serviceSlice'; import { activeInstance } from '../../../reducers/serviceSlice';
import { useMutation, useQuery, useQueryClient } from 'react-query'; import { useMutation, useQuery, useQueryClient } from 'react-query';
import { ErrorInfo, MapInfo } from '../../../services'; import { ErrorInfo, MapInfo } from '../../../client';
import Service from '../../../services'; import Client from '../../../client';
import ActionChooser, { ActionType } from '../action-chooser'; import ActionChooser, { ActionType } from '../action-chooser';
import ActionDispatcher from '../action-dispatcher'; import ActionDispatcher from '../action-dispatcher';
import { InputBase, Link } from '@material-ui/core'; import { Button, InputBase, Link } from '@material-ui/core';
import SearchIcon from '@material-ui/icons/Search'; import SearchIcon from '@material-ui/icons/Search';
import moment from 'moment' import moment from 'moment'
import { Filter } from '..'; import { Filter } from '..';
import { FormattedMessage } from 'react-intl';
import { DeleteOutlined, LabelTwoTone } from '@material-ui/icons';
function descendingComparator<T>(a: T, b: T, orderBy: keyof T) { function descendingComparator<T>(a: T, b: T, orderBy: keyof T) {
@ -160,6 +161,14 @@ const mapsFilter = (filter: Filter, search: string): ((mapInfo: MapInfo) => bool
case 'starred': case 'starred':
result = mapInfo.starred; result = mapInfo.starred;
break; break;
case 'owned':
result = mapInfo.starred;
break;
case 'shared':
//@todo: complete ...
result = mapInfo.starred;
break;
default: default:
result = false; result = false;
} }
@ -184,25 +193,23 @@ export const MapsList = (props: MapsListProps) => {
const [page, setPage] = React.useState(0); const [page, setPage] = React.useState(0);
const [rowsPerPage, setRowsPerPage] = React.useState(10); const [rowsPerPage, setRowsPerPage] = React.useState(10);
const service: Service = useSelector(activeInstance); const client: Client = useSelector(activeInstance);
console.log("MapsList refresh");
useEffect(() => { useEffect(() => {
console.log("Update maps state.") console.log("Update maps state.")
setSelected([]); setSelected([]);
setSearchCondition('');
setPage(0); setPage(0);
setFilter(props.filter) setFilter(props.filter)
queryClient.invalidateQueries('maps');
}, [props.filter.type]); }, [props.filter.type]);
const { isLoading, error, data } = useQuery<unknown, ErrorInfo, MapInfo[]>('maps', async () => { const { isLoading, error, data } = useQuery<unknown, ErrorInfo, MapInfo[]>('maps', async () => {
return await service.fetchAllMaps(); return await client.fetchAllMaps();
}); });
const mapsInfo: MapInfo[] = data ? data.filter(mapsFilter(filter, searchCondition)) : []; const mapsInfo: MapInfo[] = data ? data.filter(mapsFilter(filter, searchCondition)) : [];
const [activeRowAction, setActiveRowAction] = React.useState<ActionPanelState | undefined>(undefined); const [activeRowAction, setActiveRowAction] = React.useState<ActionPanelState | undefined>(undefined);
type ActiveDialog = { type ActiveDialog = {
actionType: ActionType; actionType: ActionType;
@ -269,7 +276,7 @@ export const MapsList = (props: MapsListProps) => {
const queryClient = useQueryClient(); const queryClient = useQueryClient();
const starredMultation = useMutation<void, ErrorInfo, number>((id: number) => { const starredMultation = useMutation<void, ErrorInfo, number>((id: number) => {
return service.changeStarred(id); return client.changeStarred(id);
}, },
{ {
onSuccess: () => { onSuccess: () => {
@ -308,14 +315,33 @@ export const MapsList = (props: MapsListProps) => {
<Paper className={classes.paper} elevation={0}> <Paper className={classes.paper} elevation={0}>
<Toolbar className={classes.toolbar} variant="dense"> <Toolbar className={classes.toolbar} variant="dense">
<div className={classes.toolbarActions}> <div className={classes.toolbarActions}>
{selected.length > 0 ? ( {selected.length > 0 ? (
<Tooltip title="Delete selected">
<Button
color="primary"
size="medium"
variant="outlined"
type="button"
disableElevation={true}
startIcon={<DeleteOutlined />}>
<FormattedMessage id="action.delete" defaultMessage="Delete" />
</Button>
</Tooltip>
) : null}
<Tooltip title="Delete"> {selected.length > 0 ? (
<IconButton aria-label="delete"> <Tooltip title="Add label to selected">
<DeleteIcon /> <Button
</IconButton> color="primary"
size="medium"
variant="outlined"
type="button"
style={{ marginLeft: "10px" }}
disableElevation={true}
startIcon={<LabelTwoTone />}>
<FormattedMessage id="action.label" defaultMessage="Add Label" />
</Button>
</Tooltip> </Tooltip>
) : null} ) : null}
</div> </div>
@ -324,6 +350,7 @@ export const MapsList = (props: MapsListProps) => {
<TablePagination <TablePagination
style={{ float: 'right', border: "0", paddingBottom: "5px" }} style={{ float: 'right', border: "0", paddingBottom: "5px" }}
count={mapsInfo.length} count={mapsInfo.length}
rowsPerPageOptions={[]}
rowsPerPage={rowsPerPage} rowsPerPage={rowsPerPage}
page={page} page={page}
onChangePage={handleChangePage} onChangePage={handleChangePage}

View File

@ -46,10 +46,10 @@ export const useStyles = makeStyles((theme: Theme) =>
display: 'flex', display: 'flex',
borderBottom: '1px solid #cccccc', borderBottom: '1px solid #cccccc',
padding: '0', padding: '0',
marging: '0' marging: '0'
}, },
toolbarActions: { toolbarActions: {
flexGrow: 1 flexGrow: 1,
}, },
toolbarListActions: { toolbarListActions: {
flexGrow: 1 flexGrow: 1

View File

@ -34,10 +34,8 @@ export const useStyles = makeStyles((theme: Theme) =>
rightButtonGroup: { rightButtonGroup: {
marginRight: 10, marginRight: 10,
flexGrow: 10, flexGrow: 10,
textAlign: 'right' textAlign: 'right',
}, minWidth: '200px'
hide: {
display: 'none',
}, },
drawer: { drawer: {
width: drawerWidth, width: drawerWidth,
@ -52,17 +50,6 @@ export const useStyles = makeStyles((theme: Theme) =>
duration: theme.transitions.duration.enteringScreen, duration: theme.transitions.duration.enteringScreen,
}), }),
}, },
drawerClose: {
transition: theme.transitions.create('width', {
easing: theme.transitions.easing.sharp,
duration: theme.transitions.duration.leavingScreen,
}),
overflowX: 'hidden',
width: theme.spacing(7) + 1,
[theme.breakpoints.up('sm')]: {
width: theme.spacing(9) + 1,
},
},
toolbar: { toolbar: {
display: 'flex', display: 'flex',
justifyContent: 'flex-end', justifyContent: 'flex-end',

View File

@ -2,7 +2,7 @@ import React, { useState, useEffect } from 'react';
import { FormattedMessage, useIntl } from 'react-intl'; import { FormattedMessage, useIntl } from 'react-intl';
import ReCAPTCHA from 'react-google-recaptcha'; import ReCAPTCHA from 'react-google-recaptcha';
import { useHistory } from 'react-router-dom'; import { useHistory } from 'react-router-dom';
import Service , { ErrorInfo} from '../../services'; import Client , { ErrorInfo} from '../../client';
import FormContainer from '../layout/form-container'; import FormContainer from '../layout/form-container';
import Header from '../layout/header'; import Header from '../layout/header';
@ -31,9 +31,9 @@ const RegistrationForm = () => {
const history = useHistory(); const history = useHistory();
const intl = useIntl(); const intl = useIntl();
const service: Service = useSelector(activeInstance); const Client: Client = useSelector(activeInstance);
const mutation = useMutation<void, ErrorInfo, Model>( const mutation = useMutation<void, ErrorInfo, Model>(
(model: Model) => service.registerNewUser({ ...model }), (model: Model) => Client.registerNewUser({ ...model }),
{ {
onSuccess: () => history.push("/c/registration-success"), onSuccess: () => history.push("/c/registration-success"),
onError: (error) => { onError: (error) => {
@ -90,7 +90,7 @@ const RegistrationForm = () => {
</div> </div>
<div style={{ fontSize: "12px", padding: "10px 0px" }}> <div style={{ fontSize: "12px", padding: "10px 0px" }}>
<FormattedMessage id="registration.termandconditions" defaultMessage="Terms of Service: Please check the WiseMapping Account information you've entered above, and review the Terms of Service here. By clicking on 'Register' below you are agreeing to the Terms of Service above and the Privacy Policy" /> <FormattedMessage id="registration.termandconditions" defaultMessage="Terms of Client: Please check the WiseMapping Account information you've entered above, and review the Terms of Client here. By clicking on 'Register' below you are agreeing to the Terms of Client above and the Privacy Policy" />
</div> </div>
<SubmitButton value={intl.formatMessage({ id: "registration.register", defaultMessage: "Register" })} /> <SubmitButton value={intl.formatMessage({ id: "registration.register", defaultMessage: "Register" })} />

View File

@ -1,7 +1,7 @@
import { createSlice, PayloadAction } from '@reduxjs/toolkit' import { createSlice, PayloadAction } from '@reduxjs/toolkit'
import axios from 'axios'; import axios from 'axios';
import Service from '../services'; import Client from '../client';
import MockService from '../services/mock-service'; import MockClient from '../client/mock-client';
type RutimeConfig = { type RutimeConfig = {
apiBaseUrl: string; apiBaseUrl: string;
@ -34,11 +34,11 @@ async function loadRuntimeConfig() {
interface ServiceState { interface ServiceState {
instance: Service instance: Client;
} }
const initialState: ServiceState = { const initialState: ServiceState = {
instance: new MockService("", () => { console.log("401 error") }) instance: new MockClient("", () => { console.log("401 error") })
}; };
export const serviceSlice = createSlice({ export const serviceSlice = createSlice({
@ -46,12 +46,12 @@ export const serviceSlice = createSlice({
initialState: initialState, initialState: initialState,
reducers: { reducers: {
initialize(state, action: PayloadAction<void[]>) { initialize(state, action: PayloadAction<void[]>) {
state.instance = new MockService("", () => { console.log("401 error") }); state.instance = new MockClient("", () => { console.log("401 error") });
} }
}, },
}); });
export const activeInstance = (state: any): Service => { export const activeInstance = (state: any): Client => {
return state.service.instance; return state.service.instance;
} }
export default serviceSlice.reducer export default serviceSlice.reducer

127
yarn.lock
View File

@ -1712,14 +1712,14 @@
npmlog "^4.1.2" npmlog "^4.1.2"
write-file-atomic "^2.3.0" write-file-atomic "^2.3.0"
"@material-ui/core@^4.11.2": "@material-ui/core@^4.11.1":
version "4.11.2" version "4.11.3"
resolved "https://registry.yarnpkg.com/@material-ui/core/-/core-4.11.2.tgz#f8276dfa40d88304e6ceb98962af73803d27d42d" resolved "https://registry.yarnpkg.com/@material-ui/core/-/core-4.11.3.tgz#f22e41775b0bd075e36a7a093d43951bf7f63850"
integrity sha512-/D1+AQQeYX/WhT/FUk78UCRj8ch/RCglsQLYujYTIqPSJlwZHKcvHidNeVhODXeApojeXjkl0tWdk5C9ofwOkQ== integrity sha512-Adt40rGW6Uds+cAyk3pVgcErpzU/qxc7KBR94jFHBYretU4AtWZltYcNsbeMn9tXL86jjVL1kuGcIHsgLgFGRw==
dependencies: dependencies:
"@babel/runtime" "^7.4.4" "@babel/runtime" "^7.4.4"
"@material-ui/styles" "^4.11.2" "@material-ui/styles" "^4.11.3"
"@material-ui/system" "^4.11.2" "@material-ui/system" "^4.11.3"
"@material-ui/types" "^5.1.0" "@material-ui/types" "^5.1.0"
"@material-ui/utils" "^4.11.2" "@material-ui/utils" "^4.11.2"
"@types/react-transition-group" "^4.2.0" "@types/react-transition-group" "^4.2.0"
@ -1748,10 +1748,10 @@
prop-types "^15.7.2" prop-types "^15.7.2"
react-is "^16.8.0 || ^17.0.0" react-is "^16.8.0 || ^17.0.0"
"@material-ui/styles@^4.11.2": "@material-ui/styles@^4.11.3":
version "4.11.2" version "4.11.3"
resolved "https://registry.yarnpkg.com/@material-ui/styles/-/styles-4.11.2.tgz#e70558be3f41719e8c0d63c7a3c9ae163fdc84cb" resolved "https://registry.yarnpkg.com/@material-ui/styles/-/styles-4.11.3.tgz#1b8d97775a4a643b53478c895e3f2a464e8916f2"
integrity sha512-xbItf8zkfD3FuGoD9f2vlcyPf9jTEtj9YTJoNNV+NMWaSAHXgrW6geqRoo/IwBuMjqpwqsZhct13e2nUyU9Ljw== integrity sha512-HzVzCG+PpgUGMUYEJ2rTEmQYeonGh41BYfILNFb/1ueqma+p1meSdu4RX6NjxYBMhf7k+jgfHFTTz+L1SXL/Zg==
dependencies: dependencies:
"@babel/runtime" "^7.4.4" "@babel/runtime" "^7.4.4"
"@emotion/hash" "^0.8.0" "@emotion/hash" "^0.8.0"
@ -1760,20 +1760,20 @@
clsx "^1.0.4" clsx "^1.0.4"
csstype "^2.5.2" csstype "^2.5.2"
hoist-non-react-statics "^3.3.2" hoist-non-react-statics "^3.3.2"
jss "^10.0.3" jss "^10.5.1"
jss-plugin-camel-case "^10.0.3" jss-plugin-camel-case "^10.5.1"
jss-plugin-default-unit "^10.0.3" jss-plugin-default-unit "^10.5.1"
jss-plugin-global "^10.0.3" jss-plugin-global "^10.5.1"
jss-plugin-nested "^10.0.3" jss-plugin-nested "^10.5.1"
jss-plugin-props-sort "^10.0.3" jss-plugin-props-sort "^10.5.1"
jss-plugin-rule-value-function "^10.0.3" jss-plugin-rule-value-function "^10.5.1"
jss-plugin-vendor-prefixer "^10.0.3" jss-plugin-vendor-prefixer "^10.5.1"
prop-types "^15.7.2" prop-types "^15.7.2"
"@material-ui/system@^4.11.2": "@material-ui/system@^4.11.3":
version "4.11.2" version "4.11.3"
resolved "https://registry.yarnpkg.com/@material-ui/system/-/system-4.11.2.tgz#7f0a754bba3673ed5fdbfa02fe438096c104b1f6" resolved "https://registry.yarnpkg.com/@material-ui/system/-/system-4.11.3.tgz#466bc14c9986798fd325665927c963eb47cc4143"
integrity sha512-BELFJEel5E+5DMiZb6XXT3peWRn6UixRvBtKwSxqntmD0+zwbbfCij6jtGwwdJhN1qX/aXrKu10zX31GBaeR7A== integrity sha512-SY7otguNGol41Mu2Sg6KbBP1ZRFIbFLHGK81y4KYbsV2yIcaEPOmsCK6zwWlp+2yTV3J/VwT6oSBARtGIVdXPw==
dependencies: dependencies:
"@babel/runtime" "^7.4.4" "@babel/runtime" "^7.4.4"
"@material-ui/utils" "^4.11.2" "@material-ui/utils" "^4.11.2"
@ -6110,70 +6110,70 @@ jsprim@^1.2.2:
json-schema "0.2.3" json-schema "0.2.3"
verror "1.10.0" verror "1.10.0"
jss-plugin-camel-case@^10.0.3: jss-plugin-camel-case@^10.5.1:
version "10.5.0" version "10.5.1"
resolved "https://registry.yarnpkg.com/jss-plugin-camel-case/-/jss-plugin-camel-case-10.5.0.tgz#4b0a9c85e65e5eb72cbfba59373686c604d88f72" resolved "https://registry.yarnpkg.com/jss-plugin-camel-case/-/jss-plugin-camel-case-10.5.1.tgz#427b24a9951b4c2eaa7e3d5267acd2e00b0934f9"
integrity sha512-GSjPL0adGAkuoqeYiXTgO7PlIrmjv5v8lA6TTBdfxbNYpxADOdGKJgIEkffhlyuIZHlPuuiFYTwUreLUmSn7rg== integrity sha512-9+oymA7wPtswm+zxVti1qiowC5q7bRdCJNORtns2JUj/QHp2QPXYwSNRD8+D2Cy3/CEMtdJzlNnt5aXmpS6NAg==
dependencies: dependencies:
"@babel/runtime" "^7.3.1" "@babel/runtime" "^7.3.1"
hyphenate-style-name "^1.0.3" hyphenate-style-name "^1.0.3"
jss "10.5.0" jss "10.5.1"
jss-plugin-default-unit@^10.0.3: jss-plugin-default-unit@^10.5.1:
version "10.5.0" version "10.5.1"
resolved "https://registry.yarnpkg.com/jss-plugin-default-unit/-/jss-plugin-default-unit-10.5.0.tgz#e9f2e89741b0118ba15d52b4c13bda2b27262373" resolved "https://registry.yarnpkg.com/jss-plugin-default-unit/-/jss-plugin-default-unit-10.5.1.tgz#2be385d71d50aee2ee81c2a9ac70e00592ed861b"
integrity sha512-rsbTtZGCMrbcb9beiDd+TwL991NGmsAgVYH0hATrYJtue9e+LH/Gn4yFD1ENwE+3JzF3A+rPnM2JuD9L/SIIWw== integrity sha512-D48hJBc9Tj3PusvlillHW8Fz0y/QqA7MNmTYDQaSB/7mTrCZjt7AVRROExoOHEtd2qIYKOYJW3Jc2agnvsXRlQ==
dependencies: dependencies:
"@babel/runtime" "^7.3.1" "@babel/runtime" "^7.3.1"
jss "10.5.0" jss "10.5.1"
jss-plugin-global@^10.0.3: jss-plugin-global@^10.5.1:
version "10.5.0" version "10.5.1"
resolved "https://registry.yarnpkg.com/jss-plugin-global/-/jss-plugin-global-10.5.0.tgz#eb357ccd35cb4894277fb2117a78d1e498668ad6" resolved "https://registry.yarnpkg.com/jss-plugin-global/-/jss-plugin-global-10.5.1.tgz#0e1793dea86c298360a7e2004721351653c7e764"
integrity sha512-FZd9+JE/3D7HMefEG54fEC0XiQ9rhGtDHAT/ols24y8sKQ1D5KIw6OyXEmIdKFmACgxZV2ARQ5pAUypxkk2IFQ== integrity sha512-jX4XpNgoaB8yPWw/gA1aPXJEoX0LNpvsROPvxlnYe+SE0JOhuvF7mA6dCkgpXBxfTWKJsno7cDSCgzHTocRjCQ==
dependencies: dependencies:
"@babel/runtime" "^7.3.1" "@babel/runtime" "^7.3.1"
jss "10.5.0" jss "10.5.1"
jss-plugin-nested@^10.0.3: jss-plugin-nested@^10.5.1:
version "10.5.0" version "10.5.1"
resolved "https://registry.yarnpkg.com/jss-plugin-nested/-/jss-plugin-nested-10.5.0.tgz#790c506432a23a63c71ceb5044e2ac85f0958702" resolved "https://registry.yarnpkg.com/jss-plugin-nested/-/jss-plugin-nested-10.5.1.tgz#8753a80ad31190fb6ac6fdd39f57352dcf1295bb"
integrity sha512-ejPlCLNlEGgx8jmMiDk/zarsCZk+DV0YqXfddpgzbO9Toamo0HweCFuwJ3ZO40UFOfqKwfpKMVH/3HUXgxkTMg== integrity sha512-xXkWKOCljuwHNjSYcXrCxBnjd8eJp90KVFW1rlhvKKRXnEKVD6vdKXYezk2a89uKAHckSvBvBoDGsfZrldWqqQ==
dependencies: dependencies:
"@babel/runtime" "^7.3.1" "@babel/runtime" "^7.3.1"
jss "10.5.0" jss "10.5.1"
tiny-warning "^1.0.2" tiny-warning "^1.0.2"
jss-plugin-props-sort@^10.0.3: jss-plugin-props-sort@^10.5.1:
version "10.5.0" version "10.5.1"
resolved "https://registry.yarnpkg.com/jss-plugin-props-sort/-/jss-plugin-props-sort-10.5.0.tgz#5bcc3bd8e68cd3e2dafb47d67db28fd5a4fcf102" resolved "https://registry.yarnpkg.com/jss-plugin-props-sort/-/jss-plugin-props-sort-10.5.1.tgz#ab1c167fd2d4506fb6a1c1d66c5f3ef545ff1cd8"
integrity sha512-kTLRvrOetFKz5vM88FAhLNeJIxfjhCepnvq65G7xsAQ/Wgy7HwO1BS/2wE5mx8iLaAWC6Rj5h16mhMk9sKdZxg== integrity sha512-t+2vcevNmMg4U/jAuxlfjKt46D/jHzCPEjsjLRj/J56CvP7Iy03scsUP58Iw8mVnaV36xAUZH2CmAmAdo8994g==
dependencies: dependencies:
"@babel/runtime" "^7.3.1" "@babel/runtime" "^7.3.1"
jss "10.5.0" jss "10.5.1"
jss-plugin-rule-value-function@^10.0.3: jss-plugin-rule-value-function@^10.5.1:
version "10.5.0" version "10.5.1"
resolved "https://registry.yarnpkg.com/jss-plugin-rule-value-function/-/jss-plugin-rule-value-function-10.5.0.tgz#60ee8240dfe60418e1ba4729adee893cbe9be7a3" resolved "https://registry.yarnpkg.com/jss-plugin-rule-value-function/-/jss-plugin-rule-value-function-10.5.1.tgz#37f4030523fb3032c8801fab48c36c373004de7e"
integrity sha512-jXINGr8BSsB13JVuK274oEtk0LoooYSJqTBCGeBu2cG/VJ3+4FPs1gwLgsq24xTgKshtZ+WEQMVL34OprLidRA== integrity sha512-3gjrSxsy4ka/lGQsTDY8oYYtkt2esBvQiceGBB4PykXxHoGRz14tbCK31Zc6DHEnIeqsjMUGbq+wEly5UViStQ==
dependencies: dependencies:
"@babel/runtime" "^7.3.1" "@babel/runtime" "^7.3.1"
jss "10.5.0" jss "10.5.1"
tiny-warning "^1.0.2" tiny-warning "^1.0.2"
jss-plugin-vendor-prefixer@^10.0.3: jss-plugin-vendor-prefixer@^10.5.1:
version "10.5.0" version "10.5.1"
resolved "https://registry.yarnpkg.com/jss-plugin-vendor-prefixer/-/jss-plugin-vendor-prefixer-10.5.0.tgz#01f04cfff31f43f153f5d71972f5800b10a2eb84" resolved "https://registry.yarnpkg.com/jss-plugin-vendor-prefixer/-/jss-plugin-vendor-prefixer-10.5.1.tgz#45a183a3a0eb097bdfab0986b858d99920c0bbd8"
integrity sha512-rux3gmfwDdOKCLDx0IQjTwTm03IfBa+Rm/hs747cOw5Q7O3RaTUIMPKjtVfc31Xr/XI9Abz2XEupk1/oMQ7zRA== integrity sha512-cLkH6RaPZWHa1TqSfd2vszNNgxT1W0omlSjAd6hCFHp3KIocSrW21gaHjlMU26JpTHwkc+tJTCQOmE/O1A4FKQ==
dependencies: dependencies:
"@babel/runtime" "^7.3.1" "@babel/runtime" "^7.3.1"
css-vendor "^2.0.8" css-vendor "^2.0.8"
jss "10.5.0" jss "10.5.1"
jss@10.5.0, jss@^10.0.3: jss@10.5.1, jss@^10.5.1:
version "10.5.0" version "10.5.1"
resolved "https://registry.yarnpkg.com/jss/-/jss-10.5.0.tgz#0c2de8a29874b2dc8162ab7f34ef6573a87d9dd3" resolved "https://registry.yarnpkg.com/jss/-/jss-10.5.1.tgz#93e6b2428c840408372d8b548c3f3c60fa601c40"
integrity sha512-B6151NvG+thUg3murLNHRPLxTLwQ13ep4SH5brj4d8qKtogOx/jupnpfkPGSHPqvcwKJaCLctpj2lEk+5yGwMw== integrity sha512-hbbO3+FOTqVdd7ZUoTiwpHzKXIo5vGpMNbuXH1a0wubRSWLWSBvwvaq4CiHH/U42CmjOnp6lVNNs/l+Z7ZdDmg==
dependencies: dependencies:
"@babel/runtime" "^7.3.1" "@babel/runtime" "^7.3.1"
csstype "^3.0.2" csstype "^3.0.2"
@ -6806,6 +6806,11 @@ modify-values@^1.0.0:
resolved "https://registry.yarnpkg.com/modify-values/-/modify-values-1.0.1.tgz#b3939fa605546474e3e3e3c63d64bd43b4ee6022" resolved "https://registry.yarnpkg.com/modify-values/-/modify-values-1.0.1.tgz#b3939fa605546474e3e3e3c63d64bd43b4ee6022"
integrity sha512-xV2bxeN6F7oYjZWTe/YPAy6MN2M+sL4u/Rlm2AHCIVGfo2p1yGmBHQ6vHehl4bRTZBdHu3TSkWdYgkwpYzAGSw== integrity sha512-xV2bxeN6F7oYjZWTe/YPAy6MN2M+sL4u/Rlm2AHCIVGfo2p1yGmBHQ6vHehl4bRTZBdHu3TSkWdYgkwpYzAGSw==
moment@^2.29.1:
version "2.29.1"
resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.1.tgz#b2be769fa31940be9eeea6469c075e35006fa3d3"
integrity sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==
move-concurrently@^1.0.1: move-concurrently@^1.0.1:
version "1.0.1" version "1.0.1"
resolved "https://registry.yarnpkg.com/move-concurrently/-/move-concurrently-1.0.1.tgz#be2c005fda32e0b29af1f05d7c4b33214c701f92" resolved "https://registry.yarnpkg.com/move-concurrently/-/move-concurrently-1.0.1.tgz#be2c005fda32e0b29af1f05d7c4b33214c701f92"