Skip to content

Commit

Permalink
#17: Creates dialog to change label and color on dynamic mode
Browse files Browse the repository at this point in the history
  • Loading branch information
williamquintas committed Jun 15, 2022
1 parent 0822806 commit c1ecbb4
Show file tree
Hide file tree
Showing 8 changed files with 202 additions and 56 deletions.
8 changes: 0 additions & 8 deletions components/ColorPicker/ColorPicker.css
Original file line number Diff line number Diff line change
@@ -1,15 +1,7 @@
.color-picker {
margin-left: 8px;
}

.color-picker div {
display: flex !important;
}

label#color-picker-label {
padding-left: 10px;
}

.color-circle {
width: 12px;
height: 12px;
Expand Down
19 changes: 2 additions & 17 deletions components/ColorPicker/ColorPicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,7 @@ import {
SelectChangeEvent,
} from "@mui/material";
import { FunctionComponent } from "react";

export const Colors = {
Gray: "#212529",
Red: "#c92a2a",
Pink: "#a61e4d",
Grape: "#862e9c",
Violet: "#5f3dc4",
Indigo: "#364fc7",
Blue: "#1864ab",
Cyan: "#0b7285",
Teal: "#087f5b",
Green: "#2b8a3e",
Lime: "#5c940d",
Yellow: "#e67700",
Orange: "#d9480f",
};
import { Colors } from "../../utils/colors";

interface ColorPickerProps {
selectedColor: string;
Expand All @@ -33,7 +18,7 @@ const ColorPicker: FunctionComponent<ColorPickerProps> = ({
onChangeColor,
}) => {
return (
<FormControl sx={{ m: 1, minWidth: 120 }}>
<FormControl sx={{ my: 1, minWidth: 120 }} required>
<InputLabel id="color-picker-label">Color</InputLabel>
<Select
size="small"
Expand Down
83 changes: 66 additions & 17 deletions components/CoordinatesList/CoordinatesList.tsx
Original file line number Diff line number Diff line change
@@ -1,39 +1,80 @@
import { Circle, ExpandLess, ExpandMore } from "@mui/icons-material";
import { Circle, Edit, ExpandLess, ExpandMore } from "@mui/icons-material";
import {
Collapse,
Container,
Icon,
IconButton,
List,
ListItemButton,
ListItemIcon,
ListItemText,
Typography,
} from "@mui/material";
import { Fragment, FunctionComponent, useState } from "react";
import { Fragment, FunctionComponent, useEffect, useState } from "react";
import { IEntity } from "../../models/IEntity";
import EntityDialog from "../EntityDialog/EntityDialog";

interface CoordinatesListProps {
entity: IEntity;
}
const CoordinatesList: FunctionComponent<CoordinatesListProps> = ({
entity,
}) => {
const [open, setOpen] = useState<boolean>(false);
const { id, color, coordinates } = entity;
const [label, setLabel] = useState<string>("");
const [color, setColor] = useState<string>("");
const [isCollapseOpen, setIsCollapseOpen] = useState<boolean>(false);
const [isDialogOpen, setIsDialogOpen] = useState<boolean>(false);
const { coordinates } = entity;

useEffect(() => {
setLabel(entity.id);
setColor(entity.color);
}, [entity]);

return (
<Fragment>
<ListItemButton
onClick={() => {
setOpen(!open);
<div
style={{
display: "flex",
justifyContent: "space-between",
alignItems: "center",
backgroundColor: "#f1f3f5",
}}
sx={{ backgroundColor: "#f1f3f5" }}
>
<ListItemIcon sx={{ minWidth: 0, mr: 2, color }}>
<Circle fontSize="small" />
</ListItemIcon>
<ListItemText primary={id} />
{open ? <ExpandLess /> : <ExpandMore />}
</ListItemButton>
<Collapse in={open} timeout="auto" unmountOnExit>
<div
style={{
display: "flex",
flexDirection: "row",
alignItems: "center",
}}
>
<Icon sx={{ display: "flex", mx: 1, color }}>
<Circle fontSize="small" />
</Icon>

<Typography component="span" variant="body1">
{label}
</Typography>
</div>

<div>
<IconButton
onClick={() => {
setIsDialogOpen(true);
}}
sx={{ backgroundColor: "#f1f3f5" }}
>
<Edit fontSize="small" />
</IconButton>
<IconButton
onClick={() => {
setIsCollapseOpen(!isCollapseOpen);
}}
sx={{ backgroundColor: "#f1f3f5" }}
>
{isCollapseOpen ? <ExpandLess /> : <ExpandMore />}
</IconButton>
</div>
</div>
<Collapse in={isCollapseOpen} timeout="auto" unmountOnExit>
<Container sx={{ maxHeight: 200, overflow: "auto" }}>
<List component="div" disablePadding>
{coordinates?.map((row, index) => (
Expand All @@ -45,6 +86,14 @@ const CoordinatesList: FunctionComponent<CoordinatesListProps> = ({
</List>
</Container>
</Collapse>
<EntityDialog
open={isDialogOpen}
setOpen={setIsDialogOpen}
label={label}
setLabel={setLabel}
color={color}
setColor={setColor}
/>
</Fragment>
);
};
Expand Down
5 changes: 4 additions & 1 deletion components/DynamicModeContainer/DynamicModeContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ import { db } from "../../config/firebaseClient";
import { useAppDispatch, useAppSelector } from "../../config/hooks";
import { selectSession, updateEntities } from "../../features/sessions/slice";
import { ICoordinatesData } from "../../models/ICoordinatesData";
import { IEntity } from "../../models/IEntity";
import { getRandomColor } from "../../utils/colors";
import MapContainer from "../MapContainer/MapContainer";

interface DynamicModeContainerProps {
Expand All @@ -30,7 +32,8 @@ const DynamicModeContainer: FunctionComponent<DynamicModeContainerProps> = ({
const entitiesIds = [...new Set(coordinatesData?.map(({ id }) => id))];
return entitiesIds.map((entityId) => ({
id: entityId,
color: "#ff0000",
label: entityId,
color: getRandomColor(),
coordinates: coordinatesData.filter(({ id }) => id === entityId),
}));
};
Expand Down
97 changes: 97 additions & 0 deletions components/EntityDialog/EntityDialog.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import { Box } from "@mui/material";
import Button from "@mui/material/Button";
import Dialog from "@mui/material/Dialog";
import DialogActions from "@mui/material/DialogActions";
import DialogContent from "@mui/material/DialogContent";
import DialogTitle from "@mui/material/DialogTitle";
import TextField from "@mui/material/TextField";
import { FunctionComponent, useEffect, useState } from "react";
import ColorPicker from "../ColorPicker/ColorPicker";

interface EntityDialogProps {
open: boolean;
setOpen: (open: boolean) => void;
label: string;
setLabel: (label: string) => void;
color: string;
setColor: (color: string) => void;
}
const EntityDialog: FunctionComponent<EntityDialogProps> = ({
open,
setOpen,
label,
setLabel,
color,
setColor,
}) => {
const [currentColor, setCurrentColor] = useState<string>("");
const [currentLabel, setCurrentLabel] = useState<string>("");

useEffect(() => {
setCurrentColor(color);
setCurrentLabel(label);
}, [open]);

const handleSubmit = () => {
setColor(currentColor);
setLabel(currentLabel);
setOpen(false);
};

return (
<div>
<Dialog open={open} onClose={() => setOpen(false)}>
<DialogTitle>Edit entity</DialogTitle>

<DialogContent>
<Box
component="form"
onSubmit={handleSubmit}
noValidate
sx={{ mt: 1 }}
>
<div
style={{
display: "flex",
flexDirection: "row",
alignItems: "center",
justifyContent: "space-between",
}}
>
<div style={{ justifyContent: "flex-start", paddingRight: 8 }}>
<ColorPicker
selectedColor={currentColor}
onChangeColor={(evt) => setCurrentColor(evt.target.value)}
/>
</div>
<TextField
id="label"
name="label"
label="Label"
size="small"
value={currentLabel}
required
autoFocus
onChange={(evt) => setCurrentLabel(evt.target.value)}
sx={{ alignSelf: "center" }}
/>
</div>
<Button
onClick={handleSubmit}
type="button"
fullWidth
variant="contained"
>
Save
</Button>
</Box>
</DialogContent>
<DialogActions>
<Button onClick={() => setOpen(false)}>Cancel</Button>
</DialogActions>
</Dialog>
</div>
);
};

export default EntityDialog;
22 changes: 9 additions & 13 deletions components/FilesSelectionContainer/FilesSelectionContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,22 +20,15 @@ import {
editEntity,
selectEntities,
} from "../../features/sessions/slice";
import ColorPicker, { Colors } from "../ColorPicker/ColorPicker";
import { getRandomColor } from "../../utils/colors";
import ColorPicker from "../ColorPicker/ColorPicker";
import FileUploadButton from "../FileUploadButton/FileUploadButton";
import Link from "../Link/Link";

const FilesSelectionContainer: FunctionComponent = () => {
const dispatch = useAppDispatch();
const entities = useAppSelector(selectEntities);

const getRandomColor = (): string => {
const colors = Object.keys(Colors);
const index = Math.floor(Math.random() * colors.length);
const key = colors[index];

return Colors[key];
};

const parseFileData = (file: File) => {
Papa.parse(file, {
header: true,
Expand All @@ -44,6 +37,7 @@ const FilesSelectionContainer: FunctionComponent = () => {
dispatch(
createEntity({
id: file.name,
label: file.name,
color: getRandomColor(),
coordinates: data,
})
Expand Down Expand Up @@ -132,10 +126,12 @@ const FilesSelectionContainer: FunctionComponent = () => {
onDelete={() => onRemoveFile(id)}
deleteIcon={<Delete fontSize="small" />}
/>
<ColorPicker
selectedColor={color}
onChangeColor={(evt) => onChangeColor(id, evt)}
/>
<div style={{ paddingLeft: 8 }}>
<ColorPicker
selectedColor={color}
onChangeColor={(evt) => onChangeColor(id, evt)}
/>
</div>
</ListItem>
))}
</List>
Expand Down
1 change: 1 addition & 0 deletions models/IEntity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { ICoordinatesData } from "./ICoordinatesData";

export interface IEntity {
id: string;
label: string;
color: string;
coordinates: ICoordinatesData[];
}
23 changes: 23 additions & 0 deletions utils/colors.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
export const Colors = {
Gray: "#212529",
Red: "#c92a2a",
Pink: "#a61e4d",
Grape: "#862e9c",
Violet: "#5f3dc4",
Indigo: "#364fc7",
Blue: "#1864ab",
Cyan: "#0b7285",
Teal: "#087f5b",
Green: "#2b8a3e",
Lime: "#5c940d",
Yellow: "#e67700",
Orange: "#d9480f",
};

export const getRandomColor = (): string => {
const colors = Object.keys(Colors);
const index = Math.floor(Math.random() * colors.length);
const key = colors[index];

return Colors[key];
};

0 comments on commit c1ecbb4

Please sign in to comment.