Skip to content

Commit

Permalink
refine type use on sort keys
Browse files Browse the repository at this point in the history
  • Loading branch information
RODO94 committed Jan 10, 2025
1 parent 97ddeb7 commit f235e5b
Show file tree
Hide file tree
Showing 5 changed files with 155 additions and 91 deletions.
6 changes: 5 additions & 1 deletion editor.planx.uk/src/lib/featureFlags.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
// add/edit/remove feature flags in array below
const AVAILABLE_FEATURE_FLAGS = ["FEE_BREAKDOWN", "EXCLUSIVE_OR"] as const;
const AVAILABLE_FEATURE_FLAGS = [
"FEE_BREAKDOWN",
"EXCLUSIVE_OR",
"SORT_FLOWS",
] as const;

type FeatureFlag = (typeof AVAILABLE_FEATURE_FLAGS)[number];

Expand Down
29 changes: 22 additions & 7 deletions editor.planx.uk/src/pages/FlowEditor/lib/store/editor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,19 +132,27 @@ interface PublishFlowResponse {
message: string;
}

export type PublishedFlowSummary = {
publishedAt: string;
hasSendComponent: boolean;
};

export type FlowSummaryOperations = {
createdAt: string;
actor: {
firstName: string;
lastName: string;
};
};

export interface FlowSummary {
id: string;
name: string;
slug: string;
status: "online" | "offline";
updatedAt: string;
operations: {
createdAt: string;
actor: {
firstName: string;
lastName: string;
};
}[];
operations: FlowSummaryOperations[];
publishedFlows: PublishedFlowSummary[];
}

export interface EditorStore extends Store.Store {
Expand Down Expand Up @@ -392,6 +400,13 @@ export const editorStore: StateCreator<
lastName: last_name
}
}
publishedFlows: published_flows(
order_by: { created_at: desc }
limit: 1
) {
publishedAt: created_at
hasSendComponent: has_send_component
}
}
}
`,
Expand Down
7 changes: 5 additions & 2 deletions editor.planx.uk/src/pages/Team.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,13 @@ import DialogContentText from "@mui/material/DialogContentText";
import DialogTitle from "@mui/material/DialogTitle";
import { styled } from "@mui/material/styles";
import Typography from "@mui/material/Typography";
import { hasFeatureFlag } from "lib/featureFlags";
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 { OrderingFlowsSelect } from "ui/editor/OrderingFlowsSelect";
import { SortFlowsSelect } from "ui/editor/SortFlowsSelect";
import { slugify } from "utils";

import { client } from "../lib/graphql";
Expand Down Expand Up @@ -351,7 +352,9 @@ const Team: React.FC = () => {
</Box>
{showAddFlowButton && <AddFlowButton flows={flows} />}
</Box>
{flows && <OrderingFlowsSelect flows={flows} setFlows={setFlows} />}
{hasFeatureFlag("SORT_FLOWS") && flows && (
<SortFlowsSelect flows={flows} setFlows={setFlows} />
)}
{teamHasFlows && (
<DashboardList>
{flows.map((flow) => (
Expand Down
81 changes: 0 additions & 81 deletions editor.planx.uk/src/ui/editor/OrderingFlowsSelect.tsx

This file was deleted.

123 changes: 123 additions & 0 deletions editor.planx.uk/src/ui/editor/SortFlowsSelect.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
import TrendingDownIcon from "@mui/icons-material/TrendingDown";
import TrendingUpIcon from "@mui/icons-material/TrendingUp";
import Box from "@mui/material/Box";
import IconButton from "@mui/material/IconButton";
import MenuItem from "@mui/material/MenuItem";
import {
FlowSummary,
FlowSummaryOperations,
PublishedFlowSummary,
} from "pages/FlowEditor/lib/store/editor";
import React, { useEffect, useState } from "react";

import SelectInput from "./SelectInput/SelectInput";

type SortDirection = "asc" | "desc";
type SortKeys = keyof FlowSummary;
type SortNestedKeys = keyof PublishedFlowSummary | keyof FlowSummaryOperations;
type SortTypes = SortKeys | SortNestedKeys;

interface BasicSort {
displayName: string;
sortKey: Exclude<SortKeys, "publishedFlows" | "operations">;
}

interface PublishedFlowSort {
displayName: string;
sortKey: "publishedFlows";
nestedKey: keyof PublishedFlowSummary;
}

type SortObject = PublishedFlowSort | BasicSort;

const sortArray: SortObject[] = [
{ displayName: "Name", sortKey: "name" },
{ displayName: "Last updated", sortKey: "updatedAt" },
{ displayName: "Status", sortKey: "status" },
{
displayName: "Last published",
sortKey: "publishedFlows",
nestedKey: "publishedAt",
},
];

const sortFlowList = (
a: string | boolean,
b: string | boolean,
sortDirection: SortDirection,
) => {
if (a < b) {
return sortDirection === "asc" ? 1 : -1;
}
if (a > b) {
return sortDirection === "asc" ? -1 : 1;
}
return 0;
};

export const SortFlowsSelect = ({
flows,
setFlows,
}: {
flows: FlowSummary[];
setFlows: React.Dispatch<React.SetStateAction<FlowSummary[] | null>>;
}) => {
const [sortBy, setSortBy] = useState<SortObject>(sortArray[0]);
const [sortDirection, setSortDirection] = useState<SortDirection>("asc");
useEffect(() => {
const { sortKey } = sortBy;

if (sortKey === "publishedFlows") {
const sortedFlows = flows?.sort((a: FlowSummary, b: FlowSummary) => {
const { nestedKey } = sortBy;

// auto sort unpublished flows to bottom
if (!a[sortKey][0]) return 1;
if (!b[sortKey][0]) return -1;

const aValue = a[sortKey][0][nestedKey];
const bValue = b[sortKey][0][nestedKey];

return sortFlowList(aValue, bValue, sortDirection);
});
sortedFlows && setFlows([...sortedFlows]);
} else {
const sortedFlows = flows?.sort((a: FlowSummary, b: FlowSummary) =>
sortFlowList(a[sortKey], b[sortKey], sortDirection),
);
sortedFlows && setFlows([...sortedFlows]);
}
}, [sortBy, sortDirection]);

return (
<Box display={"flex"}>
<SelectInput
value={sortBy.sortKey}
onChange={(e) => {
const targetKey = e.target.value as SortTypes;
const newSortObject = sortArray.find(
(sortObject) => sortObject.sortKey === targetKey,
);
newSortObject && setSortBy(newSortObject);
}}
>
{sortArray.map(({ displayName, sortKey }) => (
<MenuItem key={sortKey} value={sortKey}>
{displayName}
</MenuItem>
))}
</SelectInput>
<IconButton
title="ordering"
aria-label="ordering"
onClick={() =>
sortDirection === "asc"
? setSortDirection("desc")
: setSortDirection("asc")
}
>
{sortDirection === "asc" ? <TrendingUpIcon /> : <TrendingDownIcon />}
</IconButton>
</Box>
);
};

0 comments on commit f235e5b

Please sign in to comment.