Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(frontend): Toggle flow online or offline #3183

Merged
merged 3 commits into from
May 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
import Alert from "@mui/material/Alert";
import Box from "@mui/material/Box";
import Button from "@mui/material/Button";
import FormControlLabel, {
formControlLabelClasses,
} from "@mui/material/FormControlLabel";
import Snackbar from "@mui/material/Snackbar";
import Switch, { SwitchProps } from "@mui/material/Switch";
import Typography from "@mui/material/Typography";
import { FlowStatus } from "@opensystemslab/planx-core/types";
import { useFormik } from "formik";
import React, { useState } from "react";
import { FONT_WEIGHT_BOLD } from "theme";
import EditorRow from "ui/editor/EditorRow";
import InputGroup from "ui/editor/InputGroup";
import InputLegend from "ui/editor/InputLegend";
Expand Down Expand Up @@ -72,7 +77,13 @@ const TextInput: React.FC<{
};

const ServiceSettings: React.FC = () => {
const flowSettings = useStore((state) => state.flowSettings);
const [flowSettings, updateFlowSettings, flowStatus, updateFlowStatus] =
useStore((state) => [
state.flowSettings,
state.updateFlowSettings,
state.flowStatus,
state.updateFlowStatus,
]);

const [isAlertOpen, setIsAlertOpen] = useState(false);

Expand All @@ -87,7 +98,7 @@ const ServiceSettings: React.FC = () => {
setIsAlertOpen(false);
};

const formik = useFormik<FlowSettings>({
const elementsForm = useFormik<FlowSettings>({
initialValues: {
elements: {
legalDisclaimer: {
Expand All @@ -108,15 +119,25 @@ const ServiceSettings: React.FC = () => {
},
},
onSubmit: async (values) => {
await useStore.getState().updateFlowSettings(values);
await updateFlowSettings(values);
setIsAlertOpen(true);
},
validate: () => {},
});

const statusForm = useFormik<{ status: FlowStatus }>({
initialValues: {
status: flowStatus || "online",
},
onSubmit: async ({ status }) => {
await updateFlowStatus(status);
setIsAlertOpen(true);
},
});

return (
<Box maxWidth="formWrap" mx="auto">
<form onSubmit={formik.handleSubmit}>
<Box component="form" onSubmit={elementsForm.handleSubmit} mb={2}>
<EditorRow>
<Typography variant="h2" component="h3" gutterBottom>
Elements
Expand All @@ -131,18 +152,18 @@ const ServiceSettings: React.FC = () => {
description="Displayed before a user submits their application"
switchProps={{
name: "elements.legalDisclaimer.show",
checked: formik.values.elements?.legalDisclaimer?.show,
onChange: formik.handleChange,
checked: elementsForm.values.elements?.legalDisclaimer?.show,
onChange: elementsForm.handleChange,
}}
headingInputProps={{
name: "elements.legalDisclaimer.heading",
value: formik.values.elements?.legalDisclaimer?.heading,
onChange: formik.handleChange,
value: elementsForm.values.elements?.legalDisclaimer?.heading,
onChange: elementsForm.handleChange,
}}
contentInputProps={{
name: "elements.legalDisclaimer.content",
value: formik.values.elements?.legalDisclaimer?.content,
onChange: formik.handleChange,
value: elementsForm.values.elements?.legalDisclaimer?.content,
onChange: elementsForm.handleChange,
}}
/>
</EditorRow>
Expand All @@ -156,18 +177,18 @@ const ServiceSettings: React.FC = () => {
description="A place to communicate FAQs, useful tips, or contact information"
switchProps={{
name: "elements.help.show",
checked: formik.values.elements?.help?.show,
onChange: formik.handleChange,
checked: elementsForm.values.elements?.help?.show,
onChange: elementsForm.handleChange,
}}
headingInputProps={{
name: "elements.help.heading",
value: formik.values.elements?.help?.heading,
onChange: formik.handleChange,
value: elementsForm.values.elements?.help?.heading,
onChange: elementsForm.handleChange,
}}
contentInputProps={{
name: "elements.help.content",
value: formik.values.elements?.help?.content,
onChange: formik.handleChange,
value: elementsForm.values.elements?.help?.content,
onChange: elementsForm.handleChange,
}}
/>
</InputRow>
Expand All @@ -178,18 +199,18 @@ const ServiceSettings: React.FC = () => {
description="Your privacy policy"
switchProps={{
name: "elements.privacy.show",
checked: formik.values.elements?.privacy?.show,
onChange: formik.handleChange,
checked: elementsForm.values.elements?.privacy?.show,
onChange: elementsForm.handleChange,
}}
headingInputProps={{
name: "elements.privacy.heading",
value: formik.values.elements?.privacy?.heading,
onChange: formik.handleChange,
value: elementsForm.values.elements?.privacy?.heading,
onChange: elementsForm.handleChange,
}}
contentInputProps={{
name: "elements.privacy.content",
value: formik.values.elements?.privacy?.content,
onChange: formik.handleChange,
value: elementsForm.values.elements?.privacy?.content,
onChange: elementsForm.handleChange,
}}
/>
</InputRow>
Expand All @@ -200,25 +221,87 @@ const ServiceSettings: React.FC = () => {
type="submit"
variant="contained"
color="primary"
disabled={!formik.dirty}
disabled={!elementsForm.dirty}
>
Update elements
</Button>
</EditorRow>
<Snackbar
open={isAlertOpen}
autoHideDuration={6000}
onClose={handleClose}
>
<Alert
onClose={handleClose}
severity="success"
sx={{ width: "100%" }}
>
Service settings updated successfully
</Alert>
</Snackbar>
</form>
</Box>
<Box component="form" onSubmit={statusForm.handleSubmit}>
<EditorRow>
<Typography variant="h2" component="h3" gutterBottom>
Status
</Typography>
<Typography variant="body1">
Manage the status of your service.
</Typography>
</EditorRow>
<EditorRow background>
<FormControlLabel
label={statusForm.values.status}
sx={{
[`& .${formControlLabelClasses.label}`]: {
fontWeight: FONT_WEIGHT_BOLD,
textTransform: "capitalize",
fontSize: 19,
},
}}
control={
<Switch
name="service.status"
color="primary"
checked={statusForm.values.status === "online"}
onChange={() =>
statusForm.setFieldValue(
"status",
statusForm.values.status === "online"
? "offline"
: "online",
)
}
/>
}
/>
<Typography variant="body1">
Toggle your service between "offline" and "online".
</Typography>
<Typography variant="body1">
A service must be online to be accessed by the public, and to enable
analytics gathering.
DafyddLlyr marked this conversation as resolved.
Show resolved Hide resolved
</Typography>
<Typography variant="body1">
Offline services can still be edited and published as normal.
</Typography>
<Box>
<Button
type="submit"
variant="contained"
disabled={!statusForm.dirty}
>
Save
</Button>
<Button
onClick={() => statusForm.resetForm()}
type="reset"
variant="contained"
disabled={!statusForm.dirty}
color="secondary"
sx={{ ml: 1.5 }}
>
Reset changes
</Button>
</Box>
</EditorRow>
</Box>
<Snackbar
open={isAlertOpen}
autoHideDuration={6000}
onClose={handleClose}
>
<Alert onClose={handleClose} severity="success" sx={{ width: "100%" }}>
Service settings updated successfully
</Alert>
</Snackbar>
</Box>
);
};
Expand Down
17 changes: 17 additions & 0 deletions editor.planx.uk/src/pages/FlowEditor/lib/store/settings.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { gql } from "@apollo/client";
import { FlowStatus } from "@opensystemslab/planx-core/types";
import camelcaseKeys from "camelcase-keys";
import { client } from "lib/graphql";
import {
Expand All @@ -15,6 +16,9 @@ import { TeamStore } from "./team";
export interface SettingsStore {
flowSettings?: FlowSettings;
setFlowSettings: (flowSettings?: FlowSettings) => void;
flowStatus?: FlowStatus;
setFlowStatus: (flowStatus: FlowStatus) => void;
updateFlowStatus: (newStatus: FlowStatus) => Promise<boolean>;
globalSettings?: GlobalSettings;
setGlobalSettings: (globalSettings: GlobalSettings) => void;
updateFlowSettings: (newSettings: FlowSettings) => Promise<number>;
Expand All @@ -33,6 +37,19 @@ export const settingsStore: StateCreator<

setFlowSettings: (flowSettings) => set({ flowSettings }),

flowStatus: undefined,
jessicamcinchak marked this conversation as resolved.
Show resolved Hide resolved

setFlowStatus: (flowStatus) => set({ flowStatus }),

updateFlowStatus: async (newStatus) => {
const { id, $client } = get();
const result = await $client.flow.setStatus({
flow: { id },
status: newStatus,
});
return Boolean(result?.id);
},

globalSettings: undefined,

setGlobalSettings: (globalSettings) => {
Expand Down
10 changes: 7 additions & 3 deletions editor.planx.uk/src/routes/flowSettings.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { FlowStatus } from "@opensystemslab/planx-core/types";
import gql from "graphql-tag";
import { publicClient } from "lib/graphql";
import {
compose,
map,
Expand All @@ -17,6 +17,7 @@ import Submissions from "pages/FlowEditor/components/Settings/Submissions";
import { useStore } from "pages/FlowEditor/lib/store";
import React from "react";

import { client } from "../lib/graphql";
import Settings, { SettingsTab } from "../pages/FlowEditor/components/Settings";
import type { FlowSettings } from "../types";
import { makeTitle } from "./utils";
Expand All @@ -25,15 +26,16 @@ interface GetFlowSettings {
flows: {
id: string;
settings: FlowSettings;
status: FlowStatus;
}[];
}

export const getFlowSettings = async (req: NaviRequest) => {
const {
data: {
flows: [{ settings }],
flows: [{ settings, status }],
},
} = await publicClient.query<GetFlowSettings>({
} = await client.query<GetFlowSettings>({
query: gql`
query GetFlow($slug: String!, $team_slug: String!) {
flows(
Expand All @@ -42,6 +44,7 @@ export const getFlowSettings = async (req: NaviRequest) => {
) {
id
settings
status
}
}
`,
Expand All @@ -52,6 +55,7 @@ export const getFlowSettings = async (req: NaviRequest) => {
});

useStore.getState().setFlowSettings(settings);
useStore.getState().setFlowStatus(status);
};

const tabs: SettingsTab[] = [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ INSERT INTO "public"."flow_status_enum"("value", "comment") VALUES (E'offline',
alter table "public"."flows" add column "status" text
not null default 'offline';

-- Populate flows.status for all existing flows
UPDATE "public"."flows" SET status = 'online';

alter table "public"."flows"
add constraint "flows_status_fkey"
foreign key ("status")
Expand Down
Loading