feat(ui): reconnect registry-admin under integration hub [SPRINT-023]
Mount registry-admin routes under canonical /ops/integrations (and /setup/integrations) with plans list, editor, and audit flows reachable from integration-hub entry points. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,20 +1,23 @@
|
||||
/**
|
||||
* Integration Hub Routes
|
||||
* Updated: SPRINT_20260220_031_FE_platform_global_ops_integrations_setup_advisory_recheck
|
||||
* Updated: Sprint 023 - Registry admin mounted under integrations (FE-URG-002)
|
||||
*
|
||||
* Canonical Integrations taxonomy:
|
||||
* '' - Hub overview with health summary and category navigation
|
||||
* registries - Container registries
|
||||
* scm - Source control managers
|
||||
* ci - CI/CD systems
|
||||
* runtime-hosts - Runtime and host connector inventory
|
||||
* feeds - Advisory source connectors
|
||||
* vex-sources - VEX source connectors
|
||||
* secrets - Secrets managers / vaults
|
||||
* :id - Integration detail (standard contract template)
|
||||
* '' - Hub overview with health summary and category navigation
|
||||
* registries - Container registries
|
||||
* scm - Source control managers
|
||||
* ci - CI/CD systems
|
||||
* runtime-hosts - Runtime and host connector inventory
|
||||
* feeds - Advisory source connectors
|
||||
* vex-sources - VEX source connectors
|
||||
* secrets - Secrets managers / vaults
|
||||
* registry-admin - Registry plan management and audit (Sprint 023)
|
||||
* :id - Integration detail (standard contract template)
|
||||
*
|
||||
* Ownership boundary:
|
||||
* hosts/targets/agents are managed in Topology and only aliased here.
|
||||
* registry-admin is an integration-management capability, not a standalone branch.
|
||||
*/
|
||||
|
||||
import { Routes } from '@angular/router';
|
||||
@@ -116,6 +119,21 @@ export const integrationHubRoutes: Routes = [
|
||||
import('./integration-activity.component').then((m) => m.IntegrationActivityComponent),
|
||||
},
|
||||
|
||||
// Registry admin mounted as integration-management capability (Sprint 023).
|
||||
// Canonical URLs (via Ops or Setup parent):
|
||||
// /ops/integrations/registry-admin - Plan list
|
||||
// /setup/integrations/registry-admin/plans - Plan list
|
||||
// /setup/integrations/registry-admin/plans/new - Create plan
|
||||
// /setup/integrations/registry-admin/plans/:planId - Edit plan
|
||||
// /setup/integrations/registry-admin/audit - Audit trail
|
||||
{
|
||||
path: 'registry-admin',
|
||||
title: 'Registry Admin',
|
||||
data: { breadcrumb: 'Registry Admin' },
|
||||
loadChildren: () =>
|
||||
import('../registry-admin/registry-admin.routes').then((m) => m.registryAdminRoutes),
|
||||
},
|
||||
|
||||
{
|
||||
path: ':integrationId',
|
||||
title: 'Integration Detail',
|
||||
|
||||
@@ -1,8 +1,22 @@
|
||||
// Registry Admin Routes
|
||||
// Sprint 023: Registry Admin UI
|
||||
// Updated: Sprint 023 (FE-URG-002) - Mounted under integration hub at
|
||||
// /ops/integrations/registry-admin and /setup/integrations/registry-admin
|
||||
// Ownership stays inside the Integrations shell.
|
||||
|
||||
import { Routes } from '@angular/router';
|
||||
|
||||
/**
|
||||
* Registry Admin Routes
|
||||
*
|
||||
* Mounted under integration-hub/registry-admin by integration-hub.routes.ts (Sprint 023).
|
||||
* Canonical URLs (relative to integrations parent):
|
||||
* registry-admin - Plan list (default)
|
||||
* registry-admin/plans - Plan list (explicit)
|
||||
* registry-admin/plans/new - Create plan
|
||||
* registry-admin/plans/:planId - Edit plan
|
||||
* registry-admin/audit - Audit trail
|
||||
*/
|
||||
export const registryAdminRoutes: Routes = [
|
||||
{
|
||||
path: '',
|
||||
@@ -11,6 +25,8 @@ export const registryAdminRoutes: Routes = [
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
title: 'Registry Plans',
|
||||
data: { breadcrumb: 'Plans' },
|
||||
loadComponent: () =>
|
||||
import('./components/plan-list.component').then(
|
||||
(m) => m.PlanListComponent
|
||||
@@ -18,6 +34,8 @@ export const registryAdminRoutes: Routes = [
|
||||
},
|
||||
{
|
||||
path: 'plans',
|
||||
title: 'Registry Plans',
|
||||
data: { breadcrumb: 'Plans' },
|
||||
loadComponent: () =>
|
||||
import('./components/plan-list.component').then(
|
||||
(m) => m.PlanListComponent
|
||||
@@ -25,6 +43,8 @@ export const registryAdminRoutes: Routes = [
|
||||
},
|
||||
{
|
||||
path: 'plans/new',
|
||||
title: 'Create Registry Plan',
|
||||
data: { breadcrumb: 'Create Plan' },
|
||||
loadComponent: () =>
|
||||
import('./components/plan-editor.component').then(
|
||||
(m) => m.PlanEditorComponent
|
||||
@@ -32,6 +52,8 @@ export const registryAdminRoutes: Routes = [
|
||||
},
|
||||
{
|
||||
path: 'plans/:planId',
|
||||
title: 'Edit Registry Plan',
|
||||
data: { breadcrumb: 'Edit Plan' },
|
||||
loadComponent: () =>
|
||||
import('./components/plan-editor.component').then(
|
||||
(m) => m.PlanEditorComponent
|
||||
@@ -39,6 +61,8 @@ export const registryAdminRoutes: Routes = [
|
||||
},
|
||||
{
|
||||
path: 'audit',
|
||||
title: 'Registry Audit',
|
||||
data: { breadcrumb: 'Audit' },
|
||||
loadComponent: () =>
|
||||
import('./components/plan-audit.component').then(
|
||||
(m) => m.PlanAuditComponent
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
/**
|
||||
* Integration Hub Routes - Route structure verification
|
||||
* Sprint 023: FE-URG-004
|
||||
*
|
||||
* Validates that registry-admin routes are mounted inside the integration
|
||||
* hub under the canonical Integrations shell, before the catch-all
|
||||
* :integrationId route, and without creating a standalone product branch.
|
||||
*/
|
||||
import { integrationHubRoutes } from '../features/integration-hub/integration-hub.routes';
|
||||
|
||||
describe('integrationHubRoutes', () => {
|
||||
// The integration hub uses a shell component with children
|
||||
const shellRoute = integrationHubRoutes[0];
|
||||
const children = shellRoute?.children ?? [];
|
||||
|
||||
it('should have a shell route with children', () => {
|
||||
expect(shellRoute).toBeDefined();
|
||||
expect(shellRoute.path).toBe('');
|
||||
expect(children.length).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
it('should mount registry-admin as a child route', () => {
|
||||
const registryAdminRoute = children.find((r) => r.path === 'registry-admin');
|
||||
expect(registryAdminRoute).toBeDefined();
|
||||
expect(registryAdminRoute!.loadChildren).toBeDefined();
|
||||
expect(registryAdminRoute!.title).toBe('Registry Admin');
|
||||
expect(registryAdminRoute!.data?.['breadcrumb']).toBe('Registry Admin');
|
||||
});
|
||||
|
||||
it('should place registry-admin before the catch-all :integrationId route', () => {
|
||||
const registryAdminIndex = children.findIndex((r) => r.path === 'registry-admin');
|
||||
const catchAllIndex = children.findIndex((r) => r.path === ':integrationId');
|
||||
|
||||
expect(registryAdminIndex).toBeGreaterThan(-1);
|
||||
expect(catchAllIndex).toBeGreaterThan(-1);
|
||||
expect(registryAdminIndex).toBeLessThan(catchAllIndex);
|
||||
});
|
||||
|
||||
it('should not introduce a standalone registry-admin route outside integration hub', () => {
|
||||
// Only the integration hub shell contains registry-admin
|
||||
// There should be no top-level registry-admin path
|
||||
const topLevelPaths = integrationHubRoutes.map((r) => r.path);
|
||||
expect(topLevelPaths).not.toContain('registry-admin');
|
||||
});
|
||||
|
||||
it('should preserve existing integration hub category routes', () => {
|
||||
const childPaths = children.map((r) => r.path);
|
||||
expect(childPaths).toContain('registries');
|
||||
expect(childPaths).toContain('scm');
|
||||
expect(childPaths).toContain('ci');
|
||||
expect(childPaths).toContain('secrets');
|
||||
expect(childPaths).toContain('activity');
|
||||
});
|
||||
|
||||
it('should use loadChildren for lazy-loaded registry-admin routes', () => {
|
||||
const registryAdminRoute = children.find((r) => r.path === 'registry-admin');
|
||||
expect(registryAdminRoute).toBeDefined();
|
||||
expect(typeof registryAdminRoute!.loadChildren).toBe('function');
|
||||
expect(registryAdminRoute!.loadComponent).toBeUndefined();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user