apache / apache/fineract-backoffice-ui
A failed list load looks identical to an empty list on 65 screens
- Dominant language
- TypeScript
- Stars
- 15
- Forks
- 60
- Avg merge
- 10h 15m
- Merged PRs (30d)
- 108
Description
## What is wrong
`` accepts a `[hasError]` input and emits `(retry)`. Together they turn a failed
load into a message with a retry button instead of an empty table.
**65 of the 78 screens using the shared table bind neither.** When the request fails they call
`catchError(() => of([]))` or similar and render zero rows — which is exactly what a genuinely
empty list looks like.
For a back-office user the difference matters: "this client has no charges" and "we could not
reach the server" lead to completely different next actions, and right now the screen says the
first when it means the second.
## Where to start
Any of these. One screen per pull request:
- `accounting/charges/charges-list.component.ts`
- `accounting/accounting-rules-list.component.ts`
- `accounting/accounting-closures-list.component.ts`
- `accounting/provisioning-categories/provisioning-categories-list.component.ts`
- `calendars/calendars-list.component.ts`
- `clients/charges/client-charges-list.component.ts`
- `clients/collateral/client-collateral-list.component.ts`
Full list:
```bash
for f in $(grep -rl "app-data-table" src/app/features --include=*-list.component.ts); do
grep -q "hasError" "$f" || echo "$f"
done
```
## What to change
The pattern is in `src/app/features/products/loan-products-list.component.ts`:
```ts
readonly hasError = signal(false);
private loadProducts(): void {
this.service.getThings()
.pipe(
tap(() => this.hasError.set(false)),
catchError(() => {
this.hasError.set(true);
return of([]);
}),
)
.subscribe((data) => this.products.set(data ?? []));
}
onRetry(): void {
this.loadProducts();
}
```
```html
```
Note `tap` resetting the flag on success — without it a screen that fails once shows the error
banner forever, including after a successful retry.
## How to check it
`e2e/list-pagination.spec.ts` has a worked example under *"List load failure"*: it fails the first
request, serves the second, asserts `data-table-error` appears, then that retry restores the rows.
Copying that shape for the screen you convert is the best way to show it works.
```bash
npm run test -- --watch=false --browsers=ChromeHeadless --project=fineract-backoffice-ui
npx playwright test --project=mocked
```
## Why it is worth doing
Silently swallowing an error is the failure mode users cannot diagnose and support cannot
reproduce. This is a handful of lines per screen and turns a dead end into a retry.
Good first issue: pick one screen, follow the pattern, add the spec.
Contributor guide
Research direction
Pick one listed *-list.component.ts file and compare it with src/app/features/products/loan-products-list.component.ts. Add the hasError reset, failure handling, retry binding, and a spec following the “List load failure” example in e2e/list-pagination.spec.ts. Run the mocked Playwright test and verify data-table-error appears on the first failure and rows return after retry.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- angular, playwright, typescript
- Domain
- frontend, testing
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 86/100