diff --git a/editor.planx.uk/src/pages/Team.tsx b/editor.planx.uk/src/pages/Team.tsx index 5342a1efd4..c20a8cc8a5 100644 --- a/editor.planx.uk/src/pages/Team.tsx +++ b/editor.planx.uk/src/pages/Team.tsx @@ -1,9 +1,6 @@ import { gql } from "@apollo/client"; -import Edit from "@mui/icons-material/Edit"; -import Visibility from "@mui/icons-material/Visibility"; import Box from "@mui/material/Box"; import Button from "@mui/material/Button"; -import Chip from "@mui/material/Chip"; import Container from "@mui/material/Container"; import Dialog from "@mui/material/Dialog"; import DialogActions from "@mui/material/DialogActions"; @@ -14,9 +11,9 @@ import { styled } from "@mui/material/styles"; import Typography from "@mui/material/Typography"; import React, { useCallback, useEffect, useState } from "react"; import { Link, useNavigation } from "react-navi"; -import { FONT_WEIGHT_SEMI_BOLD } from "theme"; import { borderedFocusStyle } from "theme"; import { AddButton } from "ui/editor/AddButton"; +import FlowTag, { FlowTagType, StatusVariant } from "ui/editor/FlowTag"; import Input from "ui/shared/Input/Input"; import InputRow from "ui/shared/InputRow"; import InputRowItem from "ui/shared/InputRowItem"; @@ -31,7 +28,7 @@ import { FlowSummary } from "./FlowEditor/lib/store/editor"; import { formatLastEditMessage } from "./FlowEditor/utils"; const DashboardList = styled("ul")(({ theme }) => ({ - padding: theme.spacing(0, 0, 3), + padding: theme.spacing(3, 0), borderBottom: "1px solid #fff", margin: 0, display: "grid", @@ -40,40 +37,56 @@ const DashboardList = styled("ul")(({ theme }) => ({ gridGap: theme.spacing(2), })); -const DashboardListItem = styled("li")(({ theme }) => ({ +const FlowCard = styled("li")(({ theme }) => ({ listStyle: "none", position: "relative", display: "flex", flexDirection: "column", + justifyContent: "stretch", borderRadius: "4px", - backgroundColor: theme.palette.background.paper, + backgroundColor: theme.palette.background.default, border: `1px solid ${theme.palette.border.main}`, boxShadow: "0 2px 4px 0 rgba(0, 0, 0, 0.1)", + overflow: "hidden", })); -const DashboardLink = styled(Link)(({ theme }) => ({ - display: "block", - fontSize: theme.typography.h4.fontSize, +const FlowCardContent = styled(Box)(({ theme }) => ({ + position: "relative", + height: "100%", textDecoration: "none", color: "currentColor", - fontWeight: FONT_WEIGHT_SEMI_BOLD, padding: theme.spacing(2), + display: "flex", + flexDirection: "column", + gap: theme.spacing(1.5), margin: 0, width: "100%", +})); + +const DashboardLink = styled(Link)(({ theme }) => ({ + position: "absolute", + left: 0, + top: 0, + width: "100%", + height: "100%", + zIndex: 1, "&:focus-within": { ...borderedFocusStyle, }, })); -const StyledSimpleMenu = styled(SimpleMenu)(({ theme }) => ({ - display: "flex", - marginTop: "auto", -})); - const LinkSubText = styled(Box)(({ theme }) => ({ color: theme.palette.text.secondary, fontWeight: "normal", - paddingTop: "0.5em", + paddingTop: theme.spacing(0.75), +})); + +const StyledSimpleMenu = styled(SimpleMenu)(({ theme }) => ({ + display: "flex", + marginTop: "auto", + borderTop: `1px solid ${theme.palette.border.main}`, + backgroundColor: theme.palette.background.paper, + overflow: "hidden", })); const Confirm = ({ @@ -119,6 +132,7 @@ interface FlowItemProps { teamSlug: string; refreshFlows: () => void; } + const FlowItem: React.FC = ({ flow, flows, @@ -127,6 +141,7 @@ const FlowItem: React.FC = ({ refreshFlows, }) => { const [deleting, setDeleting] = useState(false); + const handleDelete = () => { useStore .getState() @@ -136,6 +151,7 @@ const FlowItem: React.FC = ({ refreshFlows(); }); }; + const handleCopy = () => { useStore .getState() @@ -144,6 +160,7 @@ const FlowItem: React.FC = ({ refreshFlows(); }); }; + const handleMove = (newTeam: string) => { useStore .getState() @@ -153,9 +170,8 @@ const FlowItem: React.FC = ({ }); }; - const getStatusColor = (status: string) => { - return status === "online" ? "success" : "secondary"; - }; + const statusVariant = + flow.status === "online" ? StatusVariant.Online : StatusVariant.Offline; return ( <> @@ -171,23 +187,33 @@ const FlowItem: React.FC = ({ submitLabel="Delete Service" /> )} - - - - {flow.name} + + + + + {flow.name} + + + {formatLastEditMessage( + flow.operations[0].createdAt, + flow.operations[0]?.actor, + )} + + + + + {flow.status} + + + + a": { position: "relative", zIndex: 2 } }} + > + Allows users to apply for prior approval that is required for some + types of... read more - - {formatLastEditMessage( - flow.operations[0].createdAt, - flow.operations[0]?.actor, - )} - - - + {useStore.getState().canUserEditTeam(teamSlug) && ( = ({ ]} /> )} - + ); }; @@ -343,60 +369,82 @@ const Team: React.FC = () => { const showAddFlowButton = teamHasFlows && canUserEditTeam(slug); return ( - - + + - - Services - - {/* {canUserEditTeam(slug) ? : } */} - {showAddFlowButton && } - - - - - Search - - - - - + + + Services + + {/* {canUserEditTeam(slug) ? : } */} + {showAddFlowButton && } + + + + + Search + + + + + + - - - {teamHasFlows && ( - - {flows.map((flow) => ( - { - fetchFlows(); + + {teamHasFlows && ( + <> + - ))} - - )} - {flows && !flows.length && } - + > + + Showing all services + + Order toggle + + + + {flows.map((flow) => ( + { + fetchFlows(); + }} + /> + ))} + + + )} + {flows && !flows.length && } + + ); }; diff --git a/editor.planx.uk/src/pages/layout/AuthenticatedLayout.tsx b/editor.planx.uk/src/pages/layout/AuthenticatedLayout.tsx index 97b070d191..321bb225c1 100644 --- a/editor.planx.uk/src/pages/layout/AuthenticatedLayout.tsx +++ b/editor.planx.uk/src/pages/layout/AuthenticatedLayout.tsx @@ -24,7 +24,7 @@ const DashboardContainer = styled(Box)(({ theme }) => ({ flexDirection: "row", width: "100%", overflow: "hidden", - [`& > .${containerClasses.root}`]: { + [`& > .${containerClasses.root}, & > div > .${containerClasses.root}`]: { paddingTop: theme.spacing(3), paddingBottom: theme.spacing(3), [theme.breakpoints.up("lg")]: { diff --git a/editor.planx.uk/src/ui/editor/FlowTag.tsx b/editor.planx.uk/src/ui/editor/FlowTag.tsx new file mode 100644 index 0000000000..de1fa7ec68 --- /dev/null +++ b/editor.planx.uk/src/ui/editor/FlowTag.tsx @@ -0,0 +1,69 @@ +import Box from "@mui/material/Box"; +import { styled } from "@mui/material/styles"; +import React from "react"; +import { FONT_WEIGHT_SEMI_BOLD } from "theme"; + +export enum FlowTagType { + Status = "status", + ApplicationType = "applicationType", + ServiceType = "serviceType", +} + +export enum StatusVariant { + Online = "online", + Offline = "offline", +} + +const BG_ONLINE = "#D6FFD7"; +const BG_OFFLINE = "#EAEAEA"; +const BG_APPLICATION_TYPE = "#D6EFFF"; +const BG_SERVICE_TYPE = "#FFEABE"; + +const Root = styled(Box, { + shouldForwardProp: (prop) => prop !== "tagType" && prop !== "statusVariant", +})(({ theme, tagType, statusVariant }) => ({ + fontSize: theme.typography.body2.fontSize, + fontWeight: FONT_WEIGHT_SEMI_BOLD, + padding: "2px 6px", + display: "flex", + alignItems: "center", + gap: theme.spacing(0.5), + borderRadius: "4px", + textTransform: "capitalize", + border: "1px solid rgba(0, 0, 0, 0.2)", + ...(tagType === FlowTagType.Status && { + backgroundColor: + statusVariant === StatusVariant.Online ? BG_ONLINE : BG_OFFLINE, + "&::before": { + content: '""', + width: "8px", + height: "8px", + borderRadius: "50%", + background: + statusVariant === StatusVariant.Online + ? theme.palette.success.main + : "#a1a1a1", + }, + }), + ...(tagType === FlowTagType.ApplicationType && { + backgroundColor: BG_APPLICATION_TYPE, + }), + ...(tagType === FlowTagType.ServiceType && { + backgroundColor: BG_SERVICE_TYPE, + }), +})); + +export interface Props { + id?: string; + tagType: FlowTagType; + statusVariant?: StatusVariant; + children?: React.ReactNode; +} + +const FlowTag: React.FC = ({ id, tagType, statusVariant, children }) => ( + + {children} + +); + +export default FlowTag;