From 61e15e6c85d88bb6b2f28afcb44a3a897ce317c6 Mon Sep 17 00:00:00 2001
From: Gurinder Singh <gurinder@coderabbit.ai>
Date: Sat, 22 Mar 2025 16:27:02 -0400
Subject: [PATCH] Added team filter support

---
 public/app/core/reducers/fn-slice.ts          |  6 ++++++
 .../pickers/OptionsPicker/OptionsPicker.tsx   | 19 +++++++++++++++++--
 public/app/fn-app/create-mfe.ts               |  3 ++-
 .../fn-dashboard-page/render-fn-dashboard.tsx |  8 ++++----
 public/app/fn-app/types.ts                    | 12 ++----------
 5 files changed, 31 insertions(+), 17 deletions(-)

diff --git a/public/app/core/reducers/fn-slice.ts b/public/app/core/reducers/fn-slice.ts
index d71ce9aef766e..57eb2bf9385d2 100644
--- a/public/app/core/reducers/fn-slice.ts
+++ b/public/app/core/reducers/fn-slice.ts
@@ -15,6 +15,9 @@ export interface FnGlobalState {
   queryParams: AnyObject;
   hiddenVariables: readonly string[];
   fnGlobalTimeRange: TimeRange | null;
+  metadata: {
+    teams: string[];
+  };
 }
 
 export type UpdateFNGlobalStateAction = PayloadAction<Partial<FnGlobalState>>;
@@ -57,6 +60,9 @@ export const INITIAL_FN_STATE: FnGlobalState = {
   queryParams: {},
   hiddenVariables: [],
   fnGlobalTimeRange: null,
+  metadata: {
+    teams: [],
+  },
 } as const;
 
 const reducers: SliceCaseReducers<FnGlobalState> = {
diff --git a/public/app/features/variables/pickers/OptionsPicker/OptionsPicker.tsx b/public/app/features/variables/pickers/OptionsPicker/OptionsPicker.tsx
index 7a52df41e1259..aa733ac7496ea 100644
--- a/public/app/features/variables/pickers/OptionsPicker/OptionsPicker.tsx
+++ b/public/app/features/variables/pickers/OptionsPicker/OptionsPicker.tsx
@@ -53,8 +53,21 @@ export const optionPickerFactory = <Model extends VariableWithOptions | Variable
       };
     }
 
+    const isMfeTeamFilter = state.fnGlobalState.FNDashboard && state.fnGlobalState.metadata.teams.length;
+
+    const teamFilter = isMfeTeamFilter
+      ? state.fnGlobalState.metadata.teams.map((t) => ({
+          text: t,
+          value: t,
+          selected: false,
+        }))
+      : [];
+
+    const p = getVariablesState(rootStateKey, state).optionsPicker;
+
     return {
-      picker: getVariablesState(rootStateKey, state).optionsPicker,
+      picker: { ...p, ...(teamFilter.length && { options: [...p.options, ...teamFilter] }) },
+      mfeState: state.fnGlobalState,
     };
   };
 
@@ -149,7 +162,9 @@ export const optionPickerFactory = <Model extends VariableWithOptions | Variable
           <VariableInput
             id={VARIABLE_PREFIX + id}
             value={picker.queryValue}
-            onChange={this.onFilterOrSearchOptions}
+            onChange={(value) => {
+              this.onFilterOrSearchOptions(value);
+            }}
             onNavigate={this.onNavigate}
             aria-expanded={true}
             aria-controls={`options-${id}`}
diff --git a/public/app/fn-app/create-mfe.ts b/public/app/fn-app/create-mfe.ts
index d6661429f88bc..528714d0a3c4e 100644
--- a/public/app/fn-app/create-mfe.ts
+++ b/public/app/fn-app/create-mfe.ts
@@ -204,8 +204,8 @@ class createMfe {
 
           const initialState: FnGlobalState = {
             ...INITIAL_FN_STATE,
-            FNDashboard: true,
             ...pick(props, ...fnStateProps),
+            FNDashboard: true,
           };
 
           createMfe.logger.info('[FN Grafana] Dispatching initial state.', { initialState });
@@ -280,6 +280,7 @@ class createMfe {
             version: other.version,
             queryParams: other.queryParams,
             controlsContainer: other.controlsContainer,
+            metadata: other.metadata,
           })
         );
       }
diff --git a/public/app/fn-app/fn-dashboard-page/render-fn-dashboard.tsx b/public/app/fn-app/fn-dashboard-page/render-fn-dashboard.tsx
index e9dac0f5ce0cf..1f4f168718f84 100644
--- a/public/app/fn-app/fn-dashboard-page/render-fn-dashboard.tsx
+++ b/public/app/fn-app/fn-dashboard-page/render-fn-dashboard.tsx
@@ -7,7 +7,7 @@ import { DashboardRoutes, StoreState, useSelector } from 'app/types';
 
 import { FNDashboardProps } from '../types';
 
-const locationService = locationSrv as HistoryWrapper;
+export const mfeLocationService = locationSrv as HistoryWrapper;
 
 const DEFAULT_DASHBOARD_PAGE_PROPS: Pick<DashboardPageProps, 'history' | 'route'> & {
   match: Pick<DashboardPageProps['match'], 'isExact' | 'path' | 'url'>;
@@ -17,7 +17,7 @@ const DEFAULT_DASHBOARD_PAGE_PROPS: Pick<DashboardPageProps, 'history' | 'route'
     path: '/d/:uid/:slug?',
     url: '',
   },
-  history: {} as DashboardPageProps['history'],
+  history: mfeLocationService.getHistory(),
   route: {
     routeName: DashboardRoutes.Normal,
     path: '/d/:uid/:slug?',
@@ -50,7 +50,7 @@ export const RenderFNDashboard: FC<FNDashboardProps> = (props) => {
   }, [firstError, setErrors]);
 
   useEffect(() => {
-    locationService.fnPathnameChange(window.location.pathname, queryParams);
+    mfeLocationService.fnPathnameChange(window.location.pathname, queryParams);
   }, [queryParams]);
 
   const dashboardPageProps: DashboardPageProps = useMemo(
@@ -62,7 +62,7 @@ export const RenderFNDashboard: FC<FNDashboardProps> = (props) => {
             ...props,
           },
         },
-        location: locationService.getLocation(),
+        location: mfeLocationService.getLocation(),
         queryParams,
         hiddenVariables,
         controlsContainer,
diff --git a/public/app/fn-app/types.ts b/public/app/fn-app/types.ts
index 4a1bf55f26909..5d39827f25275 100644
--- a/public/app/fn-app/types.ts
+++ b/public/app/fn-app/types.ts
@@ -1,6 +1,6 @@
 import { ReactNode } from 'react';
 
-import { GrafanaThemeType } from '@grafana/data';
+import { FnGlobalState } from 'app/core/reducers/fn-slice';
 
 export type FailedToMountGrafanaErrorName = 'FailedToMountGrafana';
 
@@ -16,17 +16,9 @@ export type GrafanaMicroFrontendActions = {
 export type AnyObject<K extends string | number | symbol = string, V = any> = {
   [key in K]: V;
 };
-
-export interface FNDashboardProps {
+export interface FNDashboardProps extends FnGlobalState {
   name: string;
-  uid: string;
-  slug: string;
-  version: number;
-  mode: GrafanaThemeType.Dark | GrafanaThemeType.Light;
-  queryParams: Record<string, string>;
   fnError?: ReactNode;
-  pageTitle?: string;
-  controlsContainer: string | null;
   isLoading: (isLoading: boolean) => void;
   setErrors: (errors?: { [K: number | string]: string }) => void;
   hiddenVariables: readonly string[];