CLARIN-DSpace v9/Port #1299 (license label management) to the v9 base - #1510
Conversation
…icence table Source: 66a278c (dtq-dev PR #1299) Adds a License Labels section to /licenses/manage-table with per-row Edit and Delete, guarded by a frontend usage crawl (the authoritative guard stays the backend 400 "is in use and cannot be deleted"), de-wraps both licence modals so ng-bootstrap owns the modal chrome, and centres all five modals. v9 adaptations: - ClarinLicenseLabelDataService: BaseDataService -> IdentifiableDataService with PutDataImpl/DeleteDataImpl (providedIn:'root' and the 9-base dataService import kept). - ConfirmationModalComponent on v9 takes `name`, not `dso`. - standalone imports[] gains NgbTooltipModule; *ngIf/*ngFor -> @if/@for; [disabled] -> [dsBtnDisabled]; custom-select -> form-select; form-group -> mb-3 in the two de-wrapped modal templates. - Restores src/app/shared/testing/clarin-license-mock.ts, which the table spec imports and which is absent on 9-base. - Restores define-license-form.component.spec.ts (PB-10) and keeps the two pagination-reset tests from cb7e1bb (PB-09). Closes card FE-23 and PB-09. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…-vacuous The v7 spec asserted modalService.open was not called with a single argument, which no real call site matches, so the assertion could never fail. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…ializer boolean branch The boolean pass-through added by 66a278c (extended: string -> boolean) is not exercised by any of the 43 ported component specs - removing it leaves all 43 green. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Local gate output (sync card FE-23 / PB-09, §6.3 order)Branch Static parity checks against the port headTable-component markers, one grep per marker, all ≥ 1: i18n — all 39 keys added by Spec case counts on the port head (anchored regex — plain Negative controls (production code reverted, tests untouched)Every restored test was checked against a deliberately broken tree; a summary of the ones that
|
What
Ports dtq-dev PR #1299 (
66a278c822, "license management") ontodtq-dev-9-base. Sync card FE-23; also closes card PB-09 and restores the spec noted in PB-10./licenses/manage-tablegains a License Labels section with per-row Edit and Delete. Delete of a label that some licence references is disabled with a tooltip; the frontend derives that by crawling every licence page viabyNameLike(100/page), and the authoritative guard stays the backend's 400 "is in use and cannot be deleted" (ClarinLicenseLabelRestRepositoryput/delete, already on 9-base). "Delete License" is disabled whilebitstreams > 0. All five modals now open{ centered: true }, and both licence modal templates lose the hand-rolled.modal > .modal-dialog > .modal-contentchrome (and themodal-boytypo) that double-rendered inside ng-bootstrap's own modal window. The label form gains an edit mode — prefill, icon preview, "Remove current icon" — andextendedbecomes a real boolean.Changes
Source commit:
66a278c822(dtq-dev PR #1299, 14 files). No cherry-pick — the directory has diverged on 9-base (standalone components,@if/@for, BS5,[dsBtnDisabled]), so the file contents were taken fromorigin/dtq-devand re-applied by hand.core/data/clarin/clarin-license-label-data.service.tsBaseDataService→IdentifiableDataService,PutDataImpl/DeleteDataImplwired next to the existingFindAllDataImpl/CreateDataImpl,put()/delete()/deleteByHref()delegatescore/shared/clarin/clarin-license-label-extended-serializer.ts'Yes'string pathclarin-license-table.component.{ts,html,scss}inUseLabelIds,labelsRD$,labelUsageReady$,confirmDeleteLabel,editLabel,doUpdateLabel,ensureLicenseUsageLoaded,isSelectedLicenseInUse,isLabelInUse,fetchAllLicensePages,goToLastLabelsPage,.labels-actions-columnmodal/define-license-form.component.{html,scss}.modal { display: inline }rule deletedmodal/define-license-label-form.component.{ts,html,scss}DomSanitizer+ the existingsecureImageDatahelper,clearIcon, booleanextendedsrc/assets/i18n/{en,cs}.json5shared/testing/clarin-license-mock.tsv9 adaptations (and why)
ConfirmationModalComponenttakesname, notdso. The v9 component declares eight@Input()s and nodso; its template interpolates{ dsoName: name }, so the{{ dsoName }}placeholders in the two confirm-dialog i18n keys work unchanged.modalRef.componentInstance.name = labelToDelete.label;— theDSpaceObjectimport from the v7 version is gone.NgbTooltipModuleadded toimports[]. The component is standalone and there is no NgModule to inherit it from; an un-imported structural directive fails silently at runtime, so a missing entry here would ship a tooltip that never appears.*ngIf/*ngFor→@if/@for(@angular-eslint/template/prefer-control-flowis an error).*ngVarstays.[disabled]on a<button>→[dsBtnDisabled](no-disabled-attribute-on-button), andselectedLicense == null→!selectedLicense(templateeqeqeq).!(loading$ | async) && …→(loading$ | async) === false && …:@angular-eslint/template/no-negated-asyncrejects the literal migration.loading$is aBehaviorSubject<boolean>that always has a value, so the two are equivalent.pr-1→pe-1,mr-1→me-1,custom-select→form-select, andform-group→mb-3in the two de-wrapped modal templates (BS5 has no.form-group, so without this the fields lose their spacing once the wrappers are gone).PutDataImpl(6 ctor params),DeleteDataImpl(8) andIdentifiableDataService(7) signatures are identical on both branches, so the data-service wiring needed no argument changes.One extra file the card did not list
clarin-license-table.component.spec.tsimports seven symbols fromsrc/app/shared/testing/clarin-license-mock.ts, and that file does not exist ondtq-dev-9-base(git ls-tree -r origin/dtq-dev-9-base --name-only | grep clarin-license-mock→ empty). It is restored here; without it the spec cannot compile.Why
The v7 admin licence table can create labels but never edit or delete them, and deleting a label still referenced by a licence has to be discovered by hitting the backend error. Both licence modals also rendered their own modal chrome inside ng-bootstrap's, which collapsed
.modal-contentand pinned the innerposition: fixedelement to the top of the viewport instead of centring it.Testing
29 (table) + 10 (label form) + 4 (licence form). The licence-form spec is a restoration —
66a278c822does not touch it; it exists ondtq-devand was missing on 9-base (card PB-10).PB-09 is folded in: the restored table spec keeps
should reset pagination to page 1 when the search term changesandshould not reset pagination when searching with the same termfromcb7e1bb856. Both were checked against a reverted production tree, and they need different reverts — removing the reset kills the first while the second stays green, and only making the reset unconditional kills the second.npm run sync-i18nwas not run — its-t -i -o -dswitches are dead code under Commander v14, so it ignores its target and rewrites 33 locale files. The 39 EN and 39 CS keys were edited by hand;git diff --statshows exactly two i18n files and both blobs stay pure LF.Two vacuous tests inherited from the v7 spec, both repaired
should create new clarin license label and load table datawasfakeAsync(...)with an untick'dfixture.whenStable().then(...), so none of its four expectations ever ran. 9-base karma setsfailSpecWithNoExpectations: true, which surfaced it asSpec has no expectations.whenStable()alone does not fix it either — reading a Blob throughFileReaderis a real browser task the zone does not count as pending — so the spec now waits for the create call and then asserts.should not open confirmation modal when clicking disabled delete on linked labelassertednot.toHaveBeenCalledWith(ConfirmationModalComponent)with one argument, while every real call passes two; the matcher could never match, so.notcould never fail. Now matched against the real two-argument call.Coverage gap found and closed
The serializer's boolean pass-through — the point of the
extended: string → booleanchange — is exercised by none of the 43 ported specs: removing it leaves all 43 green. Addedcore/shared/clarin/clarin-license-label-extended-serializer.spec.ts(4it()), deliberately outside thesrc/app/clarin-licenses/**glob.Manual testing
Needs an admin session on dev-6:8603 after deploy — LINDAT-124 (labels section; Delete disabled with tooltip for an in-use label and during the usage crawl; delete of an unused label → centred confirm modal → row disappears; Edit prefill + icon preview + "Remove current icon"; jump to the last page after "Define License Label"; "Delete License" disabled while
bitstreams > 0), plus LINDAT-119 and the LINDAT-036 / 037 / 111 regressions. Negative probe:DELETE $REST/core/clarinlicenselabels/<in-use id>with an admin token → 400 "is in use and cannot be deleted".🤖 Generated with Claude Code