Refactor of the ApplicationSet UI coupling
Summary
When the ApplicationSet UI was added, the applications files were used and if conditions where added to handle the ApplicationSet use case. This has become a limitation to introduce new features to the appset UI. While many components must be reused like the resource tree and list views, they are currently not re-usable as shared components.
Motivation
Ensure the ApplicationSet UI can grow without exponentially increasing the complexity of the UI components
Proposal
Since this is a big refactor with multiple file move and partial extraction, this cannot be done in one big-bang refactor PR. This would simply have too much risk of merge conflicts without a major code freeze. Instead, most of the existing components can be extracted on by one, to eventually be able to rework highly coupled components such as the application ResourceDetail.
Structure
shared/components/resource/*— per-kind resource building blocks (a node/resource kind and how it's displayed).shared/components/resource-helpers/*+shared/components/app-utils— kind-agnostic logic/helpers.shared/components/views/*— the list/details/tree view scaffolding shared by the Application and ApplicationSet screens.applications/andapplicationsets/— only genuinely kind-specific code.
Phase 0 — Scaffolding (must come first)
-
applicationsets/module + route split. Create theapplicationsets/folder andApplicationSetsContainer; register the/applicationsetslazy route inapp.tsx. Carve the appset entry point out of the applications list/details so there's a place to receive extracted code. -
shared/components/app-utils.tsx. Extract the kind-agnostic status primitives + type guards + appset domain logic:ComparisonStatusIcon,HealthStatusIcon,isApp,appInstanceName,appQualifiedName,getAppSetHealthStatus,getAppSetConditionCategory,isAppNode,isAppSetNode,getApplicationParentRef. Depended on by almost everything below.
Phase 1 — Leaf primitives (Tier 0)
-
resource-icon→shared/components/resource/. -
resource-label→shared/components/resource/. -
resources.ts(kind/status maps) →shared/components/resource/. -
resource-customizations.ts→shared/components/resource/. -
application-urls.tsx→shared/components/resource/. -
view-type-switcher→shared/components/(only needs shared context/services). -
filterwidget (Filter/FiltersGroup+ scss) →shared/components/filter/. Prerequisite for every filter and for resource-list/resource-filter.
Phase 2 — Helper modules (Tier 1)
-
resource-helpers— extract kind-agnostic helpers fromutils.tsx(nodeKey,getAppUrl,getAppListLink,PodHealthIcon,getPodStateReason,formatCreationTimestamp,resourceStatusToResourceNode,handlePageVisibility,getApplicationLinkURLFromNode,userMsgsList, source helpers…) intoshared/components/resource-helpers/; re-export fromutils.tsx. Breaks theutils ↔ treecycle; keystone for Phase 3–4. -
list-search— consolidate the duplicatedcreateMatcher(applications + resources) intoshared/components/list-search.ts(+ merged test). -
filtersmodule —label-selector,selectors(createMetadataSelector),favorite(favoriteKey/isFavorite/toggleFavorite),FavoriteFilter,LabelsFilter→shared/components/filters/; re-export favorites throughutils.tsx.
Phase 3 — Mid resource components (Tier 2)
-
application-resource-sort→shared/components/resource/. -
application-resource-filter(+ test) →shared/components/resource/(needs filter widget + resource-helpers). -
application-resource-list(+ scss) →shared/components/resource/. -
resource-highlight-pulse.scss→shared/components/resource/(shared scss partial imported by list + tree; move before/with the tree).
Phase 4 — Heavy resource components (Tier 3)
-
application-resource-tree/→shared/components/resource/. -
application-pod-view/→shared/components/resource/. -
application-node-info/→shared/components/resource/. -
application-resources-diff/→shared/components/resource/.
Phase 5 — Shared view scaffolding (shared/components/views/)
-
shared/components/views/details/tree-filter.ts—NodeInfo,SelectNode,getTreeFilter,filterTreeNode, wildcard/escape helpers. -
shared/components/views/tree/load-application-info.ts—loadApplicationInfo. -
shared/components/views/tree/resource-tree-toolbar.tsx— graph options panel (zoom/expand/group/name direction). -
shared/components/views/tree/application-details-filters.tsx— filter portal wrapper. -
shared/components/views/list/use-items-per-container.ts— list layout hook shared by both list views.
Phase 6 — Per-kind split (this is the actual refactor of the most entangled components)
-
ApplicationDetails→ app-only. DropobjectListKind, collapse everyisApplicationbranch to its app side, remove appset imports; compose the Phase 5 scaffolding. -
ApplicationSetDetails— new thin appset view composing the same scaffolding (no branching). - App-dropdown split —
ApplicationsDetailsAppDropdownapp-only (hardcodeargo-icon-application); duplicate asApplicationSetsDetailsAppDropdown(hardcodeargo-icon-applicationset) + co-located scss. - Filter split —
ApplicationsFilterapp-only; newapplicationsets-filterreusingFavoriteFilter/LabelsFilter. - Status bar split —
AppsStatusBarapp-only;AppSetsStatusBar→applicationsets/. - Conditions split —
applicationset-conditions(+ co-located scss). - Status panel split —
appset-status-panel(+ co-located scss). - Per-kind list rows/tiles/summary —
appset-tile,appset-table-row,application-sets-summaryinapplicationsets/, importing icons/helpers from shared (notapplications/).
Phase 7 — Resource details (the complex tail, last)
- App resource actions — extract
deleteApplication(+isChildApplication) into sharedresource-helpers/resource-actions.ts; re-export fromutils.tsx. -
appset-generated-app-details— trimmed appset view for generated-app + root-appset nodes only (SUMMARY/EVENTS), reusing shared header/tree/diff. - Invert
AppSetResourceNodePreview— remove theapplications → applicationsetsimport fromResourceDetailsvia an injected node-preview seam. - Shared
ResourceDetailsHeader→shared/components/views/details(icon/label/health/comparison/links/actions). - Shared
ResourceTabsshell →shared/components/views/details(Tabs + extension wiring + manifest/YAML/EVENTS), with app-only tabs (ApplicationParameters,ApplicationSummary) injected. -
applications/ResourceDetails→ shared shell. Collapse into a thin composition over shared header + tabs + injected preview; repointresources/resources-details-panel; optionally retire the appset duplicate onto the shared shell.
All these items are the result of a coupling analysis and are subject to changes as the implementation progresses.
Source: argoproj/argo-cd