AgentSkillsCN

migrate-page

将页面从传统MVC迁移到Angular SPA + API。根据需要,统筹网格、地图、模态框与工作流子技能。

SKILL.md
--- frontmatter
name: migrate-page
description: Migrate a page from legacy MVC to Angular SPA + API. Orchestrates grid, map, modal, and workflow sub-skills as needed.
allowed-tools: [Read, Glob, Grep, Edit, Write, Bash(dotnet build:*), Bash(npm run gen-model:*), Bash(dotnet test:*), Bash(npm test:*), Skill(migrate-grid), Skill(migrate-map), Skill(crud-modal), Skill(migrate-workflow)]
argument-hint: <EntityName>

Migrate Page Skill

When the user invokes /migrate-page <EntityName>:

1. Analyze Legacy Code

First, thoroughly examine the existing MVC implementation:

  • Read the legacy controller: Neptune.WebMvc/Controllers/{Entity}Controller.cs
  • Read all views in: Neptune.WebMvc/Views/{Entity}/
  • Check for partials in: Neptune.WebMvc/Views/Shared/ that may be used
  • Look for JavaScript in: Neptune.WebMvc/Scripts/ related to the entity

Identify and document:

  • All CRUD operations (Index, Detail, New, Edit, Delete)
  • Special/custom endpoints
  • Bootstrap patterns used (panels, tables, forms, modals)
  • Client-side validation or JavaScript behavior
  • Related entities and their relationships
  • Authorization/permission requirements

Identify Components Requiring Specialized Skills

Based on your analysis, note which of these components the page contains:

Component FoundSpecialized SkillWhen to Use
Data tables/grids/migrate-gridIndex pages, detail pages with related entity lists
Maps with boundaries/locations/migrate-mapPages showing spatial data
Create/Edit forms/crud-modalPages with New/Edit functionality
Multi-step wizards/migrate-workflowPages with sequential data entry steps

Document which skills you'll need for this migration.

2. Plan API Layer

Before writing code, plan the artifacts needed:

DTOs to create:

  • {Entity}GridDto — Fields needed for list/index view
  • {Entity}Dto — Fields for detail view including related data
  • {Entity}UpsertDto — Fields for create/edit forms
  • {Entity}SimpleDto — If used in dropdowns elsewhere

Identify:

  • Which related entities need to be Included for extension methods
  • Query optimization opportunities (avoid N+1)
  • Validation rules to implement

3. Create API Files

Create the following files in order:

3.1 DTOs

Location: Neptune.Models/DataTransferObjects/

  • {Entity}GridDto.cs
  • {Entity}Dto.cs
  • {Entity}UpsertDto.cs

3.2 Extension Methods

Extension methods are generated by scaffold in Neptune.EFModels/Entities/Generated/ExtensionMethods/{Entity}ExtensionMethods.cs. If you need custom extension methods beyond what scaffold generates, add them in Neptune.EFModels/Entities/ as a partial class or separate file:

  • AsDto() — Full detail mapping
  • AsGridDto() — Grid row mapping
  • AsSimpleDto() — Simple/dropdown mapping

3.3 Static Helpers

Location: Neptune.EFModels/Entities/{PluralEntity}.cs

  • ListAsDtoAsync() or ListAsGridDto()
  • GetByIDAsDto()
  • GetByID()
  • GetByIDWithChangeTracking()
  • CreateNew()
  • Update()
  • DeleteAsync()

3.4 Controller

Location: Neptune.API/Controllers/{Entity}Controller.cs

  • Extend SitkaController<{Entity}Controller>(dbContext, logger, neptuneConfiguration) with primary constructor (3 params)
  • Implement endpoints matching the DTOs

3.5 Authorization

Apply authorization attributes to controller endpoints based on legacy feature attributes.

Step 1: Identify legacy features Search for Feature] in the legacy controller:

bash
grep -E "Feature\]" Neptune.WebMvc/Controllers/{Entity}Controller.cs

Step 2: Map to Neptune authorization attributes

Legacy Feature PatternNew AttributeRoles
Public/anonymous endpoint[AllowAnonymous]No auth required
Admin-only operations[AdminFeature]Admin, SitkaAdmin
SitkaAdmin-only operations[SitkaAdminFeature]SitkaAdmin
Jurisdiction edit operations[JurisdictionEditFeature]Admin, SitkaAdmin, JurisdictionManager, JurisdictionEditor (+ jurisdiction match)
Jurisdiction manage operations[JurisdictionManageFeature]Admin, SitkaAdmin, JurisdictionManager (+ jurisdiction match)
Any authenticated user[UserViewFeature]All logged-in users
Unassigned users[LoggedInUnclassifiedFeature]Unassigned users

Step 3: Apply attributes

  • Add using Neptune.API.Services.Authorization; to the controller
  • Add using Microsoft.AspNetCore.Authorization; if using [AllowAnonymous]
  • Apply appropriate attribute to each endpoint:
    • GET endpoints (public data): Usually [AllowAnonymous] or [UserViewFeature]
    • POST/PUT/DELETE: Apply the feature attribute that matches the legacy feature

Example:

csharp
[HttpGet]
[UserViewFeature]
public ActionResult<List<EntityGridDto>> List() { ... }

[HttpPost]
[AdminFeature]
public ActionResult<EntityDto> Create([FromBody] EntityUpsertDto dto) { ... }

[HttpPut("{entityID}")]
[JurisdictionEditFeature]
public ActionResult<EntityDto> Update([FromRoute] int entityID, [FromBody] EntityUpsertDto dto) { ... }

4. Generate TypeScript

After API code is complete:

powershell
# Build the API to generate swagger.json
dotnet build Neptune.API/Neptune.API.csproj -c Debug

# Generate TypeScript models
cd Neptune.Web
npm run gen-model

Verify the generated files in Neptune.Web/src/app/shared/generated/.

5. Create Angular Components

5.1 Component Structure

Location: Neptune.Web/src/app/pages/{entity}/

Create the folder structure based on identified components:

  • {entity}-list/ — If page has a main grid (use /migrate-grid)
  • {entity}-detail/ — If page has a detail view
  • {entity}-modal/ — If page needs create/edit forms (use /crud-modal)

All components must be standalone with explicit imports. Use @Input() with BehaviorSubject pattern for route params.

5.2 Grids

If the page contains data grids, follow the /migrate-grid skill for:

  • Column definition patterns
  • DTO design for grid rows
  • Grid component usage (neptune-grid)

5.3 Maps

If the page contains maps, follow the /migrate-map skill for:

  • GeoJSON endpoint patterns
  • Map component integration (neptune-map)
  • Layer component usage

5.4 CRUD Modals

If the page needs create/edit/delete functionality, follow the /crud-modal skill for:

  • Modal component structure
  • Form creation with generated helpers
  • Validation patterns
  • Delete confirmation patterns

5.5 Route Configuration

Add route to Neptune.Web/src/app/app.routes.ts:

typescript
{
  path: 'entities',
  children: [
    {
      path: '',
      loadComponent: () => import('./pages/entity/entity-list/entity-list.component').then(m => m.EntityListComponent)
    },
    {
      path: ':entityID',
      loadComponent: () => import('./pages/entity/entity-detail/entity-detail.component').then(m => m.EntityDetailComponent)
    }
  ]
}

5.6 Route Guards

Apply guards as needed:

GuardPurpose
UnsavedChangesGuardPrevents navigation away from unsaved form changes

Auth checks are typically done within components using AuthenticationService.

6. Write Tests

6.1 API Tests (MSTest)

Location: Neptune.Tests/

  • Test all controller actions
  • Use in-memory database
  • Test success and error cases
  • Remember 3-param constructor: new EntityController(dbContext, logger, Options.Create(new NeptuneConfiguration()))

6.2 Angular Tests (Jasmine)

Location: Same folder as component with .spec.ts extension

  • Test component creation
  • Test data loading
  • Test user interactions
  • Mock services with jasmine.createSpyObj

7. Remove/Deprecate Legacy Code

After migration is complete and tested:

  • Add [Obsolete("Migrated to Angular SPA")] attribute to legacy controller
  • Or remove legacy controller/views entirely if safe
  • Update any internal links to point to new Angular routes

8. Run Tests and Verify

powershell
# Run API tests
dotnet test Neptune.Tests/Neptune.Tests.csproj

# Run Angular tests
cd Neptune.Web
npm test

# Manual verification
npm start
# Navigate to new pages and verify functionality

Checklist Before Completion

Core Migration

  • All CRUD operations migrated
  • Route params use @Input() + BehaviorSubject pattern
  • All queries use .AsNoTracking() with .Include() then .Select(x => x.AsDto())

Authorization

  • Legacy feature attributes identified for each action
  • Appropriate authorization attributes applied to all endpoints
  • Public GET endpoints marked with [AllowAnonymous] or [UserViewFeature]
  • Create/Edit/Delete endpoints protected with feature attributes

If Page Has Grids (per /migrate-grid)

  • Column parity verified with legacy
  • Filtering/sorting works
  • Links navigate correctly

If Page Has Maps (per /migrate-map)

  • All layers display correctly
  • Bounds/zoom behavior correct
  • Layer toggle works (if applicable)

If Page Has CRUD (per /crud-modal)

  • Create flow works
  • Edit flow works
  • Delete confirmation works
  • Form validation displays correctly

Final

  • API tests pass
  • Angular tests pass
  • Legacy code deprecated/removed
  • Manual testing complete