From d4b37f4139ea04c327148fe2e3b4b08ddafaa260 Mon Sep 17 00:00:00 2001 From: Matias Arriola Date: Fri, 11 Feb 2022 21:23:06 +0000 Subject: [PATCH] Add labels support. --- .../delete-multiselect-dialog/index.tsx | 9 +- .../maps-page/action-dispatcher/index.tsx | 7 +- .../action-dispatcher/label-dialog/index.tsx | 45 +++--- .../webapp/src/components/maps-page/index.tsx | 13 +- .../maps-list/add-label-button/index.tsx | 72 --------- .../maps-list/add-label-form/index.tsx | 94 +++++++++++ .../maps-list/add-label-form/styled.ts | 25 +++ .../components/maps-page/maps-list/index.tsx | 116 ++++++++------ .../maps-list/label-delete-confirm/index.tsx | 45 ++++++ .../maps-list/label-selector/index.tsx | 146 +++++------------- .../maps-list/label-selector/styled.ts | 39 +---- .../maps-page/maps-list/label/index.tsx | 43 ++++-- .../maps-page/maps-list/label/styled.ts | 32 ++-- .../components/maps-page/maps-list/styled.ts | 7 + 14 files changed, 372 insertions(+), 321 deletions(-) delete mode 100644 packages/webapp/src/components/maps-page/maps-list/add-label-button/index.tsx create mode 100644 packages/webapp/src/components/maps-page/maps-list/add-label-form/index.tsx create mode 100644 packages/webapp/src/components/maps-page/maps-list/add-label-form/styled.ts create mode 100644 packages/webapp/src/components/maps-page/maps-list/label-delete-confirm/index.tsx diff --git a/packages/webapp/src/components/maps-page/action-dispatcher/delete-multiselect-dialog/index.tsx b/packages/webapp/src/components/maps-page/action-dispatcher/delete-multiselect-dialog/index.tsx index 6e1cb9cd..e2dd6493 100644 --- a/packages/webapp/src/components/maps-page/action-dispatcher/delete-multiselect-dialog/index.tsx +++ b/packages/webapp/src/components/maps-page/action-dispatcher/delete-multiselect-dialog/index.tsx @@ -4,20 +4,15 @@ import { useMutation, useQueryClient } from 'react-query'; import { useSelector } from 'react-redux'; import Client from '../../../../classes/client'; import { activeInstance } from '../../../../redux/clientSlice'; -import { handleOnMutationSuccess } from '..'; +import { handleOnMutationSuccess, MultiDialogProps } from '..'; import BaseDialog from '../base-dialog'; import Alert from '@mui/material/Alert'; import AlertTitle from '@mui/material/AlertTitle'; -export type DeleteMultiselectDialogProps = { - mapsId: number[]; - onClose: () => void; -}; - const DeleteMultiselectDialog = ({ onClose, mapsId, -}: DeleteMultiselectDialogProps): React.ReactElement => { +}: MultiDialogProps): React.ReactElement => { const intl = useIntl(); const client: Client = useSelector(activeInstance); const queryClient = useQueryClient(); diff --git a/packages/webapp/src/components/maps-page/action-dispatcher/index.tsx b/packages/webapp/src/components/maps-page/action-dispatcher/index.tsx index c8359ad5..02a5960e 100644 --- a/packages/webapp/src/components/maps-page/action-dispatcher/index.tsx +++ b/packages/webapp/src/components/maps-page/action-dispatcher/index.tsx @@ -62,7 +62,7 @@ const ActionDispatcher = ({ mapsId, action, onClose, fromEditor }: ActionDialogP )} {action === 'share' && } - {action === 'label' && } + {action === 'label' && } ); }; @@ -81,4 +81,9 @@ export type SimpleDialogProps = { onClose: () => void; }; +export type MultiDialogProps = { + mapsId: number[]; + onClose: () => void; +}; + export default ActionDispatcher; diff --git a/packages/webapp/src/components/maps-page/action-dispatcher/label-dialog/index.tsx b/packages/webapp/src/components/maps-page/action-dispatcher/label-dialog/index.tsx index 37fb8759..99843fbc 100644 --- a/packages/webapp/src/components/maps-page/action-dispatcher/label-dialog/index.tsx +++ b/packages/webapp/src/components/maps-page/action-dispatcher/label-dialog/index.tsx @@ -1,16 +1,19 @@ import React from 'react'; -import BaseDialog from '../base-dialog'; -import { SimpleDialogProps } from '..'; -import { useIntl } from 'react-intl'; -import Client, { ErrorInfo, Label, MapInfo } from '../../../../classes/client'; -import { useStyles } from './style'; -import { LabelSelector } from '../../maps-list/label-selector'; -import { useMutation, useQuery, useQueryClient } from 'react-query'; import { useSelector } from 'react-redux'; +import { FormattedMessage, useIntl } from 'react-intl'; +import { useMutation, useQuery, useQueryClient } from 'react-query'; +import Typography from '@mui/material/Typography'; + +import { useStyles } from './style'; +import { MultiDialogProps } from '..'; +import BaseDialog from '../base-dialog'; +import Client, { ErrorInfo, Label, MapInfo } from '../../../../classes/client'; +import { LabelSelector } from '../../maps-list/label-selector'; import { activeInstance } from '../../../../redux/clientSlice'; +import { ChangeLabelMutationFunctionParam, getChangeLabelMutationFunction } from '../../maps-list'; -const LabelDialog = ({ mapId, onClose }: SimpleDialogProps): React.ReactElement => { +const LabelDialog = ({ mapsId, onClose }: MultiDialogProps): React.ReactElement => { const intl = useIntl(); const classes = useStyles(); const client: Client = useSelector(activeInstance); @@ -21,19 +24,10 @@ const LabelDialog = ({ mapId, onClose }: SimpleDialogProps): React.ReactElement return client.fetchAllMaps(); }); - const map = data.find(m => m.id === mapId); + const maps = data.filter(m => mapsId.includes(m.id)); - const changeLabelMutation = useMutation( - async ({ label, checked }) => { - if (!label.id) { - label.id = await client.createLabel(label.title, label.color); - } - if (checked){ - return client.addLabelToMap(label.id, mapId); - } else { - return client.deleteLabelFromMap(label.id, mapId); - } - }, + const changeLabelMutation = useMutation( + getChangeLabelMutationFunction(client), { onSuccess: () => { queryClient.invalidateQueries('maps'); @@ -47,6 +41,7 @@ const LabelDialog = ({ mapId, onClose }: SimpleDialogProps): React.ReactElement const handleChangesInLabels = (label: Label, checked: boolean) => { changeLabelMutation.mutate({ + maps, label, checked }); @@ -63,11 +58,17 @@ const LabelDialog = ({ mapId, onClose }: SimpleDialogProps): React.ReactElement description={intl.formatMessage({ id: 'label.description', defaultMessage: - 'Use labels to organize your maps', + 'Use labels to organize your maps.', })} PaperProps={{ classes: { root: classes.paper } }} > - + <> + + + { maps.map(m => m.title).join(', ') } + + + ); }; diff --git a/packages/webapp/src/components/maps-page/index.tsx b/packages/webapp/src/components/maps-page/index.tsx index 9960906f..26d386cd 100644 --- a/packages/webapp/src/components/maps-page/index.tsx +++ b/packages/webapp/src/components/maps-page/index.tsx @@ -40,6 +40,7 @@ import ListItemSecondaryAction from '@mui/material/ListItemSecondaryAction'; import logoIcon from './logo-small.svg'; import poweredByIcon from './pwrdby-white.svg'; +import LabelDeleteConfirm from './maps-list/label-delete-confirm'; export type Filter = GenericFilter | LabelFilter; @@ -64,7 +65,7 @@ const MapsPage = (): ReactElement => { const client: Client = useSelector(activeInstance); const queryClient = useQueryClient(); const [activeDialog, setActiveDialog] = React.useState(undefined); - + const [labelToDelete, setLabelToDelete] = React.useState(null); // Reload based on user preference ... const userLocale = AppI18n.getUserLocale(); @@ -239,7 +240,7 @@ const MapsPage = (): ReactElement => { filter={buttonInfo.filter} active={filter} onClick={handleMenuClick} - onDelete={handleLabelDelete} + onDelete={setLabelToDelete} key={`${buttonInfo.filter.type}:${buttonInfo.label}`} /> ); @@ -260,6 +261,14 @@ const MapsPage = (): ReactElement => { + { labelToDelete && setLabelToDelete(null)} + onConfirm={() => { + handleLabelDelete(labelToDelete); + setLabelToDelete(null); + }} + label={labels.find(l => l.id === labelToDelete)} + /> } ); }; diff --git a/packages/webapp/src/components/maps-page/maps-list/add-label-button/index.tsx b/packages/webapp/src/components/maps-page/maps-list/add-label-button/index.tsx deleted file mode 100644 index 0c37dc7f..00000000 --- a/packages/webapp/src/components/maps-page/maps-list/add-label-button/index.tsx +++ /dev/null @@ -1,72 +0,0 @@ -import React from 'react'; -import Popover from '@mui/material/Popover'; -import Button from '@mui/material/Button'; -import Tooltip from '@mui/material/Tooltip'; -import LabelTwoTone from '@mui/icons-material/LabelTwoTone'; -import { FormattedMessage, useIntl } from 'react-intl'; -import { Label, MapInfo } from '../../../../classes/client'; -import { LabelSelector } from '../label-selector'; - -type AddLabelButtonTypes = { - maps: MapInfo[]; - onChange: (label: Label, checked: boolean) => void; -}; - -export function AddLabelButton({ onChange, maps }: AddLabelButtonTypes): React.ReactElement { - const intl = useIntl(); - - const [anchorEl, setAnchorEl] = React.useState(null); - - const handleClick = (event: React.MouseEvent) => { - setAnchorEl(event.currentTarget); - }; - - const handleClose = () => { - setAnchorEl(null); - }; - - const open = Boolean(anchorEl); - const id = open ? 'add-label-popover' : undefined; - - return ( - <> - - - - - - - - - ); -} diff --git a/packages/webapp/src/components/maps-page/maps-list/add-label-form/index.tsx b/packages/webapp/src/components/maps-page/maps-list/add-label-form/index.tsx new file mode 100644 index 00000000..4609a2e5 --- /dev/null +++ b/packages/webapp/src/components/maps-page/maps-list/add-label-form/index.tsx @@ -0,0 +1,94 @@ +import React from 'react'; +import { useIntl } from 'react-intl'; +import AddIcon from '@mui/icons-material/Add'; +import TextField from '@mui/material/TextField'; + +import { Label } from '../../../../classes/client'; +import { StyledButton, NewLabelContainer, NewLabelColor, CreateLabel } from './styled'; +import { Tooltip } from '@mui/material'; + +const labelColors = [ + '#00b327', + '#0565ff', + '#2d2dd6', + '#6a00ba', + '#ad1599', + '#ff1e35', + '#ff6600', + '#ffff47', +]; + +type AddLabelFormProps = { + onAdd: (newLabel: Label) => void; +}; + +export default function AddLabelForm({ onAdd }: AddLabelFormProps): React.ReactElement { + const intl = useIntl(); + const [createLabelColorIndex, setCreateLabelColorIndex] = React.useState( + Math.floor(Math.random() * labelColors.length) + ); + const [newLabelTitle, setNewLabelTitle] = React.useState(''); + + const newLabelColor = labelColors[createLabelColorIndex]; + + const setNextLabelColorIndex = () => { + const nextIndex = labelColors[createLabelColorIndex + 1] ? createLabelColorIndex + 1 : 0; + setCreateLabelColorIndex(nextIndex); + }; + + const handleSubmitNew = () => { + onAdd({ + title: newLabelTitle, + color: newLabelColor, + id: 0, + }); + setNewLabelTitle(''); + setNextLabelColorIndex(); + }; + + return ( + + + + { + e.stopPropagation(); + setNextLabelColorIndex(); + }} + /> + + setNewLabelTitle(e.target.value)} + onKeyPress={(e) => { + if (e.key === 'Enter') { + handleSubmitNew(); + } + }} + value={newLabelTitle} + /> + handleSubmitNew()} + disabled={!newLabelTitle.length} + aria-label={intl.formatMessage({ + id: 'label.add-button', + defaultMessage: 'Add label', + })} + > + + + + + ); +} diff --git a/packages/webapp/src/components/maps-page/maps-list/add-label-form/styled.ts b/packages/webapp/src/components/maps-page/maps-list/add-label-form/styled.ts new file mode 100644 index 00000000..ef1da495 --- /dev/null +++ b/packages/webapp/src/components/maps-page/maps-list/add-label-form/styled.ts @@ -0,0 +1,25 @@ +import styled from 'styled-components'; +import IconButton from '@mui/material/IconButton'; +import LabelTwoTone from '@mui/icons-material/LabelTwoTone'; + +export const StyledButton = styled(IconButton)` + margin: 4px; +`; + +export const NewLabelContainer = styled.div` + display: flex; + flex-direction: row; + align-items: center; +`; + +export const NewLabelColor = styled(LabelTwoTone)` + margin-right: 12px; + cursor: pointer; +`; + +export const CreateLabel = styled.div` + padding-top: 10px; + display: flex; + flex-direction: column; + justify-content: flex-end; +`; diff --git a/packages/webapp/src/components/maps-page/maps-list/index.tsx b/packages/webapp/src/components/maps-page/maps-list/index.tsx index 32dfb83d..8b558732 100644 --- a/packages/webapp/src/components/maps-page/maps-list/index.tsx +++ b/packages/webapp/src/components/maps-page/maps-list/index.tsx @@ -33,13 +33,13 @@ import MoreHorizIcon from '@mui/icons-material/MoreHoriz'; import StarRateRoundedIcon from '@mui/icons-material/StarRateRounded'; import SearchIcon from '@mui/icons-material/Search'; -import { AddLabelButton } from './add-label-button'; import relativeTime from 'dayjs/plugin/relativeTime'; import { LabelsCell } from './labels-cell'; import LocalizedFormat from 'dayjs/plugin/localizedFormat'; import AppI18n from '../../../classes/app-i18n'; +import LabelTwoTone from '@mui/icons-material/LabelTwoTone'; -dayjs.extend(LocalizedFormat) +dayjs.extend(LocalizedFormat); dayjs.extend(relativeTime); function descendingComparator(a: T, b: T, orderBy: keyof T) { @@ -59,9 +59,9 @@ function getComparator( order: Order, orderBy: Key ): ( - a: { [key in Key]: number | string | boolean | Label[] | undefined }, - b: { [key in Key]: number | string | Label[] | boolean } - ) => number { + a: { [key in Key]: number | string | boolean | Label[] | undefined }, + b: { [key in Key]: number | string | Label[] | boolean } +) => number { return order === 'desc' ? (a, b) => descendingComparator(a, b, orderBy) : (a, b) => -descendingComparator(a, b, orderBy); @@ -236,6 +236,24 @@ const mapsFilter = (filter: Filter, search: string): ((mapInfo: MapInfo) => bool }; }; +export type ChangeLabelMutationFunctionParam = { maps: MapInfo[]; label: Label; checked: boolean }; + +export const getChangeLabelMutationFunction = + (client: Client) => + async ({ maps, label, checked }: ChangeLabelMutationFunctionParam): Promise => { + if (!label.id) { + label.id = await client.createLabel(label.title, label.color); + } + if (checked) { + const toAdd = maps.filter((m) => !m.labels.find((l) => l.id === label.id)); + await Promise.all(toAdd.map((m) => client.addLabelToMap(label.id, m.id))); + } else { + const toRemove = maps.filter((m) => m.labels.find((l) => l.id === label.id)); + await Promise.all(toRemove.map((m) => client.deleteLabelFromMap(label.id, m.id))); + } + return Promise.resolve(); + }; + export const MapsList = (props: MapsListProps): React.ReactElement => { const classes = useStyles(); const [order, setOrder] = React.useState('desc'); @@ -384,7 +402,19 @@ export const MapsList = (props: MapsListProps): React.ReactElement => { }); }; - const removeLabelMultation = useMutation( + const handleAddLabelClick = () => { + setActiveDialog({ + actionType: 'label', + mapsId: selected, + }); + }; + + const removeLabelMultation = useMutation< + void, + ErrorInfo, + { mapId: number; labelId: number }, + number + >( ({ mapId, labelId }) => { return client.deleteLabelFromMap(labelId, mapId); }, @@ -402,40 +432,6 @@ export const MapsList = (props: MapsListProps): React.ReactElement => { removeLabelMultation.mutate({ mapId, labelId }); }; - const changeLabelMutation = useMutation( - async ({ mapIds, label, checked }) => { - const selectedMaps: MapInfo[] = mapsInfo.filter((m) => mapIds.includes(m.id)); - if (!label.id) { - label.id = await client.createLabel(label.title, label.color); - } - if (checked) { - const toAdd = selectedMaps.filter((m) => !m.labels.find((l) => l.id === label.id)); - await Promise.all(toAdd.map((m) => client.addLabelToMap(label.id, m.id))); - } else { - const toRemove = selectedMaps.filter((m) => m.labels.find((l) => l.id === label.id)); - await Promise.all(toRemove.map((m) => client.deleteLabelFromMap(label.id, m.id))); - } - return Promise.resolve(); - }, - { - onSuccess: () => { - queryClient.invalidateQueries('maps'); - queryClient.invalidateQueries('labels'); - }, - onError: (error) => { - console.error(error); - } - } - ); - - const handleChangesInLabels = (label: Label, checked: boolean) => { - changeLabelMutation.mutate({ - mapIds: selected, - label, - checked - }); - }; - const isSelected = (id: number) => selected.indexOf(id) !== -1; return (
@@ -470,10 +466,31 @@ export const MapsList = (props: MapsListProps): React.ReactElement => { )} - {selected.length > 0 && isSelected(m.id))} - />} + {selected.length > 0 && ( + + + + )}
@@ -614,10 +631,13 @@ export const MapsList = (props: MapsListProps): React.ReactElement => { - - { - handleRemoveLabel(row.id, lbl.id); - }} /> + + { + handleRemoveLabel(row.id, lbl.id); + }} + /> diff --git a/packages/webapp/src/components/maps-page/maps-list/label-delete-confirm/index.tsx b/packages/webapp/src/components/maps-page/maps-list/label-delete-confirm/index.tsx new file mode 100644 index 00000000..4817f864 --- /dev/null +++ b/packages/webapp/src/components/maps-page/maps-list/label-delete-confirm/index.tsx @@ -0,0 +1,45 @@ +import React from 'react'; +import { FormattedMessage, useIntl } from 'react-intl'; +import Alert from '@mui/material/Alert'; +import AlertTitle from '@mui/material/AlertTitle'; +import Typography from '@mui/material/Typography'; + +import BaseDialog from '../../action-dispatcher/base-dialog'; +import { Label } from '../../../../classes/client'; + +export type LabelDeleteConfirmType = { + label: Label; + onClose: () => void; + onConfirm: () => void; +}; + +const LabelDeleteConfirm = ({ label, onClose, onConfirm }: LabelDeleteConfirmType): React.ReactElement => { + const intl = useIntl(); + + return ( +
+ + + {intl.formatMessage({ id: 'label.delete-title', defaultMessage: 'Confirm label deletion' })} + + {label.title} + + + + +
+ ); +}; + +export default LabelDeleteConfirm; diff --git a/packages/webapp/src/components/maps-page/maps-list/label-selector/index.tsx b/packages/webapp/src/components/maps-page/maps-list/label-selector/index.tsx index 9e2b74c7..02235adf 100644 --- a/packages/webapp/src/components/maps-page/maps-list/label-selector/index.tsx +++ b/packages/webapp/src/components/maps-page/maps-list/label-selector/index.tsx @@ -1,125 +1,55 @@ import React from 'react'; import FormGroup from '@mui/material/FormGroup'; import FormControlLabel from '@mui/material/FormControlLabel'; -import Divider from '@mui/material/Divider'; -import AddIcon from '@mui/icons-material/Add'; import Checkbox from '@mui/material/Checkbox'; import Container from '@mui/material/Container'; -import { Label as LabelComponent } from '../label'; +import LabelComponent from '../label'; import Client, { Label, ErrorInfo, MapInfo } from '../../../../classes/client'; import { useQuery } from 'react-query'; import { useSelector } from 'react-redux'; import { activeInstance } from '../../../../redux/clientSlice'; -import { StyledButton, NewLabelContainer, NewLabelColor, CreateLabel } from './styled'; -import { TextField } from '@mui/material'; -import { FormattedMessage, useIntl } from 'react-intl'; -import Typography from '@mui/material/Typography'; - -const labelColors = [ - '#00b327', - '#0565ff', - '#2d2dd6', - '#6a00ba', - '#ad1599', - '#ff1e35', - '#ff6600', - '#ffff47', -]; +import AddLabelForm from '../add-label-form'; +import { LabelListContainer } from './styled'; export type LabelSelectorProps = { - maps: MapInfo[]; - onChange: (label: Label, checked: boolean) => void; + maps: MapInfo[]; + onChange: (label: Label, checked: boolean) => void; }; export function LabelSelector({ onChange, maps }: LabelSelectorProps): React.ReactElement { - const client: Client = useSelector(activeInstance); - const intl = useIntl(); + const client: Client = useSelector(activeInstance); + const { data: labels = [] } = useQuery('labels', async () => + client.fetchLabels() + ); - const { data: labels = [] } = useQuery('labels', async () => client.fetchLabels()); + const checkedLabelIds = labels + .map((l) => l.id) + .filter((labelId) => maps.every((m) => m.labels.find((l) => l.id === labelId))); - const checkedLabelIds = labels.map(l => l.id).filter(labelId => maps.every(m => m.labels.find(l => l.id === labelId))); - - const [createLabelColorIndex, setCreateLabelColorIndex] = React.useState(Math.floor(Math.random() * labelColors.length)); - const [newLabelTitle, setNewLabelTitle] = React.useState(''); - - const newLabelColor = labelColors[createLabelColorIndex]; - - const setNextLabelColorIndex = () => { - const nextIndex = labelColors[createLabelColorIndex + 1] ? - createLabelColorIndex + 1 : - 0; - setCreateLabelColorIndex(nextIndex); - }; - - - const handleSubmitNew = () => { - onChange({ - title: newLabelTitle, - color: newLabelColor, - id: 0, - }, true); - setNewLabelTitle(''); - setNextLabelColorIndex(); - }; - - return ( - - - {labels.map(({ id, title, color}) => ( - { - onChange({ id, title, color }, e.target.checked); - }} - name={title} - color="primary" - /> - } - label={} - /> - ))} - - - - - - - { - e.stopPropagation(); - setNextLabelColorIndex(); - }} - /> - setNewLabelTitle(e.target.value)} - onKeyPress={(e) => { - if (e.key === 'Enter') { - handleSubmitNew(); - } - }} - value={newLabelTitle} /> - - } - onClick={() => handleSubmitNew()} - disabled={!newLabelTitle.length} - > - - - - - - - ); + return ( + + + onChange(label, true)} /> + + + {labels.map(({ id, title, color }) => ( + { + onChange({ id, title, color }, e.target.checked); + }} + name={title} + color="primary" + /> + } + label={} + /> + ))} + + + ); } diff --git a/packages/webapp/src/components/maps-page/maps-list/label-selector/styled.ts b/packages/webapp/src/components/maps-page/maps-list/label-selector/styled.ts index 289353b3..b2e697c5 100644 --- a/packages/webapp/src/components/maps-page/maps-list/label-selector/styled.ts +++ b/packages/webapp/src/components/maps-page/maps-list/label-selector/styled.ts @@ -1,33 +1,8 @@ -import styled, { css } from 'styled-components'; -import Button from '@mui/material/Button'; +import FormGroup from '@mui/material/FormGroup'; +import styled from 'styled-components'; -export const StyledButton = styled(Button)` - margin: 4px; -`; - -export const NewLabelContainer = styled.div` - display: flex; - flex-direction: row; - align-items: center; - padding: 15px 0 5px 0 ; -`; - -const SIZE = 25; -export const NewLabelColor = styled.div` - width: ${SIZE}px; - height: ${SIZE}px; - border-radius: ${SIZE * 0.25}px; - border: 1px solid black; - margin: 1px ${SIZE * 0.5}px 1px 0px; - ${props => props.color && css` - background-color: ${props.color}; - `} - cursor: pointer; -`; - -export const CreateLabel = styled.div` - padding-top: 10px; - display: flex; - flex-direction: column; - justify-content: flex-end; -`; +export const LabelListContainer = styled(FormGroup)` + max-height: 400px; + flex-wrap: nowrap; + overflow-y: scroll; +`; \ No newline at end of file diff --git a/packages/webapp/src/components/maps-page/maps-list/label/index.tsx b/packages/webapp/src/components/maps-page/maps-list/label/index.tsx index 5ca36096..151ddf5f 100644 --- a/packages/webapp/src/components/maps-page/maps-list/label/index.tsx +++ b/packages/webapp/src/components/maps-page/maps-list/label/index.tsx @@ -1,13 +1,38 @@ import React from 'react'; -import { Color, StyledLabel, Name } from './styled'; +import { LabelContainer, LabelText } from './styled'; -type Props = { name: string, color: string }; +import { Label } from '../../../../classes/client'; +import LabelTwoTone from '@mui/icons-material/LabelTwoTone'; +import DeleteIcon from '@mui/icons-material/Clear'; +import IconButton from '@mui/material/IconButton'; -export function Label({ name, color }: Props): React.ReactElement { - return ( - - - {name} - - ); + +type LabelSize = 'small' | 'big'; +type LabelComponentProps = { label: Label; onDelete?: (label: Label) => void; size?: LabelSize }; + +export default function LabelComponent({ label, onDelete, size = 'small' }: LabelComponentProps): React.ReactElement { + const iconSize = size === 'small' ? { + height: '0.6em', width: '0.6em' + } : { height: '0.9em', width: '0.9em' }; + + return ( + + + {label.title} + {onDelete && ( + { + e.stopPropagation(); + onDelete(label); + }} + > + + + )} + + ); } diff --git a/packages/webapp/src/components/maps-page/maps-list/label/styled.ts b/packages/webapp/src/components/maps-page/maps-list/label/styled.ts index 4c48bfd9..eab7c0cb 100644 --- a/packages/webapp/src/components/maps-page/maps-list/label/styled.ts +++ b/packages/webapp/src/components/maps-page/maps-list/label/styled.ts @@ -1,23 +1,15 @@ -import styled, { css } from 'styled-components'; +import styled from 'styled-components'; -const SIZE = 20; - -export const Color = styled.div` - width: ${SIZE}px; - height: ${SIZE}px; - border-radius: ${SIZE * 0.25}px; - border: 1px solid black; - margin: 1px ${SIZE * 0.5}px 1px 0px; - ${props => props.color && css` - background-color: ${props.color}; - `} -`; - -export const StyledLabel = styled.div` - display: flex; +export const LabelContainer = styled.div` + display: inline-flex; flex-direction: row; + margin: 4px; + padding: 4px; + align-items: center; + font-size: smaller; `; - -export const Name = styled.div` - flex: 1; -`; + +export const LabelText = styled.span` + margin-left: 4px; + margin-right: 2px; +`; \ No newline at end of file diff --git a/packages/webapp/src/components/maps-page/maps-list/styled.ts b/packages/webapp/src/components/maps-page/maps-list/styled.ts index d0a4335e..55e32fee 100644 --- a/packages/webapp/src/components/maps-page/maps-list/styled.ts +++ b/packages/webapp/src/components/maps-page/maps-list/styled.ts @@ -33,6 +33,13 @@ export const useStyles = makeStyles((theme: Theme) => bodyCell: { border: '0px', }, + labelsCell: { + maxWidth: '300px', + overflow: 'hidden', + textAlign: 'right', + whiteSpace: 'nowrap', + textOverflow: 'ellipsis' + }, visuallyHidden: { border: 0, clip: 'rect(0 0 0 0)',