feat(website): XLSX submission template with Data + Guidance sheets and dropdown enforcement#6637
feat(website): XLSX submission template with Data + Guidance sheets and dropdown enforcement#6637theosanderson wants to merge 12 commits into
Conversation
…nforcement Rework the downloadable XLSX submission template into a richer workbook: - `Data` sheet (first): every input field as a column, ordered template (default-enabled) fields first, then the remaining opt-in fields. Headers remain machine field names so the file round-trips through upload. - `Config` sheet (read-only): human-readable reference listing every field with its display name, whether it is enabled by default, whether it is required, and its allowed values. - `_lists` sheet (hidden): one column per field with a controlled vocabulary, the lookup source for dropdowns. Dropdown enforcement is a single, header-driven data validation over the whole Data grid: each cell reads its own column header and looks it up in `_lists`, so the dropdown follows a column even if the user reorders or renames it. Free-text columns are left unconstrained (the lookup errors, which Excel treats permissively). Generation switches to ExcelJS, which (unlike @lokalise/xlsx / SheetJS CE) can write data validations, hidden sheets and sheet protection. Upload parsing is unchanged and the multi-sheet upload warning now ignores the `Config`/`_lists` reference sheets. TSV output is unchanged. Refs #6636 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Only fields with a controlled vocabulary now get a dropdown, each pointing
directly at that field's column in `_lists`. Free-text columns get no
validation, so they accept any value (a single grid-wide `list` rule rejected
free text, because list validation cannot express "allow anything").
The dropdowns are advisory rather than strict: a value typed outside the list
warns ("Yes" keeps it) instead of being rejected.
Also widen the Data and Config columns so headers and option values are readable.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…amed columns Each option field's dropdown now resolves its allowed values by looking its own column header up in `_lists` (via MATCH/OFFSET) instead of referencing a fixed `_lists` range. The header reference is column-relative to the validation range, so the dropdown follows the field when the column is renamed or moved. Still per-column and advisory: free-text columns get no validation (so they never warn), and off-list values on option columns warn rather than reject. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…eze, date format Make the generated template friendlier to fill in: - Header hover notes carrying each field's definition, guidance and example. - Colour-coded headers by tier (required / included-by-default / opt-in), with a matching colour legend on the Config sheet. - Frozen header row and an auto-filter on the Data sheet. - Date-typed columns formatted as yyyy-mm-dd (the format upload expects), via a new `metadataType` on the ordered template fields. - Config header row styled and frozen. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…p filter - Remove the Data sheet auto-filter (its header arrows clutter the sheet and are easily confused with the validation dropdowns); keep the frozen header. - Rename the `Config` reference sheet to `Guidance` (and update the upload parser's reference-sheet allowlist accordingly). - Drop the "Enabled by default" column; relabel the blue tier to "Priority fields" in the colour key. - Add Definition, Guidance and Example columns to the Guidance sheet so the field descriptions are readable in the workbook, not only in header notes. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Long option values (e.g. country names) were stretching columns to the 45-char cap. Width is now based on the field name only. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…st values) Switch the per-column option dropdowns from advisory to strict (errorStyle stop): a value outside a field's controlled vocabulary is rejected. Only columns with options are validated, so free-text columns remain unrestricted. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Lead with the XLSX template (recommended) and call the TSV one a minimal template, on the metadata upload page. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…rder The XLSX upload parser read the first sheet by position, so reordering the template's sheets (e.g. dragging Guidance to the front) would parse the reference sheet as metadata. Select the 'Data' sheet by name when present, falling back to the first sheet for non-template workbooks, and compute the multi-sheet warning relative to the parsed sheet. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
@codex review |
The upload parser now selects the Data sheet by name, so its position is no longer load-bearing; it is still added first so the workbook opens on it. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 9b8d8fae91
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
Claude finished @theosanderson's task in 2m 37s —— View job Code Review
This is a well-structured and thoroughly documented feature. The approach — a three-sheet workbook with enforced dropdowns, a hidden lookup sheet, and a read-only guidance sheet — is solid, and the test suite is comprehensive including raw-XML assertions to catch the one ExcelJS abstraction leak (the General observations
Tests See inline comments for two small fixable items (a comment typo and a missing intent comment on the empty-string sheet password). |
| add(sqref: string, validation: ExcelJS.DataValidation): void; | ||
| } | ||
|
|
||
| /** Visual tiers used to colour-code field headers (and explained by the legend on `Config`). */ |
There was a problem hiding this comment.
Typo in comment: Config should be Guidance.
| /** Visual tiers used to colour-code field headers (and explained by the legend on `Config`). */ | |
| /** Visual tiers used to colour-code field headers (and explained by the legend on `Guidance`). */ |
| listsSheet.getCell(optionIndex + 2, columnIndex + 1).value = option.name; | ||
| }); | ||
| }); | ||
| void listsSheet.protect('', { selectLockedCells: false, selectUnlockedCells: false }); |
There was a problem hiding this comment.
Empty-string password is functional (prevents accidental edits without locking out anyone), but it's worth a short comment to make the intent clear — otherwise it reads as an oversight.
| void listsSheet.protect('', { selectLockedCells: false, selectUnlockedCells: false }); | |
| // Empty-string password: protection is cosmetic (guard against accidental edits), not a security boundary. | |
| void listsSheet.protect('', { selectLockedCells: false, selectUnlockedCells: false }); |
|
|
||
| if (optionFields.length > 0) { | ||
| addOptionsLookup(workbook, dataSheet, fields, optionFields); | ||
| } |
There was a problem hiding this comment.
The sheet creation order is Data → _lists → Guidance, but the PR description table lists them as Data → Guidance → _lists. Not a bug (the tests use toContain not positional ordering for these two), but the doc/code ordering should agree to avoid confusion for future readers.
- Link text is 'XLSX template' with '(recommended)' outside the link. - Make the revision page object click the template links by href (fileType query param) instead of exact 'TSV'/'XLSX' text, which broke when the copy changed. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Implements #6636 — a richer XLSX submission template with enforced dropdown choices for controlled-vocabulary fields.
What it does
The XLSX template (
/[organism]/submission/template?fileType=xlsx) is now a three-sheet workbook:DataGuidance_listsData sheet
metadataTemplate) fields first, then the rest. Headers stay machine field names so the file round-trips through upload.options): a value outside the list is rejected (errorStyle=stop). Free-text columns get no validation, so they accept anything._lists(MATCH/OFFSET), so the dropdown follows the field if the column is renamed or moved.Guidance.yyyy-mm-dd(what upload expects); columns sized to the field name.Guidance sheet (read-only)
One row per field: Field name, Display name, Required, Definition, Guidance, Example, Allowed values — plus the colour legend.
Other changes
Data); its multi-sheet warning now ignores theGuidance/_listsreference sheets, so a freshly-downloaded template uploads without a spurious warning.@lokalise/xlsx/SheetJS-CE cannot write data validations, hidden sheets or sheet protection); upload parsing is unchanged. TSV output is unchanged.Previews
🤖 Generated with Claude Code
🚀 Preview: https://excel-val.loculus.org