From 27e6869e5621c56981507c99ee66013af4677282 Mon Sep 17 00:00:00 2001 From: David An Date: Wed, 26 Apr 2023 11:47:54 -0700 Subject: [PATCH 1/9] sort feature flag Signed-off-by: David An --- .../LocalStorageFeatureFlags.test.tsx | 47 +++++++++++++++++++ .../LocalStorageFeatureFlags.tsx | 7 +++ .../src/apis/definitions/FeatureFlagsApi.ts | 5 ++ .../ExploreLayout/ExploreLayout.test.tsx | 1 + .../TemplatePage/TemplatePage.test.tsx | 1 + .../FeatureFlags/UserSettingsFeatureFlags.tsx | 21 ++++++++- 6 files changed, 81 insertions(+), 1 deletion(-) diff --git a/packages/core-app-api/src/apis/implementations/FeatureFlagsApi/LocalStorageFeatureFlags.test.tsx b/packages/core-app-api/src/apis/implementations/FeatureFlagsApi/LocalStorageFeatureFlags.test.tsx index 1193592e96..a0b04a922c 100644 --- a/packages/core-app-api/src/apis/implementations/FeatureFlagsApi/LocalStorageFeatureFlags.test.tsx +++ b/packages/core-app-api/src/apis/implementations/FeatureFlagsApi/LocalStorageFeatureFlags.test.tsx @@ -218,4 +218,51 @@ describe('FeatureFlags', () => { ).toThrow(/only contain lowercase letters, numbers and hyphens/i); }); }); + + describe('getSortedRegisteredFlags', () => { + let featureFlags: FeatureFlagsApi; + + beforeEach(() => { + featureFlags = new LocalStorageFeatureFlags(); + }); + + it('should return empty list', () => { + expect(featureFlags.getSortedFlags()).toEqual([]); + }); + + it('loads active flags first in registered order', () => { + featureFlags.registerFlag({ + name: 'registered-flag-1', + pluginId: 'plugin-one', + }); + featureFlags.registerFlag({ + name: 'registered-flag-2', + pluginId: 'plugin-two', + }); + featureFlags.registerFlag({ + name: 'registered-flag-3', + pluginId: 'plugin-three', + }); + featureFlags.registerFlag({ + name: 'registered-flag-4', + pluginId: 'plugin-four', + }); + + featureFlags.save({ + states: { + 'registered-flag-1': FeatureFlagState.None, + 'registered-flag-2': FeatureFlagState.Active, + 'registered-flag-3': FeatureFlagState.None, + 'registered-flag-4': FeatureFlagState.Active, + }, + }); + + expect(featureFlags.getSortedFlags()).toEqual([ + { name: 'registered-flag-2', pluginId: 'plugin-two' }, + { name: 'registered-flag-4', pluginId: 'plugin-four' }, + { name: 'registered-flag-1', pluginId: 'plugin-one' }, + { name: 'registered-flag-3', pluginId: 'plugin-three' }, + ]); + }); + }); }); diff --git a/packages/core-app-api/src/apis/implementations/FeatureFlagsApi/LocalStorageFeatureFlags.tsx b/packages/core-app-api/src/apis/implementations/FeatureFlagsApi/LocalStorageFeatureFlags.tsx index 2c8470642a..08333b1161 100644 --- a/packages/core-app-api/src/apis/implementations/FeatureFlagsApi/LocalStorageFeatureFlags.tsx +++ b/packages/core-app-api/src/apis/implementations/FeatureFlagsApi/LocalStorageFeatureFlags.tsx @@ -57,6 +57,13 @@ export class LocalStorageFeatureFlags implements FeatureFlagsApi { this.registeredFeatureFlags.push(flag); } + getSortedFlags(): FeatureFlag[] { + const flags = this.registeredFeatureFlags; + const activeFlags = flags.filter(flag => this.isActive(flag.name)); + const idleFlags = flags.filter(flag => !this.isActive(flag.name)); + return [...activeFlags, ...idleFlags]; + } + getRegisteredFlags(): FeatureFlag[] { return this.registeredFeatureFlags.slice(); } diff --git a/packages/core-plugin-api/src/apis/definitions/FeatureFlagsApi.ts b/packages/core-plugin-api/src/apis/definitions/FeatureFlagsApi.ts index 66260afa32..1dcc1ba74d 100644 --- a/packages/core-plugin-api/src/apis/definitions/FeatureFlagsApi.ts +++ b/packages/core-plugin-api/src/apis/definitions/FeatureFlagsApi.ts @@ -84,6 +84,11 @@ export interface FeatureFlagsApi { */ registerFlag(flag: FeatureFlag): void; + /** + * Get a list of all registered flags sorted. + */ + getSortedFlags(): FeatureFlag[]; + /** * Get a list of all registered flags. */ diff --git a/plugins/explore/src/components/ExploreLayout/ExploreLayout.test.tsx b/plugins/explore/src/components/ExploreLayout/ExploreLayout.test.tsx index 7574c685a4..808a0d9dec 100644 --- a/plugins/explore/src/components/ExploreLayout/ExploreLayout.test.tsx +++ b/plugins/explore/src/components/ExploreLayout/ExploreLayout.test.tsx @@ -29,6 +29,7 @@ const featureFlagsApi: jest.Mocked = { save: jest.fn(), getRegisteredFlags: jest.fn(), registerFlag: jest.fn(), + getSortedFlags: jest.fn(), }; describe('', () => { diff --git a/plugins/scaffolder/src/components/TemplatePage/TemplatePage.test.tsx b/plugins/scaffolder/src/components/TemplatePage/TemplatePage.test.tsx index 344929fa43..1854f4a307 100644 --- a/plugins/scaffolder/src/components/TemplatePage/TemplatePage.test.tsx +++ b/plugins/scaffolder/src/components/TemplatePage/TemplatePage.test.tsx @@ -62,6 +62,7 @@ const featureFlagsApiMock: jest.Mocked = { registerFlag: jest.fn(), getRegisteredFlags: jest.fn(), save: jest.fn(), + getSortedFlags: jest.fn(), }; const errorApiMock = { post: jest.fn(), error$: jest.fn() }; diff --git a/plugins/user-settings/src/components/FeatureFlags/UserSettingsFeatureFlags.tsx b/plugins/user-settings/src/components/FeatureFlags/UserSettingsFeatureFlags.tsx index c58e637bd2..67356381ce 100644 --- a/plugins/user-settings/src/components/FeatureFlags/UserSettingsFeatureFlags.tsx +++ b/plugins/user-settings/src/components/FeatureFlags/UserSettingsFeatureFlags.tsx @@ -25,6 +25,7 @@ import { import { EmptyFlags } from './EmptyFlags'; import { FlagItem } from './FeatureFlagsItem'; import { + FeatureFlag, featureFlagsApiRef, FeatureFlagState, useApi, @@ -32,11 +33,27 @@ import { import { InfoCard } from '@backstage/core-components'; import ClearIcon from '@material-ui/icons/Clear'; +let registered = false; +const f1: FeatureFlag = { name: 'f111', pluginId: 'f111' }; +const f2: FeatureFlag = { name: 'f222', pluginId: 'f222' }; +const f3: FeatureFlag = { name: 'f333', pluginId: 'f333' }; +const f4: FeatureFlag = { name: 'f444', pluginId: 'f444' }; +const f5: FeatureFlag = { name: 'f555', pluginId: 'f555' }; /** @public */ export const UserSettingsFeatureFlags = () => { const featureFlagsApi = useApi(featureFlagsApiRef); - const featureFlags = featureFlagsApi.getRegisteredFlags(); + if (!registered) { + featureFlagsApi.registerFlag(f1); + featureFlagsApi.registerFlag(f2); + featureFlagsApi.registerFlag(f3); + featureFlagsApi.registerFlag(f4); + featureFlagsApi.registerFlag(f5); + registered = true; + } + + // featureFlagsApi.sortFlags(); + const featureFlags = featureFlagsApi.getSortedFlags(); const initialFlagState = Object.fromEntries( featureFlags.map(({ name }) => [name, featureFlagsApi.isActive(name)]), ); @@ -132,3 +149,5 @@ export const UserSettingsFeatureFlags = () => { ); }; + +export default React.memo(UserSettingsFeatureFlags); From cb60e69046d2221a5222793ba1724d0a68eab353 Mon Sep 17 00:00:00 2001 From: David An Date: Wed, 26 Apr 2023 13:23:26 -0700 Subject: [PATCH 2/9] update api report Signed-off-by: David An --- packages/core-app-api/api-report.md | 2 ++ packages/core-plugin-api/api-report.md | 1 + 2 files changed, 3 insertions(+) diff --git a/packages/core-app-api/api-report.md b/packages/core-app-api/api-report.md index b6d3722822..d295f6cd6f 100644 --- a/packages/core-app-api/api-report.md +++ b/packages/core-app-api/api-report.md @@ -433,6 +433,8 @@ export class LocalStorageFeatureFlags implements FeatureFlagsApi { // (undocumented) getRegisteredFlags(): FeatureFlag[]; // (undocumented) + getSortedFlags(): FeatureFlag[]; + // (undocumented) isActive(name: string): boolean; // (undocumented) registerFlag(flag: FeatureFlag): void; diff --git a/packages/core-plugin-api/api-report.md b/packages/core-plugin-api/api-report.md index 52ee47f6bb..b9c88f7cd7 100644 --- a/packages/core-plugin-api/api-report.md +++ b/packages/core-plugin-api/api-report.md @@ -436,6 +436,7 @@ export type FeatureFlag = { // @public export interface FeatureFlagsApi { getRegisteredFlags(): FeatureFlag[]; + getSortedFlags(): FeatureFlag[]; isActive(name: string): boolean; registerFlag(flag: FeatureFlag): void; save(options: FeatureFlagsSaveOptions): void; From 76a7d2e3cd9a91c8ffce010804a1314e13c0a767 Mon Sep 17 00:00:00 2001 From: David An Date: Wed, 26 Apr 2023 13:24:45 -0700 Subject: [PATCH 3/9] clean up code Signed-off-by: David An --- .../FeatureFlags/UserSettingsFeatureFlags.tsx | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/plugins/user-settings/src/components/FeatureFlags/UserSettingsFeatureFlags.tsx b/plugins/user-settings/src/components/FeatureFlags/UserSettingsFeatureFlags.tsx index 67356381ce..35e3048bd6 100644 --- a/plugins/user-settings/src/components/FeatureFlags/UserSettingsFeatureFlags.tsx +++ b/plugins/user-settings/src/components/FeatureFlags/UserSettingsFeatureFlags.tsx @@ -33,26 +33,10 @@ import { import { InfoCard } from '@backstage/core-components'; import ClearIcon from '@material-ui/icons/Clear'; -let registered = false; -const f1: FeatureFlag = { name: 'f111', pluginId: 'f111' }; -const f2: FeatureFlag = { name: 'f222', pluginId: 'f222' }; -const f3: FeatureFlag = { name: 'f333', pluginId: 'f333' }; -const f4: FeatureFlag = { name: 'f444', pluginId: 'f444' }; -const f5: FeatureFlag = { name: 'f555', pluginId: 'f555' }; /** @public */ export const UserSettingsFeatureFlags = () => { const featureFlagsApi = useApi(featureFlagsApiRef); - if (!registered) { - featureFlagsApi.registerFlag(f1); - featureFlagsApi.registerFlag(f2); - featureFlagsApi.registerFlag(f3); - featureFlagsApi.registerFlag(f4); - featureFlagsApi.registerFlag(f5); - registered = true; - } - - // featureFlagsApi.sortFlags(); const featureFlags = featureFlagsApi.getSortedFlags(); const initialFlagState = Object.fromEntries( featureFlags.map(({ name }) => [name, featureFlagsApi.isActive(name)]), From 9c65d49dca33c9252185a3cfd1260f4bac6fc93b Mon Sep 17 00:00:00 2001 From: David An Date: Wed, 26 Apr 2023 13:34:30 -0700 Subject: [PATCH 4/9] fix tsc Signed-off-by: David An --- .../src/components/FeatureFlags/UserSettingsFeatureFlags.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/plugins/user-settings/src/components/FeatureFlags/UserSettingsFeatureFlags.tsx b/plugins/user-settings/src/components/FeatureFlags/UserSettingsFeatureFlags.tsx index 35e3048bd6..110e82c00e 100644 --- a/plugins/user-settings/src/components/FeatureFlags/UserSettingsFeatureFlags.tsx +++ b/plugins/user-settings/src/components/FeatureFlags/UserSettingsFeatureFlags.tsx @@ -25,7 +25,6 @@ import { import { EmptyFlags } from './EmptyFlags'; import { FlagItem } from './FeatureFlagsItem'; import { - FeatureFlag, featureFlagsApiRef, FeatureFlagState, useApi, From 00a7f66e9243e22d78253c98f770b8779599fe7f Mon Sep 17 00:00:00 2001 From: David An Date: Thu, 27 Apr 2023 09:14:36 -0700 Subject: [PATCH 5/9] remove export Signed-off-by: David An --- .../src/components/FeatureFlags/UserSettingsFeatureFlags.tsx | 2 -- 1 file changed, 2 deletions(-) diff --git a/plugins/user-settings/src/components/FeatureFlags/UserSettingsFeatureFlags.tsx b/plugins/user-settings/src/components/FeatureFlags/UserSettingsFeatureFlags.tsx index 110e82c00e..be61df887f 100644 --- a/plugins/user-settings/src/components/FeatureFlags/UserSettingsFeatureFlags.tsx +++ b/plugins/user-settings/src/components/FeatureFlags/UserSettingsFeatureFlags.tsx @@ -132,5 +132,3 @@ export const UserSettingsFeatureFlags = () => { ); }; - -export default React.memo(UserSettingsFeatureFlags); From 541b7eaf34678ae19c39f2920d17e81ddca5b475 Mon Sep 17 00:00:00 2001 From: David An Date: Mon, 15 May 2023 09:04:02 -0700 Subject: [PATCH 6/9] prevent rerendering order Signed-off-by: David An --- .../FeatureFlagsApi/LocalStorageFeatureFlags.tsx | 3 ++- .../FeatureFlags/UserSettingsFeatureFlags.tsx | 13 ++++++++++--- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/packages/core-app-api/src/apis/implementations/FeatureFlagsApi/LocalStorageFeatureFlags.tsx b/packages/core-app-api/src/apis/implementations/FeatureFlagsApi/LocalStorageFeatureFlags.tsx index 08333b1161..66bb5f48c0 100644 --- a/packages/core-app-api/src/apis/implementations/FeatureFlagsApi/LocalStorageFeatureFlags.tsx +++ b/packages/core-app-api/src/apis/implementations/FeatureFlagsApi/LocalStorageFeatureFlags.tsx @@ -61,7 +61,8 @@ export class LocalStorageFeatureFlags implements FeatureFlagsApi { const flags = this.registeredFeatureFlags; const activeFlags = flags.filter(flag => this.isActive(flag.name)); const idleFlags = flags.filter(flag => !this.isActive(flag.name)); - return [...activeFlags, ...idleFlags]; + this.registeredFeatureFlags = [...activeFlags, ...idleFlags]; + return this.registeredFeatureFlags.slice(); } getRegisteredFlags(): FeatureFlag[] { diff --git a/plugins/user-settings/src/components/FeatureFlags/UserSettingsFeatureFlags.tsx b/plugins/user-settings/src/components/FeatureFlags/UserSettingsFeatureFlags.tsx index be61df887f..d5943c4e8c 100644 --- a/plugins/user-settings/src/components/FeatureFlags/UserSettingsFeatureFlags.tsx +++ b/plugins/user-settings/src/components/FeatureFlags/UserSettingsFeatureFlags.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ -import React, { useCallback, useState } from 'react'; +import React, { useCallback, useEffect, useState } from 'react'; import { List, TextField, @@ -36,14 +36,21 @@ import ClearIcon from '@material-ui/icons/Clear'; export const UserSettingsFeatureFlags = () => { const featureFlagsApi = useApi(featureFlagsApiRef); - const featureFlags = featureFlagsApi.getSortedFlags(); + const inputRef = React.useRef(); + const [isFirstLoad, setIsFirstLoad] = React.useState(true); + useEffect(() => { + if (isFirstLoad) setIsFirstLoad(false); + }, [isFirstLoad]); + + const featureFlags = isFirstLoad + ? featureFlagsApi.getSortedFlags() + : featureFlagsApi.getRegisteredFlags(); const initialFlagState = Object.fromEntries( featureFlags.map(({ name }) => [name, featureFlagsApi.isActive(name)]), ); const [state, setState] = useState>(initialFlagState); const [filterInput, setFilterInput] = useState(''); - const inputRef = React.useRef(); const toggleFlag = useCallback( (flagName: string) => { From 405d849606e21237ec026e70edcdc2fa31ab8cc8 Mon Sep 17 00:00:00 2001 From: David An Date: Mon, 15 May 2023 09:41:00 -0700 Subject: [PATCH 7/9] remove unnecessary api report change Signed-off-by: David An --- packages/core-app-api/api-report.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/core-app-api/api-report.md b/packages/core-app-api/api-report.md index f922f5e7d5..c899ccc065 100644 --- a/packages/core-app-api/api-report.md +++ b/packages/core-app-api/api-report.md @@ -445,8 +445,6 @@ export class LocalStorageFeatureFlags implements FeatureFlagsApi { // (undocumented) getRegisteredFlags(): FeatureFlag[]; // (undocumented) - getSortedFlags(): FeatureFlag[]; - // (undocumented) isActive(name: string): boolean; // (undocumented) registerFlag(flag: FeatureFlag): void; From 8588fae2afaa4b65907308824b080a9187fa3bc6 Mon Sep 17 00:00:00 2001 From: David An Date: Fri, 19 May 2023 13:35:00 -0700 Subject: [PATCH 8/9] re-implemented logic without core api change Signed-off-by: David An --- .../LocalStorageFeatureFlags.test.tsx | 47 ------------------- .../LocalStorageFeatureFlags.tsx | 8 ---- packages/core-plugin-api/api-report.md | 1 - .../src/apis/definitions/FeatureFlagsApi.ts | 5 -- .../ExploreLayout/ExploreLayout.test.tsx | 1 - .../TemplatePage/TemplatePage.test.tsx | 1 - .../FeatureFlags/UserSettingsFeatureFlags.tsx | 28 +++++++---- 7 files changed, 19 insertions(+), 72 deletions(-) diff --git a/packages/core-app-api/src/apis/implementations/FeatureFlagsApi/LocalStorageFeatureFlags.test.tsx b/packages/core-app-api/src/apis/implementations/FeatureFlagsApi/LocalStorageFeatureFlags.test.tsx index a0b04a922c..1193592e96 100644 --- a/packages/core-app-api/src/apis/implementations/FeatureFlagsApi/LocalStorageFeatureFlags.test.tsx +++ b/packages/core-app-api/src/apis/implementations/FeatureFlagsApi/LocalStorageFeatureFlags.test.tsx @@ -218,51 +218,4 @@ describe('FeatureFlags', () => { ).toThrow(/only contain lowercase letters, numbers and hyphens/i); }); }); - - describe('getSortedRegisteredFlags', () => { - let featureFlags: FeatureFlagsApi; - - beforeEach(() => { - featureFlags = new LocalStorageFeatureFlags(); - }); - - it('should return empty list', () => { - expect(featureFlags.getSortedFlags()).toEqual([]); - }); - - it('loads active flags first in registered order', () => { - featureFlags.registerFlag({ - name: 'registered-flag-1', - pluginId: 'plugin-one', - }); - featureFlags.registerFlag({ - name: 'registered-flag-2', - pluginId: 'plugin-two', - }); - featureFlags.registerFlag({ - name: 'registered-flag-3', - pluginId: 'plugin-three', - }); - featureFlags.registerFlag({ - name: 'registered-flag-4', - pluginId: 'plugin-four', - }); - - featureFlags.save({ - states: { - 'registered-flag-1': FeatureFlagState.None, - 'registered-flag-2': FeatureFlagState.Active, - 'registered-flag-3': FeatureFlagState.None, - 'registered-flag-4': FeatureFlagState.Active, - }, - }); - - expect(featureFlags.getSortedFlags()).toEqual([ - { name: 'registered-flag-2', pluginId: 'plugin-two' }, - { name: 'registered-flag-4', pluginId: 'plugin-four' }, - { name: 'registered-flag-1', pluginId: 'plugin-one' }, - { name: 'registered-flag-3', pluginId: 'plugin-three' }, - ]); - }); - }); }); diff --git a/packages/core-app-api/src/apis/implementations/FeatureFlagsApi/LocalStorageFeatureFlags.tsx b/packages/core-app-api/src/apis/implementations/FeatureFlagsApi/LocalStorageFeatureFlags.tsx index 66bb5f48c0..2c8470642a 100644 --- a/packages/core-app-api/src/apis/implementations/FeatureFlagsApi/LocalStorageFeatureFlags.tsx +++ b/packages/core-app-api/src/apis/implementations/FeatureFlagsApi/LocalStorageFeatureFlags.tsx @@ -57,14 +57,6 @@ export class LocalStorageFeatureFlags implements FeatureFlagsApi { this.registeredFeatureFlags.push(flag); } - getSortedFlags(): FeatureFlag[] { - const flags = this.registeredFeatureFlags; - const activeFlags = flags.filter(flag => this.isActive(flag.name)); - const idleFlags = flags.filter(flag => !this.isActive(flag.name)); - this.registeredFeatureFlags = [...activeFlags, ...idleFlags]; - return this.registeredFeatureFlags.slice(); - } - getRegisteredFlags(): FeatureFlag[] { return this.registeredFeatureFlags.slice(); } diff --git a/packages/core-plugin-api/api-report.md b/packages/core-plugin-api/api-report.md index b9c88f7cd7..52ee47f6bb 100644 --- a/packages/core-plugin-api/api-report.md +++ b/packages/core-plugin-api/api-report.md @@ -436,7 +436,6 @@ export type FeatureFlag = { // @public export interface FeatureFlagsApi { getRegisteredFlags(): FeatureFlag[]; - getSortedFlags(): FeatureFlag[]; isActive(name: string): boolean; registerFlag(flag: FeatureFlag): void; save(options: FeatureFlagsSaveOptions): void; diff --git a/packages/core-plugin-api/src/apis/definitions/FeatureFlagsApi.ts b/packages/core-plugin-api/src/apis/definitions/FeatureFlagsApi.ts index 1dcc1ba74d..66260afa32 100644 --- a/packages/core-plugin-api/src/apis/definitions/FeatureFlagsApi.ts +++ b/packages/core-plugin-api/src/apis/definitions/FeatureFlagsApi.ts @@ -84,11 +84,6 @@ export interface FeatureFlagsApi { */ registerFlag(flag: FeatureFlag): void; - /** - * Get a list of all registered flags sorted. - */ - getSortedFlags(): FeatureFlag[]; - /** * Get a list of all registered flags. */ diff --git a/plugins/explore/src/components/ExploreLayout/ExploreLayout.test.tsx b/plugins/explore/src/components/ExploreLayout/ExploreLayout.test.tsx index 808a0d9dec..7574c685a4 100644 --- a/plugins/explore/src/components/ExploreLayout/ExploreLayout.test.tsx +++ b/plugins/explore/src/components/ExploreLayout/ExploreLayout.test.tsx @@ -29,7 +29,6 @@ const featureFlagsApi: jest.Mocked = { save: jest.fn(), getRegisteredFlags: jest.fn(), registerFlag: jest.fn(), - getSortedFlags: jest.fn(), }; describe('', () => { diff --git a/plugins/scaffolder/src/components/TemplatePage/TemplatePage.test.tsx b/plugins/scaffolder/src/components/TemplatePage/TemplatePage.test.tsx index 1854f4a307..344929fa43 100644 --- a/plugins/scaffolder/src/components/TemplatePage/TemplatePage.test.tsx +++ b/plugins/scaffolder/src/components/TemplatePage/TemplatePage.test.tsx @@ -62,7 +62,6 @@ const featureFlagsApiMock: jest.Mocked = { registerFlag: jest.fn(), getRegisteredFlags: jest.fn(), save: jest.fn(), - getSortedFlags: jest.fn(), }; const errorApiMock = { post: jest.fn(), error$: jest.fn() }; diff --git a/plugins/user-settings/src/components/FeatureFlags/UserSettingsFeatureFlags.tsx b/plugins/user-settings/src/components/FeatureFlags/UserSettingsFeatureFlags.tsx index d5943c4e8c..60b951ab60 100644 --- a/plugins/user-settings/src/components/FeatureFlags/UserSettingsFeatureFlags.tsx +++ b/plugins/user-settings/src/components/FeatureFlags/UserSettingsFeatureFlags.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ -import React, { useCallback, useEffect, useState } from 'react'; +import React, { useCallback, useState } from 'react'; import { List, TextField, @@ -25,6 +25,8 @@ import { import { EmptyFlags } from './EmptyFlags'; import { FlagItem } from './FeatureFlagsItem'; import { + FeatureFlag, + FeatureFlagsApi, featureFlagsApiRef, FeatureFlagState, useApi, @@ -32,19 +34,27 @@ import { import { InfoCard } from '@backstage/core-components'; import ClearIcon from '@material-ui/icons/Clear'; +export const sortFlags = ( + flags: FeatureFlag[], + featureFlagsApi: FeatureFlagsApi, +): FeatureFlag[] => { + const activeFlags = flags.filter(flag => featureFlagsApi.isActive(flag.name)); + const idleFlags = flags.filter(flag => !featureFlagsApi.isActive(flag.name)); + return [...activeFlags, ...idleFlags]; +}; + /** @public */ export const UserSettingsFeatureFlags = () => { const featureFlagsApi = useApi(featureFlagsApiRef); - const inputRef = React.useRef(); - const [isFirstLoad, setIsFirstLoad] = React.useState(true); - useEffect(() => { - if (isFirstLoad) setIsFirstLoad(false); - }, [isFirstLoad]); - const featureFlags = isFirstLoad - ? featureFlagsApi.getSortedFlags() - : featureFlagsApi.getRegisteredFlags(); + const initialFeatureFlags = featureFlagsApi.getRegisteredFlags(); + const initialFeatureFlagsSorted = sortFlags( + initialFeatureFlags, + featureFlagsApi, + ); + const [featureFlags] = useState(initialFeatureFlagsSorted); + const initialFlagState = Object.fromEntries( featureFlags.map(({ name }) => [name, featureFlagsApi.isActive(name)]), ); From 5362a7c58eaafd3600dfabf83893669de75aa600 Mon Sep 17 00:00:00 2001 From: David An Date: Tue, 23 May 2023 10:55:54 -0700 Subject: [PATCH 9/9] added changeset Signed-off-by: David An --- .changeset/fast-ears-know.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/fast-ears-know.md diff --git a/.changeset/fast-ears-know.md b/.changeset/fast-ears-know.md new file mode 100644 index 0000000000..fa56c4c99d --- /dev/null +++ b/.changeset/fast-ears-know.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-user-settings': patch +--- + +Improved the user experience of the feature flags list. It now sorts the enabled flags to the top of the list to increase the visibilities of the toggled flags.