diff --git a/web/src/app/admin/assistants/AssistantEditor.tsx b/web/src/app/admin/assistants/AssistantEditor.tsx index 1f961614dbc..19ddba86b3c 100644 --- a/web/src/app/admin/assistants/AssistantEditor.tsx +++ b/web/src/app/admin/assistants/AssistantEditor.tsx @@ -106,6 +106,7 @@ export function AssistantEditor({ admin?: boolean; }) { const router = useRouter(); + const { popup, setPopup } = usePopup(); const colorOptions = [ diff --git a/web/src/app/admin/configuration/search/page.tsx b/web/src/app/admin/configuration/search/page.tsx index 6a0d428d357..a66e45d9023 100644 --- a/web/src/app/admin/configuration/search/page.tsx +++ b/web/src/app/admin/configuration/search/page.tsx @@ -19,7 +19,9 @@ export interface EmbeddingDetails { default_model_id?: number; name: string; } + import { EmbeddingIcon } from "@/components/icons/icons"; +import { usePopupFromQuery } from "@/components/popup/PopupFromQuery"; import Link from "next/link"; import { SavedSearchSettings } from "../../embeddings/interfaces"; @@ -29,6 +31,12 @@ import { SettingsContext } from "@/components/settings/SettingsProvider"; function Main() { const settings = useContext(SettingsContext); + const { popup: searchSettingsPopup } = usePopupFromQuery({ + "search-settings": { + message: `Changed search settings successfully`, + type: "success", + }, + }); const { data: currentEmeddingModel, isLoading: isLoadingCurrentModel, @@ -74,6 +82,7 @@ function Main() { return (
+ {searchSettingsPopup} {!futureEmbeddingModel ? ( <> {settings?.settings.needs_reindexing && ( diff --git a/web/src/app/admin/connectors/[connector]/AddConnectorPage.tsx b/web/src/app/admin/connectors/[connector]/AddConnectorPage.tsx index 8294b6ca0d0..07b719d8341 100644 --- a/web/src/app/admin/connectors/[connector]/AddConnectorPage.tsx +++ b/web/src/app/admin/connectors/[connector]/AddConnectorPage.tsx @@ -41,7 +41,7 @@ import { Formik } from "formik"; import { AccessTypeForm } from "@/components/admin/connectors/AccessTypeForm"; import { AccessTypeGroupSelector } from "@/components/admin/connectors/AccessTypeGroupSelector"; import NavigationRow from "./NavigationRow"; - +import { useRouter } from "next/navigation"; export interface AdvancedConfig { refreshFreq: number; pruneFreq: number; @@ -111,6 +111,8 @@ export default function AddConnector({ }: { connector: ConfigurableSources; }) { + const router = useRouter(); + // State for managing credentials and files const [currentCredential, setCurrentCredential] = useState | null>(null); @@ -201,13 +203,7 @@ export default function AddConnector({ }; const onSuccess = () => { - setPopup({ - message: "Connector created! Redirecting to connector home page", - type: "success", - }); - setTimeout(() => { - window.open("/admin/indexing/status", "_self"); - }, 1000); + router.push("/admin/indexing/status?message=connector-created"); }; return ( diff --git a/web/src/app/admin/embeddings/pages/EmbeddingFormPage.tsx b/web/src/app/admin/embeddings/pages/EmbeddingFormPage.tsx index adf486ed5d4..196c99da0d2 100644 --- a/web/src/app/admin/embeddings/pages/EmbeddingFormPage.tsx +++ b/web/src/app/admin/embeddings/pages/EmbeddingFormPage.tsx @@ -25,9 +25,11 @@ import RerankingDetailsForm from "../RerankingFormPage"; import { useEmbeddingFormContext } from "@/components/context/EmbeddingContext"; import { Modal } from "@/components/Modal"; +import { useRouter } from "next/navigation"; export default function EmbeddingForm() { const { formStep, nextFormStep, prevFormStep } = useEmbeddingFormContext(); const { popup, setPopup } = usePopup(); + const router = useRouter(); const [advancedEmbeddingDetails, setAdvancedEmbeddingDetails] = useState({ @@ -172,10 +174,6 @@ export default function EmbeddingForm() { const response = await updateSearchSettings(values); if (response.ok) { - setPopup({ - message: "Updated search settings successfully", - type: "success", - }); return true; } else { setPopup({ message: "Failed to update search settings", type: "error" }); @@ -184,14 +182,7 @@ export default function EmbeddingForm() { }; const navigateToEmbeddingPage = (changedResource: string) => { - setPopup({ - message: `Changed ${changedResource} successfully. Redirecting to embedding page`, - type: "success", - }); - - setTimeout(() => { - window.open("/admin/configuration/search", "_self"); - }, 2000); + router.push("/admin/configuration/search?message=search-settings"); }; const onConfirm = async () => { diff --git a/web/src/app/admin/indexing/status/page.tsx b/web/src/app/admin/indexing/status/page.tsx index f5d64d3ac3a..bb56ceaa74e 100644 --- a/web/src/app/admin/indexing/status/page.tsx +++ b/web/src/app/admin/indexing/status/page.tsx @@ -11,8 +11,15 @@ import { AdminPageTitle } from "@/components/admin/Title"; import Link from "next/link"; import { Button, Text } from "@tremor/react"; import { useConnectorCredentialIndexingStatus } from "@/lib/hooks"; +import { usePopupFromQuery } from "@/components/popup/PopupFromQuery"; function Main() { + const { popup } = usePopupFromQuery({ + "connector-created": { + message: "Connector created successfully", + type: "success", + }, + }); const { data: indexAttemptData, isLoading: indexAttemptIsLoading, @@ -67,10 +74,13 @@ function Main() { }); return ( - + <> + {popup} + + ); } diff --git a/web/src/components/context/EmbeddingContext.tsx b/web/src/components/context/EmbeddingContext.tsx index 2ca18dc955e..3d03b99b1d5 100644 --- a/web/src/components/context/EmbeddingContext.tsx +++ b/web/src/components/context/EmbeddingContext.tsx @@ -57,9 +57,15 @@ export const EmbeddingFormProvider: React.FC<{ useEffect(() => { // Update URL when formStep changes const updatedSearchParams = new URLSearchParams(searchParams.toString()); + const existingStep = updatedSearchParams.get("step"); updatedSearchParams.set("step", formStep.toString()); const newUrl = `${pathname}?${updatedSearchParams.toString()}`; - router.push(newUrl); + + if (!existingStep) { + router.replace(newUrl); + } else if (newUrl !== pathname) { + router.push(newUrl); + } }, [formStep, router, pathname, searchParams]); // Update formStep when URL changes diff --git a/web/src/components/context/FormContext.tsx b/web/src/components/context/FormContext.tsx index 8755fbe6da1..d445782f718 100644 --- a/web/src/components/context/FormContext.tsx +++ b/web/src/components/context/FormContext.tsx @@ -57,12 +57,17 @@ export const FormProvider: React.FC<{ useEffect(() => { // Update URL when formStep changes const updatedSearchParams = new URLSearchParams(searchParams.toString()); + const existingStep = updatedSearchParams.get("step"); updatedSearchParams.set("step", formStep.toString()); const newUrl = `${pathname}?${updatedSearchParams.toString()}`; - router.push(newUrl); + + if (!existingStep) { + router.replace(newUrl); + } else if (newUrl !== pathname) { + router.push(newUrl); + } }, [formStep, router, pathname, searchParams]); - // Update formStep when URL changes useEffect(() => { const stepFromUrl = parseInt(searchParams.get("step") || "0", 10); if (stepFromUrl !== formStep) { diff --git a/web/src/components/popup/PopupFromQuery.tsx b/web/src/components/popup/PopupFromQuery.tsx new file mode 100644 index 00000000000..71834f69987 --- /dev/null +++ b/web/src/components/popup/PopupFromQuery.tsx @@ -0,0 +1,28 @@ +import { useEffect } from "react"; + +import { usePopup } from "../admin/connectors/Popup"; +import { PopupSpec } from "../admin/connectors/Popup"; +import { useRouter } from "next/navigation"; + +interface PopupMessages { + [key: string]: PopupSpec; +} + +export const usePopupFromQuery = (messages: PopupMessages) => { + const router = useRouter(); + const { popup, setPopup } = usePopup(); + + useEffect(() => { + const searchParams = new URLSearchParams(window.location.search); + // Get the value for search param with key "message" + const messageValue = searchParams.get("message"); + // Check if any key from messages object is present in search params + if (messageValue && messageValue in messages) { + const popupMessage = messages[messageValue]; + router.replace(window.location.pathname); + setPopup(popupMessage); + } + }, []); + + return { popup }; +};