+
+ )}
);
}
diff --git a/ui/src/components/graphs/index.tsx b/ui/src/components/graphs/index.tsx
new file mode 100644
index 0000000000..839cc46131
--- /dev/null
+++ b/ui/src/components/graphs/index.tsx
@@ -0,0 +1,94 @@
+import {
+ Chart as ChartJS,
+ BarElement,
+ CategoryScale,
+ LinearScale,
+ ArcElement,
+ TimeScale,
+ TimeSeriesScale,
+ Title,
+ Tooltip,
+ Legend
+} from 'chart.js';
+import { useMemo } from 'react';
+import { Bar } from 'react-chartjs-2';
+import { useSelector } from 'react-redux';
+import { selectTimezone } from '~/app/preferences/preferencesSlice';
+import { useTimezone } from '~/data/hooks/timezone';
+import { Timezone } from '~/types/Preferences';
+
+ChartJS.register(
+ ArcElement,
+ BarElement,
+ CategoryScale,
+ LinearScale,
+ TimeScale,
+ TimeSeriesScale,
+ Title,
+ Tooltip,
+ Legend
+);
+
+const timeFormat = 'yyyy-MM-dd HH:mm:ss';
+
+type BarGraphProps = {
+ flagKey: string;
+ timestamps: string[];
+ values: number[];
+};
+
+export function BarGraph({ flagKey, timestamps, values }: BarGraphProps) {
+ const timezone = useSelector(selectTimezone);
+ const { inTimezone } = useTimezone();
+ const formattedTimestamps = timestamps.map((timestamp) =>
+ inTimezone(timestamp).slice(0, -4)
+ );
+ const isUTC = useMemo(() => timezone === Timezone.UTC, [timezone]);
+
+ const xLabel = isUTC ? 'Time (UTC)' : 'Time (Local)';
+
+ return (
+ <>
+
+ >
+ );
+}
diff --git a/ui/src/data/api.ts b/ui/src/data/api.ts
index 24d7f3dfd1..cac9eae1b4 100644
--- a/ui/src/data/api.ts
+++ b/ui/src/data/api.ts
@@ -5,6 +5,7 @@ export const apiURL = 'api/v1';
export const authURL = 'auth/v1';
export const evaluateURL = 'evaluate/v1';
export const metaURL = 'meta';
+export const internalURL = 'internal/v1';
const csrfTokenHeaderKey = 'x-csrf-token';
const sessionKey = 'session';
diff --git a/ui/src/store.ts b/ui/src/store.ts
index 1827472d78..421d228779 100644
--- a/ui/src/store.ts
+++ b/ui/src/store.ts
@@ -10,6 +10,7 @@ import {
namespaceKey,
namespacesSlice
} from '~/app/namespaces/namespacesSlice';
+import { analyticsApi } from './app/flags/analyticsApi';
import { flagsApi } from './app/flags/flagsApi';
import { rolloutTag, rolloutsApi } from './app/flags/rolloutsApi';
import { ruleTag, rulesApi } from './app/flags/rulesApi';
@@ -152,7 +153,8 @@ export const store = configureStore({
[rulesApi.reducerPath]: rulesApi.reducer,
[rolloutsApi.reducerPath]: rolloutsApi.reducer,
[tokensApi.reducerPath]: tokensApi.reducer,
- [authProvidersApi.reducerPath]: authProvidersApi.reducer
+ [authProvidersApi.reducerPath]: authProvidersApi.reducer,
+ [analyticsApi.reducerPath]: analyticsApi.reducer
},
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware()
@@ -164,7 +166,8 @@ export const store = configureStore({
rulesApi.middleware,
rolloutsApi.middleware,
tokensApi.middleware,
- authProvidersApi.middleware
+ authProvidersApi.middleware,
+ analyticsApi.middleware
)
});
diff --git a/ui/src/types/Analytics.ts b/ui/src/types/Analytics.ts
new file mode 100644
index 0000000000..887f3850ab
--- /dev/null
+++ b/ui/src/types/Analytics.ts
@@ -0,0 +1,4 @@
+export interface IFlagEvaluationCount {
+ timestamps: string[];
+ values: number[];
+}
diff --git a/ui/src/utils/redux-rtk.ts b/ui/src/utils/redux-rtk.ts
index 9b1e01cca1..da3ed402f6 100644
--- a/ui/src/utils/redux-rtk.ts
+++ b/ui/src/utils/redux-rtk.ts
@@ -4,7 +4,7 @@ import {
FetchBaseQueryError,
fetchBaseQuery
} from '@reduxjs/toolkit/query/react';
-import { apiURL, checkResponse, defaultHeaders } from '~/data/api';
+import { apiURL, checkResponse, defaultHeaders, internalURL } from '~/data/api';
type CustomFetchFn = (
url: RequestInfo,
options: RequestInit | undefined
@@ -21,6 +21,11 @@ export const customFetchFn: CustomFetchFn = async (url, options) => {
return response;
};
+export const internalQuery = fetchBaseQuery({
+ baseUrl: internalURL,
+ fetchFn: customFetchFn
+});
+
export const baseQuery: BaseQueryFn<
string | FetchArgs,
unknown,
diff --git a/ui/vite.config.ts b/ui/vite.config.ts
index 276b134e2c..31bd181b04 100644
--- a/ui/vite.config.ts
+++ b/ui/vite.config.ts
@@ -23,6 +23,7 @@ export default defineConfig({
'/api/v1': fliptAddr,
'/auth/v1': fliptAddr,
'/evaluate/v1': fliptAddr,
+ '/internal/v1': fliptAddr,
'/meta': fliptAddr
},
origin: 'http://localhost:5173'