Skip to content

Commit

Permalink
Consolidated Item Removal process which can be used on offshoot pages. (
Browse files Browse the repository at this point in the history
  • Loading branch information
nsharma123 authored Jan 31, 2025
1 parent 7ef77af commit 5099ea6
Show file tree
Hide file tree
Showing 7 changed files with 428 additions and 61 deletions.
42 changes: 38 additions & 4 deletions src/app-root.ts
Original file line number Diff line number Diff line change
Expand Up @@ -489,10 +489,8 @@ export class AppRoot extends LitElement {
@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`<div slot="sortbar-left-slot">Sort Slot</div>`
Expand Down Expand Up @@ -707,6 +705,36 @@ export class AppRoot extends LitElement {
if (manageCheckbox) manageCheckbox.checked = e.detail;
}

/**
* Handler for item removal
*/
private handleItemRemovalRequest(e: CustomEvent) {
this.collectionBrowser.showRemoveItemsProcessingModal();
console.log('itemRemovalRequested: ', e.detail.items);

setTimeout(() => {
// 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.showRemoveItemsErrorModal();
}
}, 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.
*/
Expand Down Expand Up @@ -936,6 +964,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);
Expand Down
52 changes: 36 additions & 16 deletions src/collection-browser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,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,
Expand All @@ -66,9 +65,9 @@ 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';
import type { ManageBar } from './manage/manage-bar';

import './empty-placeholder';
import './tiles/tile-dispatcher';
Expand Down Expand Up @@ -299,6 +298,8 @@ export class CollectionBrowser

@query('collection-facets') private collectionFacets?: CollectionFacets;

@query('manage-bar') private manageBar?: ManageBar;

@property({ type: Object, attribute: false })
analyticsHandler?: AnalyticsManagerInterface;

Expand Down Expand Up @@ -774,15 +775,23 @@ export class CollectionBrowser
* showing the management view. This generally replaces the sort bar when present.
*/
private get manageBarTemplate(): TemplateResult {
const manageViewModalMsg =
this.profileElement === 'uploads'
? 'Note: it may take a few minutes for these items to stop appearing in your uploads list.'
: nothing;

return html`
<manage-bar
.label=${this.manageViewLabel}
.pageContext=${this.pageContext}
.modalManager=${this.modalManager}
.selectedItems=${this.dataSource.checkedTileModels}
.manageViewModalMsg=${manageViewModalMsg}
showSelectAll
showUnselectAll
?showItemManageButton=${this.pageContext === 'search'}
?removeAllowed=${this.dataSource.checkedTileModels.length !== 0}
@removeItems=${this.handleRemoveItems}
@itemsManager=${this.handleItemsManager}
@manageItems=${this.handleManageItems}
@selectAll=${() => this.dataSource.checkAllTiles()}
@unselectAll=${() => this.dataSource.uncheckAllTiles()}
@cancel=${() => {
Expand All @@ -799,13 +808,11 @@ export class CollectionBrowser
*/
private handleRemoveItems(): void {
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 : ''
),
},
})
);
Expand All @@ -814,19 +821,32 @@ 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: String[] }>('itemManagerRequested', {
detail: {
items: this.dataSource.checkedTileModels
.map(item => item.identifier)
.filter(Boolean)
.join(','),
items: this.dataSource.checkedTileModels.map(model =>
model?.identifier ? model.identifier : ''
),
},
})
);
}

/**
* 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.
Expand Down
142 changes: 119 additions & 23 deletions src/manage/manage-bar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@ import { msg } from '@lit/localize';
import { LitElement, html, css, TemplateResult, CSSResultGroup } 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 {
Expand All @@ -18,9 +18,19 @@ 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
* The shared modal manager component for displaying modal dialogs on this page
*/
@property({ type: String }) pageContext?: string;
@property({ type: Object }) modalManager?: ModalManagerInterface;

/**
* Array of items that have been selected for management
*/
@property({ type: Object }) selectedItems: Array<ManageableItem> = [];

/**
* Message shows as note in the modal when removing items
*/
@property({ type: String }) manageViewModalMsg?: string;

/**
* Whether to show the "Select All" button (default false)
Expand All @@ -32,6 +42,11 @@ export class ManageBar extends LitElement {
*/
@property({ type: Boolean }) showUnselectAll = false;

/**
* Whether to show "Item Manager the items" button (default false)
*/
@property({ type: Boolean }) showItemManageButton = false;

/**
* Whether to active delete button for selectable items
*/
Expand All @@ -48,21 +63,20 @@ export class ManageBar extends LitElement {
<button
class="ia-button danger"
?disabled=${!this.removeAllowed}
@click=${this.removeClicked}
@click=${this.showRemoveItemsModal}
>
${msg('Remove selected items')}
</button>
${this.pageContext === 'search'
? html`
<button
class="ia-button warning"
?disabled=${!this.removeAllowed}
@click=${this.itemsManagerClicked}
>
${msg('Item Manager the items')}
</button>
`
: ''}
${when(
this.showItemManageButton,
() => html` <button
class="ia-button warning"
?disabled=${!this.removeAllowed}
@click=${this.manageItemsClicked}
>
${msg('Item Manager the items')}
</button>`
)}
<div class="selection-buttons">
${when(
this.showSelectAll,
Expand Down Expand Up @@ -92,12 +106,12 @@ export class ManageBar extends LitElement {
this.dispatchEvent(new CustomEvent('cancel'));
}

private removeClicked(): void {
private removeItemsClicked(): void {
this.dispatchEvent(new CustomEvent('removeItems'));
}

private itemsManagerClicked(): void {
this.dispatchEvent(new CustomEvent('itemsManager'));
private manageItemsClicked(): void {
this.dispatchEvent(new CustomEvent('manageItems'));
}

private selectAllClicked(): void {
Expand All @@ -108,6 +122,88 @@ 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 customModalContent = html`
<remove-items-modal-content
.items=${this.selectedItems}
.message=${this.manageViewModalMsg}
@confirm=${() => this.removeItemsClicked()}
></remove-items-modal-content>
`;

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
*/
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
*/
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}
Expand Down
Loading

0 comments on commit 5099ea6

Please sign in to comment.