@flagsmith/backstage-plugin 0.2.1 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. package/README.md +3 -2
  2. package/dist/api/FlagsmithClient.esm.js +11 -0
  3. package/dist/api/FlagsmithClient.esm.js.map +1 -1
  4. package/dist/components/FlagsTab/ExpandableRow.esm.js +4 -11
  5. package/dist/components/FlagsTab/ExpandableRow.esm.js.map +1 -1
  6. package/dist/components/FlagsTab/FeatureAnalyticsSection.esm.js +1 -0
  7. package/dist/components/FlagsTab/FeatureAnalyticsSection.esm.js.map +1 -1
  8. package/dist/components/FlagsTab/FeatureDetailsGrid.esm.js +9 -1
  9. package/dist/components/FlagsTab/FeatureDetailsGrid.esm.js.map +1 -1
  10. package/dist/components/FlagsTab/SegmentOverridesSection.esm.js +1 -0
  11. package/dist/components/FlagsTab/SegmentOverridesSection.esm.js.map +1 -1
  12. package/dist/components/FlagsTab/index.esm.js +3 -1
  13. package/dist/components/FlagsTab/index.esm.js.map +1 -1
  14. package/dist/components/FlagsmithOverviewCard/FeatureFlagRow.esm.js +1 -0
  15. package/dist/components/FlagsmithOverviewCard/FeatureFlagRow.esm.js.map +1 -1
  16. package/dist/components/FlagsmithOverviewCard/FlagStatsRow.esm.js +1 -0
  17. package/dist/components/FlagsmithOverviewCard/FlagStatsRow.esm.js.map +1 -1
  18. package/dist/components/FlagsmithOverviewCard/index.esm.js +1 -0
  19. package/dist/components/FlagsmithOverviewCard/index.esm.js.map +1 -1
  20. package/dist/components/FlagsmithUsageCard/UsageChart.esm.js +1 -0
  21. package/dist/components/FlagsmithUsageCard/UsageChart.esm.js.map +1 -1
  22. package/dist/components/FlagsmithUsageCard/index.esm.js +6 -14
  23. package/dist/components/FlagsmithUsageCard/index.esm.js.map +1 -1
  24. package/dist/components/shared/TagChip.esm.js +32 -0
  25. package/dist/components/shared/TagChip.esm.js.map +1 -0
  26. package/dist/hooks/useFlagsmithProject.esm.js +9 -1
  27. package/dist/hooks/useFlagsmithProject.esm.js.map +1 -1
  28. package/dist/hooks/useFlagsmithUsage.esm.js +5 -5
  29. package/dist/hooks/useFlagsmithUsage.esm.js.map +1 -1
  30. package/dist/utils/colorUtils.esm.js +39 -0
  31. package/dist/utils/colorUtils.esm.js.map +1 -0
  32. package/package.json +1 -1
package/README.md CHANGED
@@ -86,18 +86,19 @@ metadata:
86
86
  name: my-service
87
87
  annotations:
88
88
  flagsmith.com/project-id: '12345'
89
- flagsmith.com/org-id: '67890' # Optional - defaults to first organization
90
89
  spec:
91
90
  type: service
92
91
  owner: team-a
93
92
  ```
94
93
 
94
+ > **Note:** The organization ID is automatically derived from the project data.
95
+
95
96
  ## Getting your Flagsmith credentials
96
97
 
97
98
  1. Log in to your [Flagsmith dashboard](https://app.flagsmith.com)
98
99
  2. Go to **Organisation Settings** > **API Keys**
99
100
  3. Create or copy your **Admin API Key**
100
- 4. Find your **Project ID** and **Organisation ID** in the URL or project settings
101
+ 4. Find your **Project ID** in the URL or project settings
101
102
 
102
103
  ## Development
103
104
 
@@ -59,6 +59,17 @@ class FlagsmithClient {
59
59
  }
60
60
  return await response.json();
61
61
  }
62
+ async getProjectTags(projectId) {
63
+ const baseUrl = await this.getBaseUrl();
64
+ const response = await this.fetchApi.fetch(
65
+ `${baseUrl}/projects/${projectId}/tags/`
66
+ );
67
+ if (!response.ok) {
68
+ throw new Error(`Failed to fetch project tags: ${response.statusText}`);
69
+ }
70
+ const data = await response.json();
71
+ return data.results || data;
72
+ }
62
73
  async getUsageData(orgId, projectId, environmentId) {
63
74
  const baseUrl = await this.getBaseUrl();
64
75
  const url = new URL(`${baseUrl}/organisations/${orgId}/usage-data/`);
@@ -1 +1 @@
1
- {"version":3,"file":"FlagsmithClient.esm.js","sources":["../../src/api/FlagsmithClient.ts"],"sourcesContent":["import { DiscoveryApi, FetchApi } from '@backstage/core-plugin-api';\n\nexport interface FlagsmithOrganization {\n id: number;\n name: string;\n created_date: string;\n}\n\nexport interface FlagsmithProject {\n id: number;\n name: string;\n organisation: number;\n created_date: string;\n}\n\nexport interface FlagsmithEnvironment {\n id: number;\n name: string;\n api_key: string;\n project: number;\n use_v2_feature_versioning?: boolean;\n}\n\nexport interface FlagsmithFeature {\n id: number;\n name: string;\n description?: string;\n created_date: string;\n project: number;\n environment_state?: Array<{\n id: number;\n enabled: boolean;\n feature_segment?: number | null;\n }> | null;\n num_segment_overrides?: number | null;\n num_identity_overrides?: number | null;\n live_version?: {\n is_live: boolean;\n live_from?: string | null;\n published: boolean;\n published_by?: string | null;\n uuid?: string;\n } | null;\n owners?: Array<{\n id: number;\n name: string;\n email: string;\n }>;\n group_owners?: Array<{\n id: number;\n name: string;\n }>;\n created_by?: {\n id: number;\n email: string;\n first_name?: string;\n last_name?: string;\n } | null;\n tags?: Array<string>;\n is_server_key_only?: boolean;\n type?: string;\n default_enabled?: boolean;\n is_archived?: boolean;\n initial_value?: string | null;\n multivariate_options?: Array<{\n id: number;\n type: string;\n integer_value?: number | null;\n string_value?: string | null;\n boolean_value?: boolean | null;\n default_percentage_allocation: number;\n }>;\n}\n\nexport interface FlagsmithFeatureVersion {\n uuid: string;\n is_live: boolean;\n live_from?: string | null;\n published: boolean;\n published_by?: string | null;\n}\n\nexport interface FlagsmithFeatureStateValue {\n string_value?: string | null;\n integer_value?: number | null;\n boolean_value?: boolean | null;\n}\n\nexport interface FlagsmithFeatureSegment {\n segment: number;\n priority: number;\n}\n\nexport interface FlagsmithFeatureState {\n id: number;\n enabled: boolean;\n environment?: number;\n feature_segment?: FlagsmithFeatureSegment | null;\n feature_state_value?: FlagsmithFeatureStateValue | null;\n updated_at?: string | null;\n}\n\nexport interface FlagsmithFeatureDetails {\n liveVersion: FlagsmithFeatureVersion | null;\n featureState: FlagsmithFeatureState[] | null;\n segmentOverrides: number;\n scheduledVersion: FlagsmithFeatureVersion | null;\n}\n\nexport interface FlagsmithUsageData {\n flags: number | null;\n identities: number;\n traits: number;\n environment_document: number;\n day: string;\n labels: {\n client_application_name: string | null;\n client_application_version: string | null;\n user_agent: string | null;\n };\n}\n\nexport class FlagsmithClient {\n constructor(\n private readonly discoveryApi: DiscoveryApi,\n private readonly fetchApi: FetchApi,\n ) {}\n\n private async getBaseUrl(): Promise<string> {\n const proxyUrl = await this.discoveryApi.getBaseUrl('proxy');\n return `${proxyUrl}/flagsmith`;\n }\n\n async getOrganizations(): Promise<FlagsmithOrganization[]> {\n const baseUrl = await this.getBaseUrl();\n const response = await this.fetchApi.fetch(`${baseUrl}/organisations/`);\n\n if (!response.ok) {\n throw new Error(`Failed to fetch organizations: ${response.statusText}`);\n }\n\n const data = await response.json();\n return data.results || data;\n }\n\n async getProjectsInOrg(orgId: number): Promise<FlagsmithProject[]> {\n const baseUrl = await this.getBaseUrl();\n const response = await this.fetchApi.fetch(\n `${baseUrl}/organisations/${orgId}/projects/`,\n );\n\n if (!response.ok) {\n throw new Error(`Failed to fetch projects: ${response.statusText}`);\n }\n\n const data = await response.json();\n return data.results || data;\n }\n\n async getProjectFeatures(projectId: string): Promise<FlagsmithFeature[]> {\n const baseUrl = await this.getBaseUrl();\n const response = await this.fetchApi.fetch(\n `${baseUrl}/projects/${projectId}/features/`,\n );\n\n if (!response.ok) {\n throw new Error(`Failed to fetch features: ${response.statusText}`);\n }\n\n const data = await response.json();\n return data.results || data;\n }\n\n async getProjectEnvironments(\n projectId: number,\n ): Promise<FlagsmithEnvironment[]> {\n const baseUrl = await this.getBaseUrl();\n const response = await this.fetchApi.fetch(\n `${baseUrl}/projects/${projectId}/environments/`,\n );\n\n if (!response.ok) {\n throw new Error(`Failed to fetch environments: ${response.statusText}`);\n }\n\n const data = await response.json();\n return data.results || data;\n }\n\n async getProject(projectId: number): Promise<FlagsmithProject> {\n const baseUrl = await this.getBaseUrl();\n const response = await this.fetchApi.fetch(\n `${baseUrl}/projects/${projectId}/`,\n );\n\n if (!response.ok) {\n throw new Error(`Failed to fetch project: ${response.statusText}`);\n }\n\n return await response.json();\n }\n\n async getUsageData(\n orgId: number,\n projectId?: number,\n environmentId?: number,\n ): Promise<FlagsmithUsageData[]> {\n const baseUrl = await this.getBaseUrl();\n const url = new URL(`${baseUrl}/organisations/${orgId}/usage-data/`);\n if (projectId) {\n url.searchParams.set('project_id', projectId.toString());\n }\n if (environmentId) {\n url.searchParams.set('environment_id', environmentId.toString());\n }\n\n const response = await this.fetchApi.fetch(url.toString());\n\n if (!response.ok) {\n throw new Error(`Failed to fetch usage data: ${response.statusText}`);\n }\n\n return await response.json();\n }\n\n /**\n * Fetch usage data for multiple environments in parallel\n */\n async getUsageDataByEnvironments(\n orgId: number,\n projectId: number,\n environments: Pick<FlagsmithEnvironment, 'id' | 'name'>[],\n ): Promise<Map<string, FlagsmithUsageData[]>> {\n const results = new Map<string, FlagsmithUsageData[]>();\n\n // Fetch usage data for each environment in parallel\n const promises = environments.map(async env => {\n try {\n const data = await this.getUsageData(orgId, projectId, env.id);\n return { envName: env.name, data };\n } catch {\n // If environment-level filtering isn't supported, return empty\n return { envName: env.name, data: [] };\n }\n });\n\n const responses = await Promise.all(promises);\n responses.forEach(({ envName, data }) => {\n results.set(envName, data);\n });\n\n return results;\n }\n\n // Lazy loading methods for feature details\n async getFeatureVersions(\n environmentId: number,\n featureId: number,\n ): Promise<FlagsmithFeatureVersion[]> {\n const baseUrl = await this.getBaseUrl();\n const response = await this.fetchApi.fetch(\n `${baseUrl}/environments/${environmentId}/features/${featureId}/versions/`,\n );\n\n if (!response.ok) {\n throw new Error(\n `Failed to fetch feature versions: ${response.statusText}`,\n );\n }\n\n const data = await response.json();\n return data.results || data;\n }\n\n async getFeatureStates(\n environmentId: number,\n featureId: number,\n versionUuid: string,\n ): Promise<FlagsmithFeatureState[]> {\n const baseUrl = await this.getBaseUrl();\n const response = await this.fetchApi.fetch(\n `${baseUrl}/environments/${environmentId}/features/${featureId}/versions/${versionUuid}/featurestates/`,\n );\n\n if (!response.ok) {\n throw new Error(`Failed to fetch feature states: ${response.statusText}`);\n }\n\n return await response.json();\n }\n\n // Helper to load full feature details (called on accordion expand)\n async getFeatureDetails(\n environmentId: number,\n featureId: number,\n ): Promise<FlagsmithFeatureDetails> {\n const versions = await this.getFeatureVersions(environmentId, featureId);\n const liveVersion = versions.find(v => v.is_live) || null;\n\n // Find next scheduled version (future live_from date, not yet live)\n // If multiple versions are scheduled, pick the earliest one\n const now = new Date();\n const scheduledVersions = versions\n .filter(v => !v.is_live && v.live_from && new Date(v.live_from) > now)\n .sort((a, b) => new Date(a.live_from!).getTime() - new Date(b.live_from!).getTime());\n const scheduledVersion = scheduledVersions[0] || null;\n\n let featureState: FlagsmithFeatureState[] | null = null;\n let segmentOverrides = 0;\n\n if (liveVersion) {\n featureState = await this.getFeatureStates(\n environmentId,\n featureId,\n liveVersion.uuid,\n );\n segmentOverrides = (featureState || []).filter(\n s => s.feature_segment !== null,\n ).length;\n }\n\n return {\n liveVersion,\n featureState,\n segmentOverrides,\n scheduledVersion,\n };\n }\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"FlagsmithClient.esm.js","sources":["../../src/api/FlagsmithClient.ts"],"sourcesContent":["import { DiscoveryApi, FetchApi } from '@backstage/core-plugin-api';\n\nexport interface FlagsmithOrganization {\n id: number;\n name: string;\n created_date: string;\n}\n\nexport interface FlagsmithProject {\n id: number;\n name: string;\n organisation: number;\n created_date: string;\n}\n\nexport interface FlagsmithTag {\n id: number;\n label: string;\n color?: string;\n}\n\nexport interface FlagsmithEnvironment {\n id: number;\n name: string;\n api_key: string;\n project: number;\n use_v2_feature_versioning?: boolean;\n}\n\nexport interface FlagsmithFeature {\n id: number;\n name: string;\n description?: string;\n created_date: string;\n project: number;\n environment_state?: Array<{\n id: number;\n enabled: boolean;\n feature_segment?: number | null;\n }> | null;\n num_segment_overrides?: number | null;\n num_identity_overrides?: number | null;\n live_version?: {\n is_live: boolean;\n live_from?: string | null;\n published: boolean;\n published_by?: string | null;\n uuid?: string;\n } | null;\n owners?: Array<{\n id: number;\n name: string;\n email: string;\n }>;\n group_owners?: Array<{\n id: number;\n name: string;\n }>;\n created_by?: {\n id: number;\n email: string;\n first_name?: string;\n last_name?: string;\n } | null;\n tags?: Array<number>;\n is_server_key_only?: boolean;\n type?: string;\n default_enabled?: boolean;\n is_archived?: boolean;\n initial_value?: string | null;\n multivariate_options?: Array<{\n id: number;\n type: string;\n integer_value?: number | null;\n string_value?: string | null;\n boolean_value?: boolean | null;\n default_percentage_allocation: number;\n }>;\n}\n\nexport interface FlagsmithFeatureVersion {\n uuid: string;\n is_live: boolean;\n live_from?: string | null;\n published: boolean;\n published_by?: string | null;\n}\n\nexport interface FlagsmithFeatureStateValue {\n string_value?: string | null;\n integer_value?: number | null;\n boolean_value?: boolean | null;\n}\n\nexport interface FlagsmithFeatureSegment {\n segment: number;\n priority: number;\n}\n\nexport interface FlagsmithFeatureState {\n id: number;\n enabled: boolean;\n environment?: number;\n feature_segment?: FlagsmithFeatureSegment | null;\n feature_state_value?: FlagsmithFeatureStateValue | null;\n updated_at?: string | null;\n}\n\nexport interface FlagsmithFeatureDetails {\n liveVersion: FlagsmithFeatureVersion | null;\n featureState: FlagsmithFeatureState[] | null;\n segmentOverrides: number;\n scheduledVersion: FlagsmithFeatureVersion | null;\n}\n\nexport interface FlagsmithUsageData {\n flags: number | null;\n identities: number;\n traits: number;\n environment_document: number;\n day: string;\n labels: {\n client_application_name: string | null;\n client_application_version: string | null;\n user_agent: string | null;\n };\n}\n\nexport class FlagsmithClient {\n constructor(\n private readonly discoveryApi: DiscoveryApi,\n private readonly fetchApi: FetchApi,\n ) {}\n\n private async getBaseUrl(): Promise<string> {\n const proxyUrl = await this.discoveryApi.getBaseUrl('proxy');\n return `${proxyUrl}/flagsmith`;\n }\n\n async getOrganizations(): Promise<FlagsmithOrganization[]> {\n const baseUrl = await this.getBaseUrl();\n const response = await this.fetchApi.fetch(`${baseUrl}/organisations/`);\n\n if (!response.ok) {\n throw new Error(`Failed to fetch organizations: ${response.statusText}`);\n }\n\n const data = await response.json();\n return data.results || data;\n }\n\n async getProjectsInOrg(orgId: number): Promise<FlagsmithProject[]> {\n const baseUrl = await this.getBaseUrl();\n const response = await this.fetchApi.fetch(\n `${baseUrl}/organisations/${orgId}/projects/`,\n );\n\n if (!response.ok) {\n throw new Error(`Failed to fetch projects: ${response.statusText}`);\n }\n\n const data = await response.json();\n return data.results || data;\n }\n\n async getProjectFeatures(projectId: string): Promise<FlagsmithFeature[]> {\n const baseUrl = await this.getBaseUrl();\n const response = await this.fetchApi.fetch(\n `${baseUrl}/projects/${projectId}/features/`,\n );\n\n if (!response.ok) {\n throw new Error(`Failed to fetch features: ${response.statusText}`);\n }\n\n const data = await response.json();\n return data.results || data;\n }\n\n async getProjectEnvironments(\n projectId: number,\n ): Promise<FlagsmithEnvironment[]> {\n const baseUrl = await this.getBaseUrl();\n const response = await this.fetchApi.fetch(\n `${baseUrl}/projects/${projectId}/environments/`,\n );\n\n if (!response.ok) {\n throw new Error(`Failed to fetch environments: ${response.statusText}`);\n }\n\n const data = await response.json();\n return data.results || data;\n }\n\n async getProject(projectId: number): Promise<FlagsmithProject> {\n const baseUrl = await this.getBaseUrl();\n const response = await this.fetchApi.fetch(\n `${baseUrl}/projects/${projectId}/`,\n );\n\n if (!response.ok) {\n throw new Error(`Failed to fetch project: ${response.statusText}`);\n }\n\n return await response.json();\n }\n\n async getProjectTags(projectId: string): Promise<FlagsmithTag[]> {\n const baseUrl = await this.getBaseUrl();\n const response = await this.fetchApi.fetch(\n `${baseUrl}/projects/${projectId}/tags/`,\n );\n\n if (!response.ok) {\n throw new Error(`Failed to fetch project tags: ${response.statusText}`);\n }\n\n const data = await response.json();\n return data.results || data;\n }\n\n async getUsageData(\n orgId: number,\n projectId?: number,\n environmentId?: number,\n ): Promise<FlagsmithUsageData[]> {\n const baseUrl = await this.getBaseUrl();\n const url = new URL(`${baseUrl}/organisations/${orgId}/usage-data/`);\n if (projectId) {\n url.searchParams.set('project_id', projectId.toString());\n }\n if (environmentId) {\n url.searchParams.set('environment_id', environmentId.toString());\n }\n\n const response = await this.fetchApi.fetch(url.toString());\n\n if (!response.ok) {\n throw new Error(`Failed to fetch usage data: ${response.statusText}`);\n }\n\n return await response.json();\n }\n\n /**\n * Fetch usage data for multiple environments in parallel\n */\n async getUsageDataByEnvironments(\n orgId: number,\n projectId: number,\n environments: Pick<FlagsmithEnvironment, 'id' | 'name'>[],\n ): Promise<Map<string, FlagsmithUsageData[]>> {\n const results = new Map<string, FlagsmithUsageData[]>();\n\n // Fetch usage data for each environment in parallel\n const promises = environments.map(async env => {\n try {\n const data = await this.getUsageData(orgId, projectId, env.id);\n return { envName: env.name, data };\n } catch {\n // If environment-level filtering isn't supported, return empty\n return { envName: env.name, data: [] };\n }\n });\n\n const responses = await Promise.all(promises);\n responses.forEach(({ envName, data }) => {\n results.set(envName, data);\n });\n\n return results;\n }\n\n // Lazy loading methods for feature details\n async getFeatureVersions(\n environmentId: number,\n featureId: number,\n ): Promise<FlagsmithFeatureVersion[]> {\n const baseUrl = await this.getBaseUrl();\n const response = await this.fetchApi.fetch(\n `${baseUrl}/environments/${environmentId}/features/${featureId}/versions/`,\n );\n\n if (!response.ok) {\n throw new Error(\n `Failed to fetch feature versions: ${response.statusText}`,\n );\n }\n\n const data = await response.json();\n return data.results || data;\n }\n\n async getFeatureStates(\n environmentId: number,\n featureId: number,\n versionUuid: string,\n ): Promise<FlagsmithFeatureState[]> {\n const baseUrl = await this.getBaseUrl();\n const response = await this.fetchApi.fetch(\n `${baseUrl}/environments/${environmentId}/features/${featureId}/versions/${versionUuid}/featurestates/`,\n );\n\n if (!response.ok) {\n throw new Error(`Failed to fetch feature states: ${response.statusText}`);\n }\n\n return await response.json();\n }\n\n // Helper to load full feature details (called on accordion expand)\n async getFeatureDetails(\n environmentId: number,\n featureId: number,\n ): Promise<FlagsmithFeatureDetails> {\n const versions = await this.getFeatureVersions(environmentId, featureId);\n const liveVersion = versions.find(v => v.is_live) || null;\n\n // Find next scheduled version (future live_from date, not yet live)\n // If multiple versions are scheduled, pick the earliest one\n const now = new Date();\n const scheduledVersions = versions\n .filter(v => !v.is_live && v.live_from && new Date(v.live_from) > now)\n .sort((a, b) => new Date(a.live_from!).getTime() - new Date(b.live_from!).getTime());\n const scheduledVersion = scheduledVersions[0] || null;\n\n let featureState: FlagsmithFeatureState[] | null = null;\n let segmentOverrides = 0;\n\n if (liveVersion) {\n featureState = await this.getFeatureStates(\n environmentId,\n featureId,\n liveVersion.uuid,\n );\n segmentOverrides = (featureState || []).filter(\n s => s.feature_segment !== null,\n ).length;\n }\n\n return {\n liveVersion,\n featureState,\n segmentOverrides,\n scheduledVersion,\n };\n }\n}\n"],"names":[],"mappings":"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"}
@@ -10,6 +10,7 @@ import { FlagsmithLink } from '../shared/FlagsmithLink.esm.js';
10
10
  import '@material-ui/icons/ChevronLeft';
11
11
  import '@material-ui/icons/ChevronRight';
12
12
  import '../shared/ChartTooltip.esm.js';
13
+ import { TagChip } from '../shared/TagChip.esm.js';
13
14
  import { buildFlagUrl } from '../../theme/flagsmithTheme.esm.js';
14
15
  import { switchOnStyle } from '../../theme/sharedStyles.esm.js';
15
16
  import { MAX_TABLE_ENVIRONMENTS, MAX_DISPLAY_TAGS, DESCRIPTION_TRUNCATE_LENGTH } from '../../constants/index.esm.js';
@@ -57,7 +58,7 @@ const useStyles = makeStyles((theme) => ({
57
58
  const FIXED_COLUMNS_COUNT = 3;
58
59
  const TRAILING_COLUMNS_COUNT = 1;
59
60
  const ExpandableRow = memo(
60
- ({ feature, environments, client, projectId, orgId }) => {
61
+ ({ feature, environments, tagMap, client, projectId, orgId }) => {
61
62
  const classes = useStyles();
62
63
  const [open, setOpen] = useState(false);
63
64
  const [details, setDetails] = useState(null);
@@ -124,16 +125,7 @@ const ExpandableRow = memo(
124
125
  feature.description && /* @__PURE__ */ jsx(Typography, { variant: "body2", color: "textSecondary", children: truncateText(feature.description, DESCRIPTION_TRUNCATE_LENGTH) })
125
126
  ] }),
126
127
  /* @__PURE__ */ jsx(TableCell, { className: classes.tagsCell, children: /* @__PURE__ */ jsxs(Box, { className: classes.tagsContainer, children: [
127
- displayTags.map((tag, index) => /* @__PURE__ */ jsx(
128
- Chip,
129
- {
130
- label: tag,
131
- size: "small",
132
- variant: "outlined",
133
- className: classes.tagChip
134
- },
135
- index
136
- )),
128
+ displayTags.map((tagId, index) => /* @__PURE__ */ jsx(TagChip, { tagId, tagMap }, index)),
137
129
  remainingTagsCount > 0 && /* @__PURE__ */ jsx(
138
130
  Chip,
139
131
  {
@@ -187,6 +179,7 @@ const ExpandableRow = memo(
187
179
  FeatureDetailsGrid,
188
180
  {
189
181
  feature,
182
+ tagMap,
190
183
  liveVersion,
191
184
  segmentOverrides,
192
185
  scheduledVersion
@@ -1 +1 @@
1
- {"version":3,"file":"ExpandableRow.esm.js","sources":["../../../src/components/FlagsTab/ExpandableRow.tsx"],"sourcesContent":["import { useState, memo } from 'react';\nimport {\n Typography,\n Box,\n CircularProgress,\n Grid,\n TableCell,\n TableRow,\n IconButton,\n Collapse,\n Chip,\n Switch,\n} from '@material-ui/core';\nimport { makeStyles } from '@material-ui/core/styles';\nimport KeyboardArrowDown from '@material-ui/icons/KeyboardArrowDown';\nimport KeyboardArrowRight from '@material-ui/icons/KeyboardArrowRight';\nimport {\n FlagsmithClient,\n FlagsmithEnvironment,\n FlagsmithFeature,\n FlagsmithFeatureDetails,\n} from '../../api/FlagsmithClient';\nimport { FlagsmithLink } from '../shared';\nimport { buildFlagUrl } from '../../theme/flagsmithTheme';\nimport { switchOnStyle } from '../../theme/sharedStyles';\nimport {\n MAX_DISPLAY_TAGS,\n MAX_TABLE_ENVIRONMENTS,\n DESCRIPTION_TRUNCATE_LENGTH,\n} from '../../constants';\nimport { truncateText, getErrorMessage } from '../../utils/flagTypeHelpers';\nimport { formatDate } from '../../utils/dateFormatters';\nimport { EnvironmentTable } from './EnvironmentTable';\nimport { FeatureAnalyticsSection } from './FeatureAnalyticsSection';\nimport { FeatureDetailsGrid } from './FeatureDetailsGrid';\nimport { SegmentOverridesSection } from './SegmentOverridesSection';\n\nconst useStyles = makeStyles(theme => ({\n flagName: {\n display: 'flex',\n alignItems: 'center',\n gap: theme.spacing(0.5),\n },\n expandedContent: {\n // No backgroundColor - inherit from parent table\n },\n expandedCell: {\n paddingBottom: 0,\n paddingTop: 0,\n },\n clickableRow: {\n cursor: 'pointer',\n },\n tagChip: {\n fontSize: '0.7rem',\n height: 20,\n marginRight: theme.spacing(0.5),\n },\n tagsCell: {\n maxWidth: 200,\n },\n switchOn: switchOnStyle,\n loadingText: {\n marginLeft: theme.spacing(1),\n },\n tagsContainer: {\n display: 'flex',\n flexWrap: 'wrap',\n gap: 2,\n },\n}));\n\n/** Number of fixed columns before environment columns (checkbox, name, tags) */\nconst FIXED_COLUMNS_COUNT = 3;\n/** Number of fixed columns after environment columns (created date) */\nconst TRAILING_COLUMNS_COUNT = 1;\n\ninterface ExpandableRowProps {\n feature: FlagsmithFeature;\n environments: FlagsmithEnvironment[];\n client: FlagsmithClient;\n projectId: string;\n orgId: number;\n}\n\nexport const ExpandableRow = memo(\n ({ feature, environments, client, projectId, orgId }: ExpandableRowProps) => {\n const classes = useStyles();\n const [open, setOpen] = useState(false);\n const [details, setDetails] = useState<FlagsmithFeatureDetails | null>(null);\n const [loadingDetails, setLoadingDetails] = useState(false);\n const [detailsError, setDetailsError] = useState<string | null>(null);\n\n const primaryEnvId = environments[0]?.id;\n\n const handleToggle = async () => {\n const newOpen = !open;\n setOpen(newOpen);\n\n if (newOpen && !details && !loadingDetails && primaryEnvId) {\n setLoadingDetails(true);\n setDetailsError(null);\n try {\n const featureDetails = await client.getFeatureDetails(\n primaryEnvId,\n feature.id,\n );\n setDetails(featureDetails);\n } catch (err) {\n setDetailsError(getErrorMessage(err, 'Failed to load details'));\n } finally {\n setLoadingDetails(false);\n }\n }\n };\n\n const liveVersion = details?.liveVersion || feature.live_version;\n const scheduledVersion = details?.scheduledVersion || null;\n const segmentOverrides =\n details?.segmentOverrides ?? feature.num_segment_overrides ?? 0;\n const flagUrl = buildFlagUrl(\n projectId,\n primaryEnvId?.toString() || '',\n feature.id,\n );\n\n const displayedEnvs = environments.slice(0, MAX_TABLE_ENVIRONMENTS);\n const tags = feature.tags || [];\n const displayTags = tags.slice(0, MAX_DISPLAY_TAGS);\n const remainingTagsCount = tags.length - MAX_DISPLAY_TAGS;\n const totalColumns =\n FIXED_COLUMNS_COUNT + displayedEnvs.length + TRAILING_COLUMNS_COUNT;\n\n return (\n <>\n <TableRow hover className={classes.clickableRow} onClick={handleToggle}>\n <TableCell padding=\"checkbox\">\n <IconButton\n size=\"small\"\n onClick={e => {\n e.stopPropagation();\n handleToggle();\n }}\n aria-label={open ? `Collapse ${feature.name}` : `Expand ${feature.name}`}\n aria-expanded={open}\n >\n {open ? <KeyboardArrowDown /> : <KeyboardArrowRight />}\n </IconButton>\n </TableCell>\n <TableCell>\n <Box className={classes.flagName}>\n <FlagsmithLink\n href={flagUrl}\n tooltip=\"Open in Flagsmith\"\n onClick={e => e.stopPropagation()}\n >\n <Typography variant=\"subtitle2\">{feature.name}</Typography>\n </FlagsmithLink>\n </Box>\n {feature.description && (\n <Typography variant=\"body2\" color=\"textSecondary\">\n {truncateText(feature.description, DESCRIPTION_TRUNCATE_LENGTH)}\n </Typography>\n )}\n </TableCell>\n <TableCell className={classes.tagsCell}>\n <Box className={classes.tagsContainer}>\n {displayTags.map((tag, index) => (\n <Chip\n key={index}\n label={tag}\n size=\"small\"\n variant=\"outlined\"\n className={classes.tagChip}\n />\n ))}\n {remainingTagsCount > 0 && (\n <Chip\n label={`+${remainingTagsCount}`}\n size=\"small\"\n variant=\"outlined\"\n className={classes.tagChip}\n />\n )}\n </Box>\n </TableCell>\n {displayedEnvs.map(env => {\n const envState = feature.environment_state?.find(s => s.id === env.id);\n const enabled = envState?.enabled ?? feature.default_enabled ?? false;\n return (\n <TableCell key={env.id} align=\"center\">\n <Switch\n checked={enabled}\n size=\"small\"\n disabled\n className={classes.switchOn}\n />\n </TableCell>\n );\n })}\n <TableCell>\n <Typography variant=\"body2\">\n {formatDate(feature.created_date)}\n </Typography>\n </TableCell>\n </TableRow>\n\n <TableRow>\n <TableCell className={classes.expandedCell} colSpan={totalColumns}>\n <Collapse in={open} timeout=\"auto\" unmountOnExit>\n <Box className={classes.expandedContent} p={2}>\n {loadingDetails && (\n <Box display=\"flex\" alignItems=\"center\" p={2}>\n <CircularProgress size={20} />\n <Typography\n variant=\"body2\"\n color=\"textSecondary\"\n className={classes.loadingText}\n >\n Loading feature details...\n </Typography>\n </Box>\n )}\n {!loadingDetails && detailsError && (\n <Typography color=\"error\" variant=\"body2\">\n {detailsError}\n </Typography>\n )}\n {!loadingDetails && !detailsError && (\n <Grid container spacing={2}>\n <Grid item xs={12}>\n <FeatureAnalyticsSection\n client={client}\n orgId={orgId}\n projectId={parseInt(projectId, 10)}\n environments={environments}\n />\n </Grid>\n\n <FeatureDetailsGrid\n feature={feature}\n liveVersion={liveVersion}\n segmentOverrides={segmentOverrides}\n scheduledVersion={scheduledVersion}\n />\n\n <Grid item xs={12}>\n <EnvironmentTable\n feature={feature}\n environments={environments}\n />\n </Grid>\n\n <Grid item xs={12}>\n <SegmentOverridesSection\n feature={feature}\n details={details}\n liveVersion={liveVersion}\n />\n </Grid>\n </Grid>\n )}\n </Box>\n </Collapse>\n </TableCell>\n </TableRow>\n </>\n );\n },\n);\n\nExpandableRow.displayName = 'ExpandableRow';\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ExpandableRow.esm.js","sources":["../../../src/components/FlagsTab/ExpandableRow.tsx"],"sourcesContent":["import { useState, memo } from 'react';\nimport {\n Typography,\n Box,\n CircularProgress,\n Grid,\n TableCell,\n TableRow,\n IconButton,\n Collapse,\n Chip,\n Switch,\n} from '@material-ui/core';\nimport { makeStyles } from '@material-ui/core/styles';\nimport KeyboardArrowDown from '@material-ui/icons/KeyboardArrowDown';\nimport KeyboardArrowRight from '@material-ui/icons/KeyboardArrowRight';\nimport {\n FlagsmithClient,\n FlagsmithEnvironment,\n FlagsmithFeature,\n FlagsmithFeatureDetails,\n FlagsmithTag,\n} from '../../api/FlagsmithClient';\nimport { FlagsmithLink, TagChip } from '../shared';\nimport { buildFlagUrl } from '../../theme/flagsmithTheme';\nimport { switchOnStyle } from '../../theme/sharedStyles';\nimport {\n MAX_DISPLAY_TAGS,\n MAX_TABLE_ENVIRONMENTS,\n DESCRIPTION_TRUNCATE_LENGTH,\n} from '../../constants';\nimport { truncateText, getErrorMessage } from '../../utils/flagTypeHelpers';\nimport { formatDate } from '../../utils/dateFormatters';\nimport { EnvironmentTable } from './EnvironmentTable';\nimport { FeatureAnalyticsSection } from './FeatureAnalyticsSection';\nimport { FeatureDetailsGrid } from './FeatureDetailsGrid';\nimport { SegmentOverridesSection } from './SegmentOverridesSection';\n\nconst useStyles = makeStyles(theme => ({\n flagName: {\n display: 'flex',\n alignItems: 'center',\n gap: theme.spacing(0.5),\n },\n expandedContent: {\n // No backgroundColor - inherit from parent table\n },\n expandedCell: {\n paddingBottom: 0,\n paddingTop: 0,\n },\n clickableRow: {\n cursor: 'pointer',\n },\n tagChip: {\n fontSize: '0.7rem',\n height: 20,\n marginRight: theme.spacing(0.5),\n },\n tagsCell: {\n maxWidth: 200,\n },\n switchOn: switchOnStyle,\n loadingText: {\n marginLeft: theme.spacing(1),\n },\n tagsContainer: {\n display: 'flex',\n flexWrap: 'wrap',\n gap: 2,\n },\n}));\n\n/** Number of fixed columns before environment columns (checkbox, name, tags) */\nconst FIXED_COLUMNS_COUNT = 3;\n/** Number of fixed columns after environment columns (created date) */\nconst TRAILING_COLUMNS_COUNT = 1;\n\ninterface ExpandableRowProps {\n feature: FlagsmithFeature;\n environments: FlagsmithEnvironment[];\n tagMap: Map<number, FlagsmithTag>;\n client: FlagsmithClient;\n projectId: string;\n orgId: number;\n}\n\nexport const ExpandableRow = memo(\n ({ feature, environments, tagMap, client, projectId, orgId }: ExpandableRowProps) => {\n const classes = useStyles();\n const [open, setOpen] = useState(false);\n const [details, setDetails] = useState<FlagsmithFeatureDetails | null>(null);\n const [loadingDetails, setLoadingDetails] = useState(false);\n const [detailsError, setDetailsError] = useState<string | null>(null);\n\n const primaryEnvId = environments[0]?.id;\n\n const handleToggle = async () => {\n const newOpen = !open;\n setOpen(newOpen);\n\n if (newOpen && !details && !loadingDetails && primaryEnvId) {\n setLoadingDetails(true);\n setDetailsError(null);\n try {\n const featureDetails = await client.getFeatureDetails(\n primaryEnvId,\n feature.id,\n );\n setDetails(featureDetails);\n } catch (err) {\n setDetailsError(getErrorMessage(err, 'Failed to load details'));\n } finally {\n setLoadingDetails(false);\n }\n }\n };\n\n const liveVersion = details?.liveVersion || feature.live_version;\n const scheduledVersion = details?.scheduledVersion || null;\n const segmentOverrides =\n details?.segmentOverrides ?? feature.num_segment_overrides ?? 0;\n const flagUrl = buildFlagUrl(\n projectId,\n primaryEnvId?.toString() || '',\n feature.id,\n );\n\n const displayedEnvs = environments.slice(0, MAX_TABLE_ENVIRONMENTS);\n const tags = feature.tags || [];\n const displayTags = tags.slice(0, MAX_DISPLAY_TAGS);\n const remainingTagsCount = tags.length - MAX_DISPLAY_TAGS;\n const totalColumns =\n FIXED_COLUMNS_COUNT + displayedEnvs.length + TRAILING_COLUMNS_COUNT;\n\n return (\n <>\n <TableRow hover className={classes.clickableRow} onClick={handleToggle}>\n <TableCell padding=\"checkbox\">\n <IconButton\n size=\"small\"\n onClick={e => {\n e.stopPropagation();\n handleToggle();\n }}\n aria-label={open ? `Collapse ${feature.name}` : `Expand ${feature.name}`}\n aria-expanded={open}\n >\n {open ? <KeyboardArrowDown /> : <KeyboardArrowRight />}\n </IconButton>\n </TableCell>\n <TableCell>\n <Box className={classes.flagName}>\n <FlagsmithLink\n href={flagUrl}\n tooltip=\"Open in Flagsmith\"\n onClick={e => e.stopPropagation()}\n >\n <Typography variant=\"subtitle2\">{feature.name}</Typography>\n </FlagsmithLink>\n </Box>\n {feature.description && (\n <Typography variant=\"body2\" color=\"textSecondary\">\n {truncateText(feature.description, DESCRIPTION_TRUNCATE_LENGTH)}\n </Typography>\n )}\n </TableCell>\n <TableCell className={classes.tagsCell}>\n <Box className={classes.tagsContainer}>\n {displayTags.map((tagId, index) => (\n <TagChip key={index} tagId={tagId} tagMap={tagMap} />\n ))}\n {remainingTagsCount > 0 && (\n <Chip\n label={`+${remainingTagsCount}`}\n size=\"small\"\n variant=\"outlined\"\n className={classes.tagChip}\n />\n )}\n </Box>\n </TableCell>\n {displayedEnvs.map(env => {\n const envState = feature.environment_state?.find(s => s.id === env.id);\n const enabled = envState?.enabled ?? feature.default_enabled ?? false;\n return (\n <TableCell key={env.id} align=\"center\">\n <Switch\n checked={enabled}\n size=\"small\"\n disabled\n className={classes.switchOn}\n />\n </TableCell>\n );\n })}\n <TableCell>\n <Typography variant=\"body2\">\n {formatDate(feature.created_date)}\n </Typography>\n </TableCell>\n </TableRow>\n\n <TableRow>\n <TableCell className={classes.expandedCell} colSpan={totalColumns}>\n <Collapse in={open} timeout=\"auto\" unmountOnExit>\n <Box className={classes.expandedContent} p={2}>\n {loadingDetails && (\n <Box display=\"flex\" alignItems=\"center\" p={2}>\n <CircularProgress size={20} />\n <Typography\n variant=\"body2\"\n color=\"textSecondary\"\n className={classes.loadingText}\n >\n Loading feature details...\n </Typography>\n </Box>\n )}\n {!loadingDetails && detailsError && (\n <Typography color=\"error\" variant=\"body2\">\n {detailsError}\n </Typography>\n )}\n {!loadingDetails && !detailsError && (\n <Grid container spacing={2}>\n <Grid item xs={12}>\n <FeatureAnalyticsSection\n client={client}\n orgId={orgId}\n projectId={parseInt(projectId, 10)}\n environments={environments}\n />\n </Grid>\n\n <FeatureDetailsGrid\n feature={feature}\n tagMap={tagMap}\n liveVersion={liveVersion}\n segmentOverrides={segmentOverrides}\n scheduledVersion={scheduledVersion}\n />\n\n <Grid item xs={12}>\n <EnvironmentTable\n feature={feature}\n environments={environments}\n />\n </Grid>\n\n <Grid item xs={12}>\n <SegmentOverridesSection\n feature={feature}\n details={details}\n liveVersion={liveVersion}\n />\n </Grid>\n </Grid>\n )}\n </Box>\n </Collapse>\n </TableCell>\n </TableRow>\n </>\n );\n },\n);\n\nExpandableRow.displayName = 'ExpandableRow';\n"],"names":[],"mappings":"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"}
@@ -12,6 +12,7 @@ import '../shared/FlagsmithLink.esm.js';
12
12
  import '@material-ui/icons/ChevronLeft';
13
13
  import '@material-ui/icons/ChevronRight';
14
14
  import { ChartTooltip, ChartTooltipText } from '../shared/ChartTooltip.esm.js';
15
+ import '../shared/TagChip.esm.js';
15
16
 
16
17
  const useStyles = makeStyles((theme) => ({
17
18
  container: {
@@ -1 +1 @@
1
- {"version":3,"file":"FeatureAnalyticsSection.esm.js","sources":["../../../src/components/FlagsTab/FeatureAnalyticsSection.tsx"],"sourcesContent":["import { useState, useEffect } from 'react';\nimport { Box, CircularProgress, Typography } from '@material-ui/core';\nimport { makeStyles } from '@material-ui/core/styles';\nimport {\n LineChart,\n Line,\n XAxis,\n YAxis,\n CartesianGrid,\n Tooltip,\n Legend,\n ResponsiveContainer,\n} from 'recharts';\nimport {\n FlagsmithClient,\n FlagsmithEnvironment,\n FlagsmithUsageData,\n} from '../../api/FlagsmithClient';\nimport {\n CHART_CONFIG,\n MAX_TABLE_ENVIRONMENTS,\n getEnvColor,\n} from '../../constants';\nimport { getErrorMessage } from '../../utils/flagTypeHelpers';\nimport { formatShortDate } from '../../utils/dateFormatters';\nimport { ChartTooltip, ChartTooltipText } from '../shared';\n\nconst useStyles = makeStyles(theme => ({\n container: {\n padding: theme.spacing(2),\n border: `1px solid ${theme.palette.divider}`,\n borderRadius: theme.shape.borderRadius,\n backgroundColor: theme.palette.background.paper,\n },\n chartContainer: {\n width: '100%',\n height: CHART_CONFIG.HEIGHT,\n marginTop: theme.spacing(1),\n },\n noData: {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n height: 150,\n color: theme.palette.text.secondary,\n },\n loading: {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n gap: theme.spacing(1),\n height: 150,\n },\n}));\n\ninterface ChartDataPoint {\n date: string;\n [envName: string]: number | string;\n}\n\n/**\n * Custom tooltip component for analytics chart\n */\nconst AnalyticsTooltip = ({ active, payload, label }: any) => {\n return (\n <ChartTooltip active={active} payload={payload} label={label}>\n {(data, tooltipLabel) => (\n <>\n <ChartTooltipText variant=\"subtitle2\" fontWeight={600}>\n {tooltipLabel}\n </ChartTooltipText>\n <Box mt={1}>\n {data.map((entry: any, index: number) => (\n <Box\n key={`item-${index}`}\n display=\"flex\"\n alignItems=\"center\"\n mt={0.25}\n style={{ gap: '4px' }}\n >\n <span\n style={{\n display: 'inline-block',\n width: '8px',\n height: '8px',\n backgroundColor: entry.color,\n borderRadius: '50%',\n }}\n />\n <ChartTooltipText>\n {entry.name}: {entry.value}\n </ChartTooltipText>\n </Box>\n ))}\n </Box>\n </>\n )}\n </ChartTooltip>\n );\n};\n\ninterface FeatureAnalyticsSectionProps {\n client: FlagsmithClient;\n orgId: number;\n projectId: number;\n environments: FlagsmithEnvironment[];\n}\n\n/**\n * Transform usage data by environment into chart-friendly format\n */\nconst transformUsageData = (\n usageByEnv: Map<string, FlagsmithUsageData[]>,\n): { chartData: ChartDataPoint[]; envNames: string[] } => {\n const dataByDate = new Map<string, ChartDataPoint>();\n const envNames: string[] = [];\n\n usageByEnv.forEach((data: FlagsmithUsageData[], envName: string) => {\n envNames.push(envName);\n data.forEach(item => {\n const date = formatShortDate(item.day);\n if (!dataByDate.has(date)) {\n dataByDate.set(date, { date });\n }\n const point = dataByDate.get(date)!;\n point[envName] = item.flags ?? 0;\n });\n });\n\n const sortedData = Array.from(dataByDate.values()).sort((a, b) => {\n const dateA = new Date(a.date);\n const dateB = new Date(b.date);\n return dateA.getTime() - dateB.getTime();\n });\n\n return { chartData: sortedData, envNames };\n};\n\nexport const FeatureAnalyticsSection = ({\n client,\n orgId,\n projectId,\n environments,\n}: FeatureAnalyticsSectionProps) => {\n const classes = useStyles();\n const [loading, setLoading] = useState(true);\n const [chartData, setChartData] = useState<ChartDataPoint[]>([]);\n const [envNames, setEnvNames] = useState<string[]>([]);\n const [error, setError] = useState<string | null>(null);\n\n useEffect(() => {\n const fetchUsageData = async () => {\n if (!orgId || !projectId || environments.length === 0) {\n setLoading(false);\n return;\n }\n\n try {\n setLoading(true);\n setError(null);\n\n const displayedEnvs = environments.slice(0, MAX_TABLE_ENVIRONMENTS);\n\n const usageByEnv = await client.getUsageDataByEnvironments(\n orgId,\n projectId,\n displayedEnvs,\n );\n\n const { chartData: data, envNames: names } = transformUsageData(usageByEnv);\n setChartData(data);\n setEnvNames(names);\n } catch (err) {\n setError(getErrorMessage(err, 'Failed to load analytics'));\n } finally {\n setLoading(false);\n }\n };\n\n fetchUsageData();\n }, [client, orgId, projectId, environments]);\n\n if (loading) {\n return (\n <Box className={classes.container}>\n <Typography variant=\"subtitle2\" gutterBottom>\n Usage Analytics\n </Typography>\n <Box className={classes.loading}>\n <CircularProgress size={20} />\n <Typography variant=\"body2\" color=\"textSecondary\">\n Loading analytics...\n </Typography>\n </Box>\n </Box>\n );\n }\n\n if (error) {\n return (\n <Box className={classes.container}>\n <Typography variant=\"subtitle2\" gutterBottom>\n Usage Analytics\n </Typography>\n <Box className={classes.noData}>\n <Typography variant=\"body2\" color=\"error\">\n {error}\n </Typography>\n </Box>\n </Box>\n );\n }\n\n if (chartData.length === 0) {\n return null;\n }\n\n return (\n <Box className={classes.container}>\n <Typography variant=\"subtitle2\" gutterBottom>\n Usage Analytics (Last 30 Days)\n </Typography>\n <Box className={classes.chartContainer}>\n <ResponsiveContainer width=\"100%\" height=\"100%\">\n <LineChart data={chartData} margin={CHART_CONFIG.MARGIN}>\n <CartesianGrid strokeDasharray=\"3 3\" />\n <XAxis dataKey=\"date\" fontSize={12} />\n <YAxis fontSize={12} />\n <Tooltip content={<AnalyticsTooltip />} />\n <Legend />\n {envNames.map((envName, index) => (\n <Line\n key={envName}\n type=\"monotone\"\n dataKey={envName}\n stroke={getEnvColor(envName, index)}\n strokeWidth={2}\n dot={false}\n activeDot={{ r: 4 }}\n />\n ))}\n </LineChart>\n </ResponsiveContainer>\n </Box>\n </Box>\n );\n};\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"FeatureAnalyticsSection.esm.js","sources":["../../../src/components/FlagsTab/FeatureAnalyticsSection.tsx"],"sourcesContent":["import { useState, useEffect } from 'react';\nimport { Box, CircularProgress, Typography } from '@material-ui/core';\nimport { makeStyles } from '@material-ui/core/styles';\nimport {\n LineChart,\n Line,\n XAxis,\n YAxis,\n CartesianGrid,\n Tooltip,\n Legend,\n ResponsiveContainer,\n} from 'recharts';\nimport {\n FlagsmithClient,\n FlagsmithEnvironment,\n FlagsmithUsageData,\n} from '../../api/FlagsmithClient';\nimport {\n CHART_CONFIG,\n MAX_TABLE_ENVIRONMENTS,\n getEnvColor,\n} from '../../constants';\nimport { getErrorMessage } from '../../utils/flagTypeHelpers';\nimport { formatShortDate } from '../../utils/dateFormatters';\nimport { ChartTooltip, ChartTooltipText } from '../shared';\n\nconst useStyles = makeStyles(theme => ({\n container: {\n padding: theme.spacing(2),\n border: `1px solid ${theme.palette.divider}`,\n borderRadius: theme.shape.borderRadius,\n backgroundColor: theme.palette.background.paper,\n },\n chartContainer: {\n width: '100%',\n height: CHART_CONFIG.HEIGHT,\n marginTop: theme.spacing(1),\n },\n noData: {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n height: 150,\n color: theme.palette.text.secondary,\n },\n loading: {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n gap: theme.spacing(1),\n height: 150,\n },\n}));\n\ninterface ChartDataPoint {\n date: string;\n [envName: string]: number | string;\n}\n\n/**\n * Custom tooltip component for analytics chart\n */\nconst AnalyticsTooltip = ({ active, payload, label }: any) => {\n return (\n <ChartTooltip active={active} payload={payload} label={label}>\n {(data, tooltipLabel) => (\n <>\n <ChartTooltipText variant=\"subtitle2\" fontWeight={600}>\n {tooltipLabel}\n </ChartTooltipText>\n <Box mt={1}>\n {data.map((entry: any, index: number) => (\n <Box\n key={`item-${index}`}\n display=\"flex\"\n alignItems=\"center\"\n mt={0.25}\n style={{ gap: '4px' }}\n >\n <span\n style={{\n display: 'inline-block',\n width: '8px',\n height: '8px',\n backgroundColor: entry.color,\n borderRadius: '50%',\n }}\n />\n <ChartTooltipText>\n {entry.name}: {entry.value}\n </ChartTooltipText>\n </Box>\n ))}\n </Box>\n </>\n )}\n </ChartTooltip>\n );\n};\n\ninterface FeatureAnalyticsSectionProps {\n client: FlagsmithClient;\n orgId: number;\n projectId: number;\n environments: FlagsmithEnvironment[];\n}\n\n/**\n * Transform usage data by environment into chart-friendly format\n */\nconst transformUsageData = (\n usageByEnv: Map<string, FlagsmithUsageData[]>,\n): { chartData: ChartDataPoint[]; envNames: string[] } => {\n const dataByDate = new Map<string, ChartDataPoint>();\n const envNames: string[] = [];\n\n usageByEnv.forEach((data: FlagsmithUsageData[], envName: string) => {\n envNames.push(envName);\n data.forEach(item => {\n const date = formatShortDate(item.day);\n if (!dataByDate.has(date)) {\n dataByDate.set(date, { date });\n }\n const point = dataByDate.get(date)!;\n point[envName] = item.flags ?? 0;\n });\n });\n\n const sortedData = Array.from(dataByDate.values()).sort((a, b) => {\n const dateA = new Date(a.date);\n const dateB = new Date(b.date);\n return dateA.getTime() - dateB.getTime();\n });\n\n return { chartData: sortedData, envNames };\n};\n\nexport const FeatureAnalyticsSection = ({\n client,\n orgId,\n projectId,\n environments,\n}: FeatureAnalyticsSectionProps) => {\n const classes = useStyles();\n const [loading, setLoading] = useState(true);\n const [chartData, setChartData] = useState<ChartDataPoint[]>([]);\n const [envNames, setEnvNames] = useState<string[]>([]);\n const [error, setError] = useState<string | null>(null);\n\n useEffect(() => {\n const fetchUsageData = async () => {\n if (!orgId || !projectId || environments.length === 0) {\n setLoading(false);\n return;\n }\n\n try {\n setLoading(true);\n setError(null);\n\n const displayedEnvs = environments.slice(0, MAX_TABLE_ENVIRONMENTS);\n\n const usageByEnv = await client.getUsageDataByEnvironments(\n orgId,\n projectId,\n displayedEnvs,\n );\n\n const { chartData: data, envNames: names } = transformUsageData(usageByEnv);\n setChartData(data);\n setEnvNames(names);\n } catch (err) {\n setError(getErrorMessage(err, 'Failed to load analytics'));\n } finally {\n setLoading(false);\n }\n };\n\n fetchUsageData();\n }, [client, orgId, projectId, environments]);\n\n if (loading) {\n return (\n <Box className={classes.container}>\n <Typography variant=\"subtitle2\" gutterBottom>\n Usage Analytics\n </Typography>\n <Box className={classes.loading}>\n <CircularProgress size={20} />\n <Typography variant=\"body2\" color=\"textSecondary\">\n Loading analytics...\n </Typography>\n </Box>\n </Box>\n );\n }\n\n if (error) {\n return (\n <Box className={classes.container}>\n <Typography variant=\"subtitle2\" gutterBottom>\n Usage Analytics\n </Typography>\n <Box className={classes.noData}>\n <Typography variant=\"body2\" color=\"error\">\n {error}\n </Typography>\n </Box>\n </Box>\n );\n }\n\n if (chartData.length === 0) {\n return null;\n }\n\n return (\n <Box className={classes.container}>\n <Typography variant=\"subtitle2\" gutterBottom>\n Usage Analytics (Last 30 Days)\n </Typography>\n <Box className={classes.chartContainer}>\n <ResponsiveContainer width=\"100%\" height=\"100%\">\n <LineChart data={chartData} margin={CHART_CONFIG.MARGIN}>\n <CartesianGrid strokeDasharray=\"3 3\" />\n <XAxis dataKey=\"date\" fontSize={12} />\n <YAxis fontSize={12} />\n <Tooltip content={<AnalyticsTooltip />} />\n <Legend />\n {envNames.map((envName, index) => (\n <Line\n key={envName}\n type=\"monotone\"\n dataKey={envName}\n stroke={getEnvColor(envName, index)}\n strokeWidth={2}\n dot={false}\n activeDot={{ r: 4 }}\n />\n ))}\n </LineChart>\n </ResponsiveContainer>\n </Box>\n </Box>\n );\n};\n"],"names":[],"mappings":"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"}
@@ -4,6 +4,13 @@ import { makeStyles } from '@material-ui/core/styles';
4
4
  import ArchiveIcon from '@material-ui/icons/Archive';
5
5
  import ScheduleIcon from '@material-ui/icons/Schedule';
6
6
  import VpnKeyIcon from '@material-ui/icons/VpnKey';
7
+ import '../shared/FlagStatusIndicator.esm.js';
8
+ import '../shared/SearchInput.esm.js';
9
+ import '../shared/FlagsmithLink.esm.js';
10
+ import '@material-ui/icons/ChevronLeft';
11
+ import '@material-ui/icons/ChevronRight';
12
+ import '../shared/ChartTooltip.esm.js';
13
+ import { TagChip } from '../shared/TagChip.esm.js';
7
14
  import { flagsmithColors } from '../../theme/flagsmithTheme.esm.js';
8
15
  import { detailCardStyle } from '../../theme/sharedStyles.esm.js';
9
16
  import { getFlagType, getValueType, isDefined } from '../../utils/flagTypeHelpers.esm.js';
@@ -55,6 +62,7 @@ const getCreatorDisplayName = (feature) => {
55
62
  };
56
63
  const FeatureDetailsGrid = ({
57
64
  feature,
65
+ tagMap,
58
66
  liveVersion,
59
67
  segmentOverrides,
60
68
  scheduledVersion
@@ -151,7 +159,7 @@ const FeatureDetailsGrid = ({
151
159
  ] }) }),
152
160
  feature.tags && feature.tags.length > 0 && /* @__PURE__ */ jsxs(Grid, { item: true, xs: 12, children: [
153
161
  /* @__PURE__ */ jsx(Typography, { variant: "subtitle2", gutterBottom: true, children: "Tags" }),
154
- /* @__PURE__ */ jsx(Box, { className: classes.tagsContainer, children: feature.tags.map((tag, index) => /* @__PURE__ */ jsx(Chip, { label: tag, size: "small", variant: "outlined" }, index)) })
162
+ /* @__PURE__ */ jsx(Box, { className: classes.tagsContainer, children: feature.tags.map((tagId, index) => /* @__PURE__ */ jsx(TagChip, { tagId, tagMap }, index)) })
155
163
  ] })
156
164
  ] });
157
165
  };
@@ -1 +1 @@
1
- {"version":3,"file":"FeatureDetailsGrid.esm.js","sources":["../../../src/components/FlagsTab/FeatureDetailsGrid.tsx"],"sourcesContent":["import { Box, Chip, Grid, Typography } from '@material-ui/core';\nimport { makeStyles } from '@material-ui/core/styles';\nimport ArchiveIcon from '@material-ui/icons/Archive';\nimport ScheduleIcon from '@material-ui/icons/Schedule';\nimport VpnKeyIcon from '@material-ui/icons/VpnKey';\nimport { FlagsmithFeature, FlagsmithFeatureVersion } from '../../api/FlagsmithClient';\nimport { flagsmithColors } from '../../theme/flagsmithTheme';\nimport { detailCardStyle } from '../../theme/sharedStyles';\nimport { getFlagType, getValueType, isDefined } from '../../utils/flagTypeHelpers';\nimport { formatDate, formatDateTime } from '../../utils/dateFormatters';\n\nconst useStyles = makeStyles(theme => ({\n detailCard: detailCardStyle(theme),\n badgeChip: {\n marginRight: theme.spacing(0.5),\n marginTop: theme.spacing(0.5),\n },\n archivedChip: {\n backgroundColor: theme.palette.warning.light,\n color: theme.palette.warning.contrastText,\n },\n serverKeyChip: {\n backgroundColor: flagsmithColors.secondary,\n color: 'white',\n },\n scheduledCard: {\n padding: theme.spacing(1.5),\n marginBottom: theme.spacing(1),\n border: `1px solid ${theme.palette.warning.main}`,\n borderRadius: theme.shape.borderRadius,\n backgroundColor: `${theme.palette.warning.light}20`,\n },\n scheduledHeader: {\n display: 'flex',\n alignItems: 'center',\n gap: theme.spacing(0.5),\n color: theme.palette.warning.dark,\n },\n scheduleIcon: {\n fontSize: '1.2rem',\n color: theme.palette.warning.main,\n },\n tagsContainer: {\n display: 'flex',\n flexWrap: 'wrap',\n gap: 4,\n },\n}));\n\ntype LiveVersionInfo = FlagsmithFeature['live_version'];\n\ninterface FeatureDetailsGridProps {\n feature: FlagsmithFeature;\n liveVersion: LiveVersionInfo;\n segmentOverrides: number;\n scheduledVersion?: FlagsmithFeatureVersion | null;\n}\n\n/**\n * Get display name for the feature creator\n */\nconst getCreatorDisplayName = (feature: FlagsmithFeature): string => {\n if (!feature.created_by) return 'Unknown';\n const { email, first_name, last_name } = feature.created_by;\n if (email) return email;\n const fullName = `${first_name || ''} ${last_name || ''}`.trim();\n return fullName || 'Unknown';\n};\n\nexport const FeatureDetailsGrid = ({\n feature,\n liveVersion,\n segmentOverrides,\n scheduledVersion,\n}: FeatureDetailsGridProps) => {\n const classes = useStyles();\n\n const flagType = getFlagType(feature);\n const valueType = getValueType(feature);\n\n return (\n <>\n {/* Status badges row */}\n {(feature.is_server_key_only || feature.is_archived) && (\n <Grid item xs={12}>\n <Box display=\"flex\" flexWrap=\"wrap\">\n {feature.is_server_key_only && (\n <Chip\n icon={<VpnKeyIcon />}\n label=\"Server-side Only\"\n size=\"small\"\n className={`${classes.badgeChip} ${classes.serverKeyChip}`}\n />\n )}\n {feature.is_archived && (\n <Chip\n icon={<ArchiveIcon />}\n label=\"Archived\"\n size=\"small\"\n className={`${classes.badgeChip} ${classes.archivedChip}`}\n />\n )}\n </Box>\n </Grid>\n )}\n\n {/* Scheduled changes card */}\n {scheduledVersion && scheduledVersion.live_from && (\n <Grid item xs={12} md={4}>\n <Box className={classes.scheduledCard}>\n <Box className={classes.scheduledHeader}>\n <ScheduleIcon className={classes.scheduleIcon} />\n <Typography variant=\"subtitle2\">Scheduled Change</Typography>\n </Box>\n <Typography variant=\"body2\">\n Scheduled for: {formatDateTime(scheduledVersion.live_from)}\n </Typography>\n {scheduledVersion.published_by && (\n <Typography variant=\"body2\" color=\"textSecondary\">\n By: {scheduledVersion.published_by}\n </Typography>\n )}\n </Box>\n </Grid>\n )}\n\n {/* Version card */}\n {liveVersion && (\n <Grid item xs={12} md={4}>\n <Box className={classes.detailCard}>\n <Typography variant=\"subtitle2\" gutterBottom>\n Version\n </Typography>\n <Typography variant=\"body2\">\n Status: {liveVersion.is_live ? 'Active' : 'Inactive'}\n </Typography>\n {liveVersion.live_from && (\n <Typography variant=\"body2\">\n Live since: {formatDate(liveVersion.live_from)}\n </Typography>\n )}\n </Box>\n </Grid>\n )}\n\n {/* Targeting card */}\n <Grid item xs={12} md={4}>\n <Box className={classes.detailCard}>\n <Typography variant=\"subtitle2\" gutterBottom>\n Targeting\n </Typography>\n <Typography variant=\"body2\">\n Segment overrides: {segmentOverrides}\n </Typography>\n {isDefined(feature.num_identity_overrides) && (\n <Typography variant=\"body2\">\n Identity overrides: {feature.num_identity_overrides}\n </Typography>\n )}\n </Box>\n </Grid>\n\n {/* Details card */}\n <Grid item xs={12} md={4}>\n <Box className={classes.detailCard}>\n <Typography variant=\"subtitle2\" gutterBottom>\n Details\n </Typography>\n <Typography variant=\"body2\">ID: {feature.id}</Typography>\n <Typography variant=\"body2\">Flag Type: {flagType}</Typography>\n <Typography variant=\"body2\">Value Type: {valueType}</Typography>\n </Box>\n </Grid>\n\n {/* Ownership card */}\n <Grid item xs={12} md={4}>\n <Box className={classes.detailCard}>\n <Typography variant=\"subtitle2\" gutterBottom>\n Ownership\n </Typography>\n {feature.created_by && (\n <Typography variant=\"body2\">\n Creator: {getCreatorDisplayName(feature)}\n </Typography>\n )}\n {feature.owners && feature.owners.length > 0 ? (\n <Typography variant=\"body2\">\n Assigned Users: {feature.owners.map(o => o.email || o.name).join(', ')}\n </Typography>\n ) : (\n <Typography variant=\"body2\" color=\"textSecondary\">\n No assigned users\n </Typography>\n )}\n {feature.group_owners && feature.group_owners.length > 0 && (\n <Typography variant=\"body2\">\n Groups: {feature.group_owners.map(g => g.name).join(', ')}\n </Typography>\n )}\n </Box>\n </Grid>\n\n {/* Tags */}\n {feature.tags && feature.tags.length > 0 && (\n <Grid item xs={12}>\n <Typography variant=\"subtitle2\" gutterBottom>\n Tags\n </Typography>\n <Box className={classes.tagsContainer}>\n {feature.tags.map((tag, index) => (\n <Chip key={index} label={tag} size=\"small\" variant=\"outlined\" />\n ))}\n </Box>\n </Grid>\n )}\n </>\n );\n};\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"FeatureDetailsGrid.esm.js","sources":["../../../src/components/FlagsTab/FeatureDetailsGrid.tsx"],"sourcesContent":["import { Box, Chip, Grid, Typography } from '@material-ui/core';\nimport { makeStyles } from '@material-ui/core/styles';\nimport ArchiveIcon from '@material-ui/icons/Archive';\nimport ScheduleIcon from '@material-ui/icons/Schedule';\nimport VpnKeyIcon from '@material-ui/icons/VpnKey';\nimport { FlagsmithFeature, FlagsmithFeatureVersion, FlagsmithTag } from '../../api/FlagsmithClient';\nimport { TagChip } from '../shared';\nimport { flagsmithColors } from '../../theme/flagsmithTheme';\nimport { detailCardStyle } from '../../theme/sharedStyles';\nimport { getFlagType, getValueType, isDefined } from '../../utils/flagTypeHelpers';\nimport { formatDate, formatDateTime } from '../../utils/dateFormatters';\n\nconst useStyles = makeStyles(theme => ({\n detailCard: detailCardStyle(theme),\n badgeChip: {\n marginRight: theme.spacing(0.5),\n marginTop: theme.spacing(0.5),\n },\n archivedChip: {\n backgroundColor: theme.palette.warning.light,\n color: theme.palette.warning.contrastText,\n },\n serverKeyChip: {\n backgroundColor: flagsmithColors.secondary,\n color: 'white',\n },\n scheduledCard: {\n padding: theme.spacing(1.5),\n marginBottom: theme.spacing(1),\n border: `1px solid ${theme.palette.warning.main}`,\n borderRadius: theme.shape.borderRadius,\n backgroundColor: `${theme.palette.warning.light}20`,\n },\n scheduledHeader: {\n display: 'flex',\n alignItems: 'center',\n gap: theme.spacing(0.5),\n color: theme.palette.warning.dark,\n },\n scheduleIcon: {\n fontSize: '1.2rem',\n color: theme.palette.warning.main,\n },\n tagsContainer: {\n display: 'flex',\n flexWrap: 'wrap',\n gap: 4,\n },\n}));\n\ntype LiveVersionInfo = FlagsmithFeature['live_version'];\n\ninterface FeatureDetailsGridProps {\n feature: FlagsmithFeature;\n tagMap: Map<number, FlagsmithTag>;\n liveVersion: LiveVersionInfo;\n segmentOverrides: number;\n scheduledVersion?: FlagsmithFeatureVersion | null;\n}\n\n/**\n * Get display name for the feature creator\n */\nconst getCreatorDisplayName = (feature: FlagsmithFeature): string => {\n if (!feature.created_by) return 'Unknown';\n const { email, first_name, last_name } = feature.created_by;\n if (email) return email;\n const fullName = `${first_name || ''} ${last_name || ''}`.trim();\n return fullName || 'Unknown';\n};\n\nexport const FeatureDetailsGrid = ({\n feature,\n tagMap,\n liveVersion,\n segmentOverrides,\n scheduledVersion,\n}: FeatureDetailsGridProps) => {\n const classes = useStyles();\n\n const flagType = getFlagType(feature);\n const valueType = getValueType(feature);\n\n return (\n <>\n {/* Status badges row */}\n {(feature.is_server_key_only || feature.is_archived) && (\n <Grid item xs={12}>\n <Box display=\"flex\" flexWrap=\"wrap\">\n {feature.is_server_key_only && (\n <Chip\n icon={<VpnKeyIcon />}\n label=\"Server-side Only\"\n size=\"small\"\n className={`${classes.badgeChip} ${classes.serverKeyChip}`}\n />\n )}\n {feature.is_archived && (\n <Chip\n icon={<ArchiveIcon />}\n label=\"Archived\"\n size=\"small\"\n className={`${classes.badgeChip} ${classes.archivedChip}`}\n />\n )}\n </Box>\n </Grid>\n )}\n\n {/* Scheduled changes card */}\n {scheduledVersion && scheduledVersion.live_from && (\n <Grid item xs={12} md={4}>\n <Box className={classes.scheduledCard}>\n <Box className={classes.scheduledHeader}>\n <ScheduleIcon className={classes.scheduleIcon} />\n <Typography variant=\"subtitle2\">Scheduled Change</Typography>\n </Box>\n <Typography variant=\"body2\">\n Scheduled for: {formatDateTime(scheduledVersion.live_from)}\n </Typography>\n {scheduledVersion.published_by && (\n <Typography variant=\"body2\" color=\"textSecondary\">\n By: {scheduledVersion.published_by}\n </Typography>\n )}\n </Box>\n </Grid>\n )}\n\n {/* Version card */}\n {liveVersion && (\n <Grid item xs={12} md={4}>\n <Box className={classes.detailCard}>\n <Typography variant=\"subtitle2\" gutterBottom>\n Version\n </Typography>\n <Typography variant=\"body2\">\n Status: {liveVersion.is_live ? 'Active' : 'Inactive'}\n </Typography>\n {liveVersion.live_from && (\n <Typography variant=\"body2\">\n Live since: {formatDate(liveVersion.live_from)}\n </Typography>\n )}\n </Box>\n </Grid>\n )}\n\n {/* Targeting card */}\n <Grid item xs={12} md={4}>\n <Box className={classes.detailCard}>\n <Typography variant=\"subtitle2\" gutterBottom>\n Targeting\n </Typography>\n <Typography variant=\"body2\">\n Segment overrides: {segmentOverrides}\n </Typography>\n {isDefined(feature.num_identity_overrides) && (\n <Typography variant=\"body2\">\n Identity overrides: {feature.num_identity_overrides}\n </Typography>\n )}\n </Box>\n </Grid>\n\n {/* Details card */}\n <Grid item xs={12} md={4}>\n <Box className={classes.detailCard}>\n <Typography variant=\"subtitle2\" gutterBottom>\n Details\n </Typography>\n <Typography variant=\"body2\">ID: {feature.id}</Typography>\n <Typography variant=\"body2\">Flag Type: {flagType}</Typography>\n <Typography variant=\"body2\">Value Type: {valueType}</Typography>\n </Box>\n </Grid>\n\n {/* Ownership card */}\n <Grid item xs={12} md={4}>\n <Box className={classes.detailCard}>\n <Typography variant=\"subtitle2\" gutterBottom>\n Ownership\n </Typography>\n {feature.created_by && (\n <Typography variant=\"body2\">\n Creator: {getCreatorDisplayName(feature)}\n </Typography>\n )}\n {feature.owners && feature.owners.length > 0 ? (\n <Typography variant=\"body2\">\n Assigned Users: {feature.owners.map(o => o.email || o.name).join(', ')}\n </Typography>\n ) : (\n <Typography variant=\"body2\" color=\"textSecondary\">\n No assigned users\n </Typography>\n )}\n {feature.group_owners && feature.group_owners.length > 0 && (\n <Typography variant=\"body2\">\n Groups: {feature.group_owners.map(g => g.name).join(', ')}\n </Typography>\n )}\n </Box>\n </Grid>\n\n {/* Tags */}\n {feature.tags && feature.tags.length > 0 && (\n <Grid item xs={12}>\n <Typography variant=\"subtitle2\" gutterBottom>\n Tags\n </Typography>\n <Box className={classes.tagsContainer}>\n {feature.tags.map((tagId, index) => (\n <TagChip key={index} tagId={tagId} tagMap={tagMap} />\n ))}\n </Box>\n </Grid>\n )}\n </>\n );\n};\n"],"names":[],"mappings":"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"}
@@ -10,6 +10,7 @@ import '../shared/FlagsmithLink.esm.js';
10
10
  import '@material-ui/icons/ChevronLeft';
11
11
  import '@material-ui/icons/ChevronRight';
12
12
  import '../shared/ChartTooltip.esm.js';
13
+ import '../shared/TagChip.esm.js';
13
14
  import { flagsmithColors } from '../../theme/flagsmithTheme.esm.js';
14
15
 
15
16
  const useStyles = makeStyles((theme) => ({
@@ -1 +1 @@
1
- {"version":3,"file":"SegmentOverridesSection.esm.js","sources":["../../../src/components/FlagsTab/SegmentOverridesSection.tsx"],"sourcesContent":["import { useState } from 'react';\nimport { Box, Chip, Collapse, Typography } from '@material-ui/core';\nimport { makeStyles } from '@material-ui/core/styles';\nimport KeyboardArrowDown from '@material-ui/icons/KeyboardArrowDown';\nimport KeyboardArrowRight from '@material-ui/icons/KeyboardArrowRight';\nimport {\n FlagsmithFeature,\n FlagsmithFeatureDetails,\n} from '../../api/FlagsmithClient';\nimport { FlagStatusIndicator } from '../shared';\nimport { flagsmithColors } from '../../theme/flagsmithTheme';\n\nconst useStyles = makeStyles(theme => ({\n showMoreButton: {\n display: 'flex',\n alignItems: 'center',\n gap: theme.spacing(0.5),\n cursor: 'pointer',\n color: theme.palette.primary.main,\n fontSize: '0.875rem',\n marginTop: theme.spacing(1),\n '&:hover': {\n textDecoration: 'underline',\n },\n },\n showMoreContent: {\n marginTop: theme.spacing(1.5),\n padding: theme.spacing(1.5),\n backgroundColor:\n theme.palette.type === 'dark'\n ? 'rgba(255, 255, 255, 0.05)'\n : 'rgba(0, 0, 0, 0.02)',\n borderRadius: theme.shape.borderRadius,\n border: `1px solid ${theme.palette.divider}`,\n },\n featureStateItem: {\n padding: theme.spacing(1),\n marginBottom: theme.spacing(0.5),\n backgroundColor: theme.palette.background.paper,\n borderRadius: theme.shape.borderRadius,\n border: `1px solid ${theme.palette.divider}`,\n },\n segmentBadge: {\n backgroundColor: flagsmithColors.warning,\n color: 'white',\n fontSize: '0.7rem',\n height: 20,\n marginLeft: theme.spacing(1),\n },\n}));\n\ntype LiveVersionInfo = FlagsmithFeature['live_version'];\n\ninterface SegmentOverridesSectionProps {\n feature: FlagsmithFeature;\n details: FlagsmithFeatureDetails | null;\n liveVersion: LiveVersionInfo;\n}\n\nexport const SegmentOverridesSection = ({\n feature,\n details,\n liveVersion,\n}: SegmentOverridesSectionProps) => {\n const classes = useStyles();\n const [showMoreOpen, setShowMoreOpen] = useState(false);\n\n const segmentOverrides =\n details?.featureState?.filter(state => state.feature_segment !== null) ??\n [];\n\n return (\n <>\n <Box\n className={classes.showMoreButton}\n onClick={() => setShowMoreOpen(!showMoreOpen)}\n >\n {showMoreOpen ? (\n <KeyboardArrowDown fontSize=\"small\" />\n ) : (\n <KeyboardArrowRight fontSize=\"small\" />\n )}\n <Typography variant=\"body2\" component=\"span\">\n {showMoreOpen ? 'Hide additional details' : 'Show additional details'}\n </Typography>\n </Box>\n\n <Collapse in={showMoreOpen} timeout=\"auto\">\n <Box className={classes.showMoreContent}>\n <Box mb={1.5}>\n <Typography variant=\"body2\">\n <strong>Published:</strong> {liveVersion?.published ? 'Yes' : 'No'}\n {liveVersion?.published_by && ` (by ${liveVersion.published_by})`}\n </Typography>\n <Typography variant=\"body2\">\n <strong>Archived:</strong> {feature.is_archived ? 'Yes' : 'No'}\n </Typography>\n </Box>\n\n {details?.featureState && details.featureState.length > 0 && (\n <Box>\n <Typography variant=\"subtitle2\" gutterBottom>\n Segment Overrides\n </Typography>\n {segmentOverrides.length === 0 ? (\n <Typography variant=\"body2\" color=\"textSecondary\">\n No segment overrides configured.\n </Typography>\n ) : (\n segmentOverrides.map((state, index) => (\n <Box\n key={state.id || index}\n className={classes.featureStateItem}\n >\n <Box display=\"flex\" alignItems=\"center\">\n <FlagStatusIndicator enabled={state.enabled} size=\"small\" />\n <Typography variant=\"body2\" style={{ marginLeft: 8 }}>\n {state.enabled ? 'Enabled' : 'Disabled'}\n </Typography>\n {state.feature_segment && (\n <Chip\n label={`Segment: ${state.feature_segment.segment} (Priority: ${state.feature_segment.priority})`}\n size=\"small\"\n className={classes.segmentBadge}\n />\n )}\n </Box>\n {state.feature_state_value && (\n <Box mt={0.5} ml={3}>\n {state.feature_state_value.string_value !== null &&\n state.feature_state_value.string_value !==\n undefined && (\n <Typography variant=\"caption\" color=\"textSecondary\">\n Value: \"{state.feature_state_value.string_value}\"\n </Typography>\n )}\n {state.feature_state_value.integer_value !== null &&\n state.feature_state_value.integer_value !==\n undefined && (\n <Typography variant=\"caption\" color=\"textSecondary\">\n Value: {state.feature_state_value.integer_value}\n </Typography>\n )}\n {state.feature_state_value.boolean_value !== null &&\n state.feature_state_value.boolean_value !==\n undefined && (\n <Typography variant=\"caption\" color=\"textSecondary\">\n Value:{' '}\n {String(state.feature_state_value.boolean_value)}\n </Typography>\n )}\n </Box>\n )}\n </Box>\n ))\n )}\n </Box>\n )}\n </Box>\n </Collapse>\n </>\n );\n};\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"SegmentOverridesSection.esm.js","sources":["../../../src/components/FlagsTab/SegmentOverridesSection.tsx"],"sourcesContent":["import { useState } from 'react';\nimport { Box, Chip, Collapse, Typography } from '@material-ui/core';\nimport { makeStyles } from '@material-ui/core/styles';\nimport KeyboardArrowDown from '@material-ui/icons/KeyboardArrowDown';\nimport KeyboardArrowRight from '@material-ui/icons/KeyboardArrowRight';\nimport {\n FlagsmithFeature,\n FlagsmithFeatureDetails,\n} from '../../api/FlagsmithClient';\nimport { FlagStatusIndicator } from '../shared';\nimport { flagsmithColors } from '../../theme/flagsmithTheme';\n\nconst useStyles = makeStyles(theme => ({\n showMoreButton: {\n display: 'flex',\n alignItems: 'center',\n gap: theme.spacing(0.5),\n cursor: 'pointer',\n color: theme.palette.primary.main,\n fontSize: '0.875rem',\n marginTop: theme.spacing(1),\n '&:hover': {\n textDecoration: 'underline',\n },\n },\n showMoreContent: {\n marginTop: theme.spacing(1.5),\n padding: theme.spacing(1.5),\n backgroundColor:\n theme.palette.type === 'dark'\n ? 'rgba(255, 255, 255, 0.05)'\n : 'rgba(0, 0, 0, 0.02)',\n borderRadius: theme.shape.borderRadius,\n border: `1px solid ${theme.palette.divider}`,\n },\n featureStateItem: {\n padding: theme.spacing(1),\n marginBottom: theme.spacing(0.5),\n backgroundColor: theme.palette.background.paper,\n borderRadius: theme.shape.borderRadius,\n border: `1px solid ${theme.palette.divider}`,\n },\n segmentBadge: {\n backgroundColor: flagsmithColors.warning,\n color: 'white',\n fontSize: '0.7rem',\n height: 20,\n marginLeft: theme.spacing(1),\n },\n}));\n\ntype LiveVersionInfo = FlagsmithFeature['live_version'];\n\ninterface SegmentOverridesSectionProps {\n feature: FlagsmithFeature;\n details: FlagsmithFeatureDetails | null;\n liveVersion: LiveVersionInfo;\n}\n\nexport const SegmentOverridesSection = ({\n feature,\n details,\n liveVersion,\n}: SegmentOverridesSectionProps) => {\n const classes = useStyles();\n const [showMoreOpen, setShowMoreOpen] = useState(false);\n\n const segmentOverrides =\n details?.featureState?.filter(state => state.feature_segment !== null) ??\n [];\n\n return (\n <>\n <Box\n className={classes.showMoreButton}\n onClick={() => setShowMoreOpen(!showMoreOpen)}\n >\n {showMoreOpen ? (\n <KeyboardArrowDown fontSize=\"small\" />\n ) : (\n <KeyboardArrowRight fontSize=\"small\" />\n )}\n <Typography variant=\"body2\" component=\"span\">\n {showMoreOpen ? 'Hide additional details' : 'Show additional details'}\n </Typography>\n </Box>\n\n <Collapse in={showMoreOpen} timeout=\"auto\">\n <Box className={classes.showMoreContent}>\n <Box mb={1.5}>\n <Typography variant=\"body2\">\n <strong>Published:</strong> {liveVersion?.published ? 'Yes' : 'No'}\n {liveVersion?.published_by && ` (by ${liveVersion.published_by})`}\n </Typography>\n <Typography variant=\"body2\">\n <strong>Archived:</strong> {feature.is_archived ? 'Yes' : 'No'}\n </Typography>\n </Box>\n\n {details?.featureState && details.featureState.length > 0 && (\n <Box>\n <Typography variant=\"subtitle2\" gutterBottom>\n Segment Overrides\n </Typography>\n {segmentOverrides.length === 0 ? (\n <Typography variant=\"body2\" color=\"textSecondary\">\n No segment overrides configured.\n </Typography>\n ) : (\n segmentOverrides.map((state, index) => (\n <Box\n key={state.id || index}\n className={classes.featureStateItem}\n >\n <Box display=\"flex\" alignItems=\"center\">\n <FlagStatusIndicator enabled={state.enabled} size=\"small\" />\n <Typography variant=\"body2\" style={{ marginLeft: 8 }}>\n {state.enabled ? 'Enabled' : 'Disabled'}\n </Typography>\n {state.feature_segment && (\n <Chip\n label={`Segment: ${state.feature_segment.segment} (Priority: ${state.feature_segment.priority})`}\n size=\"small\"\n className={classes.segmentBadge}\n />\n )}\n </Box>\n {state.feature_state_value && (\n <Box mt={0.5} ml={3}>\n {state.feature_state_value.string_value !== null &&\n state.feature_state_value.string_value !==\n undefined && (\n <Typography variant=\"caption\" color=\"textSecondary\">\n Value: \"{state.feature_state_value.string_value}\"\n </Typography>\n )}\n {state.feature_state_value.integer_value !== null &&\n state.feature_state_value.integer_value !==\n undefined && (\n <Typography variant=\"caption\" color=\"textSecondary\">\n Value: {state.feature_state_value.integer_value}\n </Typography>\n )}\n {state.feature_state_value.boolean_value !== null &&\n state.feature_state_value.boolean_value !==\n undefined && (\n <Typography variant=\"caption\" color=\"textSecondary\">\n Value:{' '}\n {String(state.feature_state_value.boolean_value)}\n </Typography>\n )}\n </Box>\n )}\n </Box>\n ))\n )}\n </Box>\n )}\n </Box>\n </Collapse>\n </>\n );\n};\n"],"names":[],"mappings":"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"}
@@ -11,6 +11,7 @@ import '@material-ui/icons/ChevronRight';
11
11
  import { LoadingState } from '../shared/LoadingState.esm.js';
12
12
  import { ErrorState } from '../shared/ErrorState.esm.js';
13
13
  import '../shared/ChartTooltip.esm.js';
14
+ import '../shared/TagChip.esm.js';
14
15
  import { buildProjectUrl } from '../../theme/flagsmithTheme.esm.js';
15
16
  import { useFlagsmithProject } from '../../hooks/useFlagsmithProject.esm.js';
16
17
  import '@backstage/core-plugin-api';
@@ -39,7 +40,7 @@ const FlagsTab = () => {
39
40
  const [page, setPage] = useState(0);
40
41
  const [rowsPerPage, setRowsPerPage] = useState(DEFAULT_ROWS_PER_PAGE);
41
42
  const projectId = entity.metadata.annotations?.["flagsmith.com/project-id"];
42
- const { project, environments, features, loading, error, client } = useFlagsmithProject(projectId);
43
+ const { project, environments, features, tagMap, loading, error, client } = useFlagsmithProject(projectId);
43
44
  const filteredFeatures = useMemo(() => {
44
45
  if (!searchQuery.trim()) return features;
45
46
  const query = searchQuery.toLowerCase();
@@ -112,6 +113,7 @@ const FlagsTab = () => {
112
113
  {
113
114
  feature,
114
115
  environments,
116
+ tagMap,
115
117
  client,
116
118
  projectId,
117
119
  orgId: project?.organisation || 0
@@ -1 +1 @@
1
- {"version":3,"file":"index.esm.js","sources":["../../../src/components/FlagsTab/index.tsx"],"sourcesContent":["import { useState, useMemo } from 'react';\nimport {\n Typography,\n Box,\n Grid,\n Table,\n TableBody,\n TableCell,\n TableContainer,\n TableHead,\n TableRow,\n TablePagination,\n Paper,\n} from '@material-ui/core';\nimport { makeStyles } from '@material-ui/core/styles';\nimport { useEntity } from '@backstage/plugin-catalog-react';\nimport { SearchInput, FlagsmithLink, LoadingState, ErrorState } from '../shared';\nimport { buildProjectUrl } from '../../theme/flagsmithTheme';\nimport { useFlagsmithProject } from '../../hooks';\nimport {\n MAX_TABLE_ENVIRONMENTS,\n DEFAULT_ROWS_PER_PAGE,\n PAGINATION_OPTIONS,\n} from '../../constants';\nimport { ExpandableRow } from './ExpandableRow';\n\nconst useStyles = makeStyles(theme => ({\n header: {\n marginBottom: theme.spacing(2),\n },\n headerActions: {\n display: 'flex',\n alignItems: 'center',\n gap: theme.spacing(2),\n justifyContent: 'flex-end',\n },\n errorHint: {\n marginTop: theme.spacing(2),\n },\n}));\n\n/** Number of fixed columns (checkbox, name, tags, created) */\nconst FIXED_COLUMNS_COUNT = 4;\n\nexport const FlagsTab = () => {\n const classes = useStyles();\n const { entity } = useEntity();\n const [searchQuery, setSearchQuery] = useState('');\n const [page, setPage] = useState(0);\n const [rowsPerPage, setRowsPerPage] = useState(DEFAULT_ROWS_PER_PAGE);\n\n const projectId = entity.metadata.annotations?.['flagsmith.com/project-id'];\n const { project, environments, features, loading, error, client } =\n useFlagsmithProject(projectId);\n\n const filteredFeatures = useMemo(() => {\n if (!searchQuery.trim()) return features;\n const query = searchQuery.toLowerCase();\n return features.filter(\n f =>\n f.name.toLowerCase().includes(query) ||\n f.description?.toLowerCase().includes(query),\n );\n }, [features, searchQuery]);\n\n const paginatedFeatures = useMemo(() => {\n const startIndex = page * rowsPerPage;\n return filteredFeatures.slice(startIndex, startIndex + rowsPerPage);\n }, [filteredFeatures, page, rowsPerPage]);\n\n const handleChangePage = (_event: unknown, newPage: number) => {\n setPage(newPage);\n };\n\n const handleChangeRowsPerPage = (event: React.ChangeEvent<HTMLInputElement>) => {\n setRowsPerPage(parseInt(event.target.value, 10));\n setPage(0);\n };\n\n const dashboardUrl = buildProjectUrl(\n projectId || '',\n environments[0]?.id?.toString(),\n );\n\n const displayedEnvs = environments.slice(0, MAX_TABLE_ENVIRONMENTS);\n const totalColumns = FIXED_COLUMNS_COUNT + displayedEnvs.length;\n\n if (loading) {\n return <LoadingState message=\"Loading feature flags...\" />;\n }\n\n if (error) {\n return (\n <Box p={3}>\n <ErrorState\n message={error}\n hint={!projectId ? 'Add a flagsmith.com/project-id annotation to this entity to view feature flags.' : undefined}\n />\n </Box>\n );\n }\n\n return (\n <Box p={3}>\n <Grid container spacing={2} alignItems=\"center\" className={classes.header}>\n <Grid item xs={12} md={6}>\n <Typography variant=\"h4\">Feature Flags</Typography>\n <Typography variant=\"body2\" color=\"textSecondary\">\n {project?.name} ({features.length} flags)\n </Typography>\n </Grid>\n <Grid item xs={12} md={6}>\n <Box className={classes.headerActions}>\n <SearchInput\n value={searchQuery}\n onChange={setSearchQuery}\n placeholder=\"Search flags...\"\n />\n <FlagsmithLink href={dashboardUrl} iconOnly tooltip=\"Open Dashboard\" />\n </Box>\n </Grid>\n </Grid>\n\n <TableContainer component={Paper}>\n <Table size=\"small\">\n <TableHead>\n <TableRow>\n <TableCell padding=\"checkbox\" />\n <TableCell>Flag Name</TableCell>\n <TableCell>Tags</TableCell>\n {displayedEnvs.map(env => (\n <TableCell key={env.id} align=\"center\">\n {env.name}\n </TableCell>\n ))}\n <TableCell>Created</TableCell>\n </TableRow>\n </TableHead>\n <TableBody>\n {filteredFeatures.length === 0 ? (\n <TableRow>\n <TableCell colSpan={totalColumns} align=\"center\">\n <Typography color=\"textSecondary\">\n {searchQuery\n ? 'No flags match your search'\n : 'No feature flags found for this project'}\n </Typography>\n </TableCell>\n </TableRow>\n ) : (\n paginatedFeatures.map(feature => (\n <ExpandableRow\n key={feature.id}\n feature={feature}\n environments={environments}\n client={client}\n projectId={projectId!}\n orgId={project?.organisation || 0}\n />\n ))\n )}\n </TableBody>\n </Table>\n </TableContainer>\n <TablePagination\n component=\"div\"\n count={filteredFeatures.length}\n page={page}\n onPageChange={handleChangePage}\n rowsPerPage={rowsPerPage}\n onRowsPerPageChange={handleChangeRowsPerPage}\n rowsPerPageOptions={PAGINATION_OPTIONS}\n />\n </Box>\n );\n};\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.esm.js","sources":["../../../src/components/FlagsTab/index.tsx"],"sourcesContent":["import { useState, useMemo } from 'react';\nimport {\n Typography,\n Box,\n Grid,\n Table,\n TableBody,\n TableCell,\n TableContainer,\n TableHead,\n TableRow,\n TablePagination,\n Paper,\n} from '@material-ui/core';\nimport { makeStyles } from '@material-ui/core/styles';\nimport { useEntity } from '@backstage/plugin-catalog-react';\nimport { SearchInput, FlagsmithLink, LoadingState, ErrorState } from '../shared';\nimport { buildProjectUrl } from '../../theme/flagsmithTheme';\nimport { useFlagsmithProject } from '../../hooks';\nimport {\n MAX_TABLE_ENVIRONMENTS,\n DEFAULT_ROWS_PER_PAGE,\n PAGINATION_OPTIONS,\n} from '../../constants';\nimport { ExpandableRow } from './ExpandableRow';\n\nconst useStyles = makeStyles(theme => ({\n header: {\n marginBottom: theme.spacing(2),\n },\n headerActions: {\n display: 'flex',\n alignItems: 'center',\n gap: theme.spacing(2),\n justifyContent: 'flex-end',\n },\n errorHint: {\n marginTop: theme.spacing(2),\n },\n}));\n\n/** Number of fixed columns (checkbox, name, tags, created) */\nconst FIXED_COLUMNS_COUNT = 4;\n\nexport const FlagsTab = () => {\n const classes = useStyles();\n const { entity } = useEntity();\n const [searchQuery, setSearchQuery] = useState('');\n const [page, setPage] = useState(0);\n const [rowsPerPage, setRowsPerPage] = useState(DEFAULT_ROWS_PER_PAGE);\n\n const projectId = entity.metadata.annotations?.['flagsmith.com/project-id'];\n const { project, environments, features, tagMap, loading, error, client } =\n useFlagsmithProject(projectId);\n\n const filteredFeatures = useMemo(() => {\n if (!searchQuery.trim()) return features;\n const query = searchQuery.toLowerCase();\n return features.filter(\n f =>\n f.name.toLowerCase().includes(query) ||\n f.description?.toLowerCase().includes(query),\n );\n }, [features, searchQuery]);\n\n const paginatedFeatures = useMemo(() => {\n const startIndex = page * rowsPerPage;\n return filteredFeatures.slice(startIndex, startIndex + rowsPerPage);\n }, [filteredFeatures, page, rowsPerPage]);\n\n const handleChangePage = (_event: unknown, newPage: number) => {\n setPage(newPage);\n };\n\n const handleChangeRowsPerPage = (event: React.ChangeEvent<HTMLInputElement>) => {\n setRowsPerPage(parseInt(event.target.value, 10));\n setPage(0);\n };\n\n const dashboardUrl = buildProjectUrl(\n projectId || '',\n environments[0]?.id?.toString(),\n );\n\n const displayedEnvs = environments.slice(0, MAX_TABLE_ENVIRONMENTS);\n const totalColumns = FIXED_COLUMNS_COUNT + displayedEnvs.length;\n\n if (loading) {\n return <LoadingState message=\"Loading feature flags...\" />;\n }\n\n if (error) {\n return (\n <Box p={3}>\n <ErrorState\n message={error}\n hint={!projectId ? 'Add a flagsmith.com/project-id annotation to this entity to view feature flags.' : undefined}\n />\n </Box>\n );\n }\n\n return (\n <Box p={3}>\n <Grid container spacing={2} alignItems=\"center\" className={classes.header}>\n <Grid item xs={12} md={6}>\n <Typography variant=\"h4\">Feature Flags</Typography>\n <Typography variant=\"body2\" color=\"textSecondary\">\n {project?.name} ({features.length} flags)\n </Typography>\n </Grid>\n <Grid item xs={12} md={6}>\n <Box className={classes.headerActions}>\n <SearchInput\n value={searchQuery}\n onChange={setSearchQuery}\n placeholder=\"Search flags...\"\n />\n <FlagsmithLink href={dashboardUrl} iconOnly tooltip=\"Open Dashboard\" />\n </Box>\n </Grid>\n </Grid>\n\n <TableContainer component={Paper}>\n <Table size=\"small\">\n <TableHead>\n <TableRow>\n <TableCell padding=\"checkbox\" />\n <TableCell>Flag Name</TableCell>\n <TableCell>Tags</TableCell>\n {displayedEnvs.map(env => (\n <TableCell key={env.id} align=\"center\">\n {env.name}\n </TableCell>\n ))}\n <TableCell>Created</TableCell>\n </TableRow>\n </TableHead>\n <TableBody>\n {filteredFeatures.length === 0 ? (\n <TableRow>\n <TableCell colSpan={totalColumns} align=\"center\">\n <Typography color=\"textSecondary\">\n {searchQuery\n ? 'No flags match your search'\n : 'No feature flags found for this project'}\n </Typography>\n </TableCell>\n </TableRow>\n ) : (\n paginatedFeatures.map(feature => (\n <ExpandableRow\n key={feature.id}\n feature={feature}\n environments={environments}\n tagMap={tagMap}\n client={client}\n projectId={projectId!}\n orgId={project?.organisation || 0}\n />\n ))\n )}\n </TableBody>\n </Table>\n </TableContainer>\n <TablePagination\n component=\"div\"\n count={filteredFeatures.length}\n page={page}\n onPageChange={handleChangePage}\n rowsPerPage={rowsPerPage}\n onRowsPerPageChange={handleChangeRowsPerPage}\n rowsPerPageOptions={PAGINATION_OPTIONS}\n />\n </Box>\n );\n};\n"],"names":[],"mappings":"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"}
@@ -7,6 +7,7 @@ import '../shared/FlagsmithLink.esm.js';
7
7
  import '@material-ui/icons/ChevronLeft';
8
8
  import '@material-ui/icons/ChevronRight';
9
9
  import '../shared/ChartTooltip.esm.js';
10
+ import '../shared/TagChip.esm.js';
10
11
  import { buildEnvStatusTooltip, getFeatureEnvStatus } from '../../utils/flagHelpers.esm.js';
11
12
 
12
13
  const useStyles = makeStyles(() => ({
@@ -1 +1 @@
1
- {"version":3,"file":"FeatureFlagRow.esm.js","sources":["../../../src/components/FlagsmithOverviewCard/FeatureFlagRow.tsx"],"sourcesContent":["import { Box, TableCell, TableRow, Tooltip, Typography } from '@material-ui/core';\nimport { makeStyles } from '@material-ui/core/styles';\nimport { FlagsmithFeature, FlagsmithEnvironment } from '../../api/FlagsmithClient';\nimport { FlagStatusIndicator } from '../shared';\nimport { getFeatureEnvStatus, buildEnvStatusTooltip } from '../../utils';\n\nconst useStyles = makeStyles(() => ({\n envDots: {\n display: 'flex',\n gap: 2,\n justifyContent: 'flex-end',\n },\n}));\n\ninterface FeatureFlagRowProps {\n feature: FlagsmithFeature;\n environments: FlagsmithEnvironment[];\n}\n\nexport const FeatureFlagRow = ({ feature, environments }: FeatureFlagRowProps) => {\n const classes = useStyles();\n\n return (\n <TableRow hover>\n <TableCell>\n <Typography variant=\"body2\">{feature.name}</Typography>\n {feature.description && (\n <Typography variant=\"caption\" color=\"textSecondary\">\n {feature.description.substring(0, 40)}\n {feature.description.length > 40 ? '...' : ''}\n </Typography>\n )}\n </TableCell>\n <TableCell align=\"right\">\n <Tooltip title={buildEnvStatusTooltip(feature, environments)}>\n <Box className={classes.envDots}>\n {environments.map(env => (\n <FlagStatusIndicator\n key={env.id}\n enabled={getFeatureEnvStatus(feature, env.id)}\n size=\"small\"\n />\n ))}\n </Box>\n </Tooltip>\n </TableCell>\n </TableRow>\n );\n};\n"],"names":[],"mappings":";;;;;;;;;;;AAMA,MAAM,SAAA,GAAY,WAAW,OAAO;AAAA,EAClC,OAAA,EAAS;AAAA,IACP,OAAA,EAAS,MAAA;AAAA,IACT,GAAA,EAAK,CAAA;AAAA,IACL,cAAA,EAAgB;AAAA;AAEpB,CAAA,CAAE,CAAA;AAOK,MAAM,cAAA,GAAiB,CAAC,EAAE,OAAA,EAAS,cAAa,KAA2B;AAChF,EAAA,MAAM,UAAU,SAAA,EAAU;AAE1B,EAAA,uBACE,IAAA,CAAC,QAAA,EAAA,EAAS,KAAA,EAAK,IAAA,EACb,QAAA,EAAA;AAAA,oBAAA,IAAA,CAAC,SAAA,EAAA,EACC,QAAA,EAAA;AAAA,sBAAA,GAAA,CAAC,UAAA,EAAA,EAAW,OAAA,EAAQ,OAAA,EAAS,QAAA,EAAA,OAAA,CAAQ,IAAA,EAAK,CAAA;AAAA,MACzC,QAAQ,WAAA,oBACP,IAAA,CAAC,cAAW,OAAA,EAAQ,SAAA,EAAU,OAAM,eAAA,EACjC,QAAA,EAAA;AAAA,QAAA,OAAA,CAAQ,WAAA,CAAY,SAAA,CAAU,CAAA,EAAG,EAAE,CAAA;AAAA,QACnC,OAAA,CAAQ,WAAA,CAAY,MAAA,GAAS,EAAA,GAAK,KAAA,GAAQ;AAAA,OAAA,EAC7C;AAAA,KAAA,EAEJ,CAAA;AAAA,wBACC,SAAA,EAAA,EAAU,KAAA,EAAM,SACf,QAAA,kBAAA,GAAA,CAAC,OAAA,EAAA,EAAQ,OAAO,qBAAA,CAAsB,OAAA,EAAS,YAAY,CAAA,EACzD,8BAAC,GAAA,EAAA,EAAI,SAAA,EAAW,QAAQ,OAAA,EACrB,QAAA,EAAA,YAAA,CAAa,IAAI,CAAA,GAAA,qBAChB,GAAA;AAAA,MAAC,mBAAA;AAAA,MAAA;AAAA,QAEC,OAAA,EAAS,mBAAA,CAAoB,OAAA,EAAS,GAAA,CAAI,EAAE,CAAA;AAAA,QAC5C,IAAA,EAAK;AAAA,OAAA;AAAA,MAFA,GAAA,CAAI;AAAA,KAIZ,CAAA,EACH,CAAA,EACF,CAAA,EACF;AAAA,GAAA,EACF,CAAA;AAEJ;;;;"}
1
+ {"version":3,"file":"FeatureFlagRow.esm.js","sources":["../../../src/components/FlagsmithOverviewCard/FeatureFlagRow.tsx"],"sourcesContent":["import { Box, TableCell, TableRow, Tooltip, Typography } from '@material-ui/core';\nimport { makeStyles } from '@material-ui/core/styles';\nimport { FlagsmithFeature, FlagsmithEnvironment } from '../../api/FlagsmithClient';\nimport { FlagStatusIndicator } from '../shared';\nimport { getFeatureEnvStatus, buildEnvStatusTooltip } from '../../utils';\n\nconst useStyles = makeStyles(() => ({\n envDots: {\n display: 'flex',\n gap: 2,\n justifyContent: 'flex-end',\n },\n}));\n\ninterface FeatureFlagRowProps {\n feature: FlagsmithFeature;\n environments: FlagsmithEnvironment[];\n}\n\nexport const FeatureFlagRow = ({ feature, environments }: FeatureFlagRowProps) => {\n const classes = useStyles();\n\n return (\n <TableRow hover>\n <TableCell>\n <Typography variant=\"body2\">{feature.name}</Typography>\n {feature.description && (\n <Typography variant=\"caption\" color=\"textSecondary\">\n {feature.description.substring(0, 40)}\n {feature.description.length > 40 ? '...' : ''}\n </Typography>\n )}\n </TableCell>\n <TableCell align=\"right\">\n <Tooltip title={buildEnvStatusTooltip(feature, environments)}>\n <Box className={classes.envDots}>\n {environments.map(env => (\n <FlagStatusIndicator\n key={env.id}\n enabled={getFeatureEnvStatus(feature, env.id)}\n size=\"small\"\n />\n ))}\n </Box>\n </Tooltip>\n </TableCell>\n </TableRow>\n );\n};\n"],"names":[],"mappings":";;;;;;;;;;;;AAMA,MAAM,SAAA,GAAY,WAAW,OAAO;AAAA,EAClC,OAAA,EAAS;AAAA,IACP,OAAA,EAAS,MAAA;AAAA,IACT,GAAA,EAAK,CAAA;AAAA,IACL,cAAA,EAAgB;AAAA;AAEpB,CAAA,CAAE,CAAA;AAOK,MAAM,cAAA,GAAiB,CAAC,EAAE,OAAA,EAAS,cAAa,KAA2B;AAChF,EAAA,MAAM,UAAU,SAAA,EAAU;AAE1B,EAAA,uBACE,IAAA,CAAC,QAAA,EAAA,EAAS,KAAA,EAAK,IAAA,EACb,QAAA,EAAA;AAAA,oBAAA,IAAA,CAAC,SAAA,EAAA,EACC,QAAA,EAAA;AAAA,sBAAA,GAAA,CAAC,UAAA,EAAA,EAAW,OAAA,EAAQ,OAAA,EAAS,QAAA,EAAA,OAAA,CAAQ,IAAA,EAAK,CAAA;AAAA,MACzC,QAAQ,WAAA,oBACP,IAAA,CAAC,cAAW,OAAA,EAAQ,SAAA,EAAU,OAAM,eAAA,EACjC,QAAA,EAAA;AAAA,QAAA,OAAA,CAAQ,WAAA,CAAY,SAAA,CAAU,CAAA,EAAG,EAAE,CAAA;AAAA,QACnC,OAAA,CAAQ,WAAA,CAAY,MAAA,GAAS,EAAA,GAAK,KAAA,GAAQ;AAAA,OAAA,EAC7C;AAAA,KAAA,EAEJ,CAAA;AAAA,wBACC,SAAA,EAAA,EAAU,KAAA,EAAM,SACf,QAAA,kBAAA,GAAA,CAAC,OAAA,EAAA,EAAQ,OAAO,qBAAA,CAAsB,OAAA,EAAS,YAAY,CAAA,EACzD,8BAAC,GAAA,EAAA,EAAI,SAAA,EAAW,QAAQ,OAAA,EACrB,QAAA,EAAA,YAAA,CAAa,IAAI,CAAA,GAAA,qBAChB,GAAA;AAAA,MAAC,mBAAA;AAAA,MAAA;AAAA,QAEC,OAAA,EAAS,mBAAA,CAAoB,OAAA,EAAS,GAAA,CAAI,EAAE,CAAA;AAAA,QAC5C,IAAA,EAAK;AAAA,OAAA;AAAA,MAFA,GAAA,CAAI;AAAA,KAIZ,CAAA,EACH,CAAA,EACF,CAAA,EACF;AAAA,GAAA,EACF,CAAA;AAEJ;;;;"}
@@ -7,6 +7,7 @@ import '../shared/FlagsmithLink.esm.js';
7
7
  import '@material-ui/icons/ChevronLeft';
8
8
  import '@material-ui/icons/ChevronRight';
9
9
  import '../shared/ChartTooltip.esm.js';
10
+ import '../shared/TagChip.esm.js';
10
11
 
11
12
  const useStyles = makeStyles((theme) => ({
12
13
  statsRow: {
@@ -1 +1 @@
1
- {"version":3,"file":"FlagStatsRow.esm.js","sources":["../../../src/components/FlagsmithOverviewCard/FlagStatsRow.tsx"],"sourcesContent":["import { Box, Typography } from '@material-ui/core';\nimport { makeStyles } from '@material-ui/core/styles';\nimport { FlagStatusIndicator } from '../shared';\n\nconst useStyles = makeStyles(theme => ({\n statsRow: {\n display: 'flex',\n alignItems: 'center',\n gap: theme.spacing(2),\n marginBottom: theme.spacing(1),\n fontSize: '0.75rem',\n },\n statItem: {\n display: 'flex',\n alignItems: 'center',\n gap: theme.spacing(0.5),\n },\n}));\n\ninterface FlagStatsRowProps {\n enabledCount: number;\n disabledCount: number;\n}\n\nexport const FlagStatsRow = ({ enabledCount, disabledCount }: FlagStatsRowProps) => {\n const classes = useStyles();\n\n return (\n <Box px={2} pt={1}>\n <Box className={classes.statsRow}>\n <Box className={classes.statItem}>\n <FlagStatusIndicator enabled size=\"small\" />\n <Typography variant=\"caption\">{enabledCount} Enabled</Typography>\n </Box>\n <Box className={classes.statItem}>\n <FlagStatusIndicator enabled={false} size=\"small\" />\n <Typography variant=\"caption\">{disabledCount} Disabled</Typography>\n </Box>\n </Box>\n </Box>\n );\n};\n"],"names":[],"mappings":";;;;;;;;;;AAIA,MAAM,SAAA,GAAY,WAAW,CAAA,KAAA,MAAU;AAAA,EACrC,QAAA,EAAU;AAAA,IACR,OAAA,EAAS,MAAA;AAAA,IACT,UAAA,EAAY,QAAA;AAAA,IACZ,GAAA,EAAK,KAAA,CAAM,OAAA,CAAQ,CAAC,CAAA;AAAA,IACpB,YAAA,EAAc,KAAA,CAAM,OAAA,CAAQ,CAAC,CAAA;AAAA,IAC7B,QAAA,EAAU;AAAA,GACZ;AAAA,EACA,QAAA,EAAU;AAAA,IACR,OAAA,EAAS,MAAA;AAAA,IACT,UAAA,EAAY,QAAA;AAAA,IACZ,GAAA,EAAK,KAAA,CAAM,OAAA,CAAQ,GAAG;AAAA;AAE1B,CAAA,CAAE,CAAA;AAOK,MAAM,YAAA,GAAe,CAAC,EAAE,YAAA,EAAc,eAAc,KAAyB;AAClF,EAAA,MAAM,UAAU,SAAA,EAAU;AAE1B,EAAA,uBACE,GAAA,CAAC,GAAA,EAAA,EAAI,EAAA,EAAI,CAAA,EAAG,EAAA,EAAI,GACd,QAAA,kBAAA,IAAA,CAAC,GAAA,EAAA,EAAI,SAAA,EAAW,OAAA,CAAQ,QAAA,EACtB,QAAA,EAAA;AAAA,oBAAA,IAAA,CAAC,GAAA,EAAA,EAAI,SAAA,EAAW,OAAA,CAAQ,QAAA,EACtB,QAAA,EAAA;AAAA,sBAAA,GAAA,CAAC,mBAAA,EAAA,EAAoB,OAAA,EAAO,IAAA,EAAC,IAAA,EAAK,OAAA,EAAQ,CAAA;AAAA,sBAC1C,IAAA,CAAC,UAAA,EAAA,EAAW,OAAA,EAAQ,SAAA,EAAW,QAAA,EAAA;AAAA,QAAA,YAAA;AAAA,QAAa;AAAA,OAAA,EAAQ;AAAA,KAAA,EACtD,CAAA;AAAA,oBACA,IAAA,CAAC,GAAA,EAAA,EAAI,SAAA,EAAW,OAAA,CAAQ,QAAA,EACtB,QAAA,EAAA;AAAA,sBAAA,GAAA,CAAC,mBAAA,EAAA,EAAoB,OAAA,EAAS,KAAA,EAAO,IAAA,EAAK,OAAA,EAAQ,CAAA;AAAA,sBAClD,IAAA,CAAC,UAAA,EAAA,EAAW,OAAA,EAAQ,SAAA,EAAW,QAAA,EAAA;AAAA,QAAA,aAAA;AAAA,QAAc;AAAA,OAAA,EAAS;AAAA,KAAA,EACxD;AAAA,GAAA,EACF,CAAA,EACF,CAAA;AAEJ;;;;"}
1
+ {"version":3,"file":"FlagStatsRow.esm.js","sources":["../../../src/components/FlagsmithOverviewCard/FlagStatsRow.tsx"],"sourcesContent":["import { Box, Typography } from '@material-ui/core';\nimport { makeStyles } from '@material-ui/core/styles';\nimport { FlagStatusIndicator } from '../shared';\n\nconst useStyles = makeStyles(theme => ({\n statsRow: {\n display: 'flex',\n alignItems: 'center',\n gap: theme.spacing(2),\n marginBottom: theme.spacing(1),\n fontSize: '0.75rem',\n },\n statItem: {\n display: 'flex',\n alignItems: 'center',\n gap: theme.spacing(0.5),\n },\n}));\n\ninterface FlagStatsRowProps {\n enabledCount: number;\n disabledCount: number;\n}\n\nexport const FlagStatsRow = ({ enabledCount, disabledCount }: FlagStatsRowProps) => {\n const classes = useStyles();\n\n return (\n <Box px={2} pt={1}>\n <Box className={classes.statsRow}>\n <Box className={classes.statItem}>\n <FlagStatusIndicator enabled size=\"small\" />\n <Typography variant=\"caption\">{enabledCount} Enabled</Typography>\n </Box>\n <Box className={classes.statItem}>\n <FlagStatusIndicator enabled={false} size=\"small\" />\n <Typography variant=\"caption\">{disabledCount} Disabled</Typography>\n </Box>\n </Box>\n </Box>\n );\n};\n"],"names":[],"mappings":";;;;;;;;;;;AAIA,MAAM,SAAA,GAAY,WAAW,CAAA,KAAA,MAAU;AAAA,EACrC,QAAA,EAAU;AAAA,IACR,OAAA,EAAS,MAAA;AAAA,IACT,UAAA,EAAY,QAAA;AAAA,IACZ,GAAA,EAAK,KAAA,CAAM,OAAA,CAAQ,CAAC,CAAA;AAAA,IACpB,YAAA,EAAc,KAAA,CAAM,OAAA,CAAQ,CAAC,CAAA;AAAA,IAC7B,QAAA,EAAU;AAAA,GACZ;AAAA,EACA,QAAA,EAAU;AAAA,IACR,OAAA,EAAS,MAAA;AAAA,IACT,UAAA,EAAY,QAAA;AAAA,IACZ,GAAA,EAAK,KAAA,CAAM,OAAA,CAAQ,GAAG;AAAA;AAE1B,CAAA,CAAE,CAAA;AAOK,MAAM,YAAA,GAAe,CAAC,EAAE,YAAA,EAAc,eAAc,KAAyB;AAClF,EAAA,MAAM,UAAU,SAAA,EAAU;AAE1B,EAAA,uBACE,GAAA,CAAC,GAAA,EAAA,EAAI,EAAA,EAAI,CAAA,EAAG,EAAA,EAAI,GACd,QAAA,kBAAA,IAAA,CAAC,GAAA,EAAA,EAAI,SAAA,EAAW,OAAA,CAAQ,QAAA,EACtB,QAAA,EAAA;AAAA,oBAAA,IAAA,CAAC,GAAA,EAAA,EAAI,SAAA,EAAW,OAAA,CAAQ,QAAA,EACtB,QAAA,EAAA;AAAA,sBAAA,GAAA,CAAC,mBAAA,EAAA,EAAoB,OAAA,EAAO,IAAA,EAAC,IAAA,EAAK,OAAA,EAAQ,CAAA;AAAA,sBAC1C,IAAA,CAAC,UAAA,EAAA,EAAW,OAAA,EAAQ,SAAA,EAAW,QAAA,EAAA;AAAA,QAAA,YAAA;AAAA,QAAa;AAAA,OAAA,EAAQ;AAAA,KAAA,EACtD,CAAA;AAAA,oBACA,IAAA,CAAC,GAAA,EAAA,EAAI,SAAA,EAAW,OAAA,CAAQ,QAAA,EACtB,QAAA,EAAA;AAAA,sBAAA,GAAA,CAAC,mBAAA,EAAA,EAAoB,OAAA,EAAS,KAAA,EAAO,IAAA,EAAK,OAAA,EAAQ,CAAA;AAAA,sBAClD,IAAA,CAAC,UAAA,EAAA,EAAW,OAAA,EAAQ,SAAA,EAAW,QAAA,EAAA;AAAA,QAAA,aAAA;AAAA,QAAc;AAAA,OAAA,EAAS;AAAA,KAAA,EACxD;AAAA,GAAA,EACF,CAAA,EACF,CAAA;AAEJ;;;;"}
@@ -11,6 +11,7 @@ import { MiniPagination } from '../shared/MiniPagination.esm.js';
11
11
  import { LoadingState } from '../shared/LoadingState.esm.js';
12
12
  import { ErrorState } from '../shared/ErrorState.esm.js';
13
13
  import '../shared/ChartTooltip.esm.js';
14
+ import '../shared/TagChip.esm.js';
14
15
  import { buildProjectUrl } from '../../theme/flagsmithTheme.esm.js';
15
16
  import { useFlagsmithProject } from '../../hooks/useFlagsmithProject.esm.js';
16
17
  import '@backstage/core-plugin-api';
@@ -1 +1 @@
1
- {"version":3,"file":"index.esm.js","sources":["../../../src/components/FlagsmithOverviewCard/index.tsx"],"sourcesContent":["import { useState } from 'react';\nimport {\n Typography,\n Box,\n Table,\n TableBody,\n TableCell,\n TableContainer,\n TableHead,\n TableRow,\n Paper,\n Tooltip,\n} from '@material-ui/core';\nimport { makeStyles } from '@material-ui/core/styles';\nimport { InfoCard } from '@backstage/core-components';\nimport { useEntity } from '@backstage/plugin-catalog-react';\nimport { FlagsmithLink, MiniPagination, LoadingState, ErrorState } from '../shared';\nimport { buildProjectUrl } from '../../theme/flagsmithTheme';\nimport { useFlagsmithProject } from '../../hooks';\nimport { calculateFeatureStats, paginate } from '../../utils';\nimport { FlagStatsRow } from './FlagStatsRow';\nimport { FeatureFlagRow } from './FeatureFlagRow';\n\nconst useStyles = makeStyles(theme => ({\n headerActions: {\n display: 'flex',\n alignItems: 'center',\n gap: theme.spacing(1),\n },\n}));\n\nconst PAGE_SIZE = 5;\n\nexport const FlagsmithOverviewCard = () => {\n const classes = useStyles();\n const { entity } = useEntity();\n const [page, setPage] = useState(0);\n\n const projectId = entity.metadata.annotations?.['flagsmith.com/project-id'];\n const { project, environments, features, loading, error } = useFlagsmithProject(projectId);\n\n if (loading) {\n return (\n <InfoCard title=\"Flagsmith Flags\">\n <LoadingState message=\"Loading flags...\" size={24} />\n </InfoCard>\n );\n }\n\n if (error) {\n return (\n <InfoCard title=\"Flagsmith Flags\">\n <ErrorState message={error} />\n </InfoCard>\n );\n }\n\n const { paginatedItems: paginatedFeatures, totalPages } = paginate(\n features,\n page,\n PAGE_SIZE,\n );\n const { enabledCount, disabledCount } = calculateFeatureStats(features);\n const dashboardUrl = buildProjectUrl(\n projectId || '',\n environments[0]?.id?.toString(),\n );\n\n return (\n <InfoCard\n title=\"Flagsmith Flags\"\n subheader={project?.name}\n action={\n <Box className={classes.headerActions}>\n <FlagsmithLink href={dashboardUrl} iconOnly tooltip=\"Open Dashboard\" />\n </Box>\n }\n >\n <FlagStatsRow enabledCount={enabledCount} disabledCount={disabledCount} />\n\n <TableContainer component={Paper} variant=\"outlined\">\n <Table size=\"small\">\n <TableHead>\n <TableRow>\n <TableCell>Flag Name</TableCell>\n <TableCell align=\"right\">\n <Tooltip title={environments.map(e => e.name).join(' • ')}>\n <span>Environments</span>\n </Tooltip>\n </TableCell>\n </TableRow>\n </TableHead>\n <TableBody>\n {paginatedFeatures.length === 0 ? (\n <TableRow>\n <TableCell colSpan={2} align=\"center\">\n <Typography color=\"textSecondary\" variant=\"body2\">\n No feature flags found\n </Typography>\n </TableCell>\n </TableRow>\n ) : (\n paginatedFeatures.map(feature => (\n <FeatureFlagRow\n key={feature.id}\n feature={feature}\n environments={environments}\n />\n ))\n )}\n </TableBody>\n </Table>\n </TableContainer>\n\n <MiniPagination\n page={page}\n totalPages={totalPages}\n totalItems={features.length}\n onPrevious={() => setPage(p => Math.max(0, p - 1))}\n onNext={() => setPage(p => Math.min(totalPages - 1, p + 1))}\n itemLabel=\"flags\"\n />\n </InfoCard>\n );\n};\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.esm.js","sources":["../../../src/components/FlagsmithOverviewCard/index.tsx"],"sourcesContent":["import { useState } from 'react';\nimport {\n Typography,\n Box,\n Table,\n TableBody,\n TableCell,\n TableContainer,\n TableHead,\n TableRow,\n Paper,\n Tooltip,\n} from '@material-ui/core';\nimport { makeStyles } from '@material-ui/core/styles';\nimport { InfoCard } from '@backstage/core-components';\nimport { useEntity } from '@backstage/plugin-catalog-react';\nimport { FlagsmithLink, MiniPagination, LoadingState, ErrorState } from '../shared';\nimport { buildProjectUrl } from '../../theme/flagsmithTheme';\nimport { useFlagsmithProject } from '../../hooks';\nimport { calculateFeatureStats, paginate } from '../../utils';\nimport { FlagStatsRow } from './FlagStatsRow';\nimport { FeatureFlagRow } from './FeatureFlagRow';\n\nconst useStyles = makeStyles(theme => ({\n headerActions: {\n display: 'flex',\n alignItems: 'center',\n gap: theme.spacing(1),\n },\n}));\n\nconst PAGE_SIZE = 5;\n\nexport const FlagsmithOverviewCard = () => {\n const classes = useStyles();\n const { entity } = useEntity();\n const [page, setPage] = useState(0);\n\n const projectId = entity.metadata.annotations?.['flagsmith.com/project-id'];\n const { project, environments, features, loading, error } = useFlagsmithProject(projectId);\n\n if (loading) {\n return (\n <InfoCard title=\"Flagsmith Flags\">\n <LoadingState message=\"Loading flags...\" size={24} />\n </InfoCard>\n );\n }\n\n if (error) {\n return (\n <InfoCard title=\"Flagsmith Flags\">\n <ErrorState message={error} />\n </InfoCard>\n );\n }\n\n const { paginatedItems: paginatedFeatures, totalPages } = paginate(\n features,\n page,\n PAGE_SIZE,\n );\n const { enabledCount, disabledCount } = calculateFeatureStats(features);\n const dashboardUrl = buildProjectUrl(\n projectId || '',\n environments[0]?.id?.toString(),\n );\n\n return (\n <InfoCard\n title=\"Flagsmith Flags\"\n subheader={project?.name}\n action={\n <Box className={classes.headerActions}>\n <FlagsmithLink href={dashboardUrl} iconOnly tooltip=\"Open Dashboard\" />\n </Box>\n }\n >\n <FlagStatsRow enabledCount={enabledCount} disabledCount={disabledCount} />\n\n <TableContainer component={Paper} variant=\"outlined\">\n <Table size=\"small\">\n <TableHead>\n <TableRow>\n <TableCell>Flag Name</TableCell>\n <TableCell align=\"right\">\n <Tooltip title={environments.map(e => e.name).join(' • ')}>\n <span>Environments</span>\n </Tooltip>\n </TableCell>\n </TableRow>\n </TableHead>\n <TableBody>\n {paginatedFeatures.length === 0 ? (\n <TableRow>\n <TableCell colSpan={2} align=\"center\">\n <Typography color=\"textSecondary\" variant=\"body2\">\n No feature flags found\n </Typography>\n </TableCell>\n </TableRow>\n ) : (\n paginatedFeatures.map(feature => (\n <FeatureFlagRow\n key={feature.id}\n feature={feature}\n environments={environments}\n />\n ))\n )}\n </TableBody>\n </Table>\n </TableContainer>\n\n <MiniPagination\n page={page}\n totalPages={totalPages}\n totalItems={features.length}\n onPrevious={() => setPage(p => Math.max(0, p - 1))}\n onNext={() => setPage(p => Math.min(totalPages - 1, p + 1))}\n itemLabel=\"flags\"\n />\n </InfoCard>\n );\n};\n"],"names":[],"mappings":"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"}
@@ -8,6 +8,7 @@ import '../shared/FlagsmithLink.esm.js';
8
8
  import '@material-ui/icons/ChevronLeft';
9
9
  import '@material-ui/icons/ChevronRight';
10
10
  import { ChartTooltip, ChartTooltipText } from '../shared/ChartTooltip.esm.js';
11
+ import '../shared/TagChip.esm.js';
11
12
 
12
13
  const UsageChartTooltip = ({ active, payload }) => /* @__PURE__ */ jsx(ChartTooltip, { active, payload, children: (data) => {
13
14
  const usageData = data[0].payload;
@@ -1 +1 @@
1
- {"version":3,"file":"UsageChart.esm.js","sources":["../../../src/components/FlagsmithUsageCard/UsageChart.tsx"],"sourcesContent":["import { Box, Typography } from '@material-ui/core';\nimport {\n BarChart,\n Bar,\n XAxis,\n YAxis,\n CartesianGrid,\n Tooltip,\n ResponsiveContainer,\n} from 'recharts';\nimport { FlagsmithUsageData } from '../../api/FlagsmithClient';\nimport { flagsmithColors } from '../../theme/flagsmithTheme';\nimport { ChartTooltip, ChartTooltipText } from '../shared';\n\ninterface UsageChartProps {\n data: FlagsmithUsageData[];\n}\n\n/**\n * Custom tooltip for usage chart displaying flags, identities, traits, and environment document\n */\nconst UsageChartTooltip = ({ active, payload }: any) => (\n <ChartTooltip active={active} payload={payload}>\n {(data) => {\n const usageData = data[0].payload as FlagsmithUsageData;\n return (\n <>\n <ChartTooltipText variant=\"subtitle2\" fontWeight={600}>\n {new Date(usageData.day).toLocaleDateString('en-US', {\n month: 'short',\n day: 'numeric',\n year: 'numeric',\n })}\n </ChartTooltipText>\n <Box mt={1}>\n <ChartTooltipText>\n <strong>Flags:</strong> {usageData.flags ?? 0}\n </ChartTooltipText>\n <ChartTooltipText>\n <strong>Identities:</strong> {usageData.identities}\n </ChartTooltipText>\n <ChartTooltipText>\n <strong>Traits:</strong> {usageData.traits}\n </ChartTooltipText>\n <ChartTooltipText>\n <strong>Environment Document:</strong> {usageData.environment_document}\n </ChartTooltipText>\n </Box>\n </>\n );\n }}\n </ChartTooltip>\n);\n\nexport const UsageChart = ({ data }: UsageChartProps) => {\n if (data.length === 0) {\n return (\n <Box display=\"flex\" justifyContent=\"center\" alignItems=\"center\" height={300}>\n <Typography color=\"textSecondary\">\n No usage data available\n </Typography>\n </Box>\n );\n }\n\n return (\n <ResponsiveContainer width=\"100%\" height={300}>\n <BarChart\n data={data}\n margin={{ top: 5, right: 30, left: 20, bottom: 5 }}\n >\n <CartesianGrid strokeDasharray=\"3 3\" />\n <XAxis\n dataKey=\"day\"\n tickFormatter={value => {\n const date = new Date(value);\n return `${date.getMonth() + 1}/${date.getDate()}`;\n }}\n angle={-45}\n textAnchor=\"end\"\n height={80}\n />\n <YAxis />\n <Tooltip content={<UsageChartTooltip />} />\n <Bar\n dataKey=\"flags\"\n fill={flagsmithColors.primary}\n radius={[2, 2, 0, 0]}\n />\n </BarChart>\n </ResponsiveContainer>\n );\n};\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"UsageChart.esm.js","sources":["../../../src/components/FlagsmithUsageCard/UsageChart.tsx"],"sourcesContent":["import { Box, Typography } from '@material-ui/core';\nimport {\n BarChart,\n Bar,\n XAxis,\n YAxis,\n CartesianGrid,\n Tooltip,\n ResponsiveContainer,\n} from 'recharts';\nimport { FlagsmithUsageData } from '../../api/FlagsmithClient';\nimport { flagsmithColors } from '../../theme/flagsmithTheme';\nimport { ChartTooltip, ChartTooltipText } from '../shared';\n\ninterface UsageChartProps {\n data: FlagsmithUsageData[];\n}\n\n/**\n * Custom tooltip for usage chart displaying flags, identities, traits, and environment document\n */\nconst UsageChartTooltip = ({ active, payload }: any) => (\n <ChartTooltip active={active} payload={payload}>\n {(data) => {\n const usageData = data[0].payload as FlagsmithUsageData;\n return (\n <>\n <ChartTooltipText variant=\"subtitle2\" fontWeight={600}>\n {new Date(usageData.day).toLocaleDateString('en-US', {\n month: 'short',\n day: 'numeric',\n year: 'numeric',\n })}\n </ChartTooltipText>\n <Box mt={1}>\n <ChartTooltipText>\n <strong>Flags:</strong> {usageData.flags ?? 0}\n </ChartTooltipText>\n <ChartTooltipText>\n <strong>Identities:</strong> {usageData.identities}\n </ChartTooltipText>\n <ChartTooltipText>\n <strong>Traits:</strong> {usageData.traits}\n </ChartTooltipText>\n <ChartTooltipText>\n <strong>Environment Document:</strong> {usageData.environment_document}\n </ChartTooltipText>\n </Box>\n </>\n );\n }}\n </ChartTooltip>\n);\n\nexport const UsageChart = ({ data }: UsageChartProps) => {\n if (data.length === 0) {\n return (\n <Box display=\"flex\" justifyContent=\"center\" alignItems=\"center\" height={300}>\n <Typography color=\"textSecondary\">\n No usage data available\n </Typography>\n </Box>\n );\n }\n\n return (\n <ResponsiveContainer width=\"100%\" height={300}>\n <BarChart\n data={data}\n margin={{ top: 5, right: 30, left: 20, bottom: 5 }}\n >\n <CartesianGrid strokeDasharray=\"3 3\" />\n <XAxis\n dataKey=\"day\"\n tickFormatter={value => {\n const date = new Date(value);\n return `${date.getMonth() + 1}/${date.getDate()}`;\n }}\n angle={-45}\n textAnchor=\"end\"\n height={80}\n />\n <YAxis />\n <Tooltip content={<UsageChartTooltip />} />\n <Bar\n dataKey=\"flags\"\n fill={flagsmithColors.primary}\n radius={[2, 2, 0, 0]}\n />\n </BarChart>\n </ResponsiveContainer>\n );\n};\n"],"names":[],"mappings":"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"}
@@ -11,6 +11,7 @@ import '@material-ui/icons/ChevronRight';
11
11
  import { LoadingState } from '../shared/LoadingState.esm.js';
12
12
  import { ErrorState } from '../shared/ErrorState.esm.js';
13
13
  import '../shared/ChartTooltip.esm.js';
14
+ import '../shared/TagChip.esm.js';
14
15
  import { FLAGSMITH_DASHBOARD_URL } from '../../theme/flagsmithTheme.esm.js';
15
16
  import 'react';
16
17
  import '@backstage/core-plugin-api';
@@ -28,23 +29,14 @@ const FlagsmithUsageCard = () => {
28
29
  const classes = useStyles();
29
30
  const { entity } = useEntity();
30
31
  const projectId = entity.metadata.annotations?.["flagsmith.com/project-id"];
31
- const orgId = entity.metadata.annotations?.["flagsmith.com/org-id"];
32
- const { project, usageData, totalFlags, loading, error } = useFlagsmithUsage(
33
- projectId,
34
- orgId
35
- );
36
- const usageUrl = `${FLAGSMITH_DASHBOARD_URL}/organisation/${orgId}/usage`;
32
+ const { project, usageData, totalFlags, loading, error } = useFlagsmithUsage(projectId);
33
+ const orgId = project?.organisation;
34
+ const usageUrl = orgId ? `${FLAGSMITH_DASHBOARD_URL}/organisation/${orgId}/usage` : void 0;
37
35
  if (loading) {
38
36
  return /* @__PURE__ */ jsx(InfoCard, { title: "Flags Usage Data (30 Days)", children: /* @__PURE__ */ jsx(LoadingState, { message: "Loading usage data...", size: 24 }) });
39
37
  }
40
38
  if (error) {
41
- return /* @__PURE__ */ jsx(InfoCard, { title: "Flags Usage Data (30 Days)", children: /* @__PURE__ */ jsx(
42
- ErrorState,
43
- {
44
- message: error,
45
- hint: !orgId ? "Add a flagsmith.com/organization-id annotation to this entity." : void 0
46
- }
47
- ) });
39
+ return /* @__PURE__ */ jsx(InfoCard, { title: "Flags Usage Data (30 Days)", children: /* @__PURE__ */ jsx(ErrorState, { message: error }) });
48
40
  }
49
41
  const subheader = project?.name ? `${project.name} - ${totalFlags.toLocaleString()} total flag calls` : void 0;
50
42
  return /* @__PURE__ */ jsx(
@@ -52,7 +44,7 @@ const FlagsmithUsageCard = () => {
52
44
  {
53
45
  title: "Flags Usage Data (30 Days)",
54
46
  subheader,
55
- action: orgId && /* @__PURE__ */ jsx(Box, { className: classes.headerActions, children: /* @__PURE__ */ jsx(FlagsmithLink, { href: usageUrl, iconOnly: true, tooltip: "View Usage Analytics" }) }),
47
+ action: usageUrl && /* @__PURE__ */ jsx(Box, { className: classes.headerActions, children: /* @__PURE__ */ jsx(FlagsmithLink, { href: usageUrl, iconOnly: true, tooltip: "View Usage Analytics" }) }),
56
48
  children: /* @__PURE__ */ jsx(Box, { p: 2, children: /* @__PURE__ */ jsx(UsageChart, { data: usageData }) })
57
49
  }
58
50
  );
@@ -1 +1 @@
1
- {"version":3,"file":"index.esm.js","sources":["../../../src/components/FlagsmithUsageCard/index.tsx"],"sourcesContent":["import { Box } from '@material-ui/core';\nimport { makeStyles } from '@material-ui/core/styles';\nimport { InfoCard } from '@backstage/core-components';\nimport { useEntity } from '@backstage/plugin-catalog-react';\nimport { FlagsmithLink, LoadingState, ErrorState } from '../shared';\nimport { FLAGSMITH_DASHBOARD_URL } from '../../theme/flagsmithTheme';\nimport { useFlagsmithUsage } from '../../hooks';\nimport { UsageChart } from './UsageChart';\n\nconst useStyles = makeStyles(theme => ({\n headerActions: {\n display: 'flex',\n alignItems: 'center',\n gap: theme.spacing(1),\n },\n}));\n\nexport const FlagsmithUsageCard = () => {\n const classes = useStyles();\n const { entity } = useEntity();\n\n const projectId = entity.metadata.annotations?.['flagsmith.com/project-id'];\n const orgId = entity.metadata.annotations?.['flagsmith.com/org-id'];\n\n const { project, usageData, totalFlags, loading, error } = useFlagsmithUsage(\n projectId,\n orgId,\n );\n\n const usageUrl = `${FLAGSMITH_DASHBOARD_URL}/organisation/${orgId}/usage`;\n\n if (loading) {\n return (\n <InfoCard title=\"Flags Usage Data (30 Days)\">\n <LoadingState message=\"Loading usage data...\" size={24} />\n </InfoCard>\n );\n }\n\n if (error) {\n return (\n <InfoCard title=\"Flags Usage Data (30 Days)\">\n <ErrorState\n message={error}\n hint={!orgId ? 'Add a flagsmith.com/organization-id annotation to this entity.' : undefined}\n />\n </InfoCard>\n );\n }\n\n const subheader = project?.name\n ? `${project.name} - ${totalFlags.toLocaleString()} total flag calls`\n : undefined;\n\n return (\n <InfoCard\n title=\"Flags Usage Data (30 Days)\"\n subheader={subheader}\n action={\n orgId && (\n <Box className={classes.headerActions}>\n <FlagsmithLink href={usageUrl} iconOnly tooltip=\"View Usage Analytics\" />\n </Box>\n )\n }\n >\n <Box p={2}>\n <UsageChart data={usageData} />\n </Box>\n </InfoCard>\n );\n};\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;AASA,MAAM,SAAA,GAAY,WAAW,CAAA,KAAA,MAAU;AAAA,EACrC,aAAA,EAAe;AAAA,IACb,OAAA,EAAS,MAAA;AAAA,IACT,UAAA,EAAY,QAAA;AAAA,IACZ,GAAA,EAAK,KAAA,CAAM,OAAA,CAAQ,CAAC;AAAA;AAExB,CAAA,CAAE,CAAA;AAEK,MAAM,qBAAqB,MAAM;AACtC,EAAA,MAAM,UAAU,SAAA,EAAU;AAC1B,EAAA,MAAM,EAAE,MAAA,EAAO,GAAI,SAAA,EAAU;AAE7B,EAAA,MAAM,SAAA,GAAY,MAAA,CAAO,QAAA,CAAS,WAAA,GAAc,0BAA0B,CAAA;AAC1E,EAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,QAAA,CAAS,WAAA,GAAc,sBAAsB,CAAA;AAElE,EAAA,MAAM,EAAE,OAAA,EAAS,SAAA,EAAW,UAAA,EAAY,OAAA,EAAS,OAAM,GAAI,iBAAA;AAAA,IACzD,SAAA;AAAA,IACA;AAAA,GACF;AAEA,EAAA,MAAM,QAAA,GAAW,CAAA,EAAG,uBAAuB,CAAA,cAAA,EAAiB,KAAK,CAAA,MAAA,CAAA;AAEjE,EAAA,IAAI,OAAA,EAAS;AACX,IAAA,uBACE,GAAA,CAAC,QAAA,EAAA,EAAS,KAAA,EAAM,4BAAA,EACd,QAAA,kBAAA,GAAA,CAAC,gBAAa,OAAA,EAAQ,uBAAA,EAAwB,IAAA,EAAM,EAAA,EAAI,CAAA,EAC1D,CAAA;AAAA,EAEJ;AAEA,EAAA,IAAI,KAAA,EAAO;AACT,IAAA,uBACE,GAAA,CAAC,QAAA,EAAA,EAAS,KAAA,EAAM,4BAAA,EACd,QAAA,kBAAA,GAAA;AAAA,MAAC,UAAA;AAAA,MAAA;AAAA,QACC,OAAA,EAAS,KAAA;AAAA,QACT,IAAA,EAAM,CAAC,KAAA,GAAQ,gEAAA,GAAmE;AAAA;AAAA,KACpF,EACF,CAAA;AAAA,EAEJ;AAEA,EAAA,MAAM,SAAA,GAAY,OAAA,EAAS,IAAA,GACvB,CAAA,EAAG,OAAA,CAAQ,IAAI,CAAA,GAAA,EAAM,UAAA,CAAW,cAAA,EAAgB,CAAA,iBAAA,CAAA,GAChD,MAAA;AAEJ,EAAA,uBACE,GAAA;AAAA,IAAC,QAAA;AAAA,IAAA;AAAA,MACC,KAAA,EAAM,4BAAA;AAAA,MACN,SAAA;AAAA,MACA,MAAA,EACE,KAAA,oBACE,GAAA,CAAC,GAAA,EAAA,EAAI,WAAW,OAAA,CAAQ,aAAA,EACtB,QAAA,kBAAA,GAAA,CAAC,aAAA,EAAA,EAAc,MAAM,QAAA,EAAU,QAAA,EAAQ,IAAA,EAAC,OAAA,EAAQ,wBAAuB,CAAA,EACzE,CAAA;AAAA,MAIJ,QAAA,kBAAA,GAAA,CAAC,OAAI,CAAA,EAAG,CAAA,EACN,8BAAC,UAAA,EAAA,EAAW,IAAA,EAAM,WAAW,CAAA,EAC/B;AAAA;AAAA,GACF;AAEJ;;;;"}
1
+ {"version":3,"file":"index.esm.js","sources":["../../../src/components/FlagsmithUsageCard/index.tsx"],"sourcesContent":["import { Box } from '@material-ui/core';\nimport { makeStyles } from '@material-ui/core/styles';\nimport { InfoCard } from '@backstage/core-components';\nimport { useEntity } from '@backstage/plugin-catalog-react';\nimport { FlagsmithLink, LoadingState, ErrorState } from '../shared';\nimport { FLAGSMITH_DASHBOARD_URL } from '../../theme/flagsmithTheme';\nimport { useFlagsmithUsage } from '../../hooks';\nimport { UsageChart } from './UsageChart';\n\nconst useStyles = makeStyles(theme => ({\n headerActions: {\n display: 'flex',\n alignItems: 'center',\n gap: theme.spacing(1),\n },\n}));\n\nexport const FlagsmithUsageCard = () => {\n const classes = useStyles();\n const { entity } = useEntity();\n\n const projectId = entity.metadata.annotations?.['flagsmith.com/project-id'];\n\n const { project, usageData, totalFlags, loading, error } = useFlagsmithUsage(projectId);\n\n // Derive organization ID from project data for the dashboard link\n const orgId = project?.organisation;\n const usageUrl = orgId ? `${FLAGSMITH_DASHBOARD_URL}/organisation/${orgId}/usage` : undefined;\n\n if (loading) {\n return (\n <InfoCard title=\"Flags Usage Data (30 Days)\">\n <LoadingState message=\"Loading usage data...\" size={24} />\n </InfoCard>\n );\n }\n\n if (error) {\n return (\n <InfoCard title=\"Flags Usage Data (30 Days)\">\n <ErrorState message={error} />\n </InfoCard>\n );\n }\n\n const subheader = project?.name\n ? `${project.name} - ${totalFlags.toLocaleString()} total flag calls`\n : undefined;\n\n return (\n <InfoCard\n title=\"Flags Usage Data (30 Days)\"\n subheader={subheader}\n action={\n usageUrl && (\n <Box className={classes.headerActions}>\n <FlagsmithLink href={usageUrl} iconOnly tooltip=\"View Usage Analytics\" />\n </Box>\n )\n }\n >\n <Box p={2}>\n <UsageChart data={usageData} />\n </Box>\n </InfoCard>\n );\n};\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;AASA,MAAM,SAAA,GAAY,WAAW,CAAA,KAAA,MAAU;AAAA,EACrC,aAAA,EAAe;AAAA,IACb,OAAA,EAAS,MAAA;AAAA,IACT,UAAA,EAAY,QAAA;AAAA,IACZ,GAAA,EAAK,KAAA,CAAM,OAAA,CAAQ,CAAC;AAAA;AAExB,CAAA,CAAE,CAAA;AAEK,MAAM,qBAAqB,MAAM;AACtC,EAAA,MAAM,UAAU,SAAA,EAAU;AAC1B,EAAA,MAAM,EAAE,MAAA,EAAO,GAAI,SAAA,EAAU;AAE7B,EAAA,MAAM,SAAA,GAAY,MAAA,CAAO,QAAA,CAAS,WAAA,GAAc,0BAA0B,CAAA;AAE1E,EAAA,MAAM,EAAE,SAAS,SAAA,EAAW,UAAA,EAAY,SAAS,KAAA,EAAM,GAAI,kBAAkB,SAAS,CAAA;AAGtF,EAAA,MAAM,QAAQ,OAAA,EAAS,YAAA;AACvB,EAAA,MAAM,WAAW,KAAA,GAAQ,CAAA,EAAG,uBAAuB,CAAA,cAAA,EAAiB,KAAK,CAAA,MAAA,CAAA,GAAW,MAAA;AAEpF,EAAA,IAAI,OAAA,EAAS;AACX,IAAA,uBACE,GAAA,CAAC,QAAA,EAAA,EAAS,KAAA,EAAM,4BAAA,EACd,QAAA,kBAAA,GAAA,CAAC,gBAAa,OAAA,EAAQ,uBAAA,EAAwB,IAAA,EAAM,EAAA,EAAI,CAAA,EAC1D,CAAA;AAAA,EAEJ;AAEA,EAAA,IAAI,KAAA,EAAO;AACT,IAAA,uBACE,GAAA,CAAC,YAAS,KAAA,EAAM,4BAAA,EACd,8BAAC,UAAA,EAAA,EAAW,OAAA,EAAS,OAAO,CAAA,EAC9B,CAAA;AAAA,EAEJ;AAEA,EAAA,MAAM,SAAA,GAAY,OAAA,EAAS,IAAA,GACvB,CAAA,EAAG,OAAA,CAAQ,IAAI,CAAA,GAAA,EAAM,UAAA,CAAW,cAAA,EAAgB,CAAA,iBAAA,CAAA,GAChD,MAAA;AAEJ,EAAA,uBACE,GAAA;AAAA,IAAC,QAAA;AAAA,IAAA;AAAA,MACC,KAAA,EAAM,4BAAA;AAAA,MACN,SAAA;AAAA,MACA,MAAA,EACE,QAAA,oBACE,GAAA,CAAC,GAAA,EAAA,EAAI,WAAW,OAAA,CAAQ,aAAA,EACtB,QAAA,kBAAA,GAAA,CAAC,aAAA,EAAA,EAAc,MAAM,QAAA,EAAU,QAAA,EAAQ,IAAA,EAAC,OAAA,EAAQ,wBAAuB,CAAA,EACzE,CAAA;AAAA,MAIJ,QAAA,kBAAA,GAAA,CAAC,OAAI,CAAA,EAAG,CAAA,EACN,8BAAC,UAAA,EAAA,EAAW,IAAA,EAAM,WAAW,CAAA,EAC/B;AAAA;AAAA,GACF;AAEJ;;;;"}
@@ -0,0 +1,32 @@
1
+ import { jsx } from 'react/jsx-runtime';
2
+ import { Chip } from '@material-ui/core';
3
+ import { makeStyles } from '@material-ui/core/styles';
4
+ import { getTagChipStyle } from '../../utils/colorUtils.esm.js';
5
+
6
+ const useStyles = makeStyles(() => ({
7
+ root: {
8
+ fontSize: "0.7rem",
9
+ height: 20
10
+ }
11
+ }));
12
+ const TagChip = ({ tagId, tagMap }) => {
13
+ const classes = useStyles();
14
+ const tag = tagMap.get(tagId);
15
+ if (!tag) {
16
+ return null;
17
+ }
18
+ const tagStyle = getTagChipStyle(tag.color);
19
+ return /* @__PURE__ */ jsx(
20
+ Chip,
21
+ {
22
+ label: tag.label,
23
+ size: "small",
24
+ variant: "outlined",
25
+ className: classes.root,
26
+ style: tagStyle
27
+ }
28
+ );
29
+ };
30
+
31
+ export { TagChip };
32
+ //# sourceMappingURL=TagChip.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TagChip.esm.js","sources":["../../../src/components/shared/TagChip.tsx"],"sourcesContent":["import { Chip } from '@material-ui/core';\nimport { makeStyles } from '@material-ui/core/styles';\nimport { FlagsmithTag } from '../../api/FlagsmithClient';\nimport { getTagChipStyle } from '../../utils/colorUtils';\n\nconst useStyles = makeStyles(() => ({\n root: {\n fontSize: '0.7rem',\n height: 20,\n },\n}));\n\ninterface TagChipProps {\n tagId: number;\n tagMap: Map<number, FlagsmithTag>;\n}\n\nexport const TagChip = ({ tagId, tagMap }: TagChipProps) => {\n const classes = useStyles();\n const tag = tagMap.get(tagId);\n\n if (!tag) {\n return null;\n }\n\n const tagStyle = getTagChipStyle(tag.color);\n\n return (\n <Chip\n label={tag.label}\n size=\"small\"\n variant=\"outlined\"\n className={classes.root}\n style={tagStyle}\n />\n );\n};\n"],"names":[],"mappings":";;;;;AAKA,MAAM,SAAA,GAAY,WAAW,OAAO;AAAA,EAClC,IAAA,EAAM;AAAA,IACJ,QAAA,EAAU,QAAA;AAAA,IACV,MAAA,EAAQ;AAAA;AAEZ,CAAA,CAAE,CAAA;AAOK,MAAM,OAAA,GAAU,CAAC,EAAE,KAAA,EAAO,QAAO,KAAoB;AAC1D,EAAA,MAAM,UAAU,SAAA,EAAU;AAC1B,EAAA,MAAM,GAAA,GAAM,MAAA,CAAO,GAAA,CAAI,KAAK,CAAA;AAE5B,EAAA,IAAI,CAAC,GAAA,EAAK;AACR,IAAA,OAAO,IAAA;AAAA,EACT;AAEA,EAAA,MAAM,QAAA,GAAW,eAAA,CAAgB,GAAA,CAAI,KAAK,CAAA;AAE1C,EAAA,uBACE,GAAA;AAAA,IAAC,IAAA;AAAA,IAAA;AAAA,MACC,OAAO,GAAA,CAAI,KAAA;AAAA,MACX,IAAA,EAAK,OAAA;AAAA,MACL,OAAA,EAAQ,UAAA;AAAA,MACR,WAAW,OAAA,CAAQ,IAAA;AAAA,MACnB,KAAA,EAAO;AAAA;AAAA,GACT;AAEJ;;;;"}
@@ -12,6 +12,7 @@ function useFlagsmithProject(projectId) {
12
12
  const [project, setProject] = useState(null);
13
13
  const [environments, setEnvironments] = useState([]);
14
14
  const [features, setFeatures] = useState([]);
15
+ const [tags, setTags] = useState([]);
15
16
  const [loading, setLoading] = useState(true);
16
17
  const [error, setError] = useState(null);
17
18
  useEffect(() => {
@@ -28,6 +29,8 @@ function useFlagsmithProject(projectId) {
28
29
  setEnvironments(envs || []);
29
30
  const projectFeatures = await client.getProjectFeatures(projectId);
30
31
  setFeatures(projectFeatures || []);
32
+ const projectTags = await client.getProjectTags(projectId);
33
+ setTags(projectTags || []);
31
34
  } catch (err) {
32
35
  setError(err instanceof Error ? err.message : "Unknown error");
33
36
  } finally {
@@ -42,7 +45,12 @@ function useFlagsmithProject(projectId) {
42
45
  // eslint-disable-next-line react-hooks/exhaustive-deps
43
46
  [envIds]
44
47
  );
45
- return { project, environments: memoizedEnvironments, features, loading, error, client };
48
+ const tagMap = useMemo(() => {
49
+ const map = /* @__PURE__ */ new Map();
50
+ tags.forEach((tag) => map.set(tag.id, tag));
51
+ return map;
52
+ }, [tags]);
53
+ return { project, environments: memoizedEnvironments, features, tagMap, loading, error, client };
46
54
  }
47
55
 
48
56
  export { useFlagsmithProject };
@@ -1 +1 @@
1
- {"version":3,"file":"useFlagsmithProject.esm.js","sources":["../../src/hooks/useFlagsmithProject.ts"],"sourcesContent":["import { useState, useEffect, useMemo } from 'react';\nimport { useApi, discoveryApiRef, fetchApiRef } from '@backstage/core-plugin-api';\nimport {\n FlagsmithClient,\n FlagsmithProject,\n FlagsmithEnvironment,\n FlagsmithFeature,\n} from '../api/FlagsmithClient';\n\nexport interface UseFlagsmithProjectResult {\n project: FlagsmithProject | null;\n environments: FlagsmithEnvironment[];\n features: FlagsmithFeature[];\n loading: boolean;\n error: string | null;\n client: FlagsmithClient;\n}\n\nexport function useFlagsmithProject(\n projectId: string | undefined,\n): UseFlagsmithProjectResult {\n const discoveryApi = useApi(discoveryApiRef);\n const fetchApi = useApi(fetchApiRef);\n\n const client = useMemo(\n () => new FlagsmithClient(discoveryApi, fetchApi),\n [discoveryApi, fetchApi],\n );\n\n const [project, setProject] = useState<FlagsmithProject | null>(null);\n const [environments, setEnvironments] = useState<FlagsmithEnvironment[]>([]);\n const [features, setFeatures] = useState<FlagsmithFeature[]>([]);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n\n useEffect(() => {\n if (!projectId) {\n setError('No Flagsmith project ID found in entity annotations');\n setLoading(false);\n return;\n }\n\n const fetchData = async () => {\n try {\n const projectData = await client.getProject(parseInt(projectId, 10));\n setProject(projectData);\n\n const envs = await client.getProjectEnvironments(parseInt(projectId, 10));\n setEnvironments(envs || []);\n\n const projectFeatures = await client.getProjectFeatures(projectId);\n setFeatures(projectFeatures || []);\n } catch (err) {\n setError(err instanceof Error ? err.message : 'Unknown error');\n } finally {\n setLoading(false);\n }\n };\n\n fetchData();\n }, [projectId, client]);\n\n // Memoize environments to prevent unnecessary re-renders in child components\n // Only create new reference when environment IDs actually change\n const envIds = environments.map(e => e.id).join(',');\n const memoizedEnvironments = useMemo(\n () => environments,\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [envIds],\n );\n\n return { project, environments: memoizedEnvironments, features, loading, error, client };\n}\n"],"names":[],"mappings":";;;;AAkBO,SAAS,oBACd,SAAA,EAC2B;AAC3B,EAAA,MAAM,YAAA,GAAe,OAAO,eAAe,CAAA;AAC3C,EAAA,MAAM,QAAA,GAAW,OAAO,WAAW,CAAA;AAEnC,EAAA,MAAM,MAAA,GAAS,OAAA;AAAA,IACb,MAAM,IAAI,eAAA,CAAgB,YAAA,EAAc,QAAQ,CAAA;AAAA,IAChD,CAAC,cAAc,QAAQ;AAAA,GACzB;AAEA,EAAA,MAAM,CAAC,OAAA,EAAS,UAAU,CAAA,GAAI,SAAkC,IAAI,CAAA;AACpE,EAAA,MAAM,CAAC,YAAA,EAAc,eAAe,CAAA,GAAI,QAAA,CAAiC,EAAE,CAAA;AAC3E,EAAA,MAAM,CAAC,QAAA,EAAU,WAAW,CAAA,GAAI,QAAA,CAA6B,EAAE,CAAA;AAC/D,EAAA,MAAM,CAAC,OAAA,EAAS,UAAU,CAAA,GAAI,SAAS,IAAI,CAAA;AAC3C,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAI,SAAwB,IAAI,CAAA;AAEtD,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,IAAI,CAAC,SAAA,EAAW;AACd,MAAA,QAAA,CAAS,qDAAqD,CAAA;AAC9D,MAAA,UAAA,CAAW,KAAK,CAAA;AAChB,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,YAAY,YAAY;AAC5B,MAAA,IAAI;AACF,QAAA,MAAM,cAAc,MAAM,MAAA,CAAO,WAAW,QAAA,CAAS,SAAA,EAAW,EAAE,CAAC,CAAA;AACnE,QAAA,UAAA,CAAW,WAAW,CAAA;AAEtB,QAAA,MAAM,OAAO,MAAM,MAAA,CAAO,uBAAuB,QAAA,CAAS,SAAA,EAAW,EAAE,CAAC,CAAA;AACxE,QAAA,eAAA,CAAgB,IAAA,IAAQ,EAAE,CAAA;AAE1B,QAAA,MAAM,eAAA,GAAkB,MAAM,MAAA,CAAO,kBAAA,CAAmB,SAAS,CAAA;AACjE,QAAA,WAAA,CAAY,eAAA,IAAmB,EAAE,CAAA;AAAA,MACnC,SAAS,GAAA,EAAK;AACZ,QAAA,QAAA,CAAS,GAAA,YAAe,KAAA,GAAQ,GAAA,CAAI,OAAA,GAAU,eAAe,CAAA;AAAA,MAC/D,CAAA,SAAE;AACA,QAAA,UAAA,CAAW,KAAK,CAAA;AAAA,MAClB;AAAA,IACF,CAAA;AAEA,IAAA,SAAA,EAAU;AAAA,EACZ,CAAA,EAAG,CAAC,SAAA,EAAW,MAAM,CAAC,CAAA;AAItB,EAAA,MAAM,MAAA,GAAS,aAAa,GAAA,CAAI,CAAA,CAAA,KAAK,EAAE,EAAE,CAAA,CAAE,KAAK,GAAG,CAAA;AACnD,EAAA,MAAM,oBAAA,GAAuB,OAAA;AAAA,IAC3B,MAAM,YAAA;AAAA;AAAA,IAEN,CAAC,MAAM;AAAA,GACT;AAEA,EAAA,OAAO,EAAE,OAAA,EAAS,YAAA,EAAc,sBAAsB,QAAA,EAAU,OAAA,EAAS,OAAO,MAAA,EAAO;AACzF;;;;"}
1
+ {"version":3,"file":"useFlagsmithProject.esm.js","sources":["../../src/hooks/useFlagsmithProject.ts"],"sourcesContent":["import { useState, useEffect, useMemo } from 'react';\nimport { useApi, discoveryApiRef, fetchApiRef } from '@backstage/core-plugin-api';\nimport {\n FlagsmithClient,\n FlagsmithProject,\n FlagsmithEnvironment,\n FlagsmithFeature,\n FlagsmithTag,\n} from '../api/FlagsmithClient';\n\nexport interface UseFlagsmithProjectResult {\n project: FlagsmithProject | null;\n environments: FlagsmithEnvironment[];\n features: FlagsmithFeature[];\n tagMap: Map<number, FlagsmithTag>;\n loading: boolean;\n error: string | null;\n client: FlagsmithClient;\n}\n\nexport function useFlagsmithProject(\n projectId: string | undefined,\n): UseFlagsmithProjectResult {\n const discoveryApi = useApi(discoveryApiRef);\n const fetchApi = useApi(fetchApiRef);\n\n const client = useMemo(\n () => new FlagsmithClient(discoveryApi, fetchApi),\n [discoveryApi, fetchApi],\n );\n\n const [project, setProject] = useState<FlagsmithProject | null>(null);\n const [environments, setEnvironments] = useState<FlagsmithEnvironment[]>([]);\n const [features, setFeatures] = useState<FlagsmithFeature[]>([]);\n const [tags, setTags] = useState<FlagsmithTag[]>([]);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n\n useEffect(() => {\n if (!projectId) {\n setError('No Flagsmith project ID found in entity annotations');\n setLoading(false);\n return;\n }\n\n const fetchData = async () => {\n try {\n const projectData = await client.getProject(parseInt(projectId, 10));\n setProject(projectData);\n\n const envs = await client.getProjectEnvironments(parseInt(projectId, 10));\n setEnvironments(envs || []);\n\n const projectFeatures = await client.getProjectFeatures(projectId);\n setFeatures(projectFeatures || []);\n\n const projectTags = await client.getProjectTags(projectId);\n setTags(projectTags || []);\n } catch (err) {\n setError(err instanceof Error ? err.message : 'Unknown error');\n } finally {\n setLoading(false);\n }\n };\n\n fetchData();\n }, [projectId, client]);\n\n // Memoize environments to prevent unnecessary re-renders in child components\n // Only create new reference when environment IDs actually change\n const envIds = environments.map(e => e.id).join(',');\n const memoizedEnvironments = useMemo(\n () => environments,\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [envIds],\n );\n\n // Create a map of tag ID to tag object for efficient lookup\n const tagMap = useMemo(() => {\n const map = new Map<number, FlagsmithTag>();\n tags.forEach(tag => map.set(tag.id, tag));\n return map;\n }, [tags]);\n\n return { project, environments: memoizedEnvironments, features, tagMap, loading, error, client };\n}\n"],"names":[],"mappings":";;;;AAoBO,SAAS,oBACd,SAAA,EAC2B;AAC3B,EAAA,MAAM,YAAA,GAAe,OAAO,eAAe,CAAA;AAC3C,EAAA,MAAM,QAAA,GAAW,OAAO,WAAW,CAAA;AAEnC,EAAA,MAAM,MAAA,GAAS,OAAA;AAAA,IACb,MAAM,IAAI,eAAA,CAAgB,YAAA,EAAc,QAAQ,CAAA;AAAA,IAChD,CAAC,cAAc,QAAQ;AAAA,GACzB;AAEA,EAAA,MAAM,CAAC,OAAA,EAAS,UAAU,CAAA,GAAI,SAAkC,IAAI,CAAA;AACpE,EAAA,MAAM,CAAC,YAAA,EAAc,eAAe,CAAA,GAAI,QAAA,CAAiC,EAAE,CAAA;AAC3E,EAAA,MAAM,CAAC,QAAA,EAAU,WAAW,CAAA,GAAI,QAAA,CAA6B,EAAE,CAAA;AAC/D,EAAA,MAAM,CAAC,IAAA,EAAM,OAAO,CAAA,GAAI,QAAA,CAAyB,EAAE,CAAA;AACnD,EAAA,MAAM,CAAC,OAAA,EAAS,UAAU,CAAA,GAAI,SAAS,IAAI,CAAA;AAC3C,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAI,SAAwB,IAAI,CAAA;AAEtD,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,IAAI,CAAC,SAAA,EAAW;AACd,MAAA,QAAA,CAAS,qDAAqD,CAAA;AAC9D,MAAA,UAAA,CAAW,KAAK,CAAA;AAChB,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,YAAY,YAAY;AAC5B,MAAA,IAAI;AACF,QAAA,MAAM,cAAc,MAAM,MAAA,CAAO,WAAW,QAAA,CAAS,SAAA,EAAW,EAAE,CAAC,CAAA;AACnE,QAAA,UAAA,CAAW,WAAW,CAAA;AAEtB,QAAA,MAAM,OAAO,MAAM,MAAA,CAAO,uBAAuB,QAAA,CAAS,SAAA,EAAW,EAAE,CAAC,CAAA;AACxE,QAAA,eAAA,CAAgB,IAAA,IAAQ,EAAE,CAAA;AAE1B,QAAA,MAAM,eAAA,GAAkB,MAAM,MAAA,CAAO,kBAAA,CAAmB,SAAS,CAAA;AACjE,QAAA,WAAA,CAAY,eAAA,IAAmB,EAAE,CAAA;AAEjC,QAAA,MAAM,WAAA,GAAc,MAAM,MAAA,CAAO,cAAA,CAAe,SAAS,CAAA;AACzD,QAAA,OAAA,CAAQ,WAAA,IAAe,EAAE,CAAA;AAAA,MAC3B,SAAS,GAAA,EAAK;AACZ,QAAA,QAAA,CAAS,GAAA,YAAe,KAAA,GAAQ,GAAA,CAAI,OAAA,GAAU,eAAe,CAAA;AAAA,MAC/D,CAAA,SAAE;AACA,QAAA,UAAA,CAAW,KAAK,CAAA;AAAA,MAClB;AAAA,IACF,CAAA;AAEA,IAAA,SAAA,EAAU;AAAA,EACZ,CAAA,EAAG,CAAC,SAAA,EAAW,MAAM,CAAC,CAAA;AAItB,EAAA,MAAM,MAAA,GAAS,aAAa,GAAA,CAAI,CAAA,CAAA,KAAK,EAAE,EAAE,CAAA,CAAE,KAAK,GAAG,CAAA;AACnD,EAAA,MAAM,oBAAA,GAAuB,OAAA;AAAA,IAC3B,MAAM,YAAA;AAAA;AAAA,IAEN,CAAC,MAAM;AAAA,GACT;AAGA,EAAA,MAAM,MAAA,GAAS,QAAQ,MAAM;AAC3B,IAAA,MAAM,GAAA,uBAAU,GAAA,EAA0B;AAC1C,IAAA,IAAA,CAAK,QAAQ,CAAA,GAAA,KAAO,GAAA,CAAI,IAAI,GAAA,CAAI,EAAA,EAAI,GAAG,CAAC,CAAA;AACxC,IAAA,OAAO,GAAA;AAAA,EACT,CAAA,EAAG,CAAC,IAAI,CAAC,CAAA;AAET,EAAA,OAAO,EAAE,SAAS,YAAA,EAAc,oBAAA,EAAsB,UAAU,MAAA,EAAQ,OAAA,EAAS,OAAO,MAAA,EAAO;AACjG;;;;"}
@@ -2,7 +2,7 @@ import { useMemo, useState, useEffect } from 'react';
2
2
  import { useApi, discoveryApiRef, fetchApiRef } from '@backstage/core-plugin-api';
3
3
  import { FlagsmithClient } from '../api/FlagsmithClient.esm.js';
4
4
 
5
- function useFlagsmithUsage(projectId, orgId) {
5
+ function useFlagsmithUsage(projectId) {
6
6
  const discoveryApi = useApi(discoveryApiRef);
7
7
  const fetchApi = useApi(fetchApiRef);
8
8
  const client = useMemo(
@@ -14,8 +14,8 @@ function useFlagsmithUsage(projectId, orgId) {
14
14
  const [loading, setLoading] = useState(true);
15
15
  const [error, setError] = useState(null);
16
16
  useEffect(() => {
17
- if (!projectId || !orgId) {
18
- setError("Missing Flagsmith project ID or organization ID in entity annotations");
17
+ if (!projectId) {
18
+ setError("Missing Flagsmith project ID in entity annotations");
19
19
  setLoading(false);
20
20
  return;
21
21
  }
@@ -24,7 +24,7 @@ function useFlagsmithUsage(projectId, orgId) {
24
24
  const projectData = await client.getProject(parseInt(projectId, 10));
25
25
  setProject(projectData);
26
26
  const usage = await client.getUsageData(
27
- parseInt(orgId, 10),
27
+ projectData.organisation,
28
28
  parseInt(projectId, 10)
29
29
  );
30
30
  setUsageData(usage);
@@ -35,7 +35,7 @@ function useFlagsmithUsage(projectId, orgId) {
35
35
  }
36
36
  };
37
37
  fetchData();
38
- }, [projectId, orgId, client]);
38
+ }, [projectId, client]);
39
39
  const totalFlags = usageData.reduce((sum, day) => sum + (day.flags ?? 0), 0);
40
40
  return { project, usageData, totalFlags, loading, error };
41
41
  }
@@ -1 +1 @@
1
- {"version":3,"file":"useFlagsmithUsage.esm.js","sources":["../../src/hooks/useFlagsmithUsage.ts"],"sourcesContent":["import { useState, useEffect, useMemo } from 'react';\nimport { useApi, discoveryApiRef, fetchApiRef } from '@backstage/core-plugin-api';\nimport {\n FlagsmithClient,\n FlagsmithProject,\n FlagsmithUsageData,\n} from '../api/FlagsmithClient';\n\nexport interface UseFlagsmithUsageResult {\n project: FlagsmithProject | null;\n usageData: FlagsmithUsageData[];\n totalFlags: number;\n loading: boolean;\n error: string | null;\n}\n\nexport function useFlagsmithUsage(\n projectId: string | undefined,\n orgId: string | undefined,\n): UseFlagsmithUsageResult {\n const discoveryApi = useApi(discoveryApiRef);\n const fetchApi = useApi(fetchApiRef);\n\n // Memoize client to prevent recreation on every render\n const client = useMemo(\n () => new FlagsmithClient(discoveryApi, fetchApi),\n [discoveryApi, fetchApi],\n );\n\n const [project, setProject] = useState<FlagsmithProject | null>(null);\n const [usageData, setUsageData] = useState<FlagsmithUsageData[]>([]);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n\n useEffect(() => {\n if (!projectId || !orgId) {\n setError('Missing Flagsmith project ID or organization ID in entity annotations');\n setLoading(false);\n return;\n }\n\n const fetchData = async () => {\n try {\n const projectData = await client.getProject(parseInt(projectId, 10));\n setProject(projectData);\n\n const usage = await client.getUsageData(\n parseInt(orgId, 10),\n parseInt(projectId, 10),\n );\n setUsageData(usage);\n } catch (err) {\n setError(err instanceof Error ? err.message : 'Unknown error');\n } finally {\n setLoading(false);\n }\n };\n\n fetchData();\n }, [projectId, orgId, client]);\n\n const totalFlags = usageData.reduce((sum, day) => sum + (day.flags ?? 0), 0);\n\n return { project, usageData, totalFlags, loading, error };\n}\n"],"names":[],"mappings":";;;;AAgBO,SAAS,iBAAA,CACd,WACA,KAAA,EACyB;AACzB,EAAA,MAAM,YAAA,GAAe,OAAO,eAAe,CAAA;AAC3C,EAAA,MAAM,QAAA,GAAW,OAAO,WAAW,CAAA;AAGnC,EAAA,MAAM,MAAA,GAAS,OAAA;AAAA,IACb,MAAM,IAAI,eAAA,CAAgB,YAAA,EAAc,QAAQ,CAAA;AAAA,IAChD,CAAC,cAAc,QAAQ;AAAA,GACzB;AAEA,EAAA,MAAM,CAAC,OAAA,EAAS,UAAU,CAAA,GAAI,SAAkC,IAAI,CAAA;AACpE,EAAA,MAAM,CAAC,SAAA,EAAW,YAAY,CAAA,GAAI,QAAA,CAA+B,EAAE,CAAA;AACnE,EAAA,MAAM,CAAC,OAAA,EAAS,UAAU,CAAA,GAAI,SAAS,IAAI,CAAA;AAC3C,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAI,SAAwB,IAAI,CAAA;AAEtD,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,IAAI,CAAC,SAAA,IAAa,CAAC,KAAA,EAAO;AACxB,MAAA,QAAA,CAAS,uEAAuE,CAAA;AAChF,MAAA,UAAA,CAAW,KAAK,CAAA;AAChB,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,YAAY,YAAY;AAC5B,MAAA,IAAI;AACF,QAAA,MAAM,cAAc,MAAM,MAAA,CAAO,WAAW,QAAA,CAAS,SAAA,EAAW,EAAE,CAAC,CAAA;AACnE,QAAA,UAAA,CAAW,WAAW,CAAA;AAEtB,QAAA,MAAM,KAAA,GAAQ,MAAM,MAAA,CAAO,YAAA;AAAA,UACzB,QAAA,CAAS,OAAO,EAAE,CAAA;AAAA,UAClB,QAAA,CAAS,WAAW,EAAE;AAAA,SACxB;AACA,QAAA,YAAA,CAAa,KAAK,CAAA;AAAA,MACpB,SAAS,GAAA,EAAK;AACZ,QAAA,QAAA,CAAS,GAAA,YAAe,KAAA,GAAQ,GAAA,CAAI,OAAA,GAAU,eAAe,CAAA;AAAA,MAC/D,CAAA,SAAE;AACA,QAAA,UAAA,CAAW,KAAK,CAAA;AAAA,MAClB;AAAA,IACF,CAAA;AAEA,IAAA,SAAA,EAAU;AAAA,EACZ,CAAA,EAAG,CAAC,SAAA,EAAW,KAAA,EAAO,MAAM,CAAC,CAAA;AAE7B,EAAA,MAAM,UAAA,GAAa,SAAA,CAAU,MAAA,CAAO,CAAC,GAAA,EAAK,QAAQ,GAAA,IAAO,GAAA,CAAI,KAAA,IAAS,CAAA,CAAA,EAAI,CAAC,CAAA;AAE3E,EAAA,OAAO,EAAE,OAAA,EAAS,SAAA,EAAW,UAAA,EAAY,SAAS,KAAA,EAAM;AAC1D;;;;"}
1
+ {"version":3,"file":"useFlagsmithUsage.esm.js","sources":["../../src/hooks/useFlagsmithUsage.ts"],"sourcesContent":["import { useState, useEffect, useMemo } from 'react';\nimport { useApi, discoveryApiRef, fetchApiRef } from '@backstage/core-plugin-api';\nimport {\n FlagsmithClient,\n FlagsmithProject,\n FlagsmithUsageData,\n} from '../api/FlagsmithClient';\n\nexport interface UseFlagsmithUsageResult {\n project: FlagsmithProject | null;\n usageData: FlagsmithUsageData[];\n totalFlags: number;\n loading: boolean;\n error: string | null;\n}\n\nexport function useFlagsmithUsage(\n projectId: string | undefined,\n): UseFlagsmithUsageResult {\n const discoveryApi = useApi(discoveryApiRef);\n const fetchApi = useApi(fetchApiRef);\n\n // Memoize client to prevent recreation on every render\n const client = useMemo(\n () => new FlagsmithClient(discoveryApi, fetchApi),\n [discoveryApi, fetchApi],\n );\n\n const [project, setProject] = useState<FlagsmithProject | null>(null);\n const [usageData, setUsageData] = useState<FlagsmithUsageData[]>([]);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n\n useEffect(() => {\n if (!projectId) {\n setError('Missing Flagsmith project ID in entity annotations');\n setLoading(false);\n return;\n }\n\n const fetchData = async () => {\n try {\n // Fetch project data to get the organization ID\n const projectData = await client.getProject(parseInt(projectId, 10));\n setProject(projectData);\n\n // Derive organization ID from project data\n const usage = await client.getUsageData(\n projectData.organisation,\n parseInt(projectId, 10),\n );\n setUsageData(usage);\n } catch (err) {\n setError(err instanceof Error ? err.message : 'Unknown error');\n } finally {\n setLoading(false);\n }\n };\n\n fetchData();\n }, [projectId, client]);\n\n const totalFlags = usageData.reduce((sum, day) => sum + (day.flags ?? 0), 0);\n\n return { project, usageData, totalFlags, loading, error };\n}\n"],"names":[],"mappings":";;;;AAgBO,SAAS,kBACd,SAAA,EACyB;AACzB,EAAA,MAAM,YAAA,GAAe,OAAO,eAAe,CAAA;AAC3C,EAAA,MAAM,QAAA,GAAW,OAAO,WAAW,CAAA;AAGnC,EAAA,MAAM,MAAA,GAAS,OAAA;AAAA,IACb,MAAM,IAAI,eAAA,CAAgB,YAAA,EAAc,QAAQ,CAAA;AAAA,IAChD,CAAC,cAAc,QAAQ;AAAA,GACzB;AAEA,EAAA,MAAM,CAAC,OAAA,EAAS,UAAU,CAAA,GAAI,SAAkC,IAAI,CAAA;AACpE,EAAA,MAAM,CAAC,SAAA,EAAW,YAAY,CAAA,GAAI,QAAA,CAA+B,EAAE,CAAA;AACnE,EAAA,MAAM,CAAC,OAAA,EAAS,UAAU,CAAA,GAAI,SAAS,IAAI,CAAA;AAC3C,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAI,SAAwB,IAAI,CAAA;AAEtD,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,IAAI,CAAC,SAAA,EAAW;AACd,MAAA,QAAA,CAAS,oDAAoD,CAAA;AAC7D,MAAA,UAAA,CAAW,KAAK,CAAA;AAChB,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,YAAY,YAAY;AAC5B,MAAA,IAAI;AAEF,QAAA,MAAM,cAAc,MAAM,MAAA,CAAO,WAAW,QAAA,CAAS,SAAA,EAAW,EAAE,CAAC,CAAA;AACnE,QAAA,UAAA,CAAW,WAAW,CAAA;AAGtB,QAAA,MAAM,KAAA,GAAQ,MAAM,MAAA,CAAO,YAAA;AAAA,UACzB,WAAA,CAAY,YAAA;AAAA,UACZ,QAAA,CAAS,WAAW,EAAE;AAAA,SACxB;AACA,QAAA,YAAA,CAAa,KAAK,CAAA;AAAA,MACpB,SAAS,GAAA,EAAK;AACZ,QAAA,QAAA,CAAS,GAAA,YAAe,KAAA,GAAQ,GAAA,CAAI,OAAA,GAAU,eAAe,CAAA;AAAA,MAC/D,CAAA,SAAE;AACA,QAAA,UAAA,CAAW,KAAK,CAAA;AAAA,MAClB;AAAA,IACF,CAAA;AAEA,IAAA,SAAA,EAAU;AAAA,EACZ,CAAA,EAAG,CAAC,SAAA,EAAW,MAAM,CAAC,CAAA;AAEtB,EAAA,MAAM,UAAA,GAAa,SAAA,CAAU,MAAA,CAAO,CAAC,GAAA,EAAK,QAAQ,GAAA,IAAO,GAAA,CAAI,KAAA,IAAS,CAAA,CAAA,EAAI,CAAC,CAAA;AAE3E,EAAA,OAAO,EAAE,OAAA,EAAS,SAAA,EAAW,UAAA,EAAY,SAAS,KAAA,EAAM;AAC1D;;;;"}
@@ -0,0 +1,39 @@
1
+ function hexToRgb(hex) {
2
+ const match = hex.match(/^#?([0-9a-f]{3}|[0-9a-f]{6})$/i);
3
+ if (!match) return null;
4
+ const cleaned = match[1];
5
+ if (cleaned.length === 3) {
6
+ return {
7
+ r: parseInt(cleaned[0] + cleaned[0], 16),
8
+ g: parseInt(cleaned[1] + cleaned[1], 16),
9
+ b: parseInt(cleaned[2] + cleaned[2], 16)
10
+ };
11
+ }
12
+ return {
13
+ r: parseInt(cleaned.substring(0, 2), 16),
14
+ g: parseInt(cleaned.substring(2, 4), 16),
15
+ b: parseInt(cleaned.substring(4, 6), 16)
16
+ };
17
+ }
18
+ function darken(rgb, amount) {
19
+ const factor = 1 - amount;
20
+ return {
21
+ r: Math.round(rgb.r * factor),
22
+ g: Math.round(rgb.g * factor),
23
+ b: Math.round(rgb.b * factor)
24
+ };
25
+ }
26
+ function getTagChipStyle(color) {
27
+ if (!color) return void 0;
28
+ const rgb = hexToRgb(color);
29
+ if (!rgb) return void 0;
30
+ const textRgb = darken(rgb, 0.3);
31
+ return {
32
+ backgroundColor: `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, 0.08)`,
33
+ color: `rgb(${textRgb.r}, ${textRgb.g}, ${textRgb.b})`,
34
+ borderColor: `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, 0.24)`
35
+ };
36
+ }
37
+
38
+ export { getTagChipStyle, hexToRgb };
39
+ //# sourceMappingURL=colorUtils.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"colorUtils.esm.js","sources":["../../src/utils/colorUtils.ts"],"sourcesContent":["/**\n * Parse a hex color string to RGB values.\n * Supports formats: #RGB, #RRGGBB\n */\nexport function hexToRgb(\n hex: string,\n): { r: number; g: number; b: number } | null {\n const match = hex.match(/^#?([0-9a-f]{3}|[0-9a-f]{6})$/i);\n if (!match) return null;\n const cleaned = match[1];\n if (cleaned.length === 3) {\n return {\n r: parseInt(cleaned[0] + cleaned[0], 16),\n g: parseInt(cleaned[1] + cleaned[1], 16),\n b: parseInt(cleaned[2] + cleaned[2], 16),\n };\n }\n return {\n r: parseInt(cleaned.substring(0, 2), 16),\n g: parseInt(cleaned.substring(2, 4), 16),\n b: parseInt(cleaned.substring(4, 6), 16),\n };\n}\n\n/**\n * Darken an RGB color by a given factor (0–1).\n */\nfunction darken(\n rgb: { r: number; g: number; b: number },\n amount: number,\n): { r: number; g: number; b: number } {\n const factor = 1 - amount;\n return {\n r: Math.round(rgb.r * factor),\n g: Math.round(rgb.g * factor),\n b: Math.round(rgb.b * factor),\n };\n}\n\n/**\n * Build inline style object for a colored tag chip.\n * Matches Flagsmith's dashboard style: light tinted background,\n * subtle border, and darkened text color.\n * Returns undefined if no color is provided.\n */\nexport function getTagChipStyle(\n color: string | undefined,\n):\n | { backgroundColor: string; color: string; borderColor: string }\n | undefined {\n if (!color) return undefined;\n const rgb = hexToRgb(color);\n if (!rgb) return undefined;\n\n const textRgb = darken(rgb, 0.3);\n\n return {\n backgroundColor: `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, 0.08)`,\n color: `rgb(${textRgb.r}, ${textRgb.g}, ${textRgb.b})`,\n borderColor: `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, 0.24)`,\n };\n}\n"],"names":[],"mappings":"AAIO,SAAS,SACd,GAAA,EAC4C;AAC5C,EAAA,MAAM,KAAA,GAAQ,GAAA,CAAI,KAAA,CAAM,gCAAgC,CAAA;AACxD,EAAA,IAAI,CAAC,OAAO,OAAO,IAAA;AACnB,EAAA,MAAM,OAAA,GAAU,MAAM,CAAC,CAAA;AACvB,EAAA,IAAI,OAAA,CAAQ,WAAW,CAAA,EAAG;AACxB,IAAA,OAAO;AAAA,MACL,CAAA,EAAG,SAAS,OAAA,CAAQ,CAAC,IAAI,OAAA,CAAQ,CAAC,GAAG,EAAE,CAAA;AAAA,MACvC,CAAA,EAAG,SAAS,OAAA,CAAQ,CAAC,IAAI,OAAA,CAAQ,CAAC,GAAG,EAAE,CAAA;AAAA,MACvC,CAAA,EAAG,SAAS,OAAA,CAAQ,CAAC,IAAI,OAAA,CAAQ,CAAC,GAAG,EAAE;AAAA,KACzC;AAAA,EACF;AACA,EAAA,OAAO;AAAA,IACL,GAAG,QAAA,CAAS,OAAA,CAAQ,UAAU,CAAA,EAAG,CAAC,GAAG,EAAE,CAAA;AAAA,IACvC,GAAG,QAAA,CAAS,OAAA,CAAQ,UAAU,CAAA,EAAG,CAAC,GAAG,EAAE,CAAA;AAAA,IACvC,GAAG,QAAA,CAAS,OAAA,CAAQ,UAAU,CAAA,EAAG,CAAC,GAAG,EAAE;AAAA,GACzC;AACF;AAKA,SAAS,MAAA,CACP,KACA,MAAA,EACqC;AACrC,EAAA,MAAM,SAAS,CAAA,GAAI,MAAA;AACnB,EAAA,OAAO;AAAA,IACL,CAAA,EAAG,IAAA,CAAK,KAAA,CAAM,GAAA,CAAI,IAAI,MAAM,CAAA;AAAA,IAC5B,CAAA,EAAG,IAAA,CAAK,KAAA,CAAM,GAAA,CAAI,IAAI,MAAM,CAAA;AAAA,IAC5B,CAAA,EAAG,IAAA,CAAK,KAAA,CAAM,GAAA,CAAI,IAAI,MAAM;AAAA,GAC9B;AACF;AAQO,SAAS,gBACd,KAAA,EAGY;AACZ,EAAA,IAAI,CAAC,OAAO,OAAO,MAAA;AACnB,EAAA,MAAM,GAAA,GAAM,SAAS,KAAK,CAAA;AAC1B,EAAA,IAAI,CAAC,KAAK,OAAO,MAAA;AAEjB,EAAA,MAAM,OAAA,GAAU,MAAA,CAAO,GAAA,EAAK,GAAG,CAAA;AAE/B,EAAA,OAAO;AAAA,IACL,eAAA,EAAiB,QAAQ,GAAA,CAAI,CAAC,KAAK,GAAA,CAAI,CAAC,CAAA,EAAA,EAAK,GAAA,CAAI,CAAC,CAAA,OAAA,CAAA;AAAA,IAClD,KAAA,EAAO,OAAO,OAAA,CAAQ,CAAC,KAAK,OAAA,CAAQ,CAAC,CAAA,EAAA,EAAK,OAAA,CAAQ,CAAC,CAAA,CAAA,CAAA;AAAA,IACnD,WAAA,EAAa,QAAQ,GAAA,CAAI,CAAC,KAAK,GAAA,CAAI,CAAC,CAAA,EAAA,EAAK,GAAA,CAAI,CAAC,CAAA,OAAA;AAAA,GAChD;AACF;;;;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flagsmith/backstage-plugin",
3
- "version": "0.2.1",
3
+ "version": "0.3.0",
4
4
  "description": "Backstage plugin for Flagsmith feature flag management",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {