fix(admin): restore SearchField + sorting modules used by AuthorPage (#7746)

* fix(admin): restore SearchField + sorting modules used by AuthorPage

PR #7736 ("replace hardcoded German strings with i18n keys") deleted
admin/src/components/SearchField.tsx and admin/src/utils/sorting.ts as
"orphan modules (no longer imported anywhere after #7716)". At that
point, the GDPR admin AuthorPage (PR #7667) had not yet landed on
develop. When #7667 merged afterwards, the new admin/src/pages/AuthorPage.tsx
brought back imports of SearchField and determineSorting — but the
files were already gone, leaving develop with broken admin imports.

This breaks `pnpm --filter admin run build-copy` on every CI job that
builds the admin UI:

  src/pages/AuthorPage.tsx(6,27): error TS2307: Cannot find module
    '../components/SearchField.tsx' or its corresponding type
    declarations.
  src/pages/AuthorPage.tsx(9,32): error TS2307: Cannot find module
    '../utils/sorting.ts' or its corresponding type declarations.
  src/pages/AuthorPage.tsx(207,29): error TS7006: Parameter 'v'
    implicitly has an 'any' type.

Backend tests, Frontend admin tests, Docker (build-test,
build-test-local-plugin, build-test-db-drivers), rate limit, and
Upgrade from latest release all fail at the admin build step on
develop.

Restore both files verbatim from before the deletion (commit ff7c4d531^).
With them back in place AuthorPage.tsx's existing imports resolve, the
implicit-any on the SearchField onChange callback goes away (typed via
SearchFieldProps), and `pnpm --filter admin run build-copy` succeeds.

This is the minimal, surgical fix; whether SearchField / determineSorting
should ultimately be inlined into AuthorPage is a separate cleanup.

Test plan:
  - cd admin && pnpm exec tsc --noEmit        → no errors
  - cd admin && pnpm exec tsc && pnpm exec vite build → built in 545ms

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* test(admin-i18n-lint): invert orphan-modules assertion now that AuthorPage imports them

PR #7736 added a lint assertion that admin/src/components/SearchField.tsx
and admin/src/utils/sorting.ts must NOT exist, on the assumption they
were dead code after #7716. They aren't — the GDPR AuthorPage (#7667)
imports both. The previous commit restored the files; this commit flips
the assertion so the test:

  - verifies both files exist
  - verifies admin/src/pages/AuthorPage.tsx still imports them

If a future cleanup wants to delete these modules, the test now forces
the author to also delete or refactor the AuthorPage consumption first,
preventing a repeat of the merge-order accident that produced this bug.

Test plan:
  - cd src && pnpm exec vitest run tests/backend-new/specs/admin-i18n-source-lint.test.ts
    → 14 passed (14)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
John McLear 2026-05-15 08:40:15 +01:00 committed by GitHub
parent e358410b68
commit 02e00ad615
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 36 additions and 6 deletions

View file

@ -0,0 +1,14 @@
import {ChangeEventHandler, FC} from "react";
import {Search} from 'lucide-react'
export type SearchFieldProps = {
value: string,
onChange: ChangeEventHandler<HTMLInputElement>,
placeholder?: string
}
export const SearchField:FC<SearchFieldProps> = ({onChange,value, placeholder})=>{
return <span className="search-field">
<input value={value} onChange={onChange} placeholder={placeholder}/>
<Search/>
</span>
}

View file

@ -0,0 +1,6 @@
export const determineSorting = (sortBy: string, ascending: boolean, currentSymbol: string) => {
if (sortBy === currentSymbol) {
return ascending ? 'sort up' : 'sort down';
}
return 'sort none';
}

View file

@ -84,16 +84,26 @@ describe('admin i18n source lint', () => {
"SearchParams['sortBy'] still includes 'downloads'").toBe(false);
});
it('orphan modules from pre-rework admin are gone', () => {
// SearchField.tsx and sorting.ts were imported by the pre-rework admin
// pages but the rework dropped both. Delete-then-grep here so a future
// unrelated import accidentally re-adding them fails review.
it('SearchField + sorting modules exist and are consumed by AuthorPage', () => {
// History: PR #7716 (admin design rework) dropped the last consumer of
// these helpers, then PR #7736 deleted both modules calling them
// "orphans". PR #7667 (GDPR author-erasure) merged afterwards from an
// older base and reintroduced imports of SearchField + determineSorting
// in admin/src/pages/AuthorPage.tsx, breaking the admin build on
// develop. The files have been restored; this test pins both the file
// presence and the AuthorPage consumption so a future "orphan" sweep
// cannot quietly remove them again without also updating AuthorPage.
const fs = require('fs');
const join = require('path').join;
expect(fs.existsSync(join(repoRoot, 'admin/src/components/SearchField.tsx')),
'admin/src/components/SearchField.tsx is dead code from pre-rework admin').toBe(false);
'admin/src/components/SearchField.tsx is missing — AuthorPage imports it').toBe(true);
expect(fs.existsSync(join(repoRoot, 'admin/src/utils/sorting.ts')),
'admin/src/utils/sorting.ts is dead code from pre-rework admin').toBe(false);
'admin/src/utils/sorting.ts is missing — AuthorPage imports determineSorting from it').toBe(true);
const authorPage = read('admin/src/pages/AuthorPage.tsx');
expect(authorPage.includes("from \"../components/SearchField.tsx\""),
'AuthorPage no longer imports SearchField — delete SearchField.tsx too').toBe(true);
expect(authorPage.includes("from \"../utils/sorting.ts\""),
'AuthorPage no longer imports determineSorting — delete sorting.ts too').toBe(true);
});
it('PadPage sort dropdown is paired with a direction toggle', () => {