@flagsmith/backstage-plugin 0.1.0-pr.7.a55a280 → 0.1.0-pr.7.de3318e
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.
- package/dist/api/FlagsmithClient.esm.js +28 -2
- package/dist/api/FlagsmithClient.esm.js.map +1 -1
- package/dist/components/FlagsTab/EnvironmentTable.esm.js +83 -45
- package/dist/components/FlagsTab/EnvironmentTable.esm.js.map +1 -1
- package/dist/components/FlagsTab/ExpandableRow.esm.js +188 -101
- package/dist/components/FlagsTab/ExpandableRow.esm.js.map +1 -1
- package/dist/components/FlagsTab/FeatureAnalyticsSection.esm.js +178 -0
- package/dist/components/FlagsTab/FeatureAnalyticsSection.esm.js.map +1 -0
- package/dist/components/FlagsTab/FeatureDetailsGrid.esm.js +111 -35
- package/dist/components/FlagsTab/FeatureDetailsGrid.esm.js.map +1 -1
- package/dist/components/FlagsTab/SegmentOverridesSection.esm.js +1 -0
- package/dist/components/FlagsTab/SegmentOverridesSection.esm.js.map +1 -1
- package/dist/components/FlagsTab/index.esm.js +48 -16
- package/dist/components/FlagsTab/index.esm.js.map +1 -1
- package/dist/components/FlagsmithOverviewCard/FeatureFlagRow.esm.js +1 -0
- package/dist/components/FlagsmithOverviewCard/FeatureFlagRow.esm.js.map +1 -1
- package/dist/components/FlagsmithOverviewCard/FlagStatsRow.esm.js +1 -0
- package/dist/components/FlagsmithOverviewCard/FlagStatsRow.esm.js.map +1 -1
- package/dist/components/FlagsmithOverviewCard/index.esm.js +4 -5
- package/dist/components/FlagsmithOverviewCard/index.esm.js.map +1 -1
- package/dist/components/FlagsmithUsageCard/UsageChart.esm.js +40 -3
- package/dist/components/FlagsmithUsageCard/UsageChart.esm.js.map +1 -1
- package/dist/components/FlagsmithUsageCard/index.esm.js +11 -13
- package/dist/components/FlagsmithUsageCard/index.esm.js.map +1 -1
- package/dist/components/shared/ChartTooltip.esm.js +33 -0
- package/dist/components/shared/ChartTooltip.esm.js.map +1 -0
- package/dist/components/shared/ErrorState.esm.js +13 -0
- package/dist/components/shared/ErrorState.esm.js.map +1 -0
- package/dist/components/shared/FlagsmithLink.esm.js +12 -4
- package/dist/components/shared/FlagsmithLink.esm.js.map +1 -1
- package/dist/constants/index.esm.js +38 -0
- package/dist/constants/index.esm.js.map +1 -0
- package/dist/hooks/useFlagsmithProject.esm.js +7 -1
- package/dist/hooks/useFlagsmithProject.esm.js.map +1 -1
- package/dist/hooks/useFlagsmithUsage.esm.js +6 -3
- package/dist/hooks/useFlagsmithUsage.esm.js.map +1 -1
- package/dist/index.d.ts +9 -2
- package/dist/index.esm.js +3 -0
- package/dist/index.esm.js.map +1 -1
- package/dist/theme/sharedStyles.esm.js +19 -0
- package/dist/theme/sharedStyles.esm.js.map +1 -0
- package/dist/utils/dateFormatters.esm.js +15 -0
- package/dist/utils/dateFormatters.esm.js.map +1 -0
- package/dist/utils/flagTypeHelpers.esm.js +42 -0
- package/dist/utils/flagTypeHelpers.esm.js.map +1 -0
- package/package.json +1 -1
- package/dist/components/FlagsmithUsageCard/UsageTooltip.esm.js +0 -52
- package/dist/components/FlagsmithUsageCard/UsageTooltip.esm.js.map +0 -1
|
@@ -59,18 +59,40 @@ class FlagsmithClient {
|
|
|
59
59
|
}
|
|
60
60
|
return await response.json();
|
|
61
61
|
}
|
|
62
|
-
async getUsageData(orgId, projectId) {
|
|
62
|
+
async getUsageData(orgId, projectId, environmentId) {
|
|
63
63
|
const baseUrl = await this.getBaseUrl();
|
|
64
64
|
const url = new URL(`${baseUrl}/organisations/${orgId}/usage-data/`);
|
|
65
65
|
if (projectId) {
|
|
66
66
|
url.searchParams.set("project_id", projectId.toString());
|
|
67
67
|
}
|
|
68
|
+
if (environmentId) {
|
|
69
|
+
url.searchParams.set("environment_id", environmentId.toString());
|
|
70
|
+
}
|
|
68
71
|
const response = await this.fetchApi.fetch(url.toString());
|
|
69
72
|
if (!response.ok) {
|
|
70
73
|
throw new Error(`Failed to fetch usage data: ${response.statusText}`);
|
|
71
74
|
}
|
|
72
75
|
return await response.json();
|
|
73
76
|
}
|
|
77
|
+
/**
|
|
78
|
+
* Fetch usage data for multiple environments in parallel
|
|
79
|
+
*/
|
|
80
|
+
async getUsageDataByEnvironments(orgId, projectId, environments) {
|
|
81
|
+
const results = /* @__PURE__ */ new Map();
|
|
82
|
+
const promises = environments.map(async (env) => {
|
|
83
|
+
try {
|
|
84
|
+
const data = await this.getUsageData(orgId, projectId, env.id);
|
|
85
|
+
return { envName: env.name, data };
|
|
86
|
+
} catch {
|
|
87
|
+
return { envName: env.name, data: [] };
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
const responses = await Promise.all(promises);
|
|
91
|
+
responses.forEach(({ envName, data }) => {
|
|
92
|
+
results.set(envName, data);
|
|
93
|
+
});
|
|
94
|
+
return results;
|
|
95
|
+
}
|
|
74
96
|
// Lazy loading methods for feature details
|
|
75
97
|
async getFeatureVersions(environmentId, featureId) {
|
|
76
98
|
const baseUrl = await this.getBaseUrl();
|
|
@@ -99,6 +121,9 @@ class FlagsmithClient {
|
|
|
99
121
|
async getFeatureDetails(environmentId, featureId) {
|
|
100
122
|
const versions = await this.getFeatureVersions(environmentId, featureId);
|
|
101
123
|
const liveVersion = versions.find((v) => v.is_live) || null;
|
|
124
|
+
const now = /* @__PURE__ */ new Date();
|
|
125
|
+
const scheduledVersions = versions.filter((v) => !v.is_live && v.live_from && new Date(v.live_from) > now).sort((a, b) => new Date(a.live_from).getTime() - new Date(b.live_from).getTime());
|
|
126
|
+
const scheduledVersion = scheduledVersions[0] || null;
|
|
102
127
|
let featureState = null;
|
|
103
128
|
let segmentOverrides = 0;
|
|
104
129
|
if (liveVersion) {
|
|
@@ -114,7 +139,8 @@ class FlagsmithClient {
|
|
|
114
139
|
return {
|
|
115
140
|
liveVersion,
|
|
116
141
|
featureState,
|
|
117
|
-
segmentOverrides
|
|
142
|
+
segmentOverrides,
|
|
143
|
+
scheduledVersion
|
|
118
144
|
};
|
|
119
145
|
}
|
|
120
146
|
}
|
|
@@ -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}\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 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}\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}\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 ): 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\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 // 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 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 };\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 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,7 +1,10 @@
|
|
|
1
|
-
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
2
|
-
import { Table, TableHead, TableRow, TableCell, TableBody,
|
|
1
|
+
import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { Table, TableHead, TableRow, TableCell, TableBody, Typography, Switch, Box, Chip } from '@material-ui/core';
|
|
3
3
|
import { makeStyles } from '@material-ui/core/styles';
|
|
4
|
-
import {
|
|
4
|
+
import { switchOnStyle } from '../../theme/sharedStyles.esm.js';
|
|
5
|
+
import { MAX_DETAIL_ENVIRONMENTS } from '../../constants/index.esm.js';
|
|
6
|
+
import { isDefined } from '../../utils/flagTypeHelpers.esm.js';
|
|
7
|
+
import { formatDate } from '../../utils/dateFormatters.esm.js';
|
|
5
8
|
|
|
6
9
|
const useStyles = makeStyles((theme) => ({
|
|
7
10
|
envTable: {
|
|
@@ -17,14 +20,7 @@ const useStyles = makeStyles((theme) => ({
|
|
|
17
20
|
textTransform: "uppercase"
|
|
18
21
|
}
|
|
19
22
|
},
|
|
20
|
-
|
|
21
|
-
color: flagsmithColors.primary,
|
|
22
|
-
fontWeight: 600
|
|
23
|
-
},
|
|
24
|
-
statusOff: {
|
|
25
|
-
color: theme.palette.text.secondary,
|
|
26
|
-
fontWeight: 600
|
|
27
|
-
},
|
|
23
|
+
switchOn: switchOnStyle,
|
|
28
24
|
envBadge: {
|
|
29
25
|
fontSize: "0.7rem",
|
|
30
26
|
height: 18,
|
|
@@ -35,50 +31,92 @@ const useStyles = makeStyles((theme) => ({
|
|
|
35
31
|
fontFamily: "monospace",
|
|
36
32
|
fontSize: "0.85rem",
|
|
37
33
|
color: theme.palette.text.primary
|
|
34
|
+
},
|
|
35
|
+
envName: {
|
|
36
|
+
fontWeight: 500
|
|
37
|
+
},
|
|
38
|
+
overridesContainer: {
|
|
39
|
+
display: "flex",
|
|
40
|
+
flexWrap: "wrap",
|
|
41
|
+
gap: 4
|
|
42
|
+
},
|
|
43
|
+
hiddenEnvsMessage: {
|
|
44
|
+
marginTop: theme.spacing(1)
|
|
38
45
|
}
|
|
39
46
|
}));
|
|
47
|
+
const formatOverrideLabel = (count, singular, plural) => {
|
|
48
|
+
return `${count} ${count > 1 ? plural : singular}`;
|
|
49
|
+
};
|
|
40
50
|
const EnvironmentTable = ({
|
|
41
51
|
feature,
|
|
42
52
|
environments
|
|
43
53
|
}) => {
|
|
44
54
|
const classes = useStyles();
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
/* @__PURE__ */ jsx(
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
55
|
+
const displayedEnvironments = environments.slice(0, MAX_DETAIL_ENVIRONMENTS);
|
|
56
|
+
const hiddenCount = environments.length - MAX_DETAIL_ENVIRONMENTS;
|
|
57
|
+
const hasVersioning = displayedEnvironments.some((env) => env.use_v2_feature_versioning);
|
|
58
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
59
|
+
/* @__PURE__ */ jsxs(Table, { size: "small", className: classes.envTable, children: [
|
|
60
|
+
/* @__PURE__ */ jsx(TableHead, { children: /* @__PURE__ */ jsxs(TableRow, { children: [
|
|
61
|
+
/* @__PURE__ */ jsx(TableCell, { children: "Environment" }),
|
|
62
|
+
/* @__PURE__ */ jsx(TableCell, { children: "Status" }),
|
|
63
|
+
/* @__PURE__ */ jsx(TableCell, { children: "Value" }),
|
|
64
|
+
/* @__PURE__ */ jsx(TableCell, { children: "Overrides" }),
|
|
65
|
+
hasVersioning && /* @__PURE__ */ jsx(TableCell, { children: "Version" }),
|
|
66
|
+
/* @__PURE__ */ jsx(TableCell, { children: "Last updated" })
|
|
67
|
+
] }) }),
|
|
68
|
+
/* @__PURE__ */ jsx(TableBody, { children: displayedEnvironments.map((env) => {
|
|
69
|
+
const envState = feature.environment_state?.find((s) => s.id === env.id);
|
|
70
|
+
const enabled = envState?.enabled ?? feature.default_enabled ?? false;
|
|
71
|
+
const segmentCount = feature.num_segment_overrides ?? 0;
|
|
72
|
+
const identityCount = feature.num_identity_overrides ?? 0;
|
|
73
|
+
const value = feature.type === "CONFIG" ? feature.initial_value : null;
|
|
74
|
+
const hasOverrides = segmentCount > 0 || identityCount > 0;
|
|
75
|
+
return /* @__PURE__ */ jsxs(TableRow, { children: [
|
|
76
|
+
/* @__PURE__ */ jsx(TableCell, { children: /* @__PURE__ */ jsx(Typography, { variant: "body2", className: classes.envName, children: env.name }) }),
|
|
77
|
+
/* @__PURE__ */ jsx(TableCell, { children: /* @__PURE__ */ jsx(
|
|
78
|
+
Switch,
|
|
62
79
|
{
|
|
63
|
-
|
|
80
|
+
checked: enabled,
|
|
64
81
|
size: "small",
|
|
65
|
-
|
|
66
|
-
className: classes.
|
|
82
|
+
disabled: true,
|
|
83
|
+
className: classes.switchOn
|
|
67
84
|
}
|
|
68
|
-
)
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
85
|
+
) }),
|
|
86
|
+
/* @__PURE__ */ jsx(TableCell, { children: /* @__PURE__ */ jsx(Typography, { variant: "body2", className: classes.valueCell, children: isDefined(value) ? `"${value}"` : "-" }) }),
|
|
87
|
+
/* @__PURE__ */ jsx(TableCell, { children: /* @__PURE__ */ jsxs(Box, { className: classes.overridesContainer, children: [
|
|
88
|
+
segmentCount > 0 && /* @__PURE__ */ jsx(
|
|
89
|
+
Chip,
|
|
90
|
+
{
|
|
91
|
+
label: formatOverrideLabel(segmentCount, "segment", "segments"),
|
|
92
|
+
size: "small",
|
|
93
|
+
variant: "outlined",
|
|
94
|
+
className: classes.envBadge
|
|
95
|
+
}
|
|
96
|
+
),
|
|
97
|
+
identityCount > 0 && /* @__PURE__ */ jsx(
|
|
98
|
+
Chip,
|
|
99
|
+
{
|
|
100
|
+
label: formatOverrideLabel(identityCount, "identity", "identities"),
|
|
101
|
+
size: "small",
|
|
102
|
+
variant: "outlined",
|
|
103
|
+
className: classes.envBadge
|
|
104
|
+
}
|
|
105
|
+
),
|
|
106
|
+
!hasOverrides && /* @__PURE__ */ jsx(Typography, { variant: "body2", color: "textSecondary", children: "-" })
|
|
107
|
+
] }) }),
|
|
108
|
+
hasVersioning && /* @__PURE__ */ jsx(TableCell, { children: /* @__PURE__ */ jsx(Typography, { variant: "body2", color: "textSecondary", children: env.use_v2_feature_versioning ? "v2" : "v1" }) }),
|
|
109
|
+
/* @__PURE__ */ jsx(TableCell, { children: /* @__PURE__ */ jsx(Typography, { variant: "body2", color: "textSecondary", children: formatDate(feature.created_date) }) })
|
|
110
|
+
] }, env.id);
|
|
111
|
+
}) })
|
|
112
|
+
] }),
|
|
113
|
+
hiddenCount > 0 && /* @__PURE__ */ jsx(Box, { className: classes.hiddenEnvsMessage, children: /* @__PURE__ */ jsxs(Typography, { variant: "body2", color: "textSecondary", children: [
|
|
114
|
+
"+",
|
|
115
|
+
hiddenCount,
|
|
116
|
+
" more environment",
|
|
117
|
+
hiddenCount > 1 ? "s" : "",
|
|
118
|
+
" not shown"
|
|
119
|
+
] }) })
|
|
82
120
|
] });
|
|
83
121
|
};
|
|
84
122
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EnvironmentTable.esm.js","sources":["../../../src/components/FlagsTab/EnvironmentTable.tsx"],"sourcesContent":["import {\n Box,\n Chip,\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableRow,\n Typography,\n} from '@material-ui/core';\nimport { makeStyles } from '@material-ui/core/styles';\nimport { FlagsmithEnvironment, FlagsmithFeature } from '../../api/FlagsmithClient';\nimport { flagsmithColors } from '../../theme/flagsmithTheme';\n\nconst useStyles = makeStyles(theme => ({\n envTable: {\n marginTop: theme.spacing(1),\n '& th, & td': {\n padding: theme.spacing(1, 1.5),\n borderBottom: `1px solid ${theme.palette.divider}`,\n },\n '& th': {\n fontWeight: 600,\n fontSize: '0.75rem',\n color: theme.palette.text.secondary,\n textTransform: 'uppercase',\n },\n },\n statusOn: {\n color: flagsmithColors.primary,\n fontWeight: 600,\n },\n statusOff: {\n color: theme.palette.text.secondary,\n fontWeight: 600,\n },\n envBadge: {\n fontSize: '0.7rem',\n height: 18,\n marginRight: theme.spacing(0.5),\n marginTop: theme.spacing(0.5),\n },\n valueCell: {\n fontFamily: 'monospace',\n fontSize: '0.85rem',\n color: theme.palette.text.primary,\n },\n}));\n\ninterface EnvironmentTableProps {\n feature: FlagsmithFeature;\n environments: FlagsmithEnvironment[];\n}\n\nexport const EnvironmentTable = ({\n feature,\n environments,\n}: EnvironmentTableProps) => {\n const classes = useStyles();\n\n return (\n <Table size=\"small\" className={classes.envTable}>\n <TableHead>\n <TableRow>\n <TableCell>Environment</TableCell>\n <TableCell>Status</TableCell>\n <TableCell>Value</TableCell>\n <TableCell>Last updated</TableCell>\n </TableRow>\n </TableHead>\n <TableBody>\n {environments.map(env => {\n const envState = feature.environment_state?.find(s => s.id === env.id);\n const enabled = envState?.enabled ?? feature.default_enabled ?? false;\n const segmentCount = feature.num_segment_overrides ?? 0;\n const value = feature.type === 'CONFIG' ? feature.initial_value : null;\n\n return (\n <TableRow key={env.id}>\n <TableCell>\n <Box>\n <Typography variant=\"body2\" style={{ fontWeight: 500 }}>\n {env.name}\n </Typography>\n {segmentCount > 0 && (\n <Chip\n label={`${segmentCount} segment${segmentCount > 1 ? 's' : ''}`}\n size=\"small\"\n variant=\"outlined\"\n className={classes.envBadge}\n />\n )}\n </Box>\n </TableCell>\n <TableCell>\n <Typography\n variant=\"body2\"\n className={enabled ? classes.statusOn : classes.statusOff}\n >\n {enabled ? 'ON' : 'OFF'}\n </Typography>\n </TableCell>\n <TableCell>\n <Typography variant=\"body2\" className={classes.valueCell}>\n {value !== null && value !== undefined ? `\"${value}\"` : '-'}\n </Typography>\n </TableCell>\n <TableCell>\n <Typography variant=\"body2\" color=\"textSecondary\">\n {new Date(feature.created_date).toLocaleDateString()}\n </Typography>\n </TableCell>\n </TableRow>\n );\n })}\n </TableBody>\n </Table>\n );\n};\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"EnvironmentTable.esm.js","sources":["../../../src/components/FlagsTab/EnvironmentTable.tsx"],"sourcesContent":["import {\n Box,\n Chip,\n Switch,\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableRow,\n Typography,\n} from '@material-ui/core';\nimport { makeStyles } from '@material-ui/core/styles';\nimport { FlagsmithEnvironment, FlagsmithFeature } from '../../api/FlagsmithClient';\nimport { switchOnStyle } from '../../theme/sharedStyles';\nimport { MAX_DETAIL_ENVIRONMENTS } from '../../constants';\nimport { isDefined } from '../../utils/flagTypeHelpers';\nimport { formatDate } from '../../utils/dateFormatters';\n\nconst useStyles = makeStyles(theme => ({\n envTable: {\n marginTop: theme.spacing(1),\n '& th, & td': {\n padding: theme.spacing(1, 1.5),\n borderBottom: `1px solid ${theme.palette.divider}`,\n },\n '& th': {\n fontWeight: 600,\n fontSize: '0.75rem',\n color: theme.palette.text.secondary,\n textTransform: 'uppercase',\n },\n },\n switchOn: switchOnStyle,\n envBadge: {\n fontSize: '0.7rem',\n height: 18,\n marginRight: theme.spacing(0.5),\n marginTop: theme.spacing(0.5),\n },\n valueCell: {\n fontFamily: 'monospace',\n fontSize: '0.85rem',\n color: theme.palette.text.primary,\n },\n envName: {\n fontWeight: 500,\n },\n overridesContainer: {\n display: 'flex',\n flexWrap: 'wrap',\n gap: 4,\n },\n hiddenEnvsMessage: {\n marginTop: theme.spacing(1),\n },\n}));\n\ninterface EnvironmentTableProps {\n feature: FlagsmithFeature;\n environments: FlagsmithEnvironment[];\n}\n\n/**\n * Format override count with proper pluralization\n */\nconst formatOverrideLabel = (count: number, singular: string, plural: string): string => {\n return `${count} ${count > 1 ? plural : singular}`;\n};\n\nexport const EnvironmentTable = ({\n feature,\n environments,\n}: EnvironmentTableProps) => {\n const classes = useStyles();\n const displayedEnvironments = environments.slice(0, MAX_DETAIL_ENVIRONMENTS);\n const hiddenCount = environments.length - MAX_DETAIL_ENVIRONMENTS;\n\n // Check if any environment uses v2 versioning\n const hasVersioning = displayedEnvironments.some(env => env.use_v2_feature_versioning);\n\n return (\n <>\n <Table size=\"small\" className={classes.envTable}>\n <TableHead>\n <TableRow>\n <TableCell>Environment</TableCell>\n <TableCell>Status</TableCell>\n <TableCell>Value</TableCell>\n <TableCell>Overrides</TableCell>\n {hasVersioning && <TableCell>Version</TableCell>}\n <TableCell>Last updated</TableCell>\n </TableRow>\n </TableHead>\n <TableBody>\n {displayedEnvironments.map(env => {\n const envState = feature.environment_state?.find(s => s.id === env.id);\n const enabled = envState?.enabled ?? feature.default_enabled ?? false;\n const segmentCount = feature.num_segment_overrides ?? 0;\n const identityCount = feature.num_identity_overrides ?? 0;\n const value = feature.type === 'CONFIG' ? feature.initial_value : null;\n const hasOverrides = segmentCount > 0 || identityCount > 0;\n\n return (\n <TableRow key={env.id}>\n <TableCell>\n <Typography variant=\"body2\" className={classes.envName}>\n {env.name}\n </Typography>\n </TableCell>\n <TableCell>\n <Switch\n checked={enabled}\n size=\"small\"\n disabled\n className={classes.switchOn}\n />\n </TableCell>\n <TableCell>\n <Typography variant=\"body2\" className={classes.valueCell}>\n {isDefined(value) ? `\"${value}\"` : '-'}\n </Typography>\n </TableCell>\n <TableCell>\n <Box className={classes.overridesContainer}>\n {segmentCount > 0 && (\n <Chip\n label={formatOverrideLabel(segmentCount, 'segment', 'segments')}\n size=\"small\"\n variant=\"outlined\"\n className={classes.envBadge}\n />\n )}\n {identityCount > 0 && (\n <Chip\n label={formatOverrideLabel(identityCount, 'identity', 'identities')}\n size=\"small\"\n variant=\"outlined\"\n className={classes.envBadge}\n />\n )}\n {!hasOverrides && (\n <Typography variant=\"body2\" color=\"textSecondary\">\n -\n </Typography>\n )}\n </Box>\n </TableCell>\n {hasVersioning && (\n <TableCell>\n <Typography variant=\"body2\" color=\"textSecondary\">\n {env.use_v2_feature_versioning ? 'v2' : 'v1'}\n </Typography>\n </TableCell>\n )}\n <TableCell>\n <Typography variant=\"body2\" color=\"textSecondary\">\n {formatDate(feature.created_date)}\n </Typography>\n </TableCell>\n </TableRow>\n );\n })}\n </TableBody>\n </Table>\n {hiddenCount > 0 && (\n <Box className={classes.hiddenEnvsMessage}>\n <Typography variant=\"body2\" color=\"textSecondary\">\n +{hiddenCount} more environment{hiddenCount > 1 ? 's' : ''} not shown\n </Typography>\n </Box>\n )}\n </>\n );\n};\n"],"names":[],"mappings":"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"}
|