diff --git a/site/src/App.tsx b/site/src/App.tsx index 521d28f..a6aeea9 100644 --- a/site/src/App.tsx +++ b/site/src/App.tsx @@ -1,4 +1,4 @@ -import { type ReactNode, useEffect, useState } from "react"; +import React, { type ReactNode, useEffect, useState } from "react"; const REPO = "GeneralUserModels/tada"; const RELEASE_URL = `https://github.com/${REPO}/releases/latest`; diff --git a/site/src/main.tsx b/site/src/main.tsx index bd4d570..423ec24 100644 --- a/site/src/main.tsx +++ b/site/src/main.tsx @@ -1,4 +1,4 @@ -import { StrictMode } from "react"; +import React, { StrictMode } from "react"; import { createRoot } from "react-dom/client"; import { App } from "./App"; import "./App.css"; diff --git a/src/apps/moments/discovery.py b/src/apps/moments/discovery.py index 671120f..9075ee8 100644 --- a/src/apps/moments/discovery.py +++ b/src/apps/moments/discovery.py @@ -7,6 +7,8 @@ from datetime import datetime from pathlib import Path +from server.feature_flags import is_enabled + logger = logging.getLogger(__name__) @@ -100,7 +102,7 @@ async def run_moments_discovery(state) -> None: logger.info("Next discovery run at %s (in %.0fs)", next_run, delay) await asyncio.sleep(delay) - if not state.config.moments_enabled: + if not (is_enabled(state.config, "moments") and state.config.moments_enabled): continue cfg = state.config diff --git a/src/apps/moments/scheduler.py b/src/apps/moments/scheduler.py index 4284331..da921d3 100644 --- a/src/apps/moments/scheduler.py +++ b/src/apps/moments/scheduler.py @@ -12,6 +12,7 @@ from apps.moments.execute import run as execute_moment, _parse_frontmatter as parse_frontmatter from apps.moments.state import load_state +from server.feature_flags import is_enabled logger = logging.getLogger(__name__) @@ -138,7 +139,7 @@ async def run_moments_scheduler(state) -> None: try: await asyncio.sleep(SCAN_INTERVAL) - if not state.config.moments_enabled: + if not (is_enabled(state.config, "moments") and state.config.moments_enabled): continue cfg = state.config diff --git a/src/client/renderer/App.tsx b/src/client/renderer/App.tsx index 0046904..31020ca 100644 --- a/src/client/renderer/App.tsx +++ b/src/client/renderer/App.tsx @@ -1,4 +1,6 @@ +import React from "react"; import { useAppContext } from "./context/AppContext"; +import { useFeatureFlag } from "./featureFlags"; import { Sidebar } from "./components/Sidebar"; import { ConnectorsView } from "./components/views/ConnectorsView"; import { UserModelView } from "./components/views/UserModelView"; @@ -8,6 +10,7 @@ import { UpdateBanner } from "./components/UpdateBanner"; export function App() { const { state, dispatch } = useAppContext(); + const momentsEnabled = useFeatureFlag("moments"); const navigate = (view: typeof state.activeView) => { dispatch({ type: "NAVIGATE", view }); @@ -30,7 +33,7 @@ export function App() { /> )} {state.activeView === "connectors" && } - {state.activeView === "tada" && } + {state.activeView === "tada" && momentsEnabled && } {state.activeView === "usermodel" && } {state.activeView === "settings" && } diff --git a/src/client/renderer/components/Sidebar.tsx b/src/client/renderer/components/Sidebar.tsx index dbfe03a..d18e222 100644 --- a/src/client/renderer/components/Sidebar.tsx +++ b/src/client/renderer/components/Sidebar.tsx @@ -1,4 +1,6 @@ +import React from "react"; import { ActiveView } from "../context/AppContext"; +import { useFeatureFlags, getFlag } from "../featureFlags"; interface Props { activeView: ActiveView; @@ -48,7 +50,19 @@ const navItems: { view: ActiveView; label: string; icon: JSX.Element }[] = [ }, ]; +const FLAG_FOR_VIEW: Partial> = { + tada: "moments", +}; + export function Sidebar({ activeView, connected, onNavigate }: Props) { + const featureFlags = useFeatureFlags(); + + const visibleItems = navItems.filter(({ view }) => { + const flag = FLAG_FOR_VIEW[view]; + if (flag && !getFlag(featureFlags, flag)) return false; + return true; + }); + return (