diff --git a/editor.planx.uk/src/components/Header.test.tsx b/editor.planx.uk/src/components/Header.test.tsx index 2f54cf38d4..3a0e0c3c3a 100644 --- a/editor.planx.uk/src/components/Header.test.tsx +++ b/editor.planx.uk/src/components/Header.test.tsx @@ -13,6 +13,7 @@ import Header from "./Header"; const { setState, getState } = vanillaStore; const mockTeam1: Team = { + id: 123, name: "Open Systems Lab", slug: "opensystemslab", theme: { @@ -21,18 +22,14 @@ const mockTeam1: Team = { }; const mockTeam2: Team = { + id: 456, name: "Closed Systems Lab", slug: "closedsystemslab", }; -jest.spyOn(ReactNavi, "useNavigation").mockImplementation( - () => - ({ - data: { - team: mockTeam1, - }, - }) as any, -); +jest.spyOn(ReactNavi, "useNavigation").mockReturnValue(({ + navigate: jest.fn() +}) as any); describe("Header Component - Editor Route", () => { beforeAll(() => { @@ -56,7 +53,6 @@ describe("Header Component - Editor Route", () => { data: { username: "Test User", flow: "test-flow", - team: mockTeam1.slug, }, }) as any, ); diff --git a/editor.planx.uk/src/components/Header.tsx b/editor.planx.uk/src/components/Header.tsx index 79bc3e8d6c..81597020ba 100644 --- a/editor.planx.uk/src/components/Header.tsx +++ b/editor.planx.uk/src/components/Header.tsx @@ -197,6 +197,7 @@ const Breadcrumbs: React.FC<{ handleClick?: (href: string) => void; }> = ({ handleClick }) => { const route = useCurrentRoute(); + const team = useStore((state) => state.getTeam()); return ( @@ -208,7 +209,7 @@ const Breadcrumbs: React.FC<{ Planâś• - {route.data.team && ( + {team && ( <> {" / "} - {route.data.team} + {team.slug} )} diff --git a/editor.planx.uk/src/pages/FlowEditor/lib/store/settings.ts b/editor.planx.uk/src/pages/FlowEditor/lib/store/settings.ts index 537353da56..55504aa09d 100644 --- a/editor.planx.uk/src/pages/FlowEditor/lib/store/settings.ts +++ b/editor.planx.uk/src/pages/FlowEditor/lib/store/settings.ts @@ -41,8 +41,8 @@ export const settingsStore: StateCreator< const response = await client.mutate({ mutation: gql` mutation UpdateFlowSettings( - $team_slug: String - $flow_slug: String + $team_slug: String! + $flow_slug: String! $settings: jsonb ) { update_flows( diff --git a/editor.planx.uk/src/pages/FlowEditor/lib/store/team.ts b/editor.planx.uk/src/pages/FlowEditor/lib/store/team.ts index ee3d43abea..b4c49bc0c3 100644 --- a/editor.planx.uk/src/pages/FlowEditor/lib/store/team.ts +++ b/editor.planx.uk/src/pages/FlowEditor/lib/store/team.ts @@ -1,10 +1,14 @@ import { GeoJSONObject } from "@turf/helpers"; +import gql from "graphql-tag"; +import { client } from "lib/graphql"; +import { getTeamFromDomain } from "routes/utils"; import { NotifyPersonalisation, TeamSettings } from "types"; import { TeamTheme } from "types"; import { Team } from "types"; import type { StateCreator } from "zustand"; export interface TeamStore { + teamId: number, teamTheme?: TeamTheme; teamName: string; teamSettings?: TeamSettings; @@ -14,12 +18,14 @@ export interface TeamStore { setTeam: (team: Team) => void; getTeam: () => Team; + initTeamStore: (teamSlugFromURLParams?: string) => Promise; } export const teamStore: StateCreator = ( set, get, ) => ({ + teamId: 0, teamTheme: undefined, teamName: "", teamSettings: undefined, @@ -29,6 +35,7 @@ export const teamStore: StateCreator = ( setTeam: (team) => set({ + teamId: team.id, teamTheme: team.theme, teamName: team.name, teamSettings: team.settings, @@ -38,6 +45,7 @@ export const teamStore: StateCreator = ( }), getTeam: () => ({ + id: get().teamId, name: get().teamName, slug: get().teamSlug, settings: get().teamSettings, @@ -45,4 +53,40 @@ export const teamStore: StateCreator = ( notifyPersonalisation: get().notifyPersonalisation, boundaryBBox: get().boundaryBBox, }), + + async initTeamStore(teamSlugFromURLParams) { + const slug = teamSlugFromURLParams || await getTeamFromDomain(window.location.hostname) + const { data } = await client.query({ + query: gql` + query GetTeams($slug: String!) { + teams( + order_by: { name: asc } + limit: 1 + where: { slug: { _eq: $slug } } + ) { + id + name + slug + flows(order_by: { updated_at: desc }) { + slug + updated_at + operations(limit: 1, order_by: { id: desc }) { + actor { + first_name + last_name + } + } + } + } + } + `, + variables: { slug }, + }); + + const team = data.teams[0]; + + if (!team) throw new Error("Team not found"); + + this.setTeam(team); + }, }); diff --git a/editor.planx.uk/src/pages/Team.tsx b/editor.planx.uk/src/pages/Team.tsx index 15317f617b..c5fbbe7e47 100644 --- a/editor.planx.uk/src/pages/Team.tsx +++ b/editor.planx.uk/src/pages/Team.tsx @@ -281,17 +281,18 @@ const FlowItem: React.FC = ({ ); }; -const Team: React.FC<{ id: number; slug: string }> = ({ id, slug }) => { +const Team: React.FC = () => { + const { id: teamId, slug } = useStore((state) => state.getTeam()); const [flows, setFlows] = useState(null); const navigation = useNavigation(); const fetchFlows = useCallback(() => { useStore .getState() - .getFlows(id) + .getFlows(teamId) .then((res: { flows: any[] }) => { setFlows(res.flows); }); - }, [id, setFlows]); + }, [teamId, setFlows]); useEffect(() => { fetchFlows(); }, [fetchFlows]); @@ -322,7 +323,7 @@ const Team: React.FC<{ id: number; slug: string }> = ({ id, slug }) => { { fetchFlows(); @@ -337,7 +338,7 @@ const Team: React.FC<{ id: number; slug: string }> = ({ id, slug }) => { const newFlowSlug = slugify(newFlowName); useStore .getState() - .createFlow(id, newFlowSlug) + .createFlow(teamId, newFlowSlug) .then((newId: string) => { navigation.navigate(`/${slug}/${newId}`); }); diff --git a/editor.planx.uk/src/routes/team.tsx b/editor.planx.uk/src/routes/team.tsx index c94fca9fe0..3c70c7a521 100644 --- a/editor.planx.uk/src/routes/team.tsx +++ b/editor.planx.uk/src/routes/team.tsx @@ -1,11 +1,12 @@ import gql from "graphql-tag"; -import { compose, lazy, mount, route, withData } from "navi"; +import { compose, lazy, mount, route, withView } from "navi"; import React from "react"; import { client } from "../lib/graphql"; import { useStore } from "../pages/FlowEditor/lib/store"; import Team from "../pages/Team"; -import { getTeamFromDomain, makeTitle } from "./utils"; +import { makeTitle } from "./utils"; +import { teamView } from "./views/team"; let cached: { flowSlug?: string; teamSlug?: string } = { flowSlug: undefined, @@ -13,56 +14,13 @@ let cached: { flowSlug?: string; teamSlug?: string } = { }; const routes = compose( - withData(async (req) => ({ - team: - req.params.team || (await getTeamFromDomain(window.location.hostname)), - })), + withView(teamView), mount({ - "/": route(async (req) => { - const { data } = await client.query({ - query: gql` - query GetTeams($slug: String!) { - teams( - order_by: { name: asc } - limit: 1 - where: { slug: { _eq: $slug } } - ) { - id - name - slug - flows(order_by: { updated_at: desc }) { - slug - updated_at - operations(limit: 1, order_by: { id: desc }) { - actor { - first_name - last_name - } - } - } - } - } - `, - variables: { - slug: req.params.team, - }, - }); - - const team = data.teams[0]; - - if (!team) { - return { - title: "Team Not Found", - view:

Team not found

, - }; - } - - return { - title: makeTitle(team.name), - view: , - }; - }), + "/": route(() => ({ + title: makeTitle(useStore.getState().teamName), + view: , + })), "/:flow": lazy(async (req) => { const [slug] = req.params.flow.split(","); diff --git a/editor.planx.uk/src/routes/views/team.tsx b/editor.planx.uk/src/routes/views/team.tsx new file mode 100644 index 0000000000..e6f7d2f5b7 --- /dev/null +++ b/editor.planx.uk/src/routes/views/team.tsx @@ -0,0 +1,21 @@ +import { NaviRequest, NotFoundError } from "navi" +import { useStore } from "pages/FlowEditor/lib/store"; +import React from "react"; +import { View } from "react-navi" + +/** + * View wrapper for /team routes + * Initialises TeamStore if not already set + */ +export const teamView = async (req: NaviRequest) => { + const { teamId, initTeamStore } = useStore.getState(); + if (!teamId) { + try { + await initTeamStore(req.params.team); + } catch (error) { + throw new NotFoundError("Team not found"); + } + } + + return +} \ No newline at end of file diff --git a/editor.planx.uk/src/types.ts b/editor.planx.uk/src/types.ts index 747a6d7686..1f1fd03de2 100644 --- a/editor.planx.uk/src/types.ts +++ b/editor.planx.uk/src/types.ts @@ -17,6 +17,7 @@ export interface Flow { } export interface Team { + id: number; name: string; slug: string; settings?: TeamSettings;