From 8f373a6b8adaba2023e9846e179785bb0545d0ca Mon Sep 17 00:00:00 2001 From: Nicolas Molina Monroy Date: Thu, 3 Sep 2026 06:00:34 -0400 Subject: [PATCH 1/4] Remove #37366's asset picker folder-selection capability, restricting th MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Withdraws `'folder'` from the browse contract end to end — the VTL-facing `DotBrowserItemKind`, the returned selection union, the picker's browse options, and the two-cursor paging model — so folders are reached only through the sidebar tree, per QA's rejection of the #37273 design. Also adds the spec-kit artifacts (spec.md, data-model.md, contracts) recording the decision and its rationale. --- .../lib/bridges/angular-form-bridge.spec.ts | 96 +++-- .../src/lib/bridges/angular-form-bridge.ts | 41 +- .../lib/interfaces/asset-browser.interface.ts | 46 ++- .../lib/interfaces/form-bridge.interface.ts | 6 +- .../asset-picker-config.spec.ts | 13 +- .../dot-asset-picker/store/constants.ts | 2 - .../store/dot-asset-picker.store.spec.ts | 145 ++++--- .../features/with-asset-browse.feature.ts | 62 +-- .../dot-asset-picker/store/models.ts | 41 +- .../content/file_browser_field_render_new.vtl | 2 +- .../contracts/README.md | 14 + .../contracts/drive-search-request-delta.md | 100 +++++ .../contracts/openbrowsermodal-public-api.md | 93 +++++ .../data-model.md | 167 +++++++++ .../spec.md | 354 ++++++++++++++++++ 15 files changed, 1019 insertions(+), 163 deletions(-) create mode 100644 specs/37366-assetpicker-list-content-only/contracts/README.md create mode 100644 specs/37366-assetpicker-list-content-only/contracts/drive-search-request-delta.md create mode 100644 specs/37366-assetpicker-list-content-only/contracts/openbrowsermodal-public-api.md create mode 100644 specs/37366-assetpicker-list-content-only/data-model.md create mode 100644 specs/37366-assetpicker-list-content-only/spec.md diff --git a/core-web/libs/edit-content-bridge/src/lib/bridges/angular-form-bridge.spec.ts b/core-web/libs/edit-content-bridge/src/lib/bridges/angular-form-bridge.spec.ts index 279276694eca..ac815e33637a 100644 --- a/core-web/libs/edit-content-bridge/src/lib/bridges/angular-form-bridge.spec.ts +++ b/core-web/libs/edit-content-bridge/src/lib/bridges/angular-form-bridge.spec.ts @@ -8,6 +8,8 @@ import { DotAssetPickerComponent } from '@dotcms/ui'; import { AngularFormBridge } from './angular-form-bridge'; +import { DotBrowserOptions } from '../interfaces/asset-browser.interface'; + /** The site the picker browses; the bridge is handed a way to resolve it. */ const SITE: DotSite = { identifier: 'site-1', @@ -942,7 +944,6 @@ describe('AngularFormBridge', () => { bridge.openBrowserModal(); expect(openedConfig().allowedBaseTypes).toEqual(['DOTASSET', 'FILEASSET']); - expect(openedConfig().browse?.showFolders).toBeFalsy(); expect(openedConfig().browse?.showLinks).toBeFalsy(); }); }); @@ -954,14 +955,72 @@ describe('AngularFormBridge', () => { expect(openedConfig().allowedBaseTypes).toEqual(['FILEASSET', 'HTMLPAGE']); }); - it('should map folder and link kinds to browse options', () => { - bridge.openBrowserModal({ kinds: ['page', 'folder', 'link'] }); + it('should map the link kind to a browse option', () => { + bridge.openBrowserModal({ kinds: ['page', 'link'] }); expect(openedConfig().browse).toEqual( - expect.objectContaining({ showFolders: true, showLinks: true }) + expect.objectContaining({ showLinks: true }) ); }); + it('should not carry a folder browse option for a caller that asks for folders', () => { + // #37366: `'folder'` left the contract, but a VTL template is a string literal — + // TypeScript polices nothing here, so the runtime has to. The kind is dropped, and + // the picker is never handed an option that would list folders. + bridge.openBrowserModal({ + kinds: ['page', 'folder', 'link'] + } as unknown as DotBrowserOptions); + + expect(openedConfig().browse).not.toHaveProperty('showFolders'); + expect(openedConfig().browse).toEqual( + expect.objectContaining({ showLinks: true }) + ); + }); + + it('should warn about an unsupported kind rather than ignore it silently', () => { + // AC-008: a template author must not be able to ask for a kind the picker refuses + // and get no signal. Same treatment the `link` + `mimeTypes` conflict already gets. + const warn = jest.spyOn(console, 'warn').mockImplementation(); + + bridge.openBrowserModal({ + kinds: ['file', 'page', 'folder'] + } as unknown as DotBrowserOptions); + + expect(warn).toHaveBeenCalledTimes(1); + expect(warn.mock.calls[0][0]).toContain('folder'); + expect(openedConfig().allowedBaseTypes).toEqual(['FILEASSET', 'HTMLPAGE']); + + warn.mockRestore(); + }); + + it('should fall back to asset-only browsing when folder is the only kind asked for', () => { + // Degenerate case: no requested kind maps to a base type, so `baseTypesFor` returns + // undefined and the picker uses its own default. Must not throw — an exception + // inside a VTL