From b62a4f6c538077f37295ce9b131af1fc65aff20a Mon Sep 17 00:00:00 2001 From: Davide Negretti Date: Tue, 18 Oct 2022 12:58:49 +0200 Subject: [PATCH 01/59] [CST-6171] Navbar border --- src/app/navbar/navbar.component.scss | 2 +- src/themes/dspace/app/navbar/navbar.component.scss | 2 +- src/themes/dspace/styles/_theme_css_variable_overrides.scss | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/app/navbar/navbar.component.scss b/src/app/navbar/navbar.component.scss index 3a9a302b06..320ce414ec 100644 --- a/src/app/navbar/navbar.component.scss +++ b/src/app/navbar/navbar.component.scss @@ -1,5 +1,5 @@ nav.navbar { - border-bottom: 1px var(--bs-gray-400) solid; + border-bottom: 1px var(--ds-header-navbar-border-bottom-color) solid; align-items: baseline; } diff --git a/src/themes/dspace/app/navbar/navbar.component.scss b/src/themes/dspace/app/navbar/navbar.component.scss index 1ad95cb8aa..45d188a264 100644 --- a/src/themes/dspace/app/navbar/navbar.component.scss +++ b/src/themes/dspace/app/navbar/navbar.component.scss @@ -1,6 +1,6 @@ nav.navbar { border-top: 1px var(--ds-header-navbar-border-top-color) solid; - border-bottom: 5px var(--bs-green) solid; + border-bottom: 5px var(--ds-header-navbar-border-bottom-color) solid; align-items: baseline; color: var(--ds-header-icon-color); } diff --git a/src/themes/dspace/styles/_theme_css_variable_overrides.scss b/src/themes/dspace/styles/_theme_css_variable_overrides.scss index e4b4b61f45..516eff9f7e 100644 --- a/src/themes/dspace/styles/_theme_css_variable_overrides.scss +++ b/src/themes/dspace/styles/_theme_css_variable_overrides.scss @@ -6,5 +6,6 @@ --ds-banner-background-gradient-width: 300px; --ds-home-news-link-color: #{$green}; --ds-home-news-link-hover-color: #{darken($green, 15%)}; + --ds-header-navbar-border-bottom-color: #{$green}; } From a69f61e4f36730ec3204a8092259b07c659cd263 Mon Sep 17 00:00:00 2001 From: Davide Negretti Date: Wed, 19 Oct 2022 00:58:59 +0200 Subject: [PATCH 02/59] [CST-6171] Item status type badge colors --- .../my-dspace-item-status.component.spec.ts | 10 ++++---- .../my-dspace-item-status.component.ts | 10 ++++---- src/styles/_global-styles.scss | 24 +++++++++++++++++++ 3 files changed, 34 insertions(+), 10 deletions(-) diff --git a/src/app/shared/object-collection/shared/mydspace-item-status/my-dspace-item-status.component.spec.ts b/src/app/shared/object-collection/shared/mydspace-item-status/my-dspace-item-status.component.spec.ts index 44e6a44b70..59fc29424d 100644 --- a/src/app/shared/object-collection/shared/mydspace-item-status/my-dspace-item-status.component.spec.ts +++ b/src/app/shared/object-collection/shared/mydspace-item-status/my-dspace-item-status.component.spec.ts @@ -55,34 +55,34 @@ describe('MyDSpaceItemStatusComponent', () => { component.status = MyDspaceItemStatusType.VALIDATION; fixture.detectChanges(); expect(component.badgeContent).toBe(MyDspaceItemStatusType.VALIDATION); - expect(component.badgeClass).toBe('text-light badge badge-warning'); + expect(component.badgeClass).toBe('text-light badge badge-validation'); }); it('should init badge content and class', () => { component.status = MyDspaceItemStatusType.WAITING_CONTROLLER; fixture.detectChanges(); expect(component.badgeContent).toBe(MyDspaceItemStatusType.WAITING_CONTROLLER); - expect(component.badgeClass).toBe('text-light badge badge-info'); + expect(component.badgeClass).toBe('text-light badge badge-waiting-controller'); }); it('should init badge content and class', () => { component.status = MyDspaceItemStatusType.WORKSPACE; fixture.detectChanges(); expect(component.badgeContent).toBe(MyDspaceItemStatusType.WORKSPACE); - expect(component.badgeClass).toBe('text-light badge badge-primary'); + expect(component.badgeClass).toBe('text-light badge badge-workspace'); }); it('should init badge content and class', () => { component.status = MyDspaceItemStatusType.ARCHIVED; fixture.detectChanges(); expect(component.badgeContent).toBe(MyDspaceItemStatusType.ARCHIVED); - expect(component.badgeClass).toBe('text-light badge badge-success'); + expect(component.badgeClass).toBe('text-light badge badge-archived'); }); it('should init badge content and class', () => { component.status = MyDspaceItemStatusType.WORKFLOW; fixture.detectChanges(); expect(component.badgeContent).toBe(MyDspaceItemStatusType.WORKFLOW); - expect(component.badgeClass).toBe('text-light badge badge-info'); + expect(component.badgeClass).toBe('text-light badge badge-workflow'); }); }); diff --git a/src/app/shared/object-collection/shared/mydspace-item-status/my-dspace-item-status.component.ts b/src/app/shared/object-collection/shared/mydspace-item-status/my-dspace-item-status.component.ts index 917dd45acc..83b2656fbd 100644 --- a/src/app/shared/object-collection/shared/mydspace-item-status/my-dspace-item-status.component.ts +++ b/src/app/shared/object-collection/shared/mydspace-item-status/my-dspace-item-status.component.ts @@ -34,19 +34,19 @@ export class MyDSpaceItemStatusComponent implements OnInit { this.badgeClass = 'text-light badge '; switch (this.status) { case MyDspaceItemStatusType.VALIDATION: - this.badgeClass += 'badge-warning'; + this.badgeClass += 'badge-validation'; break; case MyDspaceItemStatusType.WAITING_CONTROLLER: - this.badgeClass += 'badge-info'; + this.badgeClass += 'badge-waiting-controller'; break; case MyDspaceItemStatusType.WORKSPACE: - this.badgeClass += 'badge-primary'; + this.badgeClass += 'badge-workspace'; break; case MyDspaceItemStatusType.ARCHIVED: - this.badgeClass += 'badge-success'; + this.badgeClass += 'badge-archived'; break; case MyDspaceItemStatusType.WORKFLOW: - this.badgeClass += 'badge-info'; + this.badgeClass += 'badge-workflow'; break; } } diff --git a/src/styles/_global-styles.scss b/src/styles/_global-styles.scss index 930384cf64..1bc0c8c435 100644 --- a/src/styles/_global-styles.scss +++ b/src/styles/_global-styles.scss @@ -204,3 +204,27 @@ ds-dynamic-form-control-container.d-none { } + +.badge-validation { + background-color: #{map-get($theme-colors, warning)}; +} + +.badge-waiting-controller { + background-color: #{map-get($theme-colors, info)}; +} + +.badge-workspace { + background-color: #{map-get($theme-colors, primary)}; +} + +.badge-archived { + background-color: #{map-get($theme-colors, success)}; +} + +.badge-workflow { + background-color: #{map-get($theme-colors, info)}; +} + +.badge-item-type { + background-color: #{map-get($theme-colors, info)}; +} From f109e97a0ca61b8c4a520f6661d17f25b894b861 Mon Sep 17 00:00:00 2001 From: Davide Negretti Date: Fri, 21 Oct 2022 12:50:59 +0200 Subject: [PATCH 03/59] [CST-6171] Semantic color scheme --- .../styles/_theme_sass_variable_overrides.scss | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/themes/dspace/styles/_theme_sass_variable_overrides.scss b/src/themes/dspace/styles/_theme_sass_variable_overrides.scss index 9257bc46dd..b5799c9749 100644 --- a/src/themes/dspace/styles/_theme_sass_variable_overrides.scss +++ b/src/themes/dspace/styles/_theme_sass_variable_overrides.scss @@ -10,7 +10,7 @@ $font-family-sans-serif: 'Nunito', -apple-system, BlinkMacSystemFont, "Segoe UI" $navbar-dark-color: #FFFFFF; /* Reassign color vars to semantic color scheme */ -$blue: #43515f !default; +$blue: #2b4e72 !default; $green: #92C642 !default; $cyan: #207698 !default; $yellow: #ec9433 !default; @@ -18,6 +18,7 @@ $red: #CF4444 !default; $dark: #43515f !default; $gray-800: #343a40 !default; +$gray-700: #495057 !default; $gray-400: #ced4da !default; $gray-100: #f8f9fa !default; @@ -27,3 +28,14 @@ $table-accent-bg: $gray-100 !default; // Bootstrap $gray-100 $table-hover-bg: $gray-400 !default; // Bootstrap $gray-400 $yiq-contrasted-threshold: 170 !default; + +$theme-colors: ( + primary: $dark, + secondary: $gray-700, + success: $green, + info: $cyan, + warning: $yellow, + danger: $red, + light: $gray-100, + dark: $dark +) !default; From e6065b7504867334690cc7748f1dacbb8c8ad769 Mon Sep 17 00:00:00 2001 From: Ying Jin Date: Wed, 16 Nov 2022 10:34:00 -0600 Subject: [PATCH 04/59] add captioning support for video/audio files --- .../core/shared/media-viewer-item.model.ts | 5 + .../media-viewer-video/caption-info.ts | 4 + .../media-viewer-video/language-helper.ts | 190 ++++++++++++++++++ .../media-viewer-video.component.html | 11 +- .../media-viewer-video.component.ts | 38 +++- .../media-viewer/media-viewer.component.ts | 1 + 6 files changed, 245 insertions(+), 4 deletions(-) create mode 100644 src/app/item-page/media-viewer/media-viewer-video/caption-info.ts create mode 100644 src/app/item-page/media-viewer/media-viewer-video/language-helper.ts diff --git a/src/app/core/shared/media-viewer-item.model.ts b/src/app/core/shared/media-viewer-item.model.ts index cd3a31bd0b..38c53944d1 100644 --- a/src/app/core/shared/media-viewer-item.model.ts +++ b/src/app/core/shared/media-viewer-item.model.ts @@ -14,6 +14,11 @@ export class MediaViewerItem { */ format: string; + /** + * Incoming Bitsream format mime type + */ + minetype: string; + /** * Incoming Bitsream thumbnail */ diff --git a/src/app/item-page/media-viewer/media-viewer-video/caption-info.ts b/src/app/item-page/media-viewer/media-viewer-video/caption-info.ts new file mode 100644 index 0000000000..011249027f --- /dev/null +++ b/src/app/item-page/media-viewer/media-viewer-video/caption-info.ts @@ -0,0 +1,4 @@ +export class CaptionInfo { + constructor(public src: string, public srclang: string, public langLabel: string ) { + } +} diff --git a/src/app/item-page/media-viewer/media-viewer-video/language-helper.ts b/src/app/item-page/media-viewer/media-viewer-video/language-helper.ts new file mode 100644 index 0000000000..b27ab9983f --- /dev/null +++ b/src/app/item-page/media-viewer/media-viewer-video/language-helper.ts @@ -0,0 +1,190 @@ +export const languageHelper = { + ab: 'Abkhazian', + aa: 'Afar', + af: 'Afrikaans', + ak: 'Akan', + sq: 'Albanian', + am: 'Amharic', + ar: 'Arabic', + an: 'Aragonese', + hy: 'Armenian', + as: 'Assamese', + av: 'Avaric', + ae: 'Avestan', + ay: 'Aymara', + az: 'Azerbaijani', + bm: 'Bambara', + ba: 'Bashkir', + eu: 'Basque', + be: 'Belarusian', + bn: 'Bengali (Bangla)', + bh: 'Bihari', + bi: 'Bislama', + bs: 'Bosnian', + br: 'Breton', + bg: 'Bulgarian', + my: 'Burmese', + ca: 'Catalan', + ch: 'Chamorro', + ce: 'Chechen', + ny: 'Chichewa, Chewa, Nyanja', + zh: 'Chinese', + cv: 'Chuvash', + kw: 'Cornish', + co: 'Corsican', + cr: 'Cree', + hr: 'Croatian', + cs: 'Czech', + da: 'Danish', + dv: 'Divehi, Dhivehi, Maldivian', + nl: 'Dutch', + dz: 'Dzongkha', + en: 'English', + eo: 'Esperanto', + et: 'Estonian', + ee: 'Ewe', + fo: 'Faroese', + fj: 'Fijian', + fi: 'Finnish', + fr: 'French', + ff: 'Fula, Fulah, Pulaar, Pular', + gl: 'Galician', + gd: 'Gaelic (Scottish)', + gv: 'Gaelic (Manx)', + ka: 'Georgian', + de: 'German', + el: 'Greek', + gn: 'Guarani', + gu: 'Gujarati', + ht: 'Haitian Creole', + ha: 'Hausa', + he: 'Hebrew', + hz: 'Herero', + hi: 'Hindi', + ho: 'Hiri Motu', + hu: 'Hungarian', + is: 'Icelandic', + io: 'Ido', + ig: 'Igbo', + in: 'Indonesian', + ia: 'Interlingua', + ie: 'Interlingue', + iu: 'Inuktitut', + ik: 'Inupiak', + ga: 'Irish', + it: 'Italian', + ja: 'Japanese', + jv: 'Javanese', + kl: 'Kalaallisut, Greenlandic', + kn: 'Kannada', + kr: 'Kanuri', + ks: 'Kashmiri', + kk: 'Kazakh', + km: 'Khmer', + ki: 'Kikuyu', + rw: 'Kinyarwanda (Rwanda)', + rn: 'Kirundi', + ky: 'Kyrgyz', + kv: 'Komi', + kg: 'Kongo', + ko: 'Korean', + ku: 'Kurdish', + kj: 'Kwanyama', + lo: 'Lao', + la: 'Latin', + lv: 'Latvian (Lettish)', + li: 'Limburgish ( Limburger)', + ln: 'Lingala', + lt: 'Lithuanian', + lu: 'Luga-Katanga', + lg: 'Luganda, Ganda', + lb: 'Luxembourgish', + mk: 'Macedonian', + mg: 'Malagasy', + ms: 'Malay', + ml: 'Malayalam', + mt: 'Maltese', + mi: 'Maori', + mr: 'Marathi', + mh: 'Marshallese', + mo: 'Moldavian', + mn: 'Mongolian', + na: 'Nauru', + nv: 'Navajo', + ng: 'Ndonga', + nd: 'Northern Ndebele', + ne: 'Nepali', + no: 'Norwegian', + nb: 'Norwegian bokmål', + nn: 'Norwegian nynorsk', + oc: 'Occitan', + oj: 'Ojibwe', + cu: 'Old Church Slavonic, Old Bulgarian', + or: 'Oriya', + om: 'Oromo (Afaan Oromo)', + os: 'Ossetian', + pi: 'Pāli', + ps: 'Pashto, Pushto', + fa: 'Persian (Farsi)', + pl: 'Polish', + pt: 'Portuguese', + pa: 'Punjabi (Eastern)', + qu: 'Quechua', + rm: 'Romansh', + ro: 'Romanian', + ru: 'Russian', + se: 'Sami', + sm: 'Samoan', + sg: 'Sango', + sa: 'Sanskrit', + sr: 'Serbian', + sh: 'Serbo-Croatian', + st: 'Sesotho', + tn: 'Setswana', + sn: 'Shona', + ii: 'Sichuan Yi, Nuosu', + sd: 'Sindhi', + si: 'Sinhalese', + ss: 'Siswati (Swati)', + sk: 'Slovak', + sl: 'Slovenian', + so: 'Somali', + nr: 'Southern Ndebele', + es: 'Spanish', + su: 'Sundanese', + sw: 'Swahili (Kiswahili)', + sv: 'Swedish', + tl: 'Tagalog', + ty: 'Tahitian', + tg: 'Tajik', + ta: 'Tamil', + tt: 'Tatar', + te: 'Telugu', + th: 'Thai', + bo: 'Tibetan', + ti: 'Tigrinya', + to: 'Tonga', + ts: 'Tsonga', + tr: 'Turkish', + tk: 'Turkmen', + tw: 'Twi', + ug: 'Uyghur', + uk: 'Ukrainian', + ur: 'Urdu', + uz: 'Uzbek', + ve: 'Venda', + vi: 'Vietnamese', + vo: 'Volapük', + wa: 'Wallon', + cy: 'Welsh', + wo: 'Wolof', + fy: 'Western Frisian', + xh: 'Xhosa', + yi: 'Yiddish', + yo: 'Yoruba', + za: 'Zhuang, Chuang', + zu: 'Zulu' +}; + + + diff --git a/src/app/item-page/media-viewer/media-viewer-video/media-viewer-video.component.html b/src/app/item-page/media-viewer/media-viewer-video/media-viewer-video.component.html index a4493e36fc..5e74437393 100644 --- a/src/app/item-page/media-viewer/media-viewer-video/media-viewer-video.component.html +++ b/src/app/item-page/media-viewer/media-viewer-video/media-viewer-video.component.html @@ -1,4 +1,5 @@ +> + + + + + + + +
+ + + {{'search.filters.filter.show-tree' | translate: {name: ('search.filters.filter.' + filterConfig.name + '.head' | translate | lowercase )} }} + diff --git a/src/app/shared/search/search-filters/search-filter/okr-search-hierarchy-filter/okr-search-hierarchy-filter.component.spec.ts b/src/app/shared/search/search-filters/search-filter/search-hierarchy-filter/search-hierarchy-filter.component.spec.ts similarity index 92% rename from src/app/shared/search/search-filters/search-filter/okr-search-hierarchy-filter/okr-search-hierarchy-filter.component.spec.ts rename to src/app/shared/search/search-filters/search-filter/search-hierarchy-filter/search-hierarchy-filter.component.spec.ts index fe0866468a..41ab296c18 100644 --- a/src/app/shared/search/search-filters/search-filter/okr-search-hierarchy-filter/okr-search-hierarchy-filter.component.spec.ts +++ b/src/app/shared/search/search-filters/search-filter/search-hierarchy-filter/search-hierarchy-filter.component.spec.ts @@ -1,4 +1,4 @@ -import { OkrSearchHierarchyFilterComponent } from './okr-search-hierarchy-filter.component'; +import { SearchHierarchyFilterComponent } from './search-hierarchy-filter.component'; import { ComponentFixture, TestBed } from '@angular/core/testing'; import { DebugElement, EventEmitter, NO_ERRORS_SCHEMA } from '@angular/core'; import { By } from '@angular/platform-browser'; @@ -23,12 +23,12 @@ import { NgbModal, NgbModule } from '@ng-bootstrap/ng-bootstrap'; import { SEARCH_CONFIG_SERVICE } from '../../../../../my-dspace-page/my-dspace-page.component'; import { SearchConfigurationServiceStub } from '../../../../testing/search-configuration-service.stub'; import { VocabularyEntryDetail } from '../../../../../core/submission/vocabularies/models/vocabulary-entry-detail.model'; -import { FacetValue } from '../../../../../../../../app/shared/search/facet-value.model'; -import { SearchFilterConfig } from '../../../../../../../../app/shared/search/search-filter-config.model'; +import { FacetValue} from '../../../models/facet-value.model'; +import { SearchFilterConfig } from '../../../models/search-filter-config.model'; describe('OkrSearchHierarchyFilterComponent', () => { - let fixture: ComponentFixture; + let fixture: ComponentFixture; let showVocabularyTreeLink: DebugElement; const testSearchLink = 'test-search'; @@ -62,7 +62,7 @@ describe('OkrSearchHierarchyFilterComponent', () => { TranslateModule.forRoot(), ], declarations: [ - OkrSearchHierarchyFilterComponent, + SearchHierarchyFilterComponent, ], providers: [ { provide: SearchService, useValue: searchService }, @@ -80,7 +80,7 @@ describe('OkrSearchHierarchyFilterComponent', () => { }); function init() { - fixture = TestBed.createComponent(OkrSearchHierarchyFilterComponent); + fixture = TestBed.createComponent(SearchHierarchyFilterComponent); fixture.detectChanges(); showVocabularyTreeLink = fixture.debugElement.query(By.css('a#show-test-search-filter-tree')); } diff --git a/src/app/shared/search/search-filters/search-filter/search-hierarchy-filter/search-hierarchy-filter.component.ts b/src/app/shared/search/search-filters/search-filter/search-hierarchy-filter/search-hierarchy-filter.component.ts index 7aa81116de..e24e6c6d02 100644 --- a/src/app/shared/search/search-filters/search-filter/search-hierarchy-filter/search-hierarchy-filter.component.ts +++ b/src/app/shared/search/search-filters/search-filter/search-hierarchy-filter/search-hierarchy-filter.component.ts @@ -1,18 +1,110 @@ -import { Component, OnInit } from '@angular/core'; -import { FilterType } from '../../../models/filter-type.model'; +import { Component, Inject, OnInit } from '@angular/core'; import { renderFacetFor } from '../search-filter-type-decorator'; +import { FilterType } from '../../../models/filter-type.model'; import { facetLoad, SearchFacetFilterComponent } from '../search-facet-filter/search-facet-filter.component'; +import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap'; +import { VocabularyTreeviewComponent } from '../../../../vocabulary-treeview/vocabulary-treeview.component'; +import { + VocabularyEntryDetail +} from '../../../../../core/submission/vocabularies/models/vocabulary-entry-detail.model'; +import { SearchService } from '../../../../../core/shared/search/search.service'; +import { + FILTER_CONFIG, + IN_PLACE_SEARCH, + SearchFilterService +} from '../../../../../core/shared/search/search-filter.service'; +import { Router } from '@angular/router'; +import { RemoteDataBuildService } from '../../../../../core/cache/builders/remote-data-build.service'; +import { SEARCH_CONFIG_SERVICE } from '../../../../../my-dspace-page/my-dspace-page.component'; +import { SearchConfigurationService } from '../../../../../core/shared/search/search-configuration.service'; +import { SearchFilterConfig } from '../../../models/search-filter-config.model'; +import { FacetValue } from '../../../models/facet-value.model'; +import { getFacetValueForType } from '../../../search.utils'; +import { filter, map, take } from 'rxjs/operators'; +import { VocabularyService } from '../../../../../core/submission/vocabularies/vocabulary.service'; +import { Observable } from 'rxjs'; +import { PageInfo } from '../../../../../core/shared/page-info.model'; +import { environment } from '../../../../../../environments/environment'; +/** + * Component that represents a hierarchy facet for a specific filter configuration. + */ @Component({ selector: 'ds-search-hierarchy-filter', styleUrls: ['./search-hierarchy-filter.component.scss'], templateUrl: './search-hierarchy-filter.component.html', animations: [facetLoad] }) - -/** - * Component that represents a hierarchy facet for a specific filter configuration - */ -// @renderFacetFor(FilterType.hierarchy) +@renderFacetFor(FilterType.hierarchy) export class SearchHierarchyFilterComponent extends SearchFacetFilterComponent implements OnInit { + + constructor(protected searchService: SearchService, + protected filterService: SearchFilterService, + protected rdbs: RemoteDataBuildService, + protected router: Router, + protected modalService: NgbModal, + protected vocabularyService: VocabularyService, + @Inject(SEARCH_CONFIG_SERVICE) public searchConfigService: SearchConfigurationService, + @Inject(IN_PLACE_SEARCH) public inPlaceSearch: boolean, + @Inject(FILTER_CONFIG) public filterConfig: SearchFilterConfig, + ) { + super(searchService, filterService, rdbs, router, searchConfigService, inPlaceSearch, filterConfig); + } + + vocabularyExists$: Observable; + + ngOnInit() { + super.ngOnInit(); + this.vocabularyExists$ = this.vocabularyService.searchTopEntries( + this.getVocabularyEntry(), new PageInfo(), true, false, + ).pipe( + filter(rd => rd.hasCompleted), + take(1), + map(rd => { + return rd.hasSucceeded; + }), + ); + } + + /** + * Open the vocabulary tree modal popup. + * When an entry is selected, add the filter query to the search options. + */ + showVocabularyTree() { + const modalRef: NgbModalRef = this.modalService.open(VocabularyTreeviewComponent, { + size: 'lg', + windowClass: 'treeview' + }); + modalRef.componentInstance.vocabularyOptions = { + name: this.getVocabularyEntry(), + closed: true + }; + modalRef.componentInstance.select.subscribe((detail: VocabularyEntryDetail) => { + this.selectedValues$ + .pipe(take(1)) + .subscribe((selectedValues) => { + this.router.navigate( + [this.searchService.getSearchLink()], + { + queryParams: { + [this.filterConfig.paramName]: [...selectedValues, {value: detail.value}] + .map((facetValue: FacetValue) => getFacetValueForType(facetValue, this.filterConfig)), + }, + queryParamsHandling: 'merge', + }, + ); + }); + }); + } + + /** + * Returns the matching vocabulary entry for the given search filter. + * These are configurable in the config file. + */ + getVocabularyEntry() { + const foundVocabularyConfig = environment.vocabularies.filter((v) => v.filter === this.filterConfig.name); + if (foundVocabularyConfig.length > 0 && foundVocabularyConfig[0].enabled === true) { + return foundVocabularyConfig[0].vocabulary; + } + } } diff --git a/src/app/shared/search/search.module.ts b/src/app/shared/search/search.module.ts index e9c0b3e121..668d260c23 100644 --- a/src/app/shared/search/search.module.ts +++ b/src/app/shared/search/search.module.ts @@ -28,9 +28,6 @@ import { MissingTranslationHelper } from '../translate/missing-translation.helpe import { SharedModule } from '../shared.module'; import { SearchResultsComponent } from './search-results/search-results.component'; import { SearchComponent } from './search.component'; -import { - OkrSearchHierarchyFilterComponent -} from './search-filters/search-filter/okr-search-hierarchy-filter/okr-search-hierarchy-filter.component'; const COMPONENTS = [ SearchComponent, @@ -53,8 +50,7 @@ const COMPONENTS = [ SearchAuthorityFilterComponent, SearchSwitchConfigurationComponent, ConfigurationSearchPageComponent, - ThemedConfigurationSearchPageComponent, - OkrSearchHierarchyFilterComponent + ThemedConfigurationSearchPageComponent ]; const ENTRY_COMPONENTS = [ diff --git a/src/app/shared/shared.module.ts b/src/app/shared/shared.module.ts index 6f4091f465..715ee66a99 100644 --- a/src/app/shared/shared.module.ts +++ b/src/app/shared/shared.module.ts @@ -177,10 +177,6 @@ import { ScopeSelectorModalComponent } from './search-form/scope-selector-modal/ import { BitstreamRequestACopyPageComponent } from './bitstream-request-a-copy-page/bitstream-request-a-copy-page.component'; import { DsSelectComponent } from './ds-select/ds-select.component'; import { LogInOidcComponent } from './log-in/methods/oidc/log-in-oidc.component'; -import { OkrVocabularyTreeviewComponent } from './okr-vocabulary-treeview/okr-vocabulary-treeview.component'; -import { - OkrSearchHierarchyFilterComponent -} from './search/search-filters/search-filter/okr-search-hierarchy-filter/okr-search-hierarchy-filter.component'; const MODULES = [ // Do NOT include UniversalModule, HttpModule, or JsonpModule here @@ -350,7 +346,6 @@ const COMPONENTS = [ CommunitySidebarSearchListElementComponent, SearchNavbarComponent, ScopeSelectorModalComponent, - OkrVocabularyTreeviewComponent ]; const ENTRY_COMPONENTS = [ diff --git a/src/app/shared/vocabulary-treeview/vocabulary-treeview.component.ts b/src/app/shared/vocabulary-treeview/vocabulary-treeview.component.ts index f9e4d04f3b..b62c4a2274 100644 --- a/src/app/shared/vocabulary-treeview/vocabulary-treeview.component.ts +++ b/src/app/shared/vocabulary-treeview/vocabulary-treeview.component.ts @@ -2,7 +2,7 @@ import { FlatTreeControl } from '@angular/cdk/tree'; import { Component, EventEmitter, Input, OnDestroy, OnInit, Output } from '@angular/core'; import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; -import { filter, find, startWith } from 'rxjs/operators'; +import { filter, find, startWith, map } from 'rxjs/operators'; import { Observable, Subscription } from 'rxjs'; import { select, Store } from '@ngrx/store'; import { TranslateService } from '@ngx-translate/core'; @@ -18,6 +18,7 @@ import { PageInfo } from '../../core/shared/page-info.model'; import { VocabularyEntry } from '../../core/submission/vocabularies/models/vocabulary-entry.model'; import { VocabularyTreeFlattener } from './vocabulary-tree-flattener'; import { VocabularyTreeFlatDataSource } from './vocabulary-tree-flat-data-source'; +import { lowerCase } from 'lodash'; /** * Component that show a hierarchical vocabulary in a tree view @@ -98,7 +99,7 @@ export class VocabularyTreeviewComponent implements OnDestroy, OnInit { /** * Array to track all subscriptions and unsubscribe them onDestroy */ - protected subs: Subscription[] = []; + private subs: Subscription[] = []; /** * Initialize instance variables @@ -110,9 +111,9 @@ export class VocabularyTreeviewComponent implements OnDestroy, OnInit { */ constructor( public activeModal: NgbActiveModal, - protected vocabularyTreeviewService: VocabularyTreeviewService, - protected store: Store, - protected translate: TranslateService + private vocabularyTreeviewService: VocabularyTreeviewService, + private store: Store, + private translate: TranslateService ) { this.treeFlattener = new VocabularyTreeFlattener(this.transformer, this.getLevel, this.isExpandable, this.getChildren); @@ -203,23 +204,15 @@ export class VocabularyTreeviewComponent implements OnDestroy, OnInit { }) ); - const descriptionLabel = 'vocabulary-treeview.tree.description.' + this.vocabularyOptions.name; - this.description = this.translate.get(descriptionLabel).pipe( - filter((msg) => msg !== descriptionLabel), - startWith('') + this.translate.get(`search.filters.filter.${this.vocabularyOptions.name}.head`).pipe( + map((type) => lowerCase(type)), + ).subscribe( + (type) => this.description = this.translate.get('okr-vocabulary-treeview.info', { type }) ); - // set isAuthenticated - this.isAuthenticated = this.store.pipe(select(isAuthenticated)); - this.loading = this.vocabularyTreeviewService.isLoading(); - this.isAuthenticated.pipe( - find((isAuth) => isAuth) - ).subscribe(() => { - const entryId: string = (this.selectedItem) ? this.getEntryId(this.selectedItem) : null; - this.vocabularyTreeviewService.initialize(this.vocabularyOptions, new PageInfo(), entryId); - }); + this.vocabularyTreeviewService.initialize(this.vocabularyOptions, new PageInfo(), null); } /** @@ -301,7 +294,7 @@ export class VocabularyTreeviewComponent implements OnDestroy, OnInit { /** * Return an id for a given {@link VocabularyEntry} */ - protected getEntryId(entry: VocabularyEntry): string { + private getEntryId(entry: VocabularyEntry): string { return entry.authority || entry.otherInformation.id || undefined; } } From 472c2a1dd1da96b509bd75688914caea786156f1 Mon Sep 17 00:00:00 2001 From: Jens Vannerum Date: Thu, 1 Dec 2022 15:34:41 +0100 Subject: [PATCH 16/59] 97049: Remove client structure --- .../search-hierarchy-filter.component.spec.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/app/shared/search/search-filters/search-filter/search-hierarchy-filter/search-hierarchy-filter.component.spec.ts b/src/app/shared/search/search-filters/search-filter/search-hierarchy-filter/search-hierarchy-filter.component.spec.ts index 41ab296c18..88cb0400e2 100644 --- a/src/app/shared/search/search-filters/search-filter/search-hierarchy-filter/search-hierarchy-filter.component.spec.ts +++ b/src/app/shared/search/search-filters/search-filter/search-hierarchy-filter/search-hierarchy-filter.component.spec.ts @@ -26,14 +26,14 @@ import { VocabularyEntryDetail } from '../../../../../core/submission/vocabulari import { FacetValue} from '../../../models/facet-value.model'; import { SearchFilterConfig } from '../../../models/search-filter-config.model'; -describe('OkrSearchHierarchyFilterComponent', () => { +fdescribe('SearchHierarchyFilterComponent', () => { let fixture: ComponentFixture; let showVocabularyTreeLink: DebugElement; const testSearchLink = 'test-search'; const testSearchFilter = 'test-search-filter'; - const okrVocabularyTreeViewComponent = { + const VocabularyTreeViewComponent = { select: new EventEmitter(), }; @@ -47,7 +47,7 @@ describe('OkrSearchHierarchyFilterComponent', () => { const router = new RouterStub(); const ngbModal = jasmine.createSpyObj('modal', { open: { - componentInstance: okrVocabularyTreeViewComponent, + componentInstance: VocabularyTreeViewComponent, } }); const vocabularyService = { @@ -134,7 +134,7 @@ describe('OkrSearchHierarchyFilterComponent', () => { fixture.componentInstance.selectedValues$ = observableOf( alreadySelectedValues.map(value => Object.assign(new FacetValue(), { value })) ); - okrVocabularyTreeViewComponent.select.emit(Object.assign(new VocabularyEntryDetail(), { + VocabularyTreeViewComponent.select.emit(Object.assign(new VocabularyEntryDetail(), { value: newSelectedValue, })); }); From dd3a528c485a9f1644fe61525cea0dc81c4367f7 Mon Sep 17 00:00:00 2001 From: Jens Vannerum Date: Thu, 1 Dec 2022 16:52:50 +0100 Subject: [PATCH 17/59] 97049: Remove accidental focused describe --- .../search-hierarchy-filter.component.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/shared/search/search-filters/search-filter/search-hierarchy-filter/search-hierarchy-filter.component.spec.ts b/src/app/shared/search/search-filters/search-filter/search-hierarchy-filter/search-hierarchy-filter.component.spec.ts index 88cb0400e2..306d252395 100644 --- a/src/app/shared/search/search-filters/search-filter/search-hierarchy-filter/search-hierarchy-filter.component.spec.ts +++ b/src/app/shared/search/search-filters/search-filter/search-hierarchy-filter/search-hierarchy-filter.component.spec.ts @@ -26,7 +26,7 @@ import { VocabularyEntryDetail } from '../../../../../core/submission/vocabulari import { FacetValue} from '../../../models/facet-value.model'; import { SearchFilterConfig } from '../../../models/search-filter-config.model'; -fdescribe('SearchHierarchyFilterComponent', () => { +describe('SearchHierarchyFilterComponent', () => { let fixture: ComponentFixture; let showVocabularyTreeLink: DebugElement; From 6ed762a8ac1fcbe206b0f656b18457577cce49d8 Mon Sep 17 00:00:00 2001 From: Jens Vannerum Date: Thu, 1 Dec 2022 17:12:14 +0100 Subject: [PATCH 18/59] 97049: alter tests --- .../vocabulary-treeview/vocabulary-treeview.component.spec.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/app/shared/vocabulary-treeview/vocabulary-treeview.component.spec.ts b/src/app/shared/vocabulary-treeview/vocabulary-treeview.component.spec.ts index 1bdf4b9df7..d965bc7f4b 100644 --- a/src/app/shared/vocabulary-treeview/vocabulary-treeview.component.spec.ts +++ b/src/app/shared/vocabulary-treeview/vocabulary-treeview.component.spec.ts @@ -141,7 +141,7 @@ describe('VocabularyTreeviewComponent test suite', () => { comp.selectedItem = currentValue; fixture.detectChanges(); expect(comp.dataSource.data).toEqual([]); - expect(vocabularyTreeviewServiceStub.initialize).toHaveBeenCalledWith(comp.vocabularyOptions, new PageInfo(), 'entryID'); + expect(vocabularyTreeviewServiceStub.initialize).toHaveBeenCalledWith(comp.vocabularyOptions, new PageInfo(), null); }); it('should should init component properly with init value as VocabularyEntry', () => { @@ -153,7 +153,7 @@ describe('VocabularyTreeviewComponent test suite', () => { comp.selectedItem = currentValue; fixture.detectChanges(); expect(comp.dataSource.data).toEqual([]); - expect(vocabularyTreeviewServiceStub.initialize).toHaveBeenCalledWith(comp.vocabularyOptions, new PageInfo(), 'entryID'); + expect(vocabularyTreeviewServiceStub.initialize).toHaveBeenCalledWith(comp.vocabularyOptions, new PageInfo(), null); }); it('should call loadMore function', () => { From aac8fea225949e199271efb9fc9c28bb7aa47716 Mon Sep 17 00:00:00 2001 From: Jens Vannerum Date: Fri, 2 Dec 2022 13:43:22 +0100 Subject: [PATCH 19/59] 97049: Fix constructor issue + rework test for new functionality --- .../search-hierarchy-filter.component.spec.ts | 237 +++++++++--------- .../search-hierarchy-filter.component.ts | 7 +- 2 files changed, 124 insertions(+), 120 deletions(-) diff --git a/src/app/shared/search/search-filters/search-filter/search-hierarchy-filter/search-hierarchy-filter.component.spec.ts b/src/app/shared/search/search-filters/search-filter/search-hierarchy-filter/search-hierarchy-filter.component.spec.ts index 9302e66d98..872d0772bd 100644 --- a/src/app/shared/search/search-filters/search-filter/search-hierarchy-filter/search-hierarchy-filter.component.spec.ts +++ b/src/app/shared/search/search-filters/search-filter/search-hierarchy-filter/search-hierarchy-filter.component.spec.ts @@ -1,155 +1,158 @@ -import { ComponentFixture, TestBed } from '@angular/core/testing'; import { SearchHierarchyFilterComponent } from './search-hierarchy-filter.component'; +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { DebugElement, EventEmitter, NO_ERRORS_SCHEMA } from '@angular/core'; +import { By } from '@angular/platform-browser'; +import { VocabularyService } from '../../../../../core/submission/vocabularies/vocabulary.service'; +import { of as observableOf, BehaviorSubject } from 'rxjs'; +import { RemoteData } from '../../../../../core/data/remote-data'; +import { RequestEntryState } from '../../../../../core/data/request-entry-state.model'; +import { TranslateModule } from '@ngx-translate/core'; +import { RouterStub } from '../../../../testing/router.stub'; +import { buildPaginatedList } from '../../../../../core/data/paginated-list.model'; +import { PageInfo } from '../../../../../core/shared/page-info.model'; +import { CommonModule } from '@angular/common'; import { SearchService } from '../../../../../core/shared/search/search.service'; import { FILTER_CONFIG, IN_PLACE_SEARCH, - REFRESH_FILTER, - SearchFilterService + SearchFilterService, + REFRESH_FILTER } from '../../../../../core/shared/search/search-filter.service'; import { RemoteDataBuildService } from '../../../../../core/cache/builders/remote-data-build.service'; -import { SearchFiltersComponent } from '../../search-filters.component'; import { Router } from '@angular/router'; -import { RouterStub } from '../../../../testing/router.stub'; -import { SearchServiceStub } from '../../../../testing/search-service.stub'; -import { BehaviorSubject, Observable, of as observableOf } from 'rxjs'; +import { NgbModal, NgbModule } from '@ng-bootstrap/ng-bootstrap'; import { SEARCH_CONFIG_SERVICE } from '../../../../../my-dspace-page/my-dspace-page.component'; import { SearchConfigurationServiceStub } from '../../../../testing/search-configuration-service.stub'; +import { VocabularyEntryDetail } from '../../../../../core/submission/vocabularies/models/vocabulary-entry-detail.model'; +import { FacetValue} from '../../../models/facet-value.model'; import { SearchFilterConfig } from '../../../models/search-filter-config.model'; -import { TranslateModule } from '@ngx-translate/core'; -import { - FilterInputSuggestionsComponent -} from '../../../../input-suggestions/filter-suggestions/filter-input-suggestions.component'; -import { FormsModule } from '@angular/forms'; -import { NoopAnimationsModule } from '@angular/platform-browser/animations'; -import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA } from '@angular/core'; -import { createSuccessfulRemoteDataObject$ } from '../../../../remote-data.utils'; -import { FacetValue } from '../../../models/facet-value.model'; -import { FilterType } from '../../../models/filter-type.model'; -import { createPaginatedList } from '../../../../testing/utils.test'; -import { RemoteData } from '../../../../../core/data/remote-data'; -import { PaginatedList } from '../../../../../core/data/paginated-list.model'; describe('SearchHierarchyFilterComponent', () => { - let comp: SearchHierarchyFilterComponent; + let fixture: ComponentFixture; - let searchService: SearchService; - let router; + let showVocabularyTreeLink: DebugElement; - const value1 = 'testvalue1'; - const value2 = 'test2'; - const value3 = 'another value3'; - const values: FacetValue[] = [ - { - label: value1, - value: value1, - count: 52, - _links: { - self: { - href: '' - }, - search: { - href: '' - } - } - }, { - label: value2, - value: value2, - count: 20, - _links: { - self: { - href: '' - }, - search: { - href: '' - } - } - }, { - label: value3, - value: value3, - count: 5, - _links: { - self: { - href: '' - }, - search: { - href: '' - } - } - } - ]; - const mockValues = createSuccessfulRemoteDataObject$(createPaginatedList(values)); - - const searchFilterServiceStub = { - getSelectedValuesForFilter(_filterConfig: SearchFilterConfig): Observable { - return observableOf(values.map((value: FacetValue) => value.value)); - }, - getPage(_paramName: string): Observable { - return observableOf(0); - }, - resetPage(_filterName: string): void { - // empty - } + const testSearchLink = 'test-search'; + const testSearchFilter = 'test-search-filter'; + const VocabularyTreeViewComponent = { + select: new EventEmitter(), }; - const remoteDataBuildServiceStub = { - aggregate(_input: Observable>[]): Observable[]>> { - return createSuccessfulRemoteDataObject$([createPaginatedList(values)]); + const searchService = { + getSearchLink: () => testSearchLink, + getFacetValuesFor: () => observableOf([]), + }; + const searchFilterService = { + getPage: () => observableOf(0), + }; + const router = new RouterStub(); + const ngbModal = jasmine.createSpyObj('modal', { + open: { + componentInstance: VocabularyTreeViewComponent, } + }); + const vocabularyService = { + searchTopEntries: () => undefined, }; - beforeEach(async () => { - await TestBed.configureTestingModule({ - imports: [TranslateModule.forRoot(), NoopAnimationsModule, FormsModule], + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [ + CommonModule, + NgbModule, + TranslateModule.forRoot(), + ], declarations: [ SearchHierarchyFilterComponent, - SearchFiltersComponent, - FilterInputSuggestionsComponent ], providers: [ - { provide: SearchService, useValue: new SearchServiceStub() }, - { provide: SearchFilterService, useValue: searchFilterServiceStub }, - { provide: RemoteDataBuildService, useValue: remoteDataBuildServiceStub }, - { provide: Router, useValue: new RouterStub() }, + { provide: SearchService, useValue: searchService }, + { provide: SearchFilterService, useValue: searchFilterService }, + { provide: RemoteDataBuildService, useValue: {} }, + { provide: Router, useValue: router }, + { provide: NgbModal, useValue: ngbModal }, + { provide: VocabularyService, useValue: vocabularyService }, { provide: SEARCH_CONFIG_SERVICE, useValue: new SearchConfigurationServiceStub() }, { provide: IN_PLACE_SEARCH, useValue: false }, - { provide: FILTER_CONFIG, useValue: new SearchFilterConfig() }, - { provide: REFRESH_FILTER, useValue: new BehaviorSubject(false) } + { provide: FILTER_CONFIG, useValue: Object.assign(new SearchFilterConfig(), { name: testSearchFilter }) }, + { provide: REFRESH_FILTER, useValue: new BehaviorSubject(false)} ], - schemas: [NO_ERRORS_SCHEMA] - }).overrideComponent(SearchHierarchyFilterComponent, { - set: { changeDetection: ChangeDetectionStrategy.Default } + schemas: [NO_ERRORS_SCHEMA], }).compileComponents(); - }) - ; - const mockFilterConfig: SearchFilterConfig = Object.assign(new SearchFilterConfig(), { - name: 'filterName1', - filterType: FilterType.text, - hasFacets: false, - isOpenByDefault: false, - pageSize: 2 }); - beforeEach(async () => { + function init() { fixture = TestBed.createComponent(SearchHierarchyFilterComponent); - comp = fixture.componentInstance; // SearchHierarchyFilterComponent test instance - comp.filterConfig = mockFilterConfig; - searchService = (comp as any).searchService; - // @ts-ignore - spyOn(searchService, 'getFacetValuesFor').and.returnValue(mockValues); - router = (comp as any).router; fixture.detectChanges(); + showVocabularyTreeLink = fixture.debugElement.query(By.css('a#show-test-search-filter-tree')); + } + + describe('if the vocabulary doesn\'t exist', () => { + + beforeEach(() => { + spyOn(vocabularyService, 'searchTopEntries').and.returnValue(observableOf(new RemoteData( + undefined, 0, 0, RequestEntryState.Error, undefined, undefined, 404 + ))); + init(); + }); + + it('should not show the vocabulary tree link', () => { + expect(showVocabularyTreeLink).toBeNull(); + }); }); - it('should navigate to the correct filter with the query operator', () => { - expect((comp as any).searchService.getFacetValuesFor).toHaveBeenCalledWith(comp.filterConfig, 0, {}, null, true); + describe('if the vocabulary exists', () => { - const searchQuery = 'MARVEL'; - comp.onSubmit(searchQuery); + beforeEach(() => { + spyOn(vocabularyService, 'searchTopEntries').and.returnValue(observableOf(new RemoteData( + undefined, 0, 0, RequestEntryState.Success, undefined, buildPaginatedList(new PageInfo(), []), 200 + ))); + init(); + }); - expect(router.navigate).toHaveBeenCalledWith(['', 'search'], Object({ - queryParams: Object({ [mockFilterConfig.paramName]: [...values.map((value: FacetValue) => `${value.value},equals`), `${searchQuery},query`] }), - queryParamsHandling: 'merge' - })); + it('should show the vocabulary tree link', () => { + expect(showVocabularyTreeLink).toBeTruthy(); + }); + + describe('when clicking the vocabulary tree link', () => { + + beforeEach(async () => { + showVocabularyTreeLink.nativeElement.click(); + }); + + it('should open the vocabulary tree modal', () => { + expect(ngbModal.open).toHaveBeenCalled(); + }); + + describe('when selecting a value from the vocabulary tree', () => { + + const alreadySelectedValues = [ + 'already-selected-value-1', + 'already-selected-value-2', + ]; + const newSelectedValue = 'new-selected-value'; + + beforeEach(() => { + fixture.componentInstance.selectedValues$ = observableOf( + alreadySelectedValues.map(value => Object.assign(new FacetValue(), { value })) + ); + VocabularyTreeViewComponent.select.emit(Object.assign(new VocabularyEntryDetail(), { + value: newSelectedValue, + })); + }); + + it('should add a new search filter to the existing search filters', () => { + expect(router.navigate).toHaveBeenCalledWith([testSearchLink], { + queryParams: { + [`f.${testSearchFilter}`]: [ + ...alreadySelectedValues, + newSelectedValue, + ].map((value => `${value},equals`)), + }, + queryParamsHandling: 'merge', + }); + }); + }); + }); }); }); diff --git a/src/app/shared/search/search-filters/search-filter/search-hierarchy-filter/search-hierarchy-filter.component.ts b/src/app/shared/search/search-filters/search-filter/search-hierarchy-filter/search-hierarchy-filter.component.ts index f47e652f3a..3dd866c5b1 100644 --- a/src/app/shared/search/search-filters/search-filter/search-hierarchy-filter/search-hierarchy-filter.component.ts +++ b/src/app/shared/search/search-filters/search-filter/search-hierarchy-filter/search-hierarchy-filter.component.ts @@ -11,7 +11,7 @@ import { SearchService } from '../../../../../core/shared/search/search.service' import { FILTER_CONFIG, IN_PLACE_SEARCH, - SearchFilterService + SearchFilterService, REFRESH_FILTER } from '../../../../../core/shared/search/search-filter.service'; import { Router } from '@angular/router'; import { RemoteDataBuildService } from '../../../../../core/cache/builders/remote-data-build.service'; @@ -22,7 +22,7 @@ import { FacetValue } from '../../../models/facet-value.model'; import { getFacetValueForType } from '../../../search.utils'; import { filter, map, take } from 'rxjs/operators'; import { VocabularyService } from '../../../../../core/submission/vocabularies/vocabulary.service'; -import { Observable } from 'rxjs'; +import { Observable, BehaviorSubject } from 'rxjs'; import { PageInfo } from '../../../../../core/shared/page-info.model'; import { environment } from '../../../../../../environments/environment'; import { addOperatorToFilterValue } from '../../../search.utils'; @@ -49,8 +49,9 @@ export class SearchHierarchyFilterComponent extends SearchFacetFilterComponent i @Inject(SEARCH_CONFIG_SERVICE) public searchConfigService: SearchConfigurationService, @Inject(IN_PLACE_SEARCH) public inPlaceSearch: boolean, @Inject(FILTER_CONFIG) public filterConfig: SearchFilterConfig, + @Inject(REFRESH_FILTER) public refreshFilters: BehaviorSubject ) { - super(searchService, filterService, rdbs, router, searchConfigService, inPlaceSearch, filterConfig); + super(searchService, filterService, rdbs, router, searchConfigService, inPlaceSearch, filterConfig, refreshFilters); } vocabularyExists$: Observable; From 099debf6663ab4e45f939bdaddf71121999f8259 Mon Sep 17 00:00:00 2001 From: Jens Vannerum Date: Fri, 2 Dec 2022 14:11:41 +0100 Subject: [PATCH 20/59] 97049: Resolve lint issues --- .../vocabulary-treeview/vocabulary-treeview.component.ts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/app/shared/vocabulary-treeview/vocabulary-treeview.component.ts b/src/app/shared/vocabulary-treeview/vocabulary-treeview.component.ts index 369c4ac817..548c3d89be 100644 --- a/src/app/shared/vocabulary-treeview/vocabulary-treeview.component.ts +++ b/src/app/shared/vocabulary-treeview/vocabulary-treeview.component.ts @@ -2,14 +2,13 @@ import { FlatTreeControl } from '@angular/cdk/tree'; import { Component, EventEmitter, Input, OnDestroy, OnInit, Output } from '@angular/core'; import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; -import { filter, find, startWith, map } from 'rxjs/operators'; +import { map } from 'rxjs/operators'; import { Observable, Subscription } from 'rxjs'; -import { select, Store } from '@ngrx/store'; +import { Store } from '@ngrx/store'; import { TranslateService } from '@ngx-translate/core'; import { VocabularyEntryDetail } from '../../core/submission/vocabularies/models/vocabulary-entry-detail.model'; import { hasValue, isEmpty, isNotEmpty } from '../empty.util'; -import { isAuthenticated } from '../../core/auth/selectors'; import { VocabularyTreeviewService } from './vocabulary-treeview.service'; import { LOAD_MORE, LOAD_MORE_ROOT, TreeviewFlatNode, TreeviewNode } from './vocabulary-treeview-node.model'; import { VocabularyOptions } from '../../core/submission/vocabularies/models/vocabulary-options.model'; @@ -18,7 +17,7 @@ import { VocabularyEntry } from '../../core/submission/vocabularies/models/vocab import { VocabularyTreeFlattener } from './vocabulary-tree-flattener'; import { VocabularyTreeFlatDataSource } from './vocabulary-tree-flat-data-source'; import { CoreState } from '../../core/core-state.model'; -import { lowerCase } from 'lodash'; +import { lowerCase } from 'lodash/string'; /** * Component that show a hierarchical vocabulary in a tree view From eb1536819733e6e770dfa8fb58c4c5f1e7245d9e Mon Sep 17 00:00:00 2001 From: Jens Vannerum Date: Mon, 5 Dec 2022 09:58:38 +0100 Subject: [PATCH 21/59] 97049: Clean up strings --- .../vocabulary-treeview.component.ts | 2 +- src/assets/i18n/en.json5 | 22 +------------------ 2 files changed, 2 insertions(+), 22 deletions(-) diff --git a/src/app/shared/vocabulary-treeview/vocabulary-treeview.component.ts b/src/app/shared/vocabulary-treeview/vocabulary-treeview.component.ts index 548c3d89be..deffc11e88 100644 --- a/src/app/shared/vocabulary-treeview/vocabulary-treeview.component.ts +++ b/src/app/shared/vocabulary-treeview/vocabulary-treeview.component.ts @@ -206,7 +206,7 @@ export class VocabularyTreeviewComponent implements OnDestroy, OnInit { this.translate.get(`search.filters.filter.${this.vocabularyOptions.name}.head`).pipe( map((type) => lowerCase(type)), ).subscribe( - (type) => this.description = this.translate.get('okr-vocabulary-treeview.info', { type }) + (type) => this.description = this.translate.get('vocabulary-treeview.info', { type }) ); this.loading = this.vocabularyTreeviewService.isLoading(); diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index 32b8c4c265..84bbc04af3 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -4828,25 +4828,5 @@ "search.filters.filter.show-tree": "Browse {{ name }} tree", - "search.filters.filter.supportedlanguage.placeholder": "Supported Language", - - "search.filters.filter.supportedlanguage.label": "Search supported Language", - - "search.filters.filter.topic.placeholder": "Topic", - - "search.filters.filter.topic.label": "Search topic", - - "search.filters.filter.doctype.placeholder": "Document type", - - "search.filters.filter.doctype.label": "Search document type", - - "search.filters.filter.region.placeholder": "Region", - - "search.filters.filter.region.label": "Search region", - - "search.filters.filter.country.placeholder": "Country", - - "search.filters.filter.country.label": "Search country", - - "okr-vocabulary-treeview.info": "Click a {{ type }} to add a search filter" + "vocabulary-treeview.info": "Select a subject to add as search filter" } From acbff2e6b42e15284e53ee522f6cc1ed807424ca Mon Sep 17 00:00:00 2001 From: Jens Vannerum Date: Mon, 5 Dec 2022 15:13:13 +0100 Subject: [PATCH 22/59] 97049: Minor refactor // adding docs --- config/config.example.yml | 10 +++++++++- config/config.yml | 5 ----- src/config/FilterVocabularyConfig.ts | 7 ------- src/config/app-config.interface.ts | 2 +- src/config/default-app-config.ts | 5 ++++- src/config/filter-vocabulary-config.ts | 22 ++++++++++++++++++++++ 6 files changed, 36 insertions(+), 15 deletions(-) delete mode 100644 src/config/FilterVocabularyConfig.ts create mode 100644 src/config/filter-vocabulary-config.ts diff --git a/config/config.example.yml b/config/config.example.yml index 27400f0041..7bc96b8e4a 100644 --- a/config/config.example.yml +++ b/config/config.example.yml @@ -295,4 +295,12 @@ info: # display in supported metadata fields. By default, only dc.description.abstract is supported. markdown: enabled: false - mathjax: false \ No newline at end of file + mathjax: false + +# Which vocabularies should be used for which search filters +# and whether to show the filter in the search sidebar +# Take a look at the filter-vocabulary-config.ts file for documentation on how the options are obtained +vocabularies: + - filter: 'subject' + vocabulary: 'srsc' + enabled: true diff --git a/config/config.yml b/config/config.yml index 5b171d9cc4..b5eecd112f 100644 --- a/config/config.yml +++ b/config/config.yml @@ -3,8 +3,3 @@ rest: host: api7.dspace.org port: 443 nameSpace: /server - -vocabularies: - - filter: 'subject' - vocabulary: 'srsc' - enabled: true diff --git a/src/config/FilterVocabularyConfig.ts b/src/config/FilterVocabularyConfig.ts deleted file mode 100644 index a9b37af2d8..0000000000 --- a/src/config/FilterVocabularyConfig.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { Config } from './config.interface'; - -export interface FilterVocabularyConfig extends Config { - filter: string; - vocabulary: string; - enabled: boolean; -} diff --git a/src/config/app-config.interface.ts b/src/config/app-config.interface.ts index bba7c66168..d62b9e5bcb 100644 --- a/src/config/app-config.interface.ts +++ b/src/config/app-config.interface.ts @@ -20,7 +20,7 @@ import { InfoConfig } from './info-config.interface'; import { CommunityListConfig } from './community-list-config.interface'; import { HomeConfig } from './homepage-config.interface'; import { MarkdownConfig } from './markdown-config.interface'; -import { FilterVocabularyConfig } from './FilterVocabularyConfig'; +import { FilterVocabularyConfig } from './filter-vocabulary-config'; interface AppConfig extends Config { ui: UIServerConfig; diff --git a/src/config/default-app-config.ts b/src/config/default-app-config.ts index e78ef0a221..c4ab741103 100644 --- a/src/config/default-app-config.ts +++ b/src/config/default-app-config.ts @@ -20,7 +20,7 @@ import { InfoConfig } from './info-config.interface'; import { CommunityListConfig } from './community-list-config.interface'; import { HomeConfig } from './homepage-config.interface'; import { MarkdownConfig } from './markdown-config.interface'; -import { FilterVocabularyConfig } from './FilterVocabularyConfig'; +import { FilterVocabularyConfig } from './filter-vocabulary-config'; export class DefaultAppConfig implements AppConfig { production = false; @@ -378,6 +378,9 @@ export class DefaultAppConfig implements AppConfig { mathjax: false, }; + // Which vocabularies should be used for which search filters + // and whether to show the filter in the search sidebar + // Take a look at the filter-vocabulary-config.ts file for documentation on how the options are obtained vocabularies: FilterVocabularyConfig[] = [ { filter: 'subject', diff --git a/src/config/filter-vocabulary-config.ts b/src/config/filter-vocabulary-config.ts new file mode 100644 index 0000000000..54e57090c8 --- /dev/null +++ b/src/config/filter-vocabulary-config.ts @@ -0,0 +1,22 @@ +import { Config } from './config.interface'; + +/** + * Configuration that can be used to enable a vocabulary tree to be used as search filter + */ +export interface FilterVocabularyConfig extends Config { + /** + * The name of the filter where the vocabulary tree should be used + * This is the name of the filter as it's configured in the facet in discovery.xml + * (can also be seen on the /server/api/discover/facets endpoint) + */ + filter: string; + /** + * name of the vocabulary tree to use + * ( name of the file as stored in the dspace/config/controlled-vocabularies folder without file extension ) + */ + vocabulary: string; + /** + * Whether to show the vocabulary tree in the sidebar + */ + enabled: boolean; +} From 9cde4c119e22c69e749895f351e4eb033394261b Mon Sep 17 00:00:00 2001 From: Jens Vannerum Date: Thu, 8 Dec 2022 17:52:49 +0100 Subject: [PATCH 23/59] 97049: Fixing inconsistent tests --- .../search-hierarchy-filter.component.spec.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/app/shared/search/search-filters/search-filter/search-hierarchy-filter/search-hierarchy-filter.component.spec.ts b/src/app/shared/search/search-filters/search-filter/search-hierarchy-filter/search-hierarchy-filter.component.spec.ts index 872d0772bd..29d033fb17 100644 --- a/src/app/shared/search/search-filters/search-filter/search-hierarchy-filter/search-hierarchy-filter.component.spec.ts +++ b/src/app/shared/search/search-filters/search-filter/search-hierarchy-filter/search-hierarchy-filter.component.spec.ts @@ -1,5 +1,5 @@ import { SearchHierarchyFilterComponent } from './search-hierarchy-filter.component'; -import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; import { DebugElement, EventEmitter, NO_ERRORS_SCHEMA } from '@angular/core'; import { By } from '@angular/platform-browser'; import { VocabularyService } from '../../../../../core/submission/vocabularies/vocabulary.service'; @@ -89,12 +89,12 @@ describe('SearchHierarchyFilterComponent', () => { describe('if the vocabulary doesn\'t exist', () => { - beforeEach(() => { + beforeEach(waitForAsync(() => { spyOn(vocabularyService, 'searchTopEntries').and.returnValue(observableOf(new RemoteData( undefined, 0, 0, RequestEntryState.Error, undefined, undefined, 404 ))); init(); - }); + })); it('should not show the vocabulary tree link', () => { expect(showVocabularyTreeLink).toBeNull(); @@ -103,12 +103,12 @@ describe('SearchHierarchyFilterComponent', () => { describe('if the vocabulary exists', () => { - beforeEach(() => { + beforeEach(waitForAsync(() => { spyOn(vocabularyService, 'searchTopEntries').and.returnValue(observableOf(new RemoteData( undefined, 0, 0, RequestEntryState.Success, undefined, buildPaginatedList(new PageInfo(), []), 200 ))); init(); - }); + })); it('should show the vocabulary tree link', () => { expect(showVocabularyTreeLink).toBeTruthy(); From 105308cdf8bc814b5c37df667cccbfb97d60593a Mon Sep 17 00:00:00 2001 From: Jens Vannerum Date: Mon, 12 Dec 2022 11:18:31 +0100 Subject: [PATCH 24/59] 97049: Fixing inconsistent tests --- .../search-hierarchy-filter.component.spec.ts | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/app/shared/search/search-filters/search-filter/search-hierarchy-filter/search-hierarchy-filter.component.spec.ts b/src/app/shared/search/search-filters/search-filter/search-hierarchy-filter/search-hierarchy-filter.component.spec.ts index 29d033fb17..add8061e58 100644 --- a/src/app/shared/search/search-filters/search-filter/search-hierarchy-filter/search-hierarchy-filter.component.spec.ts +++ b/src/app/shared/search/search-filters/search-filter/search-hierarchy-filter/search-hierarchy-filter.component.spec.ts @@ -89,29 +89,31 @@ describe('SearchHierarchyFilterComponent', () => { describe('if the vocabulary doesn\'t exist', () => { - beforeEach(waitForAsync(() => { + beforeEach(() => { spyOn(vocabularyService, 'searchTopEntries').and.returnValue(observableOf(new RemoteData( undefined, 0, 0, RequestEntryState.Error, undefined, undefined, 404 ))); init(); - })); + }); - it('should not show the vocabulary tree link', () => { + it('should not show the vocabulary tree link', (done) => { expect(showVocabularyTreeLink).toBeNull(); + done(); }); }); describe('if the vocabulary exists', () => { - beforeEach(waitForAsync(() => { + beforeEach(() => { spyOn(vocabularyService, 'searchTopEntries').and.returnValue(observableOf(new RemoteData( undefined, 0, 0, RequestEntryState.Success, undefined, buildPaginatedList(new PageInfo(), []), 200 ))); init(); - })); + }); - it('should show the vocabulary tree link', () => { + it('should show the vocabulary tree link', (done) => { expect(showVocabularyTreeLink).toBeTruthy(); + done(); }); describe('when clicking the vocabulary tree link', () => { @@ -120,8 +122,9 @@ describe('SearchHierarchyFilterComponent', () => { showVocabularyTreeLink.nativeElement.click(); }); - it('should open the vocabulary tree modal', () => { + it('should open the vocabulary tree modal', (done) => { expect(ngbModal.open).toHaveBeenCalled(); + done(); }); describe('when selecting a value from the vocabulary tree', () => { @@ -141,7 +144,7 @@ describe('SearchHierarchyFilterComponent', () => { })); }); - it('should add a new search filter to the existing search filters', () => { + it('should add a new search filter to the existing search filters', (done) => { expect(router.navigate).toHaveBeenCalledWith([testSearchLink], { queryParams: { [`f.${testSearchFilter}`]: [ @@ -151,6 +154,7 @@ describe('SearchHierarchyFilterComponent', () => { }, queryParamsHandling: 'merge', }); + done(); }); }); }); From 1af1d511d0ebd7e6315cbcf648dc1a00f8c1d524 Mon Sep 17 00:00:00 2001 From: Jens Vannerum Date: Mon, 12 Dec 2022 11:23:19 +0100 Subject: [PATCH 25/59] 97049: Lint issue --- .../search-hierarchy-filter.component.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/shared/search/search-filters/search-filter/search-hierarchy-filter/search-hierarchy-filter.component.spec.ts b/src/app/shared/search/search-filters/search-filter/search-hierarchy-filter/search-hierarchy-filter.component.spec.ts index add8061e58..165db5e43b 100644 --- a/src/app/shared/search/search-filters/search-filter/search-hierarchy-filter/search-hierarchy-filter.component.spec.ts +++ b/src/app/shared/search/search-filters/search-filter/search-hierarchy-filter/search-hierarchy-filter.component.spec.ts @@ -1,5 +1,5 @@ import { SearchHierarchyFilterComponent } from './search-hierarchy-filter.component'; -import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; +import { ComponentFixture, TestBed } from '@angular/core/testing'; import { DebugElement, EventEmitter, NO_ERRORS_SCHEMA } from '@angular/core'; import { By } from '@angular/platform-browser'; import { VocabularyService } from '../../../../../core/submission/vocabularies/vocabulary.service'; From 04e5510c6b1fc168b8d0225b70880cc618d9e9fb Mon Sep 17 00:00:00 2001 From: Jens Vannerum Date: Tue, 13 Dec 2022 15:01:56 +0100 Subject: [PATCH 26/59] 97049: fix wrong import after merge --- .../search-hierarchy-filter.component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/shared/search/search-filters/search-filter/search-hierarchy-filter/search-hierarchy-filter.component.ts b/src/app/shared/search/search-filters/search-filter/search-hierarchy-filter/search-hierarchy-filter.component.ts index 3dd866c5b1..8504237f09 100644 --- a/src/app/shared/search/search-filters/search-filter/search-hierarchy-filter/search-hierarchy-filter.component.ts +++ b/src/app/shared/search/search-filters/search-filter/search-hierarchy-filter/search-hierarchy-filter.component.ts @@ -3,7 +3,7 @@ import { renderFacetFor } from '../search-filter-type-decorator'; import { FilterType } from '../../../models/filter-type.model'; import { facetLoad, SearchFacetFilterComponent } from '../search-facet-filter/search-facet-filter.component'; import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap'; -import { VocabularyTreeviewComponent } from '../../../../vocabulary-treeview/vocabulary-treeview.component'; +import { VocabularyTreeviewComponent } from '../../../../form/vocabulary-treeview/vocabulary-treeview.component'; import { VocabularyEntryDetail } from '../../../../../core/submission/vocabularies/models/vocabulary-entry-detail.model'; From c2ef6893d37c3c031cb4df698a34f51f81a7fe87 Mon Sep 17 00:00:00 2001 From: Jens Vannerum Date: Tue, 13 Dec 2022 15:12:28 +0100 Subject: [PATCH 27/59] 97049: fix lint issue after merge --- .../form/vocabulary-treeview/vocabulary-treeview.component.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/app/shared/form/vocabulary-treeview/vocabulary-treeview.component.ts b/src/app/shared/form/vocabulary-treeview/vocabulary-treeview.component.ts index 4b03a8c2b3..56909090c7 100644 --- a/src/app/shared/form/vocabulary-treeview/vocabulary-treeview.component.ts +++ b/src/app/shared/form/vocabulary-treeview/vocabulary-treeview.component.ts @@ -9,7 +9,6 @@ import { TranslateService } from '@ngx-translate/core'; import { VocabularyEntryDetail } from '../../../core/submission/vocabularies/models/vocabulary-entry-detail.model'; import { hasValue, isEmpty, isNotEmpty } from '../../empty.util'; -import { isAuthenticated } from '../../../core/auth/selectors'; import { VocabularyTreeviewService } from './vocabulary-treeview.service'; import { LOAD_MORE, LOAD_MORE_ROOT, TreeviewFlatNode, TreeviewNode } from './vocabulary-treeview-node.model'; import { VocabularyOptions } from '../../../core/submission/vocabularies/models/vocabulary-options.model'; From b04c8025dc96ca01dd1a06c0897d108e26ae69e1 Mon Sep 17 00:00:00 2001 From: Jens Vannerum Date: Wed, 14 Dec 2022 11:35:19 +0100 Subject: [PATCH 28/59] 97049: Attempt to fix aSync test --- .../search-hierarchy-filter.component.spec.ts | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/app/shared/search/search-filters/search-filter/search-hierarchy-filter/search-hierarchy-filter.component.spec.ts b/src/app/shared/search/search-filters/search-filter/search-hierarchy-filter/search-hierarchy-filter.component.spec.ts index 165db5e43b..a7ee15db1a 100644 --- a/src/app/shared/search/search-filters/search-filter/search-hierarchy-filter/search-hierarchy-filter.component.spec.ts +++ b/src/app/shared/search/search-filters/search-filter/search-hierarchy-filter/search-hierarchy-filter.component.spec.ts @@ -1,5 +1,5 @@ import { SearchHierarchyFilterComponent } from './search-hierarchy-filter.component'; -import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; import { DebugElement, EventEmitter, NO_ERRORS_SCHEMA } from '@angular/core'; import { By } from '@angular/platform-browser'; import { VocabularyService } from '../../../../../core/submission/vocabularies/vocabulary.service'; @@ -144,8 +144,8 @@ describe('SearchHierarchyFilterComponent', () => { })); }); - it('should add a new search filter to the existing search filters', (done) => { - expect(router.navigate).toHaveBeenCalledWith([testSearchLink], { + it('should add a new search filter to the existing search filters', () => { + waitForAsync(() => expect(router.navigate).toHaveBeenCalledWith([testSearchLink], { queryParams: { [`f.${testSearchFilter}`]: [ ...alreadySelectedValues, @@ -153,8 +153,7 @@ describe('SearchHierarchyFilterComponent', () => { ].map((value => `${value},equals`)), }, queryParamsHandling: 'merge', - }); - done(); + })); }); }); }); From 07fe4f261f1fc35c75a4f8d6952caedc497b7106 Mon Sep 17 00:00:00 2001 From: Jens Vannerum Date: Wed, 14 Dec 2022 11:52:00 +0100 Subject: [PATCH 29/59] 97049: Attempt to fix aSync test --- .../search-hierarchy-filter.component.spec.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/app/shared/search/search-filters/search-filter/search-hierarchy-filter/search-hierarchy-filter.component.spec.ts b/src/app/shared/search/search-filters/search-filter/search-hierarchy-filter/search-hierarchy-filter.component.spec.ts index a7ee15db1a..7fc21a3c31 100644 --- a/src/app/shared/search/search-filters/search-filter/search-hierarchy-filter/search-hierarchy-filter.component.spec.ts +++ b/src/app/shared/search/search-filters/search-filter/search-hierarchy-filter/search-hierarchy-filter.component.spec.ts @@ -154,6 +154,7 @@ describe('SearchHierarchyFilterComponent', () => { }, queryParamsHandling: 'merge', })); + fixture.destroy(); }); }); }); From 2fea10aced4194c73da32385d74eccf9527e9376 Mon Sep 17 00:00:00 2001 From: Ying Jin Date: Thu, 15 Dec 2022 17:18:22 -0600 Subject: [PATCH 30/59] add/remove comments --- .../media-viewer/media-viewer-video/caption-info.ts | 7 +++++++ .../media-viewer-video/media-viewer-video.component.html | 1 - .../media-viewer-video/media-viewer-video.component.ts | 1 - 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/app/item-page/media-viewer/media-viewer-video/caption-info.ts b/src/app/item-page/media-viewer/media-viewer-video/caption-info.ts index 011249027f..43996d096d 100644 --- a/src/app/item-page/media-viewer/media-viewer-video/caption-info.ts +++ b/src/app/item-page/media-viewer/media-viewer-video/caption-info.ts @@ -1,3 +1,10 @@ +/* + The class is designed to host information related to Video Captioning support + and used in HTML 5 video track + src: source vtt file + srclang: two letter language code + langLabel: language label + */ export class CaptionInfo { constructor(public src: string, public srclang: string, public langLabel: string ) { } diff --git a/src/app/item-page/media-viewer/media-viewer-video/media-viewer-video.component.html b/src/app/item-page/media-viewer/media-viewer-video/media-viewer-video.component.html index 5e74437393..0cc854b272 100644 --- a/src/app/item-page/media-viewer/media-viewer-video/media-viewer-video.component.html +++ b/src/app/item-page/media-viewer/media-viewer-video/media-viewer-video.component.html @@ -10,7 +10,6 @@ preload="none" controls > - diff --git a/src/app/item-page/media-viewer/media-viewer-video/media-viewer-video.component.ts b/src/app/item-page/media-viewer/media-viewer-video/media-viewer-video.component.ts index c4806d8306..cc08d2b4a0 100644 --- a/src/app/item-page/media-viewer/media-viewer-video/media-viewer-video.component.ts +++ b/src/app/item-page/media-viewer/media-viewer-video/media-viewer-video.component.ts @@ -52,7 +52,6 @@ export class MediaViewerVideoComponent implements OnInit { filteredCapMedias .forEach((media, index) => { let srclang: string = media.bitstream.name.slice(-6, -4).toLowerCase(); - //capInfos[index] = new CaptionInfo( capInfos.push(new CaptionInfo( media.bitstream._links.content.href, srclang, From 247e61ce2b734087a162f087d5cd9bcc38571056 Mon Sep 17 00:00:00 2001 From: Nikunj Sharma Date: Fri, 16 Dec 2022 19:15:28 +0530 Subject: [PATCH 31/59] [CST-7604] fixed as per tom comment to highlight Journal, Project, OrgUnit or Person) or is a Community or Collection --- ...rch-result-list-submission-element.component.ts | 2 +- ...rch-result-list-submission-element.component.ts | 2 +- ...em-search-result-grid-element.component.spec.ts | 14 +++++++++++++- .../item-search-result-grid-element.component.ts | 3 ++- .../item-search-result-list-element.component.html | 4 ++-- .../search-result-list-element.component.ts | 2 +- 6 files changed, 20 insertions(+), 7 deletions(-) diff --git a/src/app/entity-groups/research-entities/submission/item-list-elements/org-unit/org-unit-search-result-list-submission-element.component.ts b/src/app/entity-groups/research-entities/submission/item-list-elements/org-unit/org-unit-search-result-list-submission-element.component.ts index 7a38a02cf4..954f7bc591 100644 --- a/src/app/entity-groups/research-entities/submission/item-list-elements/org-unit/org-unit-search-result-list-submission-element.component.ts +++ b/src/app/entity-groups/research-entities/submission/item-list-elements/org-unit/org-unit-search-result-list-submission-element.component.ts @@ -61,7 +61,7 @@ export class OrgUnitSearchResultListSubmissionElementComponent extends SearchRes this.useNameVariants = this.context === Context.EntitySearchModalWithNameVariants; if (this.useNameVariants) { - const defaultValue = this.dsoTitle; + const defaultValue = this.dso ? this.dsoNameService.getName(this.dso) : undefined; const alternatives = this.allMetadataValues(this.alternativeField); this.allSuggestions = [defaultValue, ...alternatives]; diff --git a/src/app/entity-groups/research-entities/submission/item-list-elements/person/person-search-result-list-submission-element.component.ts b/src/app/entity-groups/research-entities/submission/item-list-elements/person/person-search-result-list-submission-element.component.ts index 7d761c42dd..305407f8d2 100644 --- a/src/app/entity-groups/research-entities/submission/item-list-elements/person/person-search-result-list-submission-element.component.ts +++ b/src/app/entity-groups/research-entities/submission/item-list-elements/person/person-search-result-list-submission-element.component.ts @@ -55,7 +55,7 @@ export class PersonSearchResultListSubmissionElementComponent extends SearchResu ngOnInit() { super.ngOnInit(); - const defaultValue = this.dsoTitle; + const defaultValue = this.dso ? this.dsoNameService.getName(this.dso) : undefined; const alternatives = this.allMetadataValues(this.alternativeField); this.allSuggestions = [defaultValue, ...alternatives]; diff --git a/src/app/shared/object-grid/search-result-grid-element/item-search-result/item/item-search-result-grid-element.component.spec.ts b/src/app/shared/object-grid/search-result-grid-element/item-search-result/item/item-search-result-grid-element.component.spec.ts index 57b863a1b1..97dda155c5 100644 --- a/src/app/shared/object-grid/search-result-grid-element/item-search-result/item/item-search-result-grid-element.component.spec.ts +++ b/src/app/shared/object-grid/search-result-grid-element/item-search-result/item/item-search-result-grid-element.component.spec.ts @@ -28,13 +28,14 @@ import { ItemSearchResultGridElementComponent } from './item-search-result-grid- const mockItemWithMetadata: ItemSearchResult = new ItemSearchResult(); mockItemWithMetadata.hitHighlights = {}; +const dcTitle = 'This is just another title'; mockItemWithMetadata.indexableObject = Object.assign(new Item(), { bundles: createSuccessfulRemoteDataObject$(buildPaginatedList(new PageInfo(), [])), metadata: { 'dc.title': [ { language: 'en_US', - value: 'This is just another title' + value: dcTitle } ], 'dc.contributor.author': [ @@ -154,6 +155,17 @@ export function getEntityGridElementTestComponent(component, searchResultWithMet expect(itemAuthorField).toBeNull(); }); }); + + describe('When the item has title', () => { + beforeEach(() => { + comp.object = mockItemWithMetadata; + fixture.detectChanges(); + }); + it('should show highlighted title', () => { + const titleField = fixture.debugElement.query(By.css('.card-title')); + expect(titleField.nativeNode.innerHTML).toEqual(dcTitle); + }); + }); }); }; } diff --git a/src/app/shared/object-grid/search-result-grid-element/item-search-result/item/item-search-result-grid-element.component.ts b/src/app/shared/object-grid/search-result-grid-element/item-search-result/item/item-search-result-grid-element.component.ts index b5f9c016e4..fc24d5450b 100644 --- a/src/app/shared/object-grid/search-result-grid-element/item-search-result/item/item-search-result-grid-element.component.ts +++ b/src/app/shared/object-grid/search-result-grid-element/item-search-result/item/item-search-result-grid-element.component.ts @@ -42,6 +42,7 @@ export class ItemSearchResultGridElementComponent extends SearchResultGridElemen ngOnInit(): void { super.ngOnInit(); this.itemPageRoute = getItemPageRoute(this.dso); - this.dsoTitle = this.dsoNameService.getName(this.dso); + this.dsoTitle = this.firstMetadataValue('dc.title') ?? + (this.dso ? this.dsoNameService.getName(this.dso) : undefined); } } diff --git a/src/app/shared/object-list/search-result-list-element/item-search-result/item-types/item/item-search-result-list-element.component.html b/src/app/shared/object-list/search-result-list-element/item-search-result/item-types/item/item-search-result-list-element.component.html index ad0206bd4e..6b2951495d 100644 --- a/src/app/shared/object-list/search-result-list-element/item-search-result/item-types/item/item-search-result-list-element.component.html +++ b/src/app/shared/object-list/search-result-list-element/item-search-result/item-types/item/item-search-result-list-element.component.html @@ -19,9 +19,9 @@ + [innerHTML]="dsoTitle"> + [innerHTML]="dsoTitle"> diff --git a/src/app/shared/object-list/search-result-list-element/search-result-list-element.component.ts b/src/app/shared/object-list/search-result-list-element/search-result-list-element.component.ts index 72120a6b68..c69044e907 100644 --- a/src/app/shared/object-list/search-result-list-element/search-result-list-element.component.ts +++ b/src/app/shared/object-list/search-result-list-element/search-result-list-element.component.ts @@ -33,7 +33,7 @@ export class SearchResultListElementComponent, K exten ngOnInit(): void { if (hasValue(this.object)) { this.dso = this.object.indexableObject; - this.dsoTitle = this.dsoNameService.getName(this.dso); + this.dsoTitle = this.firstMetadataValue('dc.title') ?? this.dsoNameService.getName(this.dso); } } From 2afc835b7f1ed1d3b717801c0cc14cd51243fd95 Mon Sep 17 00:00:00 2001 From: "Mark H. Wood" Date: Fri, 16 Dec 2022 17:17:55 -0500 Subject: [PATCH 32/59] Catch and report errors from non-JSON responses. --- src/app/core/auth/auth.interceptor.ts | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/app/core/auth/auth.interceptor.ts b/src/app/core/auth/auth.interceptor.ts index e55d0c0ff9..672879f436 100644 --- a/src/app/core/auth/auth.interceptor.ts +++ b/src/app/core/auth/auth.interceptor.ts @@ -196,7 +196,24 @@ export class AuthInterceptor implements HttpInterceptor { authStatus.token = new AuthTokenInfo(accessToken); } else { authStatus.authenticated = false; - authStatus.error = isNotEmpty(error) ? ((typeof error === 'string') ? JSON.parse(error) : error) : null; + if (isNotEmpty(error)) { + if (typeof error === 'string') { + try { + authStatus.error = JSON.parse(error); + } catch (e) { + console.error('Unknown auth error "', error, '" caused ', e); + authStatus.error = { + error: 'Unknown', + message: 'Unknown auth error', + status: 500, + timestamp: Date.now(), + path: '' + }; + } + } else { + authStatus.error = error; + } + } } return authStatus; } From ec89addf17ebbd0af9d99205f979a9343ee8dcdf Mon Sep 17 00:00:00 2001 From: Jens Vannerum Date: Mon, 2 Jan 2023 12:14:33 +0100 Subject: [PATCH 33/59] 97049: Missing provided service after merge --- src/modules/app/browser-app.module.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/modules/app/browser-app.module.ts b/src/modules/app/browser-app.module.ts index 6baf339003..4cdf7fbe2f 100644 --- a/src/modules/app/browser-app.module.ts +++ b/src/modules/app/browser-app.module.ts @@ -31,6 +31,7 @@ import { GoogleAnalyticsService } from '../../app/statistics/google-analytics.se import { AuthRequestService } from '../../app/core/auth/auth-request.service'; import { BrowserAuthRequestService } from '../../app/core/auth/browser-auth-request.service'; import { BrowserInitService } from './browser-init.service'; +import { VocabularyTreeviewService } from 'src/app/shared/form/vocabulary-treeview/vocabulary-treeview.service'; export const REQ_KEY = makeStateKey('req'); @@ -111,6 +112,10 @@ export function getRequest(transferState: TransferState): any { provide: LocationToken, useFactory: locationProvider, }, + { + provide: VocabularyTreeviewService, + useClass: VocabularyTreeviewService, + } ] }) export class BrowserAppModule { From 6012c66d1cf0f05b88b76cf1f1983d5798c25cfb Mon Sep 17 00:00:00 2001 From: Jens Vannerum Date: Mon, 2 Jan 2023 13:48:50 +0100 Subject: [PATCH 34/59] 97049: fix tests --- .../search-hierarchy-filter.component.spec.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/app/shared/search/search-filters/search-filter/search-hierarchy-filter/search-hierarchy-filter.component.spec.ts b/src/app/shared/search/search-filters/search-filter/search-hierarchy-filter/search-hierarchy-filter.component.spec.ts index 7fc21a3c31..7ae4545da9 100644 --- a/src/app/shared/search/search-filters/search-filter/search-hierarchy-filter/search-hierarchy-filter.component.spec.ts +++ b/src/app/shared/search/search-filters/search-filter/search-hierarchy-filter/search-hierarchy-filter.component.spec.ts @@ -87,6 +87,10 @@ describe('SearchHierarchyFilterComponent', () => { showVocabularyTreeLink = fixture.debugElement.query(By.css('a#show-test-search-filter-tree')); } + afterEach(() => { + fixture.destroy(); + }); + describe('if the vocabulary doesn\'t exist', () => { beforeEach(() => { @@ -154,7 +158,6 @@ describe('SearchHierarchyFilterComponent', () => { }, queryParamsHandling: 'merge', })); - fixture.destroy(); }); }); }); From 9b6ba906d68c90ea699f5191a85ee2e30c10fec9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 2 Jan 2023 12:50:21 +0000 Subject: [PATCH 35/59] Bump json5 from 2.2.1 to 2.2.2 Bumps [json5](https://github.com/json5/json5) from 2.2.1 to 2.2.2. - [Release notes](https://github.com/json5/json5/releases) - [Changelog](https://github.com/json5/json5/blob/main/CHANGELOG.md) - [Commits](https://github.com/json5/json5/compare/v2.2.1...v2.2.2) --- updated-dependencies: - dependency-name: json5 dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 52b089be37..387e094a67 100644 --- a/package.json +++ b/package.json @@ -99,7 +99,7 @@ "http-proxy-middleware": "^1.0.5", "js-cookie": "2.2.1", "js-yaml": "^4.1.0", - "json5": "^2.1.3", + "json5": "^2.2.2", "jsonschema": "1.4.0", "jwt-decode": "^3.1.2", "klaro": "^0.7.18", diff --git a/yarn.lock b/yarn.lock index e92c5bf954..22eeefb309 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7005,10 +7005,10 @@ json5@^1.0.1: dependencies: minimist "^1.2.0" -json5@^2.1.2, json5@^2.1.3, json5@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.1.tgz#655d50ed1e6f95ad1a3caababd2b0efda10b395c" - integrity sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA== +json5@^2.1.2, json5@^2.2.1, json5@^2.2.2: + version "2.2.2" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.2.tgz#64471c5bdcc564c18f7c1d4df2e2297f2457c5ab" + integrity sha512-46Tk9JiOL2z7ytNQWFLpj99RZkVgeHf87yGQKsIkaPz1qSH9UczKH1rO7K3wgRselo0tYMUNfecYpm/p1vC7tQ== jsonc-parser@3.0.0: version "3.0.0" From 3e09653f0b4078eaffd5e01e8a80136469b559f0 Mon Sep 17 00:00:00 2001 From: Jens Vannerum Date: Mon, 2 Jan 2023 14:38:20 +0100 Subject: [PATCH 36/59] 97049: Nest before each statements --- .../search-hierarchy-filter.component.spec.ts | 40 +++++++------------ 1 file changed, 15 insertions(+), 25 deletions(-) diff --git a/src/app/shared/search/search-filters/search-filter/search-hierarchy-filter/search-hierarchy-filter.component.spec.ts b/src/app/shared/search/search-filters/search-filter/search-hierarchy-filter/search-hierarchy-filter.component.spec.ts index 7ae4545da9..e6c74d8047 100644 --- a/src/app/shared/search/search-filters/search-filter/search-hierarchy-filter/search-hierarchy-filter.component.spec.ts +++ b/src/app/shared/search/search-filters/search-filter/search-hierarchy-filter/search-hierarchy-filter.component.spec.ts @@ -87,10 +87,6 @@ describe('SearchHierarchyFilterComponent', () => { showVocabularyTreeLink = fixture.debugElement.query(By.css('a#show-test-search-filter-tree')); } - afterEach(() => { - fixture.destroy(); - }); - describe('if the vocabulary doesn\'t exist', () => { beforeEach(() => { @@ -100,9 +96,8 @@ describe('SearchHierarchyFilterComponent', () => { init(); }); - it('should not show the vocabulary tree link', (done) => { + it('should not show the vocabulary tree link', () => { expect(showVocabularyTreeLink).toBeNull(); - done(); }); }); @@ -115,39 +110,34 @@ describe('SearchHierarchyFilterComponent', () => { init(); }); - it('should show the vocabulary tree link', (done) => { + it('should show the vocabulary tree link', () => { expect(showVocabularyTreeLink).toBeTruthy(); - done(); }); describe('when clicking the vocabulary tree link', () => { + const alreadySelectedValues = [ + 'already-selected-value-1', + 'already-selected-value-2', + ]; + const newSelectedValue = 'new-selected-value'; + beforeEach(async () => { showVocabularyTreeLink.nativeElement.click(); + fixture.componentInstance.selectedValues$ = observableOf( + alreadySelectedValues.map(value => Object.assign(new FacetValue(), { value })) + ); + VocabularyTreeViewComponent.select.emit(Object.assign(new VocabularyEntryDetail(), { + value: newSelectedValue, + })); }); - it('should open the vocabulary tree modal', (done) => { + it('should open the vocabulary tree modal', () => { expect(ngbModal.open).toHaveBeenCalled(); - done(); }); describe('when selecting a value from the vocabulary tree', () => { - const alreadySelectedValues = [ - 'already-selected-value-1', - 'already-selected-value-2', - ]; - const newSelectedValue = 'new-selected-value'; - - beforeEach(() => { - fixture.componentInstance.selectedValues$ = observableOf( - alreadySelectedValues.map(value => Object.assign(new FacetValue(), { value })) - ); - VocabularyTreeViewComponent.select.emit(Object.assign(new VocabularyEntryDetail(), { - value: newSelectedValue, - })); - }); - it('should add a new search filter to the existing search filters', () => { waitForAsync(() => expect(router.navigate).toHaveBeenCalledWith([testSearchLink], { queryParams: { From 661ed72c1188d24d4cff0157c2204580577385f5 Mon Sep 17 00:00:00 2001 From: Yury Bondarenko Date: Tue, 3 Jan 2023 17:02:05 +0100 Subject: [PATCH 37/59] 96252: Move Item page components out of SharedModule --- .../alerts}/item-alerts.component.html | 0 .../alerts}/item-alerts.component.scss | 0 .../alerts}/item-alerts.component.spec.ts | 2 +- .../alerts}/item-alerts.component.ts | 4 +- ...tstream-request-a-copy-page.component.html | 0 ...ream-request-a-copy-page.component.spec.ts | 28 +++++------ ...bitstream-request-a-copy-page.component.ts | 30 ++++++------ .../edit-item-page/edit-item-page.module.ts | 4 +- .../full-file-section.component.spec.ts | 2 +- src/app/item-page/item-page-routing.module.ts | 4 +- src/app/item-page/item-page.module.ts | 17 +++++-- src/app/item-page/item-shared.module.ts | 27 ++++++++++- .../media-viewer-video.component.spec.ts | 2 +- .../media-viewer.component.spec.ts | 2 +- .../file-section.component.spec.ts | 2 +- .../untyped-item.component.spec.ts | 2 +- .../versioned-item.component.spec.ts | 4 +- .../versioned-item.component.ts | 4 +- .../item-versions-delete-modal.component.html | 0 .../item-versions-delete-modal.component.scss | 0 ...em-versions-delete-modal.component.spec.ts | 0 .../item-versions-delete-modal.component.ts | 0 .../item-versions-shared.service.spec.ts | 16 +++---- .../versions}/item-versions-shared.service.ts | 6 +-- ...item-versions-summary-modal.component.html | 0 ...item-versions-summary-modal.component.scss | 0 ...m-versions-summary-modal.component.spec.ts | 0 .../item-versions-summary-modal.component.ts | 2 +- .../versions}/item-versions.component.html | 0 .../versions}/item-versions.component.scss | 0 .../versions}/item-versions.component.spec.ts | 42 ++++++++-------- .../versions}/item-versions.component.ts | 46 +++++++++--------- .../versions/item-versions.module.ts | 32 +++++++++++++ .../item-versions-notice.component.html | 0 .../item-versions-notice.component.spec.ts | 12 ++--- .../notice/item-versions-notice.component.ts | 18 +++---- .../metadata-field-wrapper.component.html | 0 .../metadata-field-wrapper.component.scss | 0 .../metadata-field-wrapper.component.spec.ts | 0 .../metadata-field-wrapper.component.ts | 0 src/app/shared/shared.module.ts | 48 +------------------ src/themes/custom/lazy-theme.module.ts | 4 ++ src/themes/dspace/lazy-theme.module.ts | 4 ++ 43 files changed, 198 insertions(+), 166 deletions(-) rename src/app/{shared/item/item-alerts => item-page/alerts}/item-alerts.component.html (100%) rename src/app/{shared/item/item-alerts => item-page/alerts}/item-alerts.component.scss (100%) rename src/app/{shared/item/item-alerts => item-page/alerts}/item-alerts.component.spec.ts (97%) rename src/app/{shared/item/item-alerts => item-page/alerts}/item-alerts.component.ts (80%) rename src/app/{shared/bitstream-request-a-copy-page => item-page/bitstreams/request-a-copy}/bitstream-request-a-copy-page.component.html (100%) rename src/app/{shared/bitstream-request-a-copy-page => item-page/bitstreams/request-a-copy}/bitstream-request-a-copy-page.component.spec.ts (90%) rename src/app/{shared/bitstream-request-a-copy-page => item-page/bitstreams/request-a-copy}/bitstream-request-a-copy-page.component.ts (85%) rename src/app/{shared/item/item-versions => item-page/versions}/item-versions-delete-modal/item-versions-delete-modal.component.html (100%) rename src/app/{shared/item/item-versions => item-page/versions}/item-versions-delete-modal/item-versions-delete-modal.component.scss (100%) rename src/app/{shared/item/item-versions => item-page/versions}/item-versions-delete-modal/item-versions-delete-modal.component.spec.ts (100%) rename src/app/{shared/item/item-versions => item-page/versions}/item-versions-delete-modal/item-versions-delete-modal.component.ts (100%) rename src/app/{shared/item/item-versions => item-page/versions}/item-versions-shared.service.spec.ts (75%) rename src/app/{shared/item/item-versions => item-page/versions}/item-versions-shared.service.ts (84%) rename src/app/{shared/item/item-versions => item-page/versions}/item-versions-summary-modal/item-versions-summary-modal.component.html (100%) rename src/app/{shared/item/item-versions => item-page/versions}/item-versions-summary-modal/item-versions-summary-modal.component.scss (100%) rename src/app/{shared/item/item-versions => item-page/versions}/item-versions-summary-modal/item-versions-summary-modal.component.spec.ts (100%) rename src/app/{shared/item/item-versions => item-page/versions}/item-versions-summary-modal/item-versions-summary-modal.component.ts (93%) rename src/app/{shared/item/item-versions => item-page/versions}/item-versions.component.html (100%) rename src/app/{shared/item/item-versions => item-page/versions}/item-versions.component.scss (100%) rename src/app/{shared/item/item-versions => item-page/versions}/item-versions.component.spec.ts (87%) rename src/app/{shared/item/item-versions => item-page/versions}/item-versions.component.ts (91%) create mode 100644 src/app/item-page/versions/item-versions.module.ts rename src/app/{shared/item/item-versions => item-page/versions}/notice/item-versions-notice.component.html (100%) rename src/app/{shared/item/item-versions => item-page/versions}/notice/item-versions-notice.component.spec.ts (90%) rename src/app/{shared/item/item-versions => item-page/versions}/notice/item-versions-notice.component.ts (81%) rename src/app/{item-page/field-components => shared}/metadata-field-wrapper/metadata-field-wrapper.component.html (100%) rename src/app/{item-page/field-components => shared}/metadata-field-wrapper/metadata-field-wrapper.component.scss (100%) rename src/app/{item-page/field-components => shared}/metadata-field-wrapper/metadata-field-wrapper.component.spec.ts (100%) rename src/app/{item-page/field-components => shared}/metadata-field-wrapper/metadata-field-wrapper.component.ts (100%) diff --git a/src/app/shared/item/item-alerts/item-alerts.component.html b/src/app/item-page/alerts/item-alerts.component.html similarity index 100% rename from src/app/shared/item/item-alerts/item-alerts.component.html rename to src/app/item-page/alerts/item-alerts.component.html diff --git a/src/app/shared/item/item-alerts/item-alerts.component.scss b/src/app/item-page/alerts/item-alerts.component.scss similarity index 100% rename from src/app/shared/item/item-alerts/item-alerts.component.scss rename to src/app/item-page/alerts/item-alerts.component.scss diff --git a/src/app/shared/item/item-alerts/item-alerts.component.spec.ts b/src/app/item-page/alerts/item-alerts.component.spec.ts similarity index 97% rename from src/app/shared/item/item-alerts/item-alerts.component.spec.ts rename to src/app/item-page/alerts/item-alerts.component.spec.ts index fed81199fd..a933eb6a58 100644 --- a/src/app/shared/item/item-alerts/item-alerts.component.spec.ts +++ b/src/app/item-page/alerts/item-alerts.component.spec.ts @@ -2,7 +2,7 @@ import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; import { ItemAlertsComponent } from './item-alerts.component'; import { TranslateModule } from '@ngx-translate/core'; import { NO_ERRORS_SCHEMA } from '@angular/core'; -import { Item } from '../../../core/shared/item.model'; +import { Item } from '../../core/shared/item.model'; import { By } from '@angular/platform-browser'; describe('ItemAlertsComponent', () => { diff --git a/src/app/shared/item/item-alerts/item-alerts.component.ts b/src/app/item-page/alerts/item-alerts.component.ts similarity index 80% rename from src/app/shared/item/item-alerts/item-alerts.component.ts rename to src/app/item-page/alerts/item-alerts.component.ts index 4c2d60d24c..d7a84db015 100644 --- a/src/app/shared/item/item-alerts/item-alerts.component.ts +++ b/src/app/item-page/alerts/item-alerts.component.ts @@ -1,6 +1,6 @@ import { Component, Input } from '@angular/core'; -import { Item } from '../../../core/shared/item.model'; -import { AlertType } from '../../alert/aletr-type'; +import { Item } from '../../core/shared/item.model'; +import { AlertType } from '../../shared/alert/aletr-type'; @Component({ selector: 'ds-item-alerts', diff --git a/src/app/shared/bitstream-request-a-copy-page/bitstream-request-a-copy-page.component.html b/src/app/item-page/bitstreams/request-a-copy/bitstream-request-a-copy-page.component.html similarity index 100% rename from src/app/shared/bitstream-request-a-copy-page/bitstream-request-a-copy-page.component.html rename to src/app/item-page/bitstreams/request-a-copy/bitstream-request-a-copy-page.component.html diff --git a/src/app/shared/bitstream-request-a-copy-page/bitstream-request-a-copy-page.component.spec.ts b/src/app/item-page/bitstreams/request-a-copy/bitstream-request-a-copy-page.component.spec.ts similarity index 90% rename from src/app/shared/bitstream-request-a-copy-page/bitstream-request-a-copy-page.component.spec.ts rename to src/app/item-page/bitstreams/request-a-copy/bitstream-request-a-copy-page.component.spec.ts index cc44ef8587..cbfbdf361f 100644 --- a/src/app/shared/bitstream-request-a-copy-page/bitstream-request-a-copy-page.component.spec.ts +++ b/src/app/item-page/bitstreams/request-a-copy/bitstream-request-a-copy-page.component.spec.ts @@ -1,30 +1,30 @@ import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; -import { AuthService } from '../../core/auth/auth.service'; +import { AuthService } from '../../../core/auth/auth.service'; import { of as observableOf } from 'rxjs'; -import { Bitstream } from '../../core/shared/bitstream.model'; -import { AuthorizationDataService } from '../../core/data/feature-authorization/authorization-data.service'; +import { Bitstream } from '../../../core/shared/bitstream.model'; +import { AuthorizationDataService } from '../../../core/data/feature-authorization/authorization-data.service'; import { createFailedRemoteDataObject$, createSuccessfulRemoteDataObject, createSuccessfulRemoteDataObject$ -} from '../remote-data.utils'; +} from '../../../shared/remote-data.utils'; import { ActivatedRoute, Router } from '@angular/router'; import { TranslateModule } from '@ngx-translate/core'; import { CommonModule } from '@angular/common'; import { BitstreamRequestACopyPageComponent } from './bitstream-request-a-copy-page.component'; import { By } from '@angular/platform-browser'; -import { RouterStub } from '../testing/router.stub'; +import { RouterStub } from '../../../shared/testing/router.stub'; import { FormsModule, ReactiveFormsModule } from '@angular/forms'; -import { NotificationsServiceStub } from '../testing/notifications-service.stub'; -import { ItemRequestDataService } from '../../core/data/item-request-data.service'; -import { NotificationsService } from '../notifications/notifications.service'; -import { DSONameService } from '../../core/breadcrumbs/dso-name.service'; -import { DSONameServiceMock } from '../mocks/dso-name.service.mock'; -import { Item } from '../../core/shared/item.model'; -import { EPerson } from '../../core/eperson/models/eperson.model'; -import { ItemRequest } from '../../core/shared/item-request.model'; +import { NotificationsServiceStub } from '../../../shared/testing/notifications-service.stub'; +import { ItemRequestDataService } from '../../../core/data/item-request-data.service'; +import { NotificationsService } from '../../../shared/notifications/notifications.service'; +import { DSONameService } from '../../../core/breadcrumbs/dso-name.service'; +import { DSONameServiceMock } from '../../../shared/mocks/dso-name.service.mock'; +import { Item } from '../../../core/shared/item.model'; +import { EPerson } from '../../../core/eperson/models/eperson.model'; +import { ItemRequest } from '../../../core/shared/item-request.model'; import { Location } from '@angular/common'; -import { BitstreamDataService } from '../../core/data/bitstream-data.service'; +import { BitstreamDataService } from '../../../core/data/bitstream-data.service'; describe('BitstreamRequestACopyPageComponent', () => { diff --git a/src/app/shared/bitstream-request-a-copy-page/bitstream-request-a-copy-page.component.ts b/src/app/item-page/bitstreams/request-a-copy/bitstream-request-a-copy-page.component.ts similarity index 85% rename from src/app/shared/bitstream-request-a-copy-page/bitstream-request-a-copy-page.component.ts rename to src/app/item-page/bitstreams/request-a-copy/bitstream-request-a-copy-page.component.ts index 511079a701..59819a4a66 100644 --- a/src/app/shared/bitstream-request-a-copy-page/bitstream-request-a-copy-page.component.ts +++ b/src/app/item-page/bitstreams/request-a-copy/bitstream-request-a-copy-page.component.ts @@ -1,25 +1,25 @@ import { Component, OnDestroy, OnInit } from '@angular/core'; import { filter, map, switchMap, take } from 'rxjs/operators'; import { ActivatedRoute, Router } from '@angular/router'; -import { hasValue, isNotEmpty } from '../empty.util'; -import { getFirstCompletedRemoteData, getFirstSucceededRemoteDataPayload } from '../../core/shared/operators'; -import { Bitstream } from '../../core/shared/bitstream.model'; -import { AuthorizationDataService } from '../../core/data/feature-authorization/authorization-data.service'; -import { FeatureID } from '../../core/data/feature-authorization/feature-id'; -import { AuthService } from '../../core/auth/auth.service'; +import { hasValue, isNotEmpty } from '../../../shared/empty.util'; +import { getFirstCompletedRemoteData, getFirstSucceededRemoteDataPayload } from '../../../core/shared/operators'; +import { Bitstream } from '../../../core/shared/bitstream.model'; +import { AuthorizationDataService } from '../../../core/data/feature-authorization/authorization-data.service'; +import { FeatureID } from '../../../core/data/feature-authorization/feature-id'; +import { AuthService } from '../../../core/auth/auth.service'; import { combineLatest as observableCombineLatest, Observable, of as observableOf, Subscription } from 'rxjs'; -import { getBitstreamDownloadRoute, getForbiddenRoute } from '../../app-routing-paths'; +import { getBitstreamDownloadRoute, getForbiddenRoute } from '../../../app-routing-paths'; import { TranslateService } from '@ngx-translate/core'; -import { EPerson } from '../../core/eperson/models/eperson.model'; +import { EPerson } from '../../../core/eperson/models/eperson.model'; import { FormBuilder, FormControl, FormGroup, Validators } from '@angular/forms'; -import { ItemRequestDataService } from '../../core/data/item-request-data.service'; -import { ItemRequest } from '../../core/shared/item-request.model'; -import { Item } from '../../core/shared/item.model'; -import { NotificationsService } from '../notifications/notifications.service'; -import { DSONameService } from '../../core/breadcrumbs/dso-name.service'; +import { ItemRequestDataService } from '../../../core/data/item-request-data.service'; +import { ItemRequest } from '../../../core/shared/item-request.model'; +import { Item } from '../../../core/shared/item.model'; +import { NotificationsService } from '../../../shared/notifications/notifications.service'; +import { DSONameService } from '../../../core/breadcrumbs/dso-name.service'; import { Location } from '@angular/common'; -import { BitstreamDataService } from '../../core/data/bitstream-data.service'; -import { getItemPageRoute } from '../../item-page/item-page-routing-paths'; +import { BitstreamDataService } from '../../../core/data/bitstream-data.service'; +import { getItemPageRoute } from '../../item-page-routing-paths'; @Component({ selector: 'ds-bitstream-request-a-copy-page', diff --git a/src/app/item-page/edit-item-page/edit-item-page.module.ts b/src/app/item-page/edit-item-page/edit-item-page.module.ts index 3ed741bc1a..fafbae0bd4 100644 --- a/src/app/item-page/edit-item-page/edit-item-page.module.ts +++ b/src/app/item-page/edit-item-page/edit-item-page.module.ts @@ -36,6 +36,7 @@ import { ItemVersionHistoryComponent } from './item-version-history/item-version import { ItemAuthorizationsComponent } from './item-authorizations/item-authorizations.component'; import { ObjectValuesPipe } from '../../shared/utils/object-values-pipe'; import { ResourcePoliciesModule } from '../../shared/resource-policies/resource-policies.module'; +import { ItemVersionsModule } from '../versions/item-versions.module'; /** @@ -50,7 +51,8 @@ import { ResourcePoliciesModule } from '../../shared/resource-policies/resource- SearchPageModule, DragDropModule, ResourcePoliciesModule, - NgbModule + NgbModule, + ItemVersionsModule, ], declarations: [ EditItemPageComponent, diff --git a/src/app/item-page/full/field-components/file-section/full-file-section.component.spec.ts b/src/app/item-page/full/field-components/file-section/full-file-section.component.spec.ts index 396e6c3216..9a4bd05587 100644 --- a/src/app/item-page/full/field-components/file-section/full-file-section.component.spec.ts +++ b/src/app/item-page/full/field-components/file-section/full-file-section.component.spec.ts @@ -7,7 +7,7 @@ import { TranslateLoaderMock } from '../../../../shared/mocks/translate-loader.m import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; import { VarDirective } from '../../../../shared/utils/var.directive'; import { FileSizePipe } from '../../../../shared/utils/file-size-pipe'; -import { MetadataFieldWrapperComponent } from '../../../field-components/metadata-field-wrapper/metadata-field-wrapper.component'; +import { MetadataFieldWrapperComponent } from '../../../../shared/metadata-field-wrapper/metadata-field-wrapper.component'; import { BitstreamDataService } from '../../../../core/data/bitstream-data.service'; import { NO_ERRORS_SCHEMA } from '@angular/core'; import { Bitstream } from '../../../../core/shared/bitstream.model'; diff --git a/src/app/item-page/item-page-routing.module.ts b/src/app/item-page/item-page-routing.module.ts index add2c3d768..bda09be458 100644 --- a/src/app/item-page/item-page-routing.module.ts +++ b/src/app/item-page/item-page-routing.module.ts @@ -14,9 +14,7 @@ import { ThemedItemPageComponent } from './simple/themed-item-page.component'; import { ThemedFullItemPageComponent } from './full/themed-full-item-page.component'; import { MenuItemType } from '../shared/menu/menu-item-type.model'; import { VersionPageComponent } from './version-page/version-page/version-page.component'; -import { - BitstreamRequestACopyPageComponent -} from '../shared/bitstream-request-a-copy-page/bitstream-request-a-copy-page.component'; +import { BitstreamRequestACopyPageComponent } from './bitstreams/request-a-copy/bitstream-request-a-copy-page.component'; import { REQUEST_COPY_MODULE_PATH } from '../app-routing-paths'; import { OrcidPageComponent } from './orcid-page/orcid-page.component'; import { OrcidPageGuard } from './orcid-page/orcid-page.guard'; diff --git a/src/app/item-page/item-page.module.ts b/src/app/item-page/item-page.module.ts index de9f2f60c5..39c2580921 100644 --- a/src/app/item-page/item-page.module.ts +++ b/src/app/item-page/item-page.module.ts @@ -47,6 +47,11 @@ import { NgbAccordionModule } from '@ng-bootstrap/ng-bootstrap'; import { OrcidSyncSettingsComponent } from './orcid-page/orcid-sync-settings/orcid-sync-settings.component'; import { OrcidQueueComponent } from './orcid-page/orcid-queue/orcid-queue.component'; import { UploadModule } from '../shared/upload/upload.module'; +import { ItemAlertsComponent } from './alerts/item-alerts.component'; +import { ItemVersionsModule } from './versions/item-versions.module'; +import { BitstreamRequestACopyPageComponent } from './bitstreams/request-a-copy/bitstream-request-a-copy-page.component'; +import { FileSectionComponent } from './simple/field-components/file-section/file-section.component'; +import { ItemSharedModule } from './item-shared.module'; const ENTRY_COMPONENTS = [ @@ -56,6 +61,7 @@ const ENTRY_COMPONENTS = [ ]; const DECLARATIONS = [ + FileSectionComponent, ThemedFileSectionComponent, ItemPageComponent, ThemedItemPageComponent, @@ -82,7 +88,10 @@ const DECLARATIONS = [ OrcidPageComponent, OrcidAuthComponent, OrcidSyncSettingsComponent, - OrcidQueueComponent + OrcidQueueComponent, + ItemAlertsComponent, + VersionedItemComponent, + BitstreamRequestACopyPageComponent, ]; @NgModule({ @@ -91,6 +100,8 @@ const DECLARATIONS = [ SharedModule.withEntryComponents(), ItemPageRoutingModule, EditItemPageModule, + ItemVersionsModule, + ItemSharedModule, StatisticsModule.forRoot(), JournalEntitiesModule.withEntryComponents(), ResearchEntitiesModule.withEntryComponents(), @@ -100,10 +111,10 @@ const DECLARATIONS = [ ], declarations: [ ...DECLARATIONS, - VersionedItemComponent + ], exports: [ - ...DECLARATIONS + ...DECLARATIONS, ] }) export class ItemPageModule { diff --git a/src/app/item-page/item-shared.module.ts b/src/app/item-page/item-shared.module.ts index b191b6c4b3..c558b11692 100644 --- a/src/app/item-page/item-shared.module.ts +++ b/src/app/item-page/item-shared.module.ts @@ -7,10 +7,32 @@ import { TranslateModule } from '@ngx-translate/core'; import { DYNAMIC_FORM_CONTROL_MAP_FN } from '@ng-dynamic-forms/core'; import { dsDynamicFormControlMapFn } from '../shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component'; import { TabbedRelatedEntitiesSearchComponent } from './simple/related-entities/tabbed-related-entities-search/tabbed-related-entities-search.component'; +import { ItemVersionsDeleteModalComponent } from './versions/item-versions-delete-modal/item-versions-delete-modal.component'; +import { ItemVersionsSummaryModalComponent } from './versions/item-versions-summary-modal/item-versions-summary-modal.component'; +import { MetadataValuesComponent } from './field-components/metadata-values/metadata-values.component'; +import { DsoPageVersionButtonComponent } from '../shared/dso-page/dso-page-version-button/dso-page-version-button.component'; +import { PersonPageClaimButtonComponent } from '../shared/dso-page/person-page-claim-button/person-page-claim-button.component'; +import { GenericItemPageFieldComponent } from './simple/field-components/specific-field/generic/generic-item-page-field.component'; +import { MetadataRepresentationListComponent } from './simple/metadata-representation-list/metadata-representation-list.component'; +import { RelatedItemsComponent } from './simple/related-items/related-items-component'; +import { DsoPageOrcidButtonComponent } from '../shared/dso-page/dso-page-orcid-button/dso-page-orcid-button.component'; + +const ENTRY_COMPONENTS = [ + ItemVersionsDeleteModalComponent, + ItemVersionsSummaryModalComponent, +]; const COMPONENTS = [ + ...ENTRY_COMPONENTS, RelatedEntitiesSearchComponent, - TabbedRelatedEntitiesSearchComponent + TabbedRelatedEntitiesSearchComponent, + MetadataValuesComponent, + DsoPageVersionButtonComponent, + PersonPageClaimButtonComponent, + GenericItemPageFieldComponent, + MetadataRepresentationListComponent, + RelatedItemsComponent, + DsoPageOrcidButtonComponent ]; @NgModule({ @@ -30,7 +52,8 @@ const COMPONENTS = [ { provide: DYNAMIC_FORM_CONTROL_MAP_FN, useValue: dsDynamicFormControlMapFn - } + }, + ...ENTRY_COMPONENTS, ] }) export class ItemSharedModule { } diff --git a/src/app/item-page/media-viewer/media-viewer-video/media-viewer-video.component.spec.ts b/src/app/item-page/media-viewer/media-viewer-video/media-viewer-video.component.spec.ts index 354ba57727..846b5878f4 100644 --- a/src/app/item-page/media-viewer/media-viewer-video/media-viewer-video.component.spec.ts +++ b/src/app/item-page/media-viewer/media-viewer-video/media-viewer-video.component.spec.ts @@ -8,7 +8,7 @@ import { MediaViewerItem } from '../../../core/shared/media-viewer-item.model'; import { TranslateLoaderMock } from '../../../shared/mocks/translate-loader.mock'; import { FileSizePipe } from '../../../shared/utils/file-size-pipe'; import { VarDirective } from '../../../shared/utils/var.directive'; -import { MetadataFieldWrapperComponent } from '../../field-components/metadata-field-wrapper/metadata-field-wrapper.component'; +import { MetadataFieldWrapperComponent } from '../../../shared/metadata-field-wrapper/metadata-field-wrapper.component'; import { MockBitstreamFormat1 } from '../../../shared/mocks/item.mock'; import { MediaViewerVideoComponent } from './media-viewer-video.component'; import { By } from '@angular/platform-browser'; diff --git a/src/app/item-page/media-viewer/media-viewer.component.spec.ts b/src/app/item-page/media-viewer/media-viewer.component.spec.ts index 39a35ebe61..3369574f20 100644 --- a/src/app/item-page/media-viewer/media-viewer.component.spec.ts +++ b/src/app/item-page/media-viewer/media-viewer.component.spec.ts @@ -13,7 +13,7 @@ import { BitstreamDataService } from '../../core/data/bitstream-data.service'; import { NO_ERRORS_SCHEMA } from '@angular/core'; import { MediaViewerItem } from '../../core/shared/media-viewer-item.model'; import { VarDirective } from '../../shared/utils/var.directive'; -import { MetadataFieldWrapperComponent } from '../field-components/metadata-field-wrapper/metadata-field-wrapper.component'; +import { MetadataFieldWrapperComponent } from '../../shared/metadata-field-wrapper/metadata-field-wrapper.component'; import { FileSizePipe } from '../../shared/utils/file-size-pipe'; describe('MediaViewerComponent', () => { diff --git a/src/app/item-page/simple/field-components/file-section/file-section.component.spec.ts b/src/app/item-page/simple/field-components/file-section/file-section.component.spec.ts index 2d185aef9c..dfeb253ec4 100644 --- a/src/app/item-page/simple/field-components/file-section/file-section.component.spec.ts +++ b/src/app/item-page/simple/field-components/file-section/file-section.component.spec.ts @@ -13,7 +13,7 @@ import { of as observableOf } from 'rxjs'; import { MockBitstreamFormat1 } from '../../../../shared/mocks/item.mock'; import { FileSizePipe } from '../../../../shared/utils/file-size-pipe'; import { PageInfo } from '../../../../core/shared/page-info.model'; -import { MetadataFieldWrapperComponent } from '../../../field-components/metadata-field-wrapper/metadata-field-wrapper.component'; +import { MetadataFieldWrapperComponent } from '../../../../shared/metadata-field-wrapper/metadata-field-wrapper.component'; import { createPaginatedList } from '../../../../shared/testing/utils.test'; import { NotificationsService } from '../../../../shared/notifications/notifications.service'; import { NotificationsServiceStub } from '../../../../shared/testing/notifications-service.stub'; diff --git a/src/app/item-page/simple/item-types/untyped-item/untyped-item.component.spec.ts b/src/app/item-page/simple/item-types/untyped-item/untyped-item.component.spec.ts index 57f546fbec..176a692f4b 100644 --- a/src/app/item-page/simple/item-types/untyped-item/untyped-item.component.spec.ts +++ b/src/app/item-page/simple/item-types/untyped-item/untyped-item.component.spec.ts @@ -36,7 +36,7 @@ import { VersionDataService } from '../../../../core/data/version-data.service'; import { RouterTestingModule } from '@angular/router/testing'; import { WorkspaceitemDataService } from '../../../../core/submission/workspaceitem-data.service'; import { SearchService } from '../../../../core/shared/search/search.service'; -import { ItemVersionsSharedService } from '../../../../shared/item/item-versions/item-versions-shared.service'; +import { ItemVersionsSharedService } from '../../../versions/item-versions-shared.service'; const noMetadata = new MetadataMap(); diff --git a/src/app/item-page/simple/item-types/versioned-item/versioned-item.component.spec.ts b/src/app/item-page/simple/item-types/versioned-item/versioned-item.component.spec.ts index 9aeea8b11e..fcd82ce678 100644 --- a/src/app/item-page/simple/item-types/versioned-item/versioned-item.component.spec.ts +++ b/src/app/item-page/simple/item-types/versioned-item/versioned-item.component.spec.ts @@ -5,7 +5,7 @@ import { VersionHistoryDataService } from '../../../../core/data/version-history import { TranslateLoader, TranslateModule } from '@ngx-translate/core'; import { VersionDataService } from '../../../../core/data/version-data.service'; import { NotificationsService } from '../../../../shared/notifications/notifications.service'; -import { ItemVersionsSharedService } from '../../../../shared/item/item-versions/item-versions-shared.service'; +import { ItemVersionsSharedService } from '../../../versions/item-versions-shared.service'; import { Item } from '../../../../core/shared/item.model'; import { createSuccessfulRemoteDataObject$ } from '../../../../shared/remote-data.utils'; import { buildPaginatedList } from '../../../../core/data/paginated-list.model'; @@ -20,6 +20,7 @@ import { ItemDataService } from '../../../../core/data/item-data.service'; import { Version } from '../../../../core/shared/version.model'; import { RouteService } from '../../../../core/services/route.service'; import { TranslateLoaderMock } from '../../../../shared/testing/translate-loader.mock'; +import { ItemSharedModule } from '../../../item-shared.module'; const mockItem: Item = Object.assign(new Item(), { bundles: createSuccessfulRemoteDataObject$(buildPaginatedList(new PageInfo(), [])), @@ -66,6 +67,7 @@ describe('VersionedItemComponent', () => { useClass: TranslateLoaderMock, } }), + ItemSharedModule, ], providers: [ { provide: VersionHistoryDataService, useValue: versionHistoryServiceSpy }, diff --git a/src/app/item-page/simple/item-types/versioned-item/versioned-item.component.ts b/src/app/item-page/simple/item-types/versioned-item/versioned-item.component.ts index 7f61cee10b..0cedc3bb10 100644 --- a/src/app/item-page/simple/item-types/versioned-item/versioned-item.component.ts +++ b/src/app/item-page/simple/item-types/versioned-item/versioned-item.component.ts @@ -1,6 +1,6 @@ import { Component } from '@angular/core'; import { ItemComponent } from '../shared/item.component'; -import { ItemVersionsSummaryModalComponent } from '../../../../shared/item/item-versions/item-versions-summary-modal/item-versions-summary-modal.component'; +import { ItemVersionsSummaryModalComponent } from '../../../versions/item-versions-summary-modal/item-versions-summary-modal.component'; import { getFirstCompletedRemoteData, getFirstSucceededRemoteDataPayload } from '../../../../core/shared/operators'; import { RemoteData } from '../../../../core/data/remote-data'; import { Version } from '../../../../core/shared/version.model'; @@ -9,7 +9,7 @@ import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; import { VersionHistoryDataService } from '../../../../core/data/version-history-data.service'; import { TranslateService } from '@ngx-translate/core'; import { VersionDataService } from '../../../../core/data/version-data.service'; -import { ItemVersionsSharedService } from '../../../../shared/item/item-versions/item-versions-shared.service'; +import { ItemVersionsSharedService } from '../../../versions/item-versions-shared.service'; import { Router } from '@angular/router'; import { WorkspaceitemDataService } from '../../../../core/submission/workspaceitem-data.service'; import { SearchService } from '../../../../core/shared/search/search.service'; diff --git a/src/app/shared/item/item-versions/item-versions-delete-modal/item-versions-delete-modal.component.html b/src/app/item-page/versions/item-versions-delete-modal/item-versions-delete-modal.component.html similarity index 100% rename from src/app/shared/item/item-versions/item-versions-delete-modal/item-versions-delete-modal.component.html rename to src/app/item-page/versions/item-versions-delete-modal/item-versions-delete-modal.component.html diff --git a/src/app/shared/item/item-versions/item-versions-delete-modal/item-versions-delete-modal.component.scss b/src/app/item-page/versions/item-versions-delete-modal/item-versions-delete-modal.component.scss similarity index 100% rename from src/app/shared/item/item-versions/item-versions-delete-modal/item-versions-delete-modal.component.scss rename to src/app/item-page/versions/item-versions-delete-modal/item-versions-delete-modal.component.scss diff --git a/src/app/shared/item/item-versions/item-versions-delete-modal/item-versions-delete-modal.component.spec.ts b/src/app/item-page/versions/item-versions-delete-modal/item-versions-delete-modal.component.spec.ts similarity index 100% rename from src/app/shared/item/item-versions/item-versions-delete-modal/item-versions-delete-modal.component.spec.ts rename to src/app/item-page/versions/item-versions-delete-modal/item-versions-delete-modal.component.spec.ts diff --git a/src/app/shared/item/item-versions/item-versions-delete-modal/item-versions-delete-modal.component.ts b/src/app/item-page/versions/item-versions-delete-modal/item-versions-delete-modal.component.ts similarity index 100% rename from src/app/shared/item/item-versions/item-versions-delete-modal/item-versions-delete-modal.component.ts rename to src/app/item-page/versions/item-versions-delete-modal/item-versions-delete-modal.component.ts diff --git a/src/app/shared/item/item-versions/item-versions-shared.service.spec.ts b/src/app/item-page/versions/item-versions-shared.service.spec.ts similarity index 75% rename from src/app/shared/item/item-versions/item-versions-shared.service.spec.ts rename to src/app/item-page/versions/item-versions-shared.service.spec.ts index a9f9596548..d4adbf681f 100644 --- a/src/app/shared/item/item-versions/item-versions-shared.service.spec.ts +++ b/src/app/item-page/versions/item-versions-shared.service.spec.ts @@ -2,15 +2,15 @@ import { TestBed } from '@angular/core/testing'; import { ItemVersionsSharedService } from './item-versions-shared.service'; import { ActivatedRoute } from '@angular/router'; -import { VersionDataService } from '../../../core/data/version-data.service'; -import { AuthService } from '../../../core/auth/auth.service'; -import { NotificationsService } from '../../notifications/notifications.service'; +import { VersionDataService } from '../../core/data/version-data.service'; +import { AuthService } from '../../core/auth/auth.service'; +import { NotificationsService } from '../../shared/notifications/notifications.service'; import { TranslateService } from '@ngx-translate/core'; -import { VersionHistoryDataService } from '../../../core/data/version-history-data.service'; -import { WorkspaceitemDataService } from '../../../core/submission/workspaceitem-data.service'; -import { WorkflowItemDataService } from '../../../core/submission/workflowitem-data.service'; -import { createFailedRemoteDataObject, createSuccessfulRemoteDataObject } from '../../remote-data.utils'; -import { Version } from '../../../core/shared/version.model'; +import { VersionHistoryDataService } from '../../core/data/version-history-data.service'; +import { WorkspaceitemDataService } from '../../core/submission/workspaceitem-data.service'; +import { WorkflowItemDataService } from '../../core/submission/workflowitem-data.service'; +import { createFailedRemoteDataObject, createSuccessfulRemoteDataObject } from '../../shared/remote-data.utils'; +import { Version } from '../../core/shared/version.model'; describe('ItemVersionsSharedService', () => { let service: ItemVersionsSharedService; diff --git a/src/app/shared/item/item-versions/item-versions-shared.service.ts b/src/app/item-page/versions/item-versions-shared.service.ts similarity index 84% rename from src/app/shared/item/item-versions/item-versions-shared.service.ts rename to src/app/item-page/versions/item-versions-shared.service.ts index 996623509c..09104f5ddc 100644 --- a/src/app/shared/item/item-versions/item-versions-shared.service.ts +++ b/src/app/item-page/versions/item-versions-shared.service.ts @@ -1,8 +1,8 @@ import { Injectable } from '@angular/core'; -import { NotificationsService } from '../../notifications/notifications.service'; +import { NotificationsService } from '../../shared/notifications/notifications.service'; import { TranslateService } from '@ngx-translate/core'; -import { RemoteData } from '../../../core/data/remote-data'; -import { Version } from '../../../core/shared/version.model'; +import { RemoteData } from '../../core/data/remote-data'; +import { Version } from '../../core/shared/version.model'; @Injectable({ providedIn: 'root' diff --git a/src/app/shared/item/item-versions/item-versions-summary-modal/item-versions-summary-modal.component.html b/src/app/item-page/versions/item-versions-summary-modal/item-versions-summary-modal.component.html similarity index 100% rename from src/app/shared/item/item-versions/item-versions-summary-modal/item-versions-summary-modal.component.html rename to src/app/item-page/versions/item-versions-summary-modal/item-versions-summary-modal.component.html diff --git a/src/app/shared/item/item-versions/item-versions-summary-modal/item-versions-summary-modal.component.scss b/src/app/item-page/versions/item-versions-summary-modal/item-versions-summary-modal.component.scss similarity index 100% rename from src/app/shared/item/item-versions/item-versions-summary-modal/item-versions-summary-modal.component.scss rename to src/app/item-page/versions/item-versions-summary-modal/item-versions-summary-modal.component.scss diff --git a/src/app/shared/item/item-versions/item-versions-summary-modal/item-versions-summary-modal.component.spec.ts b/src/app/item-page/versions/item-versions-summary-modal/item-versions-summary-modal.component.spec.ts similarity index 100% rename from src/app/shared/item/item-versions/item-versions-summary-modal/item-versions-summary-modal.component.spec.ts rename to src/app/item-page/versions/item-versions-summary-modal/item-versions-summary-modal.component.spec.ts diff --git a/src/app/shared/item/item-versions/item-versions-summary-modal/item-versions-summary-modal.component.ts b/src/app/item-page/versions/item-versions-summary-modal/item-versions-summary-modal.component.ts similarity index 93% rename from src/app/shared/item/item-versions/item-versions-summary-modal/item-versions-summary-modal.component.ts rename to src/app/item-page/versions/item-versions-summary-modal/item-versions-summary-modal.component.ts index 23ee62e628..8f2c7bd62e 100644 --- a/src/app/shared/item/item-versions/item-versions-summary-modal/item-versions-summary-modal.component.ts +++ b/src/app/item-page/versions/item-versions-summary-modal/item-versions-summary-modal.component.ts @@ -1,7 +1,7 @@ import { Component, EventEmitter, OnInit, Output } from '@angular/core'; import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; import { BehaviorSubject } from 'rxjs'; -import { ModalBeforeDismiss } from '../../../interfaces/modal-before-dismiss.interface'; +import { ModalBeforeDismiss } from '../../../shared/interfaces/modal-before-dismiss.interface'; @Component({ selector: 'ds-item-versions-summary-modal', diff --git a/src/app/shared/item/item-versions/item-versions.component.html b/src/app/item-page/versions/item-versions.component.html similarity index 100% rename from src/app/shared/item/item-versions/item-versions.component.html rename to src/app/item-page/versions/item-versions.component.html diff --git a/src/app/shared/item/item-versions/item-versions.component.scss b/src/app/item-page/versions/item-versions.component.scss similarity index 100% rename from src/app/shared/item/item-versions/item-versions.component.scss rename to src/app/item-page/versions/item-versions.component.scss diff --git a/src/app/shared/item/item-versions/item-versions.component.spec.ts b/src/app/item-page/versions/item-versions.component.spec.ts similarity index 87% rename from src/app/shared/item/item-versions/item-versions.component.spec.ts rename to src/app/item-page/versions/item-versions.component.spec.ts index d4dbc336ab..999176d996 100644 --- a/src/app/shared/item/item-versions/item-versions.component.spec.ts +++ b/src/app/item-page/versions/item-versions.component.spec.ts @@ -2,33 +2,33 @@ import { ItemVersionsComponent } from './item-versions.component'; import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; -import { VarDirective } from '../../utils/var.directive'; +import { VarDirective } from '../../shared/utils/var.directive'; import { TranslateModule } from '@ngx-translate/core'; import { NO_ERRORS_SCHEMA } from '@angular/core'; -import { Item } from '../../../core/shared/item.model'; -import { Version } from '../../../core/shared/version.model'; -import { VersionHistory } from '../../../core/shared/version-history.model'; -import { VersionHistoryDataService } from '../../../core/data/version-history-data.service'; +import { Item } from '../../core/shared/item.model'; +import { Version } from '../../core/shared/version.model'; +import { VersionHistory } from '../../core/shared/version-history.model'; +import { VersionHistoryDataService } from '../../core/data/version-history-data.service'; import { BrowserModule, By } from '@angular/platform-browser'; -import { createSuccessfulRemoteDataObject$ } from '../../remote-data.utils'; -import { createPaginatedList } from '../../testing/utils.test'; +import { createSuccessfulRemoteDataObject$ } from '../../shared/remote-data.utils'; +import { createPaginatedList } from '../../shared/testing/utils.test'; import { EMPTY, of, of as observableOf } from 'rxjs'; -import { PaginationService } from '../../../core/pagination/pagination.service'; -import { PaginationServiceStub } from '../../testing/pagination-service.stub'; -import { AuthService } from '../../../core/auth/auth.service'; -import { VersionDataService } from '../../../core/data/version-data.service'; -import { ItemDataService } from '../../../core/data/item-data.service'; +import { PaginationService } from '../../core/pagination/pagination.service'; +import { PaginationServiceStub } from '../../shared/testing/pagination-service.stub'; +import { AuthService } from '../../core/auth/auth.service'; +import { VersionDataService } from '../../core/data/version-data.service'; +import { ItemDataService } from '../../core/data/item-data.service'; import { FormBuilder, FormsModule, ReactiveFormsModule } from '@angular/forms'; -import { NotificationsService } from '../../notifications/notifications.service'; -import { NotificationsServiceStub } from '../../testing/notifications-service.stub'; -import { AuthorizationDataService } from '../../../core/data/feature-authorization/authorization-data.service'; -import { FeatureID } from '../../../core/data/feature-authorization/feature-id'; -import { WorkspaceitemDataService } from '../../../core/submission/workspaceitem-data.service'; -import { WorkflowItemDataService } from '../../../core/submission/workflowitem-data.service'; -import { ConfigurationDataService } from '../../../core/data/configuration-data.service'; +import { NotificationsService } from '../../shared/notifications/notifications.service'; +import { NotificationsServiceStub } from '../../shared/testing/notifications-service.stub'; +import { AuthorizationDataService } from '../../core/data/feature-authorization/authorization-data.service'; +import { FeatureID } from '../../core/data/feature-authorization/feature-id'; +import { WorkspaceitemDataService } from '../../core/submission/workspaceitem-data.service'; +import { WorkflowItemDataService } from '../../core/submission/workflowitem-data.service'; +import { ConfigurationDataService } from '../../core/data/configuration-data.service'; import { Router } from '@angular/router'; -import { NgbModule } from '@ng-bootstrap/ng-bootstrap'; import { CommonModule } from '@angular/common'; +import { ItemSharedModule } from '../item-shared.module'; describe('ItemVersionsComponent', () => { let component: ItemVersionsComponent; @@ -137,7 +137,7 @@ describe('ItemVersionsComponent', () => { TestBed.configureTestingModule({ declarations: [ItemVersionsComponent, VarDirective], - imports: [TranslateModule.forRoot(), CommonModule, NgbModule, FormsModule, ReactiveFormsModule, BrowserModule], + imports: [TranslateModule.forRoot(), CommonModule, FormsModule, ReactiveFormsModule, BrowserModule, ItemSharedModule], providers: [ {provide: PaginationService, useValue: new PaginationServiceStub()}, {provide: FormBuilder, useValue: new FormBuilder()}, diff --git a/src/app/shared/item/item-versions/item-versions.component.ts b/src/app/item-page/versions/item-versions.component.ts similarity index 91% rename from src/app/shared/item/item-versions/item-versions.component.ts rename to src/app/item-page/versions/item-versions.component.ts index b7b8182658..e0fc623f49 100644 --- a/src/app/shared/item/item-versions/item-versions.component.ts +++ b/src/app/item-page/versions/item-versions.component.ts @@ -1,7 +1,7 @@ import { Component, Input, OnInit } from '@angular/core'; -import { Item } from '../../../core/shared/item.model'; -import { Version } from '../../../core/shared/version.model'; -import { RemoteData } from '../../../core/data/remote-data'; +import { Item } from '../../core/shared/item.model'; +import { Version } from '../../core/shared/version.model'; +import { RemoteData } from '../../core/data/remote-data'; import { BehaviorSubject, combineLatest, @@ -9,7 +9,7 @@ import { of, Subscription, } from 'rxjs'; -import { VersionHistory } from '../../../core/shared/version-history.model'; +import { VersionHistory } from '../../core/shared/version-history.model'; import { getAllSucceededRemoteData, getAllSucceededRemoteDataPayload, @@ -17,37 +17,37 @@ import { getFirstSucceededRemoteData, getFirstSucceededRemoteDataPayload, getRemoteDataPayload -} from '../../../core/shared/operators'; +} from '../../core/shared/operators'; import { map, mergeMap, startWith, switchMap, take, tap } from 'rxjs/operators'; -import { PaginatedList } from '../../../core/data/paginated-list.model'; -import { PaginationComponentOptions } from '../../pagination/pagination-component-options.model'; -import { VersionHistoryDataService } from '../../../core/data/version-history-data.service'; -import { PaginatedSearchOptions } from '../../search/models/paginated-search-options.model'; -import { AlertType } from '../../alert/aletr-type'; -import { followLink } from '../../utils/follow-link-config.model'; -import { hasValue, hasValueOperator } from '../../empty.util'; -import { PaginationService } from '../../../core/pagination/pagination.service'; +import { PaginatedList } from '../../core/data/paginated-list.model'; +import { PaginationComponentOptions } from '../../shared/pagination/pagination-component-options.model'; +import { VersionHistoryDataService } from '../../core/data/version-history-data.service'; +import { PaginatedSearchOptions } from '../../shared/search/models/paginated-search-options.model'; +import { AlertType } from '../../shared/alert/aletr-type'; +import { followLink } from '../../shared/utils/follow-link-config.model'; +import { hasValue, hasValueOperator } from '../../shared/empty.util'; +import { PaginationService } from '../../core/pagination/pagination.service'; import { getItemEditVersionhistoryRoute, getItemPageRoute, getItemVersionRoute -} from '../../../item-page/item-page-routing-paths'; +} from '../item-page-routing-paths'; import { FormBuilder } from '@angular/forms'; import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; import { ItemVersionsSummaryModalComponent } from './item-versions-summary-modal/item-versions-summary-modal.component'; -import { NotificationsService } from '../../notifications/notifications.service'; +import { NotificationsService } from '../../shared/notifications/notifications.service'; import { TranslateService } from '@ngx-translate/core'; import { ItemVersionsDeleteModalComponent } from './item-versions-delete-modal/item-versions-delete-modal.component'; -import { VersionDataService } from '../../../core/data/version-data.service'; -import { ItemDataService } from '../../../core/data/item-data.service'; +import { VersionDataService } from '../../core/data/version-data.service'; +import { ItemDataService } from '../../core/data/item-data.service'; import { Router } from '@angular/router'; -import { AuthorizationDataService } from '../../../core/data/feature-authorization/authorization-data.service'; -import { FeatureID } from '../../../core/data/feature-authorization/feature-id'; +import { AuthorizationDataService } from '../../core/data/feature-authorization/authorization-data.service'; +import { FeatureID } from '../../core/data/feature-authorization/feature-id'; import { ItemVersionsSharedService } from './item-versions-shared.service'; -import { WorkspaceItem } from '../../../core/submission/models/workspaceitem.model'; -import { WorkspaceitemDataService } from '../../../core/submission/workspaceitem-data.service'; -import { WorkflowItemDataService } from '../../../core/submission/workflowitem-data.service'; -import { ConfigurationDataService } from '../../../core/data/configuration-data.service'; +import { WorkspaceItem } from '../../core/submission/models/workspaceitem.model'; +import { WorkspaceitemDataService } from '../../core/submission/workspaceitem-data.service'; +import { WorkflowItemDataService } from '../../core/submission/workflowitem-data.service'; +import { ConfigurationDataService } from '../../core/data/configuration-data.service'; @Component({ selector: 'ds-item-versions', diff --git a/src/app/item-page/versions/item-versions.module.ts b/src/app/item-page/versions/item-versions.module.ts new file mode 100644 index 0000000000..577844488d --- /dev/null +++ b/src/app/item-page/versions/item-versions.module.ts @@ -0,0 +1,32 @@ +/** + * The contents of this file are subject to the license and copyright + * detailed in the LICENSE and NOTICE files at the root of the source + * tree and available online at + * + * http://www.dspace.org/license/ + */ + +import { NgModule } from '@angular/core'; +import { SharedModule } from '../../shared/shared.module'; +import { ItemVersionsComponent } from './item-versions.component'; +import { ItemVersionsNoticeComponent } from './notice/item-versions-notice.component'; + +const DECLARATIONS = [ + ItemVersionsComponent, + ItemVersionsNoticeComponent, +]; + +@NgModule({ + imports: [ + SharedModule, + ], + declarations: [ + ...DECLARATIONS, + ], + exports: [ + ...DECLARATIONS, + ], +}) +export class ItemVersionsModule { + +} diff --git a/src/app/shared/item/item-versions/notice/item-versions-notice.component.html b/src/app/item-page/versions/notice/item-versions-notice.component.html similarity index 100% rename from src/app/shared/item/item-versions/notice/item-versions-notice.component.html rename to src/app/item-page/versions/notice/item-versions-notice.component.html diff --git a/src/app/shared/item/item-versions/notice/item-versions-notice.component.spec.ts b/src/app/item-page/versions/notice/item-versions-notice.component.spec.ts similarity index 90% rename from src/app/shared/item/item-versions/notice/item-versions-notice.component.spec.ts rename to src/app/item-page/versions/notice/item-versions-notice.component.spec.ts index 2849ba4909..fb29e54a21 100644 --- a/src/app/shared/item/item-versions/notice/item-versions-notice.component.spec.ts +++ b/src/app/item-page/versions/notice/item-versions-notice.component.spec.ts @@ -3,13 +3,13 @@ import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; import { TranslateModule } from '@ngx-translate/core'; import { RouterTestingModule } from '@angular/router/testing'; import { NO_ERRORS_SCHEMA } from '@angular/core'; -import { VersionHistory } from '../../../../core/shared/version-history.model'; -import { Version } from '../../../../core/shared/version.model'; -import { Item } from '../../../../core/shared/item.model'; -import { VersionHistoryDataService } from '../../../../core/data/version-history-data.service'; +import { VersionHistory } from '../../../core/shared/version-history.model'; +import { Version } from '../../../core/shared/version.model'; +import { Item } from '../../../core/shared/item.model'; +import { VersionHistoryDataService } from '../../../core/data/version-history-data.service'; import { By } from '@angular/platform-browser'; -import { createSuccessfulRemoteDataObject$ } from '../../../remote-data.utils'; -import { createPaginatedList } from '../../../testing/utils.test'; +import { createSuccessfulRemoteDataObject$ } from '../../../shared/remote-data.utils'; +import { createPaginatedList } from '../../../shared/testing/utils.test'; import { of } from 'rxjs'; import { take } from 'rxjs/operators'; diff --git a/src/app/shared/item/item-versions/notice/item-versions-notice.component.ts b/src/app/item-page/versions/notice/item-versions-notice.component.ts similarity index 81% rename from src/app/shared/item/item-versions/notice/item-versions-notice.component.ts rename to src/app/item-page/versions/notice/item-versions-notice.component.ts index a292ea65c6..8a8f5ff76f 100644 --- a/src/app/shared/item/item-versions/notice/item-versions-notice.component.ts +++ b/src/app/item-page/versions/notice/item-versions-notice.component.ts @@ -1,19 +1,19 @@ import { Component, Input, OnInit } from '@angular/core'; -import { Item } from '../../../../core/shared/item.model'; +import { Item } from '../../../core/shared/item.model'; import { Observable } from 'rxjs'; -import { RemoteData } from '../../../../core/data/remote-data'; -import { VersionHistory } from '../../../../core/shared/version-history.model'; -import { Version } from '../../../../core/shared/version.model'; -import { hasValue, hasValueOperator } from '../../../empty.util'; +import { RemoteData } from '../../../core/data/remote-data'; +import { VersionHistory } from '../../../core/shared/version-history.model'; +import { Version } from '../../../core/shared/version.model'; +import { hasValue, hasValueOperator } from '../../../shared/empty.util'; import { getAllSucceededRemoteData, getFirstSucceededRemoteDataPayload, getRemoteDataPayload -} from '../../../../core/shared/operators'; +} from '../../../core/shared/operators'; import { map, startWith, switchMap } from 'rxjs/operators'; -import { VersionHistoryDataService } from '../../../../core/data/version-history-data.service'; -import { AlertType } from '../../../alert/aletr-type'; -import { getItemPageRoute } from '../../../../item-page/item-page-routing-paths'; +import { VersionHistoryDataService } from '../../../core/data/version-history-data.service'; +import { AlertType } from '../../../shared/alert/aletr-type'; +import { getItemPageRoute } from '../../item-page-routing-paths'; @Component({ selector: 'ds-item-versions-notice', diff --git a/src/app/item-page/field-components/metadata-field-wrapper/metadata-field-wrapper.component.html b/src/app/shared/metadata-field-wrapper/metadata-field-wrapper.component.html similarity index 100% rename from src/app/item-page/field-components/metadata-field-wrapper/metadata-field-wrapper.component.html rename to src/app/shared/metadata-field-wrapper/metadata-field-wrapper.component.html diff --git a/src/app/item-page/field-components/metadata-field-wrapper/metadata-field-wrapper.component.scss b/src/app/shared/metadata-field-wrapper/metadata-field-wrapper.component.scss similarity index 100% rename from src/app/item-page/field-components/metadata-field-wrapper/metadata-field-wrapper.component.scss rename to src/app/shared/metadata-field-wrapper/metadata-field-wrapper.component.scss diff --git a/src/app/item-page/field-components/metadata-field-wrapper/metadata-field-wrapper.component.spec.ts b/src/app/shared/metadata-field-wrapper/metadata-field-wrapper.component.spec.ts similarity index 100% rename from src/app/item-page/field-components/metadata-field-wrapper/metadata-field-wrapper.component.spec.ts rename to src/app/shared/metadata-field-wrapper/metadata-field-wrapper.component.spec.ts diff --git a/src/app/item-page/field-components/metadata-field-wrapper/metadata-field-wrapper.component.ts b/src/app/shared/metadata-field-wrapper/metadata-field-wrapper.component.ts similarity index 100% rename from src/app/item-page/field-components/metadata-field-wrapper/metadata-field-wrapper.component.ts rename to src/app/shared/metadata-field-wrapper/metadata-field-wrapper.component.ts diff --git a/src/app/shared/shared.module.ts b/src/app/shared/shared.module.ts index 5e3742e5b9..d50cfd95bf 100644 --- a/src/app/shared/shared.module.ts +++ b/src/app/shared/shared.module.ts @@ -225,17 +225,14 @@ import { import { ImportableListItemControlComponent } from './object-collection/shared/importable-list-item-control/importable-list-item-control.component'; -import { ItemVersionsComponent } from './item/item-versions/item-versions.component'; import { LogInContainerComponent } from './log-in/container/log-in-container.component'; import { LogInShibbolethComponent } from './log-in/methods/shibboleth/log-in-shibboleth.component'; import { LogInPasswordComponent } from './log-in/methods/password/log-in-password.component'; import { LogInComponent } from './log-in/log-in.component'; import { BundleListElementComponent } from './object-list/bundle-list-element/bundle-list-element.component'; import { MissingTranslationHelper } from './translate/missing-translation.helper'; -import { ItemVersionsNoticeComponent } from './item/item-versions/notice/item-versions-notice.component'; import { FileValidator } from './utils/require-file.validator'; import { FileValueAccessorDirective } from './utils/file-value-accessor.directive'; -import { FileSectionComponent } from '../item-page/simple/field-components/file-section/file-section.component'; import { ModifyItemOverviewComponent } from '../item-page/edit-item-page/modify-item-overview/modify-item-overview.component'; @@ -268,44 +265,23 @@ import { AuthorizedCollectionSelectorComponent } from './dso-selector/dso-selector/authorized-collection-selector/authorized-collection-selector.component'; import { DsoPageEditButtonComponent } from './dso-page/dso-page-edit-button/dso-page-edit-button.component'; -import { DsoPageVersionButtonComponent } from './dso-page/dso-page-version-button/dso-page-version-button.component'; import { HoverClassDirective } from './hover-class.directive'; import { ValidationSuggestionsComponent } from './input-suggestions/validation-suggestions/validation-suggestions.component'; -import { ItemAlertsComponent } from './item/item-alerts/item-alerts.component'; import { ItemSearchResultGridElementComponent } from './object-grid/search-result-grid-element/item-search-result/item/item-search-result-grid-element.component'; -import { BitstreamDownloadPageComponent } from './bitstream-download-page/bitstream-download-page.component'; -import { - GenericItemPageFieldComponent -} from '../item-page/simple/field-components/specific-field/generic/generic-item-page-field.component'; -import { - MetadataRepresentationListComponent -} from '../item-page/simple/metadata-representation-list/metadata-representation-list.component'; -import { RelatedItemsComponent } from '../item-page/simple/related-items/related-items-component'; import { SearchNavbarComponent } from '../search-navbar/search-navbar.component'; import { ThemedSearchNavbarComponent } from '../search-navbar/themed-search-navbar.component'; -import { - ItemVersionsSummaryModalComponent -} from './item/item-versions/item-versions-summary-modal/item-versions-summary-modal.component'; -import { - ItemVersionsDeleteModalComponent -} from './item/item-versions/item-versions-delete-modal/item-versions-delete-modal.component'; import { ScopeSelectorModalComponent } from './search-form/scope-selector-modal/scope-selector-modal.component'; -import { - BitstreamRequestACopyPageComponent -} from './bitstream-request-a-copy-page/bitstream-request-a-copy-page.component'; import { DsSelectComponent } from './ds-select/ds-select.component'; import { LogInOidcComponent } from './log-in/methods/oidc/log-in-oidc.component'; import { ThemedItemListPreviewComponent } from './object-list/my-dspace-result-list-element/item-list-preview/themed-item-list-preview.component'; import { RSSComponent } from './rss-feed/rss.component'; -import { DsoPageOrcidButtonComponent } from './dso-page/dso-page-orcid-button/dso-page-orcid-button.component'; import { LogInOrcidComponent } from './log-in/methods/orcid/log-in-orcid.component'; import { BrowserOnlyPipe } from './utils/browser-only.pipe'; import { ThemedLoadingComponent } from './loading/themed-loading.component'; -import { PersonPageClaimButtonComponent } from './dso-page/person-page-claim-button/person-page-claim-button.component'; import { SearchExportCsvComponent } from './search/search-export-csv/search-export-csv.component'; import { ItemPageTitleFieldComponent @@ -367,7 +343,6 @@ const COMPONENTS = [ UserMenuComponent, DsSelectComponent, ErrorComponent, - FileSectionComponent, LangSwitchComponent, LoadingComponent, ThemedLoadingComponent, @@ -421,8 +396,6 @@ const COMPONENTS = [ SelectableListItemControlComponent, ImportableListItemControlComponent, LogInContainerComponent, - ItemVersionsComponent, - ItemVersionsNoticeComponent, ModifyItemOverviewComponent, ImpersonateNavbarComponent, EntityDropdownComponent, @@ -434,6 +407,8 @@ const COMPONENTS = [ SearchNavbarComponent, ItemPageTitleFieldComponent, ThemedSearchNavbarComponent, + DsoPageEditButtonComponent, + MetadataFieldWrapperComponent, ]; const ENTRY_COMPONENTS = [ @@ -484,7 +459,6 @@ const ENTRY_COMPONENTS = [ CollectionDropdownComponent, FileDownloadLinkComponent, BitstreamDownloadPageComponent, - BitstreamRequestACopyPageComponent, CurationFormComponent, ExportMetadataSelectorComponent, ImportBatchSelectorComponent, @@ -497,20 +471,6 @@ const ENTRY_COMPONENTS = [ ScopeSelectorModalComponent, ]; -const SHARED_ITEM_PAGE_COMPONENTS = [ - MetadataFieldWrapperComponent, - MetadataValuesComponent, - DsoPageEditButtonComponent, - DsoPageVersionButtonComponent, - PersonPageClaimButtonComponent, - ItemAlertsComponent, - GenericItemPageFieldComponent, - MetadataRepresentationListComponent, - RelatedItemsComponent, - DsoPageOrcidButtonComponent - -]; - const PROVIDERS = [ TruncatableService, MockAdminGuard, @@ -546,9 +506,6 @@ const DIRECTIVES = [ ...COMPONENTS, ...ENTRY_COMPONENTS, ...DIRECTIVES, - ...SHARED_ITEM_PAGE_COMPONENTS, - ItemVersionsSummaryModalComponent, - ItemVersionsDeleteModalComponent, ], providers: [ ...PROVIDERS @@ -558,7 +515,6 @@ const DIRECTIVES = [ ...PIPES, ...COMPONENTS, ...ENTRY_COMPONENTS, - ...SHARED_ITEM_PAGE_COMPONENTS, ...DIRECTIVES, TranslateModule, ] diff --git a/src/themes/custom/lazy-theme.module.ts b/src/themes/custom/lazy-theme.module.ts index d2ac0ae787..202f2c9635 100644 --- a/src/themes/custom/lazy-theme.module.ts +++ b/src/themes/custom/lazy-theme.module.ts @@ -114,6 +114,8 @@ import { ObjectListComponent } from './app/shared/object-list/object-list.compon import { BrowseByMetadataPageComponent } from './app/browse-by/browse-by-metadata-page/browse-by-metadata-page.component'; import { BrowseByDatePageComponent } from './app/browse-by/browse-by-date-page/browse-by-date-page.component'; import { BrowseByTitlePageComponent } from './app/browse-by/browse-by-title-page/browse-by-title-page.component'; +import { ItemVersionsModule } from '../../app/item-page/versions/item-versions.module'; +import { ItemSharedModule } from '../../app/item-page/item-shared.module'; const DECLARATIONS = [ FileSectionComponent, @@ -189,8 +191,10 @@ const DECLARATIONS = [ CommunityPageModule, CoreModule, DragDropModule, + ItemSharedModule, ItemPageModule, EditItemPageModule, + ItemVersionsModule, FormsModule, HomePageModule, HttpClientModule, diff --git a/src/themes/dspace/lazy-theme.module.ts b/src/themes/dspace/lazy-theme.module.ts index a4e8027a15..6ece4d9755 100644 --- a/src/themes/dspace/lazy-theme.module.ts +++ b/src/themes/dspace/lazy-theme.module.ts @@ -55,6 +55,8 @@ import { } from '../../app/shared/resource-policies/resource-policies.module'; import { ComcolModule } from '../../app/shared/comcol/comcol.module'; import { RootModule } from '../../app/root.module'; +import { ItemVersionsModule } from '../../app/item-page/versions/item-versions.module'; +import { ItemSharedModule } from 'src/app/item-page/item-shared.module'; const DECLARATIONS = [ ]; @@ -76,8 +78,10 @@ const DECLARATIONS = [ CommunityPageModule, CoreModule, DragDropModule, + ItemSharedModule, ItemPageModule, EditItemPageModule, + ItemVersionsModule, FormsModule, HomePageModule, HttpClientModule, From 935e9a4690ce0ecd54535adeb447503c0b76c9e6 Mon Sep 17 00:00:00 2001 From: Yury Bondarenko Date: Tue, 3 Jan 2023 17:03:32 +0100 Subject: [PATCH 38/59] 96252: Move Bitstream page components out of SharedModule --- .../bitstream-download-page.component.html | 0 .../bitstream-download-page.component.spec.ts | 2 +- .../bitstream-download-page.component.ts | 2 +- src/app/bitstream-page/bitstream-page-routing.module.ts | 2 +- src/app/bitstream-page/bitstream-page.module.ts | 4 +++- src/app/shared/shared.module.ts | 1 - 6 files changed, 6 insertions(+), 5 deletions(-) rename src/app/{shared => bitstream-page}/bitstream-download-page/bitstream-download-page.component.html (100%) rename src/app/{shared => bitstream-page}/bitstream-download-page/bitstream-download-page.component.spec.ts (98%) rename src/app/{shared => bitstream-page}/bitstream-download-page/bitstream-download-page.component.ts (98%) diff --git a/src/app/shared/bitstream-download-page/bitstream-download-page.component.html b/src/app/bitstream-page/bitstream-download-page/bitstream-download-page.component.html similarity index 100% rename from src/app/shared/bitstream-download-page/bitstream-download-page.component.html rename to src/app/bitstream-page/bitstream-download-page/bitstream-download-page.component.html diff --git a/src/app/shared/bitstream-download-page/bitstream-download-page.component.spec.ts b/src/app/bitstream-page/bitstream-download-page/bitstream-download-page.component.spec.ts similarity index 98% rename from src/app/shared/bitstream-download-page/bitstream-download-page.component.spec.ts rename to src/app/bitstream-page/bitstream-download-page/bitstream-download-page.component.spec.ts index 4100653e0f..e84b254eae 100644 --- a/src/app/shared/bitstream-download-page/bitstream-download-page.component.spec.ts +++ b/src/app/bitstream-page/bitstream-download-page/bitstream-download-page.component.spec.ts @@ -6,7 +6,7 @@ import { Bitstream } from '../../core/shared/bitstream.model'; import { BitstreamDownloadPageComponent } from './bitstream-download-page.component'; import { AuthorizationDataService } from '../../core/data/feature-authorization/authorization-data.service'; import { HardRedirectService } from '../../core/services/hard-redirect.service'; -import { createSuccessfulRemoteDataObject } from '../remote-data.utils'; +import { createSuccessfulRemoteDataObject } from '../../shared/remote-data.utils'; import { ActivatedRoute, Router } from '@angular/router'; import { getForbiddenRoute } from '../../app-routing-paths'; import { TranslateModule } from '@ngx-translate/core'; diff --git a/src/app/shared/bitstream-download-page/bitstream-download-page.component.ts b/src/app/bitstream-page/bitstream-download-page/bitstream-download-page.component.ts similarity index 98% rename from src/app/shared/bitstream-download-page/bitstream-download-page.component.ts rename to src/app/bitstream-page/bitstream-download-page/bitstream-download-page.component.ts index 9dd8c7c723..51ec762ec3 100644 --- a/src/app/shared/bitstream-download-page/bitstream-download-page.component.ts +++ b/src/app/bitstream-page/bitstream-download-page/bitstream-download-page.component.ts @@ -1,7 +1,7 @@ import { Component, OnInit } from '@angular/core'; import { filter, map, switchMap, take } from 'rxjs/operators'; import { ActivatedRoute, Router } from '@angular/router'; -import { hasValue, isNotEmpty } from '../empty.util'; +import { hasValue, isNotEmpty } from '../../shared/empty.util'; import { getRemoteDataPayload} from '../../core/shared/operators'; import { Bitstream } from '../../core/shared/bitstream.model'; import { AuthorizationDataService } from '../../core/data/feature-authorization/authorization-data.service'; diff --git a/src/app/bitstream-page/bitstream-page-routing.module.ts b/src/app/bitstream-page/bitstream-page-routing.module.ts index 0bdda29ddf..c2abe511a4 100644 --- a/src/app/bitstream-page/bitstream-page-routing.module.ts +++ b/src/app/bitstream-page/bitstream-page-routing.module.ts @@ -3,7 +3,7 @@ import { RouterModule } from '@angular/router'; import { EditBitstreamPageComponent } from './edit-bitstream-page/edit-bitstream-page.component'; import { AuthenticatedGuard } from '../core/auth/authenticated.guard'; import { BitstreamPageResolver } from './bitstream-page.resolver'; -import { BitstreamDownloadPageComponent } from '../shared/bitstream-download-page/bitstream-download-page.component'; +import { BitstreamDownloadPageComponent } from './bitstream-download-page/bitstream-download-page.component'; import { ResourcePolicyTargetResolver } from '../shared/resource-policies/resolvers/resource-policy-target.resolver'; import { ResourcePolicyCreateComponent } from '../shared/resource-policies/create/resource-policy-create.component'; import { ResourcePolicyResolver } from '../shared/resource-policies/resolvers/resource-policy.resolver'; diff --git a/src/app/bitstream-page/bitstream-page.module.ts b/src/app/bitstream-page/bitstream-page.module.ts index d168a06db2..992f714bf9 100644 --- a/src/app/bitstream-page/bitstream-page.module.ts +++ b/src/app/bitstream-page/bitstream-page.module.ts @@ -6,6 +6,7 @@ import { BitstreamPageRoutingModule } from './bitstream-page-routing.module'; import { BitstreamAuthorizationsComponent } from './bitstream-authorizations/bitstream-authorizations.component'; import { FormModule } from '../shared/form/form.module'; import { ResourcePoliciesModule } from '../shared/resource-policies/resource-policies.module'; +import { BitstreamDownloadPageComponent } from './bitstream-download-page/bitstream-download-page.component'; /** * This module handles all components that are necessary for Bitstream related pages @@ -20,7 +21,8 @@ import { ResourcePoliciesModule } from '../shared/resource-policies/resource-pol ], declarations: [ BitstreamAuthorizationsComponent, - EditBitstreamPageComponent + EditBitstreamPageComponent, + BitstreamDownloadPageComponent, ] }) export class BitstreamPageModule { diff --git a/src/app/shared/shared.module.ts b/src/app/shared/shared.module.ts index d50cfd95bf..2e078914e2 100644 --- a/src/app/shared/shared.module.ts +++ b/src/app/shared/shared.module.ts @@ -458,7 +458,6 @@ const ENTRY_COMPONENTS = [ ClaimedTaskActionsEditMetadataComponent, CollectionDropdownComponent, FileDownloadLinkComponent, - BitstreamDownloadPageComponent, CurationFormComponent, ExportMetadataSelectorComponent, ImportBatchSelectorComponent, From 1c7108e9286edf3ef54157454a99dca4123ebb79 Mon Sep 17 00:00:00 2001 From: Yury Bondarenko Date: Tue, 3 Jan 2023 17:03:42 +0100 Subject: [PATCH 39/59] 96252: Move MyDSpace components out of SharedModule Also move ds-metadata-field-wrapper to SharedModule so it can be reused in detail view without importing ItemSharedModule --- .../my-dspace-page/my-dspace-search.module.ts | 27 +++++++-- .../mydspace-actions.module.ts | 59 +++++++++++++++++++ src/app/shared/shared.module.ts | 56 +----------------- 3 files changed, 83 insertions(+), 59 deletions(-) create mode 100644 src/app/shared/mydspace-actions/mydspace-actions.module.ts diff --git a/src/app/my-dspace-page/my-dspace-search.module.ts b/src/app/my-dspace-page/my-dspace-search.module.ts index a0fa76fafa..1ce39991b3 100644 --- a/src/app/my-dspace-page/my-dspace-search.module.ts +++ b/src/app/my-dspace-page/my-dspace-search.module.ts @@ -17,9 +17,16 @@ import { PoolSearchResultDetailElementComponent } from '../shared/object-detail/ import { ClaimedApprovedSearchResultListElementComponent } from '../shared/object-list/my-dspace-result-list-element/claimed-search-result/claimed-approved-search-result/claimed-approved-search-result-list-element.component'; import { ClaimedDeclinedSearchResultListElementComponent } from '../shared/object-list/my-dspace-result-list-element/claimed-search-result/claimed-declined-search-result/claimed-declined-search-result-list-element.component'; import { ResearchEntitiesModule } from '../entity-groups/research-entities/research-entities.module'; +import { ItemSubmitterComponent } from '../shared/object-collection/shared/mydspace-item-submitter/item-submitter.component'; +import { ItemDetailPreviewComponent } from '../shared/object-detail/my-dspace-result-detail-element/item-detail-preview/item-detail-preview.component'; +import { ItemDetailPreviewFieldComponent } from '../shared/object-detail/my-dspace-result-detail-element/item-detail-preview/item-detail-preview-field/item-detail-preview-field.component'; +import { ItemListPreviewComponent } from '../shared/object-list/my-dspace-result-list-element/item-list-preview/item-list-preview.component'; +import { ThemedItemListPreviewComponent } from '../shared/object-list/my-dspace-result-list-element/item-list-preview/themed-item-list-preview.component'; +import { MyDSpaceItemStatusComponent } from '../shared/object-collection/shared/mydspace-item-status/my-dspace-item-status.component'; +import { JournalEntitiesModule } from '../entity-groups/journal-entities/journal-entities.module'; +import { MyDSpaceActionsModule } from '../shared/mydspace-actions/mydspace-actions.module'; const ENTRY_COMPONENTS = [ - // put only entry components that use custom decorator WorkspaceItemSearchResultListElementComponent, WorkflowItemSearchResultListElementComponent, ClaimedSearchResultListElementComponent, @@ -31,7 +38,17 @@ const ENTRY_COMPONENTS = [ WorkflowItemSearchResultDetailElementComponent, ClaimedTaskSearchResultDetailElementComponent, PoolSearchResultDetailElementComponent, - ItemSearchResultListElementSubmissionComponent + ItemSearchResultListElementSubmissionComponent, +]; + +const DECLARATIONS = [ + ...ENTRY_COMPONENTS, + ItemSubmitterComponent, + ItemDetailPreviewComponent, + ItemDetailPreviewFieldComponent, + ItemListPreviewComponent, + ThemedItemListPreviewComponent, + MyDSpaceItemStatusComponent, ]; @NgModule({ @@ -39,10 +56,12 @@ const ENTRY_COMPONENTS = [ CommonModule, SharedModule, MyDspacePageRoutingModule, - ResearchEntitiesModule.withEntryComponents() + MyDSpaceActionsModule, + ResearchEntitiesModule.withEntryComponents(), + JournalEntitiesModule.withEntryComponents(), ], declarations: [ - ...ENTRY_COMPONENTS + ...DECLARATIONS, ] }) diff --git a/src/app/shared/mydspace-actions/mydspace-actions.module.ts b/src/app/shared/mydspace-actions/mydspace-actions.module.ts new file mode 100644 index 0000000000..68e3a8fb58 --- /dev/null +++ b/src/app/shared/mydspace-actions/mydspace-actions.module.ts @@ -0,0 +1,59 @@ +/** + * The contents of this file are subject to the license and copyright + * detailed in the LICENSE and NOTICE files at the root of the source + * tree and available online at + * + * http://www.dspace.org/license/ + */ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { SharedModule } from '../shared.module'; +import { ClaimedTaskActionsApproveComponent } from './claimed-task/approve/claimed-task-actions-approve.component'; +import { ClaimedTaskActionsRejectComponent } from './claimed-task/reject/claimed-task-actions-reject.component'; +import { ClaimedTaskActionsReturnToPoolComponent } from './claimed-task/return-to-pool/claimed-task-actions-return-to-pool.component'; +import { ClaimedTaskActionsEditMetadataComponent } from './claimed-task/edit-metadata/claimed-task-actions-edit-metadata.component'; +import { ClaimedTaskActionsComponent } from './claimed-task/claimed-task-actions.component'; +import { ClaimedTaskActionsLoaderComponent } from './claimed-task/switcher/claimed-task-actions-loader.component'; +import { ItemActionsComponent } from './item/item-actions.component'; +import { PoolTaskActionsComponent } from './pool-task/pool-task-actions.component'; +import { WorkflowitemActionsComponent } from './workflowitem/workflowitem-actions.component'; +import { WorkspaceitemActionsComponent } from './workspaceitem/workspaceitem-actions.component'; + +const ENTRY_COMPONENTS = [ + ClaimedTaskActionsApproveComponent, + ClaimedTaskActionsRejectComponent, + ClaimedTaskActionsReturnToPoolComponent, + ClaimedTaskActionsEditMetadataComponent, +]; + +const DECLARATIONS = [ + ...ENTRY_COMPONENTS, + ClaimedTaskActionsComponent, + ClaimedTaskActionsLoaderComponent, + ItemActionsComponent, + PoolTaskActionsComponent, + WorkflowitemActionsComponent, + WorkspaceitemActionsComponent, +]; + +/** + * This module contains Item actions used in MyDSpace + */ +@NgModule({ + imports: [ + CommonModule, + SharedModule, + ], + declarations: [ + ...DECLARATIONS, + ], + providers: [ + ...ENTRY_COMPONENTS, + ], + exports: [ + ...DECLARATIONS, + ], +}) +export class MyDSpaceActionsModule { + +} diff --git a/src/app/shared/shared.module.ts b/src/app/shared/shared.module.ts index 2e078914e2..fe72121341 100644 --- a/src/app/shared/shared.module.ts +++ b/src/app/shared/shared.module.ts @@ -76,25 +76,7 @@ import { AlertComponent } from './alert/alert.component'; import { SearchResultDetailElementComponent } from './object-detail/my-dspace-result-detail-element/search-result-detail-element.component'; -import { ClaimedTaskActionsComponent } from './mydspace-actions/claimed-task/claimed-task-actions.component'; -import { PoolTaskActionsComponent } from './mydspace-actions/pool-task/pool-task-actions.component'; import { ObjectDetailComponent } from './object-detail/object-detail.component'; -import { - ItemDetailPreviewComponent -} from './object-detail/my-dspace-result-detail-element/item-detail-preview/item-detail-preview.component'; -import { - MyDSpaceItemStatusComponent -} from './object-collection/shared/mydspace-item-status/my-dspace-item-status.component'; -import { WorkspaceitemActionsComponent } from './mydspace-actions/workspaceitem/workspaceitem-actions.component'; -import { WorkflowitemActionsComponent } from './mydspace-actions/workflowitem/workflowitem-actions.component'; -import { ItemSubmitterComponent } from './object-collection/shared/mydspace-item-submitter/item-submitter.component'; -import { ItemActionsComponent } from './mydspace-actions/item/item-actions.component'; -import { - ClaimedTaskActionsApproveComponent -} from './mydspace-actions/claimed-task/approve/claimed-task-actions-approve.component'; -import { - ClaimedTaskActionsRejectComponent -} from './mydspace-actions/claimed-task/reject/claimed-task-actions-reject.component'; import { ObjNgFor } from './utils/object-ngfor.pipe'; import { BrowseByComponent } from './browse-by/browse-by.component'; import { @@ -164,21 +146,8 @@ import { import { ThemedEditCollectionSelectorComponent } from './dso-selector/modal-wrappers/edit-collection-selector/themed-edit-collection-selector.component'; -import { - ItemListPreviewComponent -} from './object-list/my-dspace-result-list-element/item-list-preview/item-list-preview.component'; -import { - MetadataFieldWrapperComponent -} from '../item-page/field-components/metadata-field-wrapper/metadata-field-wrapper.component'; -import { MetadataValuesComponent } from '../item-page/field-components/metadata-values/metadata-values.component'; import { RoleDirective } from './roles/role.directive'; import { UserMenuComponent } from './auth-nav-menu/user-menu/user-menu.component'; -import { - ClaimedTaskActionsReturnToPoolComponent -} from './mydspace-actions/claimed-task/return-to-pool/claimed-task-actions-return-to-pool.component'; -import { - ItemDetailPreviewFieldComponent -} from './object-detail/my-dspace-result-detail-element/item-detail-preview/item-detail-preview-field/item-detail-preview-field.component'; import { CollectionSearchResultGridElementComponent } from './object-grid/search-result-grid-element/collection-search-result/collection-search-result-grid-element.component'; @@ -236,13 +205,7 @@ import { FileValueAccessorDirective } from './utils/file-value-accessor.directiv import { ModifyItemOverviewComponent } from '../item-page/edit-item-page/modify-item-overview/modify-item-overview.component'; -import { - ClaimedTaskActionsLoaderComponent -} from './mydspace-actions/claimed-task/switcher/claimed-task-actions-loader.component'; import { ClaimedTaskActionsDirective } from './mydspace-actions/claimed-task/switcher/claimed-task-actions.directive'; -import { - ClaimedTaskActionsEditMetadataComponent -} from './mydspace-actions/claimed-task/edit-metadata/claimed-task-actions-edit-metadata.component'; import { ImpersonateNavbarComponent } from './impersonate-navbar/impersonate-navbar.component'; import { NgForTrackByIdDirective } from './ng-for-track-by-id.directive'; import { FileDownloadLinkComponent } from './file-download-link/file-download-link.component'; @@ -277,7 +240,6 @@ import { ThemedSearchNavbarComponent } from '../search-navbar/themed-search-navb import { ScopeSelectorModalComponent } from './search-form/scope-selector-modal/scope-selector-modal.component'; import { DsSelectComponent } from './ds-select/ds-select.component'; import { LogInOidcComponent } from './log-in/methods/oidc/log-in-oidc.component'; -import { ThemedItemListPreviewComponent } from './object-list/my-dspace-result-list-element/item-list-preview/themed-item-list-preview.component'; import { RSSComponent } from './rss-feed/rss.component'; import { LogInOrcidComponent } from './log-in/methods/orcid/log-in-orcid.component'; import { BrowserOnlyPipe } from './utils/browser-only.pipe'; @@ -289,6 +251,7 @@ import { import { MarkdownPipe } from './utils/markdown.pipe'; import { GoogleRecaptchaModule } from '../core/google-recaptcha/google-recaptcha.module'; import { MenuModule } from './menu/menu.module'; +import { MetadataFieldWrapperComponent } from './metadata-field-wrapper/metadata-field-wrapper.component'; const MODULES = [ CommonModule, @@ -362,18 +325,6 @@ const COMPONENTS = [ SidebarFilterComponent, SidebarFilterSelectedOptionComponent, ThumbnailComponent, - ItemListPreviewComponent, - ThemedItemListPreviewComponent, - MyDSpaceItemStatusComponent, - ItemSubmitterComponent, - ItemDetailPreviewComponent, - ItemDetailPreviewFieldComponent, - ClaimedTaskActionsComponent, - ClaimedTaskActionsLoaderComponent, - ItemActionsComponent, - PoolTaskActionsComponent, - WorkflowitemActionsComponent, - WorkspaceitemActionsComponent, ViewModeSwitchComponent, TruncatableComponent, TruncatablePartComponent, @@ -451,11 +402,6 @@ const ENTRY_COMPONENTS = [ LogInShibbolethComponent, LogInOidcComponent, LogInOrcidComponent, - BundleListElementComponent, - ClaimedTaskActionsApproveComponent, - ClaimedTaskActionsRejectComponent, - ClaimedTaskActionsReturnToPoolComponent, - ClaimedTaskActionsEditMetadataComponent, CollectionDropdownComponent, FileDownloadLinkComponent, CurationFormComponent, From 67616a5d524883022b32545bfdc1ff830e8aecb2 Mon Sep 17 00:00:00 2001 From: Yury Bondarenko Date: Tue, 3 Jan 2023 17:03:46 +0100 Subject: [PATCH 40/59] 96252: Remove unused sidebar filter components --- src/app/app.reducer.ts | 6 - src/app/search-page/search-page.module.ts | 2 - src/app/shared/shared.module.ts | 4 - ...ebar-filter-selected-option.component.html | 6 - ...ebar-filter-selected-option.component.scss | 11 -- ...idebar-filter-selected-option.component.ts | 15 --- .../sidebar/filter/sidebar-filter.actions.ts | 73 ------------ .../filter/sidebar-filter.component.html | 26 ----- .../filter/sidebar-filter.component.scss | 12 -- .../filter/sidebar-filter.component.ts | 89 --------------- .../sidebar/filter/sidebar-filter.reducer.ts | 70 ------------ .../filter/sidebar-filter.service.spec.ts | 107 ------------------ .../sidebar/filter/sidebar-filter.service.ts | 90 --------------- 13 files changed, 511 deletions(-) delete mode 100644 src/app/shared/sidebar/filter/sidebar-filter-selected-option.component.html delete mode 100644 src/app/shared/sidebar/filter/sidebar-filter-selected-option.component.scss delete mode 100644 src/app/shared/sidebar/filter/sidebar-filter-selected-option.component.ts delete mode 100644 src/app/shared/sidebar/filter/sidebar-filter.actions.ts delete mode 100644 src/app/shared/sidebar/filter/sidebar-filter.component.html delete mode 100644 src/app/shared/sidebar/filter/sidebar-filter.component.scss delete mode 100644 src/app/shared/sidebar/filter/sidebar-filter.component.ts delete mode 100644 src/app/shared/sidebar/filter/sidebar-filter.reducer.ts delete mode 100644 src/app/shared/sidebar/filter/sidebar-filter.service.spec.ts delete mode 100644 src/app/shared/sidebar/filter/sidebar-filter.service.ts diff --git a/src/app/app.reducer.ts b/src/app/app.reducer.ts index 1d6e86463d..32438b46ab 100644 --- a/src/app/app.reducer.ts +++ b/src/app/app.reducer.ts @@ -42,10 +42,6 @@ import { filterReducer, SearchFiltersState } from './shared/search/search-filters/search-filter/search-filter.reducer'; -import { - sidebarFilterReducer, - SidebarFiltersState -} from './shared/sidebar/filter/sidebar-filter.reducer'; import { sidebarReducer, SidebarState } from './shared/sidebar/sidebar.reducer'; import { truncatableReducer, TruncatablesState } from './shared/truncatable/truncatable.reducer'; import { ThemeState, themeReducer } from './shared/theme-support/theme.reducer'; @@ -59,7 +55,6 @@ export interface AppState { metadataRegistry: MetadataRegistryState; notifications: NotificationsState; sidebar: SidebarState; - sidebarFilter: SidebarFiltersState; searchFilter: SearchFiltersState; truncatable: TruncatablesState; cssVariables: CSSVariablesState; @@ -81,7 +76,6 @@ export const appReducers: ActionReducerMap = { metadataRegistry: metadataRegistryReducer, notifications: notificationsReducer, sidebar: sidebarReducer, - sidebarFilter: sidebarFilterReducer, searchFilter: filterReducer, truncatable: truncatableReducer, cssVariables: cssVariablesReducer, diff --git a/src/app/search-page/search-page.module.ts b/src/app/search-page/search-page.module.ts index 758eca15c0..19fd9bd309 100644 --- a/src/app/search-page/search-page.module.ts +++ b/src/app/search-page/search-page.module.ts @@ -7,7 +7,6 @@ import { ConfigurationSearchPageGuard } from './configuration-search-page.guard' import { SearchTrackerComponent } from './search-tracker.component'; import { StatisticsModule } from '../statistics/statistics.module'; import { SearchPageComponent } from './search-page.component'; -import { SidebarFilterService } from '../shared/sidebar/filter/sidebar-filter.service'; import { SearchFilterService } from '../core/shared/search/search-filter.service'; import { SearchConfigurationService } from '../core/shared/search/search-configuration.service'; import { JournalEntitiesModule } from '../entity-groups/journal-entities/journal-entities.module'; @@ -34,7 +33,6 @@ const components = [ declarations: components, providers: [ SidebarService, - SidebarFilterService, SearchFilterService, ConfigurationSearchPageGuard, SearchConfigurationService diff --git a/src/app/shared/shared.module.ts b/src/app/shared/shared.module.ts index fe72121341..50c41c82e6 100644 --- a/src/app/shared/shared.module.ts +++ b/src/app/shared/shared.module.ts @@ -186,8 +186,6 @@ import { } from './object-list/metadata-representation-list-element/item/item-metadata-representation-list-element.component'; import { PageWithSidebarComponent } from './sidebar/page-with-sidebar.component'; import { SidebarDropdownComponent } from './sidebar/sidebar-dropdown.component'; -import { SidebarFilterComponent } from './sidebar/filter/sidebar-filter.component'; -import { SidebarFilterSelectedOptionComponent } from './sidebar/filter/sidebar-filter-selected-option.component'; import { SelectableListItemControlComponent } from './object-collection/shared/selectable-list-item-control/selectable-list-item-control.component'; @@ -322,8 +320,6 @@ const COMPONENTS = [ SearchFormComponent, PageWithSidebarComponent, SidebarDropdownComponent, - SidebarFilterComponent, - SidebarFilterSelectedOptionComponent, ThumbnailComponent, ViewModeSwitchComponent, TruncatableComponent, diff --git a/src/app/shared/sidebar/filter/sidebar-filter-selected-option.component.html b/src/app/shared/sidebar/filter/sidebar-filter-selected-option.component.html deleted file mode 100644 index bbe0b93566..0000000000 --- a/src/app/shared/sidebar/filter/sidebar-filter-selected-option.component.html +++ /dev/null @@ -1,6 +0,0 @@ - - - diff --git a/src/app/shared/sidebar/filter/sidebar-filter-selected-option.component.scss b/src/app/shared/sidebar/filter/sidebar-filter-selected-option.component.scss deleted file mode 100644 index 30ab8912d3..0000000000 --- a/src/app/shared/sidebar/filter/sidebar-filter-selected-option.component.scss +++ /dev/null @@ -1,11 +0,0 @@ -a { - color: var(--bs-body-color); - - &:hover, &focus { - text-decoration: none; - } - - span.badge { - vertical-align: text-top; - } -} diff --git a/src/app/shared/sidebar/filter/sidebar-filter-selected-option.component.ts b/src/app/shared/sidebar/filter/sidebar-filter-selected-option.component.ts deleted file mode 100644 index 4f1d2415ae..0000000000 --- a/src/app/shared/sidebar/filter/sidebar-filter-selected-option.component.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { Component, EventEmitter, Input, Output } from '@angular/core'; - -@Component({ - selector: 'ds-sidebar-filter-selected-option', - styleUrls: ['./sidebar-filter-selected-option.component.scss'], - templateUrl: './sidebar-filter-selected-option.component.html', -}) - -/** - * Represents a single selected option in a sidebar filter - */ -export class SidebarFilterSelectedOptionComponent { - @Input() label: string; - @Output() click: EventEmitter = new EventEmitter(); -} diff --git a/src/app/shared/sidebar/filter/sidebar-filter.actions.ts b/src/app/shared/sidebar/filter/sidebar-filter.actions.ts deleted file mode 100644 index 5dab677c5c..0000000000 --- a/src/app/shared/sidebar/filter/sidebar-filter.actions.ts +++ /dev/null @@ -1,73 +0,0 @@ -/* eslint-disable max-classes-per-file */ -import { Action } from '@ngrx/store'; - -import { type } from '../../ngrx/type'; - -/** - * For each action type in an action group, make a simple - * enum object for all of this group's action types. - * - * The 'type' utility function coerces strings into string - * literal types and runs a simple check to guarantee all - * action types in the application are unique. - */ -export const SidebarFilterActionTypes = { - INITIALIZE: type('dspace/sidebar-filter/INITIALIZE'), - COLLAPSE: type('dspace/sidebar-filter/COLLAPSE'), - EXPAND: type('dspace/sidebar-filter/EXPAND'), - TOGGLE: type('dspace/sidebar-filter/TOGGLE'), -}; - -export class SidebarFilterAction implements Action { - /** - * Name of the filter the action is performed on, used to identify the filter - */ - filterName: string; - - /** - * Type of action that will be performed - */ - type; - - /** - * Initialize with the filter's name - * @param {string} name of the filter - */ - constructor(name: string) { - this.filterName = name; - } -} - -/** - * Used to initialize a filter - */ -export class FilterInitializeAction extends SidebarFilterAction { - type = SidebarFilterActionTypes.INITIALIZE; - initiallyExpanded; - - constructor(name: string, initiallyExpanded: boolean) { - super(name); - this.initiallyExpanded = initiallyExpanded; - } -} - -/** - * Used to collapse a filter - */ -export class FilterCollapseAction extends SidebarFilterAction { - type = SidebarFilterActionTypes.COLLAPSE; -} - -/** - * Used to expand a filter - */ -export class FilterExpandAction extends SidebarFilterAction { - type = SidebarFilterActionTypes.EXPAND; -} - -/** - * Used to collapse a filter when it's expanded and expand it when it's collapsed - */ -export class FilterToggleAction extends SidebarFilterAction { - type = SidebarFilterActionTypes.TOGGLE; -} diff --git a/src/app/shared/sidebar/filter/sidebar-filter.component.html b/src/app/shared/sidebar/filter/sidebar-filter.component.html deleted file mode 100644 index 79afaa7583..0000000000 --- a/src/app/shared/sidebar/filter/sidebar-filter.component.html +++ /dev/null @@ -1,26 +0,0 @@ -
-
-
- {{ label | translate }} -
- - -
- -
diff --git a/src/app/shared/sidebar/filter/sidebar-filter.component.scss b/src/app/shared/sidebar/filter/sidebar-filter.component.scss deleted file mode 100644 index bf7a089cb1..0000000000 --- a/src/app/shared/sidebar/filter/sidebar-filter.component.scss +++ /dev/null @@ -1,12 +0,0 @@ -:host .facet-filter { - border: 1px solid var(--bs-light); - cursor: pointer; - - .sidebar-filter-wrapper.closed { - overflow: hidden; - } - - .filter-toggle { - line-height: var(--bs-line-height-base); - } -} diff --git a/src/app/shared/sidebar/filter/sidebar-filter.component.ts b/src/app/shared/sidebar/filter/sidebar-filter.component.ts deleted file mode 100644 index 5a019d41df..0000000000 --- a/src/app/shared/sidebar/filter/sidebar-filter.component.ts +++ /dev/null @@ -1,89 +0,0 @@ -import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; -import { Observable } from 'rxjs'; -import { SidebarFilterService } from './sidebar-filter.service'; -import { slide } from '../../animations/slide'; - -@Component({ - selector: 'ds-sidebar-filter', - styleUrls: ['./sidebar-filter.component.scss'], - templateUrl: './sidebar-filter.component.html', - animations: [slide], -}) -/** - * This components renders a sidebar filter including the label and the selected values. - * The filter input itself should still be provided in the content. - */ -export class SidebarFilterComponent implements OnInit { - - @Input() name: string; - @Input() type: string; - @Input() label: string; - @Input() expanded = true; - @Input() singleValue = false; - @Input() selectedValues: Observable; - @Output() removeValue: EventEmitter = new EventEmitter(); - - /** - * True when the filter is 100% collapsed in the UI - */ - closed = true; - - /** - * Emits true when the filter is currently collapsed in the store - */ - collapsed$: Observable; - - constructor( - protected filterService: SidebarFilterService, - ) { - } - - /** - * Changes the state for this filter to collapsed when it's expanded and to expanded it when it's collapsed - */ - toggle() { - this.filterService.toggle(this.name); - } - - /** - * Method to change this.collapsed to false when the slide animation ends and is sliding open - * @param event The animation event - */ - finishSlide(event: any): void { - if (event.fromState === 'collapsed') { - this.closed = false; - } - } - - /** - * Method to change this.collapsed to true when the slide animation starts and is sliding closed - * @param event The animation event - */ - startSlide(event: any): void { - if (event.toState === 'collapsed') { - this.closed = true; - } - } - - ngOnInit(): void { - this.closed = !this.expanded; - this.initializeFilter(); - this.collapsed$ = this.isCollapsed(); - } - - /** - * Sets the initial state of the filter - */ - initializeFilter() { - this.filterService.initializeFilter(this.name, this.expanded); - } - - /** - * Checks if the filter is currently collapsed - * @returns {Observable} Emits true when the current state of the filter is collapsed, false when it's expanded - */ - private isCollapsed(): Observable { - return this.filterService.isCollapsed(this.name); - } - -} diff --git a/src/app/shared/sidebar/filter/sidebar-filter.reducer.ts b/src/app/shared/sidebar/filter/sidebar-filter.reducer.ts deleted file mode 100644 index b7784dd12b..0000000000 --- a/src/app/shared/sidebar/filter/sidebar-filter.reducer.ts +++ /dev/null @@ -1,70 +0,0 @@ -import { - FilterInitializeAction, - SidebarFilterAction, - SidebarFilterActionTypes -} from './sidebar-filter.actions'; - -/** - * Interface that represents the state for a single filters - */ -export interface SidebarFilterState { - filterCollapsed: boolean; -} - -/** - * Interface that represents the state for all available filters - */ -export interface SidebarFiltersState { - [name: string]: SidebarFilterState; -} - -const initialState: SidebarFiltersState = Object.create(null); - -/** - * Performs a filter action on the current state - * @param {SidebarFiltersState} state The state before the action is performed - * @param {SidebarFilterAction} action The action that should be performed - * @returns {SidebarFiltersState} The state after the action is performed - */ -export function sidebarFilterReducer(state = initialState, action: SidebarFilterAction): SidebarFiltersState { - - switch (action.type) { - - case SidebarFilterActionTypes.INITIALIZE: { - const initAction = (action as FilterInitializeAction); - return Object.assign({}, state, { - [action.filterName]: { - filterCollapsed: !initAction.initiallyExpanded, - } - }); - } - - case SidebarFilterActionTypes.COLLAPSE: { - return Object.assign({}, state, { - [action.filterName]: { - filterCollapsed: true, - } - }); - } - - case SidebarFilterActionTypes.EXPAND: { - return Object.assign({}, state, { - [action.filterName]: { - filterCollapsed: false, - } - }); - } - - case SidebarFilterActionTypes.TOGGLE: { - return Object.assign({}, state, { - [action.filterName]: { - filterCollapsed: !state[action.filterName].filterCollapsed, - } - }); - } - - default: { - return state; - } - } -} diff --git a/src/app/shared/sidebar/filter/sidebar-filter.service.spec.ts b/src/app/shared/sidebar/filter/sidebar-filter.service.spec.ts deleted file mode 100644 index 49192a2006..0000000000 --- a/src/app/shared/sidebar/filter/sidebar-filter.service.spec.ts +++ /dev/null @@ -1,107 +0,0 @@ -import { TestBed, waitForAsync } from '@angular/core/testing'; -import { Store, StoreModule } from '@ngrx/store'; -import { provideMockStore } from '@ngrx/store/testing'; -import { cold } from 'jasmine-marbles'; - -import { sidebarFilterReducer } from './sidebar-filter.reducer'; -import { SidebarFilterService } from './sidebar-filter.service'; -import { - FilterCollapseAction, - FilterExpandAction, - FilterInitializeAction, - FilterToggleAction -} from './sidebar-filter.actions'; -import { storeModuleConfig } from '../../../app.reducer'; - -describe('SidebarFilterService', () => { - let service: SidebarFilterService; - let store: any; - let initialState; - - function init() { - - initialState = { - sidebarFilter: { - filter_1: { - filterCollapsed: true - }, - filter_2: { - filterCollapsed: false - }, - filter_3: { - filterCollapsed: true - } - } - }; - - } - - beforeEach(waitForAsync(() => { - init(); - TestBed.configureTestingModule({ - imports: [ - StoreModule.forRoot({ sidebarFilter: sidebarFilterReducer }, storeModuleConfig) - ], - providers: [ - provideMockStore({ initialState }), - { provide: SidebarFilterService, useValue: service } - ] - }).compileComponents(); - })); - - beforeEach(() => { - store = TestBed.inject(Store); - service = new SidebarFilterService(store); - spyOn(store, 'dispatch'); - }); - - describe('initializeFilter', () => { - it('should dispatch an FilterInitializeAction with the correct arguments', () => { - service.initializeFilter('fakeFilter', true); - expect(store.dispatch).toHaveBeenCalledWith(new FilterInitializeAction('fakeFilter', true)); - }); - }); - - describe('collapse', () => { - it('should dispatch an FilterInitializeAction with the correct arguments', () => { - service.collapse('fakeFilter'); - expect(store.dispatch).toHaveBeenCalledWith(new FilterCollapseAction('fakeFilter')); - }); - }); - - describe('expand', () => { - it('should dispatch an FilterInitializeAction with the correct arguments', () => { - service.expand('fakeFilter'); - expect(store.dispatch).toHaveBeenCalledWith(new FilterExpandAction('fakeFilter')); - }); - }); - - describe('toggle', () => { - it('should dispatch an FilterInitializeAction with the correct arguments', () => { - service.toggle('fakeFilter'); - expect(store.dispatch).toHaveBeenCalledWith(new FilterToggleAction('fakeFilter')); - }); - }); - - describe('isCollapsed', () => { - it('should return true', () => { - - const result = service.isCollapsed('filter_1'); - const expected = cold('b', { - b: true - }); - - expect(result).toBeObservable(expected); - }); - - it('should return false', () => { - - const result = service.isCollapsed('filter_2'); - const expected = cold('b', { - b: false - }); - - expect(result).toBeObservable(expected); - }); - }); -}); diff --git a/src/app/shared/sidebar/filter/sidebar-filter.service.ts b/src/app/shared/sidebar/filter/sidebar-filter.service.ts deleted file mode 100644 index b67de24f9e..0000000000 --- a/src/app/shared/sidebar/filter/sidebar-filter.service.ts +++ /dev/null @@ -1,90 +0,0 @@ -import { Injectable } from '@angular/core'; -import { - FilterCollapseAction, - FilterExpandAction, FilterInitializeAction, - FilterToggleAction -} from './sidebar-filter.actions'; -import { createSelector, MemoizedSelector, select, Store } from '@ngrx/store'; -import { SidebarFiltersState, SidebarFilterState } from './sidebar-filter.reducer'; -import { Observable } from 'rxjs'; -import { distinctUntilChanged, map } from 'rxjs/operators'; -import { hasValue } from '../../empty.util'; - -/** - * Service that performs all actions that have to do with sidebar filters like collapsing or expanding them. - */ -@Injectable() -export class SidebarFilterService { - - constructor(private store: Store) { - } - - /** - * Dispatches an initialize action to the store for a given filter - * @param {string} filter The filter for which the action is dispatched - * @param {boolean} expanded If the filter should be open from the start - */ - public initializeFilter(filter: string, expanded: boolean): void { - this.store.dispatch(new FilterInitializeAction(filter, expanded)); - } - - /** - * Dispatches a collapse action to the store for a given filter - * @param {string} filterName The filter for which the action is dispatched - */ - public collapse(filterName: string): void { - this.store.dispatch(new FilterCollapseAction(filterName)); - } - - /** - * Dispatches an expand action to the store for a given filter - * @param {string} filterName The filter for which the action is dispatched - */ - public expand(filterName: string): void { - this.store.dispatch(new FilterExpandAction(filterName)); - } - - /** - * Dispatches a toggle action to the store for a given filter - * @param {string} filterName The filter for which the action is dispatched - */ - public toggle(filterName: string): void { - this.store.dispatch(new FilterToggleAction(filterName)); - } - - /** - * Checks if the state of a given filter is currently collapsed or not - * @param {string} filterName The filtername for which the collapsed state is checked - * @returns {Observable} Emits the current collapsed state of the given filter, if it's unavailable, return false - */ - isCollapsed(filterName: string): Observable { - return this.store.pipe( - select(filterByNameSelector(filterName)), - map((object: SidebarFilterState) => { - if (object) { - return object.filterCollapsed; - } else { - return false; - } - }), - distinctUntilChanged() - ); - } - -} - -const filterStateSelector = (state: SidebarFiltersState) => state.sidebarFilter; - -function filterByNameSelector(name: string): MemoizedSelector { - return keySelector(name); -} - -export function keySelector(key: string): MemoizedSelector { - return createSelector(filterStateSelector, (state: SidebarFilterState) => { - if (hasValue(state)) { - return state[key]; - } else { - return undefined; - } - }); -} From f6db75f4f8d442940655b1ccf58c0829152918ac Mon Sep 17 00:00:00 2001 From: Yury Bondarenko Date: Tue, 3 Jan 2023 17:05:36 +0100 Subject: [PATCH 41/59] 96252: Remove unneeded imports from SharedModule These are no longer required in SharedModule, so we can remove them from main.js --- .../community-list-page/community-list-page.module.ts | 5 ++++- src/app/shared/form/form.module.ts | 5 +++++ src/app/shared/search/search.module.ts | 4 +++- src/app/shared/shared.module.ts | 11 ----------- src/themes/custom/eager-theme.module.ts | 5 +---- src/themes/dspace/eager-theme.module.ts | 2 -- 6 files changed, 13 insertions(+), 19 deletions(-) diff --git a/src/app/community-list-page/community-list-page.module.ts b/src/app/community-list-page/community-list-page.module.ts index 18c28068be..15946b2e89 100644 --- a/src/app/community-list-page/community-list-page.module.ts +++ b/src/app/community-list-page/community-list-page.module.ts @@ -6,6 +6,7 @@ import { CommunityListPageRoutingModule } from './community-list-page.routing.mo import { CommunityListComponent } from './community-list/community-list.component'; import { ThemedCommunityListPageComponent } from './themed-community-list-page.component'; import { ThemedCommunityListComponent } from './community-list/themed-community-list.component'; +import { CdkTreeModule } from '@angular/cdk/tree'; const DECLARATIONS = [ @@ -21,13 +22,15 @@ const DECLARATIONS = [ imports: [ CommonModule, SharedModule, - CommunityListPageRoutingModule + CommunityListPageRoutingModule, + CdkTreeModule, ], declarations: [ ...DECLARATIONS ], exports: [ ...DECLARATIONS, + CdkTreeModule, ], }) export class CommunityListPageModule { diff --git a/src/app/shared/form/form.module.ts b/src/app/shared/form/form.module.ts index 598cc2d32c..b30b6c8306 100644 --- a/src/app/shared/form/form.module.ts +++ b/src/app/shared/form/form.module.ts @@ -37,6 +37,8 @@ import { FormBuilderService } from './builder/form-builder.service'; import { DsDynamicTypeBindRelationService } from './builder/ds-dynamic-form-ui/ds-dynamic-type-bind-relation.service'; import { FormService } from './form.service'; import { NgxMaskModule } from 'ngx-mask'; +import { NgbDatepickerModule, NgbTimepickerModule } from '@ng-bootstrap/ng-bootstrap'; +import { CdkTreeModule } from '@angular/cdk/tree'; const COMPONENTS = [ CustomSwitchComponent, @@ -84,6 +86,9 @@ const DIRECTIVES = [ TranslateModule, SortablejsModule, NgxMaskModule.forRoot(), + NgbDatepickerModule, + NgbTimepickerModule, + CdkTreeModule, ], exports: [ ...COMPONENTS, diff --git a/src/app/shared/search/search.module.ts b/src/app/shared/search/search.module.ts index 426ed82aef..713b9925a6 100644 --- a/src/app/shared/search/search.module.ts +++ b/src/app/shared/search/search.module.ts @@ -31,6 +31,7 @@ import { SearchComponent } from './search.component'; import { ThemedSearchComponent } from './themed-search.component'; import { ThemedSearchResultsComponent } from './search-results/themed-search-results.component'; import { ThemedSearchSettingsComponent } from './search-settings/themed-search-settings.component'; +import { NouisliderModule } from 'ng2-nouislider'; const COMPONENTS = [ SearchComponent, @@ -91,7 +92,8 @@ export const MODELS = [ missingTranslationHandler: { provide: MissingTranslationHandler, useClass: MissingTranslationHelper }, useDefaultLang: true }), - SharedModule.withEntryComponents() + SharedModule.withEntryComponents(), + NouisliderModule, ], exports: [ ...COMPONENTS diff --git a/src/app/shared/shared.module.ts b/src/app/shared/shared.module.ts index 50c41c82e6..b7479cd0b8 100644 --- a/src/app/shared/shared.module.ts +++ b/src/app/shared/shared.module.ts @@ -2,21 +2,15 @@ import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; import { RouterModule } from '@angular/router'; import { FormsModule, ReactiveFormsModule } from '@angular/forms'; -import { CdkTreeModule } from '@angular/cdk/tree'; import { DragDropModule } from '@angular/cdk/drag-drop'; - -import { NouisliderModule } from 'ng2-nouislider'; import { - NgbDatepickerModule, NgbDropdownModule, NgbNavModule, NgbPaginationModule, - NgbTimepickerModule, NgbTooltipModule, NgbTypeaheadModule, } from '@ng-bootstrap/ng-bootstrap'; import { MissingTranslationHandler, TranslateModule } from '@ngx-translate/core'; -import { NgxPaginationModule } from 'ngx-pagination'; import { InfiniteScrollModule } from 'ngx-infinite-scroll'; import { MomentModule } from 'ngx-moment'; import { ConfirmationModalComponent } from './confirmation-modal/confirmation-modal.component'; @@ -256,19 +250,14 @@ const MODULES = [ FormsModule, InfiniteScrollModule, NgbNavModule, - NgbDatepickerModule, - NgbTimepickerModule, NgbTypeaheadModule, - NgxPaginationModule, NgbPaginationModule, NgbDropdownModule, NgbTooltipModule, ReactiveFormsModule, RouterModule, - NouisliderModule, MomentModule, DragDropModule, - CdkTreeModule, GoogleRecaptchaModule, MenuModule, ]; diff --git a/src/themes/custom/eager-theme.module.ts b/src/themes/custom/eager-theme.module.ts index 4e3c6f8b46..7637ffdb80 100644 --- a/src/themes/custom/eager-theme.module.ts +++ b/src/themes/custom/eager-theme.module.ts @@ -7,7 +7,6 @@ import { NavbarComponent } from './app/navbar/navbar.component'; import { SearchNavbarComponent } from './app/search-navbar/search-navbar.component'; import { HeaderComponent } from './app/header/header.component'; import { HeaderNavbarWrapperComponent } from './app/header-nav-wrapper/header-navbar-wrapper.component'; -import { SearchModule } from '../../app/shared/search/search.module'; import { RootModule } from '../../app/root.module'; import { NavbarModule } from '../../app/navbar/navbar.module'; import { PublicationComponent } from './app/item-page/simple/item-types/publication/publication.component'; @@ -42,7 +41,7 @@ import { } from './app/shared/dso-selector/modal-wrappers/edit-item-selector/edit-item-selector.component'; import { CommunityListElementComponent } from './app/shared/object-list/community-list-element/community-list-element.component'; -import { CollectionListElementComponent} from './app/shared/object-list/collection-list-element/collection-list-element.component'; +import { CollectionListElementComponent } from './app/shared/object-list/collection-list-element/collection-list-element.component'; /** @@ -80,8 +79,6 @@ const DECLARATIONS = [ imports: [ CommonModule, SharedModule, - SearchModule, - FormsModule, RootModule, NavbarModule, ItemPageModule, diff --git a/src/themes/dspace/eager-theme.module.ts b/src/themes/dspace/eager-theme.module.ts index 5dd114cd72..dd09f9263e 100644 --- a/src/themes/dspace/eager-theme.module.ts +++ b/src/themes/dspace/eager-theme.module.ts @@ -29,8 +29,6 @@ const DECLARATIONS = [ imports: [ CommonModule, SharedModule, - SearchModule, - FormsModule, RootModule, NavbarModule, ], From 594f8eaa779a06ac5ade960d4b7913fa78285e87 Mon Sep 17 00:00:00 2001 From: Yana De Pauw Date: Thu, 5 Jan 2023 13:18:36 +0100 Subject: [PATCH 42/59] Fix breadcrumb color css --- src/app/breadcrumbs/breadcrumbs.component.scss | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/app/breadcrumbs/breadcrumbs.component.scss b/src/app/breadcrumbs/breadcrumbs.component.scss index 412dca87db..029609e6c0 100644 --- a/src/app/breadcrumbs/breadcrumbs.component.scss +++ b/src/app/breadcrumbs/breadcrumbs.component.scss @@ -23,9 +23,12 @@ li.breadcrumb-item { } } -li.breadcrumb-item > a { - color: var(--ds-breadcrumb-link-color) !important; +li.breadcrumb-item { + a { + color: var(--ds-breadcrumb-link-color) !important; + } } + li.breadcrumb-item.active { color: var(--ds-breadcrumb-link-active-color) !important; } From e5082ffa1f1be76e421589c3388c1ffc1b69309d Mon Sep 17 00:00:00 2001 From: Yana De Pauw Date: Thu, 5 Jan 2023 13:30:28 +0100 Subject: [PATCH 43/59] Remove unneeded important --- src/app/breadcrumbs/breadcrumbs.component.scss | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/app/breadcrumbs/breadcrumbs.component.scss b/src/app/breadcrumbs/breadcrumbs.component.scss index 029609e6c0..a4d83b82ea 100644 --- a/src/app/breadcrumbs/breadcrumbs.component.scss +++ b/src/app/breadcrumbs/breadcrumbs.component.scss @@ -25,12 +25,12 @@ li.breadcrumb-item { li.breadcrumb-item { a { - color: var(--ds-breadcrumb-link-color) !important; + color: var(--ds-breadcrumb-link-color); } } li.breadcrumb-item.active { - color: var(--ds-breadcrumb-link-active-color) !important; + color: var(--ds-breadcrumb-link-active-color); } .breadcrumb-item+ .breadcrumb-item::before { From 68a3c8a4b2f4224021f4401eaedeb188fff66616 Mon Sep 17 00:00:00 2001 From: Ying Jin Date: Thu, 5 Jan 2023 16:31:42 -0600 Subject: [PATCH 44/59] change typo from minetype to mimetype --- src/app/core/shared/media-viewer-item.model.ts | 2 +- .../media-viewer-video/media-viewer-video.component.ts | 2 +- src/app/item-page/media-viewer/media-viewer.component.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/app/core/shared/media-viewer-item.model.ts b/src/app/core/shared/media-viewer-item.model.ts index 38c53944d1..1cf4948408 100644 --- a/src/app/core/shared/media-viewer-item.model.ts +++ b/src/app/core/shared/media-viewer-item.model.ts @@ -17,7 +17,7 @@ export class MediaViewerItem { /** * Incoming Bitsream format mime type */ - minetype: string; + mimetype: string; /** * Incoming Bitsream thumbnail diff --git a/src/app/item-page/media-viewer/media-viewer-video/media-viewer-video.component.ts b/src/app/item-page/media-viewer/media-viewer-video/media-viewer-video.component.ts index cc08d2b4a0..647bbacdc3 100644 --- a/src/app/item-page/media-viewer/media-viewer-video/media-viewer-video.component.ts +++ b/src/app/item-page/media-viewer/media-viewer-video/media-viewer-video.component.ts @@ -45,7 +45,7 @@ export class MediaViewerVideoComponent implements OnInit { let filteredCapMedias: MediaViewerItem[]; let capInfos: CaptionInfo[] = []; filteredCapMedias = this.medias - .filter((media) => media.minetype === 'text/vtt') + .filter((media) => media.mimetype === 'text/vtt') .filter((media) => media.bitstream.name.substring(0, (media.bitstream.name.length - 7) ).toLowerCase() === name.toLowerCase()); if (filteredCapMedias) { diff --git a/src/app/item-page/media-viewer/media-viewer.component.ts b/src/app/item-page/media-viewer/media-viewer.component.ts index 7ee60704eb..233ae0e6f6 100644 --- a/src/app/item-page/media-viewer/media-viewer.component.ts +++ b/src/app/item-page/media-viewer/media-viewer.component.ts @@ -108,7 +108,7 @@ export class MediaViewerComponent implements OnInit { const mediaItem = new MediaViewerItem(); mediaItem.bitstream = original; mediaItem.format = format.mimetype.split('/')[0]; - mediaItem.minetype = format.mimetype; + mediaItem.mimetype = format.mimetype; mediaItem.thumbnail = thumbnail ? thumbnail._links.content.href : null; return mediaItem; } From 1c11b9813c94f7030dd1106ec6b2f022d92c3485 Mon Sep 17 00:00:00 2001 From: Kristof De Langhe Date: Mon, 9 Jan 2023 15:59:48 +0100 Subject: [PATCH 45/59] 97287: Fix GA page-view requests --- src/app/statistics/angulartics/dspace-provider.ts | 2 +- .../angulartics/dspace/view-tracker.component.ts | 2 +- src/app/statistics/google-analytics.service.ts | 9 ++++++--- src/modules/app/server-app.module.ts | 9 +++++++-- 4 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/app/statistics/angulartics/dspace-provider.ts b/src/app/statistics/angulartics/dspace-provider.ts index cd1aab94bd..6efa67f92a 100644 --- a/src/app/statistics/angulartics/dspace-provider.ts +++ b/src/app/statistics/angulartics/dspace-provider.ts @@ -24,7 +24,7 @@ export class Angulartics2DSpace { } private eventTrack(event) { - if (event.action === 'pageView') { + if (event.action === 'page_view') { this.statisticsService.trackViewEvent(event.properties.object); } else if (event.action === 'search') { this.statisticsService.trackSearchEvent( diff --git a/src/app/statistics/angulartics/dspace/view-tracker.component.ts b/src/app/statistics/angulartics/dspace/view-tracker.component.ts index 85588aeb97..d12b6c2f69 100644 --- a/src/app/statistics/angulartics/dspace/view-tracker.component.ts +++ b/src/app/statistics/angulartics/dspace/view-tracker.component.ts @@ -20,7 +20,7 @@ export class ViewTrackerComponent implements OnInit { ngOnInit(): void { this.angulartics2.eventTrack.next({ - action: 'pageView', + action: 'page_view', properties: {object: this.object}, }); } diff --git a/src/app/statistics/google-analytics.service.ts b/src/app/statistics/google-analytics.service.ts index 9c5883d183..9d32a61093 100644 --- a/src/app/statistics/google-analytics.service.ts +++ b/src/app/statistics/google-analytics.service.ts @@ -1,7 +1,10 @@ import { DOCUMENT } from '@angular/common'; import { Inject, Injectable } from '@angular/core'; -import { Angulartics2GoogleAnalytics, Angulartics2GoogleTagManager } from 'angulartics2'; +import { + Angulartics2GoogleAnalytics, + Angulartics2GoogleGlobalSiteTag, +} from 'angulartics2'; import { combineLatest } from 'rxjs'; import { ConfigurationDataService } from '../core/data/configuration-data.service'; @@ -19,7 +22,7 @@ export class GoogleAnalyticsService { constructor( private googleAnalytics: Angulartics2GoogleAnalytics, - private googleTagManager: Angulartics2GoogleTagManager, + private googleGlobalSiteTag: Angulartics2GoogleGlobalSiteTag, private klaroService: KlaroService, private configService: ConfigurationDataService, @Inject(DOCUMENT) private document: any, @@ -70,7 +73,7 @@ export class GoogleAnalyticsService { this.document.body.appendChild(libScript); // start tracking - this.googleTagManager.startTracking(); + this.googleGlobalSiteTag.startTracking(); } else { // add trackingId snippet to page const keyScript = this.document.createElement('script'); diff --git a/src/modules/app/server-app.module.ts b/src/modules/app/server-app.module.ts index 17e394ede8..4b51a846f9 100644 --- a/src/modules/app/server-app.module.ts +++ b/src/modules/app/server-app.module.ts @@ -6,7 +6,12 @@ import { ServerModule, ServerTransferStateModule } from '@angular/platform-serve import { TranslateLoader, TranslateModule } from '@ngx-translate/core'; -import { Angulartics2, Angulartics2GoogleAnalytics, Angulartics2GoogleTagManager } from 'angulartics2'; +import { + Angulartics2, + Angulartics2GoogleAnalytics, + Angulartics2GoogleGlobalSiteTag, + Angulartics2GoogleTagManager +} from 'angulartics2'; import { AppComponent } from '../../app/app.component'; @@ -63,7 +68,7 @@ export function createTranslateLoader(transferState: TransferState) { useClass: AngularticsProviderMock }, { - provide: Angulartics2GoogleTagManager, + provide: Angulartics2GoogleGlobalSiteTag, useClass: AngularticsProviderMock }, { From a7a6d1b27aef5054cd84d4f487945a2bd4a7978b Mon Sep 17 00:00:00 2001 From: Yury Bondarenko Date: Mon, 9 Jan 2023 16:47:05 +0100 Subject: [PATCH 46/59] Fix Klaro i18n issue Caused by a merge mistake in https://github.com/DSpace/dspace-angular/pull/1975 --- src/app/shared/cookies/browser-klaro.service.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/shared/cookies/browser-klaro.service.ts b/src/app/shared/cookies/browser-klaro.service.ts index 3e830811b3..4f3c8e00d5 100644 --- a/src/app/shared/cookies/browser-klaro.service.ts +++ b/src/app/shared/cookies/browser-klaro.service.ts @@ -49,7 +49,7 @@ const LAZY_KLARO = new InjectionToken>( 'Lazily loaded Klaro', { providedIn: 'root', - factory: async () => (await import('klaro')), + factory: async () => (await import('klaro/dist/klaro-no-translations')), } ); From 463bcb40e9af8295e7b674832036f46770ea6505 Mon Sep 17 00:00:00 2001 From: Yury Bondarenko Date: Mon, 9 Jan 2023 16:47:24 +0100 Subject: [PATCH 47/59] Remove stray console.log --- src/app/shared/cookies/browser-klaro.service.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/app/shared/cookies/browser-klaro.service.ts b/src/app/shared/cookies/browser-klaro.service.ts index 4f3c8e00d5..2b09c0bf15 100644 --- a/src/app/shared/cookies/browser-klaro.service.ts +++ b/src/app/shared/cookies/browser-klaro.service.ts @@ -115,7 +115,6 @@ export class BrowserKlaroService extends KlaroService { if (hideRegistrationVerification) { servicesToHideArray.push(CAPTCHA_NAME); } - console.log(servicesToHideArray); return servicesToHideArray; }) ); From f9f3ad32c78040521b950752eccfbd9dc9840305 Mon Sep 17 00:00:00 2001 From: Nikunj Sharma Date: Tue, 10 Jan 2023 19:37:06 +0530 Subject: [PATCH 48/59] [CST-7604] added hithighlight for person and orgunit --- src/app/core/breadcrumbs/dso-name.service.ts | 42 +++++++++++++++++++ src/app/shared/mocks/dso-name.service.mock.ts | 11 +++++ ...em-search-result-grid-element.component.ts | 3 +- .../item-list-preview.component.ts | 2 +- ...arch-result-list-element.component.spec.ts | 5 ++- .../search-result-list-element.component.ts | 2 +- 6 files changed, 60 insertions(+), 5 deletions(-) diff --git a/src/app/core/breadcrumbs/dso-name.service.ts b/src/app/core/breadcrumbs/dso-name.service.ts index d56f4a00eb..64f37baa65 100644 --- a/src/app/core/breadcrumbs/dso-name.service.ts +++ b/src/app/core/breadcrumbs/dso-name.service.ts @@ -2,6 +2,7 @@ import { Injectable } from '@angular/core'; import { hasValue, isEmpty } from '../../shared/empty.util'; import { DSpaceObject } from '../shared/dspace-object.model'; import { TranslateService } from '@ngx-translate/core'; +import { Metadata } from '../shared/metadata.utils'; /** * Returns a name for a {@link DSpaceObject} based @@ -67,4 +68,45 @@ export class DSONameService { return name; } + /** + * Gets the Hit highlight + * + * @param object + * @param dso + * + * @returns {string} html embedded hit highlight. + */ + getHitHighlights(object: any, dso: DSpaceObject): string { + const types = dso.getRenderTypes(); + const entityType = types + .filter((type) => typeof type === 'string') + .find((type: string) => (['Person', 'OrgUnit']).includes(type)) as string; + if (entityType === 'Person') { + const familyName = this.firstMetadataValue(object, dso, 'person.familyName'); + const givenName = this.firstMetadataValue(object, dso, 'person.givenName'); + if (isEmpty(familyName) && isEmpty(givenName)) { + return this.firstMetadataValue(object, dso, 'dc.title') || dso.name; + } else if (isEmpty(familyName) || isEmpty(givenName)) { + return familyName || givenName; + } + return `${familyName}, ${givenName}`; + } else if (entityType === 'OrgUnit') { + return this.firstMetadataValue(object, dso, 'organization.legalName'); + } + return this.firstMetadataValue(object, dso, 'dc.title') || dso.name || this.translateService.instant('dso.name.untitled'); + } + + /** + * Gets the first matching metadata string value from hitHighlights or dso metadata, preferring hitHighlights. + * + * @param object + * @param dso + * @param {string|string[]} keyOrKeys The metadata key(s) in scope. Wildcards are supported; see [[Metadata]]. + * + * @returns {string} the first matching string value, or `undefined`. + */ + firstMetadataValue(object: any, dso: DSpaceObject, keyOrKeys: string | string[]): string { + return Metadata.firstValue([object.hitHighlights, dso.metadata], keyOrKeys); + } + } diff --git a/src/app/shared/mocks/dso-name.service.mock.ts b/src/app/shared/mocks/dso-name.service.mock.ts index f4947cc860..1e3280ce8d 100644 --- a/src/app/shared/mocks/dso-name.service.mock.ts +++ b/src/app/shared/mocks/dso-name.service.mock.ts @@ -6,4 +6,15 @@ export class DSONameServiceMock { public getName(dso: DSpaceObject) { return UNDEFINED_NAME; } + + public getHitHighlights(object: any, dso: DSpaceObject) { + if (object.hitHighlights && object.hitHighlights['dc.title']) { + return object.hitHighlights['dc.title'][0]; + } else if (object.hitHighlights && object.hitHighlights['organization.legalName']) { + return object.hitHighlights['organization.legalName'][0]; + } else if (object.hitHighlights && (object.hitHighlights['person.familyName'] || object.hitHighlights['person.givenName'])) { + return `${object.hitHighlights['person.familyName'][0] || ''}, ${object.hitHighlights['person.givenName'][0] || ''}`; + } + return UNDEFINED_NAME; + } } diff --git a/src/app/shared/object-grid/search-result-grid-element/item-search-result/item/item-search-result-grid-element.component.ts b/src/app/shared/object-grid/search-result-grid-element/item-search-result/item/item-search-result-grid-element.component.ts index fc24d5450b..303e4681a2 100644 --- a/src/app/shared/object-grid/search-result-grid-element/item-search-result/item/item-search-result-grid-element.component.ts +++ b/src/app/shared/object-grid/search-result-grid-element/item-search-result/item/item-search-result-grid-element.component.ts @@ -42,7 +42,6 @@ export class ItemSearchResultGridElementComponent extends SearchResultGridElemen ngOnInit(): void { super.ngOnInit(); this.itemPageRoute = getItemPageRoute(this.dso); - this.dsoTitle = this.firstMetadataValue('dc.title') ?? - (this.dso ? this.dsoNameService.getName(this.dso) : undefined); + this.dsoTitle = this.dsoNameService.getHitHighlights(this.object, this.dso); } } diff --git a/src/app/shared/object-list/my-dspace-result-list-element/item-list-preview/item-list-preview.component.ts b/src/app/shared/object-list/my-dspace-result-list-element/item-list-preview/item-list-preview.component.ts index 04f1e24d7b..6b40678ded 100644 --- a/src/app/shared/object-list/my-dspace-result-list-element/item-list-preview/item-list-preview.component.ts +++ b/src/app/shared/object-list/my-dspace-result-list-element/item-list-preview/item-list-preview.component.ts @@ -55,7 +55,7 @@ export class ItemListPreviewComponent implements OnInit { ngOnInit(): void { this.showThumbnails = this.appConfig.browseBy.showThumbnails; - this.dsoTitle = this.dsoNameService.getName(this.item); + this.dsoTitle = this.dsoNameService.getHitHighlights(this.object, this.item); } diff --git a/src/app/shared/object-list/search-result-list-element/item-search-result/item-types/item/item-search-result-list-element.component.spec.ts b/src/app/shared/object-list/search-result-list-element/item-search-result/item-types/item/item-search-result-list-element.component.spec.ts index 660377746a..0d7c2cbc58 100644 --- a/src/app/shared/object-list/search-result-list-element/item-search-result/item-types/item/item-search-result-list-element.component.spec.ts +++ b/src/app/shared/object-list/search-result-list-element/item-search-result/item-types/item/item-search-result-list-element.component.spec.ts @@ -15,6 +15,9 @@ let publicationListElementComponent: ItemSearchResultListElementComponent; let fixture: ComponentFixture; const dcTitle = 'This is just another title'; const mockItemWithMetadata: ItemSearchResult = Object.assign(new ItemSearchResult(), { + hitHighlights: { + 'dc.title': [dcTitle], + }, indexableObject: Object.assign(new Item(), { bundles: observableOf({}), @@ -22,7 +25,7 @@ const mockItemWithMetadata: ItemSearchResult = Object.assign(new ItemSearchResul 'dc.title': [ { language: 'en_US', - value: dcTitle + value: 'This is just another title' } ], 'dc.contributor.author': [ diff --git a/src/app/shared/object-list/search-result-list-element/search-result-list-element.component.ts b/src/app/shared/object-list/search-result-list-element/search-result-list-element.component.ts index c69044e907..e56b7e970a 100644 --- a/src/app/shared/object-list/search-result-list-element/search-result-list-element.component.ts +++ b/src/app/shared/object-list/search-result-list-element/search-result-list-element.component.ts @@ -33,7 +33,7 @@ export class SearchResultListElementComponent, K exten ngOnInit(): void { if (hasValue(this.object)) { this.dso = this.object.indexableObject; - this.dsoTitle = this.firstMetadataValue('dc.title') ?? this.dsoNameService.getName(this.dso); + this.dsoTitle = this.dsoNameService.getHitHighlights(this.object, this.dso); } } From b7b2803f6ebb6e86f2c38cceb5168a80ceeefe0c Mon Sep 17 00:00:00 2001 From: Nikunj Sharma Date: Tue, 10 Jan 2023 19:37:06 +0530 Subject: [PATCH 49/59] [CST-7604] added hithighlight for person and orgunit --- src/app/core/breadcrumbs/dso-name.service.ts | 42 +++++++++++++++++++ src/app/shared/mocks/dso-name.service.mock.ts | 11 +++++ ...arch-result-grid-element.component.spec.ts | 3 ++ ...em-search-result-grid-element.component.ts | 3 +- .../item-list-preview.component.ts | 2 +- ...arch-result-list-element.component.spec.ts | 5 ++- .../search-result-list-element.component.ts | 2 +- 7 files changed, 63 insertions(+), 5 deletions(-) diff --git a/src/app/core/breadcrumbs/dso-name.service.ts b/src/app/core/breadcrumbs/dso-name.service.ts index d56f4a00eb..64f37baa65 100644 --- a/src/app/core/breadcrumbs/dso-name.service.ts +++ b/src/app/core/breadcrumbs/dso-name.service.ts @@ -2,6 +2,7 @@ import { Injectable } from '@angular/core'; import { hasValue, isEmpty } from '../../shared/empty.util'; import { DSpaceObject } from '../shared/dspace-object.model'; import { TranslateService } from '@ngx-translate/core'; +import { Metadata } from '../shared/metadata.utils'; /** * Returns a name for a {@link DSpaceObject} based @@ -67,4 +68,45 @@ export class DSONameService { return name; } + /** + * Gets the Hit highlight + * + * @param object + * @param dso + * + * @returns {string} html embedded hit highlight. + */ + getHitHighlights(object: any, dso: DSpaceObject): string { + const types = dso.getRenderTypes(); + const entityType = types + .filter((type) => typeof type === 'string') + .find((type: string) => (['Person', 'OrgUnit']).includes(type)) as string; + if (entityType === 'Person') { + const familyName = this.firstMetadataValue(object, dso, 'person.familyName'); + const givenName = this.firstMetadataValue(object, dso, 'person.givenName'); + if (isEmpty(familyName) && isEmpty(givenName)) { + return this.firstMetadataValue(object, dso, 'dc.title') || dso.name; + } else if (isEmpty(familyName) || isEmpty(givenName)) { + return familyName || givenName; + } + return `${familyName}, ${givenName}`; + } else if (entityType === 'OrgUnit') { + return this.firstMetadataValue(object, dso, 'organization.legalName'); + } + return this.firstMetadataValue(object, dso, 'dc.title') || dso.name || this.translateService.instant('dso.name.untitled'); + } + + /** + * Gets the first matching metadata string value from hitHighlights or dso metadata, preferring hitHighlights. + * + * @param object + * @param dso + * @param {string|string[]} keyOrKeys The metadata key(s) in scope. Wildcards are supported; see [[Metadata]]. + * + * @returns {string} the first matching string value, or `undefined`. + */ + firstMetadataValue(object: any, dso: DSpaceObject, keyOrKeys: string | string[]): string { + return Metadata.firstValue([object.hitHighlights, dso.metadata], keyOrKeys); + } + } diff --git a/src/app/shared/mocks/dso-name.service.mock.ts b/src/app/shared/mocks/dso-name.service.mock.ts index f4947cc860..1e3280ce8d 100644 --- a/src/app/shared/mocks/dso-name.service.mock.ts +++ b/src/app/shared/mocks/dso-name.service.mock.ts @@ -6,4 +6,15 @@ export class DSONameServiceMock { public getName(dso: DSpaceObject) { return UNDEFINED_NAME; } + + public getHitHighlights(object: any, dso: DSpaceObject) { + if (object.hitHighlights && object.hitHighlights['dc.title']) { + return object.hitHighlights['dc.title'][0]; + } else if (object.hitHighlights && object.hitHighlights['organization.legalName']) { + return object.hitHighlights['organization.legalName'][0]; + } else if (object.hitHighlights && (object.hitHighlights['person.familyName'] || object.hitHighlights['person.givenName'])) { + return `${object.hitHighlights['person.familyName'][0] || ''}, ${object.hitHighlights['person.givenName'][0] || ''}`; + } + return UNDEFINED_NAME; + } } diff --git a/src/app/shared/object-grid/search-result-grid-element/item-search-result/item/item-search-result-grid-element.component.spec.ts b/src/app/shared/object-grid/search-result-grid-element/item-search-result/item/item-search-result-grid-element.component.spec.ts index 97dda155c5..f25937df34 100644 --- a/src/app/shared/object-grid/search-result-grid-element/item-search-result/item/item-search-result-grid-element.component.spec.ts +++ b/src/app/shared/object-grid/search-result-grid-element/item-search-result/item/item-search-result-grid-element.component.spec.ts @@ -30,6 +30,9 @@ const mockItemWithMetadata: ItemSearchResult = new ItemSearchResult(); mockItemWithMetadata.hitHighlights = {}; const dcTitle = 'This is just another title'; mockItemWithMetadata.indexableObject = Object.assign(new Item(), { + hitHighlights: { + 'dc.title': [dcTitle], + }, bundles: createSuccessfulRemoteDataObject$(buildPaginatedList(new PageInfo(), [])), metadata: { 'dc.title': [ diff --git a/src/app/shared/object-grid/search-result-grid-element/item-search-result/item/item-search-result-grid-element.component.ts b/src/app/shared/object-grid/search-result-grid-element/item-search-result/item/item-search-result-grid-element.component.ts index fc24d5450b..303e4681a2 100644 --- a/src/app/shared/object-grid/search-result-grid-element/item-search-result/item/item-search-result-grid-element.component.ts +++ b/src/app/shared/object-grid/search-result-grid-element/item-search-result/item/item-search-result-grid-element.component.ts @@ -42,7 +42,6 @@ export class ItemSearchResultGridElementComponent extends SearchResultGridElemen ngOnInit(): void { super.ngOnInit(); this.itemPageRoute = getItemPageRoute(this.dso); - this.dsoTitle = this.firstMetadataValue('dc.title') ?? - (this.dso ? this.dsoNameService.getName(this.dso) : undefined); + this.dsoTitle = this.dsoNameService.getHitHighlights(this.object, this.dso); } } diff --git a/src/app/shared/object-list/my-dspace-result-list-element/item-list-preview/item-list-preview.component.ts b/src/app/shared/object-list/my-dspace-result-list-element/item-list-preview/item-list-preview.component.ts index 04f1e24d7b..6b40678ded 100644 --- a/src/app/shared/object-list/my-dspace-result-list-element/item-list-preview/item-list-preview.component.ts +++ b/src/app/shared/object-list/my-dspace-result-list-element/item-list-preview/item-list-preview.component.ts @@ -55,7 +55,7 @@ export class ItemListPreviewComponent implements OnInit { ngOnInit(): void { this.showThumbnails = this.appConfig.browseBy.showThumbnails; - this.dsoTitle = this.dsoNameService.getName(this.item); + this.dsoTitle = this.dsoNameService.getHitHighlights(this.object, this.item); } diff --git a/src/app/shared/object-list/search-result-list-element/item-search-result/item-types/item/item-search-result-list-element.component.spec.ts b/src/app/shared/object-list/search-result-list-element/item-search-result/item-types/item/item-search-result-list-element.component.spec.ts index 660377746a..0d7c2cbc58 100644 --- a/src/app/shared/object-list/search-result-list-element/item-search-result/item-types/item/item-search-result-list-element.component.spec.ts +++ b/src/app/shared/object-list/search-result-list-element/item-search-result/item-types/item/item-search-result-list-element.component.spec.ts @@ -15,6 +15,9 @@ let publicationListElementComponent: ItemSearchResultListElementComponent; let fixture: ComponentFixture; const dcTitle = 'This is just another title'; const mockItemWithMetadata: ItemSearchResult = Object.assign(new ItemSearchResult(), { + hitHighlights: { + 'dc.title': [dcTitle], + }, indexableObject: Object.assign(new Item(), { bundles: observableOf({}), @@ -22,7 +25,7 @@ const mockItemWithMetadata: ItemSearchResult = Object.assign(new ItemSearchResul 'dc.title': [ { language: 'en_US', - value: dcTitle + value: 'This is just another title' } ], 'dc.contributor.author': [ diff --git a/src/app/shared/object-list/search-result-list-element/search-result-list-element.component.ts b/src/app/shared/object-list/search-result-list-element/search-result-list-element.component.ts index c69044e907..e56b7e970a 100644 --- a/src/app/shared/object-list/search-result-list-element/search-result-list-element.component.ts +++ b/src/app/shared/object-list/search-result-list-element/search-result-list-element.component.ts @@ -33,7 +33,7 @@ export class SearchResultListElementComponent, K exten ngOnInit(): void { if (hasValue(this.object)) { this.dso = this.object.indexableObject; - this.dsoTitle = this.firstMetadataValue('dc.title') ?? this.dsoNameService.getName(this.dso); + this.dsoTitle = this.dsoNameService.getHitHighlights(this.object, this.dso); } } From 5660e7dc701a575cb0f4df5c732d6ce1ee92bb06 Mon Sep 17 00:00:00 2001 From: Nikunj Sharma Date: Wed, 11 Jan 2023 02:46:20 +0530 Subject: [PATCH 50/59] [CST-7604] test cases update --- src/app/shared/mocks/dso-name.service.mock.ts | 14 +- ...arch-result-grid-element.component.spec.ts | 136 ++++++++++++++++- ...arch-result-list-element.component.spec.ts | 139 +++++++++++++++++- 3 files changed, 282 insertions(+), 7 deletions(-) diff --git a/src/app/shared/mocks/dso-name.service.mock.ts b/src/app/shared/mocks/dso-name.service.mock.ts index 1e3280ce8d..cf3cf5466b 100644 --- a/src/app/shared/mocks/dso-name.service.mock.ts +++ b/src/app/shared/mocks/dso-name.service.mock.ts @@ -9,11 +9,19 @@ export class DSONameServiceMock { public getHitHighlights(object: any, dso: DSpaceObject) { if (object.hitHighlights && object.hitHighlights['dc.title']) { - return object.hitHighlights['dc.title'][0]; + return object.hitHighlights['dc.title'][0].value; } else if (object.hitHighlights && object.hitHighlights['organization.legalName']) { - return object.hitHighlights['organization.legalName'][0]; + return object.hitHighlights['organization.legalName'][0].value; } else if (object.hitHighlights && (object.hitHighlights['person.familyName'] || object.hitHighlights['person.givenName'])) { - return `${object.hitHighlights['person.familyName'][0] || ''}, ${object.hitHighlights['person.givenName'][0] || ''}`; + if (object.hitHighlights['person.familyName'] && object.hitHighlights['person.givenName']) { + return `${object.hitHighlights['person.familyName'][0].value}, ${object.hitHighlights['person.givenName'][0].value}`; + } + if (object.hitHighlights['person.familyName']) { + return `${object.hitHighlights['person.familyName'][0].value}`; + } + if (object.hitHighlights['person.givenName']) { + return `${object.hitHighlights['person.givenName'][0].value}`; + } } return UNDEFINED_NAME; } diff --git a/src/app/shared/object-grid/search-result-grid-element/item-search-result/item/item-search-result-grid-element.component.spec.ts b/src/app/shared/object-grid/search-result-grid-element/item-search-result/item/item-search-result-grid-element.component.spec.ts index f25937df34..dc42b033d8 100644 --- a/src/app/shared/object-grid/search-result-grid-element/item-search-result/item/item-search-result-grid-element.component.spec.ts +++ b/src/app/shared/object-grid/search-result-grid-element/item-search-result/item/item-search-result-grid-element.component.spec.ts @@ -31,7 +31,9 @@ mockItemWithMetadata.hitHighlights = {}; const dcTitle = 'This is just another title'; mockItemWithMetadata.indexableObject = Object.assign(new Item(), { hitHighlights: { - 'dc.title': [dcTitle], + 'dc.title': [{ + value: dcTitle + }], }, bundles: createSuccessfulRemoteDataObject$(buildPaginatedList(new PageInfo(), [])), metadata: { @@ -61,6 +63,114 @@ mockItemWithMetadata.indexableObject = Object.assign(new Item(), { ] } }); +const mockPerson: ItemSearchResult = Object.assign(new ItemSearchResult(), { + hitHighlights: { + 'person.familyName': [{ + value: 'Michel' + }], + }, + indexableObject: + Object.assign(new Item(), { + bundles: createSuccessfulRemoteDataObject$(buildPaginatedList(new PageInfo(), [])), + entityType: 'Person', + metadata: { + 'dc.title': [ + { + language: 'en_US', + value: 'This is just another title' + } + ], + 'dc.contributor.author': [ + { + language: 'en_US', + value: 'Smith, Donald' + } + ], + 'dc.publisher': [ + { + language: 'en_US', + value: 'a publisher' + } + ], + 'dc.date.issued': [ + { + language: 'en_US', + value: '2015-06-26' + } + ], + 'dc.description.abstract': [ + { + language: 'en_US', + value: 'This is the abstract' + } + ], + 'dspace.entity.type': [ + { + value: 'Person' + } + ], + 'person.familyName': [ + { + value: 'Michel' + } + ] + } + }) +}); +const mockOrgUnit: ItemSearchResult = Object.assign(new ItemSearchResult(), { + hitHighlights: { + 'organization.legalName': [{ + value: 'Science' + }], + }, + indexableObject: + Object.assign(new Item(), { + bundles: createSuccessfulRemoteDataObject$(buildPaginatedList(new PageInfo(), [])), + entityType: 'OrgUnit', + metadata: { + 'dc.title': [ + { + language: 'en_US', + value: 'This is just another title' + } + ], + 'dc.contributor.author': [ + { + language: 'en_US', + value: 'Smith, Donald' + } + ], + 'dc.publisher': [ + { + language: 'en_US', + value: 'a publisher' + } + ], + 'dc.date.issued': [ + { + language: 'en_US', + value: '2015-06-26' + } + ], + 'dc.description.abstract': [ + { + language: 'en_US', + value: 'This is the abstract' + } + ], + 'organization.legalName': [ + { + value: 'Science' + } + ], + 'dspace.entity.type': [ + { + value: 'OrgUnit' + } + ] + } + }) +}); const mockItemWithoutMetadata: ItemSearchResult = new ItemSearchResult(); mockItemWithoutMetadata.hitHighlights = {}; @@ -169,6 +279,30 @@ export function getEntityGridElementTestComponent(component, searchResultWithMet expect(titleField.nativeNode.innerHTML).toEqual(dcTitle); }); }); + + describe('When the item is Person and has title', () => { + beforeEach(() => { + comp.object = mockPerson; + fixture.detectChanges(); + }); + + it('should show highlighted title', () => { + const titleField = fixture.debugElement.query(By.css('.card-title')); + expect(titleField.nativeNode.innerHTML).toEqual('Michel'); + }); + }); + + describe('When the item is orgUnit and has title', () => { + beforeEach(() => { + comp.object = mockOrgUnit; + fixture.detectChanges(); + }); + + it('should show highlighted title', () => { + const titleField = fixture.debugElement.query(By.css('.card-title')); + expect(titleField.nativeNode.innerHTML).toEqual('Science'); + }); + }); }); }; } diff --git a/src/app/shared/object-list/search-result-list-element/item-search-result/item-types/item/item-search-result-list-element.component.spec.ts b/src/app/shared/object-list/search-result-list-element/item-search-result/item-types/item/item-search-result-list-element.component.spec.ts index 0d7c2cbc58..7665b7d64e 100644 --- a/src/app/shared/object-list/search-result-list-element/item-search-result/item-types/item/item-search-result-list-element.component.spec.ts +++ b/src/app/shared/object-list/search-result-list-element/item-search-result/item-types/item/item-search-result-list-element.component.spec.ts @@ -16,7 +16,9 @@ let fixture: ComponentFixture; const dcTitle = 'This is just another title'; const mockItemWithMetadata: ItemSearchResult = Object.assign(new ItemSearchResult(), { hitHighlights: { - 'dc.title': [dcTitle], + 'dc.title': [{ + value: dcTitle + }], }, indexableObject: Object.assign(new Item(), { @@ -25,7 +27,7 @@ const mockItemWithMetadata: ItemSearchResult = Object.assign(new ItemSearchResul 'dc.title': [ { language: 'en_US', - value: 'This is just another title' + value: dcTitle } ], 'dc.contributor.author': [ @@ -62,7 +64,114 @@ const mockItemWithoutMetadata: ItemSearchResult = Object.assign(new ItemSearchRe metadata: {} }) }); - +const mockPerson: ItemSearchResult = Object.assign(new ItemSearchResult(), { + hitHighlights: { + 'person.familyName': [{ + value: 'Michel' + }], + }, + indexableObject: + Object.assign(new Item(), { + bundles: observableOf({}), + entityType: 'Person', + metadata: { + 'dc.title': [ + { + language: 'en_US', + value: 'This is just another title' + } + ], + 'dc.contributor.author': [ + { + language: 'en_US', + value: 'Smith, Donald' + } + ], + 'dc.publisher': [ + { + language: 'en_US', + value: 'a publisher' + } + ], + 'dc.date.issued': [ + { + language: 'en_US', + value: '2015-06-26' + } + ], + 'dc.description.abstract': [ + { + language: 'en_US', + value: 'This is the abstract' + } + ], + 'person.familyName': [ + { + value: 'Michel' + } + ], + 'dspace.entity.type': [ + { + value: 'Person' + } + ] + } + }) +}); +const mockOrgUnit: ItemSearchResult = Object.assign(new ItemSearchResult(), { + hitHighlights: { + 'organization.legalName': [{ + value: 'Science' + }], + }, + indexableObject: + Object.assign(new Item(), { + bundles: observableOf({}), + entityType: 'OrgUnit', + metadata: { + 'dc.title': [ + { + language: 'en_US', + value: 'This is just another title' + } + ], + 'dc.contributor.author': [ + { + language: 'en_US', + value: 'Smith, Donald' + } + ], + 'dc.publisher': [ + { + language: 'en_US', + value: 'a publisher' + } + ], + 'dc.date.issued': [ + { + language: 'en_US', + value: '2015-06-26' + } + ], + 'dc.description.abstract': [ + { + language: 'en_US', + value: 'This is the abstract' + } + ], + 'organization.legalName': [ + { + value: 'Science' + } + ], + 'dspace.entity.type': [ + { + value: 'OrgUnit' + } + ] + } + }) +}); const environmentUseThumbs = { browseBy: { showThumbnails: true @@ -220,6 +329,30 @@ describe('ItemSearchResultListElementComponent', () => { }); }); + describe('When the item is Person and has title', () => { + beforeEach(() => { + publicationListElementComponent.object = mockPerson; + fixture.detectChanges(); + }); + + it('should show highlighted title', () => { + const titleField = fixture.debugElement.query(By.css('.item-list-title')); + expect(titleField.nativeNode.innerHTML).toEqual('Michel'); + }); + }); + + describe('When the item is orgUnit and has title', () => { + beforeEach(() => { + publicationListElementComponent.object = mockOrgUnit; + fixture.detectChanges(); + }); + + it('should show highlighted title', () => { + const titleField = fixture.debugElement.query(By.css('.item-list-title')); + expect(titleField.nativeNode.innerHTML).toEqual('Science'); + }); + }); + describe('When the item has no title', () => { beforeEach(() => { publicationListElementComponent.object = mockItemWithoutMetadata; From 6396e6a585b964d3c8ce0f111c9a7be3512be797 Mon Sep 17 00:00:00 2001 From: Tim Donohue Date: Wed, 11 Jan 2023 12:33:26 -0600 Subject: [PATCH 51/59] Add DataCite to i18n list of sources --- src/assets/i18n/en.json5 | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index d043d61ae5..d2bd425df0 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -3836,6 +3836,8 @@ "submission.import-external.source.crossref": "CrossRef", + "submission.import-external.source.datacite": "DataCite", + "submission.import-external.source.scielo": "SciELO", "submission.import-external.source.scopus": "Scopus", From 357525e68ac830b33062c70a73db28fc1478ab42 Mon Sep 17 00:00:00 2001 From: Michael Spalti Date: Mon, 9 Jan 2023 10:32:49 -0800 Subject: [PATCH 52/59] Ignore IP authentication method in login component. lint fix using enum Simplified assignment. --- src/app/shared/log-in/log-in.component.html | 2 +- src/app/shared/log-in/log-in.component.ts | 10 +++++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/app/shared/log-in/log-in.component.html b/src/app/shared/log-in/log-in.component.html index 6e4685a07b..36f7034f4d 100644 --- a/src/app/shared/log-in/log-in.component.html +++ b/src/app/shared/log-in/log-in.component.html @@ -1,6 +1,6 @@