Skip to content

Commit

Permalink
feat: create Frontend feature flags (langflow-ai#3029)
Browse files Browse the repository at this point in the history
* 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 <[email protected]>
(cherry picked from commit 72ff6d3)
  • Loading branch information
mfortman11 authored and nicoloboschi committed Aug 1, 2024
1 parent 1bbf39e commit 03c7975
Show file tree
Hide file tree
Showing 7 changed files with 127 additions and 54 deletions.
6 changes: 6 additions & 0 deletions src/frontend/feature-config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"ENABLE_DARK_MODE": true,
"ENABLE_API": true,
"ENABLE_LANGFLOW_STORE": true,
"ENABLE_PROFILE_ICONS": true
}
53 changes: 29 additions & 24 deletions src/frontend/src/components/chatComponent/index.tsx
Original file line number Diff line number Diff line change
@@ -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";
Expand Down Expand Up @@ -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 ${
Expand Down
48 changes: 32 additions & 16 deletions src/frontend/src/components/headerComponent/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down Expand Up @@ -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 && (
Expand All @@ -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">
Expand Down
28 changes: 24 additions & 4 deletions src/frontend/src/pages/SettingsPage/index.tsx
Original file line number Diff line number Diff line change
@@ -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";
Expand All @@ -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: (
Expand All @@ -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",
Expand Down Expand Up @@ -65,7 +85,7 @@ export default function SettingsPage(): JSX.Element {
/>
),
},
];
);
return (
<PageLayout
title="Settings"
Expand Down
17 changes: 10 additions & 7 deletions src/frontend/src/pages/SettingsPage/pages/GeneralPage/index.tsx
Original file line number Diff line number Diff line change
@@ -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";
Expand Down Expand Up @@ -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
Expand Down
24 changes: 22 additions & 2 deletions src/frontend/src/routes.tsx
Original file line number Diff line number Diff line change
@@ -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";
Expand Down Expand Up @@ -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={
Expand Down Expand Up @@ -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>
Expand Down
5 changes: 4 additions & 1 deletion src/frontend/src/stores/storeStore.ts
Original file line number Diff line number Diff line change
@@ -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";
Expand All @@ -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 })),
Expand Down

0 comments on commit 03c7975

Please sign in to comment.