From 3228f976cec1746ac159f9ac8046bb425a50c36c Mon Sep 17 00:00:00 2001 From: Neeraj Sharma Date: Thu, 2 Jan 2025 20:47:12 +0530 Subject: [PATCH 1/5] Add extra button for search page manage UI --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d794e5ad6..551c244f3 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "description": "The Internet Archive Collection Browser.", "license": "AGPL-3.0-only", "author": "Internet Archive", - "version": "2.7.5", + "version": "2.7.6", "main": "dist/index.js", "module": "dist/index.js", "scripts": { From 92c0b12d81dd3867e23a77df090b81009fd63c21 Mon Sep 17 00:00:00 2001 From: Neeraj Sharma Date: Wed, 15 Jan 2025 19:21:26 +0530 Subject: [PATCH 2/5] Initial changes --- package.json | 4 +- src/app-root.ts | 43 ++++- src/collection-browser.ts | 28 +-- src/manage/manage-bar.ts | 168 +++++++++++++++--- src/manage/remove-items-modal-content.ts | 102 +++++++++++ src/models.ts | 10 ++ test/manage/manage-bar.test.ts | 59 ++++-- .../manage/remove-items-modal-content.test.ts | 82 +++++++++ 8 files changed, 439 insertions(+), 57 deletions(-) create mode 100644 src/manage/remove-items-modal-content.ts create mode 100644 test/manage/remove-items-modal-content.test.ts diff --git a/package.json b/package.json index 551c244f3..753b0ca0e 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "description": "The Internet Archive Collection Browser.", "license": "AGPL-3.0-only", "author": "Internet Archive", - "version": "2.7.6", + "version": "2.7.6-alpha2", "main": "dist/index.js", "module": "dist/index.js", "scripts": { @@ -13,7 +13,7 @@ "lint": "eslint --ext .ts,.html . --ignore-path .gitignore && prettier \"**/*.ts\" --check --ignore-path .gitignore", "format": "eslint --ext .ts,.html . --fix --ignore-path .gitignore && prettier \"**/*.ts\" --write --ignore-path .gitignore", "circular": "madge --circular --extensions ts .", - "test": "tsc && yarn run lint && yarn run circular && wtr --coverage", + "test": "tsc && yarn run circular && wtr --coverage", "test:fast": "tsc && wtr --coverage", "test:watch": "tsc && concurrently -k -r \"tsc --watch --preserveWatchOutput\" \"wtr --watch\"", "deploy": "yarn run deploy:run -e $(git branch --show-current)", diff --git a/src/app-root.ts b/src/app-root.ts index 93c49770b..9febc5a6e 100644 --- a/src/app-root.ts +++ b/src/app-root.ts @@ -485,14 +485,13 @@ export class AppRoot extends LitElement { .modalManager=${this.modalManager} .analyticsHandler=${this.analyticsHandler} .pageContext=${'search'} + .activeTabId=${'uploads'} @visiblePageChanged=${this.visiblePageChanged} @baseQueryChanged=${this.baseQueryChanged} @searchTypeChanged=${this.searchTypeChanged} @manageModeChanged=${this.manageModeChanged} - @itemRemovalRequested=${(e: CustomEvent) => - console.log(e.detail.items)} - @itemManagerRequested=${(e: CustomEvent) => - console.log(e.detail.items)} + @itemRemovalRequested=${this.handleItemRemovalRequest} + @itemManagerRequested=${this.handleItemManagerRequest} > ${this.toggleSlots ? html`
Sort Slot
` @@ -707,6 +706,35 @@ export class AppRoot extends LitElement { if (manageCheckbox) manageCheckbox.checked = e.detail; } + /** + * Handler for item removal + */ + private handleItemRemovalRequest(e: CustomEvent) { + setTimeout(() => { + console.log('itemRemovalRequested: ', e.detail.items); + + // execute item-removal-service, and response is successfully deleted + const status = false; + + if (status) { + // looking for success? + this.collectionBrowser.isManageView = false; + this.modalManager?.closeModal(); + this.modalManager?.classList.remove('remove-items'); + } else { + // looking for failure? + this.collectionBrowser.hasItemsDeleted = false; + } + }, 2000); // let's wait to see processing modal + } + + /** + * Handler when item manage requested + */ + private handleItemManagerRequest(e: CustomEvent) { + console.log('itemManagerRequested: ', e.detail.items); + } + /** * Handler for when the dev panel's "Enable manage mode" checkbox is changed. */ @@ -715,6 +743,7 @@ export class AppRoot extends LitElement { this.collectionBrowser.isManageView = target.checked; this.collectionBrowser.manageViewLabel = 'Select items to remove (customizable texts)'; + this.collectionBrowser.hasItemsDeleted = true; } /** @@ -936,6 +965,12 @@ export class AppRoot extends LitElement { modal-manager[mode='open'] { display: block; } + modal-manager.remove-items { + --modalWidth: 58rem; + --modalBorder: 2px solid var(--primaryButtonBGColor, #194880); + --modalTitleLineHeight: 4rem; + --modalTitleFontSize: 1.8rem; + } modal-manager.more-search-facets { --modalWidth: 85rem; --modalBorder: 2px solid var(--primaryButtonBGColor, #194880); diff --git a/src/collection-browser.ts b/src/collection-browser.ts index b2eefe7a3..b641b014c 100644 --- a/src/collection-browser.ts +++ b/src/collection-browser.ts @@ -44,6 +44,7 @@ import { SORT_OPTIONS, defaultProfileElementSorts, FacetLoadStrategy, + ManageableItem, } from './models'; import { RestorationStateHandlerInterface, @@ -57,7 +58,6 @@ import type { } from './data-source/collection-browser-query-state'; import { FACETLESS_PAGE_ELEMENTS } from './data-source/models'; import type { CollectionFacets } from './collection-facets'; -import type { ManageableItem } from './manage/manage-bar'; import type { CollectionBrowserDataSourceInterface } from './data-source/collection-browser-data-source-interface'; import { analyticsActions, @@ -220,6 +220,8 @@ export class CollectionBrowser @property({ type: String }) pageContext: CollectionBrowserContext = 'search'; + @property({ type: String }) activeTabId: string = ''; + @property({ type: Object }) restorationStateHandler: RestorationStateHandlerInterface = new RestorationStateHandler( { @@ -243,7 +245,9 @@ export class CollectionBrowser /** * If item management UI active */ - @property({ type: Boolean }) isManageView = false; + @property({ type: Boolean }) isManageView = true; + + @property({ type: Boolean }) hasItemsDeleted = true; @property({ type: String }) manageViewLabel = 'Select items to remove'; @@ -777,12 +781,15 @@ export class CollectionBrowser return html` this.dataSource.checkAllTiles()} @unselectAll=${() => this.dataSource.uncheckAllTiles()} @cancel=${() => { @@ -798,6 +805,8 @@ export class CollectionBrowser * Emits an `itemRemovalRequested` event with all checked tile models. */ private handleRemoveItems(): void { + this.hasItemsDeleted = true; + this.dispatchEvent( new CustomEvent<{ items: ManageableItem[] }>('itemRemovalRequested', { detail: { @@ -814,14 +823,13 @@ export class CollectionBrowser /** * Handler when user request to bulk edit from /search/ page */ - private handleItemsManager(): void { + private handleManageItems(): void { this.dispatchEvent( - new CustomEvent('itemManagerRequested', { + new CustomEvent<{ items: ManageableItem[] }>('itemManagerRequested', { detail: { - items: this.dataSource.checkedTileModels - .map(item => item.identifier) - .filter(Boolean) - .join(','), + items: this.dataSource.checkedTileModels.map( + model => model as ManageableItem + ), }, }) ); diff --git a/src/manage/manage-bar.ts b/src/manage/manage-bar.ts index 5eb671103..3dfb3e8ed 100644 --- a/src/manage/manage-bar.ts +++ b/src/manage/manage-bar.ts @@ -1,14 +1,21 @@ import { msg } from '@lit/localize'; -import { LitElement, html, css, TemplateResult, CSSResultGroup } from 'lit'; +import { + LitElement, + html, + css, + TemplateResult, + CSSResultGroup, + PropertyValues, +} from 'lit'; import { customElement, property } from 'lit/decorators.js'; import { when } from 'lit/directives/when.js'; +import { + ModalConfig, + type ModalManagerInterface, +} from '@internetarchive/modal-manager'; +import type { ManageableItem } from '../models'; import iaButtonStyle from '../styles/ia-button'; - -export interface ManageableItem { - identifier: string; - title?: string; - dateStr?: string; -} +import './remove-items-modal-content'; @customElement('manage-bar') export class ManageBar extends LitElement { @@ -20,7 +27,17 @@ export class ManageBar extends LitElement { /** * Specifies the context in which the collection browser is being used */ - @property({ type: String }) pageContext?: string; + @property({ type: String }) activeTabId?: string; + + /** + * The shared modal manager component for displaying modal dialogs on this page + */ + @property({ type: Object }) modalManager?: ModalManagerInterface; + + /** + * Array of items that have been selected for management + */ + @property({ type: Object }) selectedItems: Array = []; /** * Whether to show the "Select All" button (default false) @@ -32,11 +49,27 @@ export class ManageBar extends LitElement { */ @property({ type: Boolean }) showUnselectAll = false; + /** + * Whether item has deleted or not (default true) + */ + @property({ type: Boolean }) hasItemsDeleted = true; + + /** + * Whether to show "Item Manager the items" button (default false) + */ + @property({ type: Boolean }) showItemManageButton = false; + /** * Whether to active delete button for selectable items */ @property({ type: Boolean }) removeAllowed = false; + updated(changed: PropertyValues): void { + if (changed.has('hasItemsDeleted') && !this.hasItemsDeleted) { + this.showRemoveItemsErrorModal(); + } + } + render(): TemplateResult { return html`
@@ -48,21 +81,20 @@ export class ManageBar extends LitElement { - ${this.pageContext === 'search' - ? html` - - ` - : ''} + ${when( + this.showItemManageButton, + () => html` ` + )}
${when( this.showSelectAll, @@ -92,12 +124,13 @@ export class ManageBar extends LitElement { this.dispatchEvent(new CustomEvent('cancel')); } - private removeClicked(): void { + private removeItemsClicked(): void { + this.showRemoveItemsProcessingModal(); this.dispatchEvent(new CustomEvent('removeItems')); } - private itemsManagerClicked(): void { - this.dispatchEvent(new CustomEvent('itemsManager')); + private manageItemsClicked(): void { + this.dispatchEvent(new CustomEvent('manageItems')); } private selectAllClicked(): void { @@ -108,6 +141,95 @@ export class ManageBar extends LitElement { this.dispatchEvent(new CustomEvent('unselectAll')); } + /** + * Shows a modal dialog confirming the list of items to be removed + * @param items Which items to list in the modal + */ + private showRemoveItemsModal(): void { + const delayMessage = + this.activeTabId === 'uploads' + ? msg( + 'Note: it may take a few minutes for these items to stop appearing in your uploads list.' + ) + : undefined; + + const customModalContent = html` + this.removeItemsClicked()} + > + `; + + const config = new ModalConfig({ + showProcessingIndicator: false, + processingImageMode: 'processing', + bodyColor: '#fff', + headerColor: '#194880', + showHeaderLogo: false, + closeOnBackdropClick: true, + title: html`${msg('Are you sure you want to remove these items?')}`, + }); + + this.modalManager?.classList.add('remove-items'); + this.modalManager?.showModal({ + config, + customModalContent, + userClosedModalCallback: () => { + this.modalManager?.classList.remove('remove-items'); + }, + }); + } + + /** + * Shows a modal dialog indicating that item removal is being processed + */ + private showRemoveItemsProcessingModal(): void { + const config = new ModalConfig({ + showProcessingIndicator: true, + processingImageMode: 'processing', + bodyColor: '#fff', + headerColor: '#194880', + showHeaderLogo: false, + closeOnBackdropClick: true, + title: html`${msg('Removing selected items...')}`, + }); + + this.modalManager?.classList.add('remove-items'); + this.modalManager?.showModal({ + config, + userClosedModalCallback: () => { + this.modalManager?.classList.remove('remove-items'); + }, + }); + } + + /** + * Shows a modal dialog indicating that an error occurred while removing items + */ + private showRemoveItemsErrorModal(): void { + const config = new ModalConfig({ + showProcessingIndicator: false, + processingImageMode: 'processing', + bodyColor: '#fff', + headerColor: '#691916', + showHeaderLogo: false, + closeOnBackdropClick: true, + title: html`${msg('Error: unable to remove items')}`, + message: html`${msg( + 'An error occurred while removing items. Please try again in a few minutes.' + )}`, + }); + + this.modalManager?.classList.add('remove-items'); + this.modalManager?.showModal({ + config, + userClosedModalCallback: () => { + this.modalManager?.classList.remove('remove-items'); + }, + }); + } + static get styles(): CSSResultGroup { return css` ${iaButtonStyle} diff --git a/src/manage/remove-items-modal-content.ts b/src/manage/remove-items-modal-content.ts new file mode 100644 index 000000000..8db1005de --- /dev/null +++ b/src/manage/remove-items-modal-content.ts @@ -0,0 +1,102 @@ +import { LitElement, html, css, nothing, TemplateResult, CSSResult } from 'lit'; +import { customElement, property } from 'lit/decorators.js'; +import { msg } from '@lit/localize'; +import { map } from 'lit/directives/map.js'; +import type { ManageableItem } from '../models'; + +@customElement('remove-items-modal-content') +export class RemoveItemsModalContent extends LitElement { + @property({ type: Object }) items: ManageableItem[] = []; + + @property({ type: String }) message?: string; + + render(): TemplateResult { + return html` +
    + ${map( + this.items, + ({ title, date }) => html` +
  • + ${title ?? '[untitled]'} + ${date ?? ''} +
  • + ` + )} +
+ ${this.message ? html`

${this.message}

` : nothing} +
+ +
+ `; + } + + private removeItemsBtnClicked(): void { + this.dispatchEvent( + new CustomEvent<{ items: ManageableItem[] }>('confirm', { + detail: { + items: this.items, + }, + }) + ); + } + + static get styles(): CSSResult { + return css` + ul { + margin: 0; + padding: 0 10px; + font-size: 1.4rem; + list-style-type: none; + max-height: min(400px, 40vh); + overflow-y: auto; + } + + li { + display: flex; + justify-content: space-between; + padding: 2px 0; + } + li:not(:last-of-type) { + border-bottom: 1px solid rgb(232, 232, 232); + } + + .item-title { + word-break: break-word; + } + + .item-date { + white-space: nowrap; + } + + .message { + font-size: 1.4rem; + padding: 5px 10px; + } + + .button-bar { + display: flex; + justify-content: center; + margin: 10px 5px; + } + + .remove-items-btn { + margin-bottom: 10px; + padding: 10px; + border: 1px solid var(--primaryErrorCTABorder, #d43f3a); + border-radius: 4px; + color: white; + background: var(--primaryErrorCTAFill, #d9534f); + appearance: none; + cursor: pointer; + } + .remove-items-btn:hover { + background: rgba(var(--primaryErrorCTAFillRGB, 229, 28, 38), 0.9); + } + .remove-items-btn:active { + background: rgba(var(--primaryErrorCTAFillRGB, 229, 28, 38), 0.7); + } + `; + } +} diff --git a/src/models.ts b/src/models.ts index cd52bb961..51916012b 100644 --- a/src/models.ts +++ b/src/models.ts @@ -675,3 +675,13 @@ export const suppressedCollections: Record = { americana: true, toronto: true, }; + +/** + * A record of manageable item + */ +export interface ManageableItem { + identifier: string; + title?: string; + dateStr?: string; + date?: string; +} diff --git a/test/manage/manage-bar.test.ts b/test/manage/manage-bar.test.ts index 92b94dc7a..267283466 100644 --- a/test/manage/manage-bar.test.ts +++ b/test/manage/manage-bar.test.ts @@ -2,9 +2,14 @@ import { expect, fixture } from '@open-wc/testing'; import { html } from 'lit'; import Sinon from 'sinon'; -import type { ManageBar } from '../../src/manage/manage-bar'; - import '../../src/manage/manage-bar'; +import { + ModalManager, + ModalManagerInterface, +} from '@internetarchive/modal-manager'; +import '@internetarchive/modal-manager'; +import { msg } from '@lit/localize'; +import type { ManageBar } from '../../src/manage/manage-bar'; describe('Manage bar', () => { it('renders basic component', async () => { @@ -38,7 +43,7 @@ describe('Manage bar', () => { it('render item manager button for /search/ page', async () => { const el = await fixture( - html`` + html`` ); expect(el.shadowRoot?.querySelector('.ia-button.warning')).to.exist; }); @@ -84,21 +89,6 @@ describe('Manage bar', () => { expect(spy.callCount).to.equal(1); }); - it('emits event when Remove Items button clicked', async () => { - const spy = Sinon.spy(); - const el = await fixture( - html`` - ); - - const removeItemsBtn = el.shadowRoot?.querySelector( - '.ia-button.danger' - ) as HTMLButtonElement; - expect(removeItemsBtn).to.exist; - - removeItemsBtn.click(); - expect(spy.callCount).to.equal(1); - }); - it('emits event when Select All button clicked', async () => { const spy = Sinon.spy(); const el = await fixture( @@ -128,4 +118,37 @@ describe('Manage bar', () => { unselectAllBtn.click(); expect(spy.callCount).to.equal(1); }); + + it('opens the remove items modal when showRemoveItemsModal is clicked', async () => { + const el = await fixture(html` + + `); + await el.updateComplete; + + const removeButton = el.shadowRoot?.querySelector( + '.ia-button.danger' + ) as HTMLButtonElement; + expect(removeButton).to.exist; + + const showModalSpy = Sinon.spy( + el.modalManager as ModalManagerInterface, + 'showModal' + ); + + await el.updateComplete; + removeButton?.click(); + + console.log(showModalSpy.args[0][0].config.title?.values[0]); + + expect(showModalSpy.callCount).to.equal(1); + expect(el.modalManager?.classList.contains('remove-items')).to.be; + expect(showModalSpy.args[0][0].config.title?.values[0]).to.equal( + msg('Are you sure you want to remove these items?') + ); + expect(showModalSpy.args[0][0].customModalContent).to.exist; + }); }); diff --git a/test/manage/remove-items-modal-content.test.ts b/test/manage/remove-items-modal-content.test.ts new file mode 100644 index 000000000..5cb53e93e --- /dev/null +++ b/test/manage/remove-items-modal-content.test.ts @@ -0,0 +1,82 @@ +/* eslint-disable import/no-duplicates */ +import { expect, fixture } from '@open-wc/testing'; +import { html } from 'lit'; +import Sinon from 'sinon'; +import type { ManageableItem } from '../../src/models'; +import type { RemoveItemsModalContent } from '../../src/manage/remove-items-modal-content'; +import '../../src/manage/remove-items-modal-content'; + +describe('RemoveItemsModalContent', () => { + const items: ManageableItem[] = [ + { identifier: '1', title: 'Item 1', date: '2022-01-01' }, + { identifier: '2', title: 'Item 2', date: '2022-01-02' }, + ]; + + it('renders basic component', async () => { + const el = await fixture(html` + + `); + + expect(el.shadowRoot?.querySelector('ul')).to.exist; + expect(el.shadowRoot?.querySelector('.button-bar')).to.exist; + expect(el.shadowRoot?.querySelector('.remove-items-btn')).to.exist; + }); + + it('renders list of items', async () => { + const el = await fixture(html` + + `); + + const listItems = el.shadowRoot?.querySelectorAll('li'); + expect(listItems).to.have.lengthOf(2); + + listItems?.forEach((item, index) => { + expect(item.querySelector('.item-title')?.textContent).to.equal( + items[index].title + ); + expect(item.querySelector('.item-date')?.textContent).to.equal( + items[index].date + ); + }); + }); + + it('renders message', async () => { + const message = 'This is a test message'; + const el = await fixture(html` + + `); + + expect(el.shadowRoot?.querySelector('.message')?.textContent).to.equal( + message + ); + }); + + it('dispatches confirm event when remove items button is clicked', async () => { + const el = await fixture(html` + + `); + + const spy = Sinon.spy(); + el.addEventListener('confirm', spy); + + const button = el.shadowRoot?.querySelector( + '.remove-items-btn' + ) as HTMLInputElement; + button?.click(); + + expect(spy.calledOnce).to.be.true; + expect(spy.args[0][0].detail.items).to.deep.equal(items); + }); +}); From e296fc62845f1f59ee7758945f0ab5221204ca56 Mon Sep 17 00:00:00 2001 From: Neeraj Sharma Date: Thu, 16 Jan 2025 15:56:43 +0530 Subject: [PATCH 3/5] Make dispathced content consistent --- src/collection-browser.ts | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/src/collection-browser.ts b/src/collection-browser.ts index 965b5f42a..0656dc42a 100644 --- a/src/collection-browser.ts +++ b/src/collection-browser.ts @@ -44,7 +44,6 @@ import { SORT_OPTIONS, defaultProfileElementSorts, FacetLoadStrategy, - ManageableItem, } from './models'; import { RestorationStateHandlerInterface, @@ -66,7 +65,6 @@ import { import chevronIcon from './assets/img/icons/chevron'; import { srOnlyStyle } from './styles/sr-only'; import { sha1 } from './utils/sha1'; -import { formatDate } from './utils/format-date'; import { log } from './utils/log'; import type { PlaceholderType } from './empty-placeholder'; @@ -806,15 +804,12 @@ export class CollectionBrowser */ private handleRemoveItems(): void { this.hasItemsDeleted = true; - this.dispatchEvent( - new CustomEvent<{ items: ManageableItem[] }>('itemRemovalRequested', { + new CustomEvent<{ items: String[] }>('itemRemovalRequested', { detail: { - items: this.dataSource.checkedTileModels.map(model => { - const cloned = model.clone(); - cloned.dateStr = formatDate(model.datePublished, 'long'); - return cloned as ManageableItem; - }), + items: this.dataSource.checkedTileModels.map(model => + model?.identifier ? model.identifier : '' + ), }, }) ); @@ -825,10 +820,10 @@ export class CollectionBrowser */ private handleManageItems(): void { this.dispatchEvent( - new CustomEvent<{ items: ManageableItem[] }>('itemManagerRequested', { + new CustomEvent<{ items: String[] }>('itemManagerRequested', { detail: { - items: this.dataSource.checkedTileModels.map( - model => model as ManageableItem + items: this.dataSource.checkedTileModels.map(model => + model?.identifier ? model.identifier : '' ), }, }) From b464f2b3118acaa8b0c01113d02fdf88a765b961 Mon Sep 17 00:00:00 2001 From: Neeraj Sharma Date: Fri, 17 Jan 2025 15:15:14 +0530 Subject: [PATCH 4/5] Code suggestions --- package.json | 2 +- src/app-root.ts | 10 +++++----- src/collection-browser.ts | 27 +++++++++++++++++++++++---- src/manage/manage-bar.ts | 39 +++++++++------------------------------ 4 files changed, 38 insertions(+), 40 deletions(-) diff --git a/package.json b/package.json index 551c244f3..fc9554c00 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "description": "The Internet Archive Collection Browser.", "license": "AGPL-3.0-only", "author": "Internet Archive", - "version": "2.7.6", + "version": "2.7.6-alpha4", "main": "dist/index.js", "module": "dist/index.js", "scripts": { diff --git a/src/app-root.ts b/src/app-root.ts index d5af6bc23..6b7d11128 100644 --- a/src/app-root.ts +++ b/src/app-root.ts @@ -485,7 +485,7 @@ export class AppRoot extends LitElement { .modalManager=${this.modalManager} .analyticsHandler=${this.analyticsHandler} .pageContext=${'search'} - .activeTabId=${''} + .activeTabId=${'uploads'} @visiblePageChanged=${this.visiblePageChanged} @baseQueryChanged=${this.baseQueryChanged} @searchTypeChanged=${this.searchTypeChanged} @@ -710,9 +710,10 @@ export class AppRoot extends LitElement { * Handler for item removal */ private handleItemRemovalRequest(e: CustomEvent) { - setTimeout(() => { - console.log('itemRemovalRequested: ', e.detail.items); + this.collectionBrowser.showRemoveItemsProcessingModal(); + console.log('itemRemovalRequested: ', e.detail.items); + setTimeout(() => { // execute item-removal-service, and response is successfully deleted const status = false; @@ -723,7 +724,7 @@ export class AppRoot extends LitElement { this.modalManager?.classList.remove('remove-items'); } else { // looking for failure? - this.collectionBrowser.hasItemsDeleted = false; + this.collectionBrowser.showRemoveItemsErrorModal(); } }, 2000); // let's wait to see processing modal } @@ -743,7 +744,6 @@ export class AppRoot extends LitElement { this.collectionBrowser.isManageView = target.checked; this.collectionBrowser.manageViewLabel = 'Select items to remove (customizable texts)'; - this.collectionBrowser.hasItemsDeleted = true; } /** diff --git a/src/collection-browser.ts b/src/collection-browser.ts index 0656dc42a..79f81e391 100644 --- a/src/collection-browser.ts +++ b/src/collection-browser.ts @@ -67,6 +67,7 @@ import { srOnlyStyle } from './styles/sr-only'; import { sha1 } from './utils/sha1'; import { log } from './utils/log'; import type { PlaceholderType } from './empty-placeholder'; +import type { ManageBar } from './manage/manage-bar'; import './empty-placeholder'; import './tiles/tile-dispatcher'; @@ -245,8 +246,6 @@ export class CollectionBrowser */ @property({ type: Boolean }) isManageView = false; - @property({ type: Boolean }) hasItemsDeleted = true; - @property({ type: String }) manageViewLabel = 'Select items to remove'; /** Whether to replace the default sort options with a slot for customization (default: false) */ @@ -301,6 +300,8 @@ export class CollectionBrowser @query('collection-facets') private collectionFacets?: CollectionFacets; + @query('manage-bar') private manageBar?: ManageBar; + @property({ type: Object, attribute: false }) analyticsHandler?: AnalyticsManagerInterface; @@ -776,12 +777,17 @@ export class CollectionBrowser * showing the management view. This generally replaces the sort bar when present. */ private get manageBarTemplate(): TemplateResult { + const manageViewModelMsg = + this.profileElement === 'uploads' + ? 'Note: it may take a few minutes for these items to stop appearing in your uploads list.' + : nothing; + return html` ('itemRemovalRequested', { detail: { @@ -830,6 +835,20 @@ export class CollectionBrowser ); } + /** + * Handler to show processing modal while removing item + */ + showRemoveItemsProcessingModal(): void { + this.manageBar?.showRemoveItemsProcessingModal(); + } + + /** + * Handler to show error modal when item removal failed + */ + showRemoveItemsErrorModal(): void { + this.manageBar?.showRemoveItemsErrorModal(); + } + /** * Removes all tile models that are currently checked & adjusts the paging * of the data source to account for any new gaps in the data. diff --git a/src/manage/manage-bar.ts b/src/manage/manage-bar.ts index 3dfb3e8ed..a36b62517 100644 --- a/src/manage/manage-bar.ts +++ b/src/manage/manage-bar.ts @@ -1,12 +1,5 @@ import { msg } from '@lit/localize'; -import { - LitElement, - html, - css, - TemplateResult, - CSSResultGroup, - PropertyValues, -} from 'lit'; +import { LitElement, html, css, TemplateResult, CSSResultGroup } from 'lit'; import { customElement, property } from 'lit/decorators.js'; import { when } from 'lit/directives/when.js'; import { @@ -39,6 +32,11 @@ export class ManageBar extends LitElement { */ @property({ type: Object }) selectedItems: Array = []; + /** + * Message shows as note in the modal when removing items + */ + @property({ type: String }) manageViewModelMsg?: string; + /** * Whether to show the "Select All" button (default false) */ @@ -49,11 +47,6 @@ export class ManageBar extends LitElement { */ @property({ type: Boolean }) showUnselectAll = false; - /** - * Whether item has deleted or not (default true) - */ - @property({ type: Boolean }) hasItemsDeleted = true; - /** * Whether to show "Item Manager the items" button (default false) */ @@ -64,12 +57,6 @@ export class ManageBar extends LitElement { */ @property({ type: Boolean }) removeAllowed = false; - updated(changed: PropertyValues): void { - if (changed.has('hasItemsDeleted') && !this.hasItemsDeleted) { - this.showRemoveItemsErrorModal(); - } - } - render(): TemplateResult { return html`
@@ -125,7 +112,6 @@ export class ManageBar extends LitElement { } private removeItemsClicked(): void { - this.showRemoveItemsProcessingModal(); this.dispatchEvent(new CustomEvent('removeItems')); } @@ -146,17 +132,10 @@ export class ManageBar extends LitElement { * @param items Which items to list in the modal */ private showRemoveItemsModal(): void { - const delayMessage = - this.activeTabId === 'uploads' - ? msg( - 'Note: it may take a few minutes for these items to stop appearing in your uploads list.' - ) - : undefined; - const customModalContent = html` this.removeItemsClicked()} > `; @@ -184,7 +163,7 @@ export class ManageBar extends LitElement { /** * Shows a modal dialog indicating that item removal is being processed */ - private showRemoveItemsProcessingModal(): void { + showRemoveItemsProcessingModal(): void { const config = new ModalConfig({ showProcessingIndicator: true, processingImageMode: 'processing', @@ -207,7 +186,7 @@ export class ManageBar extends LitElement { /** * Shows a modal dialog indicating that an error occurred while removing items */ - private showRemoveItemsErrorModal(): void { + showRemoveItemsErrorModal(): void { const config = new ModalConfig({ showProcessingIndicator: false, processingImageMode: 'processing', From 6d71997494119597fb67b466fa30cb07ced3d01a Mon Sep 17 00:00:00 2001 From: Neeraj Sharma Date: Fri, 17 Jan 2025 15:37:40 +0530 Subject: [PATCH 5/5] REmove unused properties --- src/app-root.ts | 1 - src/collection-browser.ts | 2 -- src/manage/manage-bar.ts | 5 ----- 3 files changed, 8 deletions(-) diff --git a/src/app-root.ts b/src/app-root.ts index 6b7d11128..783962d4d 100644 --- a/src/app-root.ts +++ b/src/app-root.ts @@ -485,7 +485,6 @@ export class AppRoot extends LitElement { .modalManager=${this.modalManager} .analyticsHandler=${this.analyticsHandler} .pageContext=${'search'} - .activeTabId=${'uploads'} @visiblePageChanged=${this.visiblePageChanged} @baseQueryChanged=${this.baseQueryChanged} @searchTypeChanged=${this.searchTypeChanged} diff --git a/src/collection-browser.ts b/src/collection-browser.ts index 79f81e391..3e357863f 100644 --- a/src/collection-browser.ts +++ b/src/collection-browser.ts @@ -219,8 +219,6 @@ export class CollectionBrowser @property({ type: String }) pageContext: CollectionBrowserContext = 'search'; - @property({ type: String }) activeTabId: string = ''; - @property({ type: Object }) restorationStateHandler: RestorationStateHandlerInterface = new RestorationStateHandler( { diff --git a/src/manage/manage-bar.ts b/src/manage/manage-bar.ts index a36b62517..890ece336 100644 --- a/src/manage/manage-bar.ts +++ b/src/manage/manage-bar.ts @@ -17,11 +17,6 @@ export class ManageBar extends LitElement { */ @property({ type: String }) label = msg('Select items to remove'); - /** - * Specifies the context in which the collection browser is being used - */ - @property({ type: String }) activeTabId?: string; - /** * The shared modal manager component for displaying modal dialogs on this page */