refactor: modular navigation and custom api calls (#3613)
* Added customization files * Added custom API headers and changed logout mutation * Changed mutationLogout on authGuard * Renamed feature flags * Changed auto login to run after primary loading * Removed unused code * Added undefined on mutationfunctiontype to have options * Changed logout to mutationLogout * Return data on getConfig * Added custom wrapper * changed hasStore to be the constant by default * Added custom header * Added customParam feature flag * Fix routes and custom link and navigate to consider absolute and relative paths * Fixed regex on tabs search component * Added CustomNavigate * Added basename and ports and URLs config * [autofix.ci] apply automated fixes * Update config-constants.ts * Update index.tsx * Fixed path comparations --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
This commit is contained in:
parent
cb1a2f24b3
commit
06ea6c408b
54 changed files with 300 additions and 215 deletions
|
|
@ -1,9 +0,0 @@
|
||||||
{
|
|
||||||
"ENABLE_DARK_MODE": true,
|
|
||||||
"ENABLE_API": true,
|
|
||||||
"ENABLE_LANGFLOW_STORE": true,
|
|
||||||
"ENABLE_PROFILE_ICONS": true,
|
|
||||||
"ENABLE_SOCIAL_LINKS": true,
|
|
||||||
"ENABLE_BRANDING": true,
|
|
||||||
"ENABLE_MVPS": false
|
|
||||||
}
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import { defineConfig, devices } from "@playwright/test";
|
import { defineConfig, devices } from "@playwright/test";
|
||||||
import * as dotenv from "dotenv";
|
import * as dotenv from "dotenv";
|
||||||
import path from "path";
|
import path from "path";
|
||||||
|
import { PORT } from "./src/customization/config-constants";
|
||||||
dotenv.config();
|
dotenv.config();
|
||||||
dotenv.config({ path: path.resolve(__dirname, "../../.env") });
|
dotenv.config({ path: path.resolve(__dirname, "../../.env") });
|
||||||
|
|
||||||
|
|
@ -31,7 +32,7 @@ export default defineConfig({
|
||||||
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
|
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
|
||||||
use: {
|
use: {
|
||||||
/* Base URL to use in actions like `await page.goto('/')`. */
|
/* Base URL to use in actions like `await page.goto('/')`. */
|
||||||
baseURL: "http://localhost:3000/",
|
baseURL: `http://localhost:${PORT || 3000}/`,
|
||||||
|
|
||||||
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
|
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
|
||||||
trace: "on-first-retry",
|
trace: "on-first-retry",
|
||||||
|
|
@ -85,7 +86,7 @@ export default defineConfig({
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
command: "npm start",
|
command: "npm start",
|
||||||
port: 3000,
|
port: PORT || 3000,
|
||||||
env: {
|
env: {
|
||||||
VITE_PROXY_TARGET: "http://127.0.0.1:7860",
|
VITE_PROXY_TARGET: "http://127.0.0.1:7860",
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
|
import { CustomLink } from "@/customization/components/custom-link";
|
||||||
import { Transition } from "@headlessui/react";
|
import { Transition } from "@headlessui/react";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { Link } from "react-router-dom";
|
|
||||||
import IconComponent from "../../../../components/genericIconComponent";
|
import IconComponent from "../../../../components/genericIconComponent";
|
||||||
import { SingleAlertComponentType } from "../../../../types/alerts";
|
import { SingleAlertComponentType } from "../../../../types/alerts";
|
||||||
|
|
||||||
|
|
@ -93,12 +93,12 @@ export default function SingleAlert({
|
||||||
</p>
|
</p>
|
||||||
<p className="mt-3 text-sm md:ml-6 md:mt-0">
|
<p className="mt-3 text-sm md:ml-6 md:mt-0">
|
||||||
{dropItem.link ? (
|
{dropItem.link ? (
|
||||||
<Link
|
<CustomLink
|
||||||
to={dropItem.link}
|
to={dropItem.link}
|
||||||
className="whitespace-nowrap font-medium text-info-foreground hover:text-accent-foreground"
|
className="whitespace-nowrap font-medium text-info-foreground hover:text-accent-foreground"
|
||||||
>
|
>
|
||||||
Details
|
Details
|
||||||
</Link>
|
</CustomLink>
|
||||||
) : (
|
) : (
|
||||||
<></>
|
<></>
|
||||||
)}
|
)}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
|
import { CustomLink } from "@/customization/components/custom-link";
|
||||||
import { Transition } from "@headlessui/react";
|
import { Transition } from "@headlessui/react";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { Link } from "react-router-dom";
|
|
||||||
import IconComponent from "../../components/genericIconComponent";
|
import IconComponent from "../../components/genericIconComponent";
|
||||||
import { NoticeAlertType } from "../../types/alerts";
|
import { NoticeAlertType } from "../../types/alerts";
|
||||||
|
|
||||||
|
|
@ -52,12 +52,12 @@ export default function NoticeAlert({
|
||||||
</p>
|
</p>
|
||||||
<p className="mt-3 text-sm md:ml-6 md:mt-0">
|
<p className="mt-3 text-sm md:ml-6 md:mt-0">
|
||||||
{link !== "" ? (
|
{link !== "" ? (
|
||||||
<Link
|
<CustomLink
|
||||||
to={link}
|
to={link}
|
||||||
className="whitespace-nowrap font-medium text-info-foreground hover:text-accent-foreground"
|
className="whitespace-nowrap font-medium text-info-foreground hover:text-accent-foreground"
|
||||||
>
|
>
|
||||||
Details
|
Details
|
||||||
</Link>
|
</CustomLink>
|
||||||
) : (
|
) : (
|
||||||
<></>
|
<></>
|
||||||
)}
|
)}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
|
import { CustomNavigate } from "@/customization/components/custom-navigate";
|
||||||
import { LoadingPage } from "@/pages/LoadingPage";
|
import { LoadingPage } from "@/pages/LoadingPage";
|
||||||
import useAuthStore from "@/stores/authStore";
|
import useAuthStore from "@/stores/authStore";
|
||||||
import { useContext } from "react";
|
import { useContext } from "react";
|
||||||
import { Navigate } from "react-router-dom";
|
|
||||||
import { AuthContext } from "../../contexts/authContext";
|
import { AuthContext } from "../../contexts/authContext";
|
||||||
|
|
||||||
export const ProtectedAdminRoute = ({ children }) => {
|
export const ProtectedAdminRoute = ({ children }) => {
|
||||||
|
|
@ -13,7 +13,7 @@ export const ProtectedAdminRoute = ({ children }) => {
|
||||||
if (!isAuthenticated) {
|
if (!isAuthenticated) {
|
||||||
return <LoadingPage />;
|
return <LoadingPage />;
|
||||||
} else if ((userData && !isAdmin) || autoLogin) {
|
} else if ((userData && !isAdmin) || autoLogin) {
|
||||||
return <Navigate to="/" replace />;
|
return <CustomNavigate to="/" replace />;
|
||||||
} else {
|
} else {
|
||||||
return children;
|
return children;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,10 @@ import {
|
||||||
LANGFLOW_ACCESS_TOKEN_EXPIRE_SECONDS_ENV,
|
LANGFLOW_ACCESS_TOKEN_EXPIRE_SECONDS_ENV,
|
||||||
LANGFLOW_AUTO_LOGIN_OPTION,
|
LANGFLOW_AUTO_LOGIN_OPTION,
|
||||||
} from "@/constants/constants";
|
} from "@/constants/constants";
|
||||||
import { useRefreshAccessToken } from "@/controllers/API/queries/auth";
|
import {
|
||||||
|
useLogout,
|
||||||
|
useRefreshAccessToken,
|
||||||
|
} from "@/controllers/API/queries/auth";
|
||||||
import useAuthStore from "@/stores/authStore";
|
import useAuthStore from "@/stores/authStore";
|
||||||
import { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
import { Cookies } from "react-cookie";
|
import { Cookies } from "react-cookie";
|
||||||
|
|
@ -11,11 +14,11 @@ import { Cookies } from "react-cookie";
|
||||||
export const ProtectedRoute = ({ children }) => {
|
export const ProtectedRoute = ({ children }) => {
|
||||||
const isAuthenticated = useAuthStore((state) => state.isAuthenticated);
|
const isAuthenticated = useAuthStore((state) => state.isAuthenticated);
|
||||||
const hasToken = !!localStorage.getItem(LANGFLOW_AUTO_LOGIN_OPTION);
|
const hasToken = !!localStorage.getItem(LANGFLOW_AUTO_LOGIN_OPTION);
|
||||||
const logout = useAuthStore((state) => state.logout);
|
|
||||||
|
|
||||||
const cookies = new Cookies();
|
const cookies = new Cookies();
|
||||||
const refreshToken = cookies.get("refresh_token");
|
const refreshToken = cookies.get("refresh_token");
|
||||||
const { mutate: mutateRefresh } = useRefreshAccessToken();
|
const { mutate: mutateRefresh } = useRefreshAccessToken();
|
||||||
|
const { mutate: mutationLogout } = useLogout();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const envRefreshTime = LANGFLOW_ACCESS_TOKEN_EXPIRE_SECONDS_ENV;
|
const envRefreshTime = LANGFLOW_ACCESS_TOKEN_EXPIRE_SECONDS_ENV;
|
||||||
|
|
@ -38,7 +41,7 @@ export const ProtectedRoute = ({ children }) => {
|
||||||
}, [isAuthenticated]);
|
}, [isAuthenticated]);
|
||||||
|
|
||||||
if (!isAuthenticated && hasToken) {
|
if (!isAuthenticated && hasToken) {
|
||||||
logout();
|
mutationLogout();
|
||||||
} else {
|
} else {
|
||||||
return children;
|
return children;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,16 @@
|
||||||
|
import { CustomNavigate } from "@/customization/components/custom-navigate";
|
||||||
import useAuthStore from "@/stores/authStore";
|
import useAuthStore from "@/stores/authStore";
|
||||||
import { Navigate } from "react-router-dom";
|
|
||||||
|
|
||||||
export const ProtectedLoginRoute = ({ children }) => {
|
export const ProtectedLoginRoute = ({ children }) => {
|
||||||
const autoLogin = useAuthStore((state) => state.autoLogin);
|
const autoLogin = useAuthStore((state) => state.autoLogin);
|
||||||
const isAuthenticated = useAuthStore((state) => state.isAuthenticated);
|
const isAuthenticated = useAuthStore((state) => state.isAuthenticated);
|
||||||
|
|
||||||
if (autoLogin === true) {
|
if (autoLogin === true) {
|
||||||
window.location.replace("/");
|
return <CustomNavigate to="/" replace />;
|
||||||
return <Navigate to="/" replace />;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isAuthenticated) {
|
if (isAuthenticated) {
|
||||||
window.location.replace("/");
|
return <CustomNavigate to="/" replace />;
|
||||||
return <Navigate to="/" replace />;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return children;
|
return children;
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,18 @@
|
||||||
import FeatureFlags from "@/../feature-config.json";
|
import { CustomNavigate } from "@/customization/components/custom-navigate";
|
||||||
|
import { ENABLE_PROFILE_ICONS } from "@/customization/feature-flags";
|
||||||
import useAuthStore from "@/stores/authStore";
|
import useAuthStore from "@/stores/authStore";
|
||||||
import { useStoreStore } from "@/stores/storeStore";
|
import { useStoreStore } from "@/stores/storeStore";
|
||||||
import { Navigate } from "react-router-dom";
|
|
||||||
|
|
||||||
export const AuthSettingsGuard = ({ children }) => {
|
export const AuthSettingsGuard = ({ children }) => {
|
||||||
const autoLogin = useAuthStore((state) => state.autoLogin);
|
const autoLogin = useAuthStore((state) => state.autoLogin);
|
||||||
const hasStore = useStoreStore((state) => state.hasStore);
|
const hasStore = useStoreStore((state) => state.hasStore);
|
||||||
|
|
||||||
// Hides the General settings if there is nothing to show
|
// Hides the General settings if there is nothing to show
|
||||||
const showGeneralSettings =
|
const showGeneralSettings = ENABLE_PROFILE_ICONS || hasStore || !autoLogin;
|
||||||
FeatureFlags.ENABLE_PROFILE_ICONS || hasStore || !autoLogin;
|
|
||||||
|
|
||||||
if (showGeneralSettings) {
|
if (showGeneralSettings) {
|
||||||
return children;
|
return children;
|
||||||
} else {
|
} else {
|
||||||
return <Navigate replace to="global-variables" />;
|
return <CustomNavigate replace to="global-variables" />;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
|
import { useCustomNavigate } from "@/customization/hooks/use-custom-navigate";
|
||||||
import { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
import { useNavigate } from "react-router-dom";
|
|
||||||
|
|
||||||
export const CatchAllRoute = () => {
|
export const CatchAllRoute = () => {
|
||||||
const navigate = useNavigate();
|
const navigate = useCustomNavigate();
|
||||||
|
|
||||||
// Redirect to the root ("/") when the catch-all route is matched
|
// Redirect to the root ("/") when the catch-all route is matched
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import FeatureFlags from "@/../feature-config.json";
|
import { ENABLE_API } from "@/customization/feature-flags";
|
||||||
import { Transition } from "@headlessui/react";
|
import { Transition } from "@headlessui/react";
|
||||||
import { useMemo, useState } from "react";
|
import { useMemo, useState } from "react";
|
||||||
import { useHotkeys } from "react-hotkeys-hook";
|
import { useHotkeys } from "react-hotkeys-hook";
|
||||||
|
|
@ -138,7 +138,7 @@ export default function FlowToolbar(): JSX.Element {
|
||||||
<div>
|
<div>
|
||||||
<Separator orientation="vertical" />
|
<Separator orientation="vertical" />
|
||||||
</div>
|
</div>
|
||||||
{FeatureFlags.ENABLE_API && (
|
{ENABLE_API && (
|
||||||
<>
|
<>
|
||||||
<div className="flex cursor-pointer items-center gap-2">
|
<div className="flex cursor-pointer items-center gap-2">
|
||||||
{currentFlow && currentFlow.data && (
|
{currentFlow && currentFlow.data && (
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import {
|
||||||
usePostUploadFolders,
|
usePostUploadFolders,
|
||||||
} from "@/controllers/API/queries/folders";
|
} from "@/controllers/API/queries/folders";
|
||||||
import { useGetDownloadFolders } from "@/controllers/API/queries/folders/use-get-download-folders";
|
import { useGetDownloadFolders } from "@/controllers/API/queries/folders/use-get-download-folders";
|
||||||
|
import { ENABLE_CUSTOM_PARAM } from "@/customization/feature-flags";
|
||||||
import { createFileUpload } from "@/helpers/create-file-upload";
|
import { createFileUpload } from "@/helpers/create-file-upload";
|
||||||
import { getObjectsFromFilelist } from "@/helpers/get-objects-from-filelist";
|
import { getObjectsFromFilelist } from "@/helpers/get-objects-from-filelist";
|
||||||
import useUploadFlow from "@/hooks/flows/use-upload-flow";
|
import useUploadFlow from "@/hooks/flows/use-upload-flow";
|
||||||
|
|
@ -44,7 +45,8 @@ const SideBarFoldersButtonsComponent = ({
|
||||||
folders.map((obj) => ({ name: obj.name, edit: false })) ?? [],
|
folders.map((obj) => ({ name: obj.name, edit: false })) ?? [],
|
||||||
);
|
);
|
||||||
const currentFolder = pathname.split("/");
|
const currentFolder = pathname.split("/");
|
||||||
const urlWithoutPath = pathname.split("/").length < 4;
|
const urlWithoutPath =
|
||||||
|
pathname.split("/").length < (ENABLE_CUSTOM_PARAM ? 5 : 4);
|
||||||
const myCollectionId = useFolderStore((state) => state.myCollectionId);
|
const myCollectionId = useFolderStore((state) => state.myCollectionId);
|
||||||
const folderIdDragging = useFolderStore((state) => state.folderIdDragging);
|
const folderIdDragging = useFolderStore((state) => state.folderIdDragging);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,12 +7,12 @@ import {
|
||||||
DropdownMenuTrigger,
|
DropdownMenuTrigger,
|
||||||
} from "../../../ui/dropdown-menu";
|
} from "../../../ui/dropdown-menu";
|
||||||
|
|
||||||
|
import { useCustomNavigate } from "@/customization/hooks/use-custom-navigate";
|
||||||
import useAddFlow from "@/hooks/flows/use-add-flow";
|
import useAddFlow from "@/hooks/flows/use-add-flow";
|
||||||
import useSaveFlow from "@/hooks/flows/use-save-flow";
|
import useSaveFlow from "@/hooks/flows/use-save-flow";
|
||||||
import useUploadFlow from "@/hooks/flows/use-upload-flow";
|
import useUploadFlow from "@/hooks/flows/use-upload-flow";
|
||||||
import { customStringify } from "@/utils/reactflowUtils";
|
import { customStringify } from "@/utils/reactflowUtils";
|
||||||
import { useHotkeys } from "react-hotkeys-hook";
|
import { useHotkeys } from "react-hotkeys-hook";
|
||||||
import { useNavigate } from "react-router-dom";
|
|
||||||
import { UPLOAD_ERROR_ALERT } from "../../../../constants/alerts_constants";
|
import { UPLOAD_ERROR_ALERT } from "../../../../constants/alerts_constants";
|
||||||
import { SAVED_HOVER } from "../../../../constants/constants";
|
import { SAVED_HOVER } from "../../../../constants/constants";
|
||||||
import ExportModal from "../../../../modals/exportModal";
|
import ExportModal from "../../../../modals/exportModal";
|
||||||
|
|
@ -40,7 +40,7 @@ export const MenuBar = ({}: {}): JSX.Element => {
|
||||||
const [openSettings, setOpenSettings] = useState(false);
|
const [openSettings, setOpenSettings] = useState(false);
|
||||||
const [openLogs, setOpenLogs] = useState(false);
|
const [openLogs, setOpenLogs] = useState(false);
|
||||||
const uploadFlow = useUploadFlow();
|
const uploadFlow = useUploadFlow();
|
||||||
const navigate = useNavigate();
|
const navigate = useCustomNavigate();
|
||||||
const isBuilding = useFlowStore((state) => state.isBuilding);
|
const isBuilding = useFlowStore((state) => state.isBuilding);
|
||||||
const getTypes = useTypesStore((state) => state.getTypes);
|
const getTypes = useTypesStore((state) => state.getTypes);
|
||||||
const saveFlow = useSaveFlow();
|
const saveFlow = useSaveFlow();
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { useContext } from "react";
|
import { useContext } from "react";
|
||||||
import { FaDiscord, FaGithub } from "react-icons/fa";
|
import { FaDiscord, FaGithub } from "react-icons/fa";
|
||||||
import { RiTwitterXFill } from "react-icons/ri";
|
import { RiTwitterXFill } from "react-icons/ri";
|
||||||
import { Link, useLocation, useNavigate } from "react-router-dom";
|
import { useLocation } from "react-router-dom";
|
||||||
import AlertDropdown from "../../alerts/alertDropDown";
|
import AlertDropdown from "../../alerts/alertDropDown";
|
||||||
import {
|
import {
|
||||||
BASE_URL_API,
|
BASE_URL_API,
|
||||||
|
|
@ -10,8 +10,14 @@ import {
|
||||||
} from "../../constants/constants";
|
} from "../../constants/constants";
|
||||||
import { AuthContext } from "../../contexts/authContext";
|
import { AuthContext } from "../../contexts/authContext";
|
||||||
|
|
||||||
import FeatureFlags from "@/../feature-config.json";
|
|
||||||
import { useLogout } from "@/controllers/API/queries/auth";
|
import { useLogout } from "@/controllers/API/queries/auth";
|
||||||
|
import { CustomLink } from "@/customization/components/custom-link";
|
||||||
|
import {
|
||||||
|
ENABLE_DARK_MODE,
|
||||||
|
ENABLE_PROFILE_ICONS,
|
||||||
|
ENABLE_SOCIAL_LINKS,
|
||||||
|
} from "@/customization/feature-flags";
|
||||||
|
import { useCustomNavigate } from "@/customization/hooks/use-custom-navigate";
|
||||||
import useAuthStore from "@/stores/authStore";
|
import useAuthStore from "@/stores/authStore";
|
||||||
import useAlertStore from "../../stores/alertStore";
|
import useAlertStore from "../../stores/alertStore";
|
||||||
import { useDarkStore } from "../../stores/darkStore";
|
import { useDarkStore } from "../../stores/darkStore";
|
||||||
|
|
@ -38,9 +44,8 @@ export default function Header(): JSX.Element {
|
||||||
const autoLogin = useAuthStore((state) => state.autoLogin);
|
const autoLogin = useAuthStore((state) => state.autoLogin);
|
||||||
|
|
||||||
const { mutate: mutationLogout } = useLogout();
|
const { mutate: mutationLogout } = useLogout();
|
||||||
const logout = useAuthStore((state) => state.logout);
|
|
||||||
|
|
||||||
const navigate = useNavigate();
|
const navigate = useCustomNavigate();
|
||||||
const hasStore = useStoreStore((state) => state.hasStore);
|
const hasStore = useStoreStore((state) => state.hasStore);
|
||||||
|
|
||||||
const dark = useDarkStore((state) => state.dark);
|
const dark = useDarkStore((state) => state.dark);
|
||||||
|
|
@ -65,22 +70,15 @@ export default function Header(): JSX.Element {
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleLogout = () => {
|
const handleLogout = () => {
|
||||||
mutationLogout(undefined, {
|
mutationLogout();
|
||||||
onSuccess: () => {
|
|
||||||
logout();
|
|
||||||
},
|
|
||||||
onError: (error) => {
|
|
||||||
console.error(error);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="header-arrangement relative">
|
<div className="header-arrangement relative">
|
||||||
<div className="header-start-display">
|
<div className="header-start-display">
|
||||||
<Link to="/all" className="cursor-pointer">
|
<CustomLink to="/all" className="cursor-pointer">
|
||||||
<span className="ml-4 text-2xl">⛓️</span>
|
<span className="ml-4 text-2xl">⛓️</span>
|
||||||
</Link>
|
</CustomLink>
|
||||||
{showArrowReturnIcon && (
|
{showArrowReturnIcon && (
|
||||||
<Button
|
<Button
|
||||||
unstyled
|
unstyled
|
||||||
|
|
@ -96,12 +94,12 @@ export default function Header(): JSX.Element {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex items-center xl:absolute xl:left-1/2 xl:-translate-x-1/2">
|
<div className="flex items-center xl:absolute xl:left-1/2 xl:-translate-x-1/2">
|
||||||
<Link to="/all">
|
<CustomLink to="/all">
|
||||||
<Button
|
<Button
|
||||||
className="gap-2"
|
className="gap-2"
|
||||||
variant={
|
variant={
|
||||||
location.pathname === "/all" ||
|
location.pathname.includes("/all") ||
|
||||||
location.pathname === "/components"
|
location.pathname.includes("/components")
|
||||||
? "primary"
|
? "primary"
|
||||||
: "secondary"
|
: "secondary"
|
||||||
}
|
}
|
||||||
|
|
@ -110,25 +108,27 @@ export default function Header(): JSX.Element {
|
||||||
<IconComponent name="Home" className="h-4 w-4" />
|
<IconComponent name="Home" className="h-4 w-4" />
|
||||||
<div className="hidden flex-1 lg:block">{USER_PROJECTS_HEADER}</div>
|
<div className="hidden flex-1 lg:block">{USER_PROJECTS_HEADER}</div>
|
||||||
</Button>
|
</Button>
|
||||||
</Link>
|
</CustomLink>
|
||||||
|
|
||||||
{hasStore && (
|
{hasStore && (
|
||||||
<Link to="/store">
|
<CustomLink to="/store">
|
||||||
<Button
|
<Button
|
||||||
className="gap-2"
|
className="gap-2"
|
||||||
variant={location.pathname === "/store" ? "primary" : "secondary"}
|
variant={
|
||||||
|
location.pathname.includes("/store") ? "primary" : "secondary"
|
||||||
|
}
|
||||||
size="sm"
|
size="sm"
|
||||||
data-testid="button-store"
|
data-testid="button-store"
|
||||||
>
|
>
|
||||||
<IconComponent name="Store" className="h-4 w-4" />
|
<IconComponent name="Store" className="h-4 w-4" />
|
||||||
<div className="hidden flex-1 lg:block">Store</div>
|
<div className="hidden flex-1 lg:block">Store</div>
|
||||||
</Button>
|
</Button>
|
||||||
</Link>
|
</CustomLink>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="header-end-division">
|
<div className="header-end-division">
|
||||||
<div className="header-end-display">
|
<div className="header-end-display">
|
||||||
{FeatureFlags.ENABLE_SOCIAL_LINKS && (
|
{ENABLE_SOCIAL_LINKS && (
|
||||||
<>
|
<>
|
||||||
<a
|
<a
|
||||||
href="https://github.com/langflow-ai/langflow"
|
href="https://github.com/langflow-ai/langflow"
|
||||||
|
|
@ -160,7 +160,7 @@ export default function Header(): JSX.Element {
|
||||||
<Separator orientation="vertical" />
|
<Separator orientation="vertical" />
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
{FeatureFlags.ENABLE_DARK_MODE && (
|
{ENABLE_DARK_MODE && (
|
||||||
<button
|
<button
|
||||||
className="extra-side-bar-save-disable"
|
className="extra-side-bar-save-disable"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
|
@ -202,7 +202,7 @@ export default function Header(): JSX.Element {
|
||||||
data-testid="user-profile-settings"
|
data-testid="user-profile-settings"
|
||||||
className="shrink-0"
|
className="shrink-0"
|
||||||
>
|
>
|
||||||
{FeatureFlags.ENABLE_PROFILE_ICONS ? (
|
{ENABLE_PROFILE_ICONS ? (
|
||||||
<img
|
<img
|
||||||
src={profileImageUrl}
|
src={profileImageUrl}
|
||||||
className="h-7 w-7 shrink-0 focus-visible:outline-0"
|
className="h-7 w-7 shrink-0 focus-visible:outline-0"
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { Link } from "react-router-dom";
|
import { CustomLink } from "@/customization/components/custom-link";
|
||||||
import { cn } from "../../../../utils/utils";
|
import { cn } from "../../../../utils/utils";
|
||||||
import { buttonVariants } from "../../../ui/button";
|
import { buttonVariants } from "../../../ui/button";
|
||||||
|
|
||||||
|
|
@ -18,13 +18,13 @@ const SideBarButtonsComponent = ({
|
||||||
return (
|
return (
|
||||||
<div className="flex gap-2 overflow-auto lg:h-[70vh] lg:flex-col">
|
<div className="flex gap-2 overflow-auto lg:h-[70vh] lg:flex-col">
|
||||||
{items.map((item) => (
|
{items.map((item) => (
|
||||||
<Link to={item.href!}>
|
<CustomLink to={item.href!}>
|
||||||
<div
|
<div
|
||||||
key={item.title}
|
key={item.title}
|
||||||
data-testid={`sidebar-nav-${item.title}`}
|
data-testid={`sidebar-nav-${item.title}`}
|
||||||
className={cn(
|
className={cn(
|
||||||
buttonVariants({ variant: "ghost" }),
|
buttonVariants({ variant: "ghost" }),
|
||||||
pathname === item.href
|
item.href && pathname.endsWith(item.href)
|
||||||
? "border border-border bg-muted hover:bg-muted"
|
? "border border-border bg-muted hover:bg-muted"
|
||||||
: "border border-transparent hover:border-border hover:bg-transparent",
|
: "border border-transparent hover:border-border hover:bg-transparent",
|
||||||
"flex w-full shrink-0 justify-start gap-4",
|
"flex w-full shrink-0 justify-start gap-4",
|
||||||
|
|
@ -35,7 +35,7 @@ const SideBarButtonsComponent = ({
|
||||||
{item.title}
|
{item.title}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</Link>
|
</CustomLink>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
import { Navigate } from "react-router-dom";
|
import { CustomNavigate } from "@/customization/components/custom-navigate";
|
||||||
import { useStoreStore } from "../../stores/storeStore";
|
import { useStoreStore } from "../../stores/storeStore";
|
||||||
|
|
||||||
export const StoreGuard = ({ children }) => {
|
export const StoreGuard = ({ children }) => {
|
||||||
const hasStore = useStoreStore((state) => state.hasStore);
|
const hasStore = useStoreStore((state) => state.hasStore);
|
||||||
|
|
||||||
if (!hasStore) {
|
if (!hasStore) {
|
||||||
return <Navigate to="/all" replace />;
|
return <CustomNavigate to="/all" replace />;
|
||||||
}
|
}
|
||||||
|
|
||||||
return children;
|
return children;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
// src/constants/constants.ts
|
// src/constants/constants.ts
|
||||||
|
|
||||||
|
import custom from "../customization/config-constants";
|
||||||
import { languageMap } from "../types/components";
|
import { languageMap } from "../types/components";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -567,9 +568,7 @@ export const ADMIN_HEADER_TITLE = "Admin Page";
|
||||||
export const ADMIN_HEADER_DESCRIPTION =
|
export const ADMIN_HEADER_DESCRIPTION =
|
||||||
"Navigate through this section to efficiently oversee all application users. From here, you can seamlessly manage user accounts.";
|
"Navigate through this section to efficiently oversee all application users. From here, you can seamlessly manage user accounts.";
|
||||||
|
|
||||||
export const BASE_URL_API = "/api/v1/";
|
export const BASE_URL_API = custom.BASE_URL_API || "/api/v1/";
|
||||||
|
|
||||||
export const BACKEND_URL = process.env.BACKEND_URL || "http://localhost:7860/";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* URLs excluded from error retries.
|
* URLs excluded from error retries.
|
||||||
|
|
@ -580,7 +579,7 @@ export const URL_EXCLUDED_FROM_ERROR_RETRIES = [
|
||||||
`${BASE_URL_API}validate/code`,
|
`${BASE_URL_API}validate/code`,
|
||||||
`${BASE_URL_API}custom_component`,
|
`${BASE_URL_API}custom_component`,
|
||||||
`${BASE_URL_API}validate/prompt`,
|
`${BASE_URL_API}validate/prompt`,
|
||||||
`http://localhost:7860/login`,
|
`${BASE_URL_API}/login`,
|
||||||
`${BASE_URL_API}api_key/store`,
|
`${BASE_URL_API}api_key/store`,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
import { CustomWrapper } from "@/customization/custom-wrapper";
|
||||||
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
||||||
import { ReactNode } from "react";
|
import { ReactNode } from "react";
|
||||||
import { ReactFlowProvider } from "reactflow";
|
import { ReactFlowProvider } from "reactflow";
|
||||||
|
|
@ -10,16 +11,18 @@ export default function ContextWrapper({ children }: { children: ReactNode }) {
|
||||||
//element to wrap all context
|
//element to wrap all context
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<QueryClientProvider client={queryClient}>
|
<CustomWrapper>
|
||||||
<AuthProvider>
|
<QueryClientProvider client={queryClient}>
|
||||||
<TooltipProvider skipDelayDuration={0}>
|
<AuthProvider>
|
||||||
<ReactFlowProvider>
|
<TooltipProvider skipDelayDuration={0}>
|
||||||
<ApiInterceptor />
|
<ReactFlowProvider>
|
||||||
{children}
|
<ApiInterceptor />
|
||||||
</ReactFlowProvider>
|
{children}
|
||||||
</TooltipProvider>
|
</ReactFlowProvider>
|
||||||
</AuthProvider>
|
</TooltipProvider>
|
||||||
</QueryClientProvider>
|
</AuthProvider>
|
||||||
|
</QueryClientProvider>
|
||||||
|
</CustomWrapper>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
import { LANGFLOW_ACCESS_TOKEN } from "@/constants/constants";
|
import { LANGFLOW_ACCESS_TOKEN } from "@/constants/constants";
|
||||||
|
import { useCustomApiHeaders } from "@/customization/hooks/use-custom-api-headers";
|
||||||
import useAuthStore from "@/stores/authStore";
|
import useAuthStore from "@/stores/authStore";
|
||||||
import axios, { AxiosError, AxiosInstance, AxiosRequestConfig } from "axios";
|
import axios, { AxiosError, AxiosInstance, AxiosRequestConfig } from "axios";
|
||||||
import { useContext, useEffect } from "react";
|
import { useContext, useEffect } from "react";
|
||||||
|
|
@ -22,8 +23,8 @@ function ApiInterceptor() {
|
||||||
let { accessToken, authenticationErrorCount } = useContext(AuthContext);
|
let { accessToken, authenticationErrorCount } = useContext(AuthContext);
|
||||||
const { mutate: mutationLogout } = useLogout();
|
const { mutate: mutationLogout } = useLogout();
|
||||||
const { mutate: mutationRenewAccessToken } = useRefreshAccessToken();
|
const { mutate: mutationRenewAccessToken } = useRefreshAccessToken();
|
||||||
const logout = useAuthStore((state) => state.logout);
|
|
||||||
const isLoginPage = location.pathname.includes("login");
|
const isLoginPage = location.pathname.includes("login");
|
||||||
|
const customHeaders = useCustomApiHeaders();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const interceptor = api.interceptors.response.use(
|
const interceptor = api.interceptors.response.use(
|
||||||
|
|
@ -102,6 +103,10 @@ function ApiInterceptor() {
|
||||||
config.headers["Authorization"] = `Bearer ${accessToken}`;
|
config.headers["Authorization"] = `Bearer ${accessToken}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (const [key, value] of Object.entries(customHeaders)) {
|
||||||
|
config.headers[key] = value;
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...config,
|
...config,
|
||||||
signal: controller.signal,
|
signal: controller.signal,
|
||||||
|
|
@ -117,7 +122,7 @@ function ApiInterceptor() {
|
||||||
api.interceptors.response.eject(interceptor);
|
api.interceptors.response.eject(interceptor);
|
||||||
api.interceptors.request.eject(requestInterceptor);
|
api.interceptors.request.eject(requestInterceptor);
|
||||||
};
|
};
|
||||||
}, [accessToken, setErrorData]);
|
}, [accessToken, setErrorData, customHeaders]);
|
||||||
|
|
||||||
function checkErrorCount() {
|
function checkErrorCount() {
|
||||||
if (isLoginPage) return;
|
if (isLoginPage) return;
|
||||||
|
|
@ -126,14 +131,7 @@ function ApiInterceptor() {
|
||||||
|
|
||||||
if (authenticationErrorCount > 3) {
|
if (authenticationErrorCount > 3) {
|
||||||
authenticationErrorCount = 0;
|
authenticationErrorCount = 0;
|
||||||
mutationLogout(undefined, {
|
mutationLogout();
|
||||||
onSuccess: () => {
|
|
||||||
logout();
|
|
||||||
},
|
|
||||||
onError: (error) => {
|
|
||||||
console.error(error);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -142,6 +140,11 @@ function ApiInterceptor() {
|
||||||
|
|
||||||
async function tryToRenewAccessToken(error: AxiosError) {
|
async function tryToRenewAccessToken(error: AxiosError) {
|
||||||
if (isLoginPage) return;
|
if (isLoginPage) return;
|
||||||
|
if (error.config?.headers) {
|
||||||
|
for (const [key, value] of Object.entries(customHeaders)) {
|
||||||
|
error.config.headers[key] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
mutationRenewAccessToken(
|
mutationRenewAccessToken(
|
||||||
{},
|
{},
|
||||||
{
|
{
|
||||||
|
|
@ -152,14 +155,7 @@ function ApiInterceptor() {
|
||||||
},
|
},
|
||||||
onError: (error) => {
|
onError: (error) => {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
mutationLogout(undefined, {
|
mutationLogout();
|
||||||
onSuccess: () => {
|
|
||||||
logout();
|
|
||||||
},
|
|
||||||
onError: (error) => {
|
|
||||||
console.error(error);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
return Promise.reject("Authentication error");
|
return Promise.reject("Authentication error");
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -8,9 +8,10 @@ interface IDeleteApiKey {
|
||||||
}
|
}
|
||||||
|
|
||||||
// add types for error handling and success
|
// add types for error handling and success
|
||||||
export const useDeleteApiKey: useMutationFunctionType<IDeleteApiKey> = (
|
export const useDeleteApiKey: useMutationFunctionType<
|
||||||
options,
|
undefined,
|
||||||
) => {
|
IDeleteApiKey
|
||||||
|
> = (options) => {
|
||||||
const { mutate } = UseRequestProcessor();
|
const { mutate } = UseRequestProcessor();
|
||||||
|
|
||||||
const deleteApiKeyFn = async (payload: IDeleteApiKey): Promise<any> => {
|
const deleteApiKeyFn = async (payload: IDeleteApiKey): Promise<any> => {
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import { useQueryFunctionType, Users } from "../../../../types/api";
|
||||||
import { api } from "../../api";
|
import { api } from "../../api";
|
||||||
import { getURL } from "../../helpers/constants";
|
import { getURL } from "../../helpers/constants";
|
||||||
import { UseRequestProcessor } from "../../services/request-processor";
|
import { UseRequestProcessor } from "../../services/request-processor";
|
||||||
|
import { useLogout } from "./use-post-logout";
|
||||||
|
|
||||||
export interface AutoLoginResponse {
|
export interface AutoLoginResponse {
|
||||||
frontend_timeout: number;
|
frontend_timeout: number;
|
||||||
|
|
@ -21,8 +22,8 @@ export const useGetAutoLogin: useQueryFunctionType<undefined, undefined> = (
|
||||||
const { login, setUserData, getUser } = useContext(AuthContext);
|
const { login, setUserData, getUser } = useContext(AuthContext);
|
||||||
const setAutoLogin = useAuthStore((state) => state.setAutoLogin);
|
const setAutoLogin = useAuthStore((state) => state.setAutoLogin);
|
||||||
const isAuthenticated = useAuthStore((state) => state.isAuthenticated);
|
const isAuthenticated = useAuthStore((state) => state.isAuthenticated);
|
||||||
const logout = useAuthStore((state) => state.logout);
|
|
||||||
const isLoginPage = location.pathname.includes("login");
|
const isLoginPage = location.pathname.includes("login");
|
||||||
|
const { mutate: mutationLogout } = useLogout();
|
||||||
|
|
||||||
async function getAutoLoginFn(): Promise<null> {
|
async function getAutoLoginFn(): Promise<null> {
|
||||||
try {
|
try {
|
||||||
|
|
@ -40,7 +41,7 @@ export const useGetAutoLogin: useQueryFunctionType<undefined, undefined> = (
|
||||||
setAutoLogin(false);
|
setAutoLogin(false);
|
||||||
if (!isLoginPage) {
|
if (!isLoginPage) {
|
||||||
if (!isAuthenticated) {
|
if (!isAuthenticated) {
|
||||||
await logout();
|
mutationLogout();
|
||||||
throw new Error("Unauthorized");
|
throw new Error("Unauthorized");
|
||||||
} else {
|
} else {
|
||||||
getUser();
|
getUser();
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import useAuthStore from "@/stores/authStore";
|
import useAuthStore from "@/stores/authStore";
|
||||||
import { useMutationFunctionType } from "@/types/api";
|
import { useMutationFunctionType } from "@/types/api";
|
||||||
|
|
||||||
|
import { useCustomNavigate } from "@/customization/hooks/use-custom-navigate";
|
||||||
import { api } from "../../api";
|
import { api } from "../../api";
|
||||||
import { getURL } from "../../helpers/constants";
|
import { getURL } from "../../helpers/constants";
|
||||||
import { UseRequestProcessor } from "../../services/request-processor";
|
import { UseRequestProcessor } from "../../services/request-processor";
|
||||||
|
|
@ -9,6 +10,7 @@ export const useLogout: useMutationFunctionType<undefined, void> = (
|
||||||
options?,
|
options?,
|
||||||
) => {
|
) => {
|
||||||
const { mutate } = UseRequestProcessor();
|
const { mutate } = UseRequestProcessor();
|
||||||
|
const navigate = useCustomNavigate();
|
||||||
const logout = useAuthStore((state) => state.logout);
|
const logout = useAuthStore((state) => state.logout);
|
||||||
|
|
||||||
async function logoutUser(): Promise<any> {
|
async function logoutUser(): Promise<any> {
|
||||||
|
|
@ -23,6 +25,7 @@ export const useLogout: useMutationFunctionType<undefined, void> = (
|
||||||
const mutation = mutate(["useLogout"], logoutUser, {
|
const mutation = mutate(["useLogout"], logoutUser, {
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
logout();
|
logout();
|
||||||
|
navigate("/login");
|
||||||
},
|
},
|
||||||
onError: (error) => {
|
onError: (error) => {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ export interface ConfigResponse {
|
||||||
health_check_max_retries: number;
|
health_check_max_retries: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useGetConfig: useQueryFunctionType<undefined, undefined> = (
|
export const useGetConfig: useQueryFunctionType<undefined, ConfigResponse> = (
|
||||||
options,
|
options,
|
||||||
) => {
|
) => {
|
||||||
const setAutoSaving = useFlowsManagerStore((state) => state.setAutoSaving);
|
const setAutoSaving = useFlowsManagerStore((state) => state.setAutoSaving);
|
||||||
|
|
@ -38,6 +38,7 @@ export const useGetConfig: useQueryFunctionType<undefined, undefined> = (
|
||||||
setAutoSavingInterval(data.auto_saving_interval);
|
setAutoSavingInterval(data.auto_saving_interval);
|
||||||
setHealthCheckMaxRetries(data.health_check_max_retries);
|
setHealthCheckMaxRetries(data.health_check_max_retries);
|
||||||
}
|
}
|
||||||
|
return data;
|
||||||
};
|
};
|
||||||
|
|
||||||
const queryResult = query(["useGetConfig"], getConfigFn, options);
|
const queryResult = query(["useGetConfig"], getConfigFn, options);
|
||||||
|
|
|
||||||
|
|
@ -1,32 +0,0 @@
|
||||||
import axios from "axios";
|
|
||||||
import { BASE_URL_API } from "../../constants/constants";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fetches the configuration data from the API.
|
|
||||||
* @returns {Promise<any>} A promise that resolves to the configuration data.
|
|
||||||
* @throws {Error} If there was an error fetching the configuration data.
|
|
||||||
*/
|
|
||||||
export async function fetchConfig() {
|
|
||||||
try {
|
|
||||||
const response = await axios.get(`${BASE_URL_API}config`);
|
|
||||||
return response.data;
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Failed to fetch configuration:", error);
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets up default configurations for Axios.
|
|
||||||
* Fetches the timeout configuration and sets it as the default timeout for Axios requests.
|
|
||||||
*/
|
|
||||||
export async function setupAxiosDefaults() {
|
|
||||||
const config = await fetchConfig();
|
|
||||||
// Create Axios instance with the fetched timeout configuration
|
|
||||||
|
|
||||||
const timeoutInMilliseconds = config.frontend_timeout
|
|
||||||
? config.frontend_timeout * 1000
|
|
||||||
: 30000;
|
|
||||||
axios.defaults.baseURL = "";
|
|
||||||
axios.defaults.timeout = timeoutInMilliseconds;
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
export function CustomHeader() {
|
||||||
|
return <></>;
|
||||||
|
}
|
||||||
11
src/frontend/src/customization/components/custom-link.tsx
Normal file
11
src/frontend/src/customization/components/custom-link.tsx
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
import { Link, LinkProps, useParams } from "react-router-dom";
|
||||||
|
import { ENABLE_CUSTOM_PARAM } from "../feature-flags";
|
||||||
|
|
||||||
|
export function CustomLink({ to, ...props }: LinkProps) {
|
||||||
|
const { customParam } = useParams();
|
||||||
|
|
||||||
|
const newLocation =
|
||||||
|
ENABLE_CUSTOM_PARAM && to[0] === "/" ? `/${customParam}${to}` : to;
|
||||||
|
|
||||||
|
return <Link to={newLocation} {...props} />;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
import { Navigate, NavigateProps, useParams } from "react-router-dom";
|
||||||
|
import { ENABLE_CUSTOM_PARAM } from "../feature-flags";
|
||||||
|
|
||||||
|
export function CustomNavigate({ to, ...props }: NavigateProps) {
|
||||||
|
const { customParam } = useParams();
|
||||||
|
const newLocation =
|
||||||
|
ENABLE_CUSTOM_PARAM && to[0] === "/" ? `/${customParam}${to}` : to;
|
||||||
|
|
||||||
|
return <Navigate to={newLocation} {...props} />;
|
||||||
|
}
|
||||||
13
src/frontend/src/customization/config-constants.ts
Normal file
13
src/frontend/src/customization/config-constants.ts
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
export const BASENAME = "";
|
||||||
|
export const PORT = 3000;
|
||||||
|
export const PROXY_TARGET = "http://127.0.0.1:7860";
|
||||||
|
export const API_ROUTES = ["^/api/v1/", "/health"];
|
||||||
|
export const BASE_URL_API = "/api/v1/";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
BASENAME,
|
||||||
|
PORT,
|
||||||
|
PROXY_TARGET,
|
||||||
|
API_ROUTES,
|
||||||
|
BASE_URL_API,
|
||||||
|
};
|
||||||
3
src/frontend/src/customization/custom-wrapper.tsx
Normal file
3
src/frontend/src/customization/custom-wrapper.tsx
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
export function CustomWrapper({ children }) {
|
||||||
|
return children;
|
||||||
|
}
|
||||||
8
src/frontend/src/customization/feature-flags.ts
Normal file
8
src/frontend/src/customization/feature-flags.ts
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
export const ENABLE_DARK_MODE = true;
|
||||||
|
export const ENABLE_API = true;
|
||||||
|
export const ENABLE_LANGFLOW_STORE = true;
|
||||||
|
export const ENABLE_PROFILE_ICONS = true;
|
||||||
|
export const ENABLE_SOCIAL_LINKS = true;
|
||||||
|
export const ENABLE_BRANDING = true;
|
||||||
|
export const ENABLE_MVPS = false;
|
||||||
|
export const ENABLE_CUSTOM_PARAM = false;
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
export function useCustomApiHeaders() {
|
||||||
|
const customHeaders = {};
|
||||||
|
|
||||||
|
return customHeaders;
|
||||||
|
}
|
||||||
27
src/frontend/src/customization/hooks/use-custom-navigate.ts
Normal file
27
src/frontend/src/customization/hooks/use-custom-navigate.ts
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
import {
|
||||||
|
NavigateFunction,
|
||||||
|
NavigateOptions,
|
||||||
|
To,
|
||||||
|
useNavigate,
|
||||||
|
useParams,
|
||||||
|
} from "react-router-dom";
|
||||||
|
import { ENABLE_CUSTOM_PARAM } from "../feature-flags";
|
||||||
|
|
||||||
|
export function useCustomNavigate(): NavigateFunction {
|
||||||
|
const domNavigate = useNavigate();
|
||||||
|
|
||||||
|
const { customParam } = useParams();
|
||||||
|
|
||||||
|
function navigate(to: To | number, options?: NavigateOptions) {
|
||||||
|
if (typeof to === "number") {
|
||||||
|
domNavigate(to);
|
||||||
|
} else {
|
||||||
|
domNavigate(
|
||||||
|
ENABLE_CUSTOM_PARAM && to[0] === "/" ? `/${customParam}${to}` : to,
|
||||||
|
options,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return navigate;
|
||||||
|
}
|
||||||
20
src/frontend/src/customization/hooks/use-primary-loading.ts
Normal file
20
src/frontend/src/customization/hooks/use-primary-loading.ts
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
import { UseRequestProcessor } from "@/controllers/API/services/request-processor";
|
||||||
|
import { useQueryFunctionType } from "@/types/api";
|
||||||
|
|
||||||
|
export const usePrimaryLoading: useQueryFunctionType<undefined, null> = (
|
||||||
|
options,
|
||||||
|
) => {
|
||||||
|
const { query } = UseRequestProcessor();
|
||||||
|
|
||||||
|
const getPrimaryLoadingFn = async () => {
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
const queryResult = query(
|
||||||
|
["usePrimaryLoading"],
|
||||||
|
getPrimaryLoadingFn,
|
||||||
|
options,
|
||||||
|
);
|
||||||
|
|
||||||
|
return queryResult;
|
||||||
|
};
|
||||||
|
|
@ -1,8 +1,7 @@
|
||||||
import { useGetDownloadFileMutation } from "@/controllers/API/queries/files";
|
import { useGetDownloadFileMutation } from "@/controllers/API/queries/files";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { ForwardedIconComponent } from "../../../../../components/genericIconComponent";
|
import { ForwardedIconComponent } from "../../../../../components/genericIconComponent";
|
||||||
import { BACKEND_URL, BASE_URL_API } from "../../../../../constants/constants";
|
import { BASE_URL_API } from "../../../../../constants/constants";
|
||||||
import useFlowsManagerStore from "../../../../../stores/flowsManagerStore";
|
|
||||||
import { fileCardPropsType } from "../../../../../types/components";
|
import { fileCardPropsType } from "../../../../../types/components";
|
||||||
import formatFileName from "../filePreviewChat/utils/format-file-name";
|
import formatFileName from "../filePreviewChat/utils/format-file-name";
|
||||||
import DownloadButton from "./components/downloadButton/downloadButton";
|
import DownloadButton from "./components/downloadButton/downloadButton";
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
|
import { useCustomNavigate } from "@/customization/hooks/use-custom-navigate";
|
||||||
import useAddFlow from "@/hooks/flows/use-add-flow";
|
import useAddFlow from "@/hooks/flows/use-add-flow";
|
||||||
import { useNavigate, useParams } from "react-router-dom";
|
import { useParams } from "react-router-dom";
|
||||||
import {
|
import {
|
||||||
Card,
|
Card,
|
||||||
CardContent,
|
CardContent,
|
||||||
|
|
@ -9,7 +10,7 @@ import {
|
||||||
|
|
||||||
export default function NewFlowCardComponent() {
|
export default function NewFlowCardComponent() {
|
||||||
const addFlow = useAddFlow();
|
const addFlow = useAddFlow();
|
||||||
const navigate = useNavigate();
|
const navigate = useCustomNavigate();
|
||||||
const { folderId } = useParams();
|
const { folderId } = useParams();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/// <reference types="vite-plugin-svgr/client" />
|
/// <reference types="vite-plugin-svgr/client" />
|
||||||
import { useNavigate, useParams } from "react-router-dom";
|
import { useParams } from "react-router-dom";
|
||||||
import BlogPost from "../../../../assets/undraw_blog_post_re_fy5x.svg?react";
|
import BlogPost from "../../../../assets/undraw_blog_post_re_fy5x.svg?react";
|
||||||
import ChatBot from "../../../../assets/undraw_chat_bot_re_e2gj.svg?react";
|
import ChatBot from "../../../../assets/undraw_chat_bot_re_e2gj.svg?react";
|
||||||
import PromptChaining from "../../../../assets/undraw_cloud_docs_re_xjht.svg?react";
|
import PromptChaining from "../../../../assets/undraw_cloud_docs_re_xjht.svg?react";
|
||||||
|
|
@ -10,6 +10,7 @@ import APIRequest from "../../../../assets/undraw_real_time_analytics_re_yliv.sv
|
||||||
import BasicPrompt from "../../../../assets/undraw_short_bio_re_fmx0.svg?react";
|
import BasicPrompt from "../../../../assets/undraw_short_bio_re_fmx0.svg?react";
|
||||||
import TransferFiles from "../../../../assets/undraw_transfer_files_re_a2a9.svg?react";
|
import TransferFiles from "../../../../assets/undraw_transfer_files_re_a2a9.svg?react";
|
||||||
|
|
||||||
|
import { useCustomNavigate } from "@/customization/hooks/use-custom-navigate";
|
||||||
import useAddFlow from "@/hooks/flows/use-add-flow";
|
import useAddFlow from "@/hooks/flows/use-add-flow";
|
||||||
import {
|
import {
|
||||||
Card,
|
Card,
|
||||||
|
|
@ -25,7 +26,7 @@ export default function UndrawCardComponent({
|
||||||
flow,
|
flow,
|
||||||
}: UndrawCardComponentProps): JSX.Element {
|
}: UndrawCardComponentProps): JSX.Element {
|
||||||
const addFlow = useAddFlow();
|
const addFlow = useAddFlow();
|
||||||
const navigate = useNavigate();
|
const navigate = useCustomNavigate();
|
||||||
const { folderId } = useParams();
|
const { folderId } = useParams();
|
||||||
const myCollectionId = useFolderStore((state) => state.myCollectionId);
|
const myCollectionId = useFolderStore((state) => state.myCollectionId);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import { useGetAutoLogin } from "@/controllers/API/queries/auth";
|
import { useGetAutoLogin } from "@/controllers/API/queries/auth";
|
||||||
import { useGetConfig } from "@/controllers/API/queries/config/use-get-config";
|
import { useGetConfig } from "@/controllers/API/queries/config/use-get-config";
|
||||||
import { useGetVersionQuery } from "@/controllers/API/queries/version";
|
import { useGetVersionQuery } from "@/controllers/API/queries/version";
|
||||||
|
import { usePrimaryLoading } from "@/customization/hooks/use-primary-loading";
|
||||||
import { useDarkStore } from "@/stores/darkStore";
|
import { useDarkStore } from "@/stores/darkStore";
|
||||||
import useFlowsManagerStore from "@/stores/flowsManagerStore";
|
import useFlowsManagerStore from "@/stores/flowsManagerStore";
|
||||||
import { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
|
|
@ -12,7 +13,8 @@ export function AppInitPage() {
|
||||||
const refreshStars = useDarkStore((state) => state.refreshStars);
|
const refreshStars = useDarkStore((state) => state.refreshStars);
|
||||||
const isLoading = useFlowsManagerStore((state) => state.isLoading);
|
const isLoading = useFlowsManagerStore((state) => state.isLoading);
|
||||||
|
|
||||||
const { isFetched } = useGetAutoLogin();
|
const { isFetched: isLoaded } = usePrimaryLoading();
|
||||||
|
const { isFetched } = useGetAutoLogin({ enabled: isLoaded });
|
||||||
useGetVersionQuery({ enabled: isFetched });
|
useGetVersionQuery({ enabled: isFetched });
|
||||||
useGetConfig({ enabled: isFetched });
|
useGetConfig({ enabled: isFetched });
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ import {
|
||||||
TIMEOUT_ERROR_MESSAGE,
|
TIMEOUT_ERROR_MESSAGE,
|
||||||
} from "@/constants/constants";
|
} from "@/constants/constants";
|
||||||
import { useGetHealthQuery } from "@/controllers/API/queries/health";
|
import { useGetHealthQuery } from "@/controllers/API/queries/health";
|
||||||
|
import { CustomHeader } from "@/customization/components/custom-header";
|
||||||
import useFlowsManagerStore from "@/stores/flowsManagerStore";
|
import useFlowsManagerStore from "@/stores/flowsManagerStore";
|
||||||
import { useUtilityStore } from "@/stores/utilityStore";
|
import { useUtilityStore } from "@/stores/utilityStore";
|
||||||
import { AxiosError } from "axios";
|
import { AxiosError } from "axios";
|
||||||
|
|
@ -96,6 +97,7 @@ export function AppWrapperPage() {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex h-full flex-col">
|
<div className="flex h-full flex-col">
|
||||||
|
<CustomHeader />
|
||||||
<ErrorBoundary
|
<ErrorBoundary
|
||||||
onReset={() => {
|
onReset={() => {
|
||||||
// any reset function
|
// any reset function
|
||||||
|
|
@ -107,7 +109,6 @@ export function AppWrapperPage() {
|
||||||
<Outlet />
|
<Outlet />
|
||||||
</>
|
</>
|
||||||
</ErrorBoundary>
|
</ErrorBoundary>
|
||||||
<div></div>
|
|
||||||
<div className="app-div">
|
<div className="app-div">
|
||||||
<AlertDisplayArea />
|
<AlertDisplayArea />
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import FeatureFlags from "@/../feature-config.json";
|
import { ENABLE_MVPS } from "@/customization/feature-flags";
|
||||||
import { useStoreStore } from "@/stores/storeStore";
|
import { useStoreStore } from "@/stores/storeStore";
|
||||||
import { cloneDeep } from "lodash";
|
import { cloneDeep } from "lodash";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
|
|
@ -193,10 +193,10 @@ export default function ExtraSidebar(): JSX.Element {
|
||||||
// Set search input state
|
// Set search input state
|
||||||
setSearch(event.target.value);
|
setSearch(event.target.value);
|
||||||
}}
|
}}
|
||||||
autocomplete="off"
|
autoComplete="off"
|
||||||
readonly="readonly"
|
readOnly
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
document.getElementById("search").removeAttribute("readonly")
|
document?.getElementById("search")?.removeAttribute("readonly")
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
<div
|
<div
|
||||||
|
|
@ -298,7 +298,7 @@ export default function ExtraSidebar(): JSX.Element {
|
||||||
</a>
|
</a>
|
||||||
)}
|
)}
|
||||||
</ParentDisclosureComponent>
|
</ParentDisclosureComponent>
|
||||||
{FeatureFlags.ENABLE_MVPS && (
|
{ENABLE_MVPS && (
|
||||||
<>
|
<>
|
||||||
<Separator />
|
<Separator />
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,13 @@
|
||||||
import FeatureFlags from "@/../feature-config.json";
|
|
||||||
import { useGetRefreshFlows } from "@/controllers/API/queries/flows/use-get-refresh-flows";
|
import { useGetRefreshFlows } from "@/controllers/API/queries/flows/use-get-refresh-flows";
|
||||||
import { useGetGlobalVariables } from "@/controllers/API/queries/variables";
|
import { useGetGlobalVariables } from "@/controllers/API/queries/variables";
|
||||||
|
import { ENABLE_BRANDING } from "@/customization/feature-flags";
|
||||||
|
import { useCustomNavigate } from "@/customization/hooks/use-custom-navigate";
|
||||||
import useSaveFlow from "@/hooks/flows/use-save-flow";
|
import useSaveFlow from "@/hooks/flows/use-save-flow";
|
||||||
import { SaveChangesModal } from "@/modals/saveChangesModal";
|
import { SaveChangesModal } from "@/modals/saveChangesModal";
|
||||||
import { useTypesStore } from "@/stores/typesStore";
|
import { useTypesStore } from "@/stores/typesStore";
|
||||||
import { customStringify } from "@/utils/reactflowUtils";
|
import { customStringify } from "@/utils/reactflowUtils";
|
||||||
import { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
import { useBlocker, useNavigate, useParams } from "react-router-dom";
|
import { useBlocker, useParams } from "react-router-dom";
|
||||||
import FlowToolbar from "../../components/chatComponent";
|
import FlowToolbar from "../../components/chatComponent";
|
||||||
import { useDarkStore } from "../../stores/darkStore";
|
import { useDarkStore } from "../../stores/darkStore";
|
||||||
import useFlowStore from "../../stores/flowStore";
|
import useFlowStore from "../../stores/flowStore";
|
||||||
|
|
@ -27,7 +28,7 @@ export default function FlowPage({ view }: { view?: boolean }): JSX.Element {
|
||||||
const version = useDarkStore((state) => state.version);
|
const version = useDarkStore((state) => state.version);
|
||||||
const setOnFlowPage = useFlowStore((state) => state.setOnFlowPage);
|
const setOnFlowPage = useFlowStore((state) => state.setOnFlowPage);
|
||||||
const { id } = useParams();
|
const { id } = useParams();
|
||||||
const navigate = useNavigate();
|
const navigate = useCustomNavigate();
|
||||||
useGetGlobalVariables();
|
useGetGlobalVariables();
|
||||||
const saveFlow = useSaveFlow();
|
const saveFlow = useSaveFlow();
|
||||||
|
|
||||||
|
|
@ -106,7 +107,7 @@ export default function FlowPage({ view }: { view?: boolean }): JSX.Element {
|
||||||
</main>
|
</main>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{FeatureFlags.ENABLE_BRANDING && version && (
|
{ENABLE_BRANDING && version && (
|
||||||
<a
|
<a
|
||||||
target={"_blank"}
|
target={"_blank"}
|
||||||
href="https://medium.com/logspace/langflow-datastax-better-together-1b7462cebc4d"
|
href="https://medium.com/logspace/langflow-datastax-better-together-1b7462cebc4d"
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { useLoginUser } from "@/controllers/API/queries/auth";
|
import { useLoginUser } from "@/controllers/API/queries/auth";
|
||||||
|
import { CustomLink } from "@/customization/components/custom-link";
|
||||||
import * as Form from "@radix-ui/react-form";
|
import * as Form from "@radix-ui/react-form";
|
||||||
import { useContext, useState } from "react";
|
import { useContext, useState } from "react";
|
||||||
import { Link } from "react-router-dom";
|
|
||||||
import InputComponent from "../../components/inputComponent";
|
import InputComponent from "../../components/inputComponent";
|
||||||
import { Button } from "../../components/ui/button";
|
import { Button } from "../../components/ui/button";
|
||||||
import { Input } from "../../components/ui/input";
|
import { Input } from "../../components/ui/input";
|
||||||
|
|
@ -124,11 +124,11 @@ export default function LoginPage(): JSX.Element {
|
||||||
</Form.Submit>
|
</Form.Submit>
|
||||||
</div>
|
</div>
|
||||||
<div className="w-full">
|
<div className="w-full">
|
||||||
<Link to="/signup">
|
<CustomLink to="/signup">
|
||||||
<Button className="w-full" variant="outline" type="button">
|
<Button className="w-full" variant="outline" type="button">
|
||||||
Don't have an account? <b>Sign Up</b>
|
Don't have an account? <b>Sign Up</b>
|
||||||
</Button>
|
</Button>
|
||||||
</Link>
|
</CustomLink>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,8 @@
|
||||||
import { Link, useNavigate, useParams } from "react-router-dom";
|
import { useCustomNavigate } from "@/customization/hooks/use-custom-navigate";
|
||||||
|
import { useParams } from "react-router-dom";
|
||||||
import CollectionCardComponent from "../../../../../../components/cardComponent";
|
import CollectionCardComponent from "../../../../../../components/cardComponent";
|
||||||
import IconComponent from "../../../../../../components/genericIconComponent";
|
|
||||||
import { Button } from "../../../../../../components/ui/button";
|
|
||||||
const CollectionCard = ({ item, type, isLoading, control }) => {
|
const CollectionCard = ({ item, type, isLoading, control }) => {
|
||||||
const navigate = useNavigate();
|
const navigate = useCustomNavigate();
|
||||||
const isComponent = item.is_component ?? false;
|
const isComponent = item.is_component ?? false;
|
||||||
const editFlowButtonTestId = `edit-flow-button-${item.id}`;
|
const editFlowButtonTestId = `edit-flow-button-${item.id}`;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
|
import { useCustomNavigate } from "@/customization/hooks/use-custom-navigate";
|
||||||
import { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
import { useNavigate } from "react-router-dom";
|
|
||||||
|
|
||||||
type TabsSearchComponentProps = {
|
type TabsSearchComponentProps = {
|
||||||
tabsOptions: string[];
|
tabsOptions: string[];
|
||||||
|
|
@ -14,23 +14,23 @@ const TabsSearchComponent = ({
|
||||||
loading,
|
loading,
|
||||||
tabActive,
|
tabActive,
|
||||||
}: TabsSearchComponentProps) => {
|
}: TabsSearchComponentProps) => {
|
||||||
const navigate = useNavigate();
|
const navigate = useCustomNavigate();
|
||||||
|
|
||||||
const changeLocation = (tabOption) => {
|
const changeLocation = (tabOption) => {
|
||||||
const location = window.location.pathname;
|
const location = window.location.pathname;
|
||||||
let newLocation = "";
|
let newLocation = "";
|
||||||
switch (tabOption) {
|
switch (tabOption) {
|
||||||
case "Flows":
|
case "Flows":
|
||||||
newLocation = location.replace(/components|all/, "flows");
|
newLocation = location.replace(/.*\/(?:all|components)/, "/flows");
|
||||||
break;
|
break;
|
||||||
case "Components":
|
case "Components":
|
||||||
newLocation = location.replace(/flows|all/, "components");
|
newLocation = location.replace(/.*\/(?:flows|all)/, "/components");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
newLocation = location.replace(/flows|components/, "all");
|
newLocation = location.replace(/.*\/(?:flows|components)/, "/all");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
console.log(newLocation);
|
||||||
navigate(newLocation);
|
navigate(newLocation);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,9 @@
|
||||||
import FolderSidebarNav from "@/components/folderSidebarComponent";
|
import FolderSidebarNav from "@/components/folderSidebarComponent";
|
||||||
import { useDeleteFolders } from "@/controllers/API/queries/folders";
|
import { useDeleteFolders } from "@/controllers/API/queries/folders";
|
||||||
|
import { useCustomNavigate } from "@/customization/hooks/use-custom-navigate";
|
||||||
import useAlertStore from "@/stores/alertStore";
|
import useAlertStore from "@/stores/alertStore";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { Outlet, useLocation, useNavigate } from "react-router-dom";
|
import { Outlet, useLocation } from "react-router-dom";
|
||||||
import DropdownButton from "../../../../components/dropdownButtonComponent";
|
import DropdownButton from "../../../../components/dropdownButtonComponent";
|
||||||
import PageLayout from "../../../../components/pageLayout";
|
import PageLayout from "../../../../components/pageLayout";
|
||||||
import {
|
import {
|
||||||
|
|
@ -18,9 +19,9 @@ export default function HomePage(): JSX.Element {
|
||||||
const pathname = location.pathname;
|
const pathname = location.pathname;
|
||||||
const [openModal, setOpenModal] = useState(false);
|
const [openModal, setOpenModal] = useState(false);
|
||||||
const [openDeleteFolderModal, setOpenDeleteFolderModal] = useState(false);
|
const [openDeleteFolderModal, setOpenDeleteFolderModal] = useState(false);
|
||||||
const is_component = pathname === "/components";
|
const is_component = pathname.includes("/components");
|
||||||
const setFolderToEdit = useFolderStore((state) => state.setFolderToEdit);
|
const setFolderToEdit = useFolderStore((state) => state.setFolderToEdit);
|
||||||
const navigate = useNavigate();
|
const navigate = useCustomNavigate();
|
||||||
|
|
||||||
const setSuccessData = useAlertStore((state) => state.setSuccessData);
|
const setSuccessData = useAlertStore((state) => state.setSuccessData);
|
||||||
const setErrorData = useAlertStore((state) => state.setErrorData);
|
const setErrorData = useAlertStore((state) => state.setErrorData);
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,10 @@
|
||||||
import { useGetRefreshFlows } from "@/controllers/API/queries/flows/use-get-refresh-flows";
|
import { useGetRefreshFlows } from "@/controllers/API/queries/flows/use-get-refresh-flows";
|
||||||
import { useGetGlobalVariables } from "@/controllers/API/queries/variables";
|
import { useGetGlobalVariables } from "@/controllers/API/queries/variables";
|
||||||
|
import { useCustomNavigate } from "@/customization/hooks/use-custom-navigate";
|
||||||
import { useStoreStore } from "@/stores/storeStore";
|
import { useStoreStore } from "@/stores/storeStore";
|
||||||
import { useTypesStore } from "@/stores/typesStore";
|
import { useTypesStore } from "@/stores/typesStore";
|
||||||
import { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
import { useNavigate, useParams } from "react-router-dom";
|
import { useParams } from "react-router-dom";
|
||||||
import { getComponent } from "../../controllers/API";
|
import { getComponent } from "../../controllers/API";
|
||||||
import IOModal from "../../modals/IOModal";
|
import IOModal from "../../modals/IOModal";
|
||||||
import useFlowsManagerStore from "../../stores/flowsManagerStore";
|
import useFlowsManagerStore from "../../stores/flowsManagerStore";
|
||||||
|
|
@ -22,7 +23,7 @@ export default function PlaygroundPage() {
|
||||||
return newFlow;
|
return newFlow;
|
||||||
}
|
}
|
||||||
|
|
||||||
const navigate = useNavigate();
|
const navigate = useCustomNavigate();
|
||||||
useGetGlobalVariables();
|
useGetGlobalVariables();
|
||||||
|
|
||||||
const currentFlowId = useFlowsManagerStore((state) => state.currentFlowId);
|
const currentFlowId = useFlowsManagerStore((state) => state.currentFlowId);
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import FeatureFlags from "@/../feature-config.json";
|
import { ENABLE_PROFILE_ICONS } from "@/customization/feature-flags";
|
||||||
import useAuthStore from "@/stores/authStore";
|
import useAuthStore from "@/stores/authStore";
|
||||||
import { useStoreStore } from "@/stores/storeStore";
|
import { useStoreStore } from "@/stores/storeStore";
|
||||||
import { Outlet } from "react-router-dom";
|
import { Outlet } from "react-router-dom";
|
||||||
|
|
@ -11,8 +11,7 @@ export default function SettingsPage(): JSX.Element {
|
||||||
const hasStore = useStoreStore((state) => state.hasStore);
|
const hasStore = useStoreStore((state) => state.hasStore);
|
||||||
|
|
||||||
// Hides the General settings if there is nothing to show
|
// Hides the General settings if there is nothing to show
|
||||||
const showGeneralSettings =
|
const showGeneralSettings = ENABLE_PROFILE_ICONS || hasStore || !autoLogin;
|
||||||
FeatureFlags.ENABLE_PROFILE_ICONS || hasStore || !autoLogin;
|
|
||||||
|
|
||||||
const sidebarNavItems: {
|
const sidebarNavItems: {
|
||||||
href?: string;
|
href?: string;
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
import FeatureFlags from "@/../feature-config.json";
|
|
||||||
import {
|
import {
|
||||||
EDIT_PASSWORD_ALERT_LIST,
|
EDIT_PASSWORD_ALERT_LIST,
|
||||||
EDIT_PASSWORD_ERROR_ALERT,
|
EDIT_PASSWORD_ERROR_ALERT,
|
||||||
|
|
@ -11,6 +10,7 @@ import {
|
||||||
useUpdateUser,
|
useUpdateUser,
|
||||||
} from "@/controllers/API/queries/auth";
|
} from "@/controllers/API/queries/auth";
|
||||||
import { useGetProfilePicturesQuery } from "@/controllers/API/queries/files";
|
import { useGetProfilePicturesQuery } from "@/controllers/API/queries/files";
|
||||||
|
import { ENABLE_PROFILE_ICONS } from "@/customization/feature-flags";
|
||||||
import useAuthStore from "@/stores/authStore";
|
import useAuthStore from "@/stores/authStore";
|
||||||
import { cloneDeep } from "lodash";
|
import { cloneDeep } from "lodash";
|
||||||
import { useContext, useState } from "react";
|
import { useContext, useState } from "react";
|
||||||
|
|
@ -146,7 +146,7 @@ export const GeneralPage = () => {
|
||||||
<GeneralPageHeaderComponent />
|
<GeneralPageHeaderComponent />
|
||||||
|
|
||||||
<div className="grid gap-6">
|
<div className="grid gap-6">
|
||||||
{FeatureFlags.ENABLE_PROFILE_ICONS && (
|
{ENABLE_PROFILE_ICONS && (
|
||||||
<ProfilePictureFormComponent
|
<ProfilePictureFormComponent
|
||||||
profilePicture={profilePicture}
|
profilePicture={profilePicture}
|
||||||
handleInput={handleInput}
|
handleInput={handleInput}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
import { useAddUser } from "@/controllers/API/queries/auth";
|
import { useAddUser } from "@/controllers/API/queries/auth";
|
||||||
|
import { CustomLink } from "@/customization/components/custom-link";
|
||||||
|
import { useCustomNavigate } from "@/customization/hooks/use-custom-navigate";
|
||||||
import * as Form from "@radix-ui/react-form";
|
import * as Form from "@radix-ui/react-form";
|
||||||
import { FormEvent, useEffect, useState } from "react";
|
import { FormEvent, useEffect, useState } from "react";
|
||||||
import { Link, useNavigate } from "react-router-dom";
|
|
||||||
import InputComponent from "../../components/inputComponent";
|
import InputComponent from "../../components/inputComponent";
|
||||||
import { Button } from "../../components/ui/button";
|
import { Button } from "../../components/ui/button";
|
||||||
import { Input } from "../../components/ui/input";
|
import { Input } from "../../components/ui/input";
|
||||||
|
|
@ -26,7 +27,7 @@ export default function SignUp(): JSX.Element {
|
||||||
const { password, cnfPassword, username } = inputState;
|
const { password, cnfPassword, username } = inputState;
|
||||||
const setSuccessData = useAlertStore((state) => state.setSuccessData);
|
const setSuccessData = useAlertStore((state) => state.setSuccessData);
|
||||||
const setErrorData = useAlertStore((state) => state.setErrorData);
|
const setErrorData = useAlertStore((state) => state.setErrorData);
|
||||||
const navigate = useNavigate();
|
const navigate = useCustomNavigate();
|
||||||
|
|
||||||
const { mutate: mutateAddUser } = useAddUser();
|
const { mutate: mutateAddUser } = useAddUser();
|
||||||
|
|
||||||
|
|
@ -184,11 +185,11 @@ export default function SignUp(): JSX.Element {
|
||||||
</Form.Submit>
|
</Form.Submit>
|
||||||
</div>
|
</div>
|
||||||
<div className="w-full">
|
<div className="w-full">
|
||||||
<Link to="/login">
|
<CustomLink to="/login">
|
||||||
<Button className="w-full" variant="outline">
|
<Button className="w-full" variant="outline">
|
||||||
Already have an account? <b>Sign in</b>
|
Already have an account? <b>Sign in</b>
|
||||||
</Button>
|
</Button>
|
||||||
</Link>
|
</CustomLink>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
import { uniqueId } from "lodash";
|
import { uniqueId } from "lodash";
|
||||||
import { useContext, useEffect, useState } from "react";
|
import { useContext, useEffect, useState } from "react";
|
||||||
import CollectionCardComponent from "../../components/cardComponent";
|
|
||||||
import IconComponent from "../../components/genericIconComponent";
|
import IconComponent from "../../components/genericIconComponent";
|
||||||
import PageLayout from "../../components/pageLayout";
|
import PageLayout from "../../components/pageLayout";
|
||||||
import ShadTooltip from "../../components/shadTooltipComponent";
|
import ShadTooltip from "../../components/shadTooltipComponent";
|
||||||
|
|
@ -9,7 +8,9 @@ import { Button } from "../../components/ui/button";
|
||||||
|
|
||||||
import StoreCardComponent from "@/components/storeCardComponent";
|
import StoreCardComponent from "@/components/storeCardComponent";
|
||||||
import { useGetTagsQuery } from "@/controllers/API/queries/store";
|
import { useGetTagsQuery } from "@/controllers/API/queries/store";
|
||||||
import { Link, useNavigate, useParams } from "react-router-dom";
|
import { CustomLink } from "@/customization/components/custom-link";
|
||||||
|
import { useCustomNavigate } from "@/customization/hooks/use-custom-navigate";
|
||||||
|
import { useParams } from "react-router-dom";
|
||||||
import PaginatorComponent from "../../components/paginatorComponent";
|
import PaginatorComponent from "../../components/paginatorComponent";
|
||||||
import { TagsSelector } from "../../components/tagsSelectorComponent";
|
import { TagsSelector } from "../../components/tagsSelectorComponent";
|
||||||
import { Badge } from "../../components/ui/badge";
|
import { Badge } from "../../components/ui/badge";
|
||||||
|
|
@ -62,7 +63,7 @@ export default function StorePage(): JSX.Element {
|
||||||
const [selectFilter, setSelectFilter] = useState("all");
|
const [selectFilter, setSelectFilter] = useState("all");
|
||||||
const { isFetching, data } = useGetTagsQuery();
|
const { isFetching, data } = useGetTagsQuery();
|
||||||
|
|
||||||
const navigate = useNavigate();
|
const navigate = useCustomNavigate();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!loadingApiKey) {
|
if (!loadingApiKey) {
|
||||||
|
|
@ -289,9 +290,9 @@ export default function StorePage(): JSX.Element {
|
||||||
size="sq"
|
size="sq"
|
||||||
className="gap-2 bg-beta-foreground text-background hover:bg-beta-foreground"
|
className="gap-2 bg-beta-foreground text-background hover:bg-beta-foreground"
|
||||||
>
|
>
|
||||||
<Link to={"/store"} className="cursor-pointer">
|
<CustomLink to={"/store"} className="cursor-pointer">
|
||||||
<IconComponent name="X" className="h-4 w-4" />
|
<IconComponent name="X" className="h-4 w-4" />
|
||||||
</Link>
|
</CustomLink>
|
||||||
{id}
|
{id}
|
||||||
</Badge>
|
</Badge>
|
||||||
)}
|
)}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,9 @@
|
||||||
import { useGetRefreshFlows } from "@/controllers/API/queries/flows/use-get-refresh-flows";
|
import { useGetRefreshFlows } from "@/controllers/API/queries/flows/use-get-refresh-flows";
|
||||||
import { useGetGlobalVariables } from "@/controllers/API/queries/variables";
|
import { useGetGlobalVariables } from "@/controllers/API/queries/variables";
|
||||||
|
import { useCustomNavigate } from "@/customization/hooks/use-custom-navigate";
|
||||||
import { useTypesStore } from "@/stores/typesStore";
|
import { useTypesStore } from "@/stores/typesStore";
|
||||||
import { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
import { useNavigate, useParams } from "react-router-dom";
|
import { useParams } from "react-router-dom";
|
||||||
import useFlowsManagerStore from "../../stores/flowsManagerStore";
|
import useFlowsManagerStore from "../../stores/flowsManagerStore";
|
||||||
import Page from "../FlowPage/components/PageComponent";
|
import Page from "../FlowPage/components/PageComponent";
|
||||||
|
|
||||||
|
|
@ -10,7 +11,7 @@ export default function ViewPage() {
|
||||||
const setCurrentFlow = useFlowsManagerStore((state) => state.setCurrentFlow);
|
const setCurrentFlow = useFlowsManagerStore((state) => state.setCurrentFlow);
|
||||||
|
|
||||||
const { id } = useParams();
|
const { id } = useParams();
|
||||||
const navigate = useNavigate();
|
const navigate = useCustomNavigate();
|
||||||
useGetGlobalVariables();
|
useGetGlobalVariables();
|
||||||
|
|
||||||
const flows = useFlowsManagerStore((state) => state.flows);
|
const flows = useFlowsManagerStore((state) => state.flows);
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,6 @@ import { lazy } from "react";
|
||||||
import {
|
import {
|
||||||
createBrowserRouter,
|
createBrowserRouter,
|
||||||
createRoutesFromElements,
|
createRoutesFromElements,
|
||||||
Navigate,
|
|
||||||
Outlet,
|
Outlet,
|
||||||
Route,
|
Route,
|
||||||
} from "react-router-dom";
|
} from "react-router-dom";
|
||||||
|
|
@ -12,6 +11,9 @@ import { ProtectedLoginRoute } from "./components/authLoginGuard";
|
||||||
import { AuthSettingsGuard } from "./components/authSettingsGuard";
|
import { AuthSettingsGuard } from "./components/authSettingsGuard";
|
||||||
import { StoreGuard } from "./components/storeGuard";
|
import { StoreGuard } from "./components/storeGuard";
|
||||||
import ContextWrapper from "./contexts";
|
import ContextWrapper from "./contexts";
|
||||||
|
import { CustomNavigate } from "./customization/components/custom-navigate";
|
||||||
|
import { BASENAME } from "./customization/config-constants";
|
||||||
|
import { ENABLE_CUSTOM_PARAM } from "./customization/feature-flags";
|
||||||
import { AppInitPage } from "./pages/AppInitPage";
|
import { AppInitPage } from "./pages/AppInitPage";
|
||||||
import { AppWrapperPage } from "./pages/AppWrapperPage";
|
import { AppWrapperPage } from "./pages/AppWrapperPage";
|
||||||
import { DashboardWrapperPage } from "./pages/DashboardWrapperPage";
|
import { DashboardWrapperPage } from "./pages/DashboardWrapperPage";
|
||||||
|
|
@ -38,7 +40,7 @@ const SignUp = lazy(() => import("./pages/SignUpPage"));
|
||||||
const router = createBrowserRouter(
|
const router = createBrowserRouter(
|
||||||
createRoutesFromElements([
|
createRoutesFromElements([
|
||||||
<Route
|
<Route
|
||||||
path="/"
|
path={ENABLE_CUSTOM_PARAM ? "/:customParam" : "/"}
|
||||||
element={
|
element={
|
||||||
<ContextWrapper>
|
<ContextWrapper>
|
||||||
<Outlet />
|
<Outlet />
|
||||||
|
|
@ -57,7 +59,7 @@ const router = createBrowserRouter(
|
||||||
>
|
>
|
||||||
<Route path="" element={<DashboardWrapperPage />}>
|
<Route path="" element={<DashboardWrapperPage />}>
|
||||||
<Route path="" element={<HomePage />}>
|
<Route path="" element={<HomePage />}>
|
||||||
<Route index element={<Navigate replace to={"all"} />} />
|
<Route index element={<CustomNavigate replace to={"all"} />} />
|
||||||
<Route
|
<Route
|
||||||
path="flows/"
|
path="flows/"
|
||||||
element={<MyCollectionComponent key="flows" type="flow" />}
|
element={<MyCollectionComponent key="flows" type="flow" />}
|
||||||
|
|
@ -93,8 +95,11 @@ const router = createBrowserRouter(
|
||||||
/>
|
/>
|
||||||
</Route>
|
</Route>
|
||||||
</Route>
|
</Route>
|
||||||
<Route path="/settings" element={<SettingsPage />}>
|
<Route path="settings" element={<SettingsPage />}>
|
||||||
<Route index element={<Navigate replace to={"general"} />} />
|
<Route
|
||||||
|
index
|
||||||
|
element={<CustomNavigate replace to={"general"} />}
|
||||||
|
/>
|
||||||
<Route
|
<Route
|
||||||
path="global-variables"
|
path="global-variables"
|
||||||
element={<GlobalVariablesPage />}
|
element={<GlobalVariablesPage />}
|
||||||
|
|
@ -112,7 +117,7 @@ const router = createBrowserRouter(
|
||||||
<Route path="messages" element={<MessagesPage />} />
|
<Route path="messages" element={<MessagesPage />} />
|
||||||
</Route>
|
</Route>
|
||||||
<Route
|
<Route
|
||||||
path="/store"
|
path="store"
|
||||||
element={
|
element={
|
||||||
<StoreGuard>
|
<StoreGuard>
|
||||||
<StorePage />
|
<StorePage />
|
||||||
|
|
@ -120,18 +125,18 @@ const router = createBrowserRouter(
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
<Route
|
<Route
|
||||||
path="/store/:id/"
|
path="store/:id/"
|
||||||
element={
|
element={
|
||||||
<StoreGuard>
|
<StoreGuard>
|
||||||
<StorePage />
|
<StorePage />
|
||||||
</StoreGuard>
|
</StoreGuard>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
<Route path="/account">
|
<Route path="account">
|
||||||
<Route path="delete" element={<DeleteAccountPage />}></Route>
|
<Route path="delete" element={<DeleteAccountPage />}></Route>
|
||||||
</Route>
|
</Route>
|
||||||
<Route
|
<Route
|
||||||
path="/admin"
|
path="admin"
|
||||||
element={
|
element={
|
||||||
<ProtectedAdminRoute>
|
<ProtectedAdminRoute>
|
||||||
<AdminPage />
|
<AdminPage />
|
||||||
|
|
@ -139,19 +144,19 @@ const router = createBrowserRouter(
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</Route>
|
</Route>
|
||||||
<Route path="/flow/:id/">
|
<Route path="flow/:id/">
|
||||||
<Route path="" element={<DashboardWrapperPage />}>
|
<Route path="" element={<DashboardWrapperPage />}>
|
||||||
<Route path="folder/:folderId/" element={<FlowPage />} />
|
<Route path="folder/:folderId/" element={<FlowPage />} />
|
||||||
<Route path="" element={<FlowPage />} />
|
<Route path="" element={<FlowPage />} />
|
||||||
</Route>
|
</Route>
|
||||||
<Route path="view" element={<ViewPage />} />
|
<Route path="view" element={<ViewPage />} />
|
||||||
</Route>
|
</Route>
|
||||||
<Route path="/playground/:id/">
|
<Route path="playground/:id/">
|
||||||
<Route path="" element={<PlaygroundPage />} />
|
<Route path="" element={<PlaygroundPage />} />
|
||||||
</Route>
|
</Route>
|
||||||
</Route>
|
</Route>
|
||||||
<Route
|
<Route
|
||||||
path="/login"
|
path="login"
|
||||||
element={
|
element={
|
||||||
<ProtectedLoginRoute>
|
<ProtectedLoginRoute>
|
||||||
<LoginPage />
|
<LoginPage />
|
||||||
|
|
@ -159,7 +164,7 @@ const router = createBrowserRouter(
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
<Route
|
<Route
|
||||||
path="/signup"
|
path="signup"
|
||||||
element={
|
element={
|
||||||
<ProtectedLoginRoute>
|
<ProtectedLoginRoute>
|
||||||
<SignUp />
|
<SignUp />
|
||||||
|
|
@ -167,18 +172,19 @@ const router = createBrowserRouter(
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
<Route
|
<Route
|
||||||
path="/login/admin"
|
path="login/admin"
|
||||||
element={
|
element={
|
||||||
<ProtectedLoginRoute>
|
<ProtectedLoginRoute>
|
||||||
<LoginAdminPage />
|
<LoginAdminPage />
|
||||||
</ProtectedLoginRoute>
|
</ProtectedLoginRoute>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
<Route path="*" element={<Navigate replace to="/" />} />
|
|
||||||
</Route>
|
</Route>
|
||||||
</Route>
|
</Route>
|
||||||
|
<Route path="*" element={<CustomNavigate replace to="/" />} />
|
||||||
</Route>,
|
</Route>,
|
||||||
]),
|
]),
|
||||||
|
{ basename: BASENAME || undefined },
|
||||||
);
|
);
|
||||||
|
|
||||||
export default router;
|
export default router;
|
||||||
|
|
|
||||||
|
|
@ -35,8 +35,6 @@ const useAuthStore = create<AuthStoreType>((set, get) => ({
|
||||||
autoLogin: false,
|
autoLogin: false,
|
||||||
apiKey: null,
|
apiKey: null,
|
||||||
});
|
});
|
||||||
|
|
||||||
window.location.href = "/login";
|
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,17 @@
|
||||||
import FeatureFlags from "@/../feature-config.json";
|
import { ENABLE_LANGFLOW_STORE } from "@/customization/feature-flags";
|
||||||
import { create } from "zustand";
|
import { create } from "zustand";
|
||||||
import { checkHasApiKey, checkHasStore } from "../controllers/API";
|
import { checkHasApiKey, checkHasStore } from "../controllers/API";
|
||||||
import { StoreStoreType } from "../types/zustand/store";
|
import { StoreStoreType } from "../types/zustand/store";
|
||||||
|
|
||||||
export const useStoreStore = create<StoreStoreType>((set) => ({
|
export const useStoreStore = create<StoreStoreType>((set) => ({
|
||||||
hasStore: true,
|
hasStore: ENABLE_LANGFLOW_STORE,
|
||||||
validApiKey: false,
|
validApiKey: false,
|
||||||
hasApiKey: false,
|
hasApiKey: false,
|
||||||
loadingApiKey: true,
|
loadingApiKey: true,
|
||||||
checkHasStore: () => {
|
checkHasStore: () => {
|
||||||
checkHasStore().then((res) => {
|
checkHasStore().then((res) => {
|
||||||
set({
|
set({
|
||||||
hasStore: FeatureFlags.ENABLE_LANGFLOW_STORE && (res?.enabled ?? false),
|
hasStore: ENABLE_LANGFLOW_STORE && (res?.enabled ?? false),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -58,6 +58,5 @@
|
||||||
"tests/scheduled-end-to-end/twoEdges.spec.ts",
|
"tests/scheduled-end-to-end/twoEdges.spec.ts",
|
||||||
"tests/scheduled-end-to-end/userSettings.spec.ts",
|
"tests/scheduled-end-to-end/userSettings.spec.ts",
|
||||||
"tests/end-to-end/store.spec.ts",
|
"tests/end-to-end/store.spec.ts",
|
||||||
"tests/end-to-end/logs.spec.ts"
|
"tests/end-to-end/logs.spec.ts" ]
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,17 +4,24 @@ import path from "path";
|
||||||
import { defineConfig } from "vite";
|
import { defineConfig } from "vite";
|
||||||
import svgr from "vite-plugin-svgr";
|
import svgr from "vite-plugin-svgr";
|
||||||
import tsconfigPaths from "vite-tsconfig-paths";
|
import tsconfigPaths from "vite-tsconfig-paths";
|
||||||
|
import {
|
||||||
|
API_ROUTES,
|
||||||
|
BASENAME,
|
||||||
|
PORT,
|
||||||
|
PROXY_TARGET,
|
||||||
|
} from "./src/customization/config-constants";
|
||||||
|
|
||||||
export default defineConfig(({ mode }) => {
|
export default defineConfig(({ mode }) => {
|
||||||
dotenv.config({ path: path.resolve(__dirname, "../../.env") });
|
dotenv.config({ path: path.resolve(__dirname, "../../.env") });
|
||||||
|
|
||||||
const apiRoutes = ["^/api/v1/", "/health"];
|
const apiRoutes = API_ROUTES || ["^/api/v1/", "/health"];
|
||||||
|
|
||||||
// Use environment variable to determine the target.
|
// Use environment variable to determine the target.
|
||||||
const target = process.env.VITE_PROXY_TARGET || "http://127.0.0.1:7860";
|
const target =
|
||||||
|
process.env.VITE_PROXY_TARGET || PROXY_TARGET || "http://127.0.0.1:7860";
|
||||||
|
|
||||||
// Use environment variable to determine the UI server port
|
// Use environment variable to determine the UI server port
|
||||||
const port = Number(process.env.VITE_PORT) || 3000;
|
const port = Number(process.env.VITE_PORT) || PORT || 3000;
|
||||||
|
|
||||||
const proxyTargets = apiRoutes.reduce((proxyObj, route) => {
|
const proxyTargets = apiRoutes.reduce((proxyObj, route) => {
|
||||||
proxyObj[route] = {
|
proxyObj[route] = {
|
||||||
|
|
@ -27,6 +34,7 @@ export default defineConfig(({ mode }) => {
|
||||||
}, {});
|
}, {});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
basename: (BASENAME || "") + "/",
|
||||||
build: {
|
build: {
|
||||||
outDir: "build",
|
outDir: "build",
|
||||||
},
|
},
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue