@abgov/nx-adsp 13.31.0 → 13.31.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. package/README.md +41 -32
  2. package/package.json +1 -1
  3. package/src/generators/angular-app/angular-app.js +2 -2
  4. package/src/generators/angular-app/files/AGENTS.md__tmpl__ +16 -0
  5. package/src/generators/express-service/express-service.spec.ts +26 -13
  6. package/src/generators/express-service/schema.json +1 -1
  7. package/src/generators/react-app/files/AGENTS.md__tmpl__ +16 -0
  8. package/src/generators/react-app/react-app.js +2 -2
  9. package/src/generators/vue-admin-crud/files/src/views/__editViewFileName__.vue__tmpl__ +3 -5
  10. package/src/generators/vue-admin-crud/files/src/views/__listViewFileName__.vue__tmpl__ +33 -4
  11. package/src/generators/vue-admin-crud/schema.d.ts +2 -0
  12. package/src/generators/vue-admin-crud/schema.json +7 -8
  13. package/src/generators/vue-admin-crud/vue-admin-crud.js +6 -1
  14. package/src/generators/vue-admin-crud/vue-admin-crud.js.map +1 -1
  15. package/src/generators/vue-admin-crud/vue-admin-crud.spec.ts +96 -13
  16. package/src/generators/vue-app/files/AGENTS.md__tmpl__ +56 -11
  17. package/src/generators/vue-app/files/src/App.vue__tmpl__ +2 -1
  18. package/src/generators/vue-app/files/src/composables/useApi.spec.ts__tmpl__ +5 -3
  19. package/src/generators/vue-app/files/src/composables/useApi.ts__tmpl__ +14 -2
  20. package/src/generators/vue-app/vue-app.js +33 -6
  21. package/src/generators/vue-app/vue-app.js.map +1 -1
  22. package/src/generators/vue-app/vue-app.spec.ts +133 -13
  23. package/src/generators/vue-components/files/AGENTS.md__tmpl__ +36 -17
  24. package/src/generators/vue-components/files/src/index.ts__tmpl__ +3 -0
  25. package/src/generators/vue-components/files/src/lib/formatters.ts__tmpl__ +58 -0
  26. package/src/generators/vue-components/files/src/lib/patterns/AppSideMenu.vue__tmpl__ +14 -3
  27. package/src/generators/vue-components/files/src/lib/patterns/FilterBar.vue__tmpl__ +7 -1
  28. package/src/generators/vue-components/files/src/lib/patterns/WorkspaceTable.vue__tmpl__ +7 -1
  29. package/src/generators/vue-components/vue-components.d.ts +1 -0
  30. package/src/generators/vue-components/vue-components.js +18 -39
  31. package/src/generators/vue-components/vue-components.js.map +1 -1
  32. package/src/generators/vue-components/vue-components.spec.ts +94 -2
  33. package/src/generators/vue-detail-view/files/src/views/__viewFileName__.vue__tmpl__ +51 -2
  34. package/src/generators/vue-detail-view/schema.d.ts +18 -0
  35. package/src/generators/vue-detail-view/schema.json +2 -2
  36. package/src/generators/vue-detail-view/vue-detail-view.js +4 -1
  37. package/src/generators/vue-detail-view/vue-detail-view.js.map +1 -1
  38. package/src/generators/vue-detail-view/vue-detail-view.spec.ts +36 -6
  39. package/src/generators/vue-intake-view/files/shared/src/views/__confirmationViewFileName__.vue__tmpl__ +60 -6
  40. package/src/generators/vue-intake-view/files/shared/src/views/__reviewViewFileName__.vue__tmpl__ +37 -1
  41. package/src/generators/vue-intake-view/files/steps/src/views/__stepViewFileName__.vue__tmpl__ +1 -1
  42. package/src/generators/vue-intake-view/schema.d.ts +10 -0
  43. package/src/generators/vue-intake-view/schema.json +12 -9
  44. package/src/generators/vue-intake-view/vue-intake-view.js +9 -3
  45. package/src/generators/vue-intake-view/vue-intake-view.js.map +1 -1
  46. package/src/generators/vue-intake-view/vue-intake-view.spec.ts +113 -12
  47. package/src/generators/vue-workspace-view/files/src/views/__viewFileName__.vue__tmpl__ +49 -1
  48. package/src/generators/vue-workspace-view/schema.d.ts +22 -0
  49. package/src/generators/vue-workspace-view/schema.json +8 -9
  50. package/src/generators/vue-workspace-view/vue-workspace-view.js +7 -1
  51. package/src/generators/vue-workspace-view/vue-workspace-view.js.map +1 -1
  52. package/src/generators/vue-workspace-view/vue-workspace-view.spec.ts +73 -7
  53. package/src/utils/paired-project.d.ts +10 -0
  54. package/src/utils/paired-project.js +125 -18
  55. package/src/utils/paired-project.js.map +1 -1
  56. package/src/utils/paired-project.spec.ts +126 -0
  57. package/src/utils/quality.js +43 -9
  58. package/src/utils/quality.js.map +1 -1
  59. package/src/utils/quality.spec.ts +35 -2
  60. package/src/utils/vue-eslint.d.ts +2 -0
  61. package/src/utils/vue-eslint.js +48 -0
  62. package/src/utils/vue-eslint.js.map +1 -0
  63. package/src/utils/vue-side-menu.d.ts +13 -1
  64. package/src/utils/vue-side-menu.js +50 -5
  65. package/src/utils/vue-side-menu.js.map +1 -1
  66. package/src/utils/vue-side-menu.spec.ts +100 -0
  67. package/src/utils/vue-tsconfig.d.ts +26 -0
  68. package/src/utils/vue-tsconfig.js +49 -0
  69. package/src/utils/vue-tsconfig.js.map +1 -0
@@ -1,4 +1,10 @@
1
- import { readProjectConfiguration, Tree } from '@nx/devkit';
1
+ import {
2
+ readJson,
3
+ readProjectConfiguration,
4
+ Tree,
5
+ updateJson,
6
+ writeJson,
7
+ } from '@nx/devkit';
2
8
  import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing';
3
9
  import generator, {
4
10
  ensurePackageExports,
@@ -179,7 +185,9 @@ describe('Vue Components Generator', () => {
179
185
  // Shared value formatters: every view renders a date/count the same way
180
186
  // instead of inlining its own toLocaleString (which is what a real app did
181
187
  // in three separate views before this existed).
182
- expect(host.exists('libs/vue-components/src/lib/formatters.ts')).toBeTruthy();
188
+ expect(
189
+ host.exists('libs/vue-components/src/lib/formatters.ts'),
190
+ ).toBeTruthy();
183
191
  expect(
184
192
  host.exists('libs/vue-components/src/lib/formatters.spec.ts'),
185
193
  ).toBeTruthy();
@@ -191,6 +199,12 @@ describe('Vue Components Generator', () => {
191
199
  'formatDateTime',
192
200
  'formatNumber',
193
201
  'formatPercent',
202
+ // Display of a *coded* value, the other half of formatting. Views that
203
+ // skipped these put raw domain codes and neutral-blue badges in front of
204
+ // citizens, so they live beside the date/number formatters rather than
205
+ // being re-derived per view.
206
+ 'optionLabel',
207
+ 'badgeType',
194
208
  ]) {
195
209
  expect(formatters).toContain(`export function ${fn}`);
196
210
  }
@@ -322,4 +336,82 @@ describe('Vue Components Generator', () => {
322
336
  expect(host.exists('libs/vue-components/package.json')).toBeFalsy();
323
337
  });
324
338
  });
339
+
340
+ it('exports the display helpers from the lib barrel, not just the module', async () => {
341
+ await generator(host);
342
+ const index = host.read('libs/vue-components/src/index.ts').toString();
343
+ expect(index).toContain('optionLabel');
344
+ expect(index).toContain('badgeType');
345
+ expect(index).toContain('DisplayOption');
346
+ expect(index).toContain('BadgeType');
347
+ }, 30000);
348
+
349
+ it('falls back to the raw value for an unmapped code rather than hiding it', async () => {
350
+ await generator(host);
351
+ const formatters = host
352
+ .read('libs/vue-components/src/lib/formatters.ts')
353
+ .toString();
354
+ // An unmapped code is a data/config problem; showing it is debuggable,
355
+ // blanking it is not.
356
+ expect(formatters).toContain('return match ? match.label : String(value)');
357
+ // And an unmapped badge value stays neutral rather than being asserted good
358
+ // or bad.
359
+ expect(formatters).toContain("fallback: BadgeType = 'information'");
360
+ }, 30000);
361
+
362
+ // Regression: @nx/vue writes `moduleResolution: "bundler"` into the lib's
363
+ // tsconfig but leaves `module` inherited. Against a create-nx-workspace base
364
+ // (`module: "nodenext"`) that pair is invalid -- TS5095 and TS5109 -- so
365
+ // `nx build` failed on completely unmodified generator output.
366
+ it('gives the lib a module setting compatible with its bundler moduleResolution', async () => {
367
+ writeJson(host, 'tsconfig.base.json', {
368
+ compilerOptions: {
369
+ module: 'nodenext',
370
+ moduleResolution: 'nodenext',
371
+ target: 'es2022',
372
+ },
373
+ });
374
+ await generator(host);
375
+ const compilerOptions = readJson(
376
+ host,
377
+ 'libs/vue-components/tsconfig.json',
378
+ ).compilerOptions;
379
+ expect(compilerOptions.moduleResolution).toBe('bundler');
380
+ expect(compilerOptions.module).toBe('esnext');
381
+ }, 30000);
382
+
383
+ it('leaves a tsconfig that already declares module alone', async () => {
384
+ await generator(host);
385
+ // Pin something deliberate, then re-run: the backfill must not overwrite it.
386
+ updateJson(host, 'libs/vue-components/tsconfig.json', (tsconfig) => {
387
+ tsconfig.compilerOptions.module = 'preserve';
388
+ return tsconfig;
389
+ });
390
+ await generator(host);
391
+ expect(
392
+ readJson(host, 'libs/vue-components/tsconfig.json').compilerOptions
393
+ .module,
394
+ ).toBe('preserve');
395
+ }, 30000);
396
+
397
+ // Regression: goa-work-side-menu's profile button takes its accessible name
398
+ // only from `user-name` (no aria-label prop exists on the element), and the
399
+ // shell rendered the account slot -- which is what creates that button --
400
+ // without ever supplying one. Measured on pristine generator output, that was
401
+ // an unnamed critical `button-name` violation plus an unlabelled `role-img-alt`
402
+ // icon on every route of an internal-layout app.
403
+ it('never leaves the side menu profile button without an accessible name', async () => {
404
+ await generator(host);
405
+ const sideMenu = host
406
+ .read('libs/vue-components/src/lib/patterns/AppSideMenu.vue')
407
+ .toString();
408
+
409
+ // Resolved, not passed straight through: an empty string is the realistic
410
+ // input (a signed-out user), and withDefaults only covers `undefined`.
411
+ expect(sideMenu).toContain(
412
+ "const profileName = computed(() => props.userName?.trim() || 'Account')",
413
+ );
414
+ expect(sideMenu).toContain(':user-name="profileName"');
415
+ expect(sideMenu).not.toContain(':user-name="userName"');
416
+ }, 30000);
325
417
  });
@@ -1,8 +1,52 @@
1
1
  <script setup lang="ts">
2
2
  import { ref, watch } from 'vue';
3
3
  import { useRoute, useRouter } from 'vue-router';
4
- import { RecordDetailShell, formatCurrency, formatDate } from '<%= goaImportPath %>';
4
+ import {
5
+ RecordDetailShell,
6
+ formatCurrency,
7
+ formatDate,
8
+ <% if (hasCodedFields || hasBadgeFields) { -%>
9
+ optionLabel,
10
+ <% } -%>
11
+ <% if (hasBadgeFields) { -%>
12
+ badgeType,
13
+ <% } -%>
14
+ } from '<%= goaImportPath %>';
15
+ <% if (hasCodedFields || hasBadgeFields) { -%>
16
+ import type {
17
+ <% if (hasCodedFields || hasBadgeFields) { -%>
18
+ DisplayOption,
19
+ <% } -%>
20
+ <% if (hasBadgeFields) { -%>
21
+ BadgeType,
22
+ <% } -%>
23
+ } from '<%= goaImportPath %>';
24
+ <% } -%>
5
25
  import { useApi } from '../composables/useApi';
26
+ <% if (hasCodedFields || hasBadgeFields) { -%>
27
+
28
+ // Value -> label for coded fields, so the record reads back in prose rather than
29
+ // in stored codes.
30
+ const fieldOptions: Record<string, DisplayOption[]> = {
31
+ <% fields.forEach(function (field) { -%>
32
+ <% if (field.options && field.options.length) { -%>
33
+ '<%= field.key %>': <%- JSON.stringify(field.options) %>,
34
+ <% } -%>
35
+ <% }); -%>
36
+ };
37
+ <% } -%>
38
+ <% if (hasBadgeFields) { -%>
39
+
40
+ // Value -> badge type; unmapped values render neutral rather than being asserted
41
+ // as good or bad.
42
+ const fieldBadgeTypes: Record<string, Record<string, BadgeType>> = {
43
+ <% fields.forEach(function (field) { -%>
44
+ <% if (field.type === 'badge') { -%>
45
+ '<%= field.key %>': <%- JSON.stringify(field.badgeMap || {}) %>,
46
+ <% } -%>
47
+ <% }); -%>
48
+ };
49
+ <% } -%>
6
50
 
7
51
  // The fetched record's shape isn't known to this generator -- read fields
8
52
  // defensively rather than declaring (and likely getting wrong) a fake interface.
@@ -52,7 +96,12 @@ function goBack() {
52
96
  <dt><%= field.label %></dt>
53
97
  <dd>
54
98
  <% if (field.type === 'badge') { -%>
55
- <goa-badge type="information" :content="String(record['<%= field.key %>'] ?? '—')" />
99
+ <goa-badge
100
+ :type="badgeType(fieldBadgeTypes['<%= field.key %>'], record['<%= field.key %>'])"
101
+ :content="optionLabel(fieldOptions['<%= field.key %>'], record['<%= field.key %>'])"
102
+ />
103
+ <% } else if (field.options && field.options.length) { -%>
104
+ {{ optionLabel(fieldOptions['<%= field.key %>'], record['<%= field.key %>']) }}
56
105
  <% } else if (field.type === 'date') { -%>
57
106
  {{ formatDate(record['<%= field.key %>']) }}
58
107
  <% } else if (field.type === 'currency') { -%>
@@ -2,6 +2,24 @@ export interface DetailViewField {
2
2
  key: string;
3
3
  label: string;
4
4
  type?: 'text' | 'date' | 'currency' | 'badge';
5
+ /**
6
+ * Value -> label for a coded field. Supply this whenever the stored value is a
7
+ * code rather than prose, or the view renders the raw code.
8
+ */
9
+ options?: { value: string; label: string }[];
10
+ /**
11
+ * `badge` only. Value -> goa-badge type. Unmapped values render neutral.
12
+ */
13
+ badgeMap?: Record<
14
+ string,
15
+ | 'information'
16
+ | 'success'
17
+ | 'important'
18
+ | 'emergency'
19
+ | 'dark'
20
+ | 'midtone'
21
+ | 'light'
22
+ >;
5
23
  }
6
24
 
7
25
  export interface Schema {
@@ -25,7 +25,7 @@
25
25
  },
26
26
  "resource": {
27
27
  "type": "string",
28
- "description": "API resource path segment -- the view fetches /api/<resource>/:id."
28
+ "description": "API resource path segment -- the view fetches /api/v1/<resource>/:id."
29
29
  },
30
30
  "route": {
31
31
  "type": "string",
@@ -33,7 +33,7 @@
33
33
  },
34
34
  "fields": {
35
35
  "type": "string",
36
- "description": "JSON array of fields rendered in the record's info list, in display order -- e.g. '[{\"key\":\"status\",\"label\":\"Status\",\"type\":\"badge\"}]'. Each item: { key, label, type?: \"text\"|\"date\"|\"currency\"|\"badge\" (default \"text\") }. A plain array is also accepted when this generator is invoked programmatically. Nx's CLI option coercion only supports comma-separated primitive lists for array-typed schema properties, not JSON -- a JSON string is the only CLI syntax that actually survives Nx's own arg parsing for a structured list like this."
36
+ "description": "JSON array of fields rendered in the record's info list, in display order -- e.g. '[{\"key\":\"status\",\"label\":\"Status\",\"type\":\"badge\"}]'. Each item: { key, label, type?: \"text\"|\"date\"|\"currency\"|\"badge\" (default \"text\"), options?: [{value,label}], badgeMap?: {value: badgeType} }. Supply `options` for any field whose stored value is a code, or the view renders the raw code. Supply `badgeMap` on a `badge` field to give each status its colour; unmapped values render neutral. A plain array is also accepted when this generator is invoked programmatically. Nx's CLI option coercion only supports comma-separated primitive lists for array-typed schema properties, not JSON -- a JSON string is the only CLI syntax that actually survives Nx's own arg parsing for a structured list like this."
37
37
  },
38
38
  "heading": {
39
39
  "type": "string",
@@ -38,7 +38,10 @@ function default_1(host, options) {
38
38
  // Idempotent -- ensures RecordDetailShell exists even in a project scaffolded
39
39
  // before vue-components carried it.
40
40
  yield (0, vue_components_1.default)(host);
41
- (0, devkit_1.generateFiles)(host, path.join(__dirname, 'files'), normalizedOptions.projectRoot, Object.assign(Object.assign({}, normalizedOptions), { goaImportPath: (0, vue_components_1.vueComponentsImportPath)(host), tmpl: '' }));
41
+ (0, devkit_1.generateFiles)(host, path.join(__dirname, 'files'), normalizedOptions.projectRoot, Object.assign(Object.assign({}, normalizedOptions), { goaImportPath: (0, vue_components_1.vueComponentsImportPath)(host),
42
+ // Derived here, not tested inline: EJS throws a ReferenceError on a bare
43
+ // undefined variable, so a flag the template reads must always be defined.
44
+ hasCodedFields: normalizedOptions.fields.some((field) => { var _a; return (_a = field.options) === null || _a === void 0 ? void 0 : _a.length; }), hasBadgeFields: normalizedOptions.fields.some((field) => field.type === 'badge'), tmpl: '' }));
42
45
  (0, vue_router_1.insertVueRoute)(host, normalizedOptions.projectRoot, normalizedOptions.project, {
43
46
  path: normalizedOptions.route,
44
47
  componentImportPath: `../views/${normalizedOptions.viewFileName}.vue`,
@@ -1 +1 @@
1
- {"version":3,"file":"vue-detail-view.js","sourceRoot":"","sources":["../../../../../../packages/nx-adsp/src/generators/vue-detail-view/vue-detail-view.ts"],"names":[],"mappings":";;AAqDA,4BAyBC;;AA9ED,uCAMoB;AACpB,6BAA6B;AAC7B,uDAAwD;AACxD,qEAE0C;AAG1C,6EAA6E;AAC7E,4EAA4E;AAC5E,4EAA4E;AAC5E,6EAA6E;AAC7E,0EAA0E;AAC1E,6EAA6E;AAC7E,iEAAiE;AACjE,SAAS,WAAW,CAAC,MAAwB;IAC3C,MAAM,MAAM,GAAG,OAAO,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;IACxE,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAClD,MAAM,IAAI,KAAK,CACb,2EAA2E,CAC5E,CAAC;IACJ,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,gBAAgB,CAAC,IAAU,EAAE,OAAe;;IACnD,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,GAAG,IAAA,iCAAwB,EAAC,IAAI,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;IAE9E,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QACnC,MAAM,IAAI,KAAK,CACb,YAAY,OAAO,CAAC,KAAK,qFAAqF,CAC/G,CAAC;IACJ,CAAC;IAED,MAAM,SAAS,GAAG,IAAA,cAAK,EAAC,OAAO,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC;IAChD,uCACK,OAAO,KACV,WAAW,EACX,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,MAAM,CAAC,EACnC,YAAY,EAAE,GAAG,SAAS,MAAM;QAChC,2EAA2E;QAC3E,mDAAmD;QACnD,OAAO,EAAE,MAAA,OAAO,CAAC,OAAO,mCAAI,SAAS,CAAC,OAAO,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC,IAAI,EAAE,EACvE,YAAY,EAAE,MAAA,OAAO,CAAC,YAAY,mCAAI,IAAI,IAC1C;AACJ,CAAC;AAED,mBAA+B,IAAU,EAAE,OAAe;;QACxD,MAAM,iBAAiB,GAAG,gBAAgB,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAE1D,8EAA8E;QAC9E,oCAAoC;QACpC,MAAM,IAAA,wBAAsB,EAAC,IAAI,CAAC,CAAC;QAEnC,IAAA,sBAAa,EACX,IAAI,EACJ,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,OAAO,CAAC,EAC7B,iBAAiB,CAAC,WAAW,kCAExB,iBAAiB,KACpB,aAAa,EAAE,IAAA,wCAAuB,EAAC,IAAI,CAAC,EAC5C,IAAI,EAAE,EAAE,IAEX,CAAC;QAEF,IAAA,2BAAc,EAAC,IAAI,EAAE,iBAAiB,CAAC,WAAW,EAAE,iBAAiB,CAAC,OAAO,EAAE;YAC7E,IAAI,EAAE,iBAAiB,CAAC,KAAK;YAC7B,mBAAmB,EAAE,YAAY,iBAAiB,CAAC,YAAY,MAAM;YACrE,YAAY,EAAE,iBAAiB,CAAC,YAAY;SAC7C,CAAC,CAAC;QAEH,MAAM,IAAA,oBAAW,EAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;CAAA"}
1
+ {"version":3,"file":"vue-detail-view.js","sourceRoot":"","sources":["../../../../../../packages/nx-adsp/src/generators/vue-detail-view/vue-detail-view.ts"],"names":[],"mappings":";;AAqDA,4BAsCC;;AA3FD,uCAMoB;AACpB,6BAA6B;AAC7B,uDAAwD;AACxD,qEAE0C;AAG1C,6EAA6E;AAC7E,4EAA4E;AAC5E,4EAA4E;AAC5E,6EAA6E;AAC7E,0EAA0E;AAC1E,6EAA6E;AAC7E,iEAAiE;AACjE,SAAS,WAAW,CAAC,MAAwB;IAC3C,MAAM,MAAM,GAAG,OAAO,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;IACxE,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAClD,MAAM,IAAI,KAAK,CACb,2EAA2E,CAC5E,CAAC;IACJ,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,gBAAgB,CAAC,IAAU,EAAE,OAAe;;IACnD,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,GAAG,IAAA,iCAAwB,EAAC,IAAI,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;IAE9E,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QACnC,MAAM,IAAI,KAAK,CACb,YAAY,OAAO,CAAC,KAAK,qFAAqF,CAC/G,CAAC;IACJ,CAAC;IAED,MAAM,SAAS,GAAG,IAAA,cAAK,EAAC,OAAO,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC;IAChD,uCACK,OAAO,KACV,WAAW,EACX,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,MAAM,CAAC,EACnC,YAAY,EAAE,GAAG,SAAS,MAAM;QAChC,2EAA2E;QAC3E,mDAAmD;QACnD,OAAO,EAAE,MAAA,OAAO,CAAC,OAAO,mCAAI,SAAS,CAAC,OAAO,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC,IAAI,EAAE,EACvE,YAAY,EAAE,MAAA,OAAO,CAAC,YAAY,mCAAI,IAAI,IAC1C;AACJ,CAAC;AAED,mBAA+B,IAAU,EAAE,OAAe;;QACxD,MAAM,iBAAiB,GAAG,gBAAgB,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAE1D,8EAA8E;QAC9E,oCAAoC;QACpC,MAAM,IAAA,wBAAsB,EAAC,IAAI,CAAC,CAAC;QAEnC,IAAA,sBAAa,EACX,IAAI,EACJ,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,OAAO,CAAC,EAC7B,iBAAiB,CAAC,WAAW,kCAExB,iBAAiB,KACpB,aAAa,EAAE,IAAA,wCAAuB,EAAC,IAAI,CAAC;YAC5C,yEAAyE;YACzE,2EAA2E;YAC3E,cAAc,EAAE,iBAAiB,CAAC,MAAM,CAAC,IAAI,CAC3C,CAAC,KAAK,EAAE,EAAE,WAAC,OAAA,MAAA,KAAK,CAAC,OAAO,0CAAE,MAAM,CAAA,EAAA,CACjC,EACD,cAAc,EAAE,iBAAiB,CAAC,MAAM,CAAC,IAAI,CAC3C,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,OAAO,CAClC,EACD,IAAI,EAAE,EAAE,IAEX,CAAC;QAEF,IAAA,2BAAc,EACZ,IAAI,EACJ,iBAAiB,CAAC,WAAW,EAC7B,iBAAiB,CAAC,OAAO,EACzB;YACE,IAAI,EAAE,iBAAiB,CAAC,KAAK;YAC7B,mBAAmB,EAAE,YAAY,iBAAiB,CAAC,YAAY,MAAM;YACrE,YAAY,EAAE,iBAAiB,CAAC,YAAY;SAC7C,CACF,CAAC;QAEF,MAAM,IAAA,oBAAW,EAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;CAAA"}
@@ -102,19 +102,23 @@ describe('Vue Detail View Generator', () => {
102
102
  .read('apps/test/src/views/ApplicationDetailView.vue')
103
103
  .toString();
104
104
  expect(view).toContain('heading="Application Detail"');
105
- expect(view).toContain("await get('applications', String(route.params.id))");
105
+ expect(view).toContain(
106
+ "await get('applications', String(route.params.id))",
107
+ );
106
108
  expect(view).not.toContain('apiFetch');
107
109
 
108
110
  // Vue Router reuses this component across an id-only change, so the fetch
109
111
  // is driven by a watch rather than onMounted.
110
- expect(view).toContain("watch(() => route.params.id, load, { immediate: true })");
112
+ expect(view).toContain(
113
+ 'watch(() => route.params.id, load, { immediate: true })',
114
+ );
111
115
  expect(view).not.toContain('onMounted(');
112
116
  expect(view).not.toContain('function formatCurrency');
113
117
 
114
118
  expect(view).toContain('formatDate');
115
119
  expect(view).not.toContain('function formatDate');
116
120
  expect(view).toContain(
117
- "<goa-badge type=\"information\" :content=\"String(record['status'] ?? '')\" />",
121
+ "badgeType(fieldBadgeTypes['status'], record['status'])",
118
122
  );
119
123
  // A type: 'date' column is a calendar date -- formatDate, not
120
124
  // formatDateTime, which would show an invented midnight.
@@ -168,9 +172,7 @@ describe('Vue Detail View Generator', () => {
168
172
  it('ensures the shared RecordDetailShell pattern component exists', async () => {
169
173
  await generator(host, baseOptions);
170
174
  expect(
171
- host.exists(
172
- 'libs/vue-components/src/lib/patterns/RecordDetailShell.vue',
173
- ),
175
+ host.exists('libs/vue-components/src/lib/patterns/RecordDetailShell.vue'),
174
176
  ).toBeTruthy();
175
177
  }, 30000);
176
178
 
@@ -180,4 +182,32 @@ describe('Vue Detail View Generator', () => {
180
182
  const after = readProjectConfiguration(host, 'test');
181
183
  expect(after).toEqual(before);
182
184
  }, 30000);
185
+
186
+ it('maps badge values to semantic types and renders coded fields as labels', async () => {
187
+ await generator(host, {
188
+ ...baseOptions,
189
+ fields: [
190
+ {
191
+ key: 'status',
192
+ label: 'Status',
193
+ type: 'badge',
194
+ badgeMap: { declined: 'emergency' },
195
+ },
196
+ {
197
+ key: 'region',
198
+ label: 'Region',
199
+ options: [{ value: 'northwest', label: 'North west' }],
200
+ },
201
+ ],
202
+ });
203
+ const view = host
204
+ .read('apps/test/src/views/ApplicationDetailView.vue')
205
+ .toString();
206
+ // Quote style depends on whether formatFiles ran, so match the pair.
207
+ expect(view).toMatch(/["']?declined["']?\s*:\s*["']emergency["']/);
208
+ expect(view).toContain("badgeType(fieldBadgeTypes['status']");
209
+ expect(view).toContain(
210
+ "optionLabel(fieldOptions['region'], record['region'])",
211
+ );
212
+ }, 30000);
183
213
  });
@@ -1,20 +1,74 @@
1
1
  <script setup lang="ts">
2
+ import { ref, onMounted } from 'vue';
2
3
  import { useRoute } from 'vue-router';
4
+ import { useApi } from '../composables/useApi';
3
5
 
4
6
  const route = useRoute();
7
+ const { get } = useApi();
8
+
9
+ // The confirmation page fetches the submitted record rather than reading the id
10
+ // out of the route, so it can show the business reference the person will quote
11
+ // back to us. The route id is a storage detail -- presenting it as "your
12
+ // reference number" hands them a number that means nothing to anyone they later
13
+ // talk to.
14
+ const record = ref<Record<string, unknown> | null>(null);
15
+ const loading = ref(true);
16
+
17
+ // Falls back to the route id only when the record has no reference field, so the
18
+ // page still shows something actionable rather than a blank.
19
+ const reference = ref(String(route.params.id ?? ''));
20
+
21
+ onMounted(async () => {
22
+ try {
23
+ const id = String(route.params.id ?? '');
24
+ record.value = (await get('<%- resource %>', id)) as Record<string, unknown>;
25
+ const value = record.value?.['<%- referenceField %>'];
26
+ if (value !== null && value !== undefined && value !== '') {
27
+ reference.value = String(value);
28
+ }
29
+ } catch {
30
+ // A failed lookup must not blank the confirmation: the submission already
31
+ // succeeded, and the route id is still a usable fallback reference.
32
+ } finally {
33
+ loading.value = false;
34
+ }
35
+ });
5
36
  </script>
6
37
 
7
38
  <template>
8
39
  <div>
9
- <goa-callout type="success" heading="Submitted">
10
- <p>
11
- Your reference number is <strong>{{ route.params.id }}</strong>. Keep this for your
12
- records.
13
- </p>
40
+ <goa-callout type="success" heading="<%- heading %> submitted">
41
+ <h1 class="confirmation-reference">
42
+ Your reference number is
43
+ <strong>{{ loading ? '…' : reference }}</strong>
44
+ </h1>
45
+ <p>Keep this for your records. You'll need it to check on your submission.</p>
14
46
  </goa-callout>
15
47
 
48
+ <goa-spacer vspacing="l" />
49
+
50
+ <h2>What happens next</h2>
51
+ <ol>
52
+ <li>We'll review what you submitted.</li>
53
+ <li>We'll contact you if we need anything further.</li>
54
+ <li>We'll let you know the outcome.</li>
55
+ </ol>
56
+
16
57
  <goa-spacer vspacing="m" />
17
58
 
18
- <p>You'll be notified of any updates. No further action is needed right now.</p>
59
+ <router-link to="/">
60
+ <goa-button type="secondary">Return to the start</goa-button>
61
+ </router-link>
19
62
  </div>
20
63
  </template>
64
+
65
+ <style scoped>
66
+ /* The reference is the page's heading in the GDS confirmation pattern -- an h1
67
+ for landmark/screen-reader order, sized to sit inside the callout rather than
68
+ at page-title scale. */
69
+ .confirmation-reference {
70
+ font-size: var(--goa-typography-heading-m-font-size, 1.25rem);
71
+ line-height: var(--goa-typography-heading-m-line-height, 1.5);
72
+ margin: 0 0 var(--goa-space-s, 0.75rem);
73
+ }
74
+ </style>
@@ -5,11 +5,30 @@ import { GoabCheckbox } from '<%= goaImportPath %>';
5
5
  <% if (steps.some((s) => s.fields.some((f) => f.type === 'date'))) { -%>
6
6
  import { formatDate } from '<%= goaImportPath %>';
7
7
  <% } -%>
8
+ <% if (hasCodedFields) { -%>
9
+ import { optionLabel } from '<%= goaImportPath %>';
10
+ import type { DisplayOption } from '<%= goaImportPath %>';
11
+ <% } -%>
8
12
  import { useApi } from '../composables/useApi';
9
13
 
10
14
  const route = useRoute();
11
15
  const router = useRouter();
12
16
  const { get, action } = useApi();
17
+ <% if (hasCodedFields) { -%>
18
+
19
+ // Value -> label for every coded field across the steps. Check-your-answers is
20
+ // where this matters most: the page exists so the person can read back what they
21
+ // entered, and a stored code ('cattle-mature', 'northwest') is not that.
22
+ const fieldOptions: Record<string, DisplayOption[]> = {
23
+ <% steps.forEach(function (step) { -%>
24
+ <% step.fields.forEach(function (field) { -%>
25
+ <% if (field.options && field.options.length) { -%>
26
+ '<%- field.key %>': <%- JSON.stringify(field.options) %>,
27
+ <% } -%>
28
+ <% }); -%>
29
+ <% }); -%>
30
+ };
31
+ <% } -%>
13
32
 
14
33
  const idParam = computed(() => String(route.params.id ?? ''));
15
34
 
@@ -79,11 +98,13 @@ async function onSubmit() {
79
98
  Edit
80
99
  </goa-button>
81
100
  </div>
82
- <dl>
101
+ <dl class="review-fields">
83
102
  <% step.fields.forEach(function (field) { -%>
84
103
  <dt><%- field.label %></dt>
85
104
  <% if (field.type === 'date') { -%>
86
105
  <dd>{{ formatDate(record['<%- field.key %>']) }}</dd>
106
+ <% } else if (field.options && field.options.length) { -%>
107
+ <dd>{{ optionLabel(fieldOptions['<%- field.key %>'], record['<%- field.key %>']) }}</dd>
87
108
  <% } else { -%>
88
109
  <dd>{{ record['<%- field.key %>'] ?? '—' }}</dd>
89
110
  <% } -%>
@@ -125,4 +146,19 @@ async function onSubmit() {
125
146
  align-items: center;
126
147
  gap: var(--goa-space-m);
127
148
  }
149
+
150
+ /* A bare <dl> stacks its terms and values flush, so every answer ran into the
151
+ next one on the page whose whole job is being read back. Two columns, label
152
+ distinguished by weight -- matching vue-detail-view's .detail-fields, since
153
+ both render a record as label/value pairs and should not look different. */
154
+ .review-fields {
155
+ display: grid;
156
+ grid-template-columns: auto 1fr;
157
+ gap: var(--goa-space-xs) var(--goa-space-l);
158
+ margin: 0;
159
+ }
160
+
161
+ .review-fields dt {
162
+ font-weight: 600;
163
+ }
128
164
  </style>
@@ -213,7 +213,7 @@ function goBack() {
213
213
  <StepErrorSummary :errors="errors" />
214
214
 
215
215
  <% stepFields.forEach(function (field) { -%>
216
- <goa-form-item id="field-<%- field.key %>" label="<%- field.label %>"<% if (field.required !== false) { %> requirement="required"<% } %>>
216
+ <goa-form-item mb="l" id="field-<%- field.key %>" label="<%- field.label %>"<% if (field.required !== false) { %> requirement="required"<% } %>>
217
217
  <% if (field.type === 'textarea') { -%>
218
218
  <GoabTextarea v-model="form.<%- field.key %>" name="<%- field.key %>" />
219
219
  <% } else if (field.type === 'number') { -%>
@@ -24,6 +24,14 @@ export interface Schema {
24
24
  * programmatic callers (e.g. tests).
25
25
  */
26
26
  steps: string | IntakeViewStep[];
27
+ /**
28
+ * Field on the submitted record holding the business reference shown on the
29
+ * confirmation page, e.g. `reference`. Defaults to `reference`; falls back to
30
+ * the route id when the record has no such field.
31
+ */
32
+ referenceField?: string;
33
+ /** Human title used in headings, e.g. "Compensation claim". */
34
+ heading?: string;
27
35
  requiresAuth?: boolean;
28
36
  }
29
37
 
@@ -31,6 +39,8 @@ export interface NormalizedSchema extends Omit<Schema, 'steps'> {
31
39
  projectRoot: string;
32
40
  steps: IntakeViewStep[];
33
41
  requiresAuth: boolean;
42
+ referenceField: string;
43
+ heading: string;
34
44
  /** PascalCase base name, e.g. "Application" for --name application. */
35
45
  baseName: string;
36
46
  }
@@ -2,7 +2,7 @@
2
2
  "$schema": "http://json-schema.org/schema",
3
3
  "id": "NxAdspVueIntakeView",
4
4
  "title": "Vue Multi-Step Intake View",
5
- "description": "Generates a route-per-step intake wizard (Stepper + StepErrorSummary, a required read-only review step, and a confirmation page) into an existing vue-app project. Cross-step state is server-persisted -- each step PUTs/POSTs to /api/<resource>/:id and refetches on mount; there's no client-side draft caching.",
5
+ "description": "Generates a route-per-step intake wizard (Stepper + StepErrorSummary, a required read-only review step, and a confirmation page) into an existing vue-app project. Cross-step state is server-persisted -- each step PUTs/POSTs to /api/v1/<resource>/:id and refetches on mount; there's no client-side draft caching.",
6
6
  "type": "object",
7
7
  "properties": {
8
8
  "project": {
@@ -25,7 +25,7 @@
25
25
  },
26
26
  "resource": {
27
27
  "type": "string",
28
- "description": "API resource path segment. Each step fetches/saves /api/<resource>/:id; the review step's Submit posts /api/<resource>/:id/submit."
28
+ "description": "API resource path segment. Each step fetches/saves /api/v1/<resource>/:id; the review step's Submit posts /api/v1/<resource>/:id/submit."
29
29
  },
30
30
  "route": {
31
31
  "type": "string",
@@ -39,14 +39,17 @@
39
39
  "type": "boolean",
40
40
  "description": "Whether the generated routes require authentication.",
41
41
  "default": true
42
+ },
43
+ "referenceField": {
44
+ "type": "string",
45
+ "description": "Field on the submitted record holding the business reference shown on the confirmation page, e.g. 'reference'. The confirmation fetches the record and displays this rather than the route id -- an internal id presented as a reference number is meaningless to the person quoting it back. Falls back to the route id when the record has no such field.",
46
+ "default": "reference"
47
+ },
48
+ "heading": {
49
+ "type": "string",
50
+ "description": "Human title used in the confirmation heading, e.g. 'Compensation claim'. Defaults to the class-cased --name."
42
51
  }
43
52
  },
44
- "required": [
45
- "project",
46
- "name",
47
- "resource",
48
- "route",
49
- "steps"
50
- ],
53
+ "required": ["project", "name", "resource", "route", "steps"],
51
54
  "additionalProperties": false
52
55
  }
@@ -28,9 +28,12 @@ function parseSteps(steps) {
28
28
  return parsed;
29
29
  }
30
30
  function normalizeOptions(host, options) {
31
- var _a;
31
+ var _a, _b, _c;
32
32
  const { root: projectRoot } = (0, devkit_1.readProjectConfiguration)(host, options.project);
33
- return Object.assign(Object.assign({}, options), { projectRoot, steps: parseSteps(options.steps), requiresAuth: (_a = options.requiresAuth) !== null && _a !== void 0 ? _a : true, baseName: (0, devkit_1.names)(options.name).className });
33
+ return Object.assign(Object.assign({}, options), { projectRoot, steps: parseSteps(options.steps), requiresAuth: (_a = options.requiresAuth) !== null && _a !== void 0 ? _a : true, referenceField: (_b = options.referenceField) !== null && _b !== void 0 ? _b : 'reference',
34
+ // Sentence-case the name for prose headings ("claim" -> "Claim"), so the
35
+ // confirmation reads as a service page rather than repeating a slug.
36
+ heading: (_c = options.heading) !== null && _c !== void 0 ? _c : (0, devkit_1.names)(options.name).className, baseName: (0, devkit_1.names)(options.name).className });
34
37
  }
35
38
  // PascalCase view name for a step, e.g. "personal-info" -> "PersonalInfoStepView".
36
39
  function stepViewFileName(stepKey) {
@@ -61,7 +64,10 @@ function default_1(host, options) {
61
64
  });
62
65
  (0, devkit_1.generateFiles)(host, path.join(__dirname, 'files/shared'), projectRoot, Object.assign(Object.assign({}, normalizedOptions), { goaImportPath,
63
66
  reviewViewFileName,
64
- confirmationViewFileName, tmpl: '' }));
67
+ confirmationViewFileName,
68
+ // Derived here, not tested inline: EJS throws a ReferenceError on a bare
69
+ // undefined variable, so a flag the template reads must always be defined.
70
+ hasCodedFields: steps.some((step) => step.fields.some((field) => { var _a; return (_a = field.options) === null || _a === void 0 ? void 0 : _a.length; })), tmpl: '' }));
65
71
  // Registered in reverse so the final router file lists steps in forward
66
72
  // order (each insertVueRoute call adds right after `routes: [`, pushing
67
73
  // earlier insertions down).
@@ -1 +1 @@
1
- {"version":3,"file":"vue-intake-view.js","sourceRoot":"","sources":["../../../../../../packages/nx-adsp/src/generators/vue-intake-view/vue-intake-view.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"vue-intake-view.js","sourceRoot":"","sources":["../../../../../../packages/nx-adsp/src/generators/vue-intake-view/vue-intake-view.ts"],"names":[],"mappings":"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"}