@internetarchive/collection-browser 2.7.6-alpha2 → 2.7.6-alpha4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remove-items-modal-content.test.js","sourceRoot":"","sources":["../../../test/manage/remove-items-modal-content.test.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable import/no-duplicates */\nimport { expect, fixture } from '@open-wc/testing';\nimport { html } from 'lit';\nimport Sinon from 'sinon';\nimport type { ManageableItem } from '../../src/models';\nimport type { RemoveItemsModalContent } from '../../src/manage/remove-items-modal-content';\nimport '../../src/manage/remove-items-modal-content';\n\ndescribe('RemoveItemsModalContent', () => {\n const items: ManageableItem[] = [\n { identifier: '1', title: 'Item 1', date: '2022-01-01' },\n { identifier: '2', title: 'Item 2', date: '2022-01-02' },\n ];\n\n it('renders basic component', async () => {\n const el = await fixture<RemoveItemsModalContent>(html`\n <remove-items-modal-content\n .items=${items}\n .message=${''}\n ></remove-items-modal-content>\n `);\n\n expect(el.shadowRoot?.querySelector('ul')).to.exist;\n expect(el.shadowRoot?.querySelector('.button-bar')).to.exist;\n expect(el.shadowRoot?.querySelector('.remove-items-btn')).to.exist;\n });\n\n it('renders list of items', async () => {\n const el = await fixture<RemoveItemsModalContent>(html`\n <remove-items-modal-content\n .items=${items}\n .message=${''}\n ></remove-items-modal-content>\n `);\n\n const listItems = el.shadowRoot?.querySelectorAll('li');\n expect(listItems).to.have.lengthOf(2);\n\n listItems?.forEach((item, index) => {\n expect(item.querySelector('.item-title')?.textContent).to.equal(\n items[index].title\n );\n expect(item.querySelector('.item-date')?.textContent).to.equal(\n items[index].date\n );\n });\n });\n\n it('renders message', async () => {\n const message = 'This is a test message';\n const el = await fixture<RemoveItemsModalContent>(html`\n <remove-items-modal-content\n .items=${[]}\n .message=${message}\n ></remove-items-modal-content>\n `);\n\n expect(el.shadowRoot?.querySelector('.message')?.textContent).to.equal(\n message\n );\n });\n\n it('dispatches confirm event when remove items button is clicked', async () => {\n const el = await fixture<RemoveItemsModalContent>(html`\n <remove-items-modal-content\n .items=${items}\n .message=${''}\n ></remove-items-modal-content>\n `);\n\n const spy = Sinon.spy();\n el.addEventListener('confirm', spy);\n\n const button = el.shadowRoot?.querySelector(\n '.remove-items-btn'\n ) as HTMLInputElement;\n button?.click();\n\n expect(spy.calledOnce).to.be.true;\n expect(spy.args[0][0].detail.items).to.deep.equal(items);\n });\n});\n"]}
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "description": "The Internet Archive Collection Browser.",
4
4
  "license": "AGPL-3.0-only",
5
5
  "author": "Internet Archive",
6
- "version": "2.7.6-alpha2",
6
+ "version": "2.7.6-alpha4",
7
7
  "main": "dist/index.js",
8
8
  "module": "dist/index.js",
9
9
  "scripts": {
package/src/app-root.ts CHANGED
@@ -490,15 +490,8 @@ export class AppRoot extends LitElement {
490
490
  @baseQueryChanged=${this.baseQueryChanged}
491
491
  @searchTypeChanged=${this.searchTypeChanged}
492
492
  @manageModeChanged=${this.manageModeChanged}
493
- @itemRemovalRequested=${(e: CustomEvent) => {
494
- setTimeout(() => {
495
- console.log('itemRemovalRequested: ', e.detail.items);
496
- this.collectionBrowser.isItemDeleted = false;
497
- this.collectionBrowser.isManageView = false;
498
- }, 1200);
499
- }}
500
- @itemManagerRequested=${(e: CustomEvent) =>
501
- console.log('itemManagerRequested: ', e.detail.items)}
493
+ @itemRemovalRequested=${this.handleItemRemovalRequest}
494
+ @itemManagerRequested=${this.handleItemManagerRequest}
502
495
  >
503
496
  ${this.toggleSlots
504
497
  ? html`<div slot="sortbar-left-slot">Sort Slot</div>`
@@ -713,6 +706,36 @@ export class AppRoot extends LitElement {
713
706
  if (manageCheckbox) manageCheckbox.checked = e.detail;
714
707
  }
715
708
 
709
+ /**
710
+ * Handler for item removal
711
+ */
712
+ private handleItemRemovalRequest(e: CustomEvent) {
713
+ this.collectionBrowser.showRemoveItemsProcessingModal();
714
+ console.log('itemRemovalRequested: ', e.detail.items);
715
+
716
+ setTimeout(() => {
717
+ // execute item-removal-service, and response is successfully deleted
718
+ const status = false;
719
+
720
+ if (status) {
721
+ // looking for success?
722
+ this.collectionBrowser.isManageView = false;
723
+ this.modalManager?.closeModal();
724
+ this.modalManager?.classList.remove('remove-items');
725
+ } else {
726
+ // looking for failure?
727
+ this.collectionBrowser.showRemoveItemsErrorModal();
728
+ }
729
+ }, 2000); // let's wait to see processing modal
730
+ }
731
+
732
+ /**
733
+ * Handler when item manage requested
734
+ */
735
+ private handleItemManagerRequest(e: CustomEvent) {
736
+ console.log('itemManagerRequested: ', e.detail.items);
737
+ }
738
+
716
739
  /**
717
740
  * Handler for when the dev panel's "Enable manage mode" checkbox is changed.
718
741
  */
@@ -721,7 +744,6 @@ export class AppRoot extends LitElement {
721
744
  this.collectionBrowser.isManageView = target.checked;
722
745
  this.collectionBrowser.manageViewLabel =
723
746
  'Select items to remove (customizable texts)';
724
- this.collectionBrowser.isItemDeleted = true;
725
747
  }
726
748
 
727
749
  /**
@@ -65,9 +65,9 @@ import {
65
65
  import chevronIcon from './assets/img/icons/chevron';
66
66
  import { srOnlyStyle } from './styles/sr-only';
67
67
  import { sha1 } from './utils/sha1';
68
- import { formatDate } from './utils/format-date';
69
68
  import { log } from './utils/log';
70
69
  import type { PlaceholderType } from './empty-placeholder';
70
+ import type { ManageBar } from './manage/manage-bar';
71
71
 
72
72
  import './empty-placeholder';
73
73
  import './tiles/tile-dispatcher';
@@ -244,9 +244,7 @@ export class CollectionBrowser
244
244
  /**
245
245
  * If item management UI active
246
246
  */
247
- @property({ type: Boolean }) isManageView = true;
248
-
249
- @property({ type: Boolean }) isItemDeleted = true;
247
+ @property({ type: Boolean }) isManageView = false;
250
248
 
251
249
  @property({ type: String }) manageViewLabel = 'Select items to remove';
252
250
 
@@ -302,6 +300,8 @@ export class CollectionBrowser
302
300
 
303
301
  @query('collection-facets') private collectionFacets?: CollectionFacets;
304
302
 
303
+ @query('manage-bar') private manageBar?: ManageBar;
304
+
305
305
  @property({ type: Object, attribute: false })
306
306
  analyticsHandler?: AnalyticsManagerInterface;
307
307
 
@@ -777,15 +777,20 @@ export class CollectionBrowser
777
777
  * showing the management view. This generally replaces the sort bar when present.
778
778
  */
779
779
  private get manageBarTemplate(): TemplateResult {
780
+ const manageViewModelMsg =
781
+ this.profileElement === 'uploads'
782
+ ? 'Note: it may take a few minutes for these items to stop appearing in your uploads list.'
783
+ : nothing;
784
+
780
785
  return html`
781
786
  <manage-bar
782
787
  .label=${this.manageViewLabel}
783
788
  .modalManager=${this.modalManager}
784
789
  .selectedItems=${this.dataSource.checkedTileModels}
790
+ .manageViewModelMsg=${manageViewModelMsg}
785
791
  showSelectAll
786
792
  showUnselectAll
787
- ?isItemDeleted=${this.isItemDeleted}
788
- ?showManageButton=${this.pageContext === 'search'}
793
+ ?showItemManageButton=${this.pageContext === 'search'}
789
794
  ?removeAllowed=${this.dataSource.checkedTileModels.length !== 0}
790
795
  @removeItems=${this.handleRemoveItems}
791
796
  @manageItems=${this.handleManageItems}
@@ -805,13 +810,11 @@ export class CollectionBrowser
805
810
  */
806
811
  private handleRemoveItems(): void {
807
812
  this.dispatchEvent(
808
- new CustomEvent<{ items: String }>('itemRemovalRequested', {
813
+ new CustomEvent<{ items: String[] }>('itemRemovalRequested', {
809
814
  detail: {
810
- items: this.dataSource.checkedTileModels.map(model => {
811
- const cloned = model.clone();
812
- cloned.dateStr = formatDate(model.datePublished, 'long');
813
- return cloned.identifier;
814
- }).join(','),
815
+ items: this.dataSource.checkedTileModels.map(model =>
816
+ model?.identifier ? model.identifier : ''
817
+ ),
815
818
  },
816
819
  })
817
820
  );
@@ -822,17 +825,30 @@ export class CollectionBrowser
822
825
  */
823
826
  private handleManageItems(): void {
824
827
  this.dispatchEvent(
825
- new CustomEvent<{ items: String }>('itemManagerRequested', {
828
+ new CustomEvent<{ items: String[] }>('itemManagerRequested', {
826
829
  detail: {
827
- items: this.dataSource.checkedTileModels
828
- .map(item => item.identifier)
829
- .filter(Boolean)
830
- .join(','),
830
+ items: this.dataSource.checkedTileModels.map(model =>
831
+ model?.identifier ? model.identifier : ''
832
+ ),
831
833
  },
832
834
  })
833
835
  );
834
836
  }
835
837
 
838
+ /**
839
+ * Handler to show processing modal while removing item
840
+ */
841
+ showRemoveItemsProcessingModal(): void {
842
+ this.manageBar?.showRemoveItemsProcessingModal();
843
+ }
844
+
845
+ /**
846
+ * Handler to show error modal when item removal failed
847
+ */
848
+ showRemoveItemsErrorModal(): void {
849
+ this.manageBar?.showRemoveItemsErrorModal();
850
+ }
851
+
836
852
  /**
837
853
  * Removes all tile models that are currently checked & adjusts the paging
838
854
  * of the data source to account for any new gaps in the data.
@@ -1,27 +1,15 @@
1
1
  import { msg } from '@lit/localize';
2
- import {
3
- LitElement,
4
- html,
5
- css,
6
- TemplateResult,
7
- CSSResultGroup,
8
- PropertyValues,
9
- } from 'lit';
2
+ import { LitElement, html, css, TemplateResult, CSSResultGroup } from 'lit';
10
3
  import { customElement, property } from 'lit/decorators.js';
11
4
  import { when } from 'lit/directives/when.js';
12
5
  import {
13
6
  ModalConfig,
14
7
  type ModalManagerInterface,
15
8
  } from '@internetarchive/modal-manager';
9
+ import type { ManageableItem } from '../models';
16
10
  import iaButtonStyle from '../styles/ia-button';
17
11
  import './remove-items-modal-content';
18
12
 
19
- export interface ManageableItem {
20
- identifier: string;
21
- title?: string;
22
- dateStr?: string;
23
- }
24
-
25
13
  @customElement('manage-bar')
26
14
  export class ManageBar extends LitElement {
27
15
  /**
@@ -44,6 +32,11 @@ export class ManageBar extends LitElement {
44
32
  */
45
33
  @property({ type: Object }) selectedItems: Array<ManageableItem> = [];
46
34
 
35
+ /**
36
+ * Message shows as note in the modal when removing items
37
+ */
38
+ @property({ type: String }) manageViewModelMsg?: string;
39
+
47
40
  /**
48
41
  * Whether to show the "Select All" button (default false)
49
42
  */
@@ -54,33 +47,16 @@ export class ManageBar extends LitElement {
54
47
  */
55
48
  @property({ type: Boolean }) showUnselectAll = false;
56
49
 
57
- /**
58
- * Item removal failure message, if any
59
- */
60
- @property({ type: Boolean }) isItemDeleted = true;
61
-
62
50
  /**
63
51
  * Whether to show "Item Manager the items" button (default false)
64
52
  */
65
- @property({ type: Boolean }) showManageButton = false;
53
+ @property({ type: Boolean }) showItemManageButton = false;
66
54
 
67
55
  /**
68
56
  * Whether to active delete button for selectable items
69
57
  */
70
58
  @property({ type: Boolean }) removeAllowed = false;
71
59
 
72
- updated(changed: PropertyValues): void {
73
- if (changed.has('isItemDeleted')) {
74
- console.log(this.isItemDeleted)
75
- if (this.isItemDeleted === false) {
76
- this.showRemoveItemsErrorModal();
77
- } else {
78
- this.modalManager?.closeModal();
79
- this.modalManager?.classList.remove('remove-items');
80
- }
81
- }
82
- }
83
-
84
60
  render(): TemplateResult {
85
61
  return html`
86
62
  <div class="manage-container">
@@ -97,7 +73,7 @@ export class ManageBar extends LitElement {
97
73
  ${msg('Remove selected items')}
98
74
  </button>
99
75
  ${when(
100
- this.showManageButton,
76
+ this.showItemManageButton,
101
77
  () => html` <button
102
78
  class="ia-button warning"
103
79
  ?disabled=${!this.removeAllowed}
@@ -135,12 +111,7 @@ export class ManageBar extends LitElement {
135
111
  this.dispatchEvent(new CustomEvent('cancel'));
136
112
  }
137
113
 
138
- /**
139
- * Shows a modal dialog confirming the list of items to be removed
140
- * @param items Which items to list in the modal
141
- */
142
114
  private removeItemsClicked(): void {
143
- this.showRemoveItemsProcessingModal();
144
115
  this.dispatchEvent(new CustomEvent('removeItems'));
145
116
  }
146
117
 
@@ -161,17 +132,10 @@ export class ManageBar extends LitElement {
161
132
  * @param items Which items to list in the modal
162
133
  */
163
134
  private showRemoveItemsModal(): void {
164
- const delayMessage =
165
- this.activeTabId === 'uploads'
166
- ? msg(
167
- 'Note: it may take a few minutes for these items to stop appearing in your uploads list.'
168
- )
169
- : undefined;
170
-
171
135
  const customModalContent = html`
172
136
  <remove-items-modal-content
173
137
  .items=${this.selectedItems}
174
- .message=${delayMessage}
138
+ .message=${this.manageViewModelMsg}
175
139
  @confirm=${() => this.removeItemsClicked()}
176
140
  ></remove-items-modal-content>
177
141
  `;
@@ -199,7 +163,7 @@ export class ManageBar extends LitElement {
199
163
  /**
200
164
  * Shows a modal dialog indicating that item removal is being processed
201
165
  */
202
- private showRemoveItemsProcessingModal(): void {
166
+ showRemoveItemsProcessingModal(): void {
203
167
  const config = new ModalConfig({
204
168
  showProcessingIndicator: true,
205
169
  processingImageMode: 'processing',
@@ -222,7 +186,7 @@ export class ManageBar extends LitElement {
222
186
  /**
223
187
  * Shows a modal dialog indicating that an error occurred while removing items
224
188
  */
225
- private showRemoveItemsErrorModal(): void {
189
+ showRemoveItemsErrorModal(): void {
226
190
  const config = new ModalConfig({
227
191
  showProcessingIndicator: false,
228
192
  processingImageMode: 'processing',
@@ -232,7 +196,7 @@ export class ManageBar extends LitElement {
232
196
  closeOnBackdropClick: true,
233
197
  title: html`${msg('Error: unable to remove items')}`,
234
198
  message: html`${msg(
235
- 'An error occurred while removing items. Please try again in a few minutes.',
199
+ 'An error occurred while removing items. Please try again in a few minutes.'
236
200
  )}`,
237
201
  });
238
202
 
@@ -2,12 +2,7 @@ import { LitElement, html, css, nothing, TemplateResult, CSSResult } from 'lit';
2
2
  import { customElement, property } from 'lit/decorators.js';
3
3
  import { msg } from '@lit/localize';
4
4
  import { map } from 'lit/directives/map.js';
5
-
6
- export interface ManageableItem {
7
- identifier: string;
8
- title?: string;
9
- date?: string;
10
- }
5
+ import type { ManageableItem } from '../models';
11
6
 
12
7
  @customElement('remove-items-modal-content')
13
8
  export class RemoveItemsModalContent extends LitElement {
package/src/models.ts CHANGED
@@ -675,3 +675,13 @@ export const suppressedCollections: Record<string, boolean> = {
675
675
  americana: true,
676
676
  toronto: true,
677
677
  };
678
+
679
+ /**
680
+ * A record of manageable item
681
+ */
682
+ export interface ManageableItem {
683
+ identifier: string;
684
+ title?: string;
685
+ dateStr?: string;
686
+ date?: string;
687
+ }
@@ -2,9 +2,14 @@
2
2
  import { expect, fixture } from '@open-wc/testing';
3
3
  import { html } from 'lit';
4
4
  import Sinon from 'sinon';
5
- import type { ManageBar } from '../../src/manage/manage-bar';
6
-
7
5
  import '../../src/manage/manage-bar';
6
+ import {
7
+ ModalManager,
8
+ ModalManagerInterface,
9
+ } from '@internetarchive/modal-manager';
10
+ import '@internetarchive/modal-manager';
11
+ import { msg } from '@lit/localize';
12
+ import type { ManageBar } from '../../src/manage/manage-bar';
8
13
 
9
14
  describe('Manage bar', () => {
10
15
  it('renders basic component', async () => {
@@ -38,7 +43,7 @@ describe('Manage bar', () => {
38
43
 
39
44
  it('render item manager button for /search/ page', async () => {
40
45
  const el = await fixture<ManageBar>(
41
- html`<manage-bar .pageContext=${'search'}></manage-bar>`
46
+ html`<manage-bar showItemManageButton></manage-bar>`
42
47
  );
43
48
  expect(el.shadowRoot?.querySelector('.ia-button.warning')).to.exist;
44
49
  });
@@ -84,21 +89,6 @@ describe('Manage bar', () => {
84
89
  expect(spy.callCount).to.equal(1);
85
90
  });
86
91
 
87
- it('emits event when Remove Items button clicked', async () => {
88
- const spy = Sinon.spy();
89
- const el = await fixture<ManageBar>(
90
- html`<manage-bar @removeItems=${spy} removeAllowed></manage-bar>`
91
- );
92
-
93
- const removeItemsBtn = el.shadowRoot?.querySelector(
94
- '.ia-button.danger'
95
- ) as HTMLButtonElement;
96
- expect(removeItemsBtn).to.exist;
97
-
98
- removeItemsBtn.click();
99
- expect(spy.callCount).to.equal(1);
100
- });
101
-
102
92
  it('emits event when Select All button clicked', async () => {
103
93
  const spy = Sinon.spy();
104
94
  const el = await fixture<ManageBar>(
@@ -128,4 +118,37 @@ describe('Manage bar', () => {
128
118
  unselectAllBtn.click();
129
119
  expect(spy.callCount).to.equal(1);
130
120
  });
121
+
122
+ it('opens the remove items modal when showRemoveItemsModal is clicked', async () => {
123
+ const el = await fixture<ManageBar>(html`
124
+ <manage-bar
125
+ .modalManager=${new ModalManager()}
126
+ .selectedItems=${[{ identifier: '1', title: 'Item 1' }]}
127
+ removeAllowed
128
+ ></manage-bar>
129
+ `);
130
+ await el.updateComplete;
131
+
132
+ const removeButton = el.shadowRoot?.querySelector(
133
+ '.ia-button.danger'
134
+ ) as HTMLButtonElement;
135
+ expect(removeButton).to.exist;
136
+
137
+ const showModalSpy = Sinon.spy(
138
+ el.modalManager as ModalManagerInterface,
139
+ 'showModal'
140
+ );
141
+
142
+ await el.updateComplete;
143
+ removeButton?.click();
144
+
145
+ console.log(showModalSpy.args[0][0].config.title?.values[0]);
146
+
147
+ expect(showModalSpy.callCount).to.equal(1);
148
+ expect(el.modalManager?.classList.contains('remove-items')).to.be;
149
+ expect(showModalSpy.args[0][0].config.title?.values[0]).to.equal(
150
+ msg('Are you sure you want to remove these items?')
151
+ );
152
+ expect(showModalSpy.args[0][0].customModalContent).to.exist;
153
+ });
131
154
  });
@@ -0,0 +1,82 @@
1
+ /* eslint-disable import/no-duplicates */
2
+ import { expect, fixture } from '@open-wc/testing';
3
+ import { html } from 'lit';
4
+ import Sinon from 'sinon';
5
+ import type { ManageableItem } from '../../src/models';
6
+ import type { RemoveItemsModalContent } from '../../src/manage/remove-items-modal-content';
7
+ import '../../src/manage/remove-items-modal-content';
8
+
9
+ describe('RemoveItemsModalContent', () => {
10
+ const items: ManageableItem[] = [
11
+ { identifier: '1', title: 'Item 1', date: '2022-01-01' },
12
+ { identifier: '2', title: 'Item 2', date: '2022-01-02' },
13
+ ];
14
+
15
+ it('renders basic component', async () => {
16
+ const el = await fixture<RemoveItemsModalContent>(html`
17
+ <remove-items-modal-content
18
+ .items=${items}
19
+ .message=${''}
20
+ ></remove-items-modal-content>
21
+ `);
22
+
23
+ expect(el.shadowRoot?.querySelector('ul')).to.exist;
24
+ expect(el.shadowRoot?.querySelector('.button-bar')).to.exist;
25
+ expect(el.shadowRoot?.querySelector('.remove-items-btn')).to.exist;
26
+ });
27
+
28
+ it('renders list of items', async () => {
29
+ const el = await fixture<RemoveItemsModalContent>(html`
30
+ <remove-items-modal-content
31
+ .items=${items}
32
+ .message=${''}
33
+ ></remove-items-modal-content>
34
+ `);
35
+
36
+ const listItems = el.shadowRoot?.querySelectorAll('li');
37
+ expect(listItems).to.have.lengthOf(2);
38
+
39
+ listItems?.forEach((item, index) => {
40
+ expect(item.querySelector('.item-title')?.textContent).to.equal(
41
+ items[index].title
42
+ );
43
+ expect(item.querySelector('.item-date')?.textContent).to.equal(
44
+ items[index].date
45
+ );
46
+ });
47
+ });
48
+
49
+ it('renders message', async () => {
50
+ const message = 'This is a test message';
51
+ const el = await fixture<RemoveItemsModalContent>(html`
52
+ <remove-items-modal-content
53
+ .items=${[]}
54
+ .message=${message}
55
+ ></remove-items-modal-content>
56
+ `);
57
+
58
+ expect(el.shadowRoot?.querySelector('.message')?.textContent).to.equal(
59
+ message
60
+ );
61
+ });
62
+
63
+ it('dispatches confirm event when remove items button is clicked', async () => {
64
+ const el = await fixture<RemoveItemsModalContent>(html`
65
+ <remove-items-modal-content
66
+ .items=${items}
67
+ .message=${''}
68
+ ></remove-items-modal-content>
69
+ `);
70
+
71
+ const spy = Sinon.spy();
72
+ el.addEventListener('confirm', spy);
73
+
74
+ const button = el.shadowRoot?.querySelector(
75
+ '.remove-items-btn'
76
+ ) as HTMLInputElement;
77
+ button?.click();
78
+
79
+ expect(spy.calledOnce).to.be.true;
80
+ expect(spy.args[0][0].detail.items).to.deep.equal(items);
81
+ });
82
+ });