[Development] Fix a Virto Commerce module's Admin SPA (AngularJS) UI that ships inside the module's own vc-module-* repo — blade/widget/service anatomy + idiomatic AngularJS 1.x. Two proof paths, because module repos have NO JS test harness and there is NO Storybook: logic bugs (save/payload, computed value, wrong endpoint) are proven red→green with a throwaway Node scratch harness; layout/CSS/visual bugs (overlap, misalignment, wrong width, clipping) are fixed by mirroring the platform's can...
Installs into .claude/skills of the current project.
Are you the author of Angular Admin?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/virtocommerce-angular-admin-vc-mcp-testing-module)
---
name: angular-admin
description: "[Development] Fix a Virto Commerce module's Admin SPA (AngularJS) UI that ships inside the module's own vc-module-* repo — blade/widget/service anatomy + idiomatic AngularJS 1.x. Two proof paths, because module repos have NO JS test harness and there is NO Storybook: logic bugs (save/payload, computed value, wrong endpoint) are proven red→green with a throwaway Node scratch harness; layout/CSS/visual bugs (overlap, misalignment, wrong width, clipping) are fixed by mirroring the platform's canonical UI classes (catalog bundled in this skill) and proven in a browser BEFORE the PR via a visual render harness — never inline position/fixed-px. Used by the fullstack-backend developer agent in /qa-fix when the owning layer is the module Admin UI (still single-repo)."
---
# /angular-admin — Fix a module's Admin SPA UI
Fix an Admin-UI bug that lives in a `vc-module-*` repo under `src/VirtoCommerce.<Name>.Web/Scripts/`.
Because the Admin UI ships **inside the module repo**, this is still a **single-repo** fix
(Gate 1 passes) and is owned by `fullstack-backend`.
## Reality check (read this first)
The Scripts area is **hand-written AngularJS 1.x served as static assets** — no bundler, no
`package.json`, no Karma, no spec files, **in any `vc-module-*` repo** (org-wide survey, 2026-06).
There is no in-repo JS test command to run, and you must NOT scaffold one (no `package.json`,
`karma.conf.js`, or spec files committed to the module — that's framework churn, an instant G4 fail).
So Gate 2 (red→green proof) is satisfied by a throwaway harness outside the repo — and **which harness
depends on the bug** (see *Two fix paths* below):
- **Logic** bugs → a **Node scratch harness**: a script in `.fix-workspace/_scratch/<ticket-key>/`
(gitignored, never committed, never in the PR diff) that loads the real blade/service file with a stubbed
`angular` global, drives the buggy seam, and asserts the expected behavior. Red before, green after —
both runs' output pasted into the PR body. Recipe + verified stub: `scratch-harness-patterns.md`.
- **Layout/CSS** bugs → a **visual render harness** (the Node harness can't render CSS): renders the real
blade against the real `platform.css` in a browser, red→green screenshots before the PR. See the
Layout/CSS path below + `visual-render-harness.md`.
Either way the harness is throwaway — only its evidence (output / screenshots) ships, in the PR body.
## When to use
- The `/qa-bug` owning layer is **Layer 2 — Backend Admin (Admin SPA)** AND the responsible code is in
the routed module's `Web/Scripts/`. (A storefront/`vc-frontend` Vue bug is out of `/qa-fix` backend
scope — that's the CI frontend agent's lane.)
## Two fix paths — routed by WHERE THE SYMPTOM IS OBSERVED, not by which file you edit
Read the ticket's **Actual result** sentence and ask one question: *is what it describes visible only in
a rendered DOM?*
- **YES — a rendered-DOM symptom** (text or markup wrong / literal / missing / stale, an element absent
or not updating, overlap, misalignment, wrong width, clipping, spacing, a control in the wrong place)
→ the **browser path** below. A Node process cannot observe a DOM, so it can never be the proof for
one of these however clean its red→green looks. This holds even when the DIFF is pure JS.
- **NO — a non-rendered symptom** (wrong saved payload, wrong computed value, wrong endpoint or field,
wrong request) → the **Node scratch harness** path (Steps 1–5 below): `scratch-harness-patterns.md`.
- A bug with both uses both harnesses. **If you cannot decide, it is the browser path.**
> **This routing IS the gate, and it has been got wrong.** VCST-5940 (a preview iframe rendering a
> literal template placeholder) was routed to the Node path because the fix touched a controller. The
> harness proved the controller's assignment timing red→green, review approved at HIGH confidence, CI
> was fully green — and the bug reproduced 3/3 on the deployed artifact. "No JS test harness in the
> repo" is **not** a reason to skip the browser: the render harness needs no repo test infrastructure
> at all (templates and `platform.css` are runtime-loaded static assets).
### Layout/CSS path
1. **Read `admin-spa-ui-conventions.md`** (in this skill) — the platform's canonical class vocabulary +
per-element snippets + reference blades. There is NO Storybook; that catalog + real blades are the
style guide.
2. **Mirror a canonical sibling blade** — `Grep` `*.tpl.html` for the element's class (`searchrow`,
`ui-select`, `table-wrapper`, `vc-checkbox`, …), prefer the same module, else `vc-module-pricing`. Copy
its structure. **Never** add inline `position:absolute|fixed`, fixed-px `width/height/left/top`, or inline
`ng-style` height. Note `blade-static` is **fixed-height** — a multi-row toolbar (e.g. a note above the
searchrow) must reserve height via `__expanded` or move the note into content (conventions §2.1).
Recipes: `css-layout-patterns.md`.
3. **MEASURE, then prove it before the PR** — the gate is a **numeric geometry assertion**, not a screenshot
(a screenshot gave a false PASS on VCST-5276). Run the read-only measurement script (conventions §4) in a
browser: capture the **failing** geometry (`overlapPx > 0`), apply the fix, re-measure, require
`searchrow.bottom <= gridHeader.top` (`overlapPx === 0`). Then build the **visual render harness**
(`visual-render-harness.md`) for the red→green picture; `qa-backend-expert` runs both. Iterate dev↔QA ≤2×
and squash. **Measurement numbers + screenshots** go in the PR body. (Harness can't stub it → escalate to
the full local-platform fallback; don't skip the proof.)
4. **Gate** (build + Gate 4) as in the logic path below, then hand off with the measurement + screenshots.
## Steps (logic-bug path)
1. **Locate** the blade / widget / controller / service / template under `Web/Scripts/` (`Grep`/`Glob`
on blade ids, template text, controller names, settings keys). See `angular-patterns.md` for the
anatomy (module.js registration → blades/ → widgets/ → resources/).
2. **Reproduce (red) in the scratch harness.** Write
`.fix-workspace/_scratch/<ticket-key>/repro.cjs` (the `.cjs` extension is required — the workspace
sits under a `"type": "module"` package.json) following `scratch-harness-patterns.md`: stub
`angular`, `require` the real file from the checkout, instantiate the controller/factory with
stubbed collaborators, assert the EXPECTED behavior. `node repro.cjs` must **fail** on current
code. If it passes, the RCA is wrong → re-investigate.
3. **Fix (green):** smallest correct change to the blade/service/template; idiomatic AngularJS,
matching the file's existing conventions (controllerAs vs `$scope`, `$q`, DI-array style).
`node repro.cjs` now exits 0. Capture both outputs for the PR body.
4. **Trivial-skip is now narrow:** a change with **no rendered-DOM symptom** and no assertable logic
(a one-line null-guard, a typo, an off-by-one) — justify in the PR body. A binding, label, attribute
or interpolation whose defect is *visible on screen* is a rendered-DOM symptom: it goes the browser
path above and is proven with the render harness. Never skipped, and never substituted with a
controller-state assertion.
5. **Gate:** `dotnet build -c Debug -p:NuGetAudit=false` still green (Scripts are content files — the
C# build embeds them; make sure nothing broke). Hand the diff to `backend-reviewer` (Gate 4) with
the scratch-harness evidence in the summary.
## Hard rules
- **Single repo** — all changes in the one `vc-module-*` (its `Web/Scripts/` and/or C#). Second repo → STOP.
- **The scratch harness never ships.** Nothing under `_scratch/` is committed; the PR diff contains
only the fix. No new build steps, no `package.json`, no framework/version changes in the repo.
- **Minimal diff**; never touch secrets/lockfiles/CI config.
- Match the module's existing AngularJS conventions; don't restyle, restructure, or "modernize".
- **Layout/CSS fixes use only platform classes** (`admin-spa-ui-conventions.md`) — never inline
`position:absolute|fixed`, fixed-px sizing, or `ng-style` height hacks — and are **proven before the PR**
with the visual render harness (`visual-render-harness.md`), not deferred to post-deploy.
- Same gate ladder and **no-auto-merge** as the C# path — `.claude/rules/quality-gates.md`.
## References
- `admin-spa-ui-conventions.md` — canonical platform UI class catalog (blades, search, filters, dropdowns,
inputs, buttons, grids, checkboxes, dialogs, lists) + discovery recipe — **read before any layout/CSS fix**
- `css-layout-patterns.md` — before/after layout fix recipes
- `visual-render-harness.md` — pre-PR browser proof for layout/CSS fixes
- `scratch-harness-patterns.md` — verified Node stub for `angular`, worked red→green example (logic bugs)
- `angular-patterns.md` — VC Admin SPA blade/widget/service anatomy
- `knowledge/architecture/vc-module-architecture.md` §2 (Admin UI ships in the module repo)