AI Implementation feature(883): Admin Area General Settings and Categories 1.01 (#23)

This commit was merged in pull request #23.
This commit is contained in:
2026-07-22 12:32:00 +00:00
parent fac3179427
commit 0a2b2664b4
9 changed files with 171 additions and 89 deletions
+27
View File
@@ -0,0 +1,27 @@
# Implementation Plan: Admin Area General Settings and Categories 1.01
## 1. Architectural Reconnaissance
- **Codebase style & conventions:** TypeScript monorepo with a NestJS REST API and an Angular 17 standalone-component SPA. The General page is an OnPush standalone component using a non-nullable reactive form, signals for request state, and a typed `AdminService`; server request validation uses Zod through `ZodValidationPipe`, while controllers delegate persistence to services. The affected flow is `frontend/src/app/features/admin/general.component.ts``AdminService.updateGeneralSettings()``AdminGeneralController.updateSettings()``GeneralSettingsSchema``AdminGeneralService.updateSettings()``SettingsService`, with `/api/v1/bootstrap` subsequently exposing the stored `pageTitle` to `HomeComponent` and `ShellHeaderComponent`.
- **Data Layer:** SQLite via TypeORM. General settings are key/value rows in the `setting` table; `pageTitle` is stored under `SETTINGS_KEYS.PAGE_TITLE`. No schema or migration change is required. Invalid requests must be rejected before `AdminGeneralService.updateSettings()` executes, ensuring the existing row remains unchanged.
- **Test Framework & Structure:** Root Jest 29 multi-project configuration with `ts-jest`: Node for `tests/backend/**/*.spec.ts` and jsdom for `tests/frontend/**/*.spec.ts`. Tests are kept in the dedicated `/repo/tests` tree and all run from the repository root with `npm test`; focused projects can run with `npm run test:frontend` and `npm run test:backend`. Add minimal pure frontend validation coverage and extend the existing backend schema/service test rather than introducing browser/UI infrastructure.
- **Required Tools & Dependencies:** No new system tools, global CLIs, package dependencies, persistent `/data` fixtures, or `setup.sh` changes are required. Existing Angular Forms, Zod, Jest, and ts-jest cover the implementation and tests. Verification should use `npm test` and `npm run build`; the repository has no lint script or dedicated typecheck script, and the build scripts perform TypeScript/Angular compilation.
## 2. Impacted Files
- **To Modify:**
- `frontend/src/app/features/admin/general.pure.ts` — add a small typed whitespace-aware page-title validator/helper that can be shared by the reactive form and tested without Angular UI setup.
- `frontend/src/app/features/admin/general.component.ts` — apply the page-title validator, render actionable field-level feedback, normalize the submitted title, and keep invalid forms from invoking the API.
- `backend/src/modules/admin/dto/general.dto.ts` — trim `pageTitle` before enforcing the existing 1120 character contract so whitespace-only input is rejected and valid surrounding whitespace is not persisted.
- `tests/frontend/admin-general-pure.spec.ts` — cover empty/whitespace rejection and valid-title normalization/acceptance using the pure helper.
- `tests/backend/admin-general-service.spec.ts` — cover schema rejection of whitespace-only titles and schema output trimming for a valid title, proving invalid payloads cannot reach persistence.
- `docs/guides/admin-general-settings.md` — update the Page Title contract and expected save behavior to document trimming, inline validation feedback, and preservation of the stored value on invalid input.
- `docs/api/admin.md` — document the server contract as a trimmed, non-empty 1120-character page title.
- **To Create:** None.
## 3. Proposed Changes
1. **Database / Schema Migration:** No migration is needed. Continue using the existing `setting` row and `SettingsService.set`; rely on validation occurring before the service call so empty or whitespace-only requests perform no writes and the prior `pageTitle` remains available from both admin settings and `/api/v1/bootstrap`.
2. **Backend Logic & APIs:** Change `GeneralSettingsSchema.pageTitle` from a raw `z.string().min(1).max(120)` to a trimmed string contract with the same bounds. Because `ZodValidationPipe` passes `parsed.data` onward, valid values such as `' OpenVelo '` will reach `AdminGeneralService.updateSettings()` as `'OpenVelo'`, while `''` and `' '` will produce the existing `400 VALIDATION_FAILED` envelope before any `Promise.all` persistence or SSE emission. Keep endpoint paths, response types, error envelope, settings service, and bootstrap logic unchanged.
3. **Frontend UI Integration:** Add a standalone page-title validator/helper in `general.pure.ts` that treats `value.trim().length === 0` as invalid while preserving Angular's max-length validation. Attach it to the non-nullable `pageTitle` control in `AdminGeneralComponent`, show an inline field error beneath `general-pageTitle` when the control is touched/dirty and either required/whitespace-invalid, and use an actionable message such as “Page title is required and cannot contain only whitespace.” Keep the existing disabled condition (`form.invalid`) and `onSubmit()` invalid guard/`markAllAsTouched()` so no PUT is issued for invalid values. For valid submissions, trim `v.pageTitle` before calling `AdminService.updateGeneralSettings()` so the immediate SPA request agrees with the server normalization. Clear stale save success/error state when a new submission begins as already done; only display `Saved.` after a successful response and patch the normalized response back into the form. No shell-header fallback change is needed because invalid titles will no longer be persisted.
## 4. Test Strategy
- **Target Unit Test File:** Extend `tests/frontend/admin-general-pure.spec.ts` with minimal tests for the page-title helper/validator: whitespace-only input is invalid, a normal title is valid, and valid surrounding whitespace normalizes to the intended persisted value. Extend `tests/backend/admin-general-service.spec.ts` under `GeneralSettingsSchema - validation rules` with one rejection assertion for `' '` and one successful parse assertion proving `' OpenVelo '` becomes `'OpenVelo'`. These tests directly guard both client pre-validation and the authoritative server boundary without a visual/browser test.
- **Mocking Strategy:** Frontend tests invoke only the pure helper with simple typed control-like values, so no TestBed, DOM interaction, or HTTP mock is needed. Backend schema tests use `safeParse` directly, so no Nest application or database is needed; the existing `AdminGeneralService` fake settings/hub test remains unchanged. This keeps tests fast and isolated while proving that invalid input never produces data suitable for persistence. Implement in TDD order: add the focused failing tests, verify the expected failures, make the minimal production changes, then run `npm test` and `npm run build` from `/repo`.