diff --git a/README.md b/README.md
index e53a59b..8b5c06b 100644
--- a/README.md
+++ b/README.md
@@ -86,18 +86,19 @@ metadata:
name: my-service
annotations:
flagsmith.com/project-id: '12345'
- flagsmith.com/org-id: '67890' # Optional - defaults to first organization
spec:
type: service
owner: team-a
```
+> **Note:** The organization ID is automatically derived from the project data.
+
## Getting your Flagsmith credentials
1. Log in to your [Flagsmith dashboard](https://app.flagsmith.com)
2. Go to **Organisation Settings** > **API Keys**
3. Create or copy your **Admin API Key**
-4. Find your **Project ID** and **Organisation ID** in the URL or project settings
+4. Find your **Project ID** in the URL or project settings
## Development
diff --git a/dev/index.tsx b/dev/index.tsx
index ba4ef60..5643089 100644
--- a/dev/index.tsx
+++ b/dev/index.tsx
@@ -2,6 +2,7 @@ import { PropsWithChildren } from 'react';
import { createDevApp } from '@backstage/dev-utils';
import { EntityProvider } from '@backstage/plugin-catalog-react';
import { Entity } from '@backstage/catalog-model';
+import { Box, Grid } from '@material-ui/core';
import { setupWorker } from 'msw';
import { FlagsTab } from '../src/components/FlagsTab';
import { FlagsmithOverviewCard } from '../src/components/FlagsmithOverviewCard';
@@ -23,7 +24,6 @@ const mockEntity: Entity = {
description: 'A demo service with Flagsmith feature flags integration',
annotations: {
'flagsmith.com/project-id': '31465',
- 'flagsmith.com/org-id': '24242',
},
},
spec: {
@@ -64,4 +64,25 @@ createDevApp()
title: 'Overview Cards',
path: '/flagsmith-cards',
})
+ .addPage({
+ element: (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ),
+ title: 'Complete View',
+ path: '/flagsmith-complete',
+ })
.render();
diff --git a/src/components/FlagsmithUsageCard/index.tsx b/src/components/FlagsmithUsageCard/index.tsx
index 7cef679..23e3415 100644
--- a/src/components/FlagsmithUsageCard/index.tsx
+++ b/src/components/FlagsmithUsageCard/index.tsx
@@ -20,14 +20,12 @@ export const FlagsmithUsageCard = () => {
const { entity } = useEntity();
const projectId = entity.metadata.annotations?.['flagsmith.com/project-id'];
- const orgId = entity.metadata.annotations?.['flagsmith.com/org-id'];
- const { project, usageData, totalFlags, loading, error } = useFlagsmithUsage(
- projectId,
- orgId,
- );
+ const { project, usageData, totalFlags, loading, error } = useFlagsmithUsage(projectId);
- const usageUrl = `${FLAGSMITH_DASHBOARD_URL}/organisation/${orgId}/usage`;
+ // Derive organization ID from project data for the dashboard link
+ const orgId = project?.organisation;
+ const usageUrl = orgId ? `${FLAGSMITH_DASHBOARD_URL}/organisation/${orgId}/usage` : undefined;
if (loading) {
return (
@@ -40,10 +38,7 @@ export const FlagsmithUsageCard = () => {
if (error) {
return (
-
+
);
}
@@ -57,7 +52,7 @@ export const FlagsmithUsageCard = () => {
title="Flags Usage Data (30 Days)"
subheader={subheader}
action={
- orgId && (
+ usageUrl && (
diff --git a/src/hooks/useFlagsmithUsage.test.tsx b/src/hooks/useFlagsmithUsage.test.tsx
index b60b289..4f09a9d 100644
--- a/src/hooks/useFlagsmithUsage.test.tsx
+++ b/src/hooks/useFlagsmithUsage.test.tsx
@@ -25,28 +25,29 @@ describe('useFlagsmithUsage', () => {
jest.clearAllMocks();
});
- it('returns error when projectId or orgId is missing', async () => {
- const { result } = renderHook(() => useFlagsmithUsage(undefined, '1'), { wrapper });
+ it('returns error when projectId is missing', async () => {
+ const { result } = renderHook(() => useFlagsmithUsage(undefined), { wrapper });
await waitFor(() => expect(result.current.loading).toBe(false));
expect(result.current.error).toContain('Missing Flagsmith project ID');
});
- it('fetches usage data and calculates totalFlags', async () => {
- const mockProject = { id: 123, name: 'Test', organisation: 1 };
+ it('fetches usage data and derives orgId from project', async () => {
+ const mockProject = { id: 123, name: 'Test', organisation: 456 };
const mockUsage = [{ flags: 100, day: '2024-01-01' }, { flags: 200, day: '2024-01-02' }];
mockFetch
.mockResolvedValueOnce({ ok: true, json: async () => mockProject })
.mockResolvedValueOnce({ ok: true, json: async () => mockUsage });
- const { result } = renderHook(() => useFlagsmithUsage('123', '1'), { wrapper });
+ const { result } = renderHook(() => useFlagsmithUsage('123'), { wrapper });
await waitFor(() => expect(result.current.loading).toBe(false));
expect(result.current.project).toEqual(mockProject);
expect(result.current.usageData).toEqual(mockUsage);
expect(result.current.totalFlags).toBe(300);
+ expect(result.current.error).toBeNull();
});
});
diff --git a/src/hooks/useFlagsmithUsage.ts b/src/hooks/useFlagsmithUsage.ts
index 95ccaee..085928a 100644
--- a/src/hooks/useFlagsmithUsage.ts
+++ b/src/hooks/useFlagsmithUsage.ts
@@ -16,7 +16,6 @@ export interface UseFlagsmithUsageResult {
export function useFlagsmithUsage(
projectId: string | undefined,
- orgId: string | undefined,
): UseFlagsmithUsageResult {
const discoveryApi = useApi(discoveryApiRef);
const fetchApi = useApi(fetchApiRef);
@@ -33,19 +32,21 @@ export function useFlagsmithUsage(
const [error, setError] = useState(null);
useEffect(() => {
- if (!projectId || !orgId) {
- setError('Missing Flagsmith project ID or organization ID in entity annotations');
+ if (!projectId) {
+ setError('Missing Flagsmith project ID in entity annotations');
setLoading(false);
return;
}
const fetchData = async () => {
try {
+ // Fetch project data to get the organization ID
const projectData = await client.getProject(parseInt(projectId, 10));
setProject(projectData);
+ // Derive organization ID from project data
const usage = await client.getUsageData(
- parseInt(orgId, 10),
+ projectData.organisation,
parseInt(projectId, 10),
);
setUsageData(usage);
@@ -57,7 +58,7 @@ export function useFlagsmithUsage(
};
fetchData();
- }, [projectId, orgId, client]);
+ }, [projectId, client]);
const totalFlags = usageData.reduce((sum, day) => sum + (day.flags ?? 0), 0);