diff --git a/frontend/package-lock.json b/frontend/package-lock.json index fcf2d882b..4ca430062 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -46,6 +46,7 @@ "react-dom": "^18.2.0", "react-google-recaptcha": "^3.1.0", "react-gtm-module": "^2.0.11", + "react-helmet-async": "^2.0.5", "react-js-cron": "^5.0.1", "react-product-fruits": "^2.2.6", "react-router-dom": "^6.11.2", @@ -10325,6 +10326,14 @@ "node": ">= 0.4" } }, + "node_modules/invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "dependencies": { + "loose-envify": "^1.0.0" + } + }, "node_modules/ipaddr.js": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.1.0.tgz", @@ -17159,6 +17168,11 @@ "resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.11.tgz", "integrity": "sha512-/6UZ2qgEyH2aqzYZgQPxEnz33NJ2gNsnHA2o5+o4wW9bLM/JYQitNP9xPhsXwC08hMMovfGe/8retsdDsczPRg==" }, + "node_modules/react-fast-compare": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.2.tgz", + "integrity": "sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==" + }, "node_modules/react-google-recaptcha": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/react-google-recaptcha/-/react-google-recaptcha-3.1.0.tgz", @@ -17176,6 +17190,19 @@ "resolved": "https://registry.npmjs.org/react-gtm-module/-/react-gtm-module-2.0.11.tgz", "integrity": "sha512-8gyj4TTxeP7eEyc2QKawEuQoAZdjKvMY4pgWfycGmqGByhs17fR+zEBs0JUDq4US/l+vbTl+6zvUIx27iDo/Vw==" }, + "node_modules/react-helmet-async": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/react-helmet-async/-/react-helmet-async-2.0.5.tgz", + "integrity": "sha512-rYUYHeus+i27MvFE+Jaa4WsyBKGkL6qVgbJvSBoX8mbsWoABJXdEO0bZyi0F6i+4f0NuIb8AvqPMj3iXFHkMwg==", + "dependencies": { + "invariant": "^2.2.4", + "react-fast-compare": "^3.2.2", + "shallowequal": "^1.1.0" + }, + "peerDependencies": { + "react": "^16.6.0 || ^17.0.0 || ^18.0.0" + } + }, "node_modules/react-is": { "version": "18.2.0", "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", @@ -28018,6 +28045,14 @@ "side-channel": "^1.0.4" } }, + "invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "requires": { + "loose-envify": "^1.0.0" + } + }, "ipaddr.js": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.1.0.tgz", @@ -32800,6 +32835,11 @@ "resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.11.tgz", "integrity": "sha512-/6UZ2qgEyH2aqzYZgQPxEnz33NJ2gNsnHA2o5+o4wW9bLM/JYQitNP9xPhsXwC08hMMovfGe/8retsdDsczPRg==" }, + "react-fast-compare": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.2.tgz", + "integrity": "sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==" + }, "react-google-recaptcha": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/react-google-recaptcha/-/react-google-recaptcha-3.1.0.tgz", @@ -32814,6 +32854,16 @@ "resolved": "https://registry.npmjs.org/react-gtm-module/-/react-gtm-module-2.0.11.tgz", "integrity": "sha512-8gyj4TTxeP7eEyc2QKawEuQoAZdjKvMY4pgWfycGmqGByhs17fR+zEBs0JUDq4US/l+vbTl+6zvUIx27iDo/Vw==" }, + "react-helmet-async": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/react-helmet-async/-/react-helmet-async-2.0.5.tgz", + "integrity": "sha512-rYUYHeus+i27MvFE+Jaa4WsyBKGkL6qVgbJvSBoX8mbsWoABJXdEO0bZyi0F6i+4f0NuIb8AvqPMj3iXFHkMwg==", + "requires": { + "invariant": "^2.2.4", + "react-fast-compare": "^3.2.2", + "shallowequal": "^1.1.0" + } + }, "react-is": { "version": "18.2.0", "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", diff --git a/frontend/package.json b/frontend/package.json index e1709eddf..42f658ddb 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -41,6 +41,7 @@ "react-dom": "^18.2.0", "react-google-recaptcha": "^3.1.0", "react-gtm-module": "^2.0.11", + "react-helmet-async": "^2.0.5", "react-js-cron": "^5.0.1", "react-product-fruits": "^2.2.6", "react-router-dom": "^6.11.2", diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx index 9fbf63bee..071b590c0 100644 --- a/frontend/src/App.jsx +++ b/frontend/src/App.jsx @@ -1,11 +1,13 @@ import { Button, ConfigProvider, notification, theme } from "antd"; import { BrowserRouter } from "react-router-dom"; +import { HelmetProvider } from "react-helmet-async"; import { THEME } from "./helpers/GetStaticData.js"; import { Router } from "./routes/Router.jsx"; import { useAlertStore } from "./store/alert-store.js"; import { useSessionStore } from "./store/session-store.js"; import PostHogPageviewTracker from "./PostHogPageviewTracker.js"; +import { PageTitle } from "./components/widgets/page-title/PageTitle.jsx"; import { useEffect } from "react"; let GoogleTagManagerHelper; @@ -71,12 +73,15 @@ function App() { }, }} > - - - {GoogleTagManagerHelper && } - {contextHolder} - - + + + + + {GoogleTagManagerHelper && } + {contextHolder} + + + ); } diff --git a/frontend/src/components/agency/agency/Agency.jsx b/frontend/src/components/agency/agency/Agency.jsx index 92ae5f4c1..9215c996b 100644 --- a/frontend/src/components/agency/agency/Agency.jsx +++ b/frontend/src/components/agency/agency/Agency.jsx @@ -18,6 +18,7 @@ import { useWorkflowStore } from "../../../store/workflow-store"; import { LogsLabel } from "../logs-label/LogsLabel"; import { SidePanel } from "../side-panel/SidePanel"; import { DisplayLogs } from "../display-logs/DisplayLogs"; +import { PageTitle } from "../../widgets/page-title/PageTitle"; function Agency() { const [isCollapsed, setIsCollapsed] = useState(false); @@ -31,7 +32,7 @@ function Agency() { const { message, setDefault } = useSocketMessagesStore(); const { emptyLogs } = useSocketLogsStore(); const workflowStore = useWorkflowStore(); - const { details, loadingType } = workflowStore; + const { details, loadingType, projectName } = workflowStore; const prompt = details?.prompt_text; const [activeToolId, setActiveToolId] = useState(""); const [prevLoadingType, setPrevLoadingType] = useState(""); @@ -184,6 +185,7 @@ function Agency() { return (
+ diff --git a/frontend/src/components/custom-tools/tool-ide/ToolIde.jsx b/frontend/src/components/custom-tools/tool-ide/ToolIde.jsx index 019d4a954..f64c73f74 100644 --- a/frontend/src/components/custom-tools/tool-ide/ToolIde.jsx +++ b/frontend/src/components/custom-tools/tool-ide/ToolIde.jsx @@ -15,6 +15,8 @@ import { SettingsModal } from "../settings-modal/SettingsModal"; import { ToolsMain } from "../tools-main/ToolsMain"; import "./ToolIde.css"; import usePostHogEvents from "../../../hooks/usePostHogEvents.js"; +import { PageTitle } from "../../widgets/page-title/PageTitle.jsx"; + let OnboardMessagesModal; let PromptShareModal; let PromptShareLink; @@ -227,6 +229,7 @@ function ToolIde() { return (
+ {isPublicSource && HeaderPublic && }
+ {title ? `${title} - Unstract` : "Unstract"} + + ); +} + +PageTitle.propTypes = { + title: PropTypes.string, +}; + +export { PageTitle };