Skip to content

Commit

Permalink
feat: toggle node images and data fields on editor graph (#3789)
Browse files Browse the repository at this point in the history
  • Loading branch information
jessicamcinchak authored Oct 16, 2024
1 parent 3932adb commit d2fe0cc
Show file tree
Hide file tree
Showing 10 changed files with 203 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,11 @@ import { Link } from "react-navi";

import { useStore } from "../../../lib/store";
import { getParentId } from "../lib/utils";
import { DataField } from "./DataField";
import Hanger from "./Hanger";
import Node from "./Node";
import { Tag } from "./Tag";
import { Thumbnail } from "./Thumbnail";

type Props = {
type: TYPES;
Expand Down Expand Up @@ -92,9 +94,18 @@ const Checklist: React.FC<Props> = React.memo((props) => {
onContextMenu={handleContext}
ref={drag}
>
{props.data?.img && (
<Thumbnail
imageSource={props.data?.img}
imageAltText={props.data?.text}
/>
)}
{Icon && <Icon />}
<span>{props.text}</span>
</Link>
{props.data?.fn && (
<DataField value={props.data.fn} variant="parent" />
)}
{props.tags?.map((tag) => <Tag tag={tag} key={tag} />)}
</Box>
{groupedOptions ? (
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import Box from "@mui/material/Box";
import { useStore } from "pages/FlowEditor/lib/store";
import React from "react";

export const DataField: React.FC<{
value: string;
variant: "parent" | "child";
}> = ({ value, variant }) => {
const showDataFields = useStore((state) => state.showDataFields);
if (!showDataFields) return null;

return (
<Box
sx={(theme) => ({
fontFamily: theme.typography.data.fontFamily,
fontSize: theme.typography.data,
backgroundColor: "#f0f0f0",
borderColor:
variant === "parent"
? theme.palette.common.black
: theme.palette.grey[400],
borderWidth:
variant === "parent" ? "0 1px 1px 1px" : "1px 0 0 0",
borderStyle: "solid",
width: "100%",
p: 0.5,
textAlign: "center",
})}
>
{value}
</Box>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@ import React from "react";
import { Link } from "react-navi";

import { useStore } from "../../../lib/store";
import { DataField } from "./DataField";
import Hanger from "./Hanger";
import Node from "./Node";
import { Thumbnail } from "./Thumbnail";

const Option: React.FC<any> = (props) => {
const childNodes = useStore((state) => state.childNodesOf(props.id));
Expand All @@ -14,6 +16,7 @@ const Option: React.FC<any> = (props) => {

let background = "#666"; // no flag color
let color = "#000";

try {
const flag = flatFlags.find(({ value }) =>
[props.data?.flag, props.data?.val].filter(Boolean).includes(value),
Expand All @@ -27,8 +30,15 @@ const Option: React.FC<any> = (props) => {
className={classNames("card", "option", { wasVisited: props.wasVisited })}
>
<Link href={href} prefetch={false} onClick={(e) => e.preventDefault()}>
{props.data?.img && (
<Thumbnail
imageSource={props.data?.img}
imageAltText={props.data.text}
/>
)}
<div className="band" style={{ background, color }}></div>
<div className="text">{props.data.text}</div>
{props.data?.val && <DataField value={props.data.val} variant="child" />}
</Link>
<ol className="decisions">
{childNodes.map((child: any) => (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,11 @@ import { Link } from "react-navi";

import { useStore } from "../../../lib/store";
import { getParentId } from "../lib/utils";
import { DataField } from "./DataField";
import Hanger from "./Hanger";
import Node from "./Node";
import { Tag } from "./Tag";
import { Thumbnail } from "./Thumbnail";

type Props = {
type: TYPES | "Error";
Expand Down Expand Up @@ -80,9 +82,18 @@ const Question: React.FC<Props> = React.memo((props) => {
onContextMenu={handleContext}
ref={drag}
>
{props.data?.img && (
<Thumbnail
imageSource={props.data?.img}
imageAltText={props.data?.text}
/>
)}
{Icon && <Icon titleAccess={iconTitleAccess} />}
<span>{props.text}</span>
</Link>
{props.type !== TYPES.SetValue && props.data?.fn && (
<DataField value={props.data.fn} variant="parent" />
)}
{props.tags?.map((tag) => <Tag tag={tag} key={tag} />)}
<ol className="options">
{childNodes.map((child: any) => (
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import Box from "@mui/material/Box";
import { useStore } from "pages/FlowEditor/lib/store";
import React from "react";

export const Thumbnail: React.FC<{
imageSource: string;
imageAltText?: string;
}> = ({ imageSource, imageAltText }) => {
const showImages = useStore((state) => state.showImages);
if (!showImages) return null;

return (
<Box
sx={{
maxWidth: "220px",
maxHeight: "220px",
margin: "auto",
}}
component="img"
src={imageSource}
alt={imageAltText}
/>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import DataFieldIcon from "@mui/icons-material/Code";
import DataFieldOffIcon from "@mui/icons-material/CodeOff";
import Box from "@mui/material/Box";
import IconButton from "@mui/material/IconButton";
import Tooltip from "@mui/material/Tooltip";
import { useStore } from "pages/FlowEditor/lib/store";
import React from "react";

export const ToggleDataFieldsButton: React.FC = () => {
const [showDataFields, toggleShowDataFields] = useStore((state) => [
state.showDataFields,
state.toggleShowDataFields,
]);

return (
<Box
sx={(theme) => ({
position: "fixed",
bottom: theme.spacing(6),
left: theme.spacing(7),
zIndex: theme.zIndex.appBar,
border: `1px solid ${theme.palette.border.main}`,
borderRadius: "3px",
background: theme.palette.background.paper,
})}
>
<Tooltip title="Toggle data fields" placement="right">
<IconButton
aria-label="Toggle data fields"
onClick={toggleShowDataFields}
size="large"
sx={(theme) => ({
padding: theme.spacing(1),
color: showDataFields
? theme.palette.text.primary
: theme.palette.text.disabled,
})}
>
{showDataFields ? <DataFieldIcon /> : <DataFieldOffIcon />}
</IconButton>
</Tooltip>
</Box>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import ImageOffIcon from "@mui/icons-material/HideImage";
import ImageIcon from "@mui/icons-material/Image";
import Box from "@mui/material/Box";
import IconButton from "@mui/material/IconButton";
import Tooltip from "@mui/material/Tooltip";
import { useStore } from "pages/FlowEditor/lib/store";
import React from "react";

export const ToggleImagesButton: React.FC = () => {
const [showImages, toggleShowImages] = useStore((state) => [
state.showImages,
state.toggleShowImages,
]);

return (
<Box
sx={(theme) => ({
position: "fixed",
bottom: theme.spacing(10),
left: theme.spacing(7),
zIndex: theme.zIndex.appBar,
border: `1px solid ${theme.palette.border.main}`,
borderRadius: "3px",
background: theme.palette.background.paper,
})}
>
<Tooltip title="Toggle images" placement="right">
<IconButton
aria-label="Toggle images"
onClick={toggleShowImages}
size="large"
sx={(theme) => ({
padding: theme.spacing(1),
color: showImages
? theme.palette.text.primary
: theme.palette.text.disabled,
})}
>
{showImages ? <ImageIcon /> : <ImageOffIcon />}
</IconButton>
</Tooltip>
</Box>
);
};
2 changes: 1 addition & 1 deletion editor.planx.uk/src/pages/FlowEditor/floweditor.scss
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ $fontMonospace: "Source Code Pro", monospace;
flex-direction: column;
padding: 0;
min-width: 60px;
max-width: 200px;
max-width: fit-content;
}
.band {
width: 100%;
Expand Down
12 changes: 11 additions & 1 deletion editor.planx.uk/src/pages/FlowEditor/index.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
import "./floweditor.scss";

import Box from "@mui/material/Box";
import ButtonGroup from "@mui/material/ButtonGroup";
import { styled } from "@mui/material/styles";
import { HEADER_HEIGHT_EDITOR } from "components/Header";
import React, { useRef } from "react";
import { useCurrentRoute } from "react-navi";

import Flow from "./components/Flow";
import { ToggleDataFieldsButton } from "./components/FlowEditor/ToggleDataFieldsButton";
import { ToggleImagesButton } from "./components/FlowEditor/ToggleImagesButton";
import { ToggleTagsButton } from "./components/FlowEditor/ToggleTagsButton";
import Sidebar from "./components/Sidebar";
import { useStore } from "./lib/store";
Expand Down Expand Up @@ -50,7 +53,14 @@ const FlowEditor = () => {
>
<Box id="editor" ref={scrollContainerRef} sx={{ position: "relative" }}>
<Flow flow={flow} breadcrumbs={breadcrumbs} />
<ToggleTagsButton />
<ButtonGroup
orientation="vertical"
aria-label="Toggle node attributes"
>
<ToggleImagesButton />
<ToggleDataFieldsButton />
<ToggleTagsButton />
</ButtonGroup>
</Box>
</Box>
<Sidebar />
Expand Down
15 changes: 14 additions & 1 deletion editor.planx.uk/src/pages/FlowEditor/lib/store/editor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { getPathForNode, sortFlow } from "@opensystemslab/planx-core";
import {
ComponentType,
FlowGraph,
IndexedNode,
NodeId,
OrderedFlow,
} from "@opensystemslab/planx-core/types";
Expand Down Expand Up @@ -52,6 +51,10 @@ export interface EditorUIStore {
hideTestEnvBanner: () => void;
showTags: boolean;
toggleShowTags: () => void;
showImages: boolean;
toggleShowImages: () => void;
showDataFields: boolean;
toggleShowDataFields: () => void;
}

export const editorUIStore: StateCreator<
Expand All @@ -76,12 +79,22 @@ export const editorUIStore: StateCreator<
showTags: false,

toggleShowTags: () => set({ showTags: !get().showTags }),

showImages: false,

toggleShowImages: () => set({ showImages: !get().showImages }),

showDataFields: false,

toggleShowDataFields: () => set({ showDataFields: !get().showDataFields }),
}),
{
name: "editorUIStore",
partialize: (state) => ({
showSidebar: state.showSidebar,
showTags: state.showTags,
showImages: state.showImages,
showDataFields: state.showDataFields,
}),
},
);
Expand Down

0 comments on commit d2fe0cc

Please sign in to comment.