diff --git a/editor.planx.uk/src/pages/FlowEditor/components/Sidebar/DebugConsole.tsx b/editor.planx.uk/src/pages/FlowEditor/components/Sidebar/DebugConsole.tsx
new file mode 100644
index 0000000000..7e9448e1e6
--- /dev/null
+++ b/editor.planx.uk/src/pages/FlowEditor/components/Sidebar/DebugConsole.tsx
@@ -0,0 +1,51 @@
+import ReactJson from "@microlink/react-json-view";
+import Box from "@mui/material/Box";
+import { styled } from "@mui/material/styles";
+import Typography from "@mui/material/Typography";
+import React from "react";
+
+import { useStore } from "../../lib/store";
+
+const Console = styled(Box)(({ theme }) => ({
+ overflow: "auto",
+ padding: theme.spacing(2),
+ height: "100%",
+ backgroundColor: theme.palette.background.dark,
+ color: theme.palette.common.white,
+}));
+
+export const DebugConsole = () => {
+ const [passport, breadcrumbs, flowId, cachedBreadcrumbs] = useStore(
+ (state) => [
+ state.computePassport(),
+ state.breadcrumbs,
+ state.id,
+ state.cachedBreadcrumbs,
+ ],
+ );
+ return (
+
+
+
+ );
+};
diff --git a/editor.planx.uk/src/pages/FlowEditor/components/Sidebar/PublishDialog.tsx b/editor.planx.uk/src/pages/FlowEditor/components/Sidebar/Publish/PublishDialog.tsx
similarity index 99%
rename from editor.planx.uk/src/pages/FlowEditor/components/Sidebar/PublishDialog.tsx
rename to editor.planx.uk/src/pages/FlowEditor/components/Sidebar/Publish/PublishDialog.tsx
index 5aeef4e9cf..35495d1c56 100644
--- a/editor.planx.uk/src/pages/FlowEditor/components/Sidebar/PublishDialog.tsx
+++ b/editor.planx.uk/src/pages/FlowEditor/components/Sidebar/Publish/PublishDialog.tsx
@@ -25,7 +25,7 @@ import React, { useState } from "react";
import { useAsync } from "react-use";
import Caret from "ui/icons/Caret";
-import { useStore } from "../../lib/store";
+import { useStore } from "../../../lib/store";
export interface AlteredNode {
id: string;
diff --git a/editor.planx.uk/src/pages/FlowEditor/components/Sidebar/Publish/PublishFlowButton.tsx b/editor.planx.uk/src/pages/FlowEditor/components/Sidebar/Publish/PublishFlowButton.tsx
new file mode 100644
index 0000000000..418f21e3d8
--- /dev/null
+++ b/editor.planx.uk/src/pages/FlowEditor/components/Sidebar/Publish/PublishFlowButton.tsx
@@ -0,0 +1,192 @@
+import Badge from "@mui/material/Badge";
+import Box from "@mui/material/Box";
+import Button from "@mui/material/Button";
+import Dialog from "@mui/material/Dialog";
+import DialogActions from "@mui/material/DialogActions";
+import DialogContent from "@mui/material/DialogContent";
+import DialogTitle from "@mui/material/DialogTitle";
+import Link from "@mui/material/Link";
+import Typography from "@mui/material/Typography";
+import { AxiosError } from "axios";
+import { useStore } from "pages/FlowEditor/lib/store";
+import { formatLastPublishMessage } from "pages/FlowEditor/utils";
+import React, { useState } from "react";
+import { useAsync } from "react-use";
+import Input from "ui/shared/Input";
+
+import { urls } from "..";
+import {
+ AlteredNode,
+ AlteredNodesSummaryContent,
+ ValidationCheck,
+ ValidationChecks,
+} from "./PublishDialog";
+
+export const PublishFlowButton = () => {
+ const [
+ flowId,
+ publishFlow,
+ lastPublished,
+ lastPublisher,
+ validateAndDiffFlow,
+ ] = useStore((state) => [
+ state.id,
+ state.publishFlow,
+ state.lastPublished,
+ state.lastPublisher,
+ state.validateAndDiffFlow,
+ ]);
+
+ const [lastPublishedTitle, setLastPublishedTitle] = useState(
+ "This flow is not published yet",
+ );
+ const [validationChecks, setValidationChecks] = useState(
+ [],
+ );
+ const [alteredNodes, setAlteredNodes] = useState();
+ const [dialogOpen, setDialogOpen] = useState(false);
+ const [summary, setSummary] = useState();
+
+ const handleCheckForChangesToPublish = async () => {
+ try {
+ setLastPublishedTitle("Checking for changes...");
+ const alteredFlow = await validateAndDiffFlow(flowId);
+ setAlteredNodes(
+ alteredFlow?.data.alteredNodes ? alteredFlow.data.alteredNodes : [],
+ );
+ setLastPublishedTitle(
+ alteredFlow?.data.alteredNodes
+ ? `Found changes to ${alteredFlow.data.alteredNodes.length} nodes`
+ : alteredFlow?.data.message,
+ );
+ setValidationChecks(alteredFlow?.data?.validationChecks);
+ setDialogOpen(true);
+ } catch (error) {
+ setLastPublishedTitle("Error checking for changes to publish");
+
+ if (error instanceof AxiosError) {
+ alert(error.response?.data?.error);
+ } else {
+ alert(
+ `Error checking for changes to publish. Confirm that your graph does not have any corrupted nodes and that all external portals are valid. \n${error}`,
+ );
+ }
+ }
+ };
+
+ const handlePublish = async () => {
+ try {
+ setDialogOpen(false);
+ setLastPublishedTitle("Publishing changes...");
+ const { alteredNodes, message } = await publishFlow(flowId, summary);
+ setLastPublishedTitle(
+ alteredNodes
+ ? `Successfully published changes to ${alteredNodes.length} nodes`
+ : `${message}` || "No new changes to publish",
+ );
+ } catch (error) {
+ setLastPublishedTitle("Error trying to publish");
+ alert(error);
+ }
+ };
+
+ const _lastPublishedRequest = useAsync(async () => {
+ const date = await lastPublished(flowId);
+ const user = await lastPublisher(flowId);
+
+ setLastPublishedTitle(formatLastPublishMessage(date, user));
+ });
+
+ const _validateAndDiffRequest = useAsync(async () => {
+ const newChanges = await validateAndDiffFlow(flowId);
+ setAlteredNodes(
+ newChanges?.data.alteredNodes ? newChanges.data.alteredNodes : [],
+ );
+ });
+
+ // useStore.getState().getTeam().slug undefined here, use window instead
+ const teamSlug = window.location.pathname.split("/")[1];
+
+ return (
+
+
+
+
+
+
+
+ {lastPublishedTitle}
+
+
+
+ );
+};
diff --git a/editor.planx.uk/src/pages/FlowEditor/components/Sidebar/index.tsx b/editor.planx.uk/src/pages/FlowEditor/components/Sidebar/index.tsx
index b76df2413f..65434a0e0c 100644
--- a/editor.planx.uk/src/pages/FlowEditor/components/Sidebar/index.tsx
+++ b/editor.planx.uk/src/pages/FlowEditor/components/Sidebar/index.tsx
@@ -1,50 +1,36 @@
-import ReactJson from "@microlink/react-json-view";
import LanguageIcon from "@mui/icons-material/Language";
import OpenInNewIcon from "@mui/icons-material/OpenInNew";
import OpenInNewOffIcon from "@mui/icons-material/OpenInNewOff";
-import Badge from "@mui/material/Badge";
import Box from "@mui/material/Box";
import Button from "@mui/material/Button";
import Container from "@mui/material/Container";
-import Dialog from "@mui/material/Dialog";
-import DialogActions from "@mui/material/DialogActions";
-import DialogContent from "@mui/material/DialogContent";
-import DialogTitle from "@mui/material/DialogTitle";
import Link from "@mui/material/Link";
import { styled } from "@mui/material/styles";
import Tabs from "@mui/material/Tabs";
import Tooltip from "@mui/material/Tooltip";
-import Typography from "@mui/material/Typography";
-import { AxiosError } from "axios";
import { hasFeatureFlag } from "lib/featureFlags";
-import { formatLastPublishMessage } from "pages/FlowEditor/utils";
import React, { useState } from "react";
-import { useAsync } from "react-use";
+import { rootFlowPath } from "routes/utils";
import Permission from "ui/editor/Permission";
import Reset from "ui/icons/Reset";
-import Input from "ui/shared/Input";
import Questions from "../../../Preview/Questions";
import { useStore } from "../../lib/store";
+import { DebugConsole } from "./DebugConsole";
import EditHistory from "./EditHistory";
-import {
- AlteredNode,
- AlteredNodesSummaryContent,
- ValidationCheck,
- ValidationChecks,
-} from "./PublishDialog";
+import { PublishFlowButton } from "./Publish/PublishFlowButton";
import Search from "./Search";
import StyledTab from "./StyledTab";
type SidebarTabs = "PreviewBrowser" | "History" | "Search" | "Console";
-const Console = styled(Box)(({ theme }) => ({
- overflow: "auto",
- padding: theme.spacing(2),
- height: "100%",
- backgroundColor: theme.palette.background.dark,
- color: theme.palette.common.white,
-}));
+const baseUrl = `${window.location.origin}${rootFlowPath(false)}`;
+
+export const urls = {
+ preview: baseUrl + "/preview",
+ draft: baseUrl + "/draft",
+ analytics: baseUrl + "/published" + "?analytics=false",
+};
const Root = styled(Box)(({ theme }) => ({
position: "relative",
@@ -117,152 +103,28 @@ const TabList = styled(Box)(({ theme }) => ({
},
}));
-const DebugConsole = () => {
- const [passport, breadcrumbs, flowId, cachedBreadcrumbs] = useStore(
- (state) => [
- state.computePassport(),
- state.breadcrumbs,
- state.id,
- state.cachedBreadcrumbs,
- ],
- );
- return (
-
-
-
- );
-};
-
-const Sidebar: React.FC<{
- url: string;
-}> = React.memo((props) => {
- const [showDebugConsole, setDebugConsoleVisibility] = useState(false);
- const [
- flowId,
- resetPreview,
- publishFlow,
- lastPublished,
- lastPublisher,
- validateAndDiffFlow,
- isFlowPublished,
- ] = useStore((state) => [
- state.id,
+const Sidebar: React.FC = React.memo(() => {
+ const [resetPreview, isFlowPublished] = useStore((state) => [
state.resetPreview,
- state.publishFlow,
- state.lastPublished,
- state.lastPublisher,
- state.validateAndDiffFlow,
state.isFlowPublished,
]);
- const [lastPublishedTitle, setLastPublishedTitle] = useState(
- "This flow is not published yet",
- );
- const [validationChecks, setValidationChecks] = useState(
- [],
- );
- const [alteredNodes, setAlteredNodes] = useState();
- const [dialogOpen, setDialogOpen] = useState(false);
- const [summary, setSummary] = useState();
+
const [activeTab, setActiveTab] = useState("PreviewBrowser");
const handleChange = (event: React.SyntheticEvent, newValue: SidebarTabs) => {
setActiveTab(newValue);
};
- const handleCheckForChangesToPublish = async () => {
- try {
- setLastPublishedTitle("Checking for changes...");
- const alteredFlow = await validateAndDiffFlow(flowId);
- setAlteredNodes(
- alteredFlow?.data.alteredNodes ? alteredFlow.data.alteredNodes : [],
- );
- setLastPublishedTitle(
- alteredFlow?.data.alteredNodes
- ? `Found changes to ${alteredFlow.data.alteredNodes.length} nodes`
- : alteredFlow?.data.message,
- );
- setValidationChecks(alteredFlow?.data?.validationChecks);
- setDialogOpen(true);
- } catch (error) {
- setLastPublishedTitle("Error checking for changes to publish");
-
- if (error instanceof AxiosError) {
- alert(error.response?.data?.error);
- } else {
- alert(
- `Error checking for changes to publish. Confirm that your graph does not have any corrupted nodes and that all external portals are valid. \n${error}`,
- );
- }
- }
- };
-
- const handlePublish = async () => {
- try {
- setDialogOpen(false);
- setLastPublishedTitle("Publishing changes...");
- const { alteredNodes, message } = await publishFlow(flowId, summary);
- setLastPublishedTitle(
- alteredNodes
- ? `Successfully published changes to ${alteredNodes.length} nodes`
- : `${message}` || "No new changes to publish",
- );
- } catch (error) {
- setLastPublishedTitle("Error trying to publish");
- alert(error);
- }
- };
-
- const _lastPublishedRequest = useAsync(async () => {
- const date = await lastPublished(flowId);
- const user = await lastPublisher(flowId);
-
- setLastPublishedTitle(formatLastPublishMessage(date, user));
- });
-
- const _validateAndDiffRequest = useAsync(async () => {
- const newChanges = await validateAndDiffFlow(flowId);
- setAlteredNodes(
- newChanges?.data.alteredNodes ? newChanges.data.alteredNodes : [],
- );
- });
-
- // useStore.getState().getTeam().slug undefined here, use window instead
- const teamSlug = window.location.pathname.split("/")[1];
-
return (
diff --git a/editor.planx.uk/src/pages/FlowEditor/index.tsx b/editor.planx.uk/src/pages/FlowEditor/index.tsx
index 1e68d998e7..cf55d4806b 100644
--- a/editor.planx.uk/src/pages/FlowEditor/index.tsx
+++ b/editor.planx.uk/src/pages/FlowEditor/index.tsx
@@ -5,7 +5,6 @@ import { styled } from "@mui/material/styles";
import { HEADER_HEIGHT_EDITOR } from "components/Header";
import React, { useRef } from "react";
-import { rootFlowPath } from "../../routes/utils";
import Flow from "./components/Flow";
import Sidebar from "./components/Sidebar";
import { useStore } from "./lib/store";
@@ -38,11 +37,7 @@ const FlowEditor: React.FC = ({ flow, breadcrumbs }) => {
- {showSidebar && (
-
- )}
+ {showSidebar && }
);
};