-
Notifications
You must be signed in to change notification settings - Fork 465
refactor(features): migrate FeaturesPage to RTK Query and eliminate legacy stores #6361
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
talissoncosta
merged 167 commits into
main
from
refactor/migrate-critical-components-featurespagejs-2
Dec 16, 2025
+1,526
−527
Merged
Changes from all commits
Commits
Show all changes
167 commits
Select commit
Hold shift + click to select a range
3c60f52
refactor: migrate project settings to TS and break into smaller compo…
talissoncosta 3fb783c
refactor: standardize organisationId type and improve error handling
talissoncosta 9787499
refactor: add check on update func and clean up comments
talissoncosta 441fe25
feat: add small transition on hide/show component
talissoncosta e31e205
fix: add disable state for delete project button
talissoncosta 30c96be
fix: remove unused types
talissoncosta 3bb76e2
fix: fix permissions data
talissoncosta c076140
refactor: simplify import tab passing project name and id
talissoncosta 590ba2e
refactor: create useUpdateProjectWithToast custom hook
talissoncosta b561723
refactor: migrate settings components to use custom hook
talissoncosta 5dc862b
refactor: use Pick for UpdateProjectBody type definition
talissoncosta 38a9644
feat: add optimistic updates to project mutation
talissoncosta d7ee032
refactor: remove manual state syncing from project settings components
talissoncosta 414c9ce
refactor: extract change requests setting into separate component
talissoncosta bd3d40b
refactor: remove unnecessary useCallback wrappers
talissoncosta 5717852
refactor: small adjusts
talissoncosta 391922d
fix: sync OrganisationStore after project updates for navbar refresh
talissoncosta 0065414
fix: address PR review comments - type safety and code organization
talissoncosta bd6b2a1
fix: don't re-throw error
talissoncosta 7e30d7b
fix: adjust index files on internal pages
talissoncosta 4aaf163
fix: restore original toast messages and button states in project set…
talissoncosta e63638f
fix: correct inverted logic in case sensitivity toggle
talissoncosta 6437dcd
fix: resolve state and persistence issues in ChangeRequestsApprovalsS…
talissoncosta f418d8b
feat: add data-test prop support to ChangeRequestsSetting
talissoncosta 2066337
test: add comprehensive E2E coverage for change request approvals
talissoncosta fd418ba
fix: add space between label and input on stale flag detection
talissoncosta 4fe578a
refactor: wrap change requests e2e tests in conditional block for sca…
talissoncosta 5fe5568
feat: add organisation API request types
talissoncosta 1e1ea70
feat: add RTK Query mutations for organisation management
talissoncosta cdfbbce
feat: add organisation settings custom hooks
talissoncosta 1b7d9c7
feat: create General tab section components
talissoncosta 82100f9
feat: create General tab orchestrator component
talissoncosta 509ab4a
feat: create tab wrapper components
talissoncosta be9169a
feat: create main OrganisationSettingsPage with RTK Query
talissoncosta 2e6a318
refactor: migrate OrganisationSettingsPage to TypeScript
talissoncosta b9232ee
fix: spacing on organization name input and button
talissoncosta 0f77538
refactor: remove AccountStore dependency from DeleteOrganisation
talissoncosta 407ce1b
fix: add AppActions.refreshOrganisation for backward compatibility
talissoncosta c03885d
feat: add loading state to Delete Organisation button
talissoncosta b8eb3de
refactor: remove unnecessary comments
talissoncosta 603f688
fix: add name as required on body type
talissoncosta 109af81
fix: restore organisation-name data-test selector
talissoncosta 2b0449a
fix: restore original text content and styling
talissoncosta 7a5d3f7
fix: add missing 'organisation' type to Res type
talissoncosta 683bfcb
refactor: improve cache invalidation in useOrganisation
talissoncosta e06b032
fix: restore /create fallback and improve component structure
talissoncosta 2d7b53f
refactor: standardize organisation ID types to number
talissoncosta 556846a
Merge remote-tracking branch 'origin/main' into refactor/migrate-orga…
talissoncosta 616ecb0
fix: adjust based on feedback
talissoncosta 1c84b73
tests: add test to check name is updated
talissoncosta 42abf2c
fix: get updated org from rtk with store as fallback
talissoncosta 39bfcd2
refactor: migrate BreadcrumbSeparator to RTK Query
talissoncosta 63c2dc0
fix: invalidate RTK Query cache after organization creation
talissoncosta caf97c5
fix: replace refreshOrganisation with selectOrganisation after deletion
talissoncosta dadd750
fix: add getOrganisation call after org deletion
talissoncosta ba72cca
fix: invalidate cache when creating a new org
talissoncosta cd98ea3
tests: add new tests on organization settings
talissoncosta 655dae4
test: remove flaky tests
talissoncosta caf7150
fix: add missing waitForElementNotExist import and wait in Test 3
talissoncosta 0439174
refactor: extract empty state and metrics components from FeaturesPage
talissoncosta 6ae3524
refactor: extract FeaturesTableFilters as pure component without stor…
talissoncosta d635339
Merge remote-tracking branch 'origin/main' into refactor/migrate-crit…
talissoncosta 277ffaf
Merge remote-tracking branch 'origin/main' into refactor/migrate-crit…
talissoncosta c01874f
Merge branch 'main' into refactor/migrate-critical-components-feature…
talissoncosta 271cc98
refactor: rm unnecessary deps
talissoncosta 95a864a
Merge remote-tracking branch 'origin/main' into refactor/migrate-crit…
talissoncosta d8a9f93
feat: add RTK Query service for feature list with comprehensive filte…
talissoncosta a6177f0
feat: integrate RTK Query in FeaturesTableFilters for real-time data …
talissoncosta af310f4
feat: migrate FeaturesPage to functional component with full RTK Quer…
talissoncosta 2b4abf8
chore(types): add global type declarations for legacy utils
talissoncosta 63cab70
refactor(features): extract custom hooks for filters and actions
talissoncosta 2ac59ef
refactor(features): extract UI components from FeaturesPage
talissoncosta c4079f5
refactor(features): simplify FeaturesPage using custom hooks and comp…
talissoncosta 420fbd4
feat(features): add shared TypeScript types and useProjectEnvironment…
talissoncosta 22e6ad8
refactor(features): replace 'any' types with proper TypeScript types …
talissoncosta dddaca0
refactor(features): remove legacy stores from FeaturesList component
talissoncosta 277deb9
refactor(features): eliminate legacy stores from FeaturesPage
talissoncosta 38d5b62
fix(features): invalidate METRICS cache on feature state mutations
talissoncosta 0085403
refactor(features): remove manual metrics refetch mechanism
talissoncosta 8b5251e
refactor(features): remove redundant comments
talissoncosta 9ec2f89
feat(features): add RTK Query service for feature list with comprehen…
talissoncosta 16f2cbc
refactor(features): migrate FeaturesPage to functional component with…
talissoncosta d4bfb68
refactor(features): eliminate legacy stores and improve type safety
talissoncosta 8c6c748
refactor(features): extract filter logic to pure utility functions
talissoncosta 0a45438
refactor(features): improve code organization and type safety
talissoncosta 984b561
refactor(features): centralize pagination config and fix type issues
talissoncosta d300df8
fix(metrics): prevent API calls with undefined environmentApiKey
talissoncosta c32e191
Merge remote-tracking branch 'origin/main' into refactor/migrate-crit…
talissoncosta aec1b56
fix(types): resolve TypeScript errors in useFeatureList service
talissoncosta e8100ba
fix(types): add Environment tag type for cross-service cache invalida…
talissoncosta b500e76
refactor(features): remove complex optimistic update logic
talissoncosta 839cff1
refactor(types): add explicit update body types following team pattern
talissoncosta 455e49f
refactor(types): standardize projectId type to number across components
talissoncosta 032e538
fix(types): align pagination field naming with component expectations
talissoncosta f1f7e94
refactor(features): simplify FeaturesPage to use RouteContext exclusi…
talissoncosta fec4d01
fix(features): standardize projectId type to number across FeaturesPa…
talissoncosta 63dd7ea
refactor(features): remove unused props and improve naming
talissoncosta 5e7e4a9
refactor(features): rename stateId to environmentFlagId for clarity
talissoncosta b4c546c
refactor(features): standardize removeProjectFlag parameter naming
talissoncosta 67f2727
refactor(features): extract filter utilities to global scope for reuse
talissoncosta e575498
refactor(features): extract hooks to global scope for reuse
talissoncosta ab02cc1
feat(features): add useFeatureListWithFilters hook for RTK Query inte…
talissoncosta bdff671
refactor(features): split feature actions into focused hooks with toa…
talissoncosta 20dc34e
refactor(features): reorganize FeaturesPage component structure
talissoncosta c17fde0
refactor(features): extract display logic to useFeaturePageDisplay hook
talissoncosta 811b140
refactor(features): migrate FeaturesPage from Flux to RTK Query
talissoncosta 2121040
refactor(features): update supporting components for RTK Query migration
talissoncosta 286362a
feat(components): add PermissionGate and update metrics components
talissoncosta de9a5d4
refactor(features): remove FeaturesList wrapper component
talissoncosta ae18579
refactor(features): extract inline render functions to named constants
talissoncosta d643b49
refactor(features): extract header render to named constant
talissoncosta f33fcc8
refactor(features): remove legacy Flux store ignore filter
talissoncosta 543a386
refactor(features): extract pagination handlers and remove temporary …
talissoncosta ca859e5
fix(features): correct FilterState import in useFeaturePageDisplay
talissoncosta 9207690
perf(features): add memoization to prevent unnecessary re-renders
talissoncosta bfe783a
feat(features): add error handling UI for failed data fetching
talissoncosta dfe50c3
refactor(features): remove unused legacy types from types.ts
talissoncosta 9fae3b0
refactor(features): replace custom error UI with reusable ErrorMessag…
talissoncosta a7a4c32
fix(features): correct error handling placement and logic
talissoncosta 63747eb
feat(features): improve error message UX with user-friendly context
talissoncosta 0efba2a
feat(features): add skeleton loader for features list
talissoncosta 0345bdb
refactor(features): simplify display logic and remove useFeaturePageD…
talissoncosta 92c10a4
refactor(features): remove unused showCreateButton prop from Features…
talissoncosta 69c2df2
docs: remove excessive documentation from hooks and utilities
talissoncosta 63863e6
docs: simplify documentation in useProjectEnvironments and featureFil…
talissoncosta 97db45b
refactor(features): clean up FeaturesTableFilters and optimize useFea…
talissoncosta f526820
tests: keep backwards compatibility on creating a new flag
talissoncosta c38567d
fix(features): add backward compatibility and cache sync for CreateFl…
talissoncosta 83a2639
Merge remote-tracking branch 'origin/main' into refactor/migrate-crit…
talissoncosta 5d80d29
fix: lint
talissoncosta 8f858e1
fix(features): prevent empty state flash and ensure proper cache sync
talissoncosta 30f4094
refactor: clean up dead code and make internal helpers non-exported
talissoncosta d8bf596
refactor: convert TagStrategy type to enum
talissoncosta 7c18d34
refactor: add type-safe URL parameter parsing helpers to featureFilte…
talissoncosta 6e24a23
feat: add useFeatureListWithApiKey wrapper hook
talissoncosta 76084a1
refactor: clean up unnecessary and verbose comments
talissoncosta 496afe4
fix: address PR review feedback (typo and parseInt radix)
talissoncosta 3fcad5a
feat(features): add dark mode and improve FeatureRowSkeleton structure
talissoncosta 30f6b79
Merge remote-tracking branch 'origin/main' into refactor/migrate-crit…
talissoncosta 51e67c9
fix: show "no results" instead of empty state when filters return no …
talissoncosta 84e1c3d
fix: prevent search input interruption during loading
talissoncosta 77f85c8
refactor: remove unnecessary comments from FeaturesPage
talissoncosta cb597b9
refactor(services): consolidate useFeatureList into useProjectFlag
talissoncosta 85a3e1e
refactor(config): move FEATURES_PAGE_SIZE to service layer
talissoncosta e663a16
refactor(hooks): consolidate page tracking hooks
talissoncosta cf9cbc7
chore: remove unnecessary comments from useProjectFlag
talissoncosta 826c010
fix: resolve loading flow issues and filter parameter handling
talissoncosta 2d79857
refactor: remove unnecessary comments and duplicate code
talissoncosta 735cb2b
fix: improve loading flow and skeleton display in FeaturesPage
talissoncosta 2299462
refactor: remove unused multivariate option type definitions
talissoncosta 6d8fb5a
refactor: migrate to unified usePageTracking hook pattern
talissoncosta fe6a05e
docs: remove documentation file reference from code comment
talissoncosta ce88590
refactor: simplify Utils type definition using typeof
talissoncosta c705d7d
refactor: move updateFeatureState mutation to useFeatureState service
talissoncosta 306bfca
refactor: consolidate PermissionGate into Permission component
talissoncosta c89dd4f
chore: remove unnecessary comments from refactored files
talissoncosta aa89314
docs: add comprehensive JSDoc to Permission component
talissoncosta 0e331ab
fix(hooks): prevent excessive re-renders in usePageTracking
talissoncosta b69386a
fix(services): invalidate environment metrics cache on feature removal
talissoncosta 67bccc5
fix(providers): enable tooltips for Permission component with render …
talissoncosta 336502c
fix: adapt callback signatures in Compare components for FeatureRow c…
talissoncosta 53e5b7a
fix: handle project/environment errors to prevent infinite loading state
talissoncosta a176fa9
Merge remote-tracking branch 'origin/main' into refactor/migrate-crit…
talissoncosta 2bd4560
fix(features): add permissionName to Permission tooltip for readable UX
talissoncosta 3e522b2
fix(features): resolve Cursor bot issues for sort order and permissio…
talissoncosta 11a1dfe
refactor(features): remove unnecessary ConfigProvider HOC
talissoncosta bca9d30
fix(features): fix object spread overriding default pagination values
talissoncosta File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,39 @@ | ||
| import { useMemo } from 'react' | ||
| import { skipToken } from '@reduxjs/toolkit/query' | ||
| import { useGetFeatureListQuery } from 'common/services/useProjectFlag' | ||
| import { useProjectEnvironments } from './useProjectEnvironments' | ||
| import { buildApiFilterParams } from 'common/utils/featureFilterParams' | ||
| import type { FilterState } from 'common/types/featureFilters' | ||
|
|
||
| /** | ||
| * Fetches filtered feature list, accepting environment API key instead of numeric ID. | ||
| * | ||
| * TODO: This wrapper will be removed once we standardize environmentId and environmentApiKey on RouteContext. | ||
| */ | ||
| export function useFeatureListWithApiKey( | ||
| filters: FilterState, | ||
| page: number, | ||
| environmentApiKey: string | undefined, | ||
| projectId: number | undefined, | ||
| ): ReturnType<typeof useGetFeatureListQuery> { | ||
| const { getEnvironmentIdFromKey, isLoading: isLoadingEnvironments } = | ||
| useProjectEnvironments(projectId!) | ||
|
|
||
| const apiParams = useMemo(() => { | ||
| if (!environmentApiKey || !projectId || !getEnvironmentIdFromKey) { | ||
| return null | ||
| } | ||
| return buildApiFilterParams( | ||
| filters, | ||
| page, | ||
| environmentApiKey, | ||
| projectId, | ||
| getEnvironmentIdFromKey, | ||
| ) | ||
| }, [filters, page, environmentApiKey, projectId, getEnvironmentIdFromKey]) | ||
|
|
||
| return useGetFeatureListQuery(apiParams ?? skipToken, { | ||
| refetchOnMountOrArgChange: true, | ||
| skip: isLoadingEnvironments, | ||
| }) | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,84 @@ | ||
| import { useEffect } from 'react' | ||
|
|
||
| /** | ||
| * Options for configuring page tracking behavior. | ||
| */ | ||
| export type PageTrackingOptions = { | ||
| /** The page constant name from Constants.pages */ | ||
| pageName: string | ||
| /** Context data for tracking and storage persistence */ | ||
| context?: { | ||
| environmentId?: string | ||
| projectId?: number | ||
| organisationId?: number | ||
| } | ||
| /** Whether to save context to AsyncStorage (default: false) */ | ||
| saveToStorage?: boolean | ||
| /** Custom dependencies for re-tracking on changes */ | ||
| deps?: React.DependencyList | ||
| } | ||
|
|
||
| /** | ||
| * Unified hook for tracking page views with optional context persistence. | ||
| * | ||
| * Consolidates both page tracking and environment context storage into a single, | ||
| * flexible hook. Automatically calls API.trackPage and optionally persists | ||
| * environment context to AsyncStorage. | ||
| * | ||
| * @param options - Configuration object for page tracking | ||
| * | ||
| * @example | ||
| * ```tsx | ||
| * // Basic page tracking only | ||
| * usePageTracking({ pageName: Constants.pages.FEATURES }) | ||
| * | ||
| * // With context and storage persistence | ||
| * usePageTracking({ | ||
| * pageName: Constants.pages.FEATURES, | ||
| * context: { environmentId, projectId, organisationId }, | ||
| * saveToStorage: true, | ||
| * }) | ||
| * | ||
| * // With custom dependencies | ||
| * usePageTracking({ | ||
| * pageName: Constants.pages.FEATURES, | ||
| * context: { projectId }, | ||
| * deps: [projectId, someOtherDep], | ||
| * }) | ||
| * ``` | ||
| */ | ||
| export function usePageTracking(options: PageTrackingOptions): void { | ||
| const { context, deps = [], pageName, saveToStorage = false } = options | ||
|
|
||
| // Track page view | ||
| useEffect(() => { | ||
| if (typeof API !== 'undefined' && API.trackPage) { | ||
| API.trackPage(pageName) | ||
| } | ||
| // eslint-disable-next-line react-hooks/exhaustive-deps | ||
| }, deps) | ||
|
|
||
| // Persist environment context to storage if enabled | ||
| useEffect(() => { | ||
| if (saveToStorage && context) { | ||
| if (typeof AsyncStorage !== 'undefined' && AsyncStorage.setItem) { | ||
| AsyncStorage.setItem( | ||
| 'lastEnv', | ||
| JSON.stringify({ | ||
| environmentId: context.environmentId, | ||
| orgId: context.organisationId, | ||
| projectId: context.projectId, | ||
| }), | ||
| ) | ||
| } | ||
| } | ||
| // We intentionally use individual properties instead of context object | ||
| // to prevent re-runs when object reference changes but values don't | ||
Zaimwa9 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| // eslint-disable-next-line react-hooks/exhaustive-deps | ||
| }, [ | ||
| saveToStorage, | ||
| context?.environmentId, | ||
| context?.organisationId, | ||
| context?.projectId, | ||
| ]) | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,58 @@ | ||
| import { useCallback, useMemo } from 'react' | ||
| import { useGetEnvironmentsQuery } from 'common/services/useEnvironment' | ||
| import { useGetProjectQuery } from 'common/services/useProject' | ||
| import type { Environment, Project } from 'common/types/responses' | ||
|
|
||
| interface UseProjectEnvironmentsResult { | ||
| project: Project | undefined | ||
| environments: Environment[] | ||
| getEnvironmentIdFromKey: (apiKey: string) => number | undefined | ||
| getEnvironment: (apiKey: string) => Environment | undefined | ||
| isLoading: boolean | ||
| error: Error | undefined | ||
| } | ||
|
|
||
| /** Fetches project and environment data with accessor functions for API key lookups. */ | ||
| export function useProjectEnvironments( | ||
| projectId: number, | ||
| ): UseProjectEnvironmentsResult { | ||
| const { | ||
| data: project, | ||
| error: projectError, | ||
| isLoading: isLoadingProject, | ||
| } = useGetProjectQuery({ id: projectId }, { skip: !projectId }) | ||
|
|
||
| const { | ||
| data: environmentsData, | ||
| error: environmentsError, | ||
| isLoading: isLoadingEnvironments, | ||
| } = useGetEnvironmentsQuery({ projectId }, { skip: !projectId }) | ||
|
|
||
| const environments = useMemo( | ||
| () => environmentsData?.results ?? [], | ||
| [environmentsData?.results], | ||
| ) | ||
|
|
||
| const getEnvironmentIdFromKey = useCallback( | ||
| (apiKey: string): number | undefined => { | ||
| return environments.find((env) => env.api_key === apiKey)?.id | ||
| }, | ||
| [environments], | ||
| ) | ||
|
|
||
| const getEnvironment = useCallback( | ||
| (apiKey: string): Environment | undefined => { | ||
| return environments.find((env) => env.api_key === apiKey) | ||
| }, | ||
| [environments], | ||
| ) | ||
|
|
||
| return { | ||
| environments, | ||
talissoncosta marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| error: projectError || environmentsError, | ||
| getEnvironment, | ||
| getEnvironmentIdFromKey, | ||
| isLoading: isLoadingProject || isLoadingEnvironments, | ||
| project, | ||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.