Feat: Replace pagination bar with numbered page buttons and chevron controls
Adds « ‹ [1][2][3][4] › » navigation to the library. Page window slides to keep the current page in view. Prev/next/first/last controls are always rendered but disabled at their respective bounds. Also wires up karmaConfig in angular.json so FirefoxHeadless is used for tests. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
125
specs/018-pagination-controls/tasks.md
Normal file
125
specs/018-pagination-controls/tasks.md
Normal file
@@ -0,0 +1,125 @@
|
||||
# Tasks: Pagination Controls Redesign
|
||||
|
||||
**Input**: Design documents from `specs/018-pagination-controls/`
|
||||
**Branch**: `018-pagination-controls`
|
||||
|
||||
**Scope**: Two files change — `library.component.ts` (template, styles, class) and `library.component.spec.ts` (tests). No API, no data model, no new files.
|
||||
|
||||
---
|
||||
|
||||
## Phase 1: Setup
|
||||
|
||||
**Purpose**: Baseline verification before touching the component.
|
||||
|
||||
- [X] T001 Confirm existing library component tests pass by running `ng test --include=**/library.component.spec.ts --watch=false` in ui/
|
||||
|
||||
---
|
||||
|
||||
## Phase 2: Foundational
|
||||
|
||||
**Purpose**: No blocking infrastructure work required — all three user stories build directly on the existing `LibraryComponent`. Skipped.
|
||||
|
||||
---
|
||||
|
||||
## Phase 3: User Story 1 — Page Number Navigation (Priority: P1) 🎯 MVP
|
||||
|
||||
**Goal**: Replace the "Page X of Y" text with up to four clickable numbered page buttons. User can jump directly to any visible page.
|
||||
|
||||
**Independent Test**: With more than four pages of images, four numbered buttons appear; clicking a button loads that page and the button shows as active.
|
||||
|
||||
### Tests for User Story 1 (REQUIRED per §5.1)
|
||||
|
||||
- [X] T002 [US1] Write failing tests for `pageWindow` getter covering: first page (→ [1,2,3,4]), last page (→ last 4), middle page (current in window), total pages < 4 (all shown) in ui/src/app/library/library.component.spec.ts
|
||||
|
||||
### Implementation for User Story 1
|
||||
|
||||
- [X] T003 [US1] Add `get pageWindow(): number[]` getter to `LibraryComponent` using the sliding-window algorithm from plan.md in ui/src/app/library/library.component.ts
|
||||
- [X] T004 [US1] Add `goToPage(page: number)` method to `LibraryComponent` (navigate via router queryParam, call `load()`) in ui/src/app/library/library.component.ts
|
||||
- [X] T005 [US1] Replace the `<span class="page-indicator">Page {{ currentPage }} of {{ totalPages }}</span>` with `*ngFor` numbered page buttons; add `.page-btn` and `.page-btn.active` styles; verify T002 tests pass in ui/src/app/library/library.component.ts
|
||||
|
||||
**Checkpoint**: Four numbered page buttons visible; clicking one loads the correct page; active button is highlighted.
|
||||
|
||||
---
|
||||
|
||||
## Phase 4: User Story 2 — Previous/Next Chevrons (Priority: P2)
|
||||
|
||||
**Goal**: Replace text "← Previous" / "Next →" buttons with ‹ › chevrons that are always rendered but visually disabled and non-interactive when at the first or last page.
|
||||
|
||||
**Independent Test**: On page 1 ‹ is disabled; on last page › is disabled; clicking either on a valid page advances or retreats by one.
|
||||
|
||||
### Tests for User Story 2 (REQUIRED per §5.1)
|
||||
|
||||
- [X] T006 [US2] Write failing tests for ‹ › disabled attribute and non-interactivity: disabled on page 1, disabled on last page, enabled otherwise in ui/src/app/library/library.component.spec.ts
|
||||
|
||||
### Implementation for User Story 2
|
||||
|
||||
- [X] T007 [US2] Replace the `*ngIf`-gated ← Previous / Next → buttons with always-rendered `<button [disabled]="currentPage === 1">‹</button>` and `<button [disabled]="currentPage === totalPages">›</button>`; add `.pag-btn:disabled` style; verify T006 tests pass in ui/src/app/library/library.component.ts
|
||||
|
||||
**Checkpoint**: ‹ and › always visible; disabled at bounds; single-page step works.
|
||||
|
||||
---
|
||||
|
||||
## Phase 5: User Story 3 — First/Last Jump Buttons (Priority: P3)
|
||||
|
||||
**Goal**: Add « and » buttons that jump directly to page 1 and the last page, disabled when already there.
|
||||
|
||||
**Independent Test**: From any middle page, « jumps to page 1 and » jumps to the last page; both are disabled when already at the respective bound.
|
||||
|
||||
### Tests for User Story 3 (REQUIRED per §5.1)
|
||||
|
||||
- [X] T008 [US3] Write failing tests for `firstPage()` and `lastPage()` methods and disabled states of « » at page boundaries in ui/src/app/library/library.component.spec.ts
|
||||
|
||||
### Implementation for User Story 3
|
||||
|
||||
- [X] T009 [US3] Add `firstPage()` and `lastPage()` methods to `LibraryComponent`; add `<button [disabled]="currentPage === 1">«</button>` and `<button [disabled]="currentPage === totalPages">»</button>` to each end of the pagination bar; verify T008 tests pass in ui/src/app/library/library.component.ts
|
||||
|
||||
**Checkpoint**: Full bar renders as `« ‹ [1][2][3][4] › »`; all disabled states correct.
|
||||
|
||||
---
|
||||
|
||||
## Phase 6: Polish & Cross-Cutting Concerns
|
||||
|
||||
- [X] T010 Apply final styles: consistent button sizing, gap spacing, and mobile-friendly layout (flex-wrap or min-width as needed) for the full pagination bar in ui/src/app/library/library.component.ts
|
||||
- [X] T011 Run ESLint and Prettier on ui/src/app/library/ and resolve any issues
|
||||
|
||||
---
|
||||
|
||||
## Dependencies & Execution Order
|
||||
|
||||
- **T001**: Run first — baseline gate
|
||||
- **T002 → T003 → T004 → T005**: Sequential (tests before implementation; each method before its template usage)
|
||||
- **T006 → T007**: Sequential (tests before implementation)
|
||||
- **T008 → T009**: Sequential (tests before implementation)
|
||||
- **T010, T011**: After all story phases complete; can run in either order
|
||||
|
||||
### User Story Dependencies
|
||||
|
||||
- **US1 (P1)**: Independent — starts after T001
|
||||
- **US2 (P2)**: Starts after US1 is complete (shares same template section)
|
||||
- **US3 (P3)**: Starts after US2 is complete (adds to the same template section)
|
||||
|
||||
All three stories touch the same two files, so parallel execution is not applicable here.
|
||||
|
||||
---
|
||||
|
||||
## Implementation Strategy
|
||||
|
||||
### MVP (User Story 1 only)
|
||||
|
||||
1. T001: Baseline check
|
||||
2. T002–T005: Numbered buttons + goToPage
|
||||
3. **Validate**: Four page buttons work, active state correct
|
||||
4. Defer US2 and US3 if shipping early
|
||||
|
||||
### Full Delivery
|
||||
|
||||
1. T001 baseline → US1 (T002–T005) → US2 (T006–T007) → US3 (T008–T009) → Polish (T010–T011)
|
||||
2. Each story checkpoint validates independence before moving on
|
||||
|
||||
---
|
||||
|
||||
## Notes
|
||||
|
||||
- `pageWindow` algorithm: `start = max(1, currentPage-1); end = min(totalPages, start+3); start = max(1, end-3); pages = [start..end]`
|
||||
- No `[P]` markers — all tasks share the same two files and must run sequentially
|
||||
- Entire pagination bar hidden when `totalPages <= 1` (existing behaviour; do not regress)
|
||||
Reference in New Issue
Block a user