feat: create Frontend feature flags (#3029)
* Add UI feature flag config * [autofix.ci] apply automated fixes * hide general settings if there is nothing to show * make sure to handle !autoLogin case * [autofix.ci] apply automated fixes * missed commit * [autofix.ci] apply automated fixes --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: anovazzi1 <otavio2204@gmail.com>
This commit is contained in:
parent
818a17d0db
commit
72ff6d3a58
7 changed files with 127 additions and 54 deletions
6
src/frontend/feature-config.json
Normal file
6
src/frontend/feature-config.json
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"ENABLE_DARK_MODE": true,
|
||||
"ENABLE_API": true,
|
||||
"ENABLE_LANGFLOW_STORE": true,
|
||||
"ENABLE_PROFILE_ICONS": true
|
||||
}
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
import FeatureFlags from "@/../feature-config.json";
|
||||
import { Transition } from "@headlessui/react";
|
||||
import { useMemo, useRef, useState } from "react";
|
||||
import { useHotkeys } from "react-hotkeys-hook";
|
||||
|
|
@ -140,30 +141,34 @@ export default function FlowToolbar(): JSX.Element {
|
|||
<div>
|
||||
<Separator orientation="vertical" />
|
||||
</div>
|
||||
<div className="flex cursor-pointer items-center gap-2">
|
||||
{currentFlow && currentFlow.data && (
|
||||
<ApiModal
|
||||
flow={currentFlow}
|
||||
open={openCodeModal}
|
||||
setOpen={setOpenCodeModal}
|
||||
>
|
||||
<div
|
||||
className={classNames(
|
||||
"relative inline-flex w-full items-center justify-center gap-1 px-5 py-3 text-sm font-semibold text-foreground transition-all duration-150 ease-in-out hover:bg-hover",
|
||||
)}
|
||||
>
|
||||
<ForwardedIconComponent
|
||||
name="Code2"
|
||||
className={"h-5 w-5"}
|
||||
/>
|
||||
API
|
||||
</div>
|
||||
</ApiModal>
|
||||
)}
|
||||
</div>
|
||||
<div>
|
||||
<Separator orientation="vertical" />
|
||||
</div>
|
||||
{FeatureFlags.ENABLE_API && (
|
||||
<>
|
||||
<div className="flex cursor-pointer items-center gap-2">
|
||||
{currentFlow && currentFlow.data && (
|
||||
<ApiModal
|
||||
flow={currentFlow}
|
||||
open={openCodeModal}
|
||||
setOpen={setOpenCodeModal}
|
||||
>
|
||||
<div
|
||||
className={classNames(
|
||||
"relative inline-flex w-full items-center justify-center gap-1 px-5 py-3 text-sm font-semibold text-foreground transition-all duration-150 ease-in-out hover:bg-hover",
|
||||
)}
|
||||
>
|
||||
<ForwardedIconComponent
|
||||
name="Code2"
|
||||
className={"h-5 w-5"}
|
||||
/>
|
||||
API
|
||||
</div>
|
||||
</ApiModal>
|
||||
)}
|
||||
</div>
|
||||
<div>
|
||||
<Separator orientation="vertical" />
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
<div className="flex items-center gap-2">
|
||||
<div
|
||||
className={`side-bar-button ${
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import {
|
|||
} from "../../constants/constants";
|
||||
import { AuthContext } from "../../contexts/authContext";
|
||||
|
||||
import FeatureFlags from "@/../feature-config.json";
|
||||
import { useLogout } from "@/controllers/API/queries/auth";
|
||||
import useAuthStore from "@/stores/authStore";
|
||||
import useAlertStore from "../../stores/alertStore";
|
||||
|
|
@ -182,18 +183,26 @@ export default function Header(): JSX.Element {
|
|||
</a>
|
||||
|
||||
<Separator orientation="vertical" />
|
||||
<button
|
||||
className="extra-side-bar-save-disable"
|
||||
onClick={() => {
|
||||
setDark(!dark);
|
||||
}}
|
||||
>
|
||||
{dark ? (
|
||||
<IconComponent name="SunIcon" className="side-bar-button-size" />
|
||||
) : (
|
||||
<IconComponent name="MoonIcon" className="side-bar-button-size" />
|
||||
)}
|
||||
</button>
|
||||
{FeatureFlags.ENABLE_DARK_MODE && (
|
||||
<button
|
||||
className="extra-side-bar-save-disable"
|
||||
onClick={() => {
|
||||
setDark(!dark);
|
||||
}}
|
||||
>
|
||||
{dark ? (
|
||||
<IconComponent
|
||||
name="SunIcon"
|
||||
className="side-bar-button-size"
|
||||
/>
|
||||
) : (
|
||||
<IconComponent
|
||||
name="MoonIcon"
|
||||
className="side-bar-button-size"
|
||||
/>
|
||||
)}
|
||||
</button>
|
||||
)}
|
||||
<AlertDropdown>
|
||||
<div className="extra-side-bar-save-disable relative">
|
||||
{notificationCenter && (
|
||||
|
|
@ -216,10 +225,17 @@ export default function Header(): JSX.Element {
|
|||
data-testid="user-profile-settings"
|
||||
className="shrink-0"
|
||||
>
|
||||
<img
|
||||
src={profileImageUrl}
|
||||
className="h-7 w-7 shrink-0 focus-visible:outline-0"
|
||||
/>
|
||||
{FeatureFlags.ENABLE_PROFILE_ICONS ? (
|
||||
<img
|
||||
src={profileImageUrl}
|
||||
className="h-7 w-7 shrink-0 focus-visible:outline-0"
|
||||
/>
|
||||
) : (
|
||||
<IconComponent
|
||||
name="Settings"
|
||||
className="side-bar-button-size"
|
||||
/>
|
||||
)}
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent className="mr-1 mt-1 min-w-40">
|
||||
|
|
|
|||
|
|
@ -1,3 +1,6 @@
|
|||
import FeatureFlags from "@/../feature-config.json";
|
||||
import useAuthStore from "@/stores/authStore";
|
||||
import { useStoreStore } from "@/stores/storeStore";
|
||||
import { useEffect } from "react";
|
||||
import { Outlet } from "react-router-dom";
|
||||
import ForwardedIconComponent from "../../components/genericIconComponent";
|
||||
|
|
@ -10,12 +13,26 @@ export default function SettingsPage(): JSX.Element {
|
|||
const setCurrentFlowId = useFlowsManagerStore(
|
||||
(state) => state.setCurrentFlowId,
|
||||
);
|
||||
|
||||
const autoLogin = useAuthStore((state) => state.autoLogin);
|
||||
const hasStore = useStoreStore((state) => state.hasStore);
|
||||
|
||||
// Hides the General settings if there is nothing to show
|
||||
const showGeneralSettings =
|
||||
FeatureFlags.ENABLE_PROFILE_ICONS || hasStore || !autoLogin;
|
||||
|
||||
useEffect(() => {
|
||||
setCurrentFlowId("");
|
||||
}, [pathname]);
|
||||
|
||||
const sidebarNavItems = [
|
||||
{
|
||||
const sidebarNavItems: {
|
||||
href?: string;
|
||||
title: string;
|
||||
icon: React.ReactNode;
|
||||
}[] = [];
|
||||
|
||||
if (showGeneralSettings) {
|
||||
sidebarNavItems.push({
|
||||
title: "General",
|
||||
href: "/settings/general",
|
||||
icon: (
|
||||
|
|
@ -24,7 +41,10 @@ export default function SettingsPage(): JSX.Element {
|
|||
className="w-4 flex-shrink-0 justify-start stroke-[1.5]"
|
||||
/>
|
||||
),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
sidebarNavItems.push(
|
||||
{
|
||||
title: "Global Variables",
|
||||
href: "/settings/global-variables",
|
||||
|
|
@ -65,7 +85,7 @@ export default function SettingsPage(): JSX.Element {
|
|||
/>
|
||||
),
|
||||
},
|
||||
];
|
||||
);
|
||||
return (
|
||||
<PageLayout
|
||||
title="Settings"
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import FeatureFlags from "@/../feature-config.json";
|
||||
import { usePostAddApiKey } from "@/controllers/API/queries/api-keys";
|
||||
import { useGetProfilePicturesQuery } from "@/controllers/API/queries/files";
|
||||
import useAuthStore from "@/stores/authStore";
|
||||
|
|
@ -101,13 +102,15 @@ export const GeneralPage = () => {
|
|||
<GeneralPageHeaderComponent />
|
||||
|
||||
<div className="grid gap-6">
|
||||
<ProfilePictureFormComponent
|
||||
profilePicture={profilePicture}
|
||||
handleInput={handleInput}
|
||||
handlePatchProfilePicture={handlePatchProfilePicture}
|
||||
handleGetProfilePictures={handleGetProfilePictures}
|
||||
userData={userData}
|
||||
/>
|
||||
{FeatureFlags.ENABLE_PROFILE_ICONS && (
|
||||
<ProfilePictureFormComponent
|
||||
profilePicture={profilePicture}
|
||||
handleInput={handleInput}
|
||||
handlePatchProfilePicture={handlePatchProfilePicture}
|
||||
handleGetProfilePictures={handleGetProfilePictures}
|
||||
userData={userData}
|
||||
/>
|
||||
)}
|
||||
|
||||
{!autoLogin && (
|
||||
<PasswordFormComponent
|
||||
|
|
|
|||
|
|
@ -1,3 +1,6 @@
|
|||
import FeatureFlags from "@/../feature-config.json";
|
||||
import useAuthStore from "@/stores/authStore";
|
||||
import { useStoreStore } from "@/stores/storeStore";
|
||||
import { Suspense, lazy } from "react";
|
||||
import { Navigate, Route, Routes } from "react-router-dom";
|
||||
import { ProtectedAdminRoute } from "./components/authAdminGuard";
|
||||
|
|
@ -36,6 +39,13 @@ const StorePage = lazy(() => import("./pages/StorePage"));
|
|||
const ViewPage = lazy(() => import("./pages/ViewPage"));
|
||||
|
||||
const Router = () => {
|
||||
const autoLogin = useAuthStore((state) => state.autoLogin);
|
||||
const hasStore = useStoreStore((state) => state.hasStore);
|
||||
|
||||
// Hides the General settings if there is nothing to show
|
||||
const showGeneralSettings =
|
||||
FeatureFlags.ENABLE_PROFILE_ICONS || hasStore || !autoLogin;
|
||||
|
||||
return (
|
||||
<Suspense
|
||||
fallback={
|
||||
|
|
@ -77,10 +87,20 @@ const Router = () => {
|
|||
</ProtectedRoute>
|
||||
}
|
||||
>
|
||||
<Route index element={<Navigate replace to={"general"} />} />
|
||||
<Route
|
||||
index
|
||||
element={
|
||||
<Navigate
|
||||
replace
|
||||
to={showGeneralSettings ? "general" : "global-variables"}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
<Route path="global-variables" element={<GlobalVariablesPage />} />
|
||||
<Route path="api-keys" element={<ApiKeysPage />} />
|
||||
<Route path="general/:scrollId?" element={<GeneralPage />} />
|
||||
{showGeneralSettings && (
|
||||
<Route path="general/:scrollId?" element={<GeneralPage />} />
|
||||
)}
|
||||
<Route path="shortcuts" element={<ShortcutsPage />} />
|
||||
<Route path="messages" element={<MessagesPage />} />
|
||||
</Route>
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import FeatureFlags from "@/../feature-config.json";
|
||||
import { create } from "zustand";
|
||||
import { checkHasApiKey, checkHasStore } from "../controllers/API";
|
||||
import { StoreStoreType } from "../types/zustand/store";
|
||||
|
|
@ -9,7 +10,9 @@ export const useStoreStore = create<StoreStoreType>((set) => ({
|
|||
loadingApiKey: true,
|
||||
checkHasStore: () => {
|
||||
checkHasStore().then((res) => {
|
||||
set({ hasStore: res?.enabled ?? false });
|
||||
set({
|
||||
hasStore: FeatureFlags.ENABLE_LANGFLOW_STORE && (res?.enabled ?? false),
|
||||
});
|
||||
});
|
||||
},
|
||||
updateValidApiKey: (validApiKey) => set(() => ({ validApiKey: validApiKey })),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue