diff --git a/src/app/+item-page/edit-item-page/item-relationships/edit-relationship/edit-relationship.component.html b/src/app/+item-page/edit-item-page/item-relationships/edit-relationship/edit-relationship.component.html index e25c3c204f..03040ce8e0 100644 --- a/src/app/+item-page/edit-item-page/item-relationships/edit-relationship/edit-relationship.component.html +++ b/src/app/+item-page/edit-item-page/item-relationships/edit-relationship/edit-relationship.component.html @@ -1,6 +1,6 @@
- +
diff --git a/src/app/+item-page/edit-item-page/item-relationships/edit-relationship/edit-relationship.component.spec.ts b/src/app/+item-page/edit-item-page/item-relationships/edit-relationship/edit-relationship.component.spec.ts index e98da94c9d..54fce0a68e 100644 --- a/src/app/+item-page/edit-item-page/item-relationships/edit-relationship/edit-relationship.component.spec.ts +++ b/src/app/+item-page/edit-item-page/item-relationships/edit-relationship/edit-relationship.component.spec.ts @@ -5,7 +5,6 @@ import { ObjectUpdatesService } from '../../../../core/data/object-updates/objec import { NO_ERRORS_SCHEMA } from '@angular/core'; import { EditRelationshipComponent } from './edit-relationship.component'; import { RelationshipType } from '../../../../core/shared/item-relationships/relationship-type.model'; -import { ResourceType } from '../../../../core/shared/resource-type'; import { Relationship } from '../../../../core/shared/item-relationships/relationship.model'; import { RemoteData } from '../../../../core/data/remote-data'; import { Item } from '../../../../core/shared/item.model'; diff --git a/src/app/+item-page/edit-item-page/item-relationships/edit-relationship/edit-relationship.component.ts b/src/app/+item-page/edit-item-page/item-relationships/edit-relationship/edit-relationship.component.ts index 497b06775a..302ebf68a7 100644 --- a/src/app/+item-page/edit-item-page/item-relationships/edit-relationship/edit-relationship.component.ts +++ b/src/app/+item-page/edit-item-page/item-relationships/edit-relationship/edit-relationship.component.ts @@ -4,7 +4,7 @@ import { cloneDeep } from 'lodash'; import { Item } from '../../../../core/shared/item.model'; import { ObjectUpdatesService } from '../../../../core/data/object-updates/object-updates.service'; import { FieldChangeType } from '../../../../core/data/object-updates/object-updates.actions'; -import { ItemViewMode } from '../../../../shared/items/item-type-decorator'; +import { ViewMode } from '../../../../core/shared/view-mode.model'; @Component({ // tslint:disable-next-line:component-selector @@ -31,7 +31,7 @@ export class EditRelationshipComponent implements OnChanges { /** * The view-mode we're currently on */ - viewMode = ItemViewMode.Element; + viewMode = ViewMode.ListElement; constructor(private objectUpdatesService: ObjectUpdatesService) { } diff --git a/src/app/+item-page/simple/field-components/specific-field/generic/generic-item-page-field.component.ts b/src/app/+item-page/simple/field-components/specific-field/generic/generic-item-page-field.component.ts index ee7d27a11f..3b8d261dcc 100644 --- a/src/app/+item-page/simple/field-components/specific-field/generic/generic-item-page-field.component.ts +++ b/src/app/+item-page/simple/field-components/specific-field/generic/generic-item-page-field.component.ts @@ -10,7 +10,7 @@ import { ItemPageFieldComponent } from '../item-page-field.component'; /** * This component can be used to represent metadata on a simple item page. * It is the most generic way of displaying metadata values - * It expects 4 parameters: The item, a seperator, the metadata keys and an i18n key + * It expects 4 parameters: The item, a separator, the metadata keys and an i18n key */ export class GenericItemPageFieldComponent extends ItemPageFieldComponent { diff --git a/src/app/+item-page/simple/field-components/specific-field/item-page-field.component.spec.ts b/src/app/+item-page/simple/field-components/specific-field/item-page-field.component.spec.ts index 1b7acb2e3b..6e5ed2c535 100644 --- a/src/app/+item-page/simple/field-components/specific-field/item-page-field.component.spec.ts +++ b/src/app/+item-page/simple/field-components/specific-field/item-page-field.component.spec.ts @@ -4,12 +4,9 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { Item } from '../../../../core/shared/item.model'; import { PaginatedList } from '../../../../core/data/paginated-list'; import { MockTranslateLoader } from '../../../../shared/mocks/mock-translate-loader'; -import { Observable } from 'rxjs'; import { PageInfo } from '../../../../core/shared/page-info.model'; -import { RemoteData } from '../../../../core/data/remote-data'; import { ItemPageFieldComponent } from './item-page-field.component'; import { MetadataValuesComponent } from '../../../field-components/metadata-values/metadata-values.component'; -import { of as observableOf } from 'rxjs'; import { MetadataMap, MetadataValue } from '../../../../core/shared/metadata.models'; import { createSuccessfulRemoteDataObject$ } from '../../../../shared/testing/utils'; diff --git a/src/app/+item-page/simple/item-page.component.html b/src/app/+item-page/simple/item-page.component.html index b6de496dc4..501e3e161e 100644 --- a/src/app/+item-page/simple/item-page.component.html +++ b/src/app/+item-page/simple/item-page.component.html @@ -1,7 +1,7 @@
- +
diff --git a/src/app/+item-page/simple/item-page.component.ts b/src/app/+item-page/simple/item-page.component.ts index 89d5977583..10deef23e4 100644 --- a/src/app/+item-page/simple/item-page.component.ts +++ b/src/app/+item-page/simple/item-page.component.ts @@ -1,21 +1,18 @@ - -import { mergeMap, filter, map, take, tap } from 'rxjs/operators'; +import { map } from 'rxjs/operators'; import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core'; import { ActivatedRoute, Router } from '@angular/router'; import { Observable } from 'rxjs'; import { ItemDataService } from '../../core/data/item-data.service'; import { RemoteData } from '../../core/data/remote-data'; -import { Bitstream } from '../../core/shared/bitstream.model'; import { Item } from '../../core/shared/item.model'; import { MetadataService } from '../../core/metadata/metadata.service'; import { fadeInOut } from '../../shared/animations/fade'; -import { hasValue } from '../../shared/empty.util'; import { redirectToPageNotFoundOn404 } from '../../core/shared/operators'; -import { ItemViewMode } from '../../shared/items/item-type-decorator'; +import { ViewMode } from '../../core/shared/view-mode.model'; /** * This component renders a simple item page. @@ -44,7 +41,7 @@ export class ItemPageComponent implements OnInit { /** * The view-mode we're currently on */ - viewMode = ItemViewMode.Full; + viewMode = ViewMode.StandalonePage; constructor( private route: ActivatedRoute, @@ -53,6 +50,9 @@ export class ItemPageComponent implements OnInit { private metadataService: MetadataService, ) { } + /** + * Initialize instance variables + */ ngOnInit(): void { this.itemRD$ = this.route.data.pipe( map((data) => data.item as RemoteData), diff --git a/src/app/+item-page/simple/item-types/publication/publication.component.html b/src/app/+item-page/simple/item-types/publication/publication.component.html index deac919072..3cd4d0aa69 100644 --- a/src/app/+item-page/simple/item-types/publication/publication.component.html +++ b/src/app/+item-page/simple/item-types/publication/publication.component.html @@ -1,72 +1,72 @@

- {{'publication.page.titleprefix' | translate}} + {{'publication.page.titleprefix' | translate}}

- + - - - - + + + - - -
- - + - - - - + + diff --git a/src/app/+item-page/simple/item-types/publication/publication.component.spec.ts b/src/app/+item-page/simple/item-types/publication/publication.component.spec.ts index eac23a9748..5b17f7bbd4 100644 --- a/src/app/+item-page/simple/item-types/publication/publication.component.spec.ts +++ b/src/app/+item-page/simple/item-types/publication/publication.component.spec.ts @@ -3,19 +3,16 @@ import { TranslateLoader, TranslateModule } from '@ngx-translate/core'; import { MockTranslateLoader } from '../../../../shared/mocks/mock-translate-loader'; import { GenericItemPageFieldComponent } from '../../field-components/specific-field/generic/generic-item-page-field.component'; import { TruncatePipe } from '../../../../shared/utils/truncate.pipe'; -import { ITEM } from '../../../../shared/items/switcher/item-type-switcher.component'; import { ItemDataService } from '../../../../core/data/item-data.service'; import { SearchFixedFilterService } from '../../../../+search-page/search-filters/search-filter/search-fixed-filter.service'; import { TruncatableService } from '../../../../shared/truncatable/truncatable.service'; import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA } from '@angular/core'; import { Item } from '../../../../core/shared/item.model'; -import { RemoteData } from '../../../../core/data/remote-data'; import { PaginatedList } from '../../../../core/data/paginated-list'; import { PageInfo } from '../../../../core/shared/page-info.model'; import { By } from '@angular/platform-browser'; import { createRelationshipsObservable } from '../shared/item.component.spec'; import { PublicationComponent } from './publication.component'; -import { of as observableOf } from 'rxjs'; import { MetadataMap } from '../../../../core/shared/metadata.models'; import { createSuccessfulRemoteDataObject$ } from '../../../../shared/testing/utils'; @@ -45,7 +42,6 @@ describe('PublicationComponent', () => { })], declarations: [PublicationComponent, GenericItemPageFieldComponent, TruncatePipe], providers: [ - {provide: ITEM, useValue: mockItem}, {provide: ItemDataService, useValue: {}}, {provide: SearchFixedFilterService, useValue: searchFixedFilterServiceStub}, {provide: TruncatableService, useValue: {}} @@ -60,6 +56,7 @@ describe('PublicationComponent', () => { beforeEach(async(() => { fixture = TestBed.createComponent(PublicationComponent); comp = fixture.componentInstance; + comp.object = mockItem; fixture.detectChanges(); })); diff --git a/src/app/+item-page/simple/item-types/publication/publication.component.ts b/src/app/+item-page/simple/item-types/publication/publication.component.ts index 9f0f2fe6ab..a8c7539e64 100644 --- a/src/app/+item-page/simple/item-types/publication/publication.component.ts +++ b/src/app/+item-page/simple/item-types/publication/publication.component.ts @@ -1,12 +1,15 @@ import { ChangeDetectionStrategy, Component } from '@angular/core'; -import { - DEFAULT_ITEM_TYPE, ItemViewMode, - rendersItemType -} from '../../../../shared/items/item-type-decorator'; import { ItemComponent } from '../shared/item.component'; +import { listableObjectComponent } from '../../../../shared/object-collection/shared/listable-object/listable-object.decorator'; +import { Item } from '../../../../core/shared/item.model'; +import { ViewMode } from '../../../../core/shared/view-mode.model'; -@rendersItemType('Publication', ItemViewMode.Full) -@rendersItemType(DEFAULT_ITEM_TYPE, ItemViewMode.Full) +/** + * Component that represents a publication Item page + */ + +@listableObjectComponent('Publication', ViewMode.StandalonePage) +@listableObjectComponent(Item, ViewMode.StandalonePage) @Component({ selector: 'ds-publication', styleUrls: ['./publication.component.scss'], diff --git a/src/app/+item-page/simple/item-types/shared/item.component.spec.ts b/src/app/+item-page/simple/item-types/shared/item.component.spec.ts index 41d05afd1b..add2fb1e17 100644 --- a/src/app/+item-page/simple/item-types/shared/item.component.spec.ts +++ b/src/app/+item-page/simple/item-types/shared/item.component.spec.ts @@ -7,17 +7,14 @@ import { ItemDataService } from '../../../../core/data/item-data.service'; import { TranslateLoader, TranslateModule } from '@ngx-translate/core'; import { MockTranslateLoader } from '../../../../shared/mocks/mock-translate-loader'; import { ChangeDetectionStrategy, DebugElement, NO_ERRORS_SCHEMA } from '@angular/core'; -import { ITEM } from '../../../../shared/items/switcher/item-type-switcher.component'; import { TruncatePipe } from '../../../../shared/utils/truncate.pipe'; import { isNotEmpty } from '../../../../shared/empty.util'; import { SearchFixedFilterService } from '../../../../+search-page/search-filters/search-filter/search-fixed-filter.service'; import { RelationshipType } from '../../../../core/shared/item-relationships/relationship-type.model'; import { PaginatedList } from '../../../../core/data/paginated-list'; -import { RemoteData } from '../../../../core/data/remote-data'; import { Relationship } from '../../../../core/shared/item-relationships/relationship.model'; import { PageInfo } from '../../../../core/shared/page-info.model'; import { ItemComponent } from './item.component'; -import { of as observableOf } from 'rxjs'; import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; import { VarDirective } from '../../../../shared/utils/var.directive'; import { Observable } from 'rxjs/internal/Observable'; @@ -56,7 +53,6 @@ export function getItemPageFieldsTest(mockItem: Item, component) { })], declarations: [component, GenericItemPageFieldComponent, TruncatePipe], providers: [ - {provide: ITEM, useValue: mockItem}, {provide: ItemDataService, useValue: {}}, {provide: SearchFixedFilterService, useValue: searchFixedFilterServiceStub}, {provide: TruncatableService, useValue: {}} @@ -71,6 +67,7 @@ export function getItemPageFieldsTest(mockItem: Item, component) { beforeEach(async(() => { fixture = TestBed.createComponent(component); comp = fixture.componentInstance; + comp.object = mockItem; fixture.detectChanges(); })); diff --git a/src/app/+item-page/simple/item-types/shared/item.component.ts b/src/app/+item-page/simple/item-types/shared/item.component.ts index ae3d660a4f..d4b0c8de89 100644 --- a/src/app/+item-page/simple/item-types/shared/item.component.ts +++ b/src/app/+item-page/simple/item-types/shared/item.component.ts @@ -1,6 +1,5 @@ -import { Component, Inject } from '@angular/core'; +import { Component, Inject, Input } from '@angular/core'; import { Item } from '../../../../core/shared/item.model'; -import { ITEM } from '../../../../shared/items/switcher/item-type-switcher.component'; @Component({ selector: 'ds-item', @@ -10,9 +9,5 @@ import { ITEM } from '../../../../shared/items/switcher/item-type-switcher.compo * A generic component for displaying metadata and relations of an item */ export class ItemComponent { - - constructor( - @Inject(ITEM) public item: Item - ) {} - + @Input() object: Item; } diff --git a/src/app/+item-page/simple/metadata-representation-list/metadata-representation-list.component.html b/src/app/+item-page/simple/metadata-representation-list/metadata-representation-list.component.html index e9d2364ca6..64f1184181 100644 --- a/src/app/+item-page/simple/metadata-representation-list/metadata-representation-list.component.html +++ b/src/app/+item-page/simple/metadata-representation-list/metadata-representation-list.component.html @@ -1,7 +1,7 @@ - - + + diff --git a/src/app/+item-page/simple/metadata-representation-list/metadata-representation-list.component.spec.ts b/src/app/+item-page/simple/metadata-representation-list/metadata-representation-list.component.spec.ts index 120e846523..7beabdceba 100644 --- a/src/app/+item-page/simple/metadata-representation-list/metadata-representation-list.component.spec.ts +++ b/src/app/+item-page/simple/metadata-representation-list/metadata-representation-list.component.spec.ts @@ -83,8 +83,8 @@ describe('MetadataRepresentationListComponent', () => { fixture.detectChanges(); })); - it('should load 2 item-type-switcher components', () => { - const fields = fixture.debugElement.queryAll(By.css('ds-item-type-switcher')); + it('should load 2 ds-metadata-representation-loader components', () => { + const fields = fixture.debugElement.queryAll(By.css('ds-metadata-representation-loader')); expect(fields.length).toBe(2); }); diff --git a/src/app/+item-page/simple/metadata-representation-list/metadata-representation-list.component.ts b/src/app/+item-page/simple/metadata-representation-list/metadata-representation-list.component.ts index 521a93523d..b58290d87c 100644 --- a/src/app/+item-page/simple/metadata-representation-list/metadata-representation-list.component.ts +++ b/src/app/+item-page/simple/metadata-representation-list/metadata-representation-list.component.ts @@ -1,11 +1,10 @@ import { Component, Input, OnInit } from '@angular/core'; import { MetadataRepresentation } from '../../../core/shared/metadata-representation/metadata-representation.model'; -import { ItemViewMode } from '../../../shared/items/item-type-decorator'; import { Observable } from 'rxjs/internal/Observable'; import { RemoteData } from '../../../core/data/remote-data'; import { RelationshipService } from '../../../core/data/relationship.service'; import { Item } from '../../../core/shared/item.model'; -import { zip as observableZip, combineLatest as observableCombineLatest, of as observableOf } from 'rxjs'; +import { combineLatest as observableCombineLatest, of as observableOf, zip as observableZip } from 'rxjs'; import { MetadataValue } from '../../../core/shared/metadata.models'; import { MetadatumRepresentation } from '../../../core/shared/metadata-representation/metadatum/metadatum-representation.model'; import { filter, map, switchMap } from 'rxjs/operators'; @@ -56,12 +55,6 @@ export class MetadataRepresentationListComponent implements OnInit { */ representations$: Observable; - /** - * The view-mode we're currently on - * @type {ElementViewMode} - */ - viewMode = ItemViewMode.Metadata; - /** * The originally provided limit * Used for resetting the limit to the original value when collapsing the list diff --git a/src/app/+item-page/simple/related-items/related-items-component.ts b/src/app/+item-page/simple/related-items/related-items-component.ts index 5b4376bab0..9cbfd2c28d 100644 --- a/src/app/+item-page/simple/related-items/related-items-component.ts +++ b/src/app/+item-page/simple/related-items/related-items-component.ts @@ -1,14 +1,12 @@ import { Component, HostBinding, Input, OnDestroy, OnInit } from '@angular/core'; import { Item } from '../../../core/shared/item.model'; -import { ItemViewMode } from '../../../shared/items/item-type-decorator'; import { Observable } from 'rxjs/internal/Observable'; import { RemoteData } from '../../../core/data/remote-data'; import { PaginatedList } from '../../../core/data/paginated-list'; import { RelationshipService } from '../../../core/data/relationship.service'; import { FindAllOptions } from '../../../core/data/request.models'; -import { getRemoteDataPayload, getSucceededRemoteData } from '../../../core/shared/operators'; -import { hasNoValue, hasValueOperator } from '../../../shared/empty.util'; import { Subscription } from 'rxjs/internal/Subscription'; +import { ViewMode } from '../../../core/shared/view-mode.model'; @Component({ selector: 'ds-related-items', @@ -61,7 +59,7 @@ export class RelatedItemsComponent implements OnInit, OnDestroy { * The view-mode we're currently on * @type {ElementViewMode} */ - viewMode = ItemViewMode.Element; + viewMode = ViewMode.ListElement; /** * Whether or not the list is currently expanded to show all related items diff --git a/src/app/+item-page/simple/related-items/related-items.component.html b/src/app/+item-page/simple/related-items/related-items.component.html index a4baee9825..bb6c2afdc6 100644 --- a/src/app/+item-page/simple/related-items/related-items.component.html +++ b/src/app/+item-page/simple/related-items/related-items.component.html @@ -1,7 +1,7 @@ - - + diff --git a/src/app/+item-page/simple/related-items/related-items.component.spec.ts b/src/app/+item-page/simple/related-items/related-items.component.spec.ts index 6637091f02..1e76f1173e 100644 --- a/src/app/+item-page/simple/related-items/related-items.component.spec.ts +++ b/src/app/+item-page/simple/related-items/related-items.component.spec.ts @@ -61,7 +61,7 @@ describe('RelatedItemsComponent', () => { })); it(`should load ${mockItems.length} item-type-switcher components`, () => { - const fields = fixture.debugElement.queryAll(By.css('ds-item-type-switcher')); + const fields = fixture.debugElement.queryAll(By.css('ds-listable-object-component-loader')); expect(fields.length).toBe(mockItems.length); }); diff --git a/src/app/+my-dspace-page/my-dspace-new-submission/my-dspace-new-submission.component.ts b/src/app/+my-dspace-page/my-dspace-new-submission/my-dspace-new-submission.component.ts index 938a1ec899..76853db924 100644 --- a/src/app/+my-dspace-page/my-dspace-new-submission/my-dspace-new-submission.component.ts +++ b/src/app/+my-dspace-page/my-dspace-new-submission/my-dspace-new-submission.component.ts @@ -7,7 +7,6 @@ import { TranslateService } from '@ngx-translate/core'; import { SubmissionState } from '../../submission/submission.reducers'; import { AuthService } from '../../core/auth/auth.service'; -import { MyDSpaceResult } from '../my-dspace-result.model'; import { DSpaceObject } from '../../core/shared/dspace-object.model'; import { NotificationsService } from '../../shared/notifications/notifications.service'; import { NotificationOptions } from '../../shared/notifications/models/notification-options.model'; @@ -15,6 +14,7 @@ import { UploaderOptions } from '../../shared/uploader/uploader-options.model'; import { HALEndpointService } from '../../core/shared/hal-endpoint.service'; import { NotificationType } from '../../shared/notifications/models/notification-type'; import { hasValue } from '../../shared/empty.util'; +import { SearchResult } from '../../+search-page/search-result.model'; /** * This component represents the whole mydspace page header @@ -25,7 +25,10 @@ import { hasValue } from '../../shared/empty.util'; templateUrl: './my-dspace-new-submission.component.html' }) export class MyDSpaceNewSubmissionComponent implements OnDestroy, OnInit { - @Output() uploadEnd = new EventEmitter>>(); + /** + * Output that emits the workspace item when the upload has completed + */ + @Output() uploadEnd = new EventEmitter>>(); /** * The UploaderOptions object diff --git a/src/app/+my-dspace-page/my-dspace-page.component.html b/src/app/+my-dspace-page/my-dspace-page.component.html index 4c691028fc..e6d1a5c80d 100644 --- a/src/app/+my-dspace-page/my-dspace-page.component.html +++ b/src/app/+my-dspace-page/my-dspace-page.component.html @@ -39,7 +39,8 @@
+ [searchConfig]="searchOptions$ | async" + [context]="context$ | async">
diff --git a/src/app/+my-dspace-page/my-dspace-page.component.ts b/src/app/+my-dspace-page/my-dspace-page.component.ts index 251bf50bd1..3600a10d22 100644 --- a/src/app/+my-dspace-page/my-dspace-page.component.ts +++ b/src/app/+my-dspace-page/my-dspace-page.component.ts @@ -8,7 +8,7 @@ import { } from '@angular/core'; import { BehaviorSubject, Observable, Subscription } from 'rxjs'; -import { switchMap, tap, } from 'rxjs/operators'; +import { map, switchMap, tap, } from 'rxjs/operators'; import { PaginatedList } from '../core/data/paginated-list'; import { RemoteData } from '../core/data/remote-data'; @@ -20,7 +20,6 @@ import { SearchService } from '../+search-page/search-service/search.service'; import { SearchSidebarService } from '../+search-page/search-sidebar/search-sidebar.service'; import { hasValue } from '../shared/empty.util'; import { getSucceededRemoteData } from '../core/shared/operators'; -import { MyDSpaceResult } from './my-dspace-result.model'; import { MyDSpaceResponseParsingService } from '../core/data/mydspace-response-parsing.service'; import { SearchConfigurationOption } from '../+search-page/search-switch-configuration/search-configuration-option.model'; import { RoleType } from '../core/roles/role-types'; @@ -28,6 +27,8 @@ import { SearchConfigurationService } from '../+search-page/search-service/searc import { MyDSpaceConfigurationService } from './my-dspace-configuration.service'; import { ViewMode } from '../core/shared/view-mode.model'; import { MyDSpaceRequest } from '../core/data/request.models'; +import { SearchResult } from '../+search-page/search-result.model'; +import { Context } from '../core/shared/context.model'; export const MYDSPACE_ROUTE = '/mydspace'; export const SEARCH_CONFIG_SERVICE: InjectionToken = new InjectionToken('searchConfigurationService'); @@ -63,7 +64,7 @@ export class MyDSpacePageComponent implements OnInit { /** * The current search results */ - resultsRD$: BehaviorSubject>>> = new BehaviorSubject(null); + resultsRD$: BehaviorSubject>>> = new BehaviorSubject(null); /** * The current paginated search options @@ -93,7 +94,12 @@ export class MyDSpacePageComponent implements OnInit { /** * List of available view mode */ - viewModeList = [ViewMode.List, ViewMode.Detail]; + viewModeList = [ViewMode.ListElement, ViewMode.DetailedListElement]; + + /** + * The current context of this page: workspace or workflow + */ + context$: Observable; constructor(private service: SearchService, private sidebarService: SearchSidebarService, @@ -111,6 +117,9 @@ export class MyDSpacePageComponent implements OnInit { * * Listen to changes in the scope * If something changes, update the list of scopes for the dropdown + * + * Listen to changes in the configuration + * If something changes, update the current context */ ngOnInit(): void { this.configurationList$ = this.searchConfigService.getAvailableConfigurationOptions(); @@ -126,6 +135,17 @@ export class MyDSpacePageComponent implements OnInit { switchMap((scopeId) => this.service.getScopes(scopeId)) ); + this.context$ = this.searchConfigService.getCurrentConfiguration('workspace') + .pipe( + map((configuration: string) => { + if (configuration === 'workspace') { + return Context.Workspace + } else { + return Context.Workflow + } + }) + ); + } /** diff --git a/src/app/+my-dspace-page/my-dspace-page.module.ts b/src/app/+my-dspace-page/my-dspace-page.module.ts index 4b8cf37b7a..be14aebdea 100644 --- a/src/app/+my-dspace-page/my-dspace-page.module.ts +++ b/src/app/+my-dspace-page/my-dspace-page.module.ts @@ -7,19 +7,20 @@ import { MyDspacePageRoutingModule } from './my-dspace-page-routing.module'; import { MyDSpacePageComponent } from './my-dspace-page.component'; import { SearchPageModule } from '../+search-page/search-page.module'; import { MyDSpaceResultsComponent } from './my-dspace-results/my-dspace-results.component'; -import { WorkspaceitemMyDSpaceResultListElementComponent } from '../shared/object-list/my-dspace-result-list-element/workspaceitem-my-dspace-result/workspaceitem-my-dspace-result-list-element.component'; -import { ItemMyDSpaceResultListElementComponent } from '../shared/object-list/my-dspace-result-list-element/item-my-dspace-result/item-my-dspace-result-list-element.component'; -import { WorkflowitemMyDSpaceResultListElementComponent } from '../shared/object-list/my-dspace-result-list-element/workflowitem-my-dspace-result/workflowitem-my-dspace-result-list-element.component'; -import { ClaimedMyDSpaceResultListElementComponent } from '../shared/object-list/my-dspace-result-list-element/claimed-my-dspace-result/claimed-my-dspace-result-list-element.component'; -import { PoolMyDSpaceResultListElementComponent } from '../shared/object-list/my-dspace-result-list-element/pool-my-dspace-result/pool-my-dspace-result-list-element.component'; +import { WorkspaceItemSearchResultListElementComponent } from '../shared/object-list/my-dspace-result-list-element/workspace-item-search-result/workspace-item-search-result-list-element.component'; +import { ClaimedSearchResultListElementComponent } from '../shared/object-list/my-dspace-result-list-element/claimed-search-result/claimed-search-result-list-element.component'; +import { PoolSearchResultListElementComponent } from '../shared/object-list/my-dspace-result-list-element/pool-search-result/pool-search-result-list-element.component'; import { MyDSpaceNewSubmissionComponent } from './my-dspace-new-submission/my-dspace-new-submission.component'; -import { ItemMyDSpaceResultDetailElementComponent } from '../shared/object-detail/my-dspace-result-detail-element/item-my-dspace-result/item-my-dspace-result-detail-element.component'; -import { WorkspaceitemMyDSpaceResultDetailElementComponent } from '../shared/object-detail/my-dspace-result-detail-element/workspaceitem-my-dspace-result/workspaceitem-my-dspace-result-detail-element.component'; -import { WorkflowitemMyDSpaceResultDetailElementComponent } from '../shared/object-detail/my-dspace-result-detail-element/workflowitem-my-dspace-result/workflowitem-my-dspace-result-detail-element.component'; -import { ClaimedMyDSpaceResultDetailElementComponent } from '../shared/object-detail/my-dspace-result-detail-element/claimed-my-dspace-result/claimed-my-dspace-result-detail-element.component'; -import { PoolMyDSpaceResultDetailElementComponent } from '../shared/object-detail/my-dspace-result-detail-element/pool-my-dspace-result/pool-my-dspace-result-detail-lement.component'; +import { ItemSearchResultDetailElementComponent } from '../shared/object-detail/my-dspace-result-detail-element/item-search-result/item-search-result-detail-element.component'; +import { WorkspaceItemSearchResultDetailElementComponent } from '../shared/object-detail/my-dspace-result-detail-element/workspace-item-search-result/workspace-item-search-result-detail-element.component'; +import { WorkflowItemSearchResultDetailElementComponent } from '../shared/object-detail/my-dspace-result-detail-element/workflow-item-search-result/workflow-item-search-result-detail-element.component'; +import { ClaimedTaskSearchResultDetailElementComponent } from '../shared/object-detail/my-dspace-result-detail-element/claimed-task-search-result/claimed-task-search-result-detail-element.component'; import { MyDSpaceGuard } from './my-dspace.guard'; import { MyDSpaceConfigurationService } from './my-dspace-configuration.service'; +import { SearchResultListElementComponent } from '../shared/object-list/search-result-list-element/search-result-list-element.component'; +import { ItemSearchResultListElementSubmissionComponent } from '../shared/object-list/my-dspace-result-list-element/item-search-result/item-search-result-list-element-submission.component'; +import { WorkflowItemSearchResultListElementComponent } from '../shared/object-list/my-dspace-result-list-element/workflow-item-search-result/workflow-item-search-result-list-element.component'; +import { PoolSearchResultDetailElementComponent } from '../shared/object-detail/my-dspace-result-detail-element/pool-search-result/pool-search-result-detail-element.component'; @NgModule({ imports: [ @@ -31,33 +32,34 @@ import { MyDSpaceConfigurationService } from './my-dspace-configuration.service' declarations: [ MyDSpacePageComponent, MyDSpaceResultsComponent, - ItemMyDSpaceResultListElementComponent, - WorkspaceitemMyDSpaceResultListElementComponent, - WorkflowitemMyDSpaceResultListElementComponent, - ClaimedMyDSpaceResultListElementComponent, - PoolMyDSpaceResultListElementComponent, - ItemMyDSpaceResultDetailElementComponent, - WorkspaceitemMyDSpaceResultDetailElementComponent, - WorkflowitemMyDSpaceResultDetailElementComponent, - ClaimedMyDSpaceResultDetailElementComponent, - PoolMyDSpaceResultDetailElementComponent, - MyDSpaceNewSubmissionComponent + WorkspaceItemSearchResultListElementComponent, + WorkflowItemSearchResultListElementComponent, + ClaimedSearchResultListElementComponent, + PoolSearchResultListElementComponent, + ItemSearchResultDetailElementComponent, + WorkspaceItemSearchResultDetailElementComponent, + WorkflowItemSearchResultDetailElementComponent, + ClaimedTaskSearchResultDetailElementComponent, + PoolSearchResultDetailElementComponent, + MyDSpaceNewSubmissionComponent, + ItemSearchResultListElementSubmissionComponent ], providers: [ MyDSpaceGuard, MyDSpaceConfigurationService ], entryComponents: [ - ItemMyDSpaceResultListElementComponent, - WorkspaceitemMyDSpaceResultListElementComponent, - WorkflowitemMyDSpaceResultListElementComponent, - ClaimedMyDSpaceResultListElementComponent, - PoolMyDSpaceResultListElementComponent, - ItemMyDSpaceResultDetailElementComponent, - WorkspaceitemMyDSpaceResultDetailElementComponent, - WorkflowitemMyDSpaceResultDetailElementComponent, - ClaimedMyDSpaceResultDetailElementComponent, - PoolMyDSpaceResultDetailElementComponent + SearchResultListElementComponent, + WorkspaceItemSearchResultListElementComponent, + WorkflowItemSearchResultListElementComponent, + ClaimedSearchResultListElementComponent, + PoolSearchResultListElementComponent, + ItemSearchResultDetailElementComponent, + WorkspaceItemSearchResultDetailElementComponent, + WorkflowItemSearchResultDetailElementComponent, + ClaimedTaskSearchResultDetailElementComponent, + PoolSearchResultDetailElementComponent, + ItemSearchResultListElementSubmissionComponent ] }) diff --git a/src/app/+my-dspace-page/my-dspace-result.model.ts b/src/app/+my-dspace-page/my-dspace-result.model.ts deleted file mode 100644 index d300ed0bc8..0000000000 --- a/src/app/+my-dspace-page/my-dspace-result.model.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { DSpaceObject } from '../core/shared/dspace-object.model'; -import { MetadataMap } from '../core/shared/metadata.models'; -import { ListableObject } from '../shared/object-collection/shared/listable-object.model'; - -/** - * Represents a search result object of a certain () DSpaceObject - */ -export class MyDSpaceResult implements ListableObject { - /** - * The DSpaceObject that was found - */ - indexableObject: T; - - /** - * The metadata that was used to find this item, hithighlighted - */ - hitHighlights: MetadataMap; - -} diff --git a/src/app/+my-dspace-page/my-dspace-results/my-dspace-results.component.html b/src/app/+my-dspace-page/my-dspace-results/my-dspace-results.component.html index 132a0d2204..63eb0ff9a7 100644 --- a/src/app/+my-dspace-page/my-dspace-results/my-dspace-results.component.html +++ b/src/app/+my-dspace-page/my-dspace-results/my-dspace-results.component.html @@ -4,7 +4,8 @@ [hasBorder]="hasBorder" [sortConfig]="searchConfig.sort" [objects]="searchResults" - [hideGear]="true"> + [hideGear]="true" + [context]="context">
diff --git a/src/app/+my-dspace-page/my-dspace-results/my-dspace-results.component.ts b/src/app/+my-dspace-page/my-dspace-results/my-dspace-results.component.ts index 3a16def9c1..91c206fc79 100644 --- a/src/app/+my-dspace-page/my-dspace-results/my-dspace-results.component.ts +++ b/src/app/+my-dspace-page/my-dspace-results/my-dspace-results.component.ts @@ -1,13 +1,13 @@ import { Component, Input } from '@angular/core'; - import { RemoteData } from '../../core/data/remote-data'; import { DSpaceObject } from '../../core/shared/dspace-object.model'; import { fadeIn, fadeInOut } from '../../shared/animations/fade'; -import { MyDSpaceResult } from '../my-dspace-result.model'; import { SearchOptions } from '../../+search-page/search-options.model'; import { PaginatedList } from '../../core/data/paginated-list'; import { ViewMode } from '../../core/shared/view-mode.model'; import { isEmpty } from '../../shared/empty.util'; +import { SearchResult } from '../../+search-page/search-result.model'; +import { Context } from '../../core/shared/context.model'; /** * Component that represents all results for mydspace page @@ -25,7 +25,7 @@ export class MyDSpaceResultsComponent { /** * The actual search result objects */ - @Input() searchResults: RemoteData>>; + @Input() searchResults: RemoteData>>; /** * The current configuration of the search @@ -37,6 +37,10 @@ export class MyDSpaceResultsComponent { */ @Input() viewMode: ViewMode; + /** + * The current context for the search results + */ + @Input() context: Context; /** * A boolean representing if search results entry are separated by a line */ diff --git a/src/app/+search-page/normalized-search-result.model.ts b/src/app/+search-page/normalized-search-result.model.ts index abb5f21250..8b1c015fef 100644 --- a/src/app/+search-page/normalized-search-result.model.ts +++ b/src/app/+search-page/normalized-search-result.model.ts @@ -1,13 +1,12 @@ import { autoserialize, inheritSerialization } from 'cerialize'; import { MetadataMap } from '../core/shared/metadata.models'; -import { ListableObject } from '../shared/object-collection/shared/listable-object.model'; import { NormalizedObject } from '../core/cache/models/normalized-object.model'; /** * Represents a normalized version of a search result object of a certain DSpaceObject */ @inheritSerialization(NormalizedObject) -export class NormalizedSearchResult implements ListableObject { +export class NormalizedSearchResult { /** * The UUID of the DSpaceObject that was found */ @@ -19,5 +18,4 @@ export class NormalizedSearchResult implements ListableObject { */ @autoserialize hitHighlights: MetadataMap; - } diff --git a/src/app/+search-page/search-filters/search-filters.component.ts b/src/app/+search-page/search-filters/search-filters.component.ts index 9d0dfceb15..69bbb6234b 100644 --- a/src/app/+search-page/search-filters/search-filters.component.ts +++ b/src/app/+search-page/search-filters/search-filters.component.ts @@ -71,7 +71,7 @@ export class SearchFiltersComponent implements OnInit { /** * @returns {string} The base path to the search page, or the current page when inPlaceSearch is true */ - private getSearchLink(): string { + getSearchLink(): string { if (this.inPlaceSearch) { return './'; } diff --git a/src/app/+search-page/search-options.model.ts b/src/app/+search-page/search-options.model.ts index 2b18854e1e..4117c13347 100644 --- a/src/app/+search-page/search-options.model.ts +++ b/src/app/+search-page/search-options.model.ts @@ -3,14 +3,14 @@ import { URLCombiner } from '../core/url-combiner/url-combiner'; import 'core-js/library/fn/object/entries'; import { SearchFilter } from './search-filter.model'; import { DSpaceObjectType } from '../core/shared/dspace-object-type.model'; -import { SetViewMode } from '../shared/view-mode'; +import { ViewMode } from '../core/shared/view-mode.model'; /** * This model class represents all parameters needed to request information about a certain search request */ export class SearchOptions { configuration?: string; - view?: SetViewMode = SetViewMode.List; + view?: ViewMode = ViewMode.ListElement; scope?: string; query?: string; dsoType?: DSpaceObjectType; diff --git a/src/app/+search-page/search-page.module.ts b/src/app/+search-page/search-page.module.ts index 6ca449460b..f4c665d06e 100644 --- a/src/app/+search-page/search-page.module.ts +++ b/src/app/+search-page/search-page.module.ts @@ -5,7 +5,6 @@ import { SharedModule } from '../shared/shared.module'; import { SearchPageRoutingModule } from './search-page-routing.module'; import { SearchPageComponent } from './search-page.component'; import { SearchResultsComponent } from './search-results/search-results.component'; -import { ItemSearchResultGridElementComponent } from '../shared/object-grid/search-result-grid-element/item-search-result/item-search-result-grid-element.component'; import { CommunitySearchResultGridElementComponent } from '../shared/object-grid/search-result-grid-element/community-search-result/community-search-result-grid-element.component' import { CollectionSearchResultGridElementComponent } from '../shared/object-grid/search-result-grid-element/collection-search-result/collection-search-result-grid-element.component'; import { SearchSidebarComponent } from './search-sidebar/search-sidebar.component'; @@ -44,9 +43,6 @@ const components = [ SearchResultsComponent, SearchSidebarComponent, SearchSettingsComponent, - ItemSearchResultGridElementComponent, - CollectionSearchResultGridElementComponent, - CommunitySearchResultGridElementComponent, SearchFiltersComponent, SearchFilterComponent, SearchFacetFilterComponent, @@ -84,9 +80,6 @@ const components = [ SearchConfigurationService ], entryComponents: [ - ItemSearchResultGridElementComponent, - CollectionSearchResultGridElementComponent, - CommunitySearchResultGridElementComponent, SearchFacetFilterComponent, SearchRangeFilterComponent, SearchTextFilterComponent, diff --git a/src/app/+search-page/search-result.model.ts b/src/app/+search-page/search-result.model.ts index 0354edbc6b..95359209d9 100644 --- a/src/app/+search-page/search-result.model.ts +++ b/src/app/+search-page/search-result.model.ts @@ -1,6 +1,7 @@ import { DSpaceObject } from '../core/shared/dspace-object.model'; import { MetadataMap } from '../core/shared/metadata.models'; import { ListableObject } from '../shared/object-collection/shared/listable-object.model'; +import { GenericConstructor } from '../core/shared/generic-constructor'; /** * Represents a search result object of a certain () DSpaceObject @@ -16,4 +17,10 @@ export class SearchResult implements ListableObject { */ hitHighlights: MetadataMap; + /** + * Method that returns as which type of object this object should be rendered + */ + getRenderTypes(): Array> { + return [this.constructor as GenericConstructor]; + } } diff --git a/src/app/+search-page/search-results/search-results.component.html b/src/app/+search-page/search-results/search-results.component.html index 5a1e89858b..c08a4f023f 100644 --- a/src/app/+search-page/search-results/search-results.component.html +++ b/src/app/+search-page/search-results/search-results.component.html @@ -4,6 +4,7 @@ [config]="searchConfig.pagination" [sortConfig]="searchConfig.sort" [objects]="searchResults" + [linkType]="linkType" [hideGear]="true">
diff --git a/src/app/+search-page/search-results/search-results.component.ts b/src/app/+search-page/search-results/search-results.component.ts index 0ad1fd46bf..24c973e296 100644 --- a/src/app/+search-page/search-results/search-results.component.ts +++ b/src/app/+search-page/search-results/search-results.component.ts @@ -2,12 +2,13 @@ import { Component, Input } from '@angular/core'; import { RemoteData } from '../../core/data/remote-data'; import { DSpaceObject } from '../../core/shared/dspace-object.model'; import { fadeIn, fadeInOut } from '../../shared/animations/fade'; -import { SetViewMode } from '../../shared/view-mode'; import { SearchOptions } from '../search-options.model'; import { SearchResult } from '../search-result.model'; import { PaginatedList } from '../../core/data/paginated-list'; import { hasNoValue, isNotEmpty } from '../../shared/empty.util'; import { SortOptions } from '../../core/cache/models/sort-options.model'; +import { ViewMode } from '../../core/shared/view-mode.model'; +import { CollectionElementLinkType } from '../../shared/object-collection/collection-element-link.type'; @Component({ selector: 'ds-search-results', @@ -24,6 +25,11 @@ import { SortOptions } from '../../core/cache/models/sort-options.model'; export class SearchResultsComponent { hasNoValue = hasNoValue; + /** + * The link type of the listed search results + */ + @Input() linkType: CollectionElementLinkType; + /** * The actual search result objects */ @@ -42,7 +48,7 @@ export class SearchResultsComponent { /** * The current view-mode of the list */ - @Input() viewMode: SetViewMode; + @Input() viewMode: ViewMode; /** * An optional configuration to filter the result on one type diff --git a/src/app/+search-page/search-service/search-result-element-decorator.ts b/src/app/+search-page/search-service/search-result-element-decorator.ts index e804a5d8ee..62887387c5 100644 --- a/src/app/+search-page/search-service/search-result-element-decorator.ts +++ b/src/app/+search-page/search-service/search-result-element-decorator.ts @@ -12,19 +12,12 @@ const searchResultMap = new Map(); * @param {GenericConstructor} domainConstructor The constructor of the DSpaceObject * @returns Decorator function that performs the actual mapping on initialization of the component */ -export function searchResultFor(domainConstructor: GenericConstructor, configuration: string = null) { +export function searchResultFor(domainConstructor: GenericConstructor) { return function decorator(searchResult: any) { if (!searchResult) { return; } - if (isNull(configuration)) { - searchResultMap.set(domainConstructor, searchResult); - } else { - if (!searchResultMap.get(configuration)) { - searchResultMap.set(configuration, new Map()); - } - searchResultMap.get(configuration).set(domainConstructor, searchResult); - } + searchResultMap.set(domainConstructor, searchResult); }; } @@ -33,10 +26,6 @@ export function searchResultFor(domainConstructor: GenericConstructor} domainConstructor The DSpaceObject's constructor for which the search result component is requested * @returns The component's constructor that matches the given DSpaceObject */ -export function getSearchResultFor(domainConstructor: GenericConstructor, configuration: string = null) { - if (isNull(configuration) || configuration === 'default' || hasNoValue(searchResultMap.get(configuration))) { +export function getSearchResultFor(domainConstructor: GenericConstructor) { return searchResultMap.get(domainConstructor); - } else { - return searchResultMap.get(configuration).get(domainConstructor); - } } diff --git a/src/app/+search-page/search-service/search.service.spec.ts b/src/app/+search-page/search-service/search.service.spec.ts index 798670a0e0..4f91dde312 100644 --- a/src/app/+search-page/search-service/search.service.spec.ts +++ b/src/app/+search-page/search-service/search.service.spec.ts @@ -5,9 +5,6 @@ import { CommonModule } from '@angular/common'; import { Component } from '@angular/core'; import { SearchService } from './search.service'; -import { ItemDataService } from './../../core/data/item-data.service'; -import { SetViewMode } from '../../shared/view-mode'; -import { GLOBAL_CONFIG } from '../../../config'; import { RemoteDataBuildService } from '../../core/cache/builders/remote-data-build.service'; import { Router, UrlTree } from '@angular/router'; import { RequestService } from '../../core/data/request.service'; @@ -66,7 +63,7 @@ describe('SearchService', () => { it('should return list view mode', () => { searchService.getViewMode().subscribe((viewMode) => { - expect(viewMode).toBe(ViewMode.List); + expect(viewMode).toBe(ViewMode.ListElement); }); }); }); @@ -125,38 +122,38 @@ describe('SearchService', () => { }); it('should call the navigate method on the Router with view mode list parameter as a parameter when setViewMode is called', () => { - searchService.setViewMode(ViewMode.List); + searchService.setViewMode(ViewMode.ListElement); expect(router.navigate).toHaveBeenCalledWith(['/search'], { - queryParams: { view: ViewMode.List, page: 1 }, + queryParams: { view: ViewMode.ListElement, page: 1 }, queryParamsHandling: 'merge' }); }); it('should call the navigate method on the Router with view mode grid parameter as a parameter when setViewMode is called', () => { - searchService.setViewMode(ViewMode.Grid); + searchService.setViewMode(ViewMode.GridElement); expect(router.navigate).toHaveBeenCalledWith(['/search'], { - queryParams: { view: ViewMode.Grid, page: 1 }, + queryParams: { view: ViewMode.GridElement, page: 1 }, queryParamsHandling: 'merge' }); }); it('should return ViewMode.List when the viewMode is set to ViewMode.List in the ActivatedRoute', () => { - let viewMode = ViewMode.Grid; + let viewMode = ViewMode.GridElement; spyOn(routeService, 'getQueryParamMap').and.returnValue(observableOf(new Map([ - [ 'view', ViewMode.List ], + [ 'view', ViewMode.ListElement ], ]))); searchService.getViewMode().subscribe((mode) => viewMode = mode); - expect(viewMode).toEqual(ViewMode.List); + expect(viewMode).toEqual(ViewMode.ListElement); }); it('should return ViewMode.Grid when the viewMode is set to ViewMode.Grid in the ActivatedRoute', () => { - let viewMode = ViewMode.List; + let viewMode = ViewMode.ListElement; spyOn(routeService, 'getQueryParamMap').and.returnValue(observableOf(new Map([ - [ 'view', ViewMode.Grid ], + [ 'view', ViewMode.GridElement ], ]))); searchService.getViewMode().subscribe((mode) => viewMode = mode); - expect(viewMode).toEqual(ViewMode.Grid); + expect(viewMode).toEqual(ViewMode.GridElement); }); describe('when search is called', () => { diff --git a/src/app/+search-page/search-service/search.service.ts b/src/app/+search-page/search-service/search.service.ts index bedae84eaa..22a1aba637 100644 --- a/src/app/+search-page/search-service/search.service.ts +++ b/src/app/+search-page/search-service/search.service.ts @@ -160,7 +160,7 @@ export class SearchService implements OnDestroy { let co = DSpaceObject; if (dsos.payload[index]) { const constructor: GenericConstructor = dsos.payload[index].constructor as GenericConstructor; - co = getSearchResultFor(constructor, searchOptions.configuration); + co = getSearchResultFor(constructor); return Object.assign(new co(), object, { indexableObject: dsos.payload[index] }); @@ -341,7 +341,7 @@ export class SearchService implements OnDestroy { if (isNotEmpty(params.get('view')) && hasValue(params.get('view'))) { return params.get('view'); } else { - return ViewMode.List; + return ViewMode.ListElement; } })); } @@ -354,7 +354,7 @@ export class SearchService implements OnDestroy { this.routeService.getQueryParameterValue('pageSize').pipe(first()) .subscribe((pageSize) => { let queryParams = { view: viewMode, page: 1 }; - if (viewMode === ViewMode.Detail) { + if (viewMode === ViewMode.DetailedListElement) { queryParams = Object.assign(queryParams, {pageSize: '1'}); } else if (pageSize === '1') { queryParams = Object.assign(queryParams, {pageSize: '10'}); diff --git a/src/app/core/eperson/models/normalized-eperson.model.ts b/src/app/core/eperson/models/normalized-eperson.model.ts index bf644a83ef..9a3bf4c246 100644 --- a/src/app/core/eperson/models/normalized-eperson.model.ts +++ b/src/app/core/eperson/models/normalized-eperson.model.ts @@ -1,7 +1,6 @@ import { autoserialize, deserialize, inheritSerialization } from 'cerialize'; import { CacheableObject } from '../../cache/object-cache.reducer'; -import { ListableObject } from '../../../shared/object-collection/shared/listable-object.model'; import { NormalizedDSpaceObject } from '../../cache/models/normalized-dspace-object.model'; import { EPerson } from './eperson.model'; import { mapsTo, relationship } from '../../cache/builders/build-decorators'; @@ -9,7 +8,7 @@ import { Group } from './group.model'; @mapsTo(EPerson) @inheritSerialization(NormalizedDSpaceObject) -export class NormalizedEPerson extends NormalizedDSpaceObject implements CacheableObject, ListableObject { +export class NormalizedEPerson extends NormalizedDSpaceObject implements CacheableObject { /** * A string representing the unique handle of this EPerson */ diff --git a/src/app/core/eperson/models/normalized-group.model.ts b/src/app/core/eperson/models/normalized-group.model.ts index 329ffb8adf..72b4e7b1a4 100644 --- a/src/app/core/eperson/models/normalized-group.model.ts +++ b/src/app/core/eperson/models/normalized-group.model.ts @@ -1,14 +1,13 @@ import { autoserialize, deserialize, inheritSerialization } from 'cerialize'; import { CacheableObject } from '../../cache/object-cache.reducer'; -import { ListableObject } from '../../../shared/object-collection/shared/listable-object.model'; import { NormalizedDSpaceObject } from '../../cache/models/normalized-dspace-object.model'; import { mapsTo, relationship } from '../../cache/builders/build-decorators'; import { Group } from './group.model'; @mapsTo(Group) @inheritSerialization(NormalizedDSpaceObject) -export class NormalizedGroup extends NormalizedDSpaceObject implements CacheableObject, ListableObject { +export class NormalizedGroup extends NormalizedDSpaceObject implements CacheableObject { /** * List of Groups that this Group belong to diff --git a/src/app/core/metadata/metadata-field.model.ts b/src/app/core/metadata/metadata-field.model.ts index 288934e52d..78d106f143 100644 --- a/src/app/core/metadata/metadata-field.model.ts +++ b/src/app/core/metadata/metadata-field.model.ts @@ -2,6 +2,7 @@ import { ListableObject } from '../../shared/object-collection/shared/listable-o import { isNotEmpty } from '../../shared/empty.util'; import { MetadataSchema } from './metadata-schema.model'; import { ResourceType } from '../shared/resource-type'; +import { GenericConstructor } from '../shared/generic-constructor'; /** * Class the represents a metadata field @@ -50,4 +51,11 @@ export class MetadataField implements ListableObject { } return key; } + + /** + * Method that returns as which type of object this object should be rendered + */ + getRenderTypes(): Array> { + return [this.constructor as GenericConstructor]; + } } diff --git a/src/app/core/metadata/metadata-schema.model.ts b/src/app/core/metadata/metadata-schema.model.ts index bc05e475cc..78d5338f2e 100644 --- a/src/app/core/metadata/metadata-schema.model.ts +++ b/src/app/core/metadata/metadata-schema.model.ts @@ -1,5 +1,6 @@ import { ListableObject } from '../../shared/object-collection/shared/listable-object.model'; import { ResourceType } from '../shared/resource-type'; +import { GenericConstructor } from '../shared/generic-constructor'; /** * Class that represents a metadata schema @@ -26,4 +27,11 @@ export class MetadataSchema implements ListableObject { * The namespace of this metadata schema */ namespace: string; + + /** + * Method that returns as which type of object this object should be rendered + */ + getRenderTypes(): Array> { + return [this.constructor as GenericConstructor]; + } } diff --git a/src/app/core/metadata/normalized-metadata-field.model.ts b/src/app/core/metadata/normalized-metadata-field.model.ts index c6b2ee32f8..075dda79d2 100644 --- a/src/app/core/metadata/normalized-metadata-field.model.ts +++ b/src/app/core/metadata/normalized-metadata-field.model.ts @@ -10,7 +10,7 @@ import { MetadataSchema } from './metadata-schema.model'; */ @mapsTo(MetadataField) @inheritSerialization(NormalizedObject) -export class NormalizedMetadataField extends NormalizedObject implements ListableObject { +export class NormalizedMetadataField extends NormalizedObject { /** * The identifier of this normalized metadata field diff --git a/src/app/core/metadata/normalized-metadata-schema.model.ts b/src/app/core/metadata/normalized-metadata-schema.model.ts index 47c7233d81..1aa5609090 100644 --- a/src/app/core/metadata/normalized-metadata-schema.model.ts +++ b/src/app/core/metadata/normalized-metadata-schema.model.ts @@ -9,7 +9,7 @@ import { MetadataSchema } from './metadata-schema.model'; */ @mapsTo(MetadataSchema) @inheritSerialization(NormalizedObject) -export class NormalizedMetadataSchema extends NormalizedObject implements ListableObject { +export class NormalizedMetadataSchema extends NormalizedObject { /** * The unique identifier for this schema */ diff --git a/src/app/core/registry/registry.service.spec.ts b/src/app/core/registry/registry.service.spec.ts index 455a8043da..03a7c132de 100644 --- a/src/app/core/registry/registry.service.spec.ts +++ b/src/app/core/registry/registry.service.spec.ts @@ -55,22 +55,24 @@ describe('RegistryService', () => { }); const mockSchemasList = [ - { + Object.assign(new MetadataSchema(), { id: 1, self: 'https://dspace7.4science.it/dspace-spring-rest/api/core/metadataschemas/1', prefix: 'dc', namespace: 'http://dublincore.org/documents/dcmi-terms/', type: MetadataSchema.type -}, - { +}), + Object.assign(new MetadataSchema(), { + id: 2, self: 'https://dspace7.4science.it/dspace-spring-rest/api/core/metadataschemas/2', prefix: 'mock', namespace: 'http://dspace.org/mockschema', type: MetadataSchema.type - } + }) ]; const mockFieldsList = [ + Object.assign(new MetadataField(), { id: 1, self: 'https://dspace7.4science.it/dspace-spring-rest/api/core/metadatafields/8', @@ -79,8 +81,9 @@ describe('RegistryService', () => { scopeNote: null, schema: mockSchemasList[0], type: MetadataField.type - }, - { + }), + Object.assign(new MetadataField(), + { id: 2, self: 'https://dspace7.4science.it/dspace-spring-rest/api/core/metadatafields/9', element: 'contributor', @@ -88,8 +91,9 @@ describe('RegistryService', () => { scopeNote: null, schema: mockSchemasList[0], type: MetadataField.type - }, - { + }), + Object.assign(new MetadataField(), + { id: 3, self: 'https://dspace7.4science.it/dspace-spring-rest/api/core/metadatafields/10', element: 'contributor', @@ -97,8 +101,9 @@ describe('RegistryService', () => { scopeNote: 'test scope note', schema: mockSchemasList[1], type: MetadataField.type - }, - { + }), + Object.assign(new MetadataField(), + { id: 4, self: 'https://dspace7.4science.it/dspace-spring-rest/api/core/metadatafields/11', element: 'contributor', @@ -106,7 +111,7 @@ describe('RegistryService', () => { scopeNote: null, schema: mockSchemasList[1], type: MetadataField.type - } + }) ]; const pageInfo = new PageInfo(); diff --git a/src/app/core/registry/registry.service.ts b/src/app/core/registry/registry.service.ts index 206426588e..3c6de36492 100644 --- a/src/app/core/registry/registry.service.ts +++ b/src/app/core/registry/registry.service.ts @@ -400,7 +400,7 @@ export class RegistryService { distinctUntilChanged() ); - const serializedSchema = new DSpaceRESTv2Serializer(getMapsToType(MetadataSchema.type)).serialize(schema as NormalizedMetadataSchema); + const serializedSchema = new DSpaceRESTv2Serializer(getMapsToType(MetadataSchema.type)).serialize(schema); const request$ = endpoint$.pipe( take(1), diff --git a/src/app/core/shared/browse-entry.model.ts b/src/app/core/shared/browse-entry.model.ts index d5d4093c81..977afb40f6 100644 --- a/src/app/core/shared/browse-entry.model.ts +++ b/src/app/core/shared/browse-entry.model.ts @@ -1,12 +1,13 @@ import { ListableObject } from '../../shared/object-collection/shared/listable-object.model'; import { TypedObject } from '../cache/object-cache.reducer'; import { ResourceType } from './resource-type'; +import { GenericConstructor } from './generic-constructor'; /** * Class object representing a browse entry * This class is not normalized because browse entries do not have self links */ -export class BrowseEntry implements ListableObject, TypedObject { +export class BrowseEntry implements ListableObject { static type = new ResourceType('browseEntry'); /** @@ -28,4 +29,11 @@ export class BrowseEntry implements ListableObject, TypedObject { * The count of this browse entry */ count: number; + + /** + * Method that returns as which type of object this object should be rendered + */ + getRenderTypes(): Array> { + return [this.constructor as GenericConstructor]; + } } diff --git a/src/app/core/shared/context.model.ts b/src/app/core/shared/context.model.ts new file mode 100644 index 0000000000..7bfd613b65 --- /dev/null +++ b/src/app/core/shared/context.model.ts @@ -0,0 +1,13 @@ +/** + * This enumeration represents all possible ways of representing a group of objects in the UI + */ + +export enum Context { + Undefined = 'undefined', + ItemPage = 'itemPage', + Search = 'search', + Workflow = 'workflow', + Workspace = 'workspace', + AdminMenu = 'adminMenu', + SubmissionModal = 'submissionModal', +} diff --git a/src/app/core/shared/dspace-object.model.ts b/src/app/core/shared/dspace-object.model.ts index 26f76c5ce2..2e50f19c4f 100644 --- a/src/app/core/shared/dspace-object.model.ts +++ b/src/app/core/shared/dspace-object.model.ts @@ -12,6 +12,7 @@ import { CacheableObject } from '../cache/object-cache.reducer'; import { RemoteData } from '../data/remote-data'; import { ListableObject } from '../../shared/object-collection/shared/listable-object.model'; import { ResourceType } from './resource-type'; +import { GenericConstructor } from './generic-constructor'; /** * An abstract model class for a DSpaceObject. @@ -109,7 +110,7 @@ export class DSpaceObject implements CacheableObject, ListableObject { * Like [[firstMetadata]], but only returns a string value, or `undefined`. * * @param {string|string[]} keyOrKeys The metadata key(s) in scope. Wildcards are supported; see [[Metadata]]. - * @param {MetadataValueFilter} filter The value filter to use. If unspecified, no filtering will be done. + * @param {MetadataValueFilter} valueFilter The value filter to use. If unspecified, no filtering will be done. * @returns {string} the first matching string value, or `undefined`. */ firstMetadataValue(keyOrKeys: string | string[], valueFilter?: MetadataValueFilter): string { @@ -146,4 +147,10 @@ export class DSpaceObject implements CacheableObject, ListableObject { }); } + /** + * Method that returns as which type of object this object should be rendered + */ + getRenderTypes(): Array> { + return [this.constructor as GenericConstructor]; + } } diff --git a/src/app/core/shared/item.model.ts b/src/app/core/shared/item.model.ts index a3e625c022..733a8f941c 100644 --- a/src/app/core/shared/item.model.ts +++ b/src/app/core/shared/item.model.ts @@ -5,12 +5,18 @@ import { DSpaceObject } from './dspace-object.model'; import { Collection } from './collection.model'; import { RemoteData } from '../data/remote-data'; import { Bitstream } from './bitstream.model'; -import { hasValue, isNotEmpty } from '../../shared/empty.util'; +import { hasValue, isEmpty, isNotEmpty } from '../../shared/empty.util'; import { PaginatedList } from '../data/paginated-list'; import { Relationship } from './item-relationships/relationship.model'; import { ResourceType } from './resource-type'; import { getSucceededRemoteData } from './operators'; +import { GenericConstructor } from './generic-constructor'; +import { ListableObject } from '../../shared/object-collection/shared/listable-object.model'; +import { DEFAULT_ENTITY_TYPE } from '../../shared/metadata-representation/metadata-representation.decorator'; +/** + * Class representing a DSpace Item + */ export class Item extends DSpaceObject { static type = new ResourceType('item'); @@ -110,4 +116,14 @@ export class Item extends DSpaceObject { })); } + /** + * Method that returns as which type of object this object should be rendered + */ + getRenderTypes(): Array> { + let entityType = this.firstMetadataValue('relationship.type'); + if (isEmpty(entityType)) { + entityType = DEFAULT_ENTITY_TYPE; + } + return [entityType, ...super.getRenderTypes()]; + } } diff --git a/src/app/core/shared/view-mode.model.ts b/src/app/core/shared/view-mode.model.ts index 9c8d086097..c2f076a5e5 100644 --- a/src/app/core/shared/view-mode.model.ts +++ b/src/app/core/shared/view-mode.model.ts @@ -3,7 +3,8 @@ */ export enum ViewMode { - List = 'list', - Grid = 'grid', - Detail = 'detail' + ListElement = 'listElement', + GridElement = 'gridElement', + DetailedListElement = 'detailedListElement', + StandalonePage = 'standalonePage', } diff --git a/src/app/entity-groups/journal-entities/item-grid-elements/journal-issue/journal-issue-grid-element.component.html b/src/app/entity-groups/journal-entities/item-grid-elements/journal-issue/journal-issue-grid-element.component.html index 3aa79fc70a..fb69ed92f5 100644 --- a/src/app/entity-groups/journal-entities/item-grid-elements/journal-issue/journal-issue-grid-element.component.html +++ b/src/app/entity-groups/journal-entities/item-grid-elements/journal-issue/journal-issue-grid-element.component.html @@ -1,30 +1 @@ - -
- -
- - -
-
-
- - -

-
-

- - - -

-

- - - -

-
- View -
-
-
-
+ \ No newline at end of file diff --git a/src/app/entity-groups/journal-entities/item-grid-elements/journal-issue/journal-issue-grid-element.component.spec.ts b/src/app/entity-groups/journal-entities/item-grid-elements/journal-issue/journal-issue-grid-element.component.spec.ts index d13feda406..9a147637fa 100644 --- a/src/app/entity-groups/journal-entities/item-grid-elements/journal-issue/journal-issue-grid-element.component.spec.ts +++ b/src/app/entity-groups/journal-entities/item-grid-elements/journal-issue/journal-issue-grid-element.component.spec.ts @@ -1,15 +1,17 @@ -import { ItemSearchResult } from '../../../../shared/object-collection/shared/item-search-result.model'; import { Item } from '../../../../core/shared/item.model'; -import { of as observableOf } from 'rxjs/internal/observable/of'; -import { getEntityGridElementTestComponent } from '../../../../shared/object-grid/item-grid-element/item-types/publication/publication-grid-element.component.spec'; import { JournalIssueGridElementComponent } from './journal-issue-grid-element.component'; import { createSuccessfulRemoteDataObject$ } from '../../../../shared/testing/utils'; import { PaginatedList } from '../../../../core/data/paginated-list'; import { PageInfo } from '../../../../core/shared/page-info.model'; +import { of as observableOf } from 'rxjs'; +import { async, TestBed } from '@angular/core/testing'; +import { NoopAnimationsModule } from '@angular/platform-browser/animations'; +import { TruncatePipe } from '../../../../shared/utils/truncate.pipe'; +import { TruncatableService } from '../../../../shared/truncatable/truncatable.service'; +import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA } from '@angular/core'; +import { By } from '@angular/platform-browser'; -const mockItemWithMetadata: ItemSearchResult = new ItemSearchResult(); -mockItemWithMetadata.hitHighlights = {}; -mockItemWithMetadata.indexableObject = Object.assign(new Item(), { +const mockItem = Object.assign(new Item(), { bitstreams: createSuccessfulRemoteDataObject$(new PaginatedList(new PageInfo(), [])), metadata: { 'dc.title': [ @@ -33,18 +35,41 @@ mockItemWithMetadata.indexableObject = Object.assign(new Item(), { } }); -const mockItemWithoutMetadata: ItemSearchResult = new ItemSearchResult(); -mockItemWithoutMetadata.hitHighlights = {}; -mockItemWithoutMetadata.indexableObject = Object.assign(new Item(), { - bitstreams: createSuccessfulRemoteDataObject$(new PaginatedList(new PageInfo(), [])), - metadata: { - 'dc.title': [ - { - language: 'en_US', - value: 'This is just another title' - } - ] - } -}); +describe('JournalIssueGridElementComponent', () => { + let comp; + let fixture; -describe('JournalIssueGridElementComponent', getEntityGridElementTestComponent(JournalIssueGridElementComponent, mockItemWithMetadata, mockItemWithoutMetadata, ['date', 'journal-title'])); + const truncatableServiceStub: any = { + isCollapsed: (id: number) => observableOf(true), + }; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + imports: [NoopAnimationsModule], + declarations: [JournalIssueGridElementComponent, TruncatePipe], + providers: [ + { provide: TruncatableService, useValue: truncatableServiceStub }, + ], + schemas: [NO_ERRORS_SCHEMA] + }).overrideComponent(JournalIssueGridElementComponent, { + set: { changeDetection: ChangeDetectionStrategy.Default } + }).compileComponents(); + })); + + beforeEach(async(() => { + fixture = TestBed.createComponent(JournalIssueGridElementComponent); + comp = fixture.componentInstance; + })); + + describe(`when the journal issue is rendered`, () => { + beforeEach(() => { + comp.object = mockItem; + fixture.detectChanges(); + }); + + it(`should contain a JournalIssueSearchResultGridElementComponent`, () => { + const journalIssueGridElement = fixture.debugElement.query(By.css(`ds-journal-issue-search-result-grid-element`)); + expect(journalIssueGridElement).not.toBeNull(); + }); + }); +}); diff --git a/src/app/entity-groups/journal-entities/item-grid-elements/journal-issue/journal-issue-grid-element.component.ts b/src/app/entity-groups/journal-entities/item-grid-elements/journal-issue/journal-issue-grid-element.component.ts index 06c27ebacf..3e57731613 100644 --- a/src/app/entity-groups/journal-entities/item-grid-elements/journal-issue/journal-issue-grid-element.component.ts +++ b/src/app/entity-groups/journal-entities/item-grid-elements/journal-issue/journal-issue-grid-element.component.ts @@ -1,17 +1,17 @@ -import { ItemViewMode, rendersItemType } from '../../../../shared/items/item-type-decorator'; import { Component } from '@angular/core'; -import { focusShadow } from '../../../../shared/animations/focus'; -import { TypedItemSearchResultGridElementComponent } from '../../../../shared/object-grid/item-grid-element/item-types/typed-item-search-result-grid-element.component'; +import { ViewMode } from '../../../../core/shared/view-mode.model'; +import { listableObjectComponent } from '../../../../shared/object-collection/shared/listable-object/listable-object.decorator'; +import { AbstractListableElementComponent } from '../../../../shared/object-collection/shared/object-collection-element/abstract-listable-element.component'; +import { Item } from '../../../../core/shared/item.model'; -@rendersItemType('JournalIssue', ItemViewMode.Card) +@listableObjectComponent('JournalIssue', ViewMode.GridElement) @Component({ selector: 'ds-journal-issue-grid-element', styleUrls: ['./journal-issue-grid-element.component.scss'], templateUrl: './journal-issue-grid-element.component.html', - animations: [focusShadow] }) /** * The component for displaying a grid element for an item of the type Journal Issue */ -export class JournalIssueGridElementComponent extends TypedItemSearchResultGridElementComponent { +export class JournalIssueGridElementComponent extends AbstractListableElementComponent { } diff --git a/src/app/entity-groups/journal-entities/item-grid-elements/journal-volume/journal-volume-grid-element.component.html b/src/app/entity-groups/journal-entities/item-grid-elements/journal-volume/journal-volume-grid-element.component.html index b2b251f550..53713b47ee 100644 --- a/src/app/entity-groups/journal-entities/item-grid-elements/journal-volume/journal-volume-grid-element.component.html +++ b/src/app/entity-groups/journal-entities/item-grid-elements/journal-volume/journal-volume-grid-element.component.html @@ -1,30 +1 @@ - -
- -
- - -
-
-
- - -

-
-

- - - -

-

- - - -

-
- View -
-
-
-
+ \ No newline at end of file diff --git a/src/app/entity-groups/journal-entities/item-grid-elements/journal-volume/journal-volume-grid-element.component.spec.ts b/src/app/entity-groups/journal-entities/item-grid-elements/journal-volume/journal-volume-grid-element.component.spec.ts index 8c854aeb77..6f74f97ac1 100644 --- a/src/app/entity-groups/journal-entities/item-grid-elements/journal-volume/journal-volume-grid-element.component.spec.ts +++ b/src/app/entity-groups/journal-entities/item-grid-elements/journal-volume/journal-volume-grid-element.component.spec.ts @@ -1,15 +1,17 @@ -import { ItemSearchResult } from '../../../../shared/object-collection/shared/item-search-result.model'; import { Item } from '../../../../core/shared/item.model'; -import { of as observableOf } from 'rxjs/internal/observable/of'; -import { getEntityGridElementTestComponent } from '../../../../shared/object-grid/item-grid-element/item-types/publication/publication-grid-element.component.spec'; import { JournalVolumeGridElementComponent } from './journal-volume-grid-element.component'; import { createSuccessfulRemoteDataObject$ } from '../../../../shared/testing/utils'; import { PaginatedList } from '../../../../core/data/paginated-list'; import { PageInfo } from '../../../../core/shared/page-info.model'; +import { of as observableOf } from 'rxjs'; +import { async, TestBed } from '@angular/core/testing'; +import { NoopAnimationsModule } from '@angular/platform-browser/animations'; +import { TruncatePipe } from '../../../../shared/utils/truncate.pipe'; +import { TruncatableService } from '../../../../shared/truncatable/truncatable.service'; +import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA } from '@angular/core'; +import { By } from '@angular/platform-browser'; -const mockItemWithMetadata: ItemSearchResult = new ItemSearchResult(); -mockItemWithMetadata.hitHighlights = {}; -mockItemWithMetadata.indexableObject = Object.assign(new Item(), { +const mockItem = Object.assign(new Item(), { bitstreams: createSuccessfulRemoteDataObject$(new PaginatedList(new PageInfo(), [])), metadata: { 'dc.title': [ @@ -33,18 +35,41 @@ mockItemWithMetadata.indexableObject = Object.assign(new Item(), { } }); -const mockItemWithoutMetadata: ItemSearchResult = new ItemSearchResult(); -mockItemWithoutMetadata.hitHighlights = {}; -mockItemWithoutMetadata.indexableObject = Object.assign(new Item(), { - bitstreams: createSuccessfulRemoteDataObject$(new PaginatedList(new PageInfo(), [])), - metadata: { - 'dc.title': [ - { - language: 'en_US', - value: 'This is just another title' - } - ] - } -}); +describe('JournalVolumeGridElementComponent', () => { + let comp; + let fixture; -describe('JournalVolumeGridElementComponent', getEntityGridElementTestComponent(JournalVolumeGridElementComponent, mockItemWithMetadata, mockItemWithoutMetadata, ['date', 'description'])); + const truncatableServiceStub: any = { + isCollapsed: (id: number) => observableOf(true), + }; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + imports: [NoopAnimationsModule], + declarations: [JournalVolumeGridElementComponent, TruncatePipe], + providers: [ + { provide: TruncatableService, useValue: truncatableServiceStub }, + ], + schemas: [NO_ERRORS_SCHEMA] + }).overrideComponent(JournalVolumeGridElementComponent, { + set: { changeDetection: ChangeDetectionStrategy.Default } + }).compileComponents(); + })); + + beforeEach(async(() => { + fixture = TestBed.createComponent(JournalVolumeGridElementComponent); + comp = fixture.componentInstance; + })); + + describe(`when the journal volume is rendered`, () => { + beforeEach(() => { + comp.object = mockItem; + fixture.detectChanges(); + }); + + it(`should contain a JournalVolumeSearchResultGridElementComponent`, () => { + const journalVolumeGridElement = fixture.debugElement.query(By.css(`ds-journal-volume-search-result-grid-element`)); + expect(journalVolumeGridElement).not.toBeNull(); + }); + }); +}); diff --git a/src/app/entity-groups/journal-entities/item-grid-elements/journal-volume/journal-volume-grid-element.component.ts b/src/app/entity-groups/journal-entities/item-grid-elements/journal-volume/journal-volume-grid-element.component.ts index e5183536ef..eb88c25a12 100644 --- a/src/app/entity-groups/journal-entities/item-grid-elements/journal-volume/journal-volume-grid-element.component.ts +++ b/src/app/entity-groups/journal-entities/item-grid-elements/journal-volume/journal-volume-grid-element.component.ts @@ -1,17 +1,17 @@ -import { ItemViewMode, rendersItemType } from '../../../../shared/items/item-type-decorator'; import { Component } from '@angular/core'; -import { focusShadow } from '../../../../shared/animations/focus'; -import { TypedItemSearchResultGridElementComponent } from '../../../../shared/object-grid/item-grid-element/item-types/typed-item-search-result-grid-element.component'; +import { ViewMode } from '../../../../core/shared/view-mode.model'; +import { listableObjectComponent } from '../../../../shared/object-collection/shared/listable-object/listable-object.decorator'; +import { AbstractListableElementComponent } from '../../../../shared/object-collection/shared/object-collection-element/abstract-listable-element.component'; +import { Item } from '../../../../core/shared/item.model'; -@rendersItemType('JournalVolume', ItemViewMode.Card) +@listableObjectComponent('JournalVolume', ViewMode.GridElement) @Component({ selector: 'ds-journal-volume-grid-element', styleUrls: ['./journal-volume-grid-element.component.scss'], templateUrl: './journal-volume-grid-element.component.html', - animations: [focusShadow] }) /** * The component for displaying a grid element for an item of the type Journal Volume */ -export class JournalVolumeGridElementComponent extends TypedItemSearchResultGridElementComponent { +export class JournalVolumeGridElementComponent extends AbstractListableElementComponent { } diff --git a/src/app/entity-groups/journal-entities/item-grid-elements/journal/journal-grid-element.component.html b/src/app/entity-groups/journal-entities/item-grid-elements/journal/journal-grid-element.component.html index af0739004c..594a0e0dc1 100644 --- a/src/app/entity-groups/journal-entities/item-grid-elements/journal/journal-grid-element.component.html +++ b/src/app/entity-groups/journal-entities/item-grid-elements/journal/journal-grid-element.component.html @@ -1,35 +1 @@ - -
- -
- - -
-
-
- - -

-
-

- - {{dso.firstMetadataValue('creativework.editor')}} - - , - {{dso.firstMetadataValue('creativework.publisher')}} - - -

-

- - - -

-
- View -
-
-
-
+ \ No newline at end of file diff --git a/src/app/entity-groups/journal-entities/item-grid-elements/journal/journal-grid-element.component.spec.ts b/src/app/entity-groups/journal-entities/item-grid-elements/journal/journal-grid-element.component.spec.ts index 0d0f77842a..0619309d09 100644 --- a/src/app/entity-groups/journal-entities/item-grid-elements/journal/journal-grid-element.component.spec.ts +++ b/src/app/entity-groups/journal-entities/item-grid-elements/journal/journal-grid-element.component.spec.ts @@ -1,15 +1,17 @@ -import { ItemSearchResult } from '../../../../shared/object-collection/shared/item-search-result.model'; import { Item } from '../../../../core/shared/item.model'; import { of as observableOf } from 'rxjs/internal/observable/of'; -import { getEntityGridElementTestComponent } from '../../../../shared/object-grid/item-grid-element/item-types/publication/publication-grid-element.component.spec'; import { JournalGridElementComponent } from './journal-grid-element.component'; import { createSuccessfulRemoteDataObject$ } from '../../../../shared/testing/utils'; import { PaginatedList } from '../../../../core/data/paginated-list'; import { PageInfo } from '../../../../core/shared/page-info.model'; +import { async, TestBed } from '@angular/core/testing'; +import { NoopAnimationsModule } from '@angular/platform-browser/animations'; +import { TruncatePipe } from '../../../../shared/utils/truncate.pipe'; +import { TruncatableService } from '../../../../shared/truncatable/truncatable.service'; +import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA } from '@angular/core'; +import { By } from '@angular/platform-browser'; -const mockItemWithMetadata: ItemSearchResult = new ItemSearchResult(); -mockItemWithMetadata.hitHighlights = {}; -mockItemWithMetadata.indexableObject = Object.assign(new Item(), { +const mockItem = Object.assign(new Item(), { bitstreams: createSuccessfulRemoteDataObject$(new PaginatedList(new PageInfo(), [])), metadata: { 'dc.title': [ @@ -39,18 +41,41 @@ mockItemWithMetadata.indexableObject = Object.assign(new Item(), { } }); -const mockItemWithoutMetadata: ItemSearchResult = new ItemSearchResult(); -mockItemWithoutMetadata.hitHighlights = {}; -mockItemWithoutMetadata.indexableObject = Object.assign(new Item(), { - bitstreams: createSuccessfulRemoteDataObject$(new PaginatedList(new PageInfo(), [])), - metadata: { - 'dc.title': [ - { - language: 'en_US', - value: 'This is just another title' - } - ] - } -}); +describe('JournalGridElementComponent', () => { + let comp; + let fixture; -describe('JournalGridElementComponent', getEntityGridElementTestComponent(JournalGridElementComponent, mockItemWithMetadata, mockItemWithoutMetadata, ['editor', 'publisher', 'description'])); + const truncatableServiceStub: any = { + isCollapsed: (id: number) => observableOf(true), + }; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + imports: [NoopAnimationsModule], + declarations: [JournalGridElementComponent, TruncatePipe], + providers: [ + { provide: TruncatableService, useValue: truncatableServiceStub }, + ], + schemas: [NO_ERRORS_SCHEMA] + }).overrideComponent(JournalGridElementComponent, { + set: { changeDetection: ChangeDetectionStrategy.Default } + }).compileComponents(); + })); + + beforeEach(async(() => { + fixture = TestBed.createComponent(JournalGridElementComponent); + comp = fixture.componentInstance; + })); + + describe(`when the journal is rendered`, () => { + beforeEach(() => { + comp.object = mockItem; + fixture.detectChanges(); + }); + + it(`should contain a JournalGridElementComponent`, () => { + const journalGridElement = fixture.debugElement.query(By.css(`ds-journal-search-result-grid-element`)); + expect(journalGridElement).not.toBeNull(); + }); + }); +}); diff --git a/src/app/entity-groups/journal-entities/item-grid-elements/journal/journal-grid-element.component.ts b/src/app/entity-groups/journal-entities/item-grid-elements/journal/journal-grid-element.component.ts index 7f23211538..1d7c1e5b73 100644 --- a/src/app/entity-groups/journal-entities/item-grid-elements/journal/journal-grid-element.component.ts +++ b/src/app/entity-groups/journal-entities/item-grid-elements/journal/journal-grid-element.component.ts @@ -1,17 +1,17 @@ -import { ItemViewMode, rendersItemType } from '../../../../shared/items/item-type-decorator'; import { Component } from '@angular/core'; -import { focusShadow } from '../../../../shared/animations/focus'; -import { TypedItemSearchResultGridElementComponent } from '../../../../shared/object-grid/item-grid-element/item-types/typed-item-search-result-grid-element.component'; +import { ViewMode } from '../../../../core/shared/view-mode.model'; +import { listableObjectComponent } from '../../../../shared/object-collection/shared/listable-object/listable-object.decorator'; +import { AbstractListableElementComponent } from '../../../../shared/object-collection/shared/object-collection-element/abstract-listable-element.component'; +import { Item } from '../../../../core/shared/item.model'; -@rendersItemType('Journal', ItemViewMode.Card) +@listableObjectComponent('Journal', ViewMode.GridElement) @Component({ selector: 'ds-journal-grid-element', styleUrls: ['./journal-grid-element.component.scss'], templateUrl: './journal-grid-element.component.html', - animations: [focusShadow] }) /** * The component for displaying a grid element for an item of the type Journal */ -export class JournalGridElementComponent extends TypedItemSearchResultGridElementComponent { +export class JournalGridElementComponent extends AbstractListableElementComponent { } diff --git a/src/app/entity-groups/journal-entities/item-grid-elements/search-result-grid-elements/journal-issue/journal-issue-search-result-grid-element.component.html b/src/app/entity-groups/journal-entities/item-grid-elements/search-result-grid-elements/journal-issue/journal-issue-search-result-grid-element.component.html new file mode 100644 index 0000000000..18ff77bf23 --- /dev/null +++ b/src/app/entity-groups/journal-entities/item-grid-elements/search-result-grid-elements/journal-issue/journal-issue-search-result-grid-element.component.html @@ -0,0 +1,36 @@ + +
+ +
+ + +
+
+ +
+ + +
+
+
+ + +

+
+

+ + + +

+

+ + + +

+
+ View +
+
+
+
diff --git a/src/app/entity-groups/research-entities/item-grid-elements/orgunit/orgunit-grid-element.component.scss b/src/app/entity-groups/journal-entities/item-grid-elements/search-result-grid-elements/journal-issue/journal-issue-search-result-grid-element.component.scss similarity index 100% rename from src/app/entity-groups/research-entities/item-grid-elements/orgunit/orgunit-grid-element.component.scss rename to src/app/entity-groups/journal-entities/item-grid-elements/search-result-grid-elements/journal-issue/journal-issue-search-result-grid-element.component.scss diff --git a/src/app/entity-groups/journal-entities/item-grid-elements/search-result-grid-elements/journal-issue/journal-issue-search-result-grid-element.component.spec.ts b/src/app/entity-groups/journal-entities/item-grid-elements/search-result-grid-elements/journal-issue/journal-issue-search-result-grid-element.component.spec.ts new file mode 100644 index 0000000000..3cca9071b0 --- /dev/null +++ b/src/app/entity-groups/journal-entities/item-grid-elements/search-result-grid-elements/journal-issue/journal-issue-search-result-grid-element.component.spec.ts @@ -0,0 +1,49 @@ +import { ItemSearchResult } from '../../../../../shared/object-collection/shared/item-search-result.model'; +import { Item } from '../../../../../core/shared/item.model'; +import { createSuccessfulRemoteDataObject$ } from '../../../../../shared/testing/utils'; +import { PaginatedList } from '../../../../../core/data/paginated-list'; +import { PageInfo } from '../../../../../core/shared/page-info.model'; +import { getEntityGridElementTestComponent } from '../../../../../shared/object-grid/search-result-grid-element/item-search-result/publication/publication-search-result-grid-element.component.spec'; +import { JournalIssueSearchResultGridElementComponent } from './journal-issue-search-result-grid-element.component'; + +const mockItemWithMetadata: ItemSearchResult = new ItemSearchResult(); +mockItemWithMetadata.hitHighlights = {}; +mockItemWithMetadata.indexableObject = Object.assign(new Item(), { + bitstreams: createSuccessfulRemoteDataObject$(new PaginatedList(new PageInfo(), [])), + metadata: { + 'dc.title': [ + { + language: 'en_US', + value: 'This is just another title' + } + ], + 'creativework.datePublished': [ + { + language: null, + value: '2015-06-26' + } + ], + 'journal.title': [ + { + language: 'en_US', + value: 'The journal title' + } + ] + } +}); + +const mockItemWithoutMetadata: ItemSearchResult = new ItemSearchResult(); +mockItemWithoutMetadata.hitHighlights = {}; +mockItemWithoutMetadata.indexableObject = Object.assign(new Item(), { + bitstreams: createSuccessfulRemoteDataObject$(new PaginatedList(new PageInfo(), [])), + metadata: { + 'dc.title': [ + { + language: 'en_US', + value: 'This is just another title' + } + ] + } +}); + +describe('JournalIssueSearchResultGridElementComponent', getEntityGridElementTestComponent(JournalIssueSearchResultGridElementComponent, mockItemWithMetadata, mockItemWithoutMetadata, ['date', 'journal-title'])); diff --git a/src/app/entity-groups/journal-entities/item-grid-elements/search-result-grid-elements/journal-issue/journal-issue-search-result-grid-element.component.ts b/src/app/entity-groups/journal-entities/item-grid-elements/search-result-grid-elements/journal-issue/journal-issue-search-result-grid-element.component.ts new file mode 100644 index 0000000000..9d27842c16 --- /dev/null +++ b/src/app/entity-groups/journal-entities/item-grid-elements/search-result-grid-elements/journal-issue/journal-issue-search-result-grid-element.component.ts @@ -0,0 +1,20 @@ +import { Component } from '@angular/core'; +import { ViewMode } from '../../../../../core/shared/view-mode.model'; +import { listableObjectComponent } from '../../../../../shared/object-collection/shared/listable-object/listable-object.decorator'; +import { focusShadow } from '../../../../../shared/animations/focus'; +import { SearchResultGridElementComponent } from '../../../../../shared/object-grid/search-result-grid-element/search-result-grid-element.component'; +import { ItemSearchResult } from '../../../../../shared/object-collection/shared/item-search-result.model'; +import { Item } from '../../../../../core/shared/item.model'; + +@listableObjectComponent('JournalIssueSearchResult', ViewMode.GridElement) +@Component({ + selector: 'ds-journal-issue-search-result-grid-element', + styleUrls: ['./journal-issue-search-result-grid-element.component.scss'], + templateUrl: './journal-issue-search-result-grid-element.component.html', + animations: [focusShadow] +}) +/** + * The component for displaying a grid element for an item search result of the type Journal Issue + */ +export class JournalIssueSearchResultGridElementComponent extends SearchResultGridElementComponent { +} diff --git a/src/app/entity-groups/journal-entities/item-grid-elements/search-result-grid-elements/journal-volume/journal-volume-search-result-grid-element.component.html b/src/app/entity-groups/journal-entities/item-grid-elements/search-result-grid-elements/journal-volume/journal-volume-search-result-grid-element.component.html new file mode 100644 index 0000000000..07e50eb6fb --- /dev/null +++ b/src/app/entity-groups/journal-entities/item-grid-elements/search-result-grid-elements/journal-volume/journal-volume-search-result-grid-element.component.html @@ -0,0 +1,36 @@ + +
+ +
+ + +
+
+ +
+ + +
+
+
+ + +

+
+

+ + + +

+

+ + + +

+
+ View +
+
+
+
diff --git a/src/app/shared/object-detail/my-dspace-result-detail-element/workspaceitem-my-dspace-result/workspaceitem-my-dspace-result-detail-element.component.scss b/src/app/entity-groups/journal-entities/item-grid-elements/search-result-grid-elements/journal-volume/journal-volume-search-result-grid-element.component.scss similarity index 100% rename from src/app/shared/object-detail/my-dspace-result-detail-element/workspaceitem-my-dspace-result/workspaceitem-my-dspace-result-detail-element.component.scss rename to src/app/entity-groups/journal-entities/item-grid-elements/search-result-grid-elements/journal-volume/journal-volume-search-result-grid-element.component.scss diff --git a/src/app/entity-groups/journal-entities/item-grid-elements/search-result-grid-elements/journal-volume/journal-volume-search-result-grid-element.component.spec.ts b/src/app/entity-groups/journal-entities/item-grid-elements/search-result-grid-elements/journal-volume/journal-volume-search-result-grid-element.component.spec.ts new file mode 100644 index 0000000000..8923b15ccb --- /dev/null +++ b/src/app/entity-groups/journal-entities/item-grid-elements/search-result-grid-elements/journal-volume/journal-volume-search-result-grid-element.component.spec.ts @@ -0,0 +1,49 @@ +import { ItemSearchResult } from '../../../../../shared/object-collection/shared/item-search-result.model'; +import { Item } from '../../../../../core/shared/item.model'; +import { createSuccessfulRemoteDataObject$ } from '../../../../../shared/testing/utils'; +import { PaginatedList } from '../../../../../core/data/paginated-list'; +import { PageInfo } from '../../../../../core/shared/page-info.model'; +import { getEntityGridElementTestComponent } from '../../../../../shared/object-grid/search-result-grid-element/item-search-result/publication/publication-search-result-grid-element.component.spec'; +import { JournalVolumeSearchResultGridElementComponent } from './journal-volume-search-result-grid-element.component'; + +const mockItemWithMetadata: ItemSearchResult = new ItemSearchResult(); +mockItemWithMetadata.hitHighlights = {}; +mockItemWithMetadata.indexableObject = Object.assign(new Item(), { + bitstreams: createSuccessfulRemoteDataObject$(new PaginatedList(new PageInfo(), [])), + metadata: { + 'dc.title': [ + { + language: 'en_US', + value: 'This is just another title' + } + ], + 'creativework.datePublished': [ + { + language: null, + value: '2015-06-26' + } + ], + 'dc.description': [ + { + language: 'en_US', + value: 'A description for the journal volume' + } + ] + } +}); + +const mockItemWithoutMetadata: ItemSearchResult = new ItemSearchResult(); +mockItemWithoutMetadata.hitHighlights = {}; +mockItemWithoutMetadata.indexableObject = Object.assign(new Item(), { + bitstreams: createSuccessfulRemoteDataObject$(new PaginatedList(new PageInfo(), [])), + metadata: { + 'dc.title': [ + { + language: 'en_US', + value: 'This is just another title' + } + ] + } +}); + +describe('JournalVolumeSearchResultGridElementComponent', getEntityGridElementTestComponent(JournalVolumeSearchResultGridElementComponent, mockItemWithMetadata, mockItemWithoutMetadata, ['date', 'description'])); diff --git a/src/app/entity-groups/journal-entities/item-grid-elements/search-result-grid-elements/journal-volume/journal-volume-search-result-grid-element.component.ts b/src/app/entity-groups/journal-entities/item-grid-elements/search-result-grid-elements/journal-volume/journal-volume-search-result-grid-element.component.ts new file mode 100644 index 0000000000..802a6d8692 --- /dev/null +++ b/src/app/entity-groups/journal-entities/item-grid-elements/search-result-grid-elements/journal-volume/journal-volume-search-result-grid-element.component.ts @@ -0,0 +1,20 @@ +import { Component } from '@angular/core'; +import { SearchResultGridElementComponent } from '../../../../../shared/object-grid/search-result-grid-element/search-result-grid-element.component'; +import { ItemSearchResult } from '../../../../../shared/object-collection/shared/item-search-result.model'; +import { Item } from '../../../../../core/shared/item.model'; +import { ViewMode } from '../../../../../core/shared/view-mode.model'; +import { listableObjectComponent } from '../../../../../shared/object-collection/shared/listable-object/listable-object.decorator'; +import { focusShadow } from '../../../../../shared/animations/focus'; + +@listableObjectComponent('JournalVolumeSearchResult', ViewMode.GridElement) +@Component({ + selector: 'ds-journal-volume-search-result-grid-element', + styleUrls: ['./journal-volume-search-result-grid-element.component.scss'], + templateUrl: './journal-volume-search-result-grid-element.component.html', + animations: [focusShadow] +}) +/** + * The component for displaying a grid element for an item search result of the type Journal Volume + */ +export class JournalVolumeSearchResultGridElementComponent extends SearchResultGridElementComponent { +} diff --git a/src/app/entity-groups/journal-entities/item-grid-elements/search-result-grid-elements/journal/journal-search-result-grid-element.component.html b/src/app/entity-groups/journal-entities/item-grid-elements/search-result-grid-elements/journal/journal-search-result-grid-element.component.html new file mode 100644 index 0000000000..394e5241e1 --- /dev/null +++ b/src/app/entity-groups/journal-entities/item-grid-elements/search-result-grid-elements/journal/journal-search-result-grid-element.component.html @@ -0,0 +1,41 @@ + +
+ +
+ + +
+
+ +
+ + +
+
+
+ + +

+
+

+ + {{firstMetadataValue('creativework.editor')}} + + , + {{firstMetadataValue('creativework.publisher')}} + + +

+

+ + + +

+
+ View +
+
+
+
diff --git a/src/app/shared/object-list/item-list-element/item-list-element.component.scss b/src/app/entity-groups/journal-entities/item-grid-elements/search-result-grid-elements/journal/journal-search-result-grid-element.component.scss similarity index 100% rename from src/app/shared/object-list/item-list-element/item-list-element.component.scss rename to src/app/entity-groups/journal-entities/item-grid-elements/search-result-grid-elements/journal/journal-search-result-grid-element.component.scss diff --git a/src/app/entity-groups/journal-entities/item-grid-elements/search-result-grid-elements/journal/journal-search-result-grid-element.component.spec.ts b/src/app/entity-groups/journal-entities/item-grid-elements/search-result-grid-elements/journal/journal-search-result-grid-element.component.spec.ts new file mode 100644 index 0000000000..5712b211ff --- /dev/null +++ b/src/app/entity-groups/journal-entities/item-grid-elements/search-result-grid-elements/journal/journal-search-result-grid-element.component.spec.ts @@ -0,0 +1,55 @@ +import { ItemSearchResult } from '../../../../../shared/object-collection/shared/item-search-result.model'; +import { Item } from '../../../../../core/shared/item.model'; +import { createSuccessfulRemoteDataObject$ } from '../../../../../shared/testing/utils'; +import { PaginatedList } from '../../../../../core/data/paginated-list'; +import { PageInfo } from '../../../../../core/shared/page-info.model'; +import { getEntityGridElementTestComponent } from '../../../../../shared/object-grid/search-result-grid-element/item-search-result/publication/publication-search-result-grid-element.component.spec'; +import { JournalSearchResultGridElementComponent } from './journal-search-result-grid-element.component'; + +const mockItemWithMetadata: ItemSearchResult = new ItemSearchResult(); +mockItemWithMetadata.hitHighlights = {}; +mockItemWithMetadata.indexableObject = Object.assign(new Item(), { + bitstreams: createSuccessfulRemoteDataObject$(new PaginatedList(new PageInfo(), [])), + metadata: { + 'dc.title': [ + { + language: 'en_US', + value: 'This is just another title' + } + ], + 'creativework.editor': [ + { + language: 'en_US', + value: 'Smith, Donald' + } + ], + 'creativework.publisher': [ + { + language: 'en_US', + value: 'A company' + } + ], + 'dc.description': [ + { + language: 'en_US', + value: 'This is the description' + } + ] + } +}); + +const mockItemWithoutMetadata: ItemSearchResult = new ItemSearchResult(); +mockItemWithoutMetadata.hitHighlights = {}; +mockItemWithoutMetadata.indexableObject = Object.assign(new Item(), { + bitstreams: createSuccessfulRemoteDataObject$(new PaginatedList(new PageInfo(), [])), + metadata: { + 'dc.title': [ + { + language: 'en_US', + value: 'This is just another title' + } + ] + } +}); + +describe('JournalSearchResultGridElementComponent', getEntityGridElementTestComponent(JournalSearchResultGridElementComponent, mockItemWithMetadata, mockItemWithoutMetadata, ['editor', 'publisher', 'description'])); diff --git a/src/app/entity-groups/journal-entities/item-grid-elements/search-result-grid-elements/journal/journal-search-result-grid-element.component.ts b/src/app/entity-groups/journal-entities/item-grid-elements/search-result-grid-elements/journal/journal-search-result-grid-element.component.ts new file mode 100644 index 0000000000..97d43356c6 --- /dev/null +++ b/src/app/entity-groups/journal-entities/item-grid-elements/search-result-grid-elements/journal/journal-search-result-grid-element.component.ts @@ -0,0 +1,20 @@ +import { Component } from '@angular/core'; +import { focusShadow } from '../../../../../shared/animations/focus'; +import { listableObjectComponent } from '../../../../../shared/object-collection/shared/listable-object/listable-object.decorator'; +import { ViewMode } from '../../../../../core/shared/view-mode.model'; +import { SearchResultGridElementComponent } from '../../../../../shared/object-grid/search-result-grid-element/search-result-grid-element.component'; +import { ItemSearchResult } from '../../../../../shared/object-collection/shared/item-search-result.model'; +import { Item } from '../../../../../core/shared/item.model'; + +@listableObjectComponent('JournalSearchResult', ViewMode.GridElement) +@Component({ + selector: 'ds-journal-search-result-grid-element', + styleUrls: ['./journal-search-result-grid-element.component.scss'], + templateUrl: './journal-search-result-grid-element.component.html', + animations: [focusShadow] +}) +/** + * The component for displaying a grid element for an item search result of the type Journal + */ +export class JournalSearchResultGridElementComponent extends SearchResultGridElementComponent { +} diff --git a/src/app/entity-groups/journal-entities/item-list-elements/journal-issue/journal-issue-list-element.component.html b/src/app/entity-groups/journal-entities/item-list-elements/journal-issue/journal-issue-list-element.component.html index 030a26df39..398feea260 100644 --- a/src/app/entity-groups/journal-entities/item-list-elements/journal-issue/journal-issue-list-element.component.html +++ b/src/app/entity-groups/journal-entities/item-list-elements/journal-issue/journal-issue-list-element.component.html @@ -1,21 +1 @@ - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/src/app/entity-groups/journal-entities/item-list-elements/journal-issue/journal-issue-list-element.component.spec.ts b/src/app/entity-groups/journal-entities/item-list-elements/journal-issue/journal-issue-list-element.component.spec.ts index 24498088cb..a7dfcbbf36 100644 --- a/src/app/entity-groups/journal-entities/item-list-elements/journal-issue/journal-issue-list-element.component.spec.ts +++ b/src/app/entity-groups/journal-entities/item-list-elements/journal-issue/journal-issue-list-element.component.spec.ts @@ -1,17 +1,13 @@ -import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { async, TestBed } from '@angular/core/testing'; import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA } from '@angular/core'; import { By } from '@angular/platform-browser'; import { JournalIssueListElementComponent } from './journal-issue-list-element.component'; import { of as observableOf } from 'rxjs'; import { Item } from '../../../../core/shared/item.model'; import { TruncatePipe } from '../../../../shared/utils/truncate.pipe'; -import { ITEM } from '../../../../shared/items/switcher/item-type-switcher.component'; import { TruncatableService } from '../../../../shared/truncatable/truncatable.service'; -let journalIssueListElementComponent: JournalIssueListElementComponent; -let fixture: ComponentFixture; - -const mockItemWithMetadata: Item = Object.assign(new Item(), { +const mockItem: Item = Object.assign(new Item(), { bitstreams: observableOf({}), metadata: { 'dc.title': [ @@ -34,28 +30,22 @@ const mockItemWithMetadata: Item = Object.assign(new Item(), { ] } }); -const mockItemWithoutMetadata: Item = Object.assign(new Item(), { - bitstreams: observableOf({}), - metadata: { - 'dc.title': [ - { - language: 'en_US', - value: 'This is just another title' - } - ] - } -}); describe('JournalIssueListElementComponent', () => { + let comp; + let fixture; + + const truncatableServiceStub: any = { + isCollapsed: (id: number) => observableOf(true), + }; + beforeEach(async(() => { TestBed.configureTestingModule({ - declarations: [ JournalIssueListElementComponent , TruncatePipe], + declarations: [JournalIssueListElementComponent, TruncatePipe], providers: [ - { provide: ITEM, useValue: mockItemWithMetadata}, - { provide: TruncatableService, useValue: {} } + { provide: TruncatableService, useValue: truncatableServiceStub }, ], - - schemas: [ NO_ERRORS_SCHEMA ] + schemas: [NO_ERRORS_SCHEMA] }).overrideComponent(JournalIssueListElementComponent, { set: { changeDetection: ChangeDetectionStrategy.Default } }).compileComponents(); @@ -63,55 +53,19 @@ describe('JournalIssueListElementComponent', () => { beforeEach(async(() => { fixture = TestBed.createComponent(JournalIssueListElementComponent); - journalIssueListElementComponent = fixture.componentInstance; - + comp = fixture.componentInstance; })); - describe('When the item has a journal identifier', () => { + describe(`when the journal issue is rendered`, () => { beforeEach(() => { - journalIssueListElementComponent.item = mockItemWithMetadata; + comp.object = mockItem; fixture.detectChanges(); }); - it('should show the journal issues span', () => { - const journalIdentifierField = fixture.debugElement.query(By.css('span.item-list-journal-issues')); - expect(journalIdentifierField).not.toBeNull(); + it(`should contain a JournalIssueListElementComponent`, () => { + const journalIssueListElement = fixture.debugElement.query(By.css(`ds-journal-issue-search-result-list-element`)); + expect(journalIssueListElement).not.toBeNull(); }); }); - describe('When the item has no journal identifier', () => { - beforeEach(() => { - journalIssueListElementComponent.item = mockItemWithoutMetadata; - fixture.detectChanges(); - }); - - it('should not show the journal issues span', () => { - const journalIdentifierField = fixture.debugElement.query(By.css('span.item-list-journal-issues')); - expect(journalIdentifierField).toBeNull(); - }); - }); - - describe('When the item has a journal number', () => { - beforeEach(() => { - journalIssueListElementComponent.item = mockItemWithMetadata; - fixture.detectChanges(); - }); - - it('should show the journal issue numbers span', () => { - const journalNumberField = fixture.debugElement.query(By.css('span.item-list-journal-issue-numbers')); - expect(journalNumberField).not.toBeNull(); - }); - }); - - describe('When the item has no journal number', () => { - beforeEach(() => { - journalIssueListElementComponent.item = mockItemWithoutMetadata; - fixture.detectChanges(); - }); - - it('should not show the journal issue numbers span', () => { - const journalNumberField = fixture.debugElement.query(By.css('span.item-list-journal-issue-numbers')); - expect(journalNumberField).toBeNull(); - }); - }); }); diff --git a/src/app/entity-groups/journal-entities/item-list-elements/journal-issue/journal-issue-list-element.component.ts b/src/app/entity-groups/journal-entities/item-list-elements/journal-issue/journal-issue-list-element.component.ts index e1aeb7c4e6..454c140050 100644 --- a/src/app/entity-groups/journal-entities/item-list-elements/journal-issue/journal-issue-list-element.component.ts +++ b/src/app/entity-groups/journal-entities/item-list-elements/journal-issue/journal-issue-list-element.component.ts @@ -1,8 +1,10 @@ import { Component } from '@angular/core'; -import { ItemViewMode, rendersItemType } from '../../../../shared/items/item-type-decorator'; -import { TypedItemSearchResultListElementComponent } from '../../../../shared/object-list/item-list-element/item-types/typed-item-search-result-list-element.component'; +import { ViewMode } from '../../../../core/shared/view-mode.model'; +import { listableObjectComponent } from '../../../../shared/object-collection/shared/listable-object/listable-object.decorator'; +import { AbstractListableElementComponent } from '../../../../shared/object-collection/shared/object-collection-element/abstract-listable-element.component'; +import { Item } from '../../../../core/shared/item.model'; -@rendersItemType('JournalIssue', ItemViewMode.Element) +@listableObjectComponent('JournalIssue', ViewMode.ListElement) @Component({ selector: 'ds-journal-issue-list-element', styleUrls: ['./journal-issue-list-element.component.scss'], @@ -11,5 +13,5 @@ import { TypedItemSearchResultListElementComponent } from '../../../../shared/ob /** * The component for displaying a list element for an item of the type Journal Issue */ -export class JournalIssueListElementComponent extends TypedItemSearchResultListElementComponent { +export class JournalIssueListElementComponent extends AbstractListableElementComponent { } diff --git a/src/app/entity-groups/journal-entities/item-list-elements/journal-volume/journal-volume-list-element.component.html b/src/app/entity-groups/journal-entities/item-list-elements/journal-volume/journal-volume-list-element.component.html index 4e6e34d3d6..bf967e6e78 100644 --- a/src/app/entity-groups/journal-entities/item-list-elements/journal-volume/journal-volume-list-element.component.html +++ b/src/app/entity-groups/journal-entities/item-list-elements/journal-volume/journal-volume-list-element.component.html @@ -1,21 +1 @@ - - - - - - - - - - - - () - - - - - + \ No newline at end of file diff --git a/src/app/entity-groups/journal-entities/item-list-elements/journal-volume/journal-volume-list-element.component.spec.ts b/src/app/entity-groups/journal-entities/item-list-elements/journal-volume/journal-volume-list-element.component.spec.ts index 15f5424960..ba43805525 100644 --- a/src/app/entity-groups/journal-entities/item-list-elements/journal-volume/journal-volume-list-element.component.spec.ts +++ b/src/app/entity-groups/journal-entities/item-list-elements/journal-volume/journal-volume-list-element.component.spec.ts @@ -1,17 +1,13 @@ -import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { async, TestBed } from '@angular/core/testing'; import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA } from '@angular/core'; import { By } from '@angular/platform-browser'; import { JournalVolumeListElementComponent } from './journal-volume-list-element.component'; import { of as observableOf } from 'rxjs'; import { Item } from '../../../../core/shared/item.model'; import { TruncatePipe } from '../../../../shared/utils/truncate.pipe'; -import { ITEM } from '../../../../shared/items/switcher/item-type-switcher.component'; import { TruncatableService } from '../../../../shared/truncatable/truncatable.service'; -let journalVolumeListElementComponent: JournalVolumeListElementComponent; -let fixture: ComponentFixture; - -const mockItemWithMetadata: Item = Object.assign(new Item(), { +const mockItem: Item = Object.assign(new Item(), { bitstreams: observableOf({}), metadata: { 'dc.title': [ @@ -34,28 +30,22 @@ const mockItemWithMetadata: Item = Object.assign(new Item(), { ] } }); -const mockItemWithoutMetadata: Item = Object.assign(new Item(), { - bitstreams: observableOf({}), - metadata: { - 'dc.title': [ - { - language: 'en_US', - value: 'This is just another title' - } - ] - } -}); describe('JournalVolumeListElementComponent', () => { + let comp; + let fixture; + + const truncatableServiceStub: any = { + isCollapsed: (id: number) => observableOf(true), + }; + beforeEach(async(() => { TestBed.configureTestingModule({ - declarations: [ JournalVolumeListElementComponent , TruncatePipe], + declarations: [JournalVolumeListElementComponent, TruncatePipe], providers: [ - { provide: ITEM, useValue: mockItemWithMetadata}, - { provide: TruncatableService, useValue: {} } + { provide: TruncatableService, useValue: truncatableServiceStub }, ], - - schemas: [ NO_ERRORS_SCHEMA ] + schemas: [NO_ERRORS_SCHEMA] }).overrideComponent(JournalVolumeListElementComponent, { set: { changeDetection: ChangeDetectionStrategy.Default } }).compileComponents(); @@ -63,55 +53,18 @@ describe('JournalVolumeListElementComponent', () => { beforeEach(async(() => { fixture = TestBed.createComponent(JournalVolumeListElementComponent); - journalVolumeListElementComponent = fixture.componentInstance; - + comp = fixture.componentInstance; })); - describe('When the item has a journal title', () => { + describe(`when the journal volume is rendered`, () => { beforeEach(() => { - journalVolumeListElementComponent.item = mockItemWithMetadata; + comp.object = mockItem; fixture.detectChanges(); }); - it('should show the journal title span', () => { - const journalTitleField = fixture.debugElement.query(By.css('span.item-list-journal-volumes')); - expect(journalTitleField).not.toBeNull(); - }); - }); - - describe('When the item has no journal title', () => { - beforeEach(() => { - journalVolumeListElementComponent.item = mockItemWithoutMetadata; - fixture.detectChanges(); - }); - - it('should not show the journal title span', () => { - const journalTitleField = fixture.debugElement.query(By.css('span.item-list-journal-volumes')); - expect(journalTitleField).toBeNull(); - }); - }); - - describe('When the item has a journal identifier', () => { - beforeEach(() => { - journalVolumeListElementComponent.item = mockItemWithMetadata; - fixture.detectChanges(); - }); - - it('should show the journal identifiers span', () => { - const journalIdentifierField = fixture.debugElement.query(By.css('span.item-list-journal-volume-identifiers')); - expect(journalIdentifierField).not.toBeNull(); - }); - }); - - describe('When the item has no journal identifier', () => { - beforeEach(() => { - journalVolumeListElementComponent.item = mockItemWithoutMetadata; - fixture.detectChanges(); - }); - - it('should not show the journal identifiers span', () => { - const journalIdentifierField = fixture.debugElement.query(By.css('span.item-list-journal-volume-identifiers')); - expect(journalIdentifierField).toBeNull(); + it(`should contain a JournalVolumeListElementComponent`, () => { + const journalVolumeListElement = fixture.debugElement.query(By.css(`ds-journal-volume-search-result-list-element`)); + expect(journalVolumeListElement).not.toBeNull(); }); }); }); diff --git a/src/app/entity-groups/journal-entities/item-list-elements/journal-volume/journal-volume-list-element.component.ts b/src/app/entity-groups/journal-entities/item-list-elements/journal-volume/journal-volume-list-element.component.ts index 42e83ea7bd..641a0d2238 100644 --- a/src/app/entity-groups/journal-entities/item-list-elements/journal-volume/journal-volume-list-element.component.ts +++ b/src/app/entity-groups/journal-entities/item-list-elements/journal-volume/journal-volume-list-element.component.ts @@ -1,8 +1,10 @@ import { Component } from '@angular/core'; -import { ItemViewMode, rendersItemType } from '../../../../shared/items/item-type-decorator'; -import { TypedItemSearchResultListElementComponent } from '../../../../shared/object-list/item-list-element/item-types/typed-item-search-result-list-element.component'; +import { ViewMode } from '../../../../core/shared/view-mode.model'; +import { listableObjectComponent } from '../../../../shared/object-collection/shared/listable-object/listable-object.decorator'; +import { AbstractListableElementComponent } from '../../../../shared/object-collection/shared/object-collection-element/abstract-listable-element.component'; +import { Item } from '../../../../core/shared/item.model'; -@rendersItemType('JournalVolume', ItemViewMode.Element) +@listableObjectComponent('JournalVolume', ViewMode.ListElement) @Component({ selector: 'ds-journal-volume-list-element', styleUrls: ['./journal-volume-list-element.component.scss'], @@ -11,5 +13,5 @@ import { TypedItemSearchResultListElementComponent } from '../../../../shared/ob /** * The component for displaying a list element for an item of the type Journal Volume */ -export class JournalVolumeListElementComponent extends TypedItemSearchResultListElementComponent { +export class JournalVolumeListElementComponent extends AbstractListableElementComponent { } diff --git a/src/app/entity-groups/journal-entities/item-list-elements/journal/journal-list-element.component.html b/src/app/entity-groups/journal-entities/item-list-elements/journal/journal-list-element.component.html index 0e46e921bb..3e4dfb0b48 100644 --- a/src/app/entity-groups/journal-entities/item-list-elements/journal/journal-list-element.component.html +++ b/src/app/entity-groups/journal-entities/item-list-elements/journal/journal-list-element.component.html @@ -1,15 +1 @@ - - - - - - - - - - - - + \ No newline at end of file diff --git a/src/app/entity-groups/journal-entities/item-list-elements/journal/journal-list-element.component.spec.ts b/src/app/entity-groups/journal-entities/item-list-elements/journal/journal-list-element.component.spec.ts index 204672dfe9..6581619787 100644 --- a/src/app/entity-groups/journal-entities/item-list-elements/journal/journal-list-element.component.spec.ts +++ b/src/app/entity-groups/journal-entities/item-list-elements/journal/journal-list-element.component.spec.ts @@ -1,17 +1,13 @@ -import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { async, TestBed } from '@angular/core/testing'; import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA } from '@angular/core'; import { By } from '@angular/platform-browser'; import { JournalListElementComponent } from './journal-list-element.component'; import { of as observableOf } from 'rxjs'; import { Item } from '../../../../core/shared/item.model'; import { TruncatePipe } from '../../../../shared/utils/truncate.pipe'; -import { ITEM } from '../../../../shared/items/switcher/item-type-switcher.component'; import { TruncatableService } from '../../../../shared/truncatable/truncatable.service'; -let journalListElementComponent: JournalListElementComponent; -let fixture: ComponentFixture; - -const mockItemWithMetadata: Item = Object.assign(new Item(), { +const mockItem: Item = Object.assign(new Item(), { bitstreams: observableOf({}), metadata: { 'dc.title': [ @@ -28,28 +24,22 @@ const mockItemWithMetadata: Item = Object.assign(new Item(), { ] } }); -const mockItemWithoutMetadata: Item = Object.assign(new Item(), { - bitstreams: observableOf({}), - metadata: { - 'dc.title': [ - { - language: 'en_US', - value: 'This is just another title' - } - ] - } -}); describe('JournalListElementComponent', () => { + let comp; + let fixture; + + const truncatableServiceStub: any = { + isCollapsed: (id: number) => observableOf(true), + }; + beforeEach(async(() => { TestBed.configureTestingModule({ - declarations: [ JournalListElementComponent , TruncatePipe], + declarations: [JournalListElementComponent, TruncatePipe], providers: [ - { provide: ITEM, useValue: mockItemWithMetadata}, - { provide: TruncatableService, useValue: {} } + { provide: TruncatableService, useValue: truncatableServiceStub }, ], - - schemas: [ NO_ERRORS_SCHEMA ] + schemas: [NO_ERRORS_SCHEMA] }).overrideComponent(JournalListElementComponent, { set: { changeDetection: ChangeDetectionStrategy.Default } }).compileComponents(); @@ -57,31 +47,18 @@ describe('JournalListElementComponent', () => { beforeEach(async(() => { fixture = TestBed.createComponent(JournalListElementComponent); - journalListElementComponent = fixture.componentInstance; - + comp = fixture.componentInstance; })); - describe('When the item has an issn', () => { + describe(`when the journal is rendered`, () => { beforeEach(() => { - journalListElementComponent.item = mockItemWithMetadata; + comp.object = mockItem; fixture.detectChanges(); }); - it('should show the journals span', () => { - const issnField = fixture.debugElement.query(By.css('span.item-list-journals')); - expect(issnField).not.toBeNull(); - }); - }); - - describe('When the item has no issn', () => { - beforeEach(() => { - journalListElementComponent.item = mockItemWithoutMetadata; - fixture.detectChanges(); - }); - - it('should not show the journals span', () => { - const issnField = fixture.debugElement.query(By.css('span.item-list-journals')); - expect(issnField).toBeNull(); + it(`should contain a JournalListElementComponent`, () => { + const journalListElement = fixture.debugElement.query(By.css(`ds-journal-search-result-list-element`)); + expect(journalListElement).not.toBeNull(); }); }); }); diff --git a/src/app/entity-groups/journal-entities/item-list-elements/journal/journal-list-element.component.ts b/src/app/entity-groups/journal-entities/item-list-elements/journal/journal-list-element.component.ts index fdcf0ba5b0..fa83c3cff4 100644 --- a/src/app/entity-groups/journal-entities/item-list-elements/journal/journal-list-element.component.ts +++ b/src/app/entity-groups/journal-entities/item-list-elements/journal/journal-list-element.component.ts @@ -1,8 +1,10 @@ import { Component } from '@angular/core'; -import { ItemViewMode, rendersItemType } from '../../../../shared/items/item-type-decorator'; -import { TypedItemSearchResultListElementComponent } from '../../../../shared/object-list/item-list-element/item-types/typed-item-search-result-list-element.component'; +import { ViewMode } from '../../../../core/shared/view-mode.model'; +import { listableObjectComponent } from '../../../../shared/object-collection/shared/listable-object/listable-object.decorator'; +import { AbstractListableElementComponent } from '../../../../shared/object-collection/shared/object-collection-element/abstract-listable-element.component'; +import { Item } from '../../../../core/shared/item.model'; -@rendersItemType('Journal', ItemViewMode.Element) +@listableObjectComponent('Journal', ViewMode.ListElement) @Component({ selector: 'ds-journal-list-element', styleUrls: ['./journal-list-element.component.scss'], @@ -11,5 +13,5 @@ import { TypedItemSearchResultListElementComponent } from '../../../../shared/ob /** * The component for displaying a list element for an item of the type Journal */ -export class JournalListElementComponent extends TypedItemSearchResultListElementComponent { +export class JournalListElementComponent extends AbstractListableElementComponent { } diff --git a/src/app/entity-groups/journal-entities/item-list-elements/search-result-list-elements/journal-issue/journal-issue-search-result-list-element.component.html b/src/app/entity-groups/journal-entities/item-list-elements/search-result-list-elements/journal-issue/journal-issue-search-result-list-element.component.html new file mode 100644 index 0000000000..38094c5c79 --- /dev/null +++ b/src/app/entity-groups/journal-entities/item-list-elements/search-result-list-elements/journal-issue/journal-issue-search-result-list-element.component.html @@ -0,0 +1,25 @@ + + + + + + + + + + + + + - + + + + + + diff --git a/src/app/shared/object-list/search-result-list-element/item-search-result/item-search-result-list-element.component.scss b/src/app/entity-groups/journal-entities/item-list-elements/search-result-list-elements/journal-issue/journal-issue-search-result-list-element.component.scss similarity index 100% rename from src/app/shared/object-list/search-result-list-element/item-search-result/item-search-result-list-element.component.scss rename to src/app/entity-groups/journal-entities/item-list-elements/search-result-list-elements/journal-issue/journal-issue-search-result-list-element.component.scss diff --git a/src/app/entity-groups/journal-entities/item-list-elements/search-result-list-elements/journal-issue/journal-issue-search-result-list-element.component.spec.ts b/src/app/entity-groups/journal-entities/item-list-elements/search-result-list-elements/journal-issue/journal-issue-search-result-list-element.component.spec.ts new file mode 100644 index 0000000000..ab02ce244e --- /dev/null +++ b/src/app/entity-groups/journal-entities/item-list-elements/search-result-list-elements/journal-issue/journal-issue-search-result-list-element.component.spec.ts @@ -0,0 +1,125 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA } from '@angular/core'; +import { By } from '@angular/platform-browser'; +import { of as observableOf } from 'rxjs'; +import { ItemSearchResult } from '../../../../../shared/object-collection/shared/item-search-result.model'; +import { JournalIssueSearchResultListElementComponent } from './journal-issue-search-result-list-element.component'; +import { Item } from '../../../../../core/shared/item.model'; +import { TruncatePipe } from '../../../../../shared/utils/truncate.pipe'; +import { TruncatableService } from '../../../../../shared/truncatable/truncatable.service'; + +let journalIssueListElementComponent: JournalIssueSearchResultListElementComponent; +let fixture: ComponentFixture; + +const mockItemWithMetadata: ItemSearchResult = Object.assign( + new ItemSearchResult(), + { + indexableObject: Object.assign(new Item(), { + bitstreams: observableOf({}), + metadata: { + 'dc.title': [ + { + language: 'en_US', + value: 'This is just another title' + } + ], + 'publicationvolume.volumeNumber': [ + { + language: 'en_US', + value: '1234' + } + ], + 'publicationissue.issueNumber': [ + { + language: 'en_US', + value: '5678' + } + ] + } + }) + }); + +const mockItemWithoutMetadata: ItemSearchResult = Object.assign( + new ItemSearchResult(), + { + indexableObject: Object.assign(new Item(), { + bitstreams: observableOf({}), + metadata: { + 'dc.title': [ + { + language: 'en_US', + value: 'This is just another title' + } + ] + } + }) + }); + +describe('JournalIssueSearchResultListElementComponent', () => { + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [JournalIssueSearchResultListElementComponent, TruncatePipe], + providers: [ + { provide: TruncatableService, useValue: {} } + ], + + schemas: [NO_ERRORS_SCHEMA] + }).overrideComponent(JournalIssueSearchResultListElementComponent, { + set: { changeDetection: ChangeDetectionStrategy.Default } + }).compileComponents(); + })); + + beforeEach(async(() => { + fixture = TestBed.createComponent(JournalIssueSearchResultListElementComponent); + journalIssueListElementComponent = fixture.componentInstance; + + })); + + describe('When the item has a journal identifier', () => { + beforeEach(() => { + journalIssueListElementComponent.object = mockItemWithMetadata; + fixture.detectChanges(); + }); + + it('should show the journal issues span', () => { + const journalIdentifierField = fixture.debugElement.query(By.css('span.item-list-journal-issues')); + expect(journalIdentifierField).not.toBeNull(); + }); + }); + + describe('When the item has no journal identifier', () => { + beforeEach(() => { + journalIssueListElementComponent.object = mockItemWithoutMetadata; + fixture.detectChanges(); + }); + + it('should not show the journal issues span', () => { + const journalIdentifierField = fixture.debugElement.query(By.css('span.item-list-journal-issues')); + expect(journalIdentifierField).toBeNull(); + }); + }); + + describe('When the item has a journal number', () => { + beforeEach(() => { + journalIssueListElementComponent.object = mockItemWithMetadata; + fixture.detectChanges(); + }); + + it('should show the journal issue numbers span', () => { + const journalNumberField = fixture.debugElement.query(By.css('span.item-list-journal-issue-numbers')); + expect(journalNumberField).not.toBeNull(); + }); + }); + + describe('When the item has no journal number', () => { + beforeEach(() => { + journalIssueListElementComponent.object = mockItemWithoutMetadata; + fixture.detectChanges(); + }); + + it('should not show the journal issue numbers span', () => { + const journalNumberField = fixture.debugElement.query(By.css('span.item-list-journal-issue-numbers')); + expect(journalNumberField).toBeNull(); + }); + }); +}); diff --git a/src/app/entity-groups/journal-entities/item-list-elements/search-result-list-elements/journal-issue/journal-issue-search-result-list-element.component.ts b/src/app/entity-groups/journal-entities/item-list-elements/search-result-list-elements/journal-issue/journal-issue-search-result-list-element.component.ts new file mode 100644 index 0000000000..1d320cbfe8 --- /dev/null +++ b/src/app/entity-groups/journal-entities/item-list-elements/search-result-list-elements/journal-issue/journal-issue-search-result-list-element.component.ts @@ -0,0 +1,18 @@ +import { Component } from '@angular/core'; +import { listableObjectComponent } from '../../../../../shared/object-collection/shared/listable-object/listable-object.decorator'; +import { ViewMode } from '../../../../../core/shared/view-mode.model'; +import { SearchResultListElementComponent } from '../../../../../shared/object-list/search-result-list-element/search-result-list-element.component'; +import { ItemSearchResult } from '../../../../../shared/object-collection/shared/item-search-result.model'; +import { Item } from '../../../../../core/shared/item.model'; + +@listableObjectComponent('JournalIssueSearchResult', ViewMode.ListElement) +@Component({ + selector: 'ds-journal-issue-search-result-list-element', + styleUrls: ['./journal-issue-search-result-list-element.component.scss'], + templateUrl: './journal-issue-search-result-list-element.component.html' +}) +/** + * The component for displaying a list element for an item search result of the type Journal Issue + */ +export class JournalIssueSearchResultListElementComponent extends SearchResultListElementComponent { +} diff --git a/src/app/entity-groups/journal-entities/item-list-elements/search-result-list-elements/journal-volume/journal-volume-search-result-list-element.component.html b/src/app/entity-groups/journal-entities/item-list-elements/search-result-list-elements/journal-volume/journal-volume-search-result-list-element.component.html new file mode 100644 index 0000000000..460c4a2187 --- /dev/null +++ b/src/app/entity-groups/journal-entities/item-list-elements/search-result-list-elements/journal-volume/journal-volume-search-result-list-element.component.html @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + () + + + + + diff --git a/src/app/entity-groups/journal-entities/item-list-elements/search-result-list-elements/journal-volume/journal-volume-search-result-list-element.component.scss b/src/app/entity-groups/journal-entities/item-list-elements/search-result-list-elements/journal-volume/journal-volume-search-result-list-element.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/entity-groups/journal-entities/item-list-elements/search-result-list-elements/journal-volume/journal-volume-search-result-list-element.component.spec.ts b/src/app/entity-groups/journal-entities/item-list-elements/search-result-list-elements/journal-volume/journal-volume-search-result-list-element.component.spec.ts new file mode 100644 index 0000000000..4ac4e51439 --- /dev/null +++ b/src/app/entity-groups/journal-entities/item-list-elements/search-result-list-elements/journal-volume/journal-volume-search-result-list-element.component.spec.ts @@ -0,0 +1,124 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA } from '@angular/core'; +import { By } from '@angular/platform-browser'; +import { of as observableOf } from 'rxjs'; +import { ItemSearchResult } from '../../../../../shared/object-collection/shared/item-search-result.model'; +import { Item } from '../../../../../core/shared/item.model'; +import { JournalVolumeSearchResultListElementComponent } from './journal-volume-search-result-list-element.component'; +import { TruncatePipe } from '../../../../../shared/utils/truncate.pipe'; +import { TruncatableService } from '../../../../../shared/truncatable/truncatable.service'; + +let journalVolumeListElementComponent: JournalVolumeSearchResultListElementComponent; +let fixture: ComponentFixture; + +const mockItemWithMetadata: ItemSearchResult = Object.assign( + new ItemSearchResult(), + { + indexableObject: Object.assign(new Item(), { + bitstreams: observableOf({}), + metadata: { + 'dc.title': [ + { + language: 'en_US', + value: 'This is just another title' + } + ], + 'journal.title': [ + { + language: 'en_US', + value: 'This is just another journal title' + } + ], + 'publicationvolume.volumeNumber': [ + { + language: 'en_US', + value: '1234' + } + ] + } + }) + }); +const mockItemWithoutMetadata: ItemSearchResult = Object.assign( + new ItemSearchResult(), + { + indexableObject: Object.assign(new Item(), { + bitstreams: observableOf({}), + metadata: { + 'dc.title': [ + { + language: 'en_US', + value: 'This is just another title' + } + ] + } + }) + }); + +describe('JournalVolumeSearchResultListElementComponent', () => { + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [JournalVolumeSearchResultListElementComponent, TruncatePipe], + providers: [ + { provide: TruncatableService, useValue: {} } + ], + + schemas: [NO_ERRORS_SCHEMA] + }).overrideComponent(JournalVolumeSearchResultListElementComponent, { + set: { changeDetection: ChangeDetectionStrategy.Default } + }).compileComponents(); + })); + + beforeEach(async(() => { + fixture = TestBed.createComponent(JournalVolumeSearchResultListElementComponent); + journalVolumeListElementComponent = fixture.componentInstance; + + })); + + describe('When the item has a journal title', () => { + beforeEach(() => { + journalVolumeListElementComponent.object = mockItemWithMetadata; + fixture.detectChanges(); + }); + + it('should show the journal title span', () => { + const journalTitleField = fixture.debugElement.query(By.css('span.item-list-journal-volumes')); + expect(journalTitleField).not.toBeNull(); + }); + }); + + describe('When the item has no journal title', () => { + beforeEach(() => { + journalVolumeListElementComponent.object = mockItemWithoutMetadata; + fixture.detectChanges(); + }); + + it('should not show the journal title span', () => { + const journalTitleField = fixture.debugElement.query(By.css('span.item-list-journal-volumes')); + expect(journalTitleField).toBeNull(); + }); + }); + + describe('When the item has a journal identifier', () => { + beforeEach(() => { + journalVolumeListElementComponent.object = mockItemWithMetadata; + fixture.detectChanges(); + }); + + it('should show the journal identifiers span', () => { + const journalIdentifierField = fixture.debugElement.query(By.css('span.item-list-journal-volume-identifiers')); + expect(journalIdentifierField).not.toBeNull(); + }); + }); + + describe('When the item has no journal identifier', () => { + beforeEach(() => { + journalVolumeListElementComponent.object = mockItemWithoutMetadata; + fixture.detectChanges(); + }); + + it('should not show the journal identifiers span', () => { + const journalIdentifierField = fixture.debugElement.query(By.css('span.item-list-journal-volume-identifiers')); + expect(journalIdentifierField).toBeNull(); + }); + }); +}); diff --git a/src/app/entity-groups/journal-entities/item-list-elements/search-result-list-elements/journal-volume/journal-volume-search-result-list-element.component.ts b/src/app/entity-groups/journal-entities/item-list-elements/search-result-list-elements/journal-volume/journal-volume-search-result-list-element.component.ts new file mode 100644 index 0000000000..41795b8022 --- /dev/null +++ b/src/app/entity-groups/journal-entities/item-list-elements/search-result-list-elements/journal-volume/journal-volume-search-result-list-element.component.ts @@ -0,0 +1,18 @@ +import { Component } from '@angular/core'; +import { SearchResultListElementComponent } from '../../../../../shared/object-list/search-result-list-element/search-result-list-element.component'; +import { ItemSearchResult } from '../../../../../shared/object-collection/shared/item-search-result.model'; +import { Item } from '../../../../../core/shared/item.model'; +import { listableObjectComponent } from '../../../../../shared/object-collection/shared/listable-object/listable-object.decorator'; +import { ViewMode } from '../../../../../core/shared/view-mode.model'; + +@listableObjectComponent('JournalVolumeSearchResult', ViewMode.ListElement) +@Component({ + selector: 'ds-journal-volume-search-result-list-element', + styleUrls: ['./journal-volume-search-result-list-element.component.scss'], + templateUrl: './journal-volume-search-result-list-element.component.html' +}) +/** + * The component for displaying a list element for an item search result of the type Journal Volume + */ +export class JournalVolumeSearchResultListElementComponent extends SearchResultListElementComponent { +} diff --git a/src/app/entity-groups/journal-entities/item-list-elements/search-result-list-elements/journal/journal-search-result-list-element.component.html b/src/app/entity-groups/journal-entities/item-list-elements/search-result-list-elements/journal/journal-search-result-list-element.component.html new file mode 100644 index 0000000000..a43132d332 --- /dev/null +++ b/src/app/entity-groups/journal-entities/item-list-elements/search-result-list-elements/journal/journal-search-result-list-element.component.html @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + diff --git a/src/app/entity-groups/journal-entities/item-list-elements/search-result-list-elements/journal/journal-search-result-list-element.component.scss b/src/app/entity-groups/journal-entities/item-list-elements/search-result-list-elements/journal/journal-search-result-list-element.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/entity-groups/journal-entities/item-list-elements/search-result-list-elements/journal/journal-search-result-list-element.component.spec.ts b/src/app/entity-groups/journal-entities/item-list-elements/search-result-list-elements/journal/journal-search-result-list-element.component.spec.ts new file mode 100644 index 0000000000..46eeaa1fb2 --- /dev/null +++ b/src/app/entity-groups/journal-entities/item-list-elements/search-result-list-elements/journal/journal-search-result-list-element.component.spec.ts @@ -0,0 +1,96 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA } from '@angular/core'; +import { By } from '@angular/platform-browser'; +import { of as observableOf } from 'rxjs'; +import { JournalSearchResultListElementComponent } from './journal-search-result-list-element.component'; +import { Item } from '../../../../../core/shared/item.model'; +import { TruncatePipe } from '../../../../../shared/utils/truncate.pipe'; +import { TruncatableService } from '../../../../../shared/truncatable/truncatable.service'; +import { ItemSearchResult } from '../../../../../shared/object-collection/shared/item-search-result.model'; + +let journalListElementComponent: JournalSearchResultListElementComponent; +let fixture: ComponentFixture; + +const mockItemWithMetadata: ItemSearchResult = Object.assign( + new ItemSearchResult(), + { + indexableObject: Object.assign(new Item(), { + bitstreams: observableOf({}), + metadata: { + 'dc.title': [ + { + language: 'en_US', + value: 'This is just another title' + } + ], + 'creativeworkseries.issn': [ + { + language: 'en_US', + value: '1234' + } + ] + } + }) + }); + +const mockItemWithoutMetadata: ItemSearchResult = Object.assign( + new ItemSearchResult(), + { + indexableObject: Object.assign(new Item(), { + bitstreams: observableOf({}), + metadata: { + 'dc.title': [ + { + language: 'en_US', + value: 'This is just another title' + } + ] + } + }) + } +); + +describe('JournalSearchResultListElementComponent', () => { + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [JournalSearchResultListElementComponent, TruncatePipe], + providers: [ + { provide: TruncatableService, useValue: {} } + ], + + schemas: [NO_ERRORS_SCHEMA] + }).overrideComponent(JournalSearchResultListElementComponent, { + set: { changeDetection: ChangeDetectionStrategy.Default } + }).compileComponents(); + })); + + beforeEach(async(() => { + fixture = TestBed.createComponent(JournalSearchResultListElementComponent); + journalListElementComponent = fixture.componentInstance; + + })); + + describe('When the item has an issn', () => { + beforeEach(() => { + journalListElementComponent.object = mockItemWithMetadata; + fixture.detectChanges(); + }); + + it('should show the journals span', () => { + const issnField = fixture.debugElement.query(By.css('span.item-list-journals')); + expect(issnField).not.toBeNull(); + }); + }); + + describe('When the item has no issn', () => { + beforeEach(() => { + journalListElementComponent.object = mockItemWithoutMetadata; + fixture.detectChanges(); + }); + + it('should not show the journals span', () => { + const issnField = fixture.debugElement.query(By.css('span.item-list-journals')); + expect(issnField).toBeNull(); + }); + }); +}); diff --git a/src/app/entity-groups/journal-entities/item-list-elements/search-result-list-elements/journal/journal-search-result-list-element.component.ts b/src/app/entity-groups/journal-entities/item-list-elements/search-result-list-elements/journal/journal-search-result-list-element.component.ts new file mode 100644 index 0000000000..01de0d4626 --- /dev/null +++ b/src/app/entity-groups/journal-entities/item-list-elements/search-result-list-elements/journal/journal-search-result-list-element.component.ts @@ -0,0 +1,18 @@ +import { Component } from '@angular/core'; +import { SearchResultListElementComponent } from '../../../../../shared/object-list/search-result-list-element/search-result-list-element.component'; +import { ItemSearchResult } from '../../../../../shared/object-collection/shared/item-search-result.model'; +import { Item } from '../../../../../core/shared/item.model'; +import { listableObjectComponent } from '../../../../../shared/object-collection/shared/listable-object/listable-object.decorator'; +import { ViewMode } from '../../../../../core/shared/view-mode.model'; + +@listableObjectComponent('JournalSearchResult', ViewMode.ListElement) +@Component({ + selector: 'ds-journal-search-result-list-element', + styleUrls: ['./journal-search-result-list-element.component.scss'], + templateUrl: './journal-search-result-list-element.component.html' +}) +/** + * The component for displaying a list element for an item search result of the type Journal + */ +export class JournalSearchResultListElementComponent extends SearchResultListElementComponent { +} diff --git a/src/app/entity-groups/journal-entities/item-pages/journal-issue/journal-issue.component.html b/src/app/entity-groups/journal-entities/item-pages/journal-issue/journal-issue.component.html index 8db50e78c4..87312f8784 100644 --- a/src/app/entity-groups/journal-entities/item-pages/journal-issue/journal-issue.component.html +++ b/src/app/entity-groups/journal-entities/item-pages/journal-issue/journal-issue.component.html @@ -1,54 +1,54 @@

- {{'journalissue.page.titleprefix' | translate}} + {{'journalissue.page.titleprefix' | translate}}

- + - - - - -
- - diff --git a/src/app/entity-groups/journal-entities/item-pages/journal-issue/journal-issue.component.spec.ts b/src/app/entity-groups/journal-entities/item-pages/journal-issue/journal-issue.component.spec.ts index 00403473a7..4c67708b8b 100644 --- a/src/app/entity-groups/journal-entities/item-pages/journal-issue/journal-issue.component.spec.ts +++ b/src/app/entity-groups/journal-entities/item-pages/journal-issue/journal-issue.component.spec.ts @@ -1,13 +1,8 @@ import { Item } from '../../../../core/shared/item.model'; -import { RemoteData } from '../../../../core/data/remote-data'; import { PaginatedList } from '../../../../core/data/paginated-list'; import { PageInfo } from '../../../../core/shared/page-info.model'; import { JournalIssueComponent } from './journal-issue.component'; -import { of as observableOf } from 'rxjs'; -import { - createRelationshipsObservable, - getItemPageFieldsTest -} from '../../../../+item-page/simple/item-types/shared/item.component.spec'; +import { createRelationshipsObservable, getItemPageFieldsTest } from '../../../../+item-page/simple/item-types/shared/item.component.spec'; import { createSuccessfulRemoteDataObject$ } from '../../../../shared/testing/utils'; const mockItem: Item = Object.assign(new Item(), { diff --git a/src/app/entity-groups/journal-entities/item-pages/journal-issue/journal-issue.component.ts b/src/app/entity-groups/journal-entities/item-pages/journal-issue/journal-issue.component.ts index a105037b80..6f1cbf9923 100644 --- a/src/app/entity-groups/journal-entities/item-pages/journal-issue/journal-issue.component.ts +++ b/src/app/entity-groups/journal-entities/item-pages/journal-issue/journal-issue.component.ts @@ -1,8 +1,9 @@ import { Component } from '@angular/core'; -import { ItemViewMode, rendersItemType } from '../../../../shared/items/item-type-decorator'; import { ItemComponent } from '../../../../+item-page/simple/item-types/shared/item.component'; +import { listableObjectComponent } from '../../../../shared/object-collection/shared/listable-object/listable-object.decorator'; +import { ViewMode } from '../../../../core/shared/view-mode.model'; -@rendersItemType('JournalIssue', ItemViewMode.Full) +@listableObjectComponent('JournalIssue', ViewMode.StandalonePage) @Component({ selector: 'ds-journal-issue', styleUrls: ['./journal-issue.component.scss'], diff --git a/src/app/entity-groups/journal-entities/item-pages/journal-volume/journal-volume.component.html b/src/app/entity-groups/journal-entities/item-pages/journal-volume/journal-volume.component.html index 150037eccb..e77b24a98b 100644 --- a/src/app/entity-groups/journal-entities/item-pages/journal-volume/journal-volume.component.html +++ b/src/app/entity-groups/journal-entities/item-pages/journal-volume/journal-volume.component.html @@ -1,37 +1,37 @@

- {{'journalvolume.page.titleprefix' | translate}} + {{'journalvolume.page.titleprefix' | translate}}

- + - -
- diff --git a/src/app/entity-groups/journal-entities/item-pages/journal-volume/journal-volume.component.ts b/src/app/entity-groups/journal-entities/item-pages/journal-volume/journal-volume.component.ts index 83ef925e02..4219609aab 100644 --- a/src/app/entity-groups/journal-entities/item-pages/journal-volume/journal-volume.component.ts +++ b/src/app/entity-groups/journal-entities/item-pages/journal-volume/journal-volume.component.ts @@ -1,8 +1,9 @@ import { Component } from '@angular/core'; -import { ItemViewMode, rendersItemType } from '../../../../shared/items/item-type-decorator'; import { ItemComponent } from '../../../../+item-page/simple/item-types/shared/item.component'; +import { listableObjectComponent } from '../../../../shared/object-collection/shared/listable-object/listable-object.decorator'; +import { ViewMode } from '../../../../core/shared/view-mode.model'; -@rendersItemType('JournalVolume', ItemViewMode.Full) +@listableObjectComponent('JournalVolume', ViewMode.StandalonePage) @Component({ selector: 'ds-journal-volume', styleUrls: ['./journal-volume.component.scss'], diff --git a/src/app/entity-groups/journal-entities/item-pages/journal/journal.component.html b/src/app/entity-groups/journal-entities/item-pages/journal/journal.component.html index d22933a657..ae6c3a8914 100644 --- a/src/app/entity-groups/journal-entities/item-pages/journal/journal.component.html +++ b/src/app/entity-groups/journal-entities/item-pages/journal/journal.component.html @@ -1,42 +1,42 @@

- {{'journal.page.titleprefix' | translate}} + {{'journal.page.titleprefix' | translate}}

- + - - -
-
diff --git a/src/app/entity-groups/journal-entities/item-pages/journal/journal.component.spec.ts b/src/app/entity-groups/journal-entities/item-pages/journal/journal.component.spec.ts index c66c3a2462..10fdd3bf93 100644 --- a/src/app/entity-groups/journal-entities/item-pages/journal/journal.component.spec.ts +++ b/src/app/entity-groups/journal-entities/item-pages/journal/journal.component.spec.ts @@ -1,19 +1,16 @@ import { ChangeDetectionStrategy, DebugElement, NO_ERRORS_SCHEMA } from '@angular/core'; import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { TruncatableService } from '../../../../shared/truncatable/truncatable.service'; -import { ITEM } from '../../../../shared/items/switcher/item-type-switcher.component'; import { TruncatePipe } from '../../../../shared/utils/truncate.pipe'; import { ItemDataService } from '../../../../core/data/item-data.service'; import { Item } from '../../../../core/shared/item.model'; import { By } from '@angular/platform-browser'; import { TranslateLoader, TranslateModule } from '@ngx-translate/core'; import { MockTranslateLoader } from '../../../../shared/mocks/mock-translate-loader'; -import { RemoteData } from '../../../../core/data/remote-data'; import { PaginatedList } from '../../../../core/data/paginated-list'; import { PageInfo } from '../../../../core/shared/page-info.model'; import { isNotEmpty } from '../../../../shared/empty.util'; import { JournalComponent } from './journal.component'; -import { of as observableOf } from 'rxjs'; import { GenericItemPageFieldComponent } from '../../../../+item-page/simple/field-components/specific-field/generic/generic-item-page-field.component'; import { createSuccessfulRemoteDataObject$ } from '../../../../shared/testing/utils'; @@ -55,7 +52,6 @@ describe('JournalComponent', () => { })], declarations: [JournalComponent, GenericItemPageFieldComponent, TruncatePipe], providers: [ - {provide: ITEM, useValue: mockItem}, {provide: ItemDataService, useValue: {}}, {provide: TruncatableService, useValue: {}} ], @@ -69,6 +65,7 @@ describe('JournalComponent', () => { beforeEach(async(() => { fixture = TestBed.createComponent(JournalComponent); comp = fixture.componentInstance; + comp.object = mockItem; fixture.detectChanges(); })); diff --git a/src/app/entity-groups/journal-entities/item-pages/journal/journal.component.ts b/src/app/entity-groups/journal-entities/item-pages/journal/journal.component.ts index d03adf8487..dbbeb81662 100644 --- a/src/app/entity-groups/journal-entities/item-pages/journal/journal.component.ts +++ b/src/app/entity-groups/journal-entities/item-pages/journal/journal.component.ts @@ -1,8 +1,9 @@ import { Component } from '@angular/core'; -import { ItemViewMode, rendersItemType } from '../../../../shared/items/item-type-decorator'; import { ItemComponent } from '../../../../+item-page/simple/item-types/shared/item.component'; +import { listableObjectComponent } from '../../../../shared/object-collection/shared/listable-object/listable-object.decorator'; +import { ViewMode } from '../../../../core/shared/view-mode.model'; -@rendersItemType('Journal', ItemViewMode.Full) +@listableObjectComponent('Journal', ViewMode.StandalonePage) @Component({ selector: 'ds-journal', styleUrls: ['./journal.component.scss'], diff --git a/src/app/entity-groups/journal-entities/journal-entities.module.ts b/src/app/entity-groups/journal-entities/journal-entities.module.ts index 4033645e1b..d00eae1e54 100644 --- a/src/app/entity-groups/journal-entities/journal-entities.module.ts +++ b/src/app/entity-groups/journal-entities/journal-entities.module.ts @@ -12,6 +12,12 @@ import { TooltipModule } from 'ngx-bootstrap'; import { JournalIssueGridElementComponent } from './item-grid-elements/journal-issue/journal-issue-grid-element.component'; import { JournalVolumeGridElementComponent } from './item-grid-elements/journal-volume/journal-volume-grid-element.component'; import { JournalGridElementComponent } from './item-grid-elements/journal/journal-grid-element.component'; +import { JournalSearchResultListElementComponent } from './item-list-elements/search-result-list-elements/journal/journal-search-result-list-element.component'; +import { JournalSearchResultGridElementComponent } from './item-grid-elements/search-result-grid-elements/journal/journal-search-result-grid-element.component'; +import { JournalIssueSearchResultListElementComponent } from './item-list-elements/search-result-list-elements/journal-issue/journal-issue-search-result-list-element.component'; +import { JournalVolumeSearchResultListElementComponent } from './item-list-elements/search-result-list-elements/journal-volume/journal-volume-search-result-list-element.component'; +import { JournalIssueSearchResultGridElementComponent } from './item-grid-elements/search-result-grid-elements/journal-issue/journal-issue-search-result-grid-element.component'; +import { JournalVolumeSearchResultGridElementComponent } from './item-grid-elements/search-result-grid-elements/journal-volume/journal-volume-search-result-grid-element.component'; const ENTRY_COMPONENTS = [ JournalComponent, @@ -22,7 +28,13 @@ const ENTRY_COMPONENTS = [ JournalVolumeListElementComponent, JournalIssueGridElementComponent, JournalVolumeGridElementComponent, - JournalGridElementComponent + JournalGridElementComponent, + JournalSearchResultListElementComponent, + JournalIssueSearchResultListElementComponent, + JournalVolumeSearchResultListElementComponent, + JournalIssueSearchResultGridElementComponent, + JournalVolumeSearchResultGridElementComponent, + JournalSearchResultGridElementComponent ]; @NgModule({ diff --git a/src/app/entity-groups/research-entities/item-grid-elements/org-unit/org-unit-grid-element.component.html b/src/app/entity-groups/research-entities/item-grid-elements/org-unit/org-unit-grid-element.component.html new file mode 100644 index 0000000000..e4522398a6 --- /dev/null +++ b/src/app/entity-groups/research-entities/item-grid-elements/org-unit/org-unit-grid-element.component.html @@ -0,0 +1 @@ + diff --git a/src/app/entity-groups/research-entities/item-grid-elements/org-unit/org-unit-grid-element.component.scss b/src/app/entity-groups/research-entities/item-grid-elements/org-unit/org-unit-grid-element.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/entity-groups/research-entities/item-grid-elements/org-unit/org-unit-grid-element.component.spec.ts b/src/app/entity-groups/research-entities/item-grid-elements/org-unit/org-unit-grid-element.component.spec.ts new file mode 100644 index 0000000000..953cc78535 --- /dev/null +++ b/src/app/entity-groups/research-entities/item-grid-elements/org-unit/org-unit-grid-element.component.spec.ts @@ -0,0 +1,81 @@ +import { Item } from '../../../../core/shared/item.model'; +import { of as observableOf } from 'rxjs/internal/observable/of'; +import { OrgUnitGridElementComponent } from './org-unit-grid-element.component'; +import { createSuccessfulRemoteDataObject$ } from '../../../../shared/testing/utils'; +import { PaginatedList } from '../../../../core/data/paginated-list'; +import { PageInfo } from '../../../../core/shared/page-info.model'; +import { async, TestBed } from '@angular/core/testing'; +import { NoopAnimationsModule } from '@angular/platform-browser/animations'; +import { TruncatePipe } from '../../../../shared/utils/truncate.pipe'; +import { TruncatableService } from '../../../../shared/truncatable/truncatable.service'; +import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA } from '@angular/core'; +import { By } from '@angular/platform-browser'; + +const mockItem = Object.assign(new Item(), { + bitstreams: createSuccessfulRemoteDataObject$(new PaginatedList(new PageInfo(), [])), + metadata: { + 'dc.title': [ + { + language: 'en_US', + value: 'This is just another title' + } + ], + 'organization.foundingDate': [ + { + language: null, + value: '2015-06-26' + } + ], + 'organization.address.addressCountry': [ + { + language: 'en_US', + value: 'Belgium' + } + ], + 'organization.address.addressLocality': [ + { + language: 'en_US', + value: 'Brussels' + } + ] + } +}); + +describe('OrgUnitGridElementComponent', () => { + let comp; + let fixture; + + const truncatableServiceStub: any = { + isCollapsed: (id: number) => observableOf(true), + }; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + imports: [NoopAnimationsModule], + declarations: [OrgUnitGridElementComponent, TruncatePipe], + providers: [ + { provide: TruncatableService, useValue: truncatableServiceStub }, + ], + schemas: [NO_ERRORS_SCHEMA] + }).overrideComponent(OrgUnitGridElementComponent, { + set: { changeDetection: ChangeDetectionStrategy.Default } + }).compileComponents(); + })); + + beforeEach(async(() => { + fixture = TestBed.createComponent(OrgUnitGridElementComponent); + comp = fixture.componentInstance; + })); + + describe(`when the org unit is rendered`, () => { + beforeEach(() => { + comp.object = mockItem; + fixture.detectChanges(); + }); + + it(`should contain a OrgUnitGridElementComponent`, () => { + const orgUnitGridElement = fixture.debugElement.query(By.css(`ds-org-unit-search-result-grid-element`)); + expect(orgUnitGridElement).not.toBeNull(); + }); + }); +}); diff --git a/src/app/entity-groups/research-entities/item-grid-elements/org-unit/org-unit-grid-element.component.ts b/src/app/entity-groups/research-entities/item-grid-elements/org-unit/org-unit-grid-element.component.ts new file mode 100644 index 0000000000..05a7f6c8c5 --- /dev/null +++ b/src/app/entity-groups/research-entities/item-grid-elements/org-unit/org-unit-grid-element.component.ts @@ -0,0 +1,17 @@ +import { Component } from '@angular/core'; +import { ViewMode } from '../../../../core/shared/view-mode.model'; +import { listableObjectComponent } from '../../../../shared/object-collection/shared/listable-object/listable-object.decorator'; +import { AbstractListableElementComponent } from '../../../../shared/object-collection/shared/object-collection-element/abstract-listable-element.component'; +import { Item } from '../../../../core/shared/item.model'; + +@listableObjectComponent('OrgUnit', ViewMode.GridElement) +@Component({ + selector: 'ds-org-unit-grid-element', + styleUrls: ['./org-unit-grid-element.component.scss'], + templateUrl: './org-unit-grid-element.component.html', +}) +/** + * The component for displaying a grid element for an item of the type Organisation Unit + */ +export class OrgUnitGridElementComponent extends AbstractListableElementComponent { +} diff --git a/src/app/entity-groups/research-entities/item-grid-elements/orgunit/orgunit-grid-element.component.html b/src/app/entity-groups/research-entities/item-grid-elements/orgunit/orgunit-grid-element.component.html deleted file mode 100644 index a4765c4e8f..0000000000 --- a/src/app/entity-groups/research-entities/item-grid-elements/orgunit/orgunit-grid-element.component.html +++ /dev/null @@ -1,35 +0,0 @@ - -
- -
- - -
-
-
- - -

-
-

- - - -

-

- - {{dso.firstMetadataValue('organization.address.addressCountry')}} - - , - {{dso.firstMetadataValue('organization.address.addressLocality')}} - - -

-
- View -
-
-
-
diff --git a/src/app/entity-groups/research-entities/item-grid-elements/orgunit/orgunit-grid-element.component.ts b/src/app/entity-groups/research-entities/item-grid-elements/orgunit/orgunit-grid-element.component.ts deleted file mode 100644 index 0effc22027..0000000000 --- a/src/app/entity-groups/research-entities/item-grid-elements/orgunit/orgunit-grid-element.component.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { ItemViewMode, rendersItemType } from '../../../../shared/items/item-type-decorator'; -import { Component } from '@angular/core'; -import { focusShadow } from '../../../../shared/animations/focus'; -import { TypedItemSearchResultGridElementComponent } from '../../../../shared/object-grid/item-grid-element/item-types/typed-item-search-result-grid-element.component'; - -@rendersItemType('OrgUnit', ItemViewMode.Card) -@Component({ - selector: 'ds-orgunit-grid-element', - styleUrls: ['./orgunit-grid-element.component.scss'], - templateUrl: './orgunit-grid-element.component.html', - animations: [focusShadow] -}) -/** - * The component for displaying a grid element for an item of the type Organisation Unit - */ -export class OrgunitGridElementComponent extends TypedItemSearchResultGridElementComponent { -} diff --git a/src/app/entity-groups/research-entities/item-grid-elements/person/person-grid-element.component.html b/src/app/entity-groups/research-entities/item-grid-elements/person/person-grid-element.component.html index 331c2bd520..a431f5979f 100644 --- a/src/app/entity-groups/research-entities/item-grid-elements/person/person-grid-element.component.html +++ b/src/app/entity-groups/research-entities/item-grid-elements/person/person-grid-element.component.html @@ -1,30 +1 @@ - -
- -
- - -
-
-
- - -

-
- -

- - - -

-
- View -
-
-
-
+ \ No newline at end of file diff --git a/src/app/entity-groups/research-entities/item-grid-elements/person/person-grid-element.component.spec.ts b/src/app/entity-groups/research-entities/item-grid-elements/person/person-grid-element.component.spec.ts index 25268261e1..3edb0fdea7 100644 --- a/src/app/entity-groups/research-entities/item-grid-elements/person/person-grid-element.component.spec.ts +++ b/src/app/entity-groups/research-entities/item-grid-elements/person/person-grid-element.component.spec.ts @@ -1,15 +1,17 @@ -import { ItemSearchResult } from '../../../../shared/object-collection/shared/item-search-result.model'; import { Item } from '../../../../core/shared/item.model'; import { of as observableOf } from 'rxjs/internal/observable/of'; -import { getEntityGridElementTestComponent } from '../../../../shared/object-grid/item-grid-element/item-types/publication/publication-grid-element.component.spec'; import { PersonGridElementComponent } from './person-grid-element.component'; import { createSuccessfulRemoteDataObject$ } from '../../../../shared/testing/utils'; import { PaginatedList } from '../../../../core/data/paginated-list'; import { PageInfo } from '../../../../core/shared/page-info.model'; +import { async, TestBed } from '@angular/core/testing'; +import { NoopAnimationsModule } from '@angular/platform-browser/animations'; +import { TruncatePipe } from '../../../../shared/utils/truncate.pipe'; +import { TruncatableService } from '../../../../shared/truncatable/truncatable.service'; +import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA } from '@angular/core'; +import { By } from '@angular/platform-browser'; -const mockItemWithMetadata: ItemSearchResult = new ItemSearchResult(); -mockItemWithMetadata.hitHighlights = {}; -mockItemWithMetadata.indexableObject = Object.assign(new Item(), { +const mockItem = Object.assign(new Item(), { bitstreams: createSuccessfulRemoteDataObject$(new PaginatedList(new PageInfo(), [])), metadata: { 'dc.title': [ @@ -33,18 +35,41 @@ mockItemWithMetadata.indexableObject = Object.assign(new Item(), { } }); -const mockItemWithoutMetadata: ItemSearchResult = new ItemSearchResult(); -mockItemWithoutMetadata.hitHighlights = {}; -mockItemWithoutMetadata.indexableObject = Object.assign(new Item(), { - bitstreams: createSuccessfulRemoteDataObject$(new PaginatedList(new PageInfo(), [])), - metadata: { - 'dc.title': [ - { - language: 'en_US', - value: 'This is just another title' - } - ] - } -}); +describe('PersonGridElementComponent', () => { + let comp; + let fixture; -describe('PersonGridElementComponent', getEntityGridElementTestComponent(PersonGridElementComponent, mockItemWithMetadata, mockItemWithoutMetadata, ['email', 'jobtitle'])); + const truncatableServiceStub: any = { + isCollapsed: (id: number) => observableOf(true), + }; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + imports: [NoopAnimationsModule], + declarations: [PersonGridElementComponent, TruncatePipe], + providers: [ + { provide: TruncatableService, useValue: truncatableServiceStub }, + ], + schemas: [NO_ERRORS_SCHEMA] + }).overrideComponent(PersonGridElementComponent, { + set: { changeDetection: ChangeDetectionStrategy.Default } + }).compileComponents(); + })); + + beforeEach(async(() => { + fixture = TestBed.createComponent(PersonGridElementComponent); + comp = fixture.componentInstance; + })); + + describe(`when the person is rendered`, () => { + beforeEach(() => { + comp.object = mockItem; + fixture.detectChanges(); + }); + + it(`should contain a PersonGridElementComponent`, () => { + const personGridElement = fixture.debugElement.query(By.css(`ds-person-search-result-grid-element`)); + expect(personGridElement).not.toBeNull(); + }); + }); +}); diff --git a/src/app/entity-groups/research-entities/item-grid-elements/person/person-grid-element.component.ts b/src/app/entity-groups/research-entities/item-grid-elements/person/person-grid-element.component.ts index bf7b8aa119..2e3ce5804e 100644 --- a/src/app/entity-groups/research-entities/item-grid-elements/person/person-grid-element.component.ts +++ b/src/app/entity-groups/research-entities/item-grid-elements/person/person-grid-element.component.ts @@ -1,17 +1,17 @@ -import { ItemViewMode, rendersItemType } from '../../../../shared/items/item-type-decorator'; import { Component } from '@angular/core'; -import { TypedItemSearchResultGridElementComponent } from '../../../../shared/object-grid/item-grid-element/item-types/typed-item-search-result-grid-element.component'; -import { focusShadow } from '../../../../shared/animations/focus'; +import { ViewMode } from '../../../../core/shared/view-mode.model'; +import { listableObjectComponent } from '../../../../shared/object-collection/shared/listable-object/listable-object.decorator'; +import { AbstractListableElementComponent } from '../../../../shared/object-collection/shared/object-collection-element/abstract-listable-element.component'; +import { Item } from '../../../../core/shared/item.model'; -@rendersItemType('Person', ItemViewMode.Card) +@listableObjectComponent('Person', ViewMode.GridElement) @Component({ selector: 'ds-person-grid-element', styleUrls: ['./person-grid-element.component.scss'], templateUrl: './person-grid-element.component.html', - animations: [focusShadow] }) /** * The component for displaying a grid element for an item of the type Person */ -export class PersonGridElementComponent extends TypedItemSearchResultGridElementComponent { +export class PersonGridElementComponent extends AbstractListableElementComponent { } diff --git a/src/app/entity-groups/research-entities/item-grid-elements/project/project-grid-element.component.html b/src/app/entity-groups/research-entities/item-grid-elements/project/project-grid-element.component.html index 889276b29b..0c87599399 100644 --- a/src/app/entity-groups/research-entities/item-grid-elements/project/project-grid-element.component.html +++ b/src/app/entity-groups/research-entities/item-grid-elements/project/project-grid-element.component.html @@ -1,25 +1 @@ - -
- -
- - -
-
-
- - -

-
-

- - - -

-
- View -
-
-
-
+ \ No newline at end of file diff --git a/src/app/entity-groups/research-entities/item-grid-elements/project/project-grid-element.component.spec.ts b/src/app/entity-groups/research-entities/item-grid-elements/project/project-grid-element.component.spec.ts index 969912976c..8bd462b0e6 100644 --- a/src/app/entity-groups/research-entities/item-grid-elements/project/project-grid-element.component.spec.ts +++ b/src/app/entity-groups/research-entities/item-grid-elements/project/project-grid-element.component.spec.ts @@ -1,15 +1,17 @@ -import { ItemSearchResult } from '../../../../shared/object-collection/shared/item-search-result.model'; import { Item } from '../../../../core/shared/item.model'; import { of as observableOf } from 'rxjs/internal/observable/of'; -import { getEntityGridElementTestComponent } from '../../../../shared/object-grid/item-grid-element/item-types/publication/publication-grid-element.component.spec'; import { ProjectGridElementComponent } from './project-grid-element.component'; import { createSuccessfulRemoteDataObject$ } from '../../../../shared/testing/utils'; import { PaginatedList } from '../../../../core/data/paginated-list'; import { PageInfo } from '../../../../core/shared/page-info.model'; +import { async, TestBed } from '@angular/core/testing'; +import { NoopAnimationsModule } from '@angular/platform-browser/animations'; +import { TruncatePipe } from '../../../../shared/utils/truncate.pipe'; +import { TruncatableService } from '../../../../shared/truncatable/truncatable.service'; +import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA } from '@angular/core'; +import { By } from '@angular/platform-browser'; -const mockItemWithMetadata: ItemSearchResult = new ItemSearchResult(); -mockItemWithMetadata.hitHighlights = {}; -mockItemWithMetadata.indexableObject = Object.assign(new Item(), { +const mockItem = Object.assign(new Item(), { bitstreams: createSuccessfulRemoteDataObject$(new PaginatedList(new PageInfo(), [])), metadata: { 'dc.title': [ @@ -27,18 +29,41 @@ mockItemWithMetadata.indexableObject = Object.assign(new Item(), { } }); -const mockItemWithoutMetadata: ItemSearchResult = new ItemSearchResult(); -mockItemWithoutMetadata.hitHighlights = {}; -mockItemWithoutMetadata.indexableObject = Object.assign(new Item(), { - bitstreams: createSuccessfulRemoteDataObject$(new PaginatedList(new PageInfo(), [])), - metadata: { - 'dc.title': [ - { - language: 'en_US', - value: 'This is just another title' - } - ] - } -}); +describe('ProjectGridElementComponent', () => { + let comp; + let fixture; -describe('ProjectGridElementComponent', getEntityGridElementTestComponent(ProjectGridElementComponent, mockItemWithMetadata, mockItemWithoutMetadata, ['description'])); + const truncatableServiceStub: any = { + isCollapsed: (id: number) => observableOf(true), + }; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + imports: [NoopAnimationsModule], + declarations: [ProjectGridElementComponent, TruncatePipe], + providers: [ + { provide: TruncatableService, useValue: truncatableServiceStub }, + ], + schemas: [NO_ERRORS_SCHEMA] + }).overrideComponent(ProjectGridElementComponent, { + set: { changeDetection: ChangeDetectionStrategy.Default } + }).compileComponents(); + })); + + beforeEach(async(() => { + fixture = TestBed.createComponent(ProjectGridElementComponent); + comp = fixture.componentInstance; + })); + + describe(`when the project is rendered`, () => { + beforeEach(() => { + comp.object = mockItem; + fixture.detectChanges(); + }); + + it(`should contain a ProjectGridElementComponent`, () => { + const projectGridElement = fixture.debugElement.query(By.css(`ds-project-search-result-grid-element`)); + expect(projectGridElement).not.toBeNull(); + }); + }); +}); diff --git a/src/app/entity-groups/research-entities/item-grid-elements/project/project-grid-element.component.ts b/src/app/entity-groups/research-entities/item-grid-elements/project/project-grid-element.component.ts index 15d525fcf2..58547960cf 100644 --- a/src/app/entity-groups/research-entities/item-grid-elements/project/project-grid-element.component.ts +++ b/src/app/entity-groups/research-entities/item-grid-elements/project/project-grid-element.component.ts @@ -1,17 +1,17 @@ -import { ItemViewMode, rendersItemType } from '../../../../shared/items/item-type-decorator'; import { Component } from '@angular/core'; -import { focusShadow } from '../../../../shared/animations/focus'; -import { TypedItemSearchResultGridElementComponent } from '../../../../shared/object-grid/item-grid-element/item-types/typed-item-search-result-grid-element.component'; +import { ViewMode } from '../../../../core/shared/view-mode.model'; +import { listableObjectComponent } from '../../../../shared/object-collection/shared/listable-object/listable-object.decorator'; +import { AbstractListableElementComponent } from '../../../../shared/object-collection/shared/object-collection-element/abstract-listable-element.component'; +import { Item } from '../../../../core/shared/item.model'; -@rendersItemType('Project', ItemViewMode.Card) +@listableObjectComponent('Project', ViewMode.GridElement) @Component({ selector: 'ds-project-grid-element', styleUrls: ['./project-grid-element.component.scss'], templateUrl: './project-grid-element.component.html', - animations: [focusShadow] }) /** * The component for displaying a grid element for an item of the type Project */ -export class ProjectGridElementComponent extends TypedItemSearchResultGridElementComponent { +export class ProjectGridElementComponent extends AbstractListableElementComponent { } diff --git a/src/app/entity-groups/research-entities/item-grid-elements/search-result-grid-elements/org-unit/org-unit-search-result-grid-element.component.html b/src/app/entity-groups/research-entities/item-grid-elements/search-result-grid-elements/org-unit/org-unit-search-result-grid-element.component.html new file mode 100644 index 0000000000..5c42be2b24 --- /dev/null +++ b/src/app/entity-groups/research-entities/item-grid-elements/search-result-grid-elements/org-unit/org-unit-search-result-grid-element.component.html @@ -0,0 +1,41 @@ + +
+ +
+ + +
+
+ +
+ + +
+
+
+ + +

+
+

+ + + +

+

+ + {{firstMetadataValue('organization.address.addressCountry')}} + + , + {{firstMetadataValue('organization.address.addressLocality')}} + + +

+
+ View +
+
+
+
diff --git a/src/app/entity-groups/research-entities/item-grid-elements/search-result-grid-elements/org-unit/org-unit-search-result-grid-element.component.scss b/src/app/entity-groups/research-entities/item-grid-elements/search-result-grid-elements/org-unit/org-unit-search-result-grid-element.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/entity-groups/research-entities/item-grid-elements/orgunit/orgunit-grid-element.component.spec.ts b/src/app/entity-groups/research-entities/item-grid-elements/search-result-grid-elements/org-unit/org-unit-search-result-grid-element.component.spec.ts similarity index 56% rename from src/app/entity-groups/research-entities/item-grid-elements/orgunit/orgunit-grid-element.component.spec.ts rename to src/app/entity-groups/research-entities/item-grid-elements/search-result-grid-elements/org-unit/org-unit-search-result-grid-element.component.spec.ts index 15c7b75bf5..36324ad627 100644 --- a/src/app/entity-groups/research-entities/item-grid-elements/orgunit/orgunit-grid-element.component.spec.ts +++ b/src/app/entity-groups/research-entities/item-grid-elements/search-result-grid-elements/org-unit/org-unit-search-result-grid-element.component.spec.ts @@ -1,11 +1,10 @@ -import { ItemSearchResult } from '../../../../shared/object-collection/shared/item-search-result.model'; -import { Item } from '../../../../core/shared/item.model'; -import { of as observableOf } from 'rxjs/internal/observable/of'; -import { getEntityGridElementTestComponent } from '../../../../shared/object-grid/item-grid-element/item-types/publication/publication-grid-element.component.spec'; -import { OrgunitGridElementComponent } from './orgunit-grid-element.component'; -import { createSuccessfulRemoteDataObject$ } from '../../../../shared/testing/utils'; -import { PaginatedList } from '../../../../core/data/paginated-list'; -import { PageInfo } from '../../../../core/shared/page-info.model'; +import { ItemSearchResult } from '../../../../../shared/object-collection/shared/item-search-result.model'; +import { Item } from '../../../../../core/shared/item.model'; +import { createSuccessfulRemoteDataObject$ } from '../../../../../shared/testing/utils'; +import { PaginatedList } from '../../../../../core/data/paginated-list'; +import { PageInfo } from '../../../../../core/shared/page-info.model'; +import { OrgUnitSearchResultGridElementComponent } from './org-unit-search-result-grid-element.component'; +import { getEntityGridElementTestComponent } from '../../../../../shared/object-grid/search-result-grid-element/item-search-result/publication/publication-search-result-grid-element.component.spec'; const mockItemWithMetadata: ItemSearchResult = new ItemSearchResult(); mockItemWithMetadata.hitHighlights = {}; @@ -53,4 +52,4 @@ mockItemWithoutMetadata.indexableObject = Object.assign(new Item(), { } }); -describe('OrgunitGridElementComponent', getEntityGridElementTestComponent(OrgunitGridElementComponent, mockItemWithMetadata, mockItemWithoutMetadata, ['date', 'country', 'city'])); +describe('OrgUnitSearchResultGridElementComponent', getEntityGridElementTestComponent(OrgUnitSearchResultGridElementComponent, mockItemWithMetadata, mockItemWithoutMetadata, ['date', 'country', 'city'])); diff --git a/src/app/entity-groups/research-entities/item-grid-elements/search-result-grid-elements/org-unit/org-unit-search-result-grid-element.component.ts b/src/app/entity-groups/research-entities/item-grid-elements/search-result-grid-elements/org-unit/org-unit-search-result-grid-element.component.ts new file mode 100644 index 0000000000..64b4be4a11 --- /dev/null +++ b/src/app/entity-groups/research-entities/item-grid-elements/search-result-grid-elements/org-unit/org-unit-search-result-grid-element.component.ts @@ -0,0 +1,20 @@ +import { Component } from '@angular/core'; +import { listableObjectComponent } from '../../../../../shared/object-collection/shared/listable-object/listable-object.decorator'; +import { ViewMode } from '../../../../../core/shared/view-mode.model'; +import { focusShadow } from '../../../../../shared/animations/focus'; +import { SearchResultGridElementComponent } from '../../../../../shared/object-grid/search-result-grid-element/search-result-grid-element.component'; +import { ItemSearchResult } from '../../../../../shared/object-collection/shared/item-search-result.model'; +import { Item } from '../../../../../core/shared/item.model'; + +@listableObjectComponent('OrgUnitSearchResult', ViewMode.GridElement) +@Component({ + selector: 'ds-org-unit-search-result-grid-element', + styleUrls: ['./org-unit-search-result-grid-element.component.scss'], + templateUrl: './org-unit-search-result-grid-element.component.html', + animations: [focusShadow] +}) +/** + * The component for displaying a grid element for an item search result of the type Organisation Unit + */ +export class OrgUnitSearchResultGridElementComponent extends SearchResultGridElementComponent { +} diff --git a/src/app/entity-groups/research-entities/item-grid-elements/search-result-grid-elements/person/person-search-result-grid-element.component.html b/src/app/entity-groups/research-entities/item-grid-elements/search-result-grid-elements/person/person-search-result-grid-element.component.html new file mode 100644 index 0000000000..b7eed7c8b4 --- /dev/null +++ b/src/app/entity-groups/research-entities/item-grid-elements/search-result-grid-elements/person/person-search-result-grid-element.component.html @@ -0,0 +1,37 @@ + +
+ +
+ + +
+
+ +
+ + +
+
+
+ + +

+
+ +

+ + + +

+
+ View +
+
+
+
diff --git a/src/app/entity-groups/research-entities/item-grid-elements/search-result-grid-elements/person/person-search-result-grid-element.component.scss b/src/app/entity-groups/research-entities/item-grid-elements/search-result-grid-elements/person/person-search-result-grid-element.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/entity-groups/research-entities/item-grid-elements/search-result-grid-elements/person/person-search-result-grid-element.component.spec.ts b/src/app/entity-groups/research-entities/item-grid-elements/search-result-grid-elements/person/person-search-result-grid-element.component.spec.ts new file mode 100644 index 0000000000..05baa7a63f --- /dev/null +++ b/src/app/entity-groups/research-entities/item-grid-elements/search-result-grid-elements/person/person-search-result-grid-element.component.spec.ts @@ -0,0 +1,49 @@ +import { ItemSearchResult } from '../../../../../shared/object-collection/shared/item-search-result.model'; +import { Item } from '../../../../../core/shared/item.model'; +import { createSuccessfulRemoteDataObject$ } from '../../../../../shared/testing/utils'; +import { PaginatedList } from '../../../../../core/data/paginated-list'; +import { PageInfo } from '../../../../../core/shared/page-info.model'; +import { getEntityGridElementTestComponent } from '../../../../../shared/object-grid/search-result-grid-element/item-search-result/publication/publication-search-result-grid-element.component.spec'; +import { PersonSearchResultGridElementComponent } from './person-search-result-grid-element.component'; + +const mockItemWithMetadata: ItemSearchResult = new ItemSearchResult(); +mockItemWithMetadata.hitHighlights = {}; +mockItemWithMetadata.indexableObject = Object.assign(new Item(), { + bitstreams: createSuccessfulRemoteDataObject$(new PaginatedList(new PageInfo(), [])), + metadata: { + 'dc.title': [ + { + language: 'en_US', + value: 'This is just another title' + } + ], + 'person.email': [ + { + language: 'en_US', + value: 'Smith-Donald@gmail.com' + } + ], + 'person.jobTitle': [ + { + language: 'en_US', + value: 'Web Developer' + } + ] + } +}); + +const mockItemWithoutMetadata: ItemSearchResult = new ItemSearchResult(); +mockItemWithoutMetadata.hitHighlights = {}; +mockItemWithoutMetadata.indexableObject = Object.assign(new Item(), { + bitstreams: createSuccessfulRemoteDataObject$(new PaginatedList(new PageInfo(), [])), + metadata: { + 'dc.title': [ + { + language: 'en_US', + value: 'This is just another title' + } + ] + } +}); + +describe('PersonSearchResultGridElementComponent', getEntityGridElementTestComponent(PersonSearchResultGridElementComponent, mockItemWithMetadata, mockItemWithoutMetadata, ['email', 'jobtitle'])); diff --git a/src/app/entity-groups/research-entities/item-grid-elements/search-result-grid-elements/person/person-search-result-grid-element.component.ts b/src/app/entity-groups/research-entities/item-grid-elements/search-result-grid-elements/person/person-search-result-grid-element.component.ts new file mode 100644 index 0000000000..55bc4f5a0d --- /dev/null +++ b/src/app/entity-groups/research-entities/item-grid-elements/search-result-grid-elements/person/person-search-result-grid-element.component.ts @@ -0,0 +1,20 @@ +import { Component } from '@angular/core'; +import { listableObjectComponent } from '../../../../../shared/object-collection/shared/listable-object/listable-object.decorator'; +import { ViewMode } from '../../../../../core/shared/view-mode.model'; +import { focusShadow } from '../../../../../shared/animations/focus'; +import { SearchResultGridElementComponent } from '../../../../../shared/object-grid/search-result-grid-element/search-result-grid-element.component'; +import { ItemSearchResult } from '../../../../../shared/object-collection/shared/item-search-result.model'; +import { Item } from '../../../../../core/shared/item.model'; + +@listableObjectComponent('PersonSearchResult', ViewMode.GridElement) +@Component({ + selector: 'ds-person-search-result-grid-element', + styleUrls: ['./person-search-result-grid-element.component.scss'], + templateUrl: './person-search-result-grid-element.component.html', + animations: [focusShadow] +}) +/** + * The component for displaying a grid element for an item search result of the type Person + */ +export class PersonSearchResultGridElementComponent extends SearchResultGridElementComponent { +} diff --git a/src/app/entity-groups/research-entities/item-grid-elements/search-result-grid-elements/project/project-search-result-grid-element.component.html b/src/app/entity-groups/research-entities/item-grid-elements/search-result-grid-elements/project/project-search-result-grid-element.component.html new file mode 100644 index 0000000000..f3a0dea81f --- /dev/null +++ b/src/app/entity-groups/research-entities/item-grid-elements/search-result-grid-elements/project/project-search-result-grid-element.component.html @@ -0,0 +1,31 @@ + +
+ +
+ + +
+
+ +
+ + +
+
+
+ + +

+
+

+ + + +

+
+ View +
+
+
+
diff --git a/src/app/entity-groups/research-entities/item-grid-elements/search-result-grid-elements/project/project-search-result-grid-element.component.scss b/src/app/entity-groups/research-entities/item-grid-elements/search-result-grid-elements/project/project-search-result-grid-element.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/entity-groups/research-entities/item-grid-elements/search-result-grid-elements/project/project-search-result-grid-element.component.spec.ts b/src/app/entity-groups/research-entities/item-grid-elements/search-result-grid-elements/project/project-search-result-grid-element.component.spec.ts new file mode 100644 index 0000000000..15e7432b65 --- /dev/null +++ b/src/app/entity-groups/research-entities/item-grid-elements/search-result-grid-elements/project/project-search-result-grid-element.component.spec.ts @@ -0,0 +1,43 @@ +import { ItemSearchResult } from '../../../../../shared/object-collection/shared/item-search-result.model'; +import { Item } from '../../../../../core/shared/item.model'; +import { createSuccessfulRemoteDataObject$ } from '../../../../../shared/testing/utils'; +import { PaginatedList } from '../../../../../core/data/paginated-list'; +import { PageInfo } from '../../../../../core/shared/page-info.model'; +import { ProjectSearchResultGridElementComponent } from './project-search-result-grid-element.component'; +import { getEntityGridElementTestComponent } from '../../../../../shared/object-grid/search-result-grid-element/item-search-result/publication/publication-search-result-grid-element.component.spec'; + +const mockItemWithMetadata: ItemSearchResult = new ItemSearchResult(); +mockItemWithMetadata.hitHighlights = {}; +mockItemWithMetadata.indexableObject = Object.assign(new Item(), { + bitstreams: createSuccessfulRemoteDataObject$(new PaginatedList(new PageInfo(), [])), + metadata: { + 'dc.title': [ + { + language: 'en_US', + value: 'This is just another title' + } + ], + 'dc.description': [ + { + language: 'en_US', + value: 'The project description' + } + ] + } +}); + +const mockItemWithoutMetadata: ItemSearchResult = new ItemSearchResult(); +mockItemWithoutMetadata.hitHighlights = {}; +mockItemWithoutMetadata.indexableObject = Object.assign(new Item(), { + bitstreams: createSuccessfulRemoteDataObject$(new PaginatedList(new PageInfo(), [])), + metadata: { + 'dc.title': [ + { + language: 'en_US', + value: 'This is just another title' + } + ] + } +}); + +describe('ProjectSearchResultGridElementComponent', getEntityGridElementTestComponent(ProjectSearchResultGridElementComponent, mockItemWithMetadata, mockItemWithoutMetadata, ['description'])); diff --git a/src/app/entity-groups/research-entities/item-grid-elements/search-result-grid-elements/project/project-search-result-grid-element.component.ts b/src/app/entity-groups/research-entities/item-grid-elements/search-result-grid-elements/project/project-search-result-grid-element.component.ts new file mode 100644 index 0000000000..a352d2dcb0 --- /dev/null +++ b/src/app/entity-groups/research-entities/item-grid-elements/search-result-grid-elements/project/project-search-result-grid-element.component.ts @@ -0,0 +1,20 @@ +import { Component } from '@angular/core'; +import { SearchResultGridElementComponent } from '../../../../../shared/object-grid/search-result-grid-element/search-result-grid-element.component'; +import { Item } from '../../../../../core/shared/item.model'; +import { ItemSearchResult } from '../../../../../shared/object-collection/shared/item-search-result.model'; +import { listableObjectComponent } from '../../../../../shared/object-collection/shared/listable-object/listable-object.decorator'; +import { ViewMode } from '../../../../../core/shared/view-mode.model'; +import { focusShadow } from '../../../../../shared/animations/focus'; + +@listableObjectComponent('ProjectSearchResult', ViewMode.GridElement) +@Component({ + selector: 'ds-project-search-result-grid-element', + styleUrls: ['./project-search-result-grid-element.component.scss'], + templateUrl: './project-search-result-grid-element.component.html', + animations: [focusShadow] +}) +/** + * The component for displaying a grid element for an item search result of the type Project + */ +export class ProjectSearchResultGridElementComponent extends SearchResultGridElementComponent { +} diff --git a/src/app/entity-groups/research-entities/item-list-elements/org-unit/org-unit-list-element.component.html b/src/app/entity-groups/research-entities/item-list-elements/org-unit/org-unit-list-element.component.html new file mode 100644 index 0000000000..03ef45c7a4 --- /dev/null +++ b/src/app/entity-groups/research-entities/item-list-elements/org-unit/org-unit-list-element.component.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/app/entity-groups/research-entities/item-list-elements/orgunit/orgunit-list-element.component.scss b/src/app/entity-groups/research-entities/item-list-elements/org-unit/org-unit-list-element.component.scss similarity index 100% rename from src/app/entity-groups/research-entities/item-list-elements/orgunit/orgunit-list-element.component.scss rename to src/app/entity-groups/research-entities/item-list-elements/org-unit/org-unit-list-element.component.scss diff --git a/src/app/entity-groups/research-entities/item-list-elements/org-unit/org-unit-list-element.component.spec.ts b/src/app/entity-groups/research-entities/item-list-elements/org-unit/org-unit-list-element.component.spec.ts new file mode 100644 index 0000000000..43ed9b0ec5 --- /dev/null +++ b/src/app/entity-groups/research-entities/item-list-elements/org-unit/org-unit-list-element.component.spec.ts @@ -0,0 +1,64 @@ +import { async, TestBed } from '@angular/core/testing'; +import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA } from '@angular/core'; +import { By } from '@angular/platform-browser'; +import { OrgUnitListElementComponent } from './org-unit-list-element.component'; +import { of as observableOf } from 'rxjs'; +import { Item } from '../../../../core/shared/item.model'; +import { TruncatePipe } from '../../../../shared/utils/truncate.pipe'; +import { TruncatableService } from '../../../../shared/truncatable/truncatable.service'; + +const mockItem: Item = Object.assign(new Item(), { + bitstreams: observableOf({}), + metadata: { + 'dc.title': [ + { + language: 'en_US', + value: 'This is just another title' + } + ], + 'dc.description': [ + { + language: 'en_US', + value: 'A description about the OrgUnit' + } + ] + } +}); + +describe('OrgUnitListElementComponent', () => { + let comp; + let fixture; + + const truncatableServiceStub: any = { + isCollapsed: (id: number) => observableOf(true), + }; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [OrgUnitListElementComponent, TruncatePipe], + providers: [ + { provide: TruncatableService, useValue: truncatableServiceStub }, + ], + schemas: [NO_ERRORS_SCHEMA] + }).overrideComponent(OrgUnitListElementComponent, { + set: { changeDetection: ChangeDetectionStrategy.Default } + }).compileComponents(); + })); + + beforeEach(async(() => { + fixture = TestBed.createComponent(OrgUnitListElementComponent); + comp = fixture.componentInstance; + })); + + describe(`when the org unit is rendered`, () => { + beforeEach(() => { + comp.object = mockItem; + fixture.detectChanges(); + }); + + it(`should contain a OrgUnitListElementComponent`, () => { + const orgUnitListElement = fixture.debugElement.query(By.css(`ds-org-unit-search-result-list-element`)); + expect(orgUnitListElement).not.toBeNull(); + }); + }); +}); diff --git a/src/app/entity-groups/research-entities/item-list-elements/org-unit/org-unit-list-element.component.ts b/src/app/entity-groups/research-entities/item-list-elements/org-unit/org-unit-list-element.component.ts new file mode 100644 index 0000000000..32254595aa --- /dev/null +++ b/src/app/entity-groups/research-entities/item-list-elements/org-unit/org-unit-list-element.component.ts @@ -0,0 +1,17 @@ +import { Component } from '@angular/core'; +import { ViewMode } from '../../../../core/shared/view-mode.model'; +import { listableObjectComponent } from '../../../../shared/object-collection/shared/listable-object/listable-object.decorator'; +import { AbstractListableElementComponent } from '../../../../shared/object-collection/shared/object-collection-element/abstract-listable-element.component'; +import { Item } from '../../../../core/shared/item.model'; + +@listableObjectComponent('OrgUnit', ViewMode.ListElement) +@Component({ + selector: 'ds-org-unit-list-element', + styleUrls: ['./org-unit-list-element.component.scss'], + templateUrl: './org-unit-list-element.component.html' +}) +/** + * The component for displaying a list element for an item of the type Organisation Unit + */ +export class OrgUnitListElementComponent extends AbstractListableElementComponent { +} diff --git a/src/app/entity-groups/research-entities/item-list-elements/orgunit/orgunit-list-element.component.html b/src/app/entity-groups/research-entities/item-list-elements/orgunit/orgunit-list-element.component.html deleted file mode 100644 index 8d312fb7c0..0000000000 --- a/src/app/entity-groups/research-entities/item-list-elements/orgunit/orgunit-list-element.component.html +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - diff --git a/src/app/entity-groups/research-entities/item-list-elements/orgunit/orgunit-list-element.component.spec.ts b/src/app/entity-groups/research-entities/item-list-elements/orgunit/orgunit-list-element.component.spec.ts deleted file mode 100644 index dd2b138abb..0000000000 --- a/src/app/entity-groups/research-entities/item-list-elements/orgunit/orgunit-list-element.component.spec.ts +++ /dev/null @@ -1,87 +0,0 @@ -import { async, ComponentFixture, TestBed } from '@angular/core/testing'; -import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA } from '@angular/core'; -import { By } from '@angular/platform-browser'; -import { OrgUnitListElementComponent } from './orgunit-list-element.component'; -import { of as observableOf } from 'rxjs'; -import { Item } from '../../../../core/shared/item.model'; -import { TruncatePipe } from '../../../../shared/utils/truncate.pipe'; -import { ITEM } from '../../../../shared/items/switcher/item-type-switcher.component'; -import { TruncatableService } from '../../../../shared/truncatable/truncatable.service'; - -let orgUnitListElementComponent: OrgUnitListElementComponent; -let fixture: ComponentFixture; - -const mockItemWithMetadata: Item = Object.assign(new Item(), { - bitstreams: observableOf({}), - metadata: { - 'dc.title': [ - { - language: 'en_US', - value: 'This is just another title' - } - ], - 'dc.description': [ - { - language: 'en_US', - value: 'A description about the OrgUnit' - } - ] - } -}); -const mockItemWithoutMetadata: Item = Object.assign(new Item(), { - bitstreams: observableOf({}), - metadata: { - 'dc.title': [ - { - language: 'en_US', - value: 'This is just another title' - } - ] - } -}); - -describe('OrgUnitListElementComponent', () => { - beforeEach(async(() => { - TestBed.configureTestingModule({ - declarations: [ OrgUnitListElementComponent , TruncatePipe], - providers: [ - { provide: ITEM, useValue: mockItemWithMetadata}, - { provide: TruncatableService, useValue: {} } - ], - - schemas: [ NO_ERRORS_SCHEMA ] - }).overrideComponent(OrgUnitListElementComponent, { - set: { changeDetection: ChangeDetectionStrategy.Default } - }).compileComponents(); - })); - - beforeEach(async(() => { - fixture = TestBed.createComponent(OrgUnitListElementComponent); - orgUnitListElementComponent = fixture.componentInstance; - - })); - - describe('When the item has an orgunit description', () => { - beforeEach(() => { - orgUnitListElementComponent.item = mockItemWithMetadata; - fixture.detectChanges(); - }); - - it('should show the description span', () => { - const orgunitDescriptionField = fixture.debugElement.query(By.css('span.item-list-orgunit-description')); - expect(orgunitDescriptionField).not.toBeNull(); - }); - }); - - describe('When the item has no orgunit description', () => { - beforeEach(() => { - orgUnitListElementComponent.item = mockItemWithoutMetadata; - fixture.detectChanges(); - }); - - it('should not show the description span', () => { - const orgunitDescriptionField = fixture.debugElement.query(By.css('span.item-list-orgunit-description')); - expect(orgunitDescriptionField).toBeNull(); - }); - }); -}); diff --git a/src/app/entity-groups/research-entities/item-list-elements/orgunit/orgunit-list-element.component.ts b/src/app/entity-groups/research-entities/item-list-elements/orgunit/orgunit-list-element.component.ts deleted file mode 100644 index 9a56bb6d03..0000000000 --- a/src/app/entity-groups/research-entities/item-list-elements/orgunit/orgunit-list-element.component.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { Component } from '@angular/core'; -import { ItemViewMode, rendersItemType } from '../../../../shared/items/item-type-decorator'; -import { TypedItemSearchResultListElementComponent } from '../../../../shared/object-list/item-list-element/item-types/typed-item-search-result-list-element.component'; - -@rendersItemType('OrgUnit', ItemViewMode.Element) -@Component({ - selector: 'ds-orgunit-list-element', - styleUrls: ['./orgunit-list-element.component.scss'], - templateUrl: './orgunit-list-element.component.html' -}) -/** - * The component for displaying a list element for an item of the type Organisation Unit - */ -export class OrgUnitListElementComponent extends TypedItemSearchResultListElementComponent { -} diff --git a/src/app/entity-groups/research-entities/item-list-elements/orgunit/orgunit-metadata-list-element.component.ts b/src/app/entity-groups/research-entities/item-list-elements/orgunit/orgunit-metadata-list-element.component.ts deleted file mode 100644 index 21d0d9f86b..0000000000 --- a/src/app/entity-groups/research-entities/item-list-elements/orgunit/orgunit-metadata-list-element.component.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { Component } from '@angular/core'; -import { MetadataRepresentationType } from '../../../../core/shared/metadata-representation/metadata-representation.model'; -import { ItemViewMode, rendersItemType } from '../../../../shared/items/item-type-decorator'; -import { ItemMetadataRepresentationListElementComponent } from '../../../../shared/object-list/metadata-representation-list-element/item/item-metadata-representation-list-element.component'; - -@rendersItemType('OrgUnit', ItemViewMode.Element, MetadataRepresentationType.Item) -@Component({ - selector: 'ds-orgunit-metadata-list-element', - templateUrl: './orgunit-metadata-list-element.component.html' -}) -/** - * The component for displaying a list element for an item of the type OrgUnit - */ -export class OrgUnitMetadataListElementComponent extends ItemMetadataRepresentationListElementComponent { -} diff --git a/src/app/entity-groups/research-entities/item-list-elements/person/person-list-element.component.html b/src/app/entity-groups/research-entities/item-list-elements/person/person-list-element.component.html index c88b77083d..dbc3a42a05 100644 --- a/src/app/entity-groups/research-entities/item-list-elements/person/person-list-element.component.html +++ b/src/app/entity-groups/research-entities/item-list-elements/person/person-list-element.component.html @@ -1,15 +1 @@ - - - - - - - - - - - - + \ No newline at end of file diff --git a/src/app/entity-groups/research-entities/item-list-elements/person/person-list-element.component.spec.ts b/src/app/entity-groups/research-entities/item-list-elements/person/person-list-element.component.spec.ts index 3b6aeae45b..6366ba5735 100644 --- a/src/app/entity-groups/research-entities/item-list-elements/person/person-list-element.component.spec.ts +++ b/src/app/entity-groups/research-entities/item-list-elements/person/person-list-element.component.spec.ts @@ -5,13 +5,9 @@ import { PersonListElementComponent } from './person-list-element.component'; import { of as observableOf } from 'rxjs'; import { Item } from '../../../../core/shared/item.model'; import { TruncatePipe } from '../../../../shared/utils/truncate.pipe'; -import { ITEM } from '../../../../shared/items/switcher/item-type-switcher.component'; import { TruncatableService } from '../../../../shared/truncatable/truncatable.service'; -let personListElementComponent: PersonListElementComponent; -let fixture: ComponentFixture; - -const mockItemWithMetadata: Item = Object.assign(new Item(), { +const mockItem: Item = Object.assign(new Item(), { bitstreams: observableOf({}), metadata: { 'dc.title': [ @@ -28,28 +24,22 @@ const mockItemWithMetadata: Item = Object.assign(new Item(), { ] } }); -const mockItemWithoutMetadata: Item = Object.assign(new Item(), { - bitstreams: observableOf({}), - metadata: { - 'dc.title': [ - { - language: 'en_US', - value: 'This is just another title' - } - ] - } -}); describe('PersonListElementComponent', () => { + let comp; + let fixture; + + const truncatableServiceStub: any = { + isCollapsed: (id: number) => observableOf(true), + }; + beforeEach(async(() => { TestBed.configureTestingModule({ - declarations: [ PersonListElementComponent , TruncatePipe], + declarations: [PersonListElementComponent, TruncatePipe], providers: [ - { provide: ITEM, useValue: mockItemWithMetadata}, - { provide: TruncatableService, useValue: {} } + { provide: TruncatableService, useValue: truncatableServiceStub }, ], - - schemas: [ NO_ERRORS_SCHEMA ] + schemas: [NO_ERRORS_SCHEMA] }).overrideComponent(PersonListElementComponent, { set: { changeDetection: ChangeDetectionStrategy.Default } }).compileComponents(); @@ -57,31 +47,18 @@ describe('PersonListElementComponent', () => { beforeEach(async(() => { fixture = TestBed.createComponent(PersonListElementComponent); - personListElementComponent = fixture.componentInstance; - + comp = fixture.componentInstance; })); - describe('When the item has a job title', () => { + describe(`when the person is rendered`, () => { beforeEach(() => { - personListElementComponent.item = mockItemWithMetadata; + comp.object = mockItem; fixture.detectChanges(); }); - it('should show the job title span', () => { - const jobTitleField = fixture.debugElement.query(By.css('span.item-list-job-title')); - expect(jobTitleField).not.toBeNull(); - }); - }); - - describe('When the item has no job title', () => { - beforeEach(() => { - personListElementComponent.item = mockItemWithoutMetadata; - fixture.detectChanges(); - }); - - it('should not show the job title span', () => { - const jobTitleField = fixture.debugElement.query(By.css('span.item-list-job-title')); - expect(jobTitleField).toBeNull(); + it(`should contain a PersonListElementComponent`, () => { + const personListElement = fixture.debugElement.query(By.css(`ds-person-search-result-list-element`)); + expect(personListElement).not.toBeNull(); }); }); }); diff --git a/src/app/entity-groups/research-entities/item-list-elements/person/person-list-element.component.ts b/src/app/entity-groups/research-entities/item-list-elements/person/person-list-element.component.ts index 46d90a6f2d..f35ed90c58 100644 --- a/src/app/entity-groups/research-entities/item-list-elements/person/person-list-element.component.ts +++ b/src/app/entity-groups/research-entities/item-list-elements/person/person-list-element.component.ts @@ -1,8 +1,10 @@ import { Component } from '@angular/core'; -import { ItemViewMode, rendersItemType } from '../../../../shared/items/item-type-decorator'; -import { TypedItemSearchResultListElementComponent } from '../../../../shared/object-list/item-list-element/item-types/typed-item-search-result-list-element.component'; +import { ViewMode } from '../../../../core/shared/view-mode.model'; +import { listableObjectComponent } from '../../../../shared/object-collection/shared/listable-object/listable-object.decorator'; +import { AbstractListableElementComponent } from '../../../../shared/object-collection/shared/object-collection-element/abstract-listable-element.component'; +import { Item } from '../../../../core/shared/item.model'; -@rendersItemType('Person', ItemViewMode.Element) +@listableObjectComponent('Person', ViewMode.ListElement) @Component({ selector: 'ds-person-list-element', styleUrls: ['./person-list-element.component.scss'], @@ -11,5 +13,5 @@ import { TypedItemSearchResultListElementComponent } from '../../../../shared/ob /** * The component for displaying a list element for an item of the type Person */ -export class PersonListElementComponent extends TypedItemSearchResultListElementComponent { +export class PersonListElementComponent extends AbstractListableElementComponent { } diff --git a/src/app/entity-groups/research-entities/item-list-elements/person/person-metadata-list-element.component.ts b/src/app/entity-groups/research-entities/item-list-elements/person/person-metadata-list-element.component.ts deleted file mode 100644 index 35fbcd1173..0000000000 --- a/src/app/entity-groups/research-entities/item-list-elements/person/person-metadata-list-element.component.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { Component } from '@angular/core'; -import { ItemViewMode, rendersItemType } from '../../../../shared/items/item-type-decorator'; -import { MetadataRepresentationType } from '../../../../core/shared/metadata-representation/metadata-representation.model'; -import { ItemMetadataRepresentationListElementComponent } from '../../../../shared/object-list/metadata-representation-list-element/item/item-metadata-representation-list-element.component'; - -@rendersItemType('Person', ItemViewMode.Element, MetadataRepresentationType.Item) -@Component({ - selector: 'ds-person-metadata-list-element', - templateUrl: './person-metadata-list-element.component.html' -}) -/** - * The component for displaying a list element for an item of the type Person - */ -export class PersonMetadataListElementComponent extends ItemMetadataRepresentationListElementComponent { -} diff --git a/src/app/entity-groups/research-entities/item-list-elements/project/project-list-element.component.html b/src/app/entity-groups/research-entities/item-list-elements/project/project-list-element.component.html index 3e979b4e4d..8f74452eaa 100644 --- a/src/app/entity-groups/research-entities/item-list-elements/project/project-list-element.component.html +++ b/src/app/entity-groups/research-entities/item-list-elements/project/project-list-element.component.html @@ -1,16 +1 @@ - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/src/app/entity-groups/research-entities/item-list-elements/project/project-list-element.component.spec.ts b/src/app/entity-groups/research-entities/item-list-elements/project/project-list-element.component.spec.ts index 02dc3f6d73..dfa2f2506c 100644 --- a/src/app/entity-groups/research-entities/item-list-elements/project/project-list-element.component.spec.ts +++ b/src/app/entity-groups/research-entities/item-list-elements/project/project-list-element.component.spec.ts @@ -1,17 +1,13 @@ -import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { async, TestBed } from '@angular/core/testing'; import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA } from '@angular/core'; import { By } from '@angular/platform-browser'; -import { ProjectListElementComponent } from './project-list-element.component'; import { of as observableOf } from 'rxjs'; import { Item } from '../../../../core/shared/item.model'; import { TruncatePipe } from '../../../../shared/utils/truncate.pipe'; -import { ITEM } from '../../../../shared/items/switcher/item-type-switcher.component'; import { TruncatableService } from '../../../../shared/truncatable/truncatable.service'; +import { ProjectListElementComponent } from './project-list-element.component'; -let projectListElementComponent: ProjectListElementComponent; -let fixture: ComponentFixture; - -const mockItemWithMetadata: Item = Object.assign(new Item(), { +const mockItem: Item = Object.assign(new Item(), { bitstreams: observableOf({}), metadata: { 'dc.title': [ @@ -28,28 +24,22 @@ const mockItemWithMetadata: Item = Object.assign(new Item(), { // ] } }); -const mockItemWithoutMetadata: Item = Object.assign(new Item(), { - bitstreams: observableOf({}), - metadata: { - 'dc.title': [ - { - language: 'en_US', - value: 'This is just another title' - } - ] - } -}); describe('ProjectListElementComponent', () => { + let comp; + let fixture; + + const truncatableServiceStub: any = { + isCollapsed: (id: number) => observableOf(true), + }; + beforeEach(async(() => { TestBed.configureTestingModule({ - declarations: [ ProjectListElementComponent , TruncatePipe], + declarations: [ProjectListElementComponent, TruncatePipe], providers: [ - { provide: ITEM, useValue: mockItemWithMetadata}, - { provide: TruncatableService, useValue: {} } + { provide: TruncatableService, useValue: truncatableServiceStub }, ], - - schemas: [ NO_ERRORS_SCHEMA ] + schemas: [NO_ERRORS_SCHEMA] }).overrideComponent(ProjectListElementComponent, { set: { changeDetection: ChangeDetectionStrategy.Default } }).compileComponents(); @@ -57,31 +47,18 @@ describe('ProjectListElementComponent', () => { beforeEach(async(() => { fixture = TestBed.createComponent(ProjectListElementComponent); - projectListElementComponent = fixture.componentInstance; - + comp = fixture.componentInstance; })); - // describe('When the item has a status', () => { - // beforeEach(() => { - // projectListElementComponent.item = mockItemWithMetadata; - // fixture.detectChanges(); - // }); - // - // it('should show the status span', () => { - // const statusField = fixture.debugElement.query(By.css('span.item-list-status')); - // expect(statusField).not.toBeNull(); - // }); - // }); - // - // describe('When the item has no status', () => { - // beforeEach(() => { - // projectListElementComponent.item = mockItemWithoutMetadata; - // fixture.detectChanges(); - // }); - // - // it('should not show the status span', () => { - // const statusField = fixture.debugElement.query(By.css('span.item-list-status')); - // expect(statusField).toBeNull(); - // }); - // }); + describe(`when the project is rendered`, () => { + beforeEach(() => { + comp.object = mockItem; + fixture.detectChanges(); + }); + + it(`should contain a ProjectListElementComponent`, () => { + const projectListElement = fixture.debugElement.query(By.css(`ds-project-search-result-list-element`)); + expect(projectListElement).not.toBeNull(); + }); + }); }); diff --git a/src/app/entity-groups/research-entities/item-list-elements/project/project-list-element.component.ts b/src/app/entity-groups/research-entities/item-list-elements/project/project-list-element.component.ts index 2d3e716ff4..5f158158d8 100644 --- a/src/app/entity-groups/research-entities/item-list-elements/project/project-list-element.component.ts +++ b/src/app/entity-groups/research-entities/item-list-elements/project/project-list-element.component.ts @@ -1,8 +1,10 @@ import { Component } from '@angular/core'; -import { ItemViewMode, rendersItemType } from '../../../../shared/items/item-type-decorator'; -import { TypedItemSearchResultListElementComponent } from '../../../../shared/object-list/item-list-element/item-types/typed-item-search-result-list-element.component'; +import { AbstractListableElementComponent } from '../../../../shared/object-collection/shared/object-collection-element/abstract-listable-element.component'; +import { Item } from '../../../../core/shared/item.model'; +import { listableObjectComponent } from '../../../../shared/object-collection/shared/listable-object/listable-object.decorator'; +import { ViewMode } from '../../../../core/shared/view-mode.model'; -@rendersItemType('Project', ItemViewMode.Element) +@listableObjectComponent('Project', ViewMode.ListElement) @Component({ selector: 'ds-project-list-element', styleUrls: ['./project-list-element.component.scss'], @@ -11,5 +13,5 @@ import { TypedItemSearchResultListElementComponent } from '../../../../shared/ob /** * The component for displaying a list element for an item of the type Project */ -export class ProjectListElementComponent extends TypedItemSearchResultListElementComponent { +export class ProjectListElementComponent extends AbstractListableElementComponent { } diff --git a/src/app/entity-groups/research-entities/item-list-elements/search-result-list-elements/org-unit/org-unit-search-result-list-element.component.html b/src/app/entity-groups/research-entities/item-list-elements/search-result-list-elements/org-unit/org-unit-search-result-list-element.component.html new file mode 100644 index 0000000000..f08d0fdc11 --- /dev/null +++ b/src/app/entity-groups/research-entities/item-list-elements/search-result-list-elements/org-unit/org-unit-search-result-list-element.component.html @@ -0,0 +1,19 @@ + + + + + + + + + + + + + diff --git a/src/app/entity-groups/research-entities/item-list-elements/search-result-list-elements/org-unit/org-unit-search-result-list-element.component.scss b/src/app/entity-groups/research-entities/item-list-elements/search-result-list-elements/org-unit/org-unit-search-result-list-element.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/entity-groups/research-entities/item-list-elements/search-result-list-elements/org-unit/org-unit-search-result-list-element.component.spec.ts b/src/app/entity-groups/research-entities/item-list-elements/search-result-list-elements/org-unit/org-unit-search-result-list-element.component.spec.ts new file mode 100644 index 0000000000..0597c0032d --- /dev/null +++ b/src/app/entity-groups/research-entities/item-list-elements/search-result-list-elements/org-unit/org-unit-search-result-list-element.component.spec.ts @@ -0,0 +1,94 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA } from '@angular/core'; +import { By } from '@angular/platform-browser'; +import { of as observableOf } from 'rxjs'; +import { OrgUnitSearchResultListElementComponent } from './org-unit-search-result-list-element.component'; +import { Item } from '../../../../../core/shared/item.model'; +import { TruncatePipe } from '../../../../../shared/utils/truncate.pipe'; +import { TruncatableService } from '../../../../../shared/truncatable/truncatable.service'; +import { ItemSearchResult } from '../../../../../shared/object-collection/shared/item-search-result.model'; + +let orgUnitListElementComponent: OrgUnitSearchResultListElementComponent; +let fixture: ComponentFixture; + +const mockItemWithMetadata: ItemSearchResult = Object.assign( + new ItemSearchResult(), + { + indexableObject: Object.assign(new Item(), { + bitstreams: observableOf({}), + metadata: { + 'dc.title': [ + { + language: 'en_US', + value: 'This is just another title' + } + ], + 'dc.description': [ + { + language: 'en_US', + value: 'A description about the OrgUnit' + } + ] + } + }) + }); +const mockItemWithoutMetadata: ItemSearchResult = Object.assign( + new ItemSearchResult(), + { + indexableObject: Object.assign(new Item(), { + bitstreams: observableOf({}), + metadata: { + 'dc.title': [ + { + language: 'en_US', + value: 'This is just another title' + } + ] + } + }) + }); + +describe('OrgUnitSearchResultListElementComponent', () => { + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ OrgUnitSearchResultListElementComponent , TruncatePipe], + providers: [ + { provide: TruncatableService, useValue: {} } + ], + + schemas: [ NO_ERRORS_SCHEMA ] + }).overrideComponent(OrgUnitSearchResultListElementComponent, { + set: { changeDetection: ChangeDetectionStrategy.Default } + }).compileComponents(); + })); + + beforeEach(async(() => { + fixture = TestBed.createComponent(OrgUnitSearchResultListElementComponent); + orgUnitListElementComponent = fixture.componentInstance; + + })); + + describe('When the item has an org unit description', () => { + beforeEach(() => { + orgUnitListElementComponent.object = mockItemWithMetadata; + fixture.detectChanges(); + }); + + it('should show the description span', () => { + const orgUnitDescriptionField = fixture.debugElement.query(By.css('span.item-list-org-unit-description')); + expect(orgUnitDescriptionField).not.toBeNull(); + }); + }); + + describe('When the item has no org unit description', () => { + beforeEach(() => { + orgUnitListElementComponent.object = mockItemWithoutMetadata; + fixture.detectChanges(); + }); + + it('should not show the description span', () => { + const orgUnitDescriptionField = fixture.debugElement.query(By.css('span.item-list-org-unit-description')); + expect(orgUnitDescriptionField).toBeNull(); + }); + }); +}); diff --git a/src/app/entity-groups/research-entities/item-list-elements/search-result-list-elements/org-unit/org-unit-search-result-list-element.component.ts b/src/app/entity-groups/research-entities/item-list-elements/search-result-list-elements/org-unit/org-unit-search-result-list-element.component.ts new file mode 100644 index 0000000000..5b50e5a78c --- /dev/null +++ b/src/app/entity-groups/research-entities/item-list-elements/search-result-list-elements/org-unit/org-unit-search-result-list-element.component.ts @@ -0,0 +1,18 @@ +import { Component } from '@angular/core'; +import { ViewMode } from '../../../../../core/shared/view-mode.model'; +import { listableObjectComponent } from '../../../../../shared/object-collection/shared/listable-object/listable-object.decorator'; +import { SearchResultListElementComponent } from '../../../../../shared/object-list/search-result-list-element/search-result-list-element.component'; +import { ItemSearchResult } from '../../../../../shared/object-collection/shared/item-search-result.model'; +import { Item } from '../../../../../core/shared/item.model'; + +@listableObjectComponent('OrgUnitSearchResult', ViewMode.ListElement) +@Component({ + selector: 'ds-org-unit-search-result-list-element', + styleUrls: ['./org-unit-search-result-list-element.component.scss'], + templateUrl: './org-unit-search-result-list-element.component.html' +}) +/** + * The component for displaying a list element for an item search result of the type Organisation Unit + */ +export class OrgUnitSearchResultListElementComponent extends SearchResultListElementComponent { +} diff --git a/src/app/entity-groups/research-entities/item-list-elements/search-result-list-elements/person/person-search-result-list-element.component.html b/src/app/entity-groups/research-entities/item-list-elements/search-result-list-elements/person/person-search-result-list-element.component.html new file mode 100644 index 0000000000..b2791c4891 --- /dev/null +++ b/src/app/entity-groups/research-entities/item-list-elements/search-result-list-elements/person/person-search-result-list-element.component.html @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + diff --git a/src/app/entity-groups/research-entities/item-list-elements/search-result-list-elements/person/person-search-result-list-element.component.scss b/src/app/entity-groups/research-entities/item-list-elements/search-result-list-elements/person/person-search-result-list-element.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/entity-groups/research-entities/item-list-elements/search-result-list-elements/person/person-search-result-list-element.component.spec.ts b/src/app/entity-groups/research-entities/item-list-elements/search-result-list-elements/person/person-search-result-list-element.component.spec.ts new file mode 100644 index 0000000000..a240d31bec --- /dev/null +++ b/src/app/entity-groups/research-entities/item-list-elements/search-result-list-elements/person/person-search-result-list-element.component.spec.ts @@ -0,0 +1,94 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA } from '@angular/core'; +import { By } from '@angular/platform-browser'; +import { of as observableOf } from 'rxjs'; +import { ItemSearchResult } from '../../../../../shared/object-collection/shared/item-search-result.model'; +import { PersonSearchResultListElementComponent } from './person-search-result-list-element.component'; +import { Item } from '../../../../../core/shared/item.model'; +import { TruncatePipe } from '../../../../../shared/utils/truncate.pipe'; +import { TruncatableService } from '../../../../../shared/truncatable/truncatable.service'; + +let personListElementComponent: PersonSearchResultListElementComponent; +let fixture: ComponentFixture; + +const mockItemWithMetadata: ItemSearchResult = Object.assign( + new ItemSearchResult(), + { + indexableObject: Object.assign(new Item(), { + bitstreams: observableOf({}), + metadata: { + 'dc.title': [ + { + language: 'en_US', + value: 'This is just another title' + } + ], + 'person.jobTitle': [ + { + language: 'en_US', + value: 'Developer' + } + ] + } + }) + }); +const mockItemWithoutMetadata: ItemSearchResult = Object.assign( + new ItemSearchResult(), + { + indexableObject: Object.assign(new Item(), { + bitstreams: observableOf({}), + metadata: { + 'dc.title': [ + { + language: 'en_US', + value: 'This is just another title' + } + ] + } + }) + }); + +describe('PersonSearchResultListElementComponent', () => { + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [PersonSearchResultListElementComponent, TruncatePipe], + providers: [ + { provide: TruncatableService, useValue: {} } + ], + + schemas: [NO_ERRORS_SCHEMA] + }).overrideComponent(PersonSearchResultListElementComponent, { + set: { changeDetection: ChangeDetectionStrategy.Default } + }).compileComponents(); + })); + + beforeEach(async(() => { + fixture = TestBed.createComponent(PersonSearchResultListElementComponent); + personListElementComponent = fixture.componentInstance; + + })); + + describe('When the item has a job title', () => { + beforeEach(() => { + personListElementComponent.object = mockItemWithMetadata; + fixture.detectChanges(); + }); + + it('should show the job title span', () => { + const jobTitleField = fixture.debugElement.query(By.css('span.item-list-job-title')); + expect(jobTitleField).not.toBeNull(); + }); + }); + + describe('When the item has no job title', () => { + beforeEach(() => { + personListElementComponent.object = mockItemWithoutMetadata; + fixture.detectChanges(); + }); + + it('should not show the job title span', () => { + const jobTitleField = fixture.debugElement.query(By.css('span.item-list-job-title')); + expect(jobTitleField).toBeNull(); + }); + }); +}); diff --git a/src/app/entity-groups/research-entities/item-list-elements/search-result-list-elements/person/person-search-result-list-element.component.ts b/src/app/entity-groups/research-entities/item-list-elements/search-result-list-elements/person/person-search-result-list-element.component.ts new file mode 100644 index 0000000000..b4b4621261 --- /dev/null +++ b/src/app/entity-groups/research-entities/item-list-elements/search-result-list-elements/person/person-search-result-list-element.component.ts @@ -0,0 +1,18 @@ +import { Component } from '@angular/core'; +import { SearchResultListElementComponent } from '../../../../../shared/object-list/search-result-list-element/search-result-list-element.component'; +import { ItemSearchResult } from '../../../../../shared/object-collection/shared/item-search-result.model'; +import { listableObjectComponent } from '../../../../../shared/object-collection/shared/listable-object/listable-object.decorator'; +import { ViewMode } from '../../../../../core/shared/view-mode.model'; +import { Item } from '../../../../../core/shared/item.model'; + +@listableObjectComponent('PersonSearchResult', ViewMode.ListElement) +@Component({ + selector: 'ds-person-search-result-list-element', + styleUrls: ['./person-search-result-list-element.component.scss'], + templateUrl: './person-search-result-list-element.component.html' +}) +/** + * The component for displaying a list element for an item search result of the type Person + */ +export class PersonSearchResultListElementComponent extends SearchResultListElementComponent { +} diff --git a/src/app/entity-groups/research-entities/item-list-elements/search-result-list-elements/project/project-search-result-list-element.component.html b/src/app/entity-groups/research-entities/item-list-elements/search-result-list-elements/project/project-search-result-list-element.component.html new file mode 100644 index 0000000000..95bff99e7e --- /dev/null +++ b/src/app/entity-groups/research-entities/item-list-elements/search-result-list-elements/project/project-search-result-list-element.component.html @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + diff --git a/src/app/entity-groups/research-entities/item-list-elements/search-result-list-elements/project/project-search-result-list-element.component.scss b/src/app/entity-groups/research-entities/item-list-elements/search-result-list-elements/project/project-search-result-list-element.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/entity-groups/research-entities/item-list-elements/search-result-list-elements/project/project-search-result-list-element.component.spec.ts b/src/app/entity-groups/research-entities/item-list-elements/search-result-list-elements/project/project-search-result-list-element.component.spec.ts new file mode 100644 index 0000000000..128190a88b --- /dev/null +++ b/src/app/entity-groups/research-entities/item-list-elements/search-result-list-elements/project/project-search-result-list-element.component.spec.ts @@ -0,0 +1,94 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA } from '@angular/core'; +import { of as observableOf } from 'rxjs'; +import { ItemSearchResult } from '../../../../../shared/object-collection/shared/item-search-result.model'; +import { ProjectSearchResultListElementComponent } from './project-search-result-list-element.component'; +import { Item } from '../../../../../core/shared/item.model'; +import { TruncatePipe } from '../../../../../shared/utils/truncate.pipe'; +import { TruncatableService } from '../../../../../shared/truncatable/truncatable.service'; + +let projectListElementComponent: ProjectSearchResultListElementComponent; +let fixture: ComponentFixture; + +const mockItemWithMetadata: ItemSearchResult = Object.assign( + new ItemSearchResult(), + { + indexableObject: Object.assign(new Item(), { + bitstreams: observableOf({}), + metadata: { + 'dc.title': [ + { + language: 'en_US', + value: 'This is just another title' + } + ], + // 'project.identifier.status': [ + // { + // language: 'en_US', + // value: 'A status about the project' + // } + // ] + } + }) + }); + +const mockItemWithoutMetadata: ItemSearchResult = Object.assign( + new ItemSearchResult(), + { + indexableObject: Object.assign(new Item(), { + bitstreams: observableOf({}), + metadata: { + 'dc.title': [ + { + language: 'en_US', + value: 'This is just another title' + } + ] + } + }) + }); + +describe('ProjectSearchResultListElementComponent', () => { + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ProjectSearchResultListElementComponent, TruncatePipe], + providers: [ + { provide: TruncatableService, useValue: {} } + ], + + schemas: [NO_ERRORS_SCHEMA] + }).overrideComponent(ProjectSearchResultListElementComponent, { + set: { changeDetection: ChangeDetectionStrategy.Default } + }).compileComponents(); + })); + + beforeEach(async(() => { + fixture = TestBed.createComponent(ProjectSearchResultListElementComponent); + projectListElementComponent = fixture.componentInstance; + + })); + + // describe('When the item has a status', () => { + // beforeEach(() => { + // projectListElementComponent.item = mockItemWithMetadata; + // fixture.detectChanges(); + // }); + // + // it('should show the status span', () => { + // const statusField = fixture.debugElement.query(By.css('span.item-list-status')); + // expect(statusField).not.toBeNull(); + // }); + // }); + // + // describe('When the item has no status', () => { + // beforeEach(() => { + // projectListElementComponent.item = mockItemWithoutMetadata; + // fixture.detectChanges(); + // }); + // + // it('should not show the status span', () => { + // const statusField = fixture.debugElement.query(By.css('span.item-list-status')); + // expect(statusField).toBeNull(); + // }); + // }); +}); diff --git a/src/app/entity-groups/research-entities/item-list-elements/search-result-list-elements/project/project-search-result-list-element.component.ts b/src/app/entity-groups/research-entities/item-list-elements/search-result-list-elements/project/project-search-result-list-element.component.ts new file mode 100644 index 0000000000..faa15add31 --- /dev/null +++ b/src/app/entity-groups/research-entities/item-list-elements/search-result-list-elements/project/project-search-result-list-element.component.ts @@ -0,0 +1,18 @@ +import { Component } from '@angular/core'; +import { SearchResultListElementComponent } from '../../../../../shared/object-list/search-result-list-element/search-result-list-element.component'; +import { ItemSearchResult } from '../../../../../shared/object-collection/shared/item-search-result.model'; +import { Item } from '../../../../../core/shared/item.model'; +import { listableObjectComponent } from '../../../../../shared/object-collection/shared/listable-object/listable-object.decorator'; +import { ViewMode } from '../../../../../core/shared/view-mode.model'; + +@listableObjectComponent('ProjectSearchResult', ViewMode.ListElement) +@Component({ + selector: 'ds-project-search-result-list-element', + styleUrls: ['./project-search-result-list-element.component.scss'], + templateUrl: './project-search-result-list-element.component.html' +}) +/** + * The component for displaying a list element for an item search result of the type Project + */ +export class ProjectSearchResultListElementComponent extends SearchResultListElementComponent { +} diff --git a/src/app/entity-groups/research-entities/item-pages/orgunit/orgunit.component.html b/src/app/entity-groups/research-entities/item-pages/org-unit/org-unit.component.html similarity index 72% rename from src/app/entity-groups/research-entities/item-pages/orgunit/orgunit.component.html rename to src/app/entity-groups/research-entities/item-pages/org-unit/org-unit.component.html index a3d2fedb10..4d97868b58 100644 --- a/src/app/entity-groups/research-entities/item-pages/orgunit/orgunit.component.html +++ b/src/app/entity-groups/research-entities/item-pages/org-unit/org-unit.component.html @@ -1,50 +1,50 @@

- {{'orgunit.page.titleprefix' | translate}} + {{'orgunit.page.titleprefix' | translate}}

- + - - - -
- diff --git a/src/app/entity-groups/research-entities/item-pages/orgunit/orgunit.component.scss b/src/app/entity-groups/research-entities/item-pages/org-unit/org-unit.component.scss similarity index 100% rename from src/app/entity-groups/research-entities/item-pages/orgunit/orgunit.component.scss rename to src/app/entity-groups/research-entities/item-pages/org-unit/org-unit.component.scss diff --git a/src/app/entity-groups/research-entities/item-pages/orgunit/orgunit.component.spec.ts b/src/app/entity-groups/research-entities/item-pages/org-unit/org-unit.component.spec.ts similarity index 94% rename from src/app/entity-groups/research-entities/item-pages/orgunit/orgunit.component.spec.ts rename to src/app/entity-groups/research-entities/item-pages/org-unit/org-unit.component.spec.ts index a49105b2e3..28b014ddba 100644 --- a/src/app/entity-groups/research-entities/item-pages/orgunit/orgunit.component.spec.ts +++ b/src/app/entity-groups/research-entities/item-pages/org-unit/org-unit.component.spec.ts @@ -2,7 +2,7 @@ import { Item } from '../../../../core/shared/item.model'; import { RemoteData } from '../../../../core/data/remote-data'; import { PaginatedList } from '../../../../core/data/paginated-list'; import { PageInfo } from '../../../../core/shared/page-info.model'; -import { OrgunitComponent } from './orgunit.component'; +import { OrgUnitComponent } from './org-unit.component'; import { of as observableOf } from 'rxjs'; import { createRelationshipsObservable, @@ -47,4 +47,4 @@ const mockItem: Item = Object.assign(new Item(), { relationships: createRelationshipsObservable() }); -describe('OrgUnitComponent', getItemPageFieldsTest(mockItem, OrgunitComponent)); +describe('OrgUnitComponent', getItemPageFieldsTest(mockItem, OrgUnitComponent)); diff --git a/src/app/entity-groups/research-entities/item-pages/org-unit/org-unit.component.ts b/src/app/entity-groups/research-entities/item-pages/org-unit/org-unit.component.ts new file mode 100644 index 0000000000..d9d4461bfa --- /dev/null +++ b/src/app/entity-groups/research-entities/item-pages/org-unit/org-unit.component.ts @@ -0,0 +1,16 @@ +import { Component } from '@angular/core'; +import { ItemComponent } from '../../../../+item-page/simple/item-types/shared/item.component'; +import { listableObjectComponent } from '../../../../shared/object-collection/shared/listable-object/listable-object.decorator'; +import { ViewMode } from '../../../../core/shared/view-mode.model'; + +@listableObjectComponent('OrgUnit', ViewMode.StandalonePage) +@Component({ + selector: 'ds-org-unit', + styleUrls: ['./org-unit.component.scss'], + templateUrl: './org-unit.component.html' +}) +/** + * The component for displaying metadata and relations of an item of the type Organisation Unit + */ +export class OrgUnitComponent extends ItemComponent { +} diff --git a/src/app/entity-groups/research-entities/item-pages/orgunit/orgunit.component.ts b/src/app/entity-groups/research-entities/item-pages/orgunit/orgunit.component.ts deleted file mode 100644 index 804288b1dc..0000000000 --- a/src/app/entity-groups/research-entities/item-pages/orgunit/orgunit.component.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { Component } from '@angular/core'; -import { ItemViewMode, rendersItemType } from '../../../../shared/items/item-type-decorator'; -import { ItemComponent } from '../../../../+item-page/simple/item-types/shared/item.component'; - -@rendersItemType('OrgUnit', ItemViewMode.Full) -@Component({ - selector: 'ds-orgunit', - styleUrls: ['./orgunit.component.scss'], - templateUrl: './orgunit.component.html' -}) -/** - * The component for displaying metadata and relations of an item of the type Organisation Unit - */ -export class OrgunitComponent extends ItemComponent { -} diff --git a/src/app/entity-groups/research-entities/item-pages/person/person.component.html b/src/app/entity-groups/research-entities/item-pages/person/person.component.html index 3f0ca90368..ff675ab057 100644 --- a/src/app/entity-groups/research-entities/item-pages/person/person.component.html +++ b/src/app/entity-groups/research-entities/item-pages/person/person.component.html @@ -1,59 +1,59 @@

- {{'person.page.titleprefix' | translate}} + {{'person.page.titleprefix' | translate}}

- + - - + - - +
-
diff --git a/src/app/entity-groups/research-entities/item-pages/person/person.component.ts b/src/app/entity-groups/research-entities/item-pages/person/person.component.ts index b85b85ef7c..15c7184702 100644 --- a/src/app/entity-groups/research-entities/item-pages/person/person.component.ts +++ b/src/app/entity-groups/research-entities/item-pages/person/person.component.ts @@ -1,8 +1,9 @@ import { Component } from '@angular/core'; -import { ItemViewMode, rendersItemType } from '../../../../shared/items/item-type-decorator'; import { ItemComponent } from '../../../../+item-page/simple/item-types/shared/item.component'; +import { listableObjectComponent } from '../../../../shared/object-collection/shared/listable-object/listable-object.decorator'; +import { ViewMode } from '../../../../core/shared/view-mode.model'; -@rendersItemType('Person', ItemViewMode.Full) +@listableObjectComponent('Person', ViewMode.StandalonePage) @Component({ selector: 'ds-person', styleUrls: ['./person.component.scss'], diff --git a/src/app/entity-groups/research-entities/item-pages/project/project.component.html b/src/app/entity-groups/research-entities/item-pages/project/project.component.html index 9ea0676f23..bb6ce21cd1 100644 --- a/src/app/entity-groups/research-entities/item-pages/project/project.component.html +++ b/src/app/entity-groups/research-entities/item-pages/project/project.component.html @@ -1,60 +1,60 @@

- {{'project.page.titleprefix' | translate}} + {{'project.page.titleprefix' | translate}}

- + - + - - - +
- - diff --git a/src/app/entity-groups/research-entities/item-pages/project/project.component.ts b/src/app/entity-groups/research-entities/item-pages/project/project.component.ts index 5a45ac2829..8ac424af5b 100644 --- a/src/app/entity-groups/research-entities/item-pages/project/project.component.ts +++ b/src/app/entity-groups/research-entities/item-pages/project/project.component.ts @@ -1,8 +1,9 @@ import { Component } from '@angular/core'; -import { ItemViewMode, rendersItemType } from '../../../../shared/items/item-type-decorator'; import { ItemComponent } from '../../../../+item-page/simple/item-types/shared/item.component'; +import { listableObjectComponent } from '../../../../shared/object-collection/shared/listable-object/listable-object.decorator'; +import { ViewMode } from '../../../../core/shared/view-mode.model'; -@rendersItemType('Project', ItemViewMode.Full) +@listableObjectComponent('Project', ViewMode.StandalonePage) @Component({ selector: 'ds-project', styleUrls: ['./project.component.scss'], diff --git a/src/app/entity-groups/research-entities/item-list-elements/orgunit/orgunit-metadata-list-element.component.html b/src/app/entity-groups/research-entities/metadata-representations/org-unit/org-unit-item-metadata-list-element.component.html similarity index 100% rename from src/app/entity-groups/research-entities/item-list-elements/orgunit/orgunit-metadata-list-element.component.html rename to src/app/entity-groups/research-entities/metadata-representations/org-unit/org-unit-item-metadata-list-element.component.html diff --git a/src/app/entity-groups/research-entities/metadata-representations/org-unit/org-unit-item-metadata-list-element.component.spec.ts b/src/app/entity-groups/research-entities/metadata-representations/org-unit/org-unit-item-metadata-list-element.component.spec.ts new file mode 100644 index 0000000000..7d27b605ec --- /dev/null +++ b/src/app/entity-groups/research-entities/metadata-representations/org-unit/org-unit-item-metadata-list-element.component.spec.ts @@ -0,0 +1,49 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA } from '@angular/core'; +import { By } from '@angular/platform-browser'; +import { ItemMetadataRepresentation } from '../../../../core/shared/metadata-representation/item/item-metadata-representation.model'; +import { OrgUnitItemMetadataListElementComponent } from './org-unit-item-metadata-list-element.component'; +import { Item } from '../../../../core/shared/item.model'; +import { TooltipModule } from 'ngx-bootstrap'; +import { MetadataValue } from '../../../../core/shared/metadata.models'; + +const description = 'Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.'; +const organisation = 'Anonymous'; +const mockItem = Object.assign(new Item(), { metadata: { 'dc.description': [{ value: description }], 'organization.legalName': [{ value: organisation }] } }); +const virtMD = Object.assign(new MetadataValue(), { value: organisation }); +const mockItemMetadataRepresentation = Object.assign(new ItemMetadataRepresentation(virtMD), mockItem); + +describe('OrgUnitItemMetadataListElementComponent', () => { + let comp: OrgUnitItemMetadataListElementComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + imports: [TooltipModule.forRoot()], + declarations: [OrgUnitItemMetadataListElementComponent], + schemas: [NO_ERRORS_SCHEMA] + }).overrideComponent(OrgUnitItemMetadataListElementComponent, { + set: { changeDetection: ChangeDetectionStrategy.Default } + }).compileComponents(); + })); + + beforeEach(async(() => { + fixture = TestBed.createComponent(OrgUnitItemMetadataListElementComponent); + comp = fixture.componentInstance; + comp.metadataRepresentation = mockItemMetadataRepresentation; + fixture.detectChanges(); + })); + + it('should show the name of the organisation as a link', () => { + const linkText = fixture.debugElement.query(By.css('a')).nativeElement.textContent; + expect(linkText).toBe(organisation); + }); + + it('should show the description on hover over the link in a tooltip', () => { + const link = fixture.debugElement.query(By.css('a')); + link.triggerEventHandler('mouseover', null); + fixture.detectChanges(); + const tooltip = fixture.debugElement.query(By.css('.item-list-job-title')).nativeElement.textContent; + expect(tooltip).toBe(description); + }); +}); diff --git a/src/app/entity-groups/research-entities/metadata-representations/org-unit/org-unit-item-metadata-list-element.component.ts b/src/app/entity-groups/research-entities/metadata-representations/org-unit/org-unit-item-metadata-list-element.component.ts new file mode 100644 index 0000000000..183bebe10c --- /dev/null +++ b/src/app/entity-groups/research-entities/metadata-representations/org-unit/org-unit-item-metadata-list-element.component.ts @@ -0,0 +1,15 @@ +import { Component } from '@angular/core'; +import { metadataRepresentationComponent } from '../../../../shared/metadata-representation/metadata-representation.decorator'; +import { MetadataRepresentationType } from '../../../../core/shared/metadata-representation/metadata-representation.model'; +import { ItemMetadataRepresentationListElementComponent } from '../../../../shared/object-list/metadata-representation-list-element/item/item-metadata-representation-list-element.component'; + +@metadataRepresentationComponent('OrgUnit', MetadataRepresentationType.Item) +@Component({ + selector: 'ds-org-unit-item-metadata-list-element', + templateUrl: './org-unit-item-metadata-list-element.component.html' +}) +/** + * The component for displaying an item of the type OrgUnit as a metadata field + */ +export class OrgUnitItemMetadataListElementComponent extends ItemMetadataRepresentationListElementComponent { +} diff --git a/src/app/entity-groups/research-entities/item-list-elements/person/person-metadata-list-element.component.html b/src/app/entity-groups/research-entities/metadata-representations/person/person-item-metadata-list-element.component.html similarity index 100% rename from src/app/entity-groups/research-entities/item-list-elements/person/person-metadata-list-element.component.html rename to src/app/entity-groups/research-entities/metadata-representations/person/person-item-metadata-list-element.component.html diff --git a/src/app/entity-groups/research-entities/metadata-representations/person/person-item-metadata-list-element.component.spec.ts b/src/app/entity-groups/research-entities/metadata-representations/person/person-item-metadata-list-element.component.spec.ts new file mode 100644 index 0000000000..1081e45884 --- /dev/null +++ b/src/app/entity-groups/research-entities/metadata-representations/person/person-item-metadata-list-element.component.spec.ts @@ -0,0 +1,51 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA } from '@angular/core'; +import { By } from '@angular/platform-browser'; +import { ItemMetadataRepresentation } from '../../../../core/shared/metadata-representation/item/item-metadata-representation.model'; +import { Item } from '../../../../core/shared/item.model'; +import { PersonItemMetadataListElementComponent } from './person-item-metadata-list-element.component'; +import { TooltipModule } from 'ngx-bootstrap'; +import { MetadataValue } from '../../../../core/shared/metadata.models'; + +const jobTitle ='Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.'; +const firstName = 'Joe'; +const lastName = 'Anonymous'; +const mockItem = Object.assign(new Item(), { metadata: { 'person.jobTitle': [{ value: jobTitle }], 'person.givenName': [{ value: firstName }], 'person.familyName': [{ value: lastName }] } }); +const virtMD = Object.assign(new MetadataValue(), { value: lastName + ', ' + firstName }); + +const mockItemMetadataRepresentation = Object.assign(new ItemMetadataRepresentation(virtMD), mockItem); + +describe('PersonItemMetadataListElementComponent', () => { + let comp: PersonItemMetadataListElementComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + imports: [TooltipModule.forRoot()], + declarations: [PersonItemMetadataListElementComponent], + schemas: [NO_ERRORS_SCHEMA] + }).overrideComponent(PersonItemMetadataListElementComponent, { + set: { changeDetection: ChangeDetectionStrategy.Default } + }).compileComponents(); + })); + + beforeEach(async(() => { + fixture = TestBed.createComponent(PersonItemMetadataListElementComponent); + comp = fixture.componentInstance; + comp.metadataRepresentation = mockItemMetadataRepresentation; + fixture.detectChanges(); + })); + + it('should show the person\'s name as a link', () => { + const linkText = fixture.debugElement.query(By.css('a')).nativeElement.textContent; + expect(linkText).toBe(lastName + ', ' + firstName); + }); + + it('should show the description on hover over the link in a tooltip', () => { + const link = fixture.debugElement.query(By.css('a')); + link.triggerEventHandler('mouseover', null); + fixture.detectChanges(); + const tooltip = fixture.debugElement.query(By.css('.item-list-job-title')).nativeElement.textContent; + expect(tooltip).toBe(jobTitle); + }); +}); diff --git a/src/app/entity-groups/research-entities/metadata-representations/person/person-item-metadata-list-element.component.ts b/src/app/entity-groups/research-entities/metadata-representations/person/person-item-metadata-list-element.component.ts new file mode 100644 index 0000000000..f3d0a28fda --- /dev/null +++ b/src/app/entity-groups/research-entities/metadata-representations/person/person-item-metadata-list-element.component.ts @@ -0,0 +1,15 @@ +import { Component } from '@angular/core'; +import { metadataRepresentationComponent } from '../../../../shared/metadata-representation/metadata-representation.decorator'; +import { MetadataRepresentationType } from '../../../../core/shared/metadata-representation/metadata-representation.model'; +import { ItemMetadataRepresentationListElementComponent } from '../../../../shared/object-list/metadata-representation-list-element/item/item-metadata-representation-list-element.component'; + +@metadataRepresentationComponent('Person', MetadataRepresentationType.Item) +@Component({ + selector: 'ds-person-item-metadata-list-element', + templateUrl: './person-item-metadata-list-element.component.html' +}) +/** + * The component for displaying an item of the type Person as a metadata field + */ +export class PersonItemMetadataListElementComponent extends ItemMetadataRepresentationListElementComponent { +} diff --git a/src/app/entity-groups/research-entities/research-entities.module.ts b/src/app/entity-groups/research-entities/research-entities.module.ts index 099fa2a6a3..8829318f34 100644 --- a/src/app/entity-groups/research-entities/research-entities.module.ts +++ b/src/app/entity-groups/research-entities/research-entities.module.ts @@ -2,31 +2,43 @@ import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; import { SharedModule } from '../../shared/shared.module'; import { ItemPageModule } from '../../+item-page/item-page.module'; -import { OrgunitComponent } from './item-pages/orgunit/orgunit.component'; +import { OrgUnitComponent } from './item-pages/org-unit/org-unit.component'; import { PersonComponent } from './item-pages/person/person.component'; import { ProjectComponent } from './item-pages/project/project.component'; -import { OrgUnitListElementComponent } from './item-list-elements/orgunit/orgunit-list-element.component'; -import { OrgUnitMetadataListElementComponent } from './item-list-elements/orgunit/orgunit-metadata-list-element.component'; -import { PersonMetadataListElementComponent } from './item-list-elements/person/person-metadata-list-element.component'; +import { OrgUnitListElementComponent } from './item-list-elements/org-unit/org-unit-list-element.component'; import { PersonListElementComponent } from './item-list-elements/person/person-list-element.component'; import { ProjectListElementComponent } from './item-list-elements/project/project-list-element.component'; import { TooltipModule } from 'ngx-bootstrap'; import { PersonGridElementComponent } from './item-grid-elements/person/person-grid-element.component'; -import { OrgunitGridElementComponent } from './item-grid-elements/orgunit/orgunit-grid-element.component'; +import { OrgUnitGridElementComponent } from './item-grid-elements/org-unit/org-unit-grid-element.component'; import { ProjectGridElementComponent } from './item-grid-elements/project/project-grid-element.component'; +import { OrgUnitSearchResultListElementComponent } from './item-list-elements/search-result-list-elements/org-unit/org-unit-search-result-list-element.component'; +import { PersonSearchResultListElementComponent } from './item-list-elements/search-result-list-elements/person/person-search-result-list-element.component'; +import { ProjectSearchResultListElementComponent } from './item-list-elements/search-result-list-elements/project/project-search-result-list-element.component'; +import { PersonSearchResultGridElementComponent } from './item-grid-elements/search-result-grid-elements/person/person-search-result-grid-element.component'; +import { OrgUnitSearchResultGridElementComponent } from './item-grid-elements/search-result-grid-elements/org-unit/org-unit-search-result-grid-element.component'; +import { ProjectSearchResultGridElementComponent } from './item-grid-elements/search-result-grid-elements/project/project-search-result-grid-element.component'; +import { PersonItemMetadataListElementComponent } from './metadata-representations/person/person-item-metadata-list-element.component'; +import { OrgUnitItemMetadataListElementComponent } from './metadata-representations/org-unit/org-unit-item-metadata-list-element.component'; const ENTRY_COMPONENTS = [ - OrgunitComponent, + OrgUnitComponent, PersonComponent, ProjectComponent, OrgUnitListElementComponent, - OrgUnitMetadataListElementComponent, + OrgUnitItemMetadataListElementComponent, PersonListElementComponent, - PersonMetadataListElementComponent, + PersonItemMetadataListElementComponent, ProjectListElementComponent, PersonGridElementComponent, - OrgunitGridElementComponent, - ProjectGridElementComponent + OrgUnitGridElementComponent, + ProjectGridElementComponent, + OrgUnitSearchResultListElementComponent, + PersonSearchResultListElementComponent, + ProjectSearchResultListElementComponent, + PersonSearchResultGridElementComponent, + OrgUnitSearchResultGridElementComponent, + ProjectSearchResultGridElementComponent ]; @NgModule({ diff --git a/src/app/shared/browse-by/browse-by.component.html b/src/app/shared/browse-by/browse-by.component.html index c4b235f277..09d3cd3d60 100644 --- a/src/app/shared/browse-by/browse-by.component.html +++ b/src/app/shared/browse-by/browse-by.component.html @@ -25,7 +25,7 @@
  • - +
diff --git a/src/app/shared/dso-selector/dso-selector/dso-selector.component.html b/src/app/shared/dso-selector/dso-selector/dso-selector.component.html index 662144823d..e2eda4dcfd 100644 --- a/src/app/shared/dso-selector/dso-selector/dso-selector.component.html +++ b/src/app/shared/dso-selector/dso-selector/dso-selector.component.html @@ -15,6 +15,6 @@ class="list-group-item list-group-item-action border-0 list-entry" title="{{ listEntry.indexableObject.name }}" (click)="onSelect.emit(listEntry.indexableObject)" #listEntryElement> - +
diff --git a/src/app/shared/dso-selector/dso-selector/dso-selector.component.ts b/src/app/shared/dso-selector/dso-selector/dso-selector.component.ts index 04501e4923..af26f3f04f 100644 --- a/src/app/shared/dso-selector/dso-selector/dso-selector.component.ts +++ b/src/app/shared/dso-selector/dso-selector/dso-selector.component.ts @@ -19,6 +19,7 @@ import { RemoteData } from '../../../core/data/remote-data'; import { PaginatedList } from '../../../core/data/paginated-list'; import { SearchResult } from '../../../+search-page/search-result.model'; import { DSpaceObject } from '../../../core/shared/dspace-object.model'; +import { ViewMode } from '../../../core/shared/view-mode.model'; @Component({ selector: 'ds-dso-selector', @@ -31,7 +32,10 @@ import { DSpaceObject } from '../../../core/shared/dspace-object.model'; * The user can search the list by using the input field */ export class DSOSelectorComponent implements OnInit { - + /** + * The view mode of the listed objects + */ + viewMode = ViewMode.ListElement; /** * The initially selected DSO's uuid */ diff --git a/src/app/shared/input-suggestions/dso-input-suggestions/dso-input-suggestions.component.html b/src/app/shared/input-suggestions/dso-input-suggestions/dso-input-suggestions.component.html index 2b605ccdc6..7515b830b9 100644 --- a/src/app/shared/input-suggestions/dso-input-suggestions/dso-input-suggestions.component.html +++ b/src/app/shared/input-suggestions/dso-input-suggestions/dso-input-suggestions.component.html @@ -1,5 +1,5 @@
@@ -14,9 +14,7 @@ diff --git a/src/app/shared/input-suggestions/dso-input-suggestions/dso-input-suggestions.component.ts b/src/app/shared/input-suggestions/dso-input-suggestions/dso-input-suggestions.component.ts index bb1272f076..cf3658d5c9 100644 --- a/src/app/shared/input-suggestions/dso-input-suggestions/dso-input-suggestions.component.ts +++ b/src/app/shared/input-suggestions/dso-input-suggestions/dso-input-suggestions.component.ts @@ -2,6 +2,8 @@ import { Component, forwardRef, Input } from '@angular/core'; import { NG_VALUE_ACCESSOR } from '@angular/forms'; import { InputSuggestionsComponent } from '../input-suggestions.component'; import { DSpaceObject } from '../../../core/shared/dspace-object.model'; +import { ViewMode } from '../../../core/shared/view-mode.model'; +import { CollectionElementLinkType } from '../../object-collection/collection-element-link.type'; @Component({ selector: 'ds-dso-input-suggestions', @@ -22,6 +24,16 @@ import { DSpaceObject } from '../../../core/shared/dspace-object.model'; * Component representing a form with a autocomplete functionality for DSpaceObjects */ export class DsoInputSuggestionsComponent extends InputSuggestionsComponent { + /** + * The view mode of the listed object suggestions + */ + viewMode = ViewMode.ListElement; + + /** + * The available link types + */ + linkTypes = CollectionElementLinkType; + /** * The suggestions that should be shown */ diff --git a/src/app/shared/input-suggestions/input-suggestions.component.scss b/src/app/shared/input-suggestions/input-suggestions.component.scss index eb0db5ed42..263c315d30 100644 --- a/src/app/shared/input-suggestions/input-suggestions.component.scss +++ b/src/app/shared/input-suggestions/input-suggestions.component.scss @@ -5,19 +5,9 @@ white-space: normal; word-break: break-word; padding: $input-padding-y $input-padding-x; - position: relative; - &:focus { outline: none; } - - .click-blocker { - position: absolute; - top: 0; - left: 0; - right: 0; - bottom: 0; - } } } diff --git a/src/app/shared/items/item-type-decorator.ts b/src/app/shared/items/item-type-decorator.ts deleted file mode 100644 index 3a040ae5bf..0000000000 --- a/src/app/shared/items/item-type-decorator.ts +++ /dev/null @@ -1,66 +0,0 @@ -import { hasNoValue, hasValue } from '../empty.util'; -import { MetadataRepresentationType } from '../../core/shared/metadata-representation/metadata-representation.model'; - -export enum ItemViewMode { - Element = 'element', - Card = 'card', - Full = 'full', - Metadata = 'metadata' -} - -export const DEFAULT_ITEM_TYPE = 'Default'; -export const DEFAULT_VIEW_MODE = ItemViewMode.Element; -export const NO_REPRESENTATION_TYPE = MetadataRepresentationType.None; -export const DEFAULT_REPRESENTATION_TYPE = MetadataRepresentationType.PlainText; - -const map = new Map(); - -/** - * Decorator used for rendering simple item pages by type and viewMode (and optionally a representationType) - * @param type - * @param viewMode - * @param representationType - */ -export function rendersItemType(type: string, viewMode: string, representationType?: MetadataRepresentationType) { - return function decorator(component: any) { - if (hasNoValue(map.get(viewMode))) { - map.set(viewMode, new Map()); - } - if (hasNoValue(map.get(viewMode).get(type))) { - map.get(viewMode).set(type, new Map()); - } - if (hasNoValue(representationType)) { - representationType = NO_REPRESENTATION_TYPE; - } - if (hasValue(map.get(viewMode).get(type).get(representationType))) { - throw new Error(`There can't be more than one component to render Metadata of type "${type}" in view mode "${viewMode}" with representation type "${representationType}"`); - } - map.get(viewMode).get(type).set(representationType, component); - }; -} - -/** - * Get the component used for rendering an item by type and viewMode (and optionally a representationType) - * @param type - * @param viewMode - * @param representationType - */ -export function getComponentByItemType(type: string, viewMode: string, representationType?: MetadataRepresentationType) { - if (hasNoValue(representationType)) { - representationType = NO_REPRESENTATION_TYPE; - } - if (hasNoValue(map.get(viewMode))) { - viewMode = DEFAULT_VIEW_MODE; - } - if (hasNoValue(map.get(viewMode).get(type))) { - type = DEFAULT_ITEM_TYPE; - } - let representationComponent = map.get(viewMode).get(type).get(representationType); - if (hasNoValue(representationComponent)) { - representationComponent = map.get(viewMode).get(type).get(DEFAULT_REPRESENTATION_TYPE); - } - if (hasNoValue(representationComponent)) { - representationComponent = map.get(viewMode).get(type).get(NO_REPRESENTATION_TYPE); - } - return representationComponent; -} diff --git a/src/app/shared/items/switcher/item-type-switcher.component.html b/src/app/shared/items/switcher/item-type-switcher.component.html deleted file mode 100644 index f2ea5784fc..0000000000 --- a/src/app/shared/items/switcher/item-type-switcher.component.html +++ /dev/null @@ -1 +0,0 @@ - diff --git a/src/app/shared/items/switcher/item-type-switcher.component.scss b/src/app/shared/items/switcher/item-type-switcher.component.scss deleted file mode 100644 index 45a533cd01..0000000000 --- a/src/app/shared/items/switcher/item-type-switcher.component.scss +++ /dev/null @@ -1 +0,0 @@ -@import '../../../../styles/variables'; diff --git a/src/app/shared/items/switcher/item-type-switcher.component.spec.ts b/src/app/shared/items/switcher/item-type-switcher.component.spec.ts deleted file mode 100644 index 1c1612744a..0000000000 --- a/src/app/shared/items/switcher/item-type-switcher.component.spec.ts +++ /dev/null @@ -1,89 +0,0 @@ -import { ItemTypeSwitcherComponent } from './item-type-switcher.component'; -import { async, ComponentFixture, TestBed } from '@angular/core/testing'; -import { NO_ERRORS_SCHEMA } from '@angular/core'; -import { PageInfo } from '../../../core/shared/page-info.model'; -import { Item } from '../../../core/shared/item.model'; -import { PaginatedList } from '../../../core/data/paginated-list'; -import * as decorator from '../item-type-decorator'; -import { getComponentByItemType, ItemViewMode } from '../item-type-decorator'; -import { ItemMetadataRepresentation } from '../../../core/shared/metadata-representation/item/item-metadata-representation.model'; -import { createSuccessfulRemoteDataObject$ } from '../../testing/utils'; -import createSpy = jasmine.createSpy; - -const relationType = 'type'; -const mockItem: Item = Object.assign(new Item(), { - bitstreams: createSuccessfulRemoteDataObject$(new PaginatedList(new PageInfo(), [])), - metadata: { - 'dc.title': [ - { - language: 'en_US', - value: 'test item' - } - ], - 'relationship.type': [ - { - language: 'en_US', - value: relationType - } - ] - } -}); -const mockItemMetadataRepresentation = Object.assign(new ItemMetadataRepresentation(Object.assign({})), mockItem); -let viewMode = ItemViewMode.Full; - -describe('ItemTypeSwitcherComponent', () => { - let comp: ItemTypeSwitcherComponent; - let fixture: ComponentFixture; - - beforeEach(async(() => { - TestBed.configureTestingModule({ - declarations: [ ItemTypeSwitcherComponent ], - schemas: [ NO_ERRORS_SCHEMA ] - }).compileComponents(); // compile template and css - })); - - beforeEach(async(() => { - fixture = TestBed.createComponent(ItemTypeSwitcherComponent); - comp = fixture.componentInstance; - comp.object = mockItem; - comp.viewMode = viewMode; - spyOnProperty(decorator, 'getComponentByItemType').and.returnValue(createSpy('getComponentByItemType')) - })); - - describe('when the injected object is of type Item', () => { - beforeEach(() => { - viewMode = ItemViewMode.Full; - comp.object = mockItem; - comp.viewMode = viewMode; - }); - - describe('when calling getComponent', () => { - beforeEach(() => { - (comp as any).getComponent(); - }); - - it('should call getComponentByItemType with parameters type and viewMode', () => { - expect(decorator.getComponentByItemType).toHaveBeenCalledWith(relationType, viewMode); - }); - }); - }); - - describe('when the injected object is of type MetadataRepresentation', () => { - beforeEach(() => { - viewMode = ItemViewMode.Metadata; - comp.object = mockItemMetadataRepresentation; - comp.viewMode = viewMode; - }); - - describe('when calling getComponent', () => { - beforeEach(() => { - (comp as any).getComponent(); - }); - - it('should call getComponentByItemType with parameters type, viewMode and representationType', () => { - expect(decorator.getComponentByItemType).toHaveBeenCalledWith(relationType, viewMode, mockItemMetadataRepresentation.representationType); - }); - }); - }); - -}); diff --git a/src/app/shared/items/switcher/item-type-switcher.component.ts b/src/app/shared/items/switcher/item-type-switcher.component.ts deleted file mode 100644 index cd061bc1dd..0000000000 --- a/src/app/shared/items/switcher/item-type-switcher.component.ts +++ /dev/null @@ -1,69 +0,0 @@ -import { Component, InjectionToken, Injector, Input, OnInit } from '@angular/core'; -import { SearchResult } from '../../../+search-page/search-result.model'; -import { Item } from '../../../core/shared/item.model'; -import { hasValue } from '../../empty.util'; -import { ItemSearchResult } from '../../object-collection/shared/item-search-result.model'; -import { getComponentByItemType } from '../item-type-decorator'; -import { MetadataRepresentation } from '../../../core/shared/metadata-representation/metadata-representation.model'; - -export const ITEM: InjectionToken = new InjectionToken('item'); - -@Component({ - selector: 'ds-item-type-switcher', - styleUrls: ['./item-type-switcher.component.scss'], - templateUrl: './item-type-switcher.component.html' -}) -/** - * Component for determining what component to use depending on the item's relationship type (relationship.type) - */ -export class ItemTypeSwitcherComponent implements OnInit { - /** - * The item or metadata to determine the component for - */ - @Input() object: Item | SearchResult | MetadataRepresentation; - - /** - * The preferred view-mode to display - */ - @Input() viewMode: string; - - /** - * The object injector used to inject the item into the child component - */ - objectInjector: Injector; - - component: any; - - constructor(private injector: Injector) { - } - - ngOnInit(): void { - this.objectInjector = Injector.create({ - providers: [{ provide: ITEM, useFactory: () => this.object, deps:[] }], - parent: this.injector - }); - this.component = this.getComponent(); - } - - /** - * Fetch the component depending on the item's relationship type - * @returns {string} - */ - private getComponent(): string { - if (hasValue((this.object as any).representationType)) { - const metadataRepresentation = this.object as MetadataRepresentation; - return getComponentByItemType(metadataRepresentation.itemType, this.viewMode, metadataRepresentation.representationType); - } - - let item: Item; - if (hasValue((this.object as any).indexableObject)) { - const searchResult = this.object as ItemSearchResult; - item = searchResult.indexableObject; - } else { - item = this.object as Item; - } - - const type = item.firstMetadataValue('relationship.type'); - return getComponentByItemType(type, this.viewMode); - } -} diff --git a/src/app/shared/metadata-representation/metadata-representation-loader.component.html b/src/app/shared/metadata-representation/metadata-representation-loader.component.html new file mode 100644 index 0000000000..3979c238ad --- /dev/null +++ b/src/app/shared/metadata-representation/metadata-representation-loader.component.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/app/shared/metadata-representation/metadata-representation-loader.component.spec.ts b/src/app/shared/metadata-representation/metadata-representation-loader.component.spec.ts new file mode 100644 index 0000000000..4097fb99c4 --- /dev/null +++ b/src/app/shared/metadata-representation/metadata-representation-loader.component.spec.ts @@ -0,0 +1,63 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { ChangeDetectionStrategy, ComponentFactoryResolver, NO_ERRORS_SCHEMA } from '@angular/core'; +import { Context } from '../../core/shared/context.model'; +import { MetadataRepresentation, MetadataRepresentationType } from '../../core/shared/metadata-representation/metadata-representation.model'; +import { MetadataRepresentationLoaderComponent } from './metadata-representation-loader.component'; +import { PlainTextMetadataListElementComponent } from '../object-list/metadata-representation-list-element/plain-text/plain-text-metadata-list-element.component'; +import { spyOnExported } from '../testing/utils'; +import { MetadataRepresentationDirective } from './metadata-representation.directive'; +import * as metadataRepresentationDecorator from './metadata-representation.decorator'; + +const testType = 'TestType'; +const testContext = Context.Search; +const testRepresentationType = MetadataRepresentationType.Item; + +class TestType implements MetadataRepresentation { + get itemType(): string { + return testType; + } + + get representationType(): MetadataRepresentationType { + return testRepresentationType; + } + + getValue(): string { + return ''; + } +} +describe('MetadataRepresentationLoaderComponent', () => { + let comp: MetadataRepresentationLoaderComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + imports: [], + declarations: [MetadataRepresentationLoaderComponent, PlainTextMetadataListElementComponent, MetadataRepresentationDirective], + schemas: [NO_ERRORS_SCHEMA], + providers: [ComponentFactoryResolver] + }).overrideComponent(MetadataRepresentationLoaderComponent, { + set: { + changeDetection: ChangeDetectionStrategy.Default, + entryComponents: [PlainTextMetadataListElementComponent] + } + }).compileComponents(); + })); + + beforeEach(async(() => { + fixture = TestBed.createComponent(MetadataRepresentationLoaderComponent); + comp = fixture.componentInstance; + + comp.mdRepresentation = new TestType(); + comp.context = testContext; + + spyOnExported(metadataRepresentationDecorator, 'getMetadataRepresentationComponent').and.returnValue(PlainTextMetadataListElementComponent); + fixture.detectChanges(); + + })); + + describe('When the component is rendered', () => { + it('should call the getMetadataRepresentationComponent function with the right entity type, representation type and context', () => { + expect(metadataRepresentationDecorator.getMetadataRepresentationComponent).toHaveBeenCalledWith(testType, testRepresentationType, testContext); + }) + }); +}); diff --git a/src/app/shared/metadata-representation/metadata-representation-loader.component.ts b/src/app/shared/metadata-representation/metadata-representation-loader.component.ts new file mode 100644 index 0000000000..eb385b5afd --- /dev/null +++ b/src/app/shared/metadata-representation/metadata-representation-loader.component.ts @@ -0,0 +1,56 @@ +import { Component, ComponentFactoryResolver, InjectionToken, Injector, Input, OnInit, ViewChild } from '@angular/core'; +import { MetadataRepresentation } from '../../core/shared/metadata-representation/metadata-representation.model'; +import { getMetadataRepresentationComponent } from './metadata-representation.decorator'; +import { Context } from '../../core/shared/context.model'; +import { GenericConstructor } from '../../core/shared/generic-constructor'; +import { MetadataRepresentationListElementComponent } from '../object-list/metadata-representation-list-element/metadata-representation-list-element.component'; +import { MetadataRepresentationDirective } from './metadata-representation.directive'; + +@Component({ + selector: 'ds-metadata-representation-loader', + // styleUrls: ['./metadata-representation-loader.component.scss'], + templateUrl: './metadata-representation-loader.component.html' +}) +/** + * Component for determining what component to use depending on the item's relationship type (relationship.type), its metadata representation and, optionally, its context + */ +export class MetadataRepresentationLoaderComponent implements OnInit { + /** + * The item or metadata to determine the component for + */ + @Input() mdRepresentation: MetadataRepresentation; + + /** + * The optional context + */ + @Input() context: Context; + + /** + * Directive to determine where the dynamic child component is located + */ + @ViewChild(MetadataRepresentationDirective) mdRepDirective: MetadataRepresentationDirective; + + constructor(private componentFactoryResolver: ComponentFactoryResolver) { + } + + /** + * Set up the dynamic child component + */ + ngOnInit(): void { + const componentFactory = this.componentFactoryResolver.resolveComponentFactory(this.getComponent()); + + const viewContainerRef = this.mdRepDirective.viewContainerRef; + viewContainerRef.clear(); + + const componentRef = viewContainerRef.createComponent(componentFactory); + (componentRef.instance as MetadataRepresentationListElementComponent).metadataRepresentation = this.mdRepresentation; + } + + /** + * Fetch the component depending on the item's relationship type, metadata representation type and context + * @returns {string} + */ + private getComponent(): GenericConstructor { + return getMetadataRepresentationComponent(this.mdRepresentation.itemType, this.mdRepresentation.representationType, this.context); + } +} diff --git a/src/app/shared/metadata-representation/metadata-representation.decorator.spec.ts b/src/app/shared/metadata-representation/metadata-representation.decorator.spec.ts new file mode 100644 index 0000000000..0ca7ebb9b9 --- /dev/null +++ b/src/app/shared/metadata-representation/metadata-representation.decorator.spec.ts @@ -0,0 +1,63 @@ +import { DEFAULT_ENTITY_TYPE, DEFAULT_REPRESENTATION_TYPE, getMetadataRepresentationComponent, metadataRepresentationComponent } from './metadata-representation.decorator'; +import { MetadataRepresentationType } from '../../core/shared/metadata-representation/metadata-representation.model'; +import { Context } from '../../core/shared/context.model'; +import * as uuidv4 from 'uuid/v4'; + +describe('MetadataRepresentation decorator function', () => { + const type1 = 'TestType'; + const type2 = 'TestType2'; + const type3 = 'TestType3'; + const type4 = 'RandomType'; + let prefix; + /* tslint:disable:max-classes-per-file */ + class Test1PlainText {}; + class Test1Authority {}; + class Test2Item {}; + class Test2ItemSubmission {}; + class Test3ItemSubmission {}; + /* tslint:enable:max-classes-per-file */ + + beforeEach(() => { + prefix = uuidv4(); + init(prefix); + }); + + function init(key) { + metadataRepresentationComponent(key + type1, MetadataRepresentationType.PlainText)(Test1PlainText); + metadataRepresentationComponent(key + type1, MetadataRepresentationType.AuthorityControlled)(Test1Authority); + + metadataRepresentationComponent(key + type2, MetadataRepresentationType.Item)(Test2Item); + metadataRepresentationComponent(key + type2, MetadataRepresentationType.Item, Context.Workspace)(Test2ItemSubmission); + + metadataRepresentationComponent(key + type3, MetadataRepresentationType.Item, Context.Workspace)(Test3ItemSubmission); + } + + describe('If there\'s an exact match', () => { + it('should return the matching class', () => { + const component = getMetadataRepresentationComponent(prefix + type3, MetadataRepresentationType.Item, Context.Workspace); + expect(component).toEqual(Test3ItemSubmission); + }); + }); + + describe('If there isn\'nt an exact match', () => { + describe('If there is a match for the entity type and representation type', () => { + it('should return the class with the matching entity type and representation type and default context', () => { + const component = getMetadataRepresentationComponent(prefix + type1, MetadataRepresentationType.AuthorityControlled, Context.Workspace); + expect(component).toEqual(Test1Authority); + }); + }); + describe('If there isn\'t a match for the representation type', () => { + it('should return the class with the matching entity type and the default representation type and default context', () => { + const component = getMetadataRepresentationComponent(prefix + type1, MetadataRepresentationType.Item); + expect(component).toEqual(Test1PlainText); + }); + describe('If there isn\'t a match for the entity type', () => { + it('should return the class with the default entity type and the default representation type and default context', () => { + const defaultComponent = getMetadataRepresentationComponent(DEFAULT_ENTITY_TYPE, DEFAULT_REPRESENTATION_TYPE); + const component = getMetadataRepresentationComponent(prefix + type4, MetadataRepresentationType.AuthorityControlled); + expect(component).toEqual(defaultComponent); + }); + }); + }); + }); +}); diff --git a/src/app/shared/metadata-representation/metadata-representation.decorator.ts b/src/app/shared/metadata-representation/metadata-representation.decorator.ts new file mode 100644 index 0000000000..a5ea26aa89 --- /dev/null +++ b/src/app/shared/metadata-representation/metadata-representation.decorator.ts @@ -0,0 +1,56 @@ +import { MetadataRepresentationType } from '../../core/shared/metadata-representation/metadata-representation.model'; +import { hasNoValue, hasValue } from '../empty.util'; +import { Context } from '../../core/shared/context.model'; + +export const map = new Map(); + +export const DEFAULT_ENTITY_TYPE = 'Publication'; +export const DEFAULT_REPRESENTATION_TYPE = MetadataRepresentationType.PlainText; +export const DEFAULT_CONTEXT = Context.Undefined; + +/** + * Decorator function to store metadata representation mapping + * @param entityType The entity type the component represents + * @param mdRepresentationType The metadata representation type the component represents + * @param context The optional context the component represents + */ +export function metadataRepresentationComponent(entityType: string, mdRepresentationType: MetadataRepresentationType, context: Context = DEFAULT_CONTEXT) { + return function decorator(component: any) { + if (hasNoValue(map.get(entityType))) { + map.set(entityType, new Map()); + } + if (hasNoValue(map.get(entityType).get(mdRepresentationType))) { + map.get(entityType).set(mdRepresentationType, new Map()); + } + + if (hasValue(map.get(entityType).get(mdRepresentationType).get(context))) { + throw new Error(`There can't be more than one component to render Entity of type "${entityType}" in MetadataRepresentation "${mdRepresentationType}" with context "${context}"`); + } + map.get(entityType).get(mdRepresentationType).set(context, component); + } +} + +/** + * Getter to retrieve a matching component by entity type, metadata representation and context + * @param entityType The entity type to match + * @param mdRepresentationType The metadata representation to match + * @param context The context to match + */ +export function getMetadataRepresentationComponent(entityType: string, mdRepresentationType: MetadataRepresentationType, context: Context = DEFAULT_CONTEXT) { + const mapForEntity = map.get(entityType); + if (hasValue(mapForEntity)) { + const entityAndMDRepMap = mapForEntity.get(mdRepresentationType); + if (hasValue(entityAndMDRepMap)) { + if (hasValue(entityAndMDRepMap.get(context))) { + return entityAndMDRepMap.get(context); + } + if (hasValue(entityAndMDRepMap.get(DEFAULT_CONTEXT))) { + return entityAndMDRepMap.get(DEFAULT_CONTEXT); + } + } + if (hasValue(mapForEntity.get(DEFAULT_REPRESENTATION_TYPE))) { + return mapForEntity.get(DEFAULT_REPRESENTATION_TYPE).get(DEFAULT_CONTEXT); + } + } + return map.get(DEFAULT_ENTITY_TYPE).get(DEFAULT_REPRESENTATION_TYPE).get(DEFAULT_CONTEXT); +} diff --git a/src/app/shared/metadata-representation/metadata-representation.directive.ts b/src/app/shared/metadata-representation/metadata-representation.directive.ts new file mode 100644 index 0000000000..9ff0573baf --- /dev/null +++ b/src/app/shared/metadata-representation/metadata-representation.directive.ts @@ -0,0 +1,11 @@ +import { Directive, ViewContainerRef } from '@angular/core'; + +@Directive({ + selector: '[dsMetadataRepresentation]', +}) +/** + * Directive used as a hook to know where to inject the dynamic metadata representation component + */ +export class MetadataRepresentationDirective { + constructor(public viewContainerRef: ViewContainerRef) { } +} diff --git a/src/app/shared/mydspace-actions/claimed-task/claimed-task-actions.component.ts b/src/app/shared/mydspace-actions/claimed-task/claimed-task-actions.component.ts index 0ddb24ec2f..554becdb27 100644 --- a/src/app/shared/mydspace-actions/claimed-task/claimed-task-actions.component.ts +++ b/src/app/shared/mydspace-actions/claimed-task/claimed-task-actions.component.ts @@ -15,7 +15,7 @@ import { MyDSpaceActionsComponent } from '../mydspace-actions'; import { NotificationsService } from '../../notifications/notifications.service'; /** - * This component represents mydspace actions related to ClaimedTask object. + * This component represents actions related to ClaimedTask object. */ @Component({ selector: 'ds-claimed-task-actions', diff --git a/src/app/shared/mydspace-actions/workflowitem/workflowitem-actions.component.ts b/src/app/shared/mydspace-actions/workflowitem/workflowitem-actions.component.ts index 71f854c5e7..453d875150 100644 --- a/src/app/shared/mydspace-actions/workflowitem/workflowitem-actions.component.ts +++ b/src/app/shared/mydspace-actions/workflowitem/workflowitem-actions.component.ts @@ -9,7 +9,7 @@ import { WorkflowItemDataService } from '../../../core/submission/workflowitem-d import { NotificationsService } from '../../notifications/notifications.service'; /** - * This component represents mydspace actions related to WorkflowItem object. + * This component represents actions related to WorkflowItem object. */ @Component({ selector: 'ds-workflowitem-actions', diff --git a/src/app/shared/mydspace-actions/workspaceitem/workspaceitem-actions.component.ts b/src/app/shared/mydspace-actions/workspaceitem/workspaceitem-actions.component.ts index 69214e800e..ca0b416b60 100644 --- a/src/app/shared/mydspace-actions/workspaceitem/workspaceitem-actions.component.ts +++ b/src/app/shared/mydspace-actions/workspaceitem/workspaceitem-actions.component.ts @@ -8,11 +8,10 @@ import { TranslateService } from '@ngx-translate/core'; import { WorkspaceItem } from '../../../core/submission/models/workspaceitem.model'; import { MyDSpaceActionsComponent } from '../mydspace-actions'; import { WorkspaceitemDataService } from '../../../core/submission/workspaceitem-data.service'; -import { ResourceType } from '../../../core/shared/resource-type'; import { NotificationsService } from '../../notifications/notifications.service'; /** - * This component represents mydspace actions related to WorkspaceItem object. + * This component represents actions related to WorkspaceItem object. */ @Component({ selector: 'ds-workspaceitem-actions', diff --git a/src/app/shared/object-collection/collection-element-link.type.ts b/src/app/shared/object-collection/collection-element-link.type.ts new file mode 100644 index 0000000000..78b690b5ab --- /dev/null +++ b/src/app/shared/object-collection/collection-element-link.type.ts @@ -0,0 +1,9 @@ +/** + * Enumeration used to render links in listable elements + * None: Don't render the link as a link, but as plain text + * Link: Render the link as a simple link + * ExternalLink: Render the link as a link that opens in a new tab + */ +export enum CollectionElementLinkType { + None, Link, ExternalLink +} diff --git a/src/app/shared/object-collection/object-collection.component.html b/src/app/shared/object-collection/object-collection.component.html index a0878efa24..199f6d0bcf 100644 --- a/src/app/shared/object-collection/object-collection.component.html +++ b/src/app/shared/object-collection/object-collection.component.html @@ -3,31 +3,37 @@ [objects]="objects" [hasBorder]="hasBorder" [hideGear]="hideGear" + [linkType]="linkType" + [context]="context" (paginationChange)="onPaginationChange($event)" (pageChange)="onPageChange($event)" (pageSizeChange)="onPageSizeChange($event)" (sortDirectionChange)="onSortDirectionChange($event)" (sortFieldChange)="onSortFieldChange($event)" - *ngIf="(currentMode$ | async) === viewModeEnum.List"> + *ngIf="(currentMode$ | async) === viewModeEnum.ListElement"> + *ngIf="(currentMode$ | async) === viewModeEnum.GridElement"> + [linkType]="linkType" + [context]="context" + *ngIf="(currentMode$ | async) === viewModeEnum.DetailedListElement"> diff --git a/src/app/shared/object-collection/object-collection.component.spec.ts b/src/app/shared/object-collection/object-collection.component.spec.ts index 3b30666757..ceea03c367 100644 --- a/src/app/shared/object-collection/object-collection.component.spec.ts +++ b/src/app/shared/object-collection/object-collection.component.spec.ts @@ -1,11 +1,11 @@ import { ObjectCollectionComponent } from './object-collection.component'; -import { SetViewMode } from '../view-mode'; import { By } from '@angular/platform-browser'; import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { NO_ERRORS_SCHEMA } from '@angular/core'; import { ActivatedRoute, Router } from '@angular/router'; import { of as observableOf } from 'rxjs'; import { RouterStub } from '../testing/router-stub'; +import { ViewMode } from '../../core/shared/view-mode.model'; describe('ObjectCollectionComponent', () => { let fixture: ComponentFixture; @@ -36,14 +36,14 @@ describe('ObjectCollectionComponent', () => { })); it('should only show the grid component when the viewmode is set to grid', () => { - objectCollectionComponent.currentMode$ = observableOf(SetViewMode.Grid); + objectCollectionComponent.currentMode$ = observableOf(ViewMode.GridElement); expect(fixture.debugElement.query(By.css('ds-object-grid'))).toBeDefined(); expect(fixture.debugElement.query(By.css('ds-object-list'))).toBeNull(); }); it('should only show the list component when the viewmode is set to list', () => { - objectCollectionComponent.currentMode$ = observableOf(SetViewMode.List); + objectCollectionComponent.currentMode$ = observableOf(ViewMode.ListElement); expect(fixture.debugElement.query(By.css('ds-object-list'))).toBeDefined(); expect(fixture.debugElement.query(By.css('ds-object-grid'))).toBeNull(); diff --git a/src/app/shared/object-collection/object-collection.component.ts b/src/app/shared/object-collection/object-collection.component.ts index 526fc95781..955c21a26a 100644 --- a/src/app/shared/object-collection/object-collection.component.ts +++ b/src/app/shared/object-collection/object-collection.component.ts @@ -1,13 +1,4 @@ -import { - ChangeDetectorRef, - Component, - EventEmitter, - Input, - OnChanges, - OnInit, - Output, - SimpleChanges -} from '@angular/core'; +import { ChangeDetectorRef, Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; import { ActivatedRoute, Router } from '@angular/router'; import { Observable } from 'rxjs'; @@ -18,22 +9,61 @@ import { PageInfo } from '../../core/shared/page-info.model'; import { PaginationComponentOptions } from '../pagination/pagination-component-options.model'; import { SortDirection, SortOptions } from '../../core/cache/models/sort-options.model'; import { ListableObject } from './shared/listable-object.model'; -import { SetViewMode } from '../view-mode'; -import { hasValue, isEmpty, isNotEmpty } from '../empty.util'; +import { isNotEmpty } from '../empty.util'; +import { ViewMode } from '../../core/shared/view-mode.model'; +import { CollectionElementLinkType } from './collection-element-link.type'; +import { PaginatedList } from '../../core/data/paginated-list'; +import { Context } from '../../core/shared/context.model'; +/** + * Component that can render a list of listable objects in different view modes + */ @Component({ selector: 'ds-viewable-collection', styleUrls: ['./object-collection.component.scss'], templateUrl: './object-collection.component.html', }) export class ObjectCollectionComponent implements OnInit { + /** + * The list of listable objects to render in this component + */ + @Input() objects: RemoteData>; - @Input() objects: RemoteData; + /** + * The current pagination configuration + */ @Input() config?: PaginationComponentOptions; + + /** + * The current sorting configuration + */ @Input() sortConfig: SortOptions; + + /** + * Whether or not the list elements have a border or not + */ @Input() hasBorder = false; + + /** + * Whether or not to hide the gear to change the sort and pagination configuration + */ @Input() hideGear = false; + + /** + * The link type of the rendered list elements + */ + @Input() linkType: CollectionElementLinkType; + + /** + * The context of the rendered list elements + */ + @Input() context: Context; + + /** + * the page info of the list + */ pageInfo: Observable; + /** * An event fired when the page is changed. * Event's payload equals to the newly selected page. @@ -52,6 +82,9 @@ export class ObjectCollectionComponent implements OnInit { */ @Output() sortDirectionChange: EventEmitter = new EventEmitter(); + /** + * An event fired one of the pagination parameters is changed + */ @Output() paginationChange: EventEmitter = new EventEmitter(); /** @@ -59,9 +92,16 @@ export class ObjectCollectionComponent implements OnInit { * Event's payload equals to the newly selected sort field. */ @Output() sortFieldChange: EventEmitter = new EventEmitter(); - data: any = {}; - currentMode$: Observable; - viewModeEnum = SetViewMode; + + /** + * Emits the current view mode + */ + currentMode$: Observable; + + /** + * The available view modes + */ + viewModeEnum = ViewMode; ngOnInit(): void { this.currentMode$ = this.route @@ -69,7 +109,7 @@ export class ObjectCollectionComponent implements OnInit { .pipe( filter((params) => isNotEmpty(params.view)), map((params) => params.view), - startWith(SetViewMode.List) + startWith(ViewMode.ListElement) ); } @@ -87,22 +127,39 @@ export class ObjectCollectionComponent implements OnInit { private router: Router) { } + /** + * Updates the page + * @param event The new page number + */ onPageChange(event) { this.pageChange.emit(event); } - + /** + * Updates the page size + * @param event The new page size + */ onPageSizeChange(event) { this.pageSizeChange.emit(event); } - + /** + * Updates the sort direction + * @param event The new sort direction + */ onSortDirectionChange(event) { this.sortDirectionChange.emit(event); } - + /** + * Updates the sort field + * @param event The new sort field + */ onSortFieldChange(event) { this.sortFieldChange.emit(event); } + /** + * Updates the pagination + * @param event The new pagination + */ onPaginationChange(event) { this.paginationChange.emit(event); } diff --git a/src/app/shared/object-collection/shared/claimed-task-my-dspace-result.model.ts b/src/app/shared/object-collection/shared/claimed-task-search-result.model.ts similarity index 56% rename from src/app/shared/object-collection/shared/claimed-task-my-dspace-result.model.ts rename to src/app/shared/object-collection/shared/claimed-task-search-result.model.ts index 051bfe6d9f..4a7bf97850 100644 --- a/src/app/shared/object-collection/shared/claimed-task-my-dspace-result.model.ts +++ b/src/app/shared/object-collection/shared/claimed-task-search-result.model.ts @@ -1,11 +1,10 @@ import { ClaimedTask } from '../../../core/tasks/models/claimed-task-object.model'; import { SearchResult } from '../../../+search-page/search-result.model'; -import { MyDSpaceConfigurationValueType } from '../../../+my-dspace-page/my-dspace-configuration-value-type'; import { searchResultFor } from '../../../+search-page/search-service/search-result-element-decorator'; /** * Represents a search result object of a ClaimedTask object */ -@searchResultFor(ClaimedTask, MyDSpaceConfigurationValueType.Workflow) -export class ClaimedTaskMyDSpaceResult extends SearchResult { +@searchResultFor(ClaimedTask) +export class ClaimedTaskSearchResult extends SearchResult { } diff --git a/src/app/shared/object-collection/shared/dso-element-decorator.spec.ts b/src/app/shared/object-collection/shared/dso-element-decorator.spec.ts deleted file mode 100644 index 12da0f5b36..0000000000 --- a/src/app/shared/object-collection/shared/dso-element-decorator.spec.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { SetViewMode } from '../../view-mode'; -import { renderElementsFor } from './dso-element-decorator'; -import { Item } from '../../../core/shared/item.model'; - -describe('ElementDecorator', () => { - const gridDecorator = renderElementsFor(Item, SetViewMode.Grid); - const listDecorator = renderElementsFor(Item, SetViewMode.List); - it('should have a decorator for both list and grid', () => { - expect(listDecorator.length).not.toBeNull(); - expect(gridDecorator.length).not.toBeNull(); - }); - it('should have 2 separate decorators for grid and list', () => { - expect(listDecorator).not.toEqual(gridDecorator); - }); - -}); diff --git a/src/app/shared/object-collection/shared/dso-element-decorator.ts b/src/app/shared/object-collection/shared/dso-element-decorator.ts deleted file mode 100644 index 4e4d37579a..0000000000 --- a/src/app/shared/object-collection/shared/dso-element-decorator.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { GenericConstructor } from '../../../core/shared/generic-constructor'; -import { ListableObject } from './listable-object.model'; -import { SetViewMode } from '../../view-mode'; - -const dsoElementMap = new Map(); -export function renderElementsFor(listable: GenericConstructor, viewMode: SetViewMode) { - return function decorator(objectElement: any) { - if (!objectElement) { - return; - } - if (!dsoElementMap.get(viewMode)) { - dsoElementMap.set(viewMode, new Map()); - } - dsoElementMap.get(viewMode).set(listable, objectElement); - }; -} - -export function rendersDSOType(listable: GenericConstructor, viewMode: SetViewMode) { - return dsoElementMap.get(viewMode).get(listable); -} diff --git a/src/app/shared/object-collection/shared/item-my-dspace-result.model.ts b/src/app/shared/object-collection/shared/item-my-dspace-result.model.ts deleted file mode 100644 index 92724a762f..0000000000 --- a/src/app/shared/object-collection/shared/item-my-dspace-result.model.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { Item } from '../../../core/shared/item.model'; -import { SearchResult } from '../../../+search-page/search-result.model'; -import { searchResultFor } from '../../../+search-page/search-service/search-result-element-decorator'; -import { MyDSpaceConfigurationValueType } from '../../../+my-dspace-page/my-dspace-configuration-value-type'; - -/** - * Represents a search result object of a Item object - */ -@searchResultFor(Item, MyDSpaceConfigurationValueType.Workspace) -export class ItemMyDSpaceResult extends SearchResult { -} diff --git a/src/app/shared/object-collection/shared/item-search-result.model.ts b/src/app/shared/object-collection/shared/item-search-result.model.ts index f20b3db1e3..d38968ce76 100644 --- a/src/app/shared/object-collection/shared/item-search-result.model.ts +++ b/src/app/shared/object-collection/shared/item-search-result.model.ts @@ -1,7 +1,22 @@ import { SearchResult } from '../../../+search-page/search-result.model'; import { Item } from '../../../core/shared/item.model'; import { searchResultFor } from '../../../+search-page/search-service/search-result-element-decorator'; +import { GenericConstructor } from '../../../core/shared/generic-constructor'; +import { ListableObject } from './listable-object.model'; @searchResultFor(Item) export class ItemSearchResult extends SearchResult { + + /** + * Method that returns as which type of object this object should be rendered + */ + getRenderTypes(): Array> { + return this.indexableObject.getRenderTypes().map((type) => { + if (typeof type === 'string') { + return type + 'SearchResult' + } else { + return this.constructor as GenericConstructor; + } + }); + } } diff --git a/src/app/shared/object-collection/shared/listable-object.model.ts b/src/app/shared/object-collection/shared/listable-object.model.ts index 07c626cda2..d7eaf0750f 100644 --- a/src/app/shared/object-collection/shared/listable-object.model.ts +++ b/src/app/shared/object-collection/shared/listable-object.model.ts @@ -1 +1,10 @@ -export interface ListableObject {} +import { TypedObject } from '../../../core/cache/object-cache.reducer'; +import { GenericConstructor } from '../../../core/shared/generic-constructor'; + +export interface ListableObject extends TypedObject { + + /** + * Method that returns as which type of object this object should be rendered + */ + getRenderTypes(): Array>; +} diff --git a/src/app/shared/object-collection/shared/listable-object/listable-object-component-loader.component.html b/src/app/shared/object-collection/shared/listable-object/listable-object-component-loader.component.html new file mode 100644 index 0000000000..ef9a817424 --- /dev/null +++ b/src/app/shared/object-collection/shared/listable-object/listable-object-component-loader.component.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/app/shared/object-collection/shared/listable-object/listable-object-component-loader.component.spec.ts b/src/app/shared/object-collection/shared/listable-object/listable-object-component-loader.component.spec.ts new file mode 100644 index 0000000000..f470f566f0 --- /dev/null +++ b/src/app/shared/object-collection/shared/listable-object/listable-object-component-loader.component.spec.ts @@ -0,0 +1,58 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { ChangeDetectionStrategy, ComponentFactoryResolver, NO_ERRORS_SCHEMA } from '@angular/core'; +import { ListableObjectComponentLoaderComponent } from './listable-object-component-loader.component'; +import { ListableObject } from '../listable-object.model'; +import { GenericConstructor } from '../../../../core/shared/generic-constructor'; +import { Context } from '../../../../core/shared/context.model'; +import { ViewMode } from '../../../../core/shared/view-mode.model'; +import * as listableObjectDecorators from './listable-object.decorator'; +import { PublicationListElementComponent } from '../../../object-list/item-list-element/item-types/publication/publication-list-element.component'; +import { ListableObjectDirective } from './listable-object.directive'; +import { spyOnExported } from '../../../testing/utils'; + +const testType = 'TestType'; +const testContext = Context.Search; +const testViewMode = ViewMode.StandalonePage; + +class TestType implements ListableObject { + getRenderTypes(): Array> { + return [testType]; + } +} + +describe('ListableObjectComponentLoaderComponent', () => { + let comp: ListableObjectComponentLoaderComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + imports: [], + declarations: [ListableObjectComponentLoaderComponent, PublicationListElementComponent, ListableObjectDirective], + schemas: [NO_ERRORS_SCHEMA], + providers: [ComponentFactoryResolver] + }).overrideComponent(ListableObjectComponentLoaderComponent, { + set: { + changeDetection: ChangeDetectionStrategy.Default, + entryComponents: [PublicationListElementComponent] + } + }).compileComponents(); + })); + + beforeEach(async(() => { + fixture = TestBed.createComponent(ListableObjectComponentLoaderComponent); + comp = fixture.componentInstance; + + comp.object = new TestType(); + comp.viewMode = testViewMode; + comp.context = testContext; + spyOnExported(listableObjectDecorators, 'getListableObjectComponent').and.returnValue(PublicationListElementComponent); + fixture.detectChanges(); + + })); + + describe('When the component is rendered', () => { + it('should call the getListableObjectComponent function with the right types, view mode and context', () => { + expect(listableObjectDecorators.getListableObjectComponent).toHaveBeenCalledWith([testType], testViewMode, testContext); + }) + }); +}); diff --git a/src/app/shared/object-collection/shared/listable-object/listable-object-component-loader.component.ts b/src/app/shared/object-collection/shared/listable-object/listable-object-component-loader.component.ts new file mode 100644 index 0000000000..648298b0fe --- /dev/null +++ b/src/app/shared/object-collection/shared/listable-object/listable-object-component-loader.component.ts @@ -0,0 +1,74 @@ +import { Component, ComponentFactoryResolver, Input, OnInit, ViewChild } from '@angular/core'; +import { ListableObject } from '../listable-object.model'; +import { ViewMode } from '../../../../core/shared/view-mode.model'; +import { Context } from '../../../../core/shared/context.model'; +import { getListableObjectComponent } from './listable-object.decorator'; +import { GenericConstructor } from '../../../../core/shared/generic-constructor'; +import { ListableObjectDirective } from './listable-object.directive'; +import { CollectionElementLinkType } from '../../collection-element-link.type'; + +@Component({ + selector: 'ds-listable-object-component-loader', + // styleUrls: ['./listable-object-component-loader.component.scss'], + templateUrl: './listable-object-component-loader.component.html' +}) +/** + * Component for determining what component to use depending on the item's relationship type (relationship.type) + */ +export class ListableObjectComponentLoaderComponent implements OnInit { + /** + * The item or metadata to determine the component for + */ + @Input() object: ListableObject; + + /** + * The index of the object in the list + */ + @Input() index: number; + + /** + * The preferred view-mode to display + */ + @Input() viewMode: ViewMode; + + /** + * The context of listable object + */ + @Input() context: Context; + + /** + * The type of link used to render the links inside the listable object + */ + @Input() linkType: CollectionElementLinkType; + + /** + * Directive hook used to place the dynamic child component + */ + @ViewChild(ListableObjectDirective) listableObjectDirective: ListableObjectDirective; + + constructor(private componentFactoryResolver: ComponentFactoryResolver) { + } + + /** + * Setup the dynamic child component + */ + ngOnInit(): void { + const componentFactory = this.componentFactoryResolver.resolveComponentFactory(this.getComponent()); + + const viewContainerRef = this.listableObjectDirective.viewContainerRef; + viewContainerRef.clear(); + + const componentRef = viewContainerRef.createComponent(componentFactory); + (componentRef.instance as any).object = this.object; + (componentRef.instance as any).index = this.index; + (componentRef.instance as any).linkType = this.linkType; + } + + /** + * Fetch the component depending on the item's relationship type, view mode and context + * @returns {GenericConstructor} + */ + private getComponent(): GenericConstructor { + return getListableObjectComponent(this.object.getRenderTypes(), this.viewMode, this.context) + } +} diff --git a/src/app/shared/object-collection/shared/listable-object/listable-object.decorator.spec.ts b/src/app/shared/object-collection/shared/listable-object/listable-object.decorator.spec.ts new file mode 100644 index 0000000000..0143984bd6 --- /dev/null +++ b/src/app/shared/object-collection/shared/listable-object/listable-object.decorator.spec.ts @@ -0,0 +1,71 @@ +import { Item } from '../../../../core/shared/item.model'; +import { ViewMode } from '../../../../core/shared/view-mode.model'; +import { getListableObjectComponent, listableObjectComponent } from './listable-object.decorator'; +import { Context } from '../../../../core/shared/context.model'; + +describe('ListableObject decorator function', () => { + const type1 = 'TestType'; + const type2 = 'TestType2'; + const type3 = 'TestType3'; + + /* tslint:disable:max-classes-per-file */ + class Test1List {}; + class Test1Grid {}; + class Test2List {}; + class Test2ListSubmission {}; + class Test3List {}; + class Test3DetailedSubmission {}; + /* tslint:enable:max-classes-per-file */ + + beforeEach(() => { + listableObjectComponent(type1, ViewMode.ListElement)(Test1List); + listableObjectComponent(type1, ViewMode.GridElement)(Test1Grid); + + listableObjectComponent(type2, ViewMode.ListElement)(Test2List); + listableObjectComponent(type2, ViewMode.ListElement, Context.Workspace)(Test2ListSubmission); + + listableObjectComponent(type3, ViewMode.ListElement)(Test3List); + listableObjectComponent(type3, ViewMode.DetailedListElement, Context.Workspace)(Test3DetailedSubmission); + }); + + const gridDecorator = listableObjectComponent('Item', ViewMode.GridElement); + const listDecorator = listableObjectComponent('Item', ViewMode.ListElement); + it('should have a decorator for both list and grid', () => { + expect(listDecorator.length).not.toBeNull(); + expect(gridDecorator.length).not.toBeNull(); + }); + it('should have 2 separate decorators for grid and list', () => { + expect(listDecorator).not.toEqual(gridDecorator); + }); + + describe('If there\'s an exact match', () => { + it('should return the matching class', () => { + const component = getListableObjectComponent([type3], ViewMode.DetailedListElement, Context.Workspace); + expect(component).toEqual(Test3DetailedSubmission); + + const component2 = getListableObjectComponent([type3, type2], ViewMode.ListElement, Context.Workspace); + expect(component2).toEqual(Test2ListSubmission); + }); + }); + + describe('If there isn\'nt an exact match', () => { + describe('If there is a match for one of the entity types and the view mode', () => { + it('should return the class with the matching entity type and view mode and default context', () => { + const component = getListableObjectComponent([type3], ViewMode.ListElement, Context.Workspace); + expect(component).toEqual(Test3List); + + const component2 = getListableObjectComponent([type3, type1], ViewMode.GridElement, Context.Workspace); + expect(component2).toEqual(Test1Grid); + }); + }); + describe('If there isn\'t a match for the representation type', () => { + it('should return the class with the matching entity type and the default view mode and default context', () => { + const component = getListableObjectComponent([type1], ViewMode.DetailedListElement); + expect(component).toEqual(Test1List); + + const component2 = getListableObjectComponent([type2, type1], ViewMode.DetailedListElement); + expect(component2).toEqual(Test2List); + }); + }); + }); +}); diff --git a/src/app/shared/object-collection/shared/listable-object/listable-object.decorator.ts b/src/app/shared/object-collection/shared/listable-object/listable-object.decorator.ts new file mode 100644 index 0000000000..66110516bb --- /dev/null +++ b/src/app/shared/object-collection/shared/listable-object/listable-object.decorator.ts @@ -0,0 +1,62 @@ +import { ViewMode } from '../../../../core/shared/view-mode.model'; +import { Context } from '../../../../core/shared/context.model'; +import { hasNoValue, hasValue } from '../../../empty.util'; +import { DEFAULT_CONTEXT } from '../../../metadata-representation/metadata-representation.decorator'; +import { GenericConstructor } from '../../../../core/shared/generic-constructor'; +import { ListableObject } from '../listable-object.model'; + +export const DEFAULT_VIEW_MODE = ViewMode.ListElement; + +const map = new Map(); + +/** + * Decorator used for rendering a listable object + * @param type The object type or entity type the component represents + * @param viewMode The view mode the component represents + * @param context The optional context the component represents + */ +export function listableObjectComponent(objectType: string | GenericConstructor, viewMode: ViewMode, context: Context = DEFAULT_CONTEXT) { + return function decorator(component: any) { + if (hasNoValue(objectType)) { + return; + } + if (hasNoValue(map.get(objectType))) { + map.set(objectType, new Map()); + } + if (hasNoValue(map.get(objectType).get(viewMode))) { + map.get(objectType).set(viewMode, new Map()); + } + map.get(objectType).get(viewMode).set(context, component); + }; +} + +/** + * Getter to retrieve the matching listable object component + * @param types The types of which one should match the listable component + * @param viewMode The view mode that should match the components + * @param context The context that should match the components + */ +export function getListableObjectComponent(types: Array>, viewMode: ViewMode, context: Context = DEFAULT_CONTEXT) { + let bestMatch; + let bestMatchValue = 0; + for (const type of types) { + const typeMap = map.get(type); + if (hasValue(typeMap)) { + const typeModeMap = typeMap.get(viewMode); + if (hasValue(typeModeMap)) { + if (hasValue(typeModeMap.get(context))) { + return typeModeMap.get(context); + } + if (bestMatchValue < 2 && hasValue(typeModeMap.get(DEFAULT_CONTEXT))) { + bestMatchValue = 2; + bestMatch = typeModeMap.get(DEFAULT_CONTEXT); + } + } + if (bestMatchValue < 1 && hasValue(typeMap.get(DEFAULT_VIEW_MODE).get(DEFAULT_CONTEXT))) { + bestMatchValue = 1; + bestMatch = typeMap.get(DEFAULT_VIEW_MODE).get(DEFAULT_CONTEXT); + } + } + } + return bestMatch; +} diff --git a/src/app/shared/object-collection/shared/listable-object/listable-object.directive.ts b/src/app/shared/object-collection/shared/listable-object/listable-object.directive.ts new file mode 100644 index 0000000000..93c06961f4 --- /dev/null +++ b/src/app/shared/object-collection/shared/listable-object/listable-object.directive.ts @@ -0,0 +1,11 @@ +import { Directive, ViewContainerRef } from '@angular/core'; + +@Directive({ + selector: '[dsListableObject]', +}) +/** + * Directive used as a hook to know where to inject the dynamic listable object component + */ +export class ListableObjectDirective { + constructor(public viewContainerRef: ViewContainerRef) { } +} diff --git a/src/app/shared/object-collection/shared/object-collection-element/abstract-listable-element.component.ts b/src/app/shared/object-collection/shared/object-collection-element/abstract-listable-element.component.ts index d52036b5dc..c09f7df18c 100644 --- a/src/app/shared/object-collection/shared/object-collection-element/abstract-listable-element.component.ts +++ b/src/app/shared/object-collection/shared/object-collection-element/abstract-listable-element.component.ts @@ -1,13 +1,24 @@ -import { Component, Inject } from '@angular/core'; +import { Component, Input } from '@angular/core'; import { ListableObject } from '../listable-object.model'; +import { CollectionElementLinkType } from '../../collection-element-link.type'; @Component({ selector: 'ds-abstract-object-element', template: ``, }) -export class AbstractListableElementComponent { - object: T; - public constructor(@Inject('objectElementProvider') public listableObject: ListableObject) { - this.object = listableObject as T; - } +export class AbstractListableElementComponent { + /** + * The object to render in this list element + */ + @Input() object: T; + + /** + * The link type to determine the type of link rendered in this element + */ + @Input() linkType: CollectionElementLinkType; + + /** + * The available link types + */ + linkTypes = CollectionElementLinkType; } diff --git a/src/app/shared/object-collection/shared/pool-task-my-dspace-result.model.ts b/src/app/shared/object-collection/shared/pool-task-search-result.model.ts similarity index 56% rename from src/app/shared/object-collection/shared/pool-task-my-dspace-result.model.ts rename to src/app/shared/object-collection/shared/pool-task-search-result.model.ts index 1bc2c4c4c2..0af55d31a4 100644 --- a/src/app/shared/object-collection/shared/pool-task-my-dspace-result.model.ts +++ b/src/app/shared/object-collection/shared/pool-task-search-result.model.ts @@ -1,11 +1,10 @@ import { PoolTask } from '../../../core/tasks/models/pool-task-object.model'; import { SearchResult } from '../../../+search-page/search-result.model'; -import { MyDSpaceConfigurationValueType } from '../../../+my-dspace-page/my-dspace-configuration-value-type'; import { searchResultFor } from '../../../+search-page/search-service/search-result-element-decorator'; /** * Represents a search result object of a PoolTask object */ -@searchResultFor(PoolTask, MyDSpaceConfigurationValueType.Workflow) -export class PoolTaskMyDSpaceResult extends SearchResult { +@searchResultFor(PoolTask) +export class PoolTaskSearchResult extends SearchResult { } diff --git a/src/app/shared/object-collection/shared/workflowitem-my-dspace-result.model.ts b/src/app/shared/object-collection/shared/workflow-item-search-result.model.ts similarity index 56% rename from src/app/shared/object-collection/shared/workflowitem-my-dspace-result.model.ts rename to src/app/shared/object-collection/shared/workflow-item-search-result.model.ts index d91c03b549..5684976e25 100644 --- a/src/app/shared/object-collection/shared/workflowitem-my-dspace-result.model.ts +++ b/src/app/shared/object-collection/shared/workflow-item-search-result.model.ts @@ -1,11 +1,10 @@ import { WorkflowItem } from '../../../core/submission/models/workflowitem.model'; import { SearchResult } from '../../../+search-page/search-result.model'; -import { MyDSpaceConfigurationValueType } from '../../../+my-dspace-page/my-dspace-configuration-value-type'; import { searchResultFor } from '../../../+search-page/search-service/search-result-element-decorator'; /** * Represents a search result object of a WorkflowItem object */ -@searchResultFor(WorkflowItem, MyDSpaceConfigurationValueType.Workspace) -export class WorkflowitemMyDSpaceResult extends SearchResult { +@searchResultFor(WorkflowItem) +export class WorkflowItemSearchResult extends SearchResult { } diff --git a/src/app/shared/object-collection/shared/workspaceitem-my-dspace-result.model.ts b/src/app/shared/object-collection/shared/workspace-item-search-result.model.ts similarity index 56% rename from src/app/shared/object-collection/shared/workspaceitem-my-dspace-result.model.ts rename to src/app/shared/object-collection/shared/workspace-item-search-result.model.ts index b7bd5e31d6..12fde0f8f1 100644 --- a/src/app/shared/object-collection/shared/workspaceitem-my-dspace-result.model.ts +++ b/src/app/shared/object-collection/shared/workspace-item-search-result.model.ts @@ -1,11 +1,10 @@ import { WorkspaceItem } from '../../../core/submission/models/workspaceitem.model'; -import { MyDSpaceConfigurationValueType } from '../../../+my-dspace-page/my-dspace-configuration-value-type'; import { searchResultFor } from '../../../+search-page/search-service/search-result-element-decorator'; import { SearchResult } from '../../../+search-page/search-result.model'; /** * Represents a search result object of a WorkspaceItem object */ -@searchResultFor(WorkspaceItem, MyDSpaceConfigurationValueType.Workspace) -export class WorkspaceitemMyDSpaceResult extends SearchResult { +@searchResultFor(WorkspaceItem) +export class WorkspaceItemSearchResult extends SearchResult { } diff --git a/src/app/shared/object-detail/my-dspace-result-detail-element/claimed-my-dspace-result/claimed-my-dspace-result-detail-element.component.html b/src/app/shared/object-detail/my-dspace-result-detail-element/claimed-task-search-result/claimed-task-search-result-detail-element.component.html similarity index 100% rename from src/app/shared/object-detail/my-dspace-result-detail-element/claimed-my-dspace-result/claimed-my-dspace-result-detail-element.component.html rename to src/app/shared/object-detail/my-dspace-result-detail-element/claimed-task-search-result/claimed-task-search-result-detail-element.component.html diff --git a/src/app/shared/object-detail/my-dspace-result-detail-element/claimed-my-dspace-result/claimed-my-dspace-result-detail-element.component.spec.ts b/src/app/shared/object-detail/my-dspace-result-detail-element/claimed-task-search-result/claimed-task-search-result-detail-element.component.spec.ts similarity index 69% rename from src/app/shared/object-detail/my-dspace-result-detail-element/claimed-my-dspace-result/claimed-my-dspace-result-detail-element.component.spec.ts rename to src/app/shared/object-detail/my-dspace-result-detail-element/claimed-task-search-result/claimed-task-search-result-detail-element.component.spec.ts index f57eb6420e..64bdfeff7b 100644 --- a/src/app/shared/object-detail/my-dspace-result-detail-element/claimed-my-dspace-result/claimed-my-dspace-result-detail-element.component.spec.ts +++ b/src/app/shared/object-detail/my-dspace-result-detail-element/claimed-task-search-result/claimed-task-search-result-detail-element.component.spec.ts @@ -5,20 +5,19 @@ import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { of as observableOf } from 'rxjs'; import { Item } from '../../../../core/shared/item.model'; -import { ClaimedMyDSpaceResultDetailElementComponent } from './claimed-my-dspace-result-detail-element.component'; -import { ClaimedTaskMyDSpaceResult } from '../../../object-collection/shared/claimed-task-my-dspace-result.model'; +import { ClaimedTaskSearchResultDetailElementComponent } from './claimed-task-search-result-detail-element.component'; import { ClaimedTask } from '../../../../core/tasks/models/claimed-task-object.model'; -import { RemoteData } from '../../../../core/data/remote-data'; import { MyDspaceItemStatusType } from '../../../object-collection/shared/mydspace-item-status/my-dspace-item-status-type'; import { WorkflowItem } from '../../../../core/submission/models/workflowitem.model'; import { createSuccessfulRemoteDataObject } from '../../../testing/utils'; +import { ClaimedTaskSearchResult } from '../../../object-collection/shared/claimed-task-search-result.model'; -let component: ClaimedMyDSpaceResultDetailElementComponent; -let fixture: ComponentFixture; +let component: ClaimedTaskSearchResultDetailElementComponent; +let fixture: ComponentFixture; const compIndex = 1; -const mockResultObject: ClaimedTaskMyDSpaceResult = new ClaimedTaskMyDSpaceResult(); +const mockResultObject: ClaimedTaskSearchResult = new ClaimedTaskSearchResult(); mockResultObject.hitHighlights = {}; const item = Object.assign(new Item(), { @@ -55,23 +54,19 @@ const workflowitem = Object.assign(new WorkflowItem(), { item: observableOf(rdIt const rdWorkflowitem = createSuccessfulRemoteDataObject(workflowitem); mockResultObject.indexableObject = Object.assign(new ClaimedTask(), { workflowitem: observableOf(rdWorkflowitem) }); -describe('ClaimedMyDSpaceResultDetailElementComponent', () => { +describe('ClaimedTaskSearchResultDetailElementComponent', () => { beforeEach(async(() => { TestBed.configureTestingModule({ imports: [NoopAnimationsModule], - declarations: [ClaimedMyDSpaceResultDetailElementComponent], - providers: [ - { provide: 'objectElementProvider', useValue: (mockResultObject) }, - { provide: 'indexElementProvider', useValue: (compIndex) } - ], + declarations: [ClaimedTaskSearchResultDetailElementComponent], schemas: [NO_ERRORS_SCHEMA] - }).overrideComponent(ClaimedMyDSpaceResultDetailElementComponent, { + }).overrideComponent(ClaimedTaskSearchResultDetailElementComponent, { set: { changeDetection: ChangeDetectionStrategy.Default } }).compileComponents(); })); beforeEach(async(() => { - fixture = TestBed.createComponent(ClaimedMyDSpaceResultDetailElementComponent); + fixture = TestBed.createComponent(ClaimedTaskSearchResultDetailElementComponent); component = fixture.componentInstance; })); diff --git a/src/app/shared/object-detail/my-dspace-result-detail-element/claimed-my-dspace-result/claimed-my-dspace-result-detail-element.component.ts b/src/app/shared/object-detail/my-dspace-result-detail-element/claimed-task-search-result/claimed-task-search-result-detail-element.component.ts similarity index 52% rename from src/app/shared/object-detail/my-dspace-result-detail-element/claimed-my-dspace-result/claimed-my-dspace-result-detail-element.component.ts rename to src/app/shared/object-detail/my-dspace-result-detail-element/claimed-task-search-result/claimed-task-search-result-detail-element.component.ts index 581d52c05f..72ffca4b98 100644 --- a/src/app/shared/object-detail/my-dspace-result-detail-element/claimed-my-dspace-result/claimed-my-dspace-result-detail-element.component.ts +++ b/src/app/shared/object-detail/my-dspace-result-detail-element/claimed-task-search-result/claimed-task-search-result-detail-element.component.ts @@ -1,32 +1,29 @@ -import { Component, Inject } from '@angular/core'; +import { Component } from '@angular/core'; import { Observable } from 'rxjs'; import { find } from 'rxjs/operators'; -import { renderElementsFor } from '../../../object-collection/shared/dso-element-decorator'; import { RemoteData } from '../../../../core/data/remote-data'; import { ViewMode } from '../../../../core/shared/view-mode.model'; import { isNotUndefined } from '../../../empty.util'; -import { ListableObject } from '../../../object-collection/shared/listable-object.model'; import { WorkflowItem } from '../../../../core/submission/models/workflowitem.model'; import { ClaimedTask } from '../../../../core/tasks/models/claimed-task-object.model'; -import { ClaimedTaskMyDSpaceResult } from '../../../object-collection/shared/claimed-task-my-dspace-result.model'; -import { MyDSpaceResultDetailElementComponent } from '../my-dspace-result-detail-element.component'; +import { SearchResultDetailElementComponent } from '../search-result-detail-element.component'; import { MyDspaceItemStatusType } from '../../../object-collection/shared/mydspace-item-status/my-dspace-item-status-type'; -import { SetViewMode } from '../../../view-mode'; +import { listableObjectComponent } from '../../../object-collection/shared/listable-object/listable-object.decorator'; +import { ClaimedTaskSearchResult } from '../../../object-collection/shared/claimed-task-search-result.model'; /** - * This component renders claimed task object for the mydspace result in the detail view. + * This component renders claimed task object for the search result in the detail view. */ @Component({ - selector: 'ds-claimed-my-dspace-result-detail-element', - styleUrls: ['../my-dspace-result-detail-element.component.scss'], - templateUrl: './claimed-my-dspace-result-detail-element.component.html' + selector: 'ds-claimed-task-search-result-detail-element', + styleUrls: ['../search-result-detail-element.component.scss'], + templateUrl: './claimed-task-search-result-detail-element.component.html' }) -@renderElementsFor(ClaimedTaskMyDSpaceResult, SetViewMode.Detail) -@renderElementsFor(ClaimedTask, SetViewMode.Detail) -export class ClaimedMyDSpaceResultDetailElementComponent extends MyDSpaceResultDetailElementComponent { +@listableObjectComponent(ClaimedTaskSearchResult, ViewMode.DetailedListElement) +export class ClaimedTaskSearchResultDetailElementComponent extends SearchResultDetailElementComponent { /** * A boolean representing if to show submitter information @@ -43,19 +40,16 @@ export class ClaimedMyDSpaceResultDetailElementComponent extends MyDSpaceResultD */ public workflowitem: WorkflowItem; - constructor(@Inject('objectElementProvider') public listable: ListableObject) { - super(listable); - } - /** * Initialize all instance variables */ ngOnInit() { + super.ngOnInit(); this.initWorkflowItem(this.dso.workflowitem as Observable>); } /** - * Retrieve workflowitem from result object + * Retrieve workflow item from result object */ initWorkflowItem(wfi$: Observable>) { wfi$.pipe( diff --git a/src/app/shared/object-detail/my-dspace-result-detail-element/item-detail-preview/item-detail-preview-field/item-detail-preview-field.component.ts b/src/app/shared/object-detail/my-dspace-result-detail-element/item-detail-preview/item-detail-preview-field/item-detail-preview-field.component.ts index b53d0a6b2d..2456913080 100644 --- a/src/app/shared/object-detail/my-dspace-result-detail-element/item-detail-preview/item-detail-preview-field/item-detail-preview-field.component.ts +++ b/src/app/shared/object-detail/my-dspace-result-detail-element/item-detail-preview/item-detail-preview-field/item-detail-preview-field.component.ts @@ -1,8 +1,8 @@ import { Component, Input } from '@angular/core'; import { Metadata } from '../../../../../core/shared/metadata.utils'; -import { MyDSpaceResult } from '../../../../../+my-dspace-page/my-dspace-result.model'; import { Item } from '../../../../../core/shared/item.model'; +import { SearchResult } from '../../../../../+search-page/search-result.model'; /** * This component show values for the given item metadata @@ -19,9 +19,9 @@ export class ItemDetailPreviewFieldComponent { @Input() item: Item; /** - * The mydspace result object + * The search result object */ - @Input() object: MyDSpaceResult; + @Input() object: SearchResult; /** * The metadata label diff --git a/src/app/shared/object-detail/my-dspace-result-detail-element/item-detail-preview/item-detail-preview.component.ts b/src/app/shared/object-detail/my-dspace-result-detail-element/item-detail-preview/item-detail-preview.component.ts index fa15c71168..0e808321ae 100644 --- a/src/app/shared/object-detail/my-dspace-result-detail-element/item-detail-preview/item-detail-preview.component.ts +++ b/src/app/shared/object-detail/my-dspace-result-detail-element/item-detail-preview/item-detail-preview.component.ts @@ -7,7 +7,7 @@ import { Item } from '../../../../core/shared/item.model'; import { MyDspaceItemStatusType } from '../../../object-collection/shared/mydspace-item-status/my-dspace-item-status-type'; import { fadeInOut } from '../../../animations/fade'; import { Bitstream } from '../../../../core/shared/bitstream.model'; -import { MyDSpaceResult } from '../../../../+my-dspace-page/my-dspace-result.model'; +import { SearchResult } from '../../../../+search-page/search-result.model'; import { FileService } from '../../../../core/shared/file.service'; import { HALEndpointService } from '../../../../core/shared/hal-endpoint.service'; @@ -28,9 +28,9 @@ export class ItemDetailPreviewComponent { @Input() item: Item; /** - * The mydspace result object + * The search result object */ - @Input() object: MyDSpaceResult; + @Input() object: SearchResult; /** * Represent item's status diff --git a/src/app/shared/object-detail/my-dspace-result-detail-element/item-my-dspace-result/item-my-dspace-result-detail-element.component.ts b/src/app/shared/object-detail/my-dspace-result-detail-element/item-my-dspace-result/item-my-dspace-result-detail-element.component.ts deleted file mode 100644 index 26f63deb83..0000000000 --- a/src/app/shared/object-detail/my-dspace-result-detail-element/item-my-dspace-result/item-my-dspace-result-detail-element.component.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { Component } from '@angular/core'; - -import { renderElementsFor } from '../../../object-collection/shared/dso-element-decorator'; -import { ViewMode } from '../../../../core/shared/view-mode.model'; -import { Item } from '../../../../core/shared/item.model'; -import { ItemMyDSpaceResult } from '../../../object-collection/shared/item-my-dspace-result.model'; -import { MyDSpaceResultDetailElementComponent } from '../my-dspace-result-detail-element.component'; -import { MyDspaceItemStatusType } from '../../../object-collection/shared/mydspace-item-status/my-dspace-item-status-type'; -import { SetViewMode } from '../../../view-mode'; - -/** - * This component renders item object for the mydspace result in the detail view. - */ -@Component({ - selector: 'ds-workspaceitem-my-dspace-result-detail-element', - styleUrls: ['../my-dspace-result-detail-element.component.scss', './item-my-dspace-result-detail-element.component.scss'], - templateUrl: './item-my-dspace-result-detail-element.component.html' -}) - -@renderElementsFor(ItemMyDSpaceResult, SetViewMode.Detail) -export class ItemMyDSpaceResultDetailElementComponent extends MyDSpaceResultDetailElementComponent { - - /** - * Represent item's status - */ - public status = MyDspaceItemStatusType.ARCHIVED; - -} diff --git a/src/app/shared/object-detail/my-dspace-result-detail-element/item-my-dspace-result/item-my-dspace-result-detail-element.component.html b/src/app/shared/object-detail/my-dspace-result-detail-element/item-search-result/item-search-result-detail-element.component.html similarity index 100% rename from src/app/shared/object-detail/my-dspace-result-detail-element/item-my-dspace-result/item-my-dspace-result-detail-element.component.html rename to src/app/shared/object-detail/my-dspace-result-detail-element/item-search-result/item-search-result-detail-element.component.html diff --git a/src/app/shared/object-detail/my-dspace-result-detail-element/item-my-dspace-result/item-my-dspace-result-detail-element.component.scss b/src/app/shared/object-detail/my-dspace-result-detail-element/item-search-result/item-search-result-detail-element.component.scss similarity index 100% rename from src/app/shared/object-detail/my-dspace-result-detail-element/item-my-dspace-result/item-my-dspace-result-detail-element.component.scss rename to src/app/shared/object-detail/my-dspace-result-detail-element/item-search-result/item-search-result-detail-element.component.scss diff --git a/src/app/shared/object-detail/my-dspace-result-detail-element/item-my-dspace-result/item-my-dspace-result-detail-element.component.spec.ts b/src/app/shared/object-detail/my-dspace-result-detail-element/item-search-result/item-search-result-detail-element.component.spec.ts similarity index 65% rename from src/app/shared/object-detail/my-dspace-result-detail-element/item-my-dspace-result/item-my-dspace-result-detail-element.component.spec.ts rename to src/app/shared/object-detail/my-dspace-result-detail-element/item-search-result/item-search-result-detail-element.component.spec.ts index c99f44cbae..72fbff78ed 100644 --- a/src/app/shared/object-detail/my-dspace-result-detail-element/item-my-dspace-result/item-my-dspace-result-detail-element.component.spec.ts +++ b/src/app/shared/object-detail/my-dspace-result-detail-element/item-search-result/item-search-result-detail-element.component.spec.ts @@ -5,16 +5,16 @@ import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { of as observableOf } from 'rxjs'; import { Item } from '../../../../core/shared/item.model'; -import { ItemMyDSpaceResultDetailElementComponent } from './item-my-dspace-result-detail-element.component'; +import { ItemSearchResultDetailElementComponent } from './item-search-result-detail-element.component'; import { MyDspaceItemStatusType } from '../../../object-collection/shared/mydspace-item-status/my-dspace-item-status-type'; -import { ItemMyDSpaceResult } from '../../../object-collection/shared/item-my-dspace-result.model'; +import { ItemSearchResult } from '../../../object-collection/shared/item-search-result.model'; -let component: ItemMyDSpaceResultDetailElementComponent; -let fixture: ComponentFixture; +let component: ItemSearchResultDetailElementComponent; +let fixture: ComponentFixture; const compIndex = 1; -const mockResultObject: ItemMyDSpaceResult = new ItemMyDSpaceResult(); +const mockResultObject: ItemSearchResult = new ItemSearchResult(); mockResultObject.hitHighlights = {}; mockResultObject.indexableObject = Object.assign(new Item(), { @@ -47,23 +47,19 @@ mockResultObject.indexableObject = Object.assign(new Item(), { } }); -describe('ItemMyDSpaceResultDetailElementComponent', () => { +describe('ItemSearchResultDetailElementComponent', () => { beforeEach(async(() => { TestBed.configureTestingModule({ imports: [NoopAnimationsModule], - declarations: [ItemMyDSpaceResultDetailElementComponent], - providers: [ - { provide: 'objectElementProvider', useValue: (mockResultObject) }, - { provide: 'indexElementProvider', useValue: (compIndex) } - ], + declarations: [ItemSearchResultDetailElementComponent], schemas: [NO_ERRORS_SCHEMA] - }).overrideComponent(ItemMyDSpaceResultDetailElementComponent, { + }).overrideComponent(ItemSearchResultDetailElementComponent, { set: { changeDetection: ChangeDetectionStrategy.Default } }).compileComponents(); })); beforeEach(async(() => { - fixture = TestBed.createComponent(ItemMyDSpaceResultDetailElementComponent); + fixture = TestBed.createComponent(ItemSearchResultDetailElementComponent); component = fixture.componentInstance; })); diff --git a/src/app/shared/object-detail/my-dspace-result-detail-element/item-search-result/item-search-result-detail-element.component.ts b/src/app/shared/object-detail/my-dspace-result-detail-element/item-search-result/item-search-result-detail-element.component.ts new file mode 100644 index 0000000000..7e611ec3c8 --- /dev/null +++ b/src/app/shared/object-detail/my-dspace-result-detail-element/item-search-result/item-search-result-detail-element.component.ts @@ -0,0 +1,27 @@ +import { Component } from '@angular/core'; + +import { ViewMode } from '../../../../core/shared/view-mode.model'; +import { Item } from '../../../../core/shared/item.model'; +import { SearchResultDetailElementComponent } from '../search-result-detail-element.component'; +import { MyDspaceItemStatusType } from '../../../object-collection/shared/mydspace-item-status/my-dspace-item-status-type'; +import { listableObjectComponent } from '../../../object-collection/shared/listable-object/listable-object.decorator'; +import { ItemSearchResult } from '../../../object-collection/shared/item-search-result.model'; + +/** + * This component renders item object for the search result in the detail view. + */ +@Component({ + selector: 'ds-item-search-result-detail-element', + styleUrls: ['../search-result-detail-element.component.scss', './item-search-result-detail-element.component.scss'], + templateUrl: './item-search-result-detail-element.component.html' +}) + +@listableObjectComponent(Item, ViewMode.DetailedListElement) +export class ItemSearchResultDetailElementComponent extends SearchResultDetailElementComponent { + + /** + * Represent item's status + */ + public status = MyDspaceItemStatusType.ARCHIVED; + +} diff --git a/src/app/shared/object-detail/my-dspace-result-detail-element/pool-my-dspace-result/pool-my-dspace-result-detail-element.component.html b/src/app/shared/object-detail/my-dspace-result-detail-element/pool-search-result/pool-search-result-detail-element.component.html similarity index 100% rename from src/app/shared/object-detail/my-dspace-result-detail-element/pool-my-dspace-result/pool-my-dspace-result-detail-element.component.html rename to src/app/shared/object-detail/my-dspace-result-detail-element/pool-search-result/pool-search-result-detail-element.component.html diff --git a/src/app/shared/object-list/my-dspace-result-list-element/pool-my-dspace-result/pool-my-dspace-result-list-element.component.spec.ts b/src/app/shared/object-detail/my-dspace-result-detail-element/pool-search-result/pool-search-result-detail-element.component.spec.ts similarity index 77% rename from src/app/shared/object-list/my-dspace-result-list-element/pool-my-dspace-result/pool-my-dspace-result-list-element.component.spec.ts rename to src/app/shared/object-detail/my-dspace-result-detail-element/pool-search-result/pool-search-result-detail-element.component.spec.ts index 22804a3a30..412dd00c13 100644 --- a/src/app/shared/object-list/my-dspace-result-list-element/pool-my-dspace-result/pool-my-dspace-result-list-element.component.spec.ts +++ b/src/app/shared/object-detail/my-dspace-result-detail-element/pool-search-result/pool-search-result-detail-element.component.spec.ts @@ -5,20 +5,19 @@ import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { of as observableOf } from 'rxjs'; import { Item } from '../../../../core/shared/item.model'; -import { PoolMyDSpaceResultListElementComponent } from './pool-my-dspace-result-list-element.component'; -import { PoolTaskMyDSpaceResult } from '../../../object-collection/shared/pool-task-my-dspace-result.model'; import { PoolTask } from '../../../../core/tasks/models/pool-task-object.model'; -import { RemoteData } from '../../../../core/data/remote-data'; import { MyDspaceItemStatusType } from '../../../object-collection/shared/mydspace-item-status/my-dspace-item-status-type'; import { WorkflowItem } from '../../../../core/submission/models/workflowitem.model'; import { createSuccessfulRemoteDataObject } from '../../../testing/utils'; +import { PoolSearchResultDetailElementComponent } from './pool-search-result-detail-element.component'; +import { PoolTaskSearchResult } from '../../../object-collection/shared/pool-task-search-result.model'; -let component: PoolMyDSpaceResultListElementComponent; -let fixture: ComponentFixture; +let component: PoolSearchResultDetailElementComponent; +let fixture: ComponentFixture; const compIndex = 1; -const mockResultObject: PoolTaskMyDSpaceResult = new PoolTaskMyDSpaceResult(); +const mockResultObject: PoolTaskSearchResult = new PoolTaskSearchResult(); mockResultObject.hitHighlights = {}; const item = Object.assign(new Item(), { @@ -55,23 +54,23 @@ const workflowitem = Object.assign(new WorkflowItem(), { item: observableOf(rdIt const rdWorkflowitem = createSuccessfulRemoteDataObject(workflowitem); mockResultObject.indexableObject = Object.assign(new PoolTask(), { workflowitem: observableOf(rdWorkflowitem) }); -describe('PoolMyDSpaceResultListElementComponent', () => { +describe('PoolSearchResultDetailElementComponent', () => { beforeEach(async(() => { TestBed.configureTestingModule({ imports: [NoopAnimationsModule], - declarations: [PoolMyDSpaceResultListElementComponent], + declarations: [PoolSearchResultDetailElementComponent], providers: [ { provide: 'objectElementProvider', useValue: (mockResultObject) }, { provide: 'indexElementProvider', useValue: (compIndex) } ], schemas: [NO_ERRORS_SCHEMA] - }).overrideComponent(PoolMyDSpaceResultListElementComponent, { + }).overrideComponent(PoolSearchResultDetailElementComponent, { set: { changeDetection: ChangeDetectionStrategy.Default } }).compileComponents(); })); beforeEach(async(() => { - fixture = TestBed.createComponent(PoolMyDSpaceResultListElementComponent); + fixture = TestBed.createComponent(PoolSearchResultDetailElementComponent); component = fixture.componentInstance; })); diff --git a/src/app/shared/object-detail/my-dspace-result-detail-element/pool-my-dspace-result/pool-my-dspace-result-detail-lement.component.ts b/src/app/shared/object-detail/my-dspace-result-detail-element/pool-search-result/pool-search-result-detail-element.component.ts similarity index 54% rename from src/app/shared/object-detail/my-dspace-result-detail-element/pool-my-dspace-result/pool-my-dspace-result-detail-lement.component.ts rename to src/app/shared/object-detail/my-dspace-result-detail-element/pool-search-result/pool-search-result-detail-element.component.ts index 0b5b6c6524..95de372713 100644 --- a/src/app/shared/object-detail/my-dspace-result-detail-element/pool-my-dspace-result/pool-my-dspace-result-detail-lement.component.ts +++ b/src/app/shared/object-detail/my-dspace-result-detail-element/pool-search-result/pool-search-result-detail-element.component.ts @@ -1,30 +1,28 @@ -import { Component, Inject } from '@angular/core'; +import { Component } from '@angular/core'; import { Observable } from 'rxjs'; import { find } from 'rxjs/operators'; -import { renderElementsFor } from '../../../object-collection/shared/dso-element-decorator'; import { RemoteData } from '../../../../core/data/remote-data'; import { isNotUndefined } from '../../../empty.util'; -import { ListableObject } from '../../../object-collection/shared/listable-object.model'; import { PoolTask } from '../../../../core/tasks/models/pool-task-object.model'; -import { PoolTaskMyDSpaceResult } from '../../../object-collection/shared/pool-task-my-dspace-result.model'; -import { MyDSpaceResultDetailElementComponent } from '../my-dspace-result-detail-element.component'; +import { SearchResultDetailElementComponent } from '../search-result-detail-element.component'; import { MyDspaceItemStatusType } from '../../../object-collection/shared/mydspace-item-status/my-dspace-item-status-type'; -import { SetViewMode } from '../../../view-mode'; import { WorkflowItem } from '../../../../core/submission/models/workflowitem.model'; +import { ViewMode } from '../../../../core/shared/view-mode.model'; +import { listableObjectComponent } from '../../../object-collection/shared/listable-object/listable-object.decorator'; +import { PoolTaskSearchResult } from '../../../object-collection/shared/pool-task-search-result.model'; /** - * This component renders pool task object for the mydspace result in the detail view. + * This component renders pool task object for the search result in the detail view. */ @Component({ - selector: 'ds-pool-my-dspace-result-detail-element', - styleUrls: ['../my-dspace-result-detail-element.component.scss'], - templateUrl: './pool-my-dspace-result-detail-element.component.html', + selector: 'ds-pool-search-result-detail-element', + styleUrls: ['../search-result-detail-element.component.scss'], + templateUrl: './pool-search-result-detail-element.component.html', }) -@renderElementsFor(PoolTaskMyDSpaceResult, SetViewMode.Detail) -@renderElementsFor(PoolTask, SetViewMode.Detail) -export class PoolMyDSpaceResultDetailElementComponent extends MyDSpaceResultDetailElementComponent { +@listableObjectComponent(PoolTaskSearchResult, ViewMode.DetailedListElement) +export class PoolSearchResultDetailElementComponent extends SearchResultDetailElementComponent { /** * A boolean representing if to show submitter information @@ -41,14 +39,11 @@ export class PoolMyDSpaceResultDetailElementComponent extends MyDSpaceResultDeta */ public workflowitem: WorkflowItem; - constructor(@Inject('objectElementProvider') public listable: ListableObject) { - super(listable); - } - /** * Initialize all instance variables */ ngOnInit() { + super.ngOnInit(); this.initWorkflowItem(this.dso.workflowitem as Observable>); } diff --git a/src/app/shared/object-detail/my-dspace-result-detail-element/my-dspace-result-detail-element.component.scss b/src/app/shared/object-detail/my-dspace-result-detail-element/search-result-detail-element.component.scss similarity index 100% rename from src/app/shared/object-detail/my-dspace-result-detail-element/my-dspace-result-detail-element.component.scss rename to src/app/shared/object-detail/my-dspace-result-detail-element/search-result-detail-element.component.scss diff --git a/src/app/shared/object-detail/my-dspace-result-detail-element/my-dspace-result-detail-element.component.ts b/src/app/shared/object-detail/my-dspace-result-detail-element/search-result-detail-element.component.ts similarity index 68% rename from src/app/shared/object-detail/my-dspace-result-detail-element/my-dspace-result-detail-element.component.ts rename to src/app/shared/object-detail/my-dspace-result-detail-element/search-result-detail-element.component.ts index 47a44d3132..f1e9fe698c 100644 --- a/src/app/shared/object-detail/my-dspace-result-detail-element/my-dspace-result-detail-element.component.ts +++ b/src/app/shared/object-detail/my-dspace-result-detail-element/search-result-detail-element.component.ts @@ -1,16 +1,19 @@ -import { Component, Inject } from '@angular/core'; +import { Component, OnInit } from '@angular/core'; -import { MyDSpaceResult } from '../../../+my-dspace-page/my-dspace-result.model'; import { AbstractListableElementComponent } from '../../object-collection/shared/object-collection-element/abstract-listable-element.component'; -import { ListableObject } from '../../object-collection/shared/listable-object.model'; import { DSpaceObject } from '../../../core/shared/dspace-object.model'; import { Metadata } from '../../../core/shared/metadata.utils'; +import { SearchResult } from '../../../+search-page/search-result.model'; +import { hasValue } from '../../empty.util'; +/** + * Component representing Search Results with ViewMode.DetailedElement + */ @Component({ - selector: 'ds-my-dspace-result-detail-element', + selector: 'ds-search-result-detail-element', template: `` }) -export class MyDSpaceResultDetailElementComponent, K extends DSpaceObject> extends AbstractListableElementComponent { +export class SearchResultDetailElementComponent, K extends DSpaceObject> extends AbstractListableElementComponent implements OnInit { /** * The result element object @@ -19,12 +22,11 @@ export class MyDSpaceResultDetailElementComponent, K /** * Initialize instance variables - * - * @param {ListableObject} detailable */ - public constructor(@Inject('objectElementProvider') public detailable: ListableObject) { - super(detailable); - this.dso = this.object.indexableObject; + ngOnInit(): void { + if (hasValue(this.object)) { + this.dso = this.object.indexableObject; + } } /** diff --git a/src/app/shared/object-detail/my-dspace-result-detail-element/workflowitem-my-dspace-result/workflowitem-my-dspace-result-detail-element.component.html b/src/app/shared/object-detail/my-dspace-result-detail-element/workflow-item-search-result/workflow-item-search-result-detail-element.component.html similarity index 100% rename from src/app/shared/object-detail/my-dspace-result-detail-element/workflowitem-my-dspace-result/workflowitem-my-dspace-result-detail-element.component.html rename to src/app/shared/object-detail/my-dspace-result-detail-element/workflow-item-search-result/workflow-item-search-result-detail-element.component.html diff --git a/src/app/shared/object-list/my-dspace-result-list-element/workflowitem-my-dspace-result/workflowitem-my-dspace-result-list-element.component.spec.ts b/src/app/shared/object-detail/my-dspace-result-detail-element/workflow-item-search-result/workflow-item-search-result-detail-element.component.spec.ts similarity index 73% rename from src/app/shared/object-list/my-dspace-result-list-element/workflowitem-my-dspace-result/workflowitem-my-dspace-result-list-element.component.spec.ts rename to src/app/shared/object-detail/my-dspace-result-detail-element/workflow-item-search-result/workflow-item-search-result-detail-element.component.spec.ts index ab472b4014..2e6ad0ef95 100644 --- a/src/app/shared/object-list/my-dspace-result-list-element/workflowitem-my-dspace-result/workflowitem-my-dspace-result-list-element.component.spec.ts +++ b/src/app/shared/object-detail/my-dspace-result-detail-element/workflow-item-search-result/workflow-item-search-result-detail-element.component.spec.ts @@ -5,19 +5,18 @@ import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { of as observableOf } from 'rxjs'; import { Item } from '../../../../core/shared/item.model'; -import { WorkflowitemMyDSpaceResultListElementComponent } from './workflowitem-my-dspace-result-list-element.component'; -import { WorkflowitemMyDSpaceResult } from '../../../object-collection/shared/workflowitem-my-dspace-result.model'; +import { WorkflowItemSearchResultDetailElementComponent } from './workflow-item-search-result-detail-element.component'; import { WorkflowItem } from '../../../../core/submission/models/workflowitem.model'; -import { RemoteData } from '../../../../core/data/remote-data'; import { MyDspaceItemStatusType } from '../../../object-collection/shared/mydspace-item-status/my-dspace-item-status-type'; import { createSuccessfulRemoteDataObject } from '../../../testing/utils'; +import { WorkflowItemSearchResult } from '../../../object-collection/shared/workflow-item-search-result.model'; -let component: WorkflowitemMyDSpaceResultListElementComponent; -let fixture: ComponentFixture; +let component: WorkflowItemSearchResultDetailElementComponent; +let fixture: ComponentFixture; const compIndex = 1; -const mockResultObject: WorkflowitemMyDSpaceResult = new WorkflowitemMyDSpaceResult(); +const mockResultObject: WorkflowItemSearchResult = new WorkflowItemSearchResult(); mockResultObject.hitHighlights = {}; const item = Object.assign(new Item(), { @@ -52,23 +51,23 @@ const item = Object.assign(new Item(), { const rd = createSuccessfulRemoteDataObject(item); mockResultObject.indexableObject = Object.assign(new WorkflowItem(), { item: observableOf(rd) }); -describe('WorkflowitemMyDSpaceResultListElementComponent', () => { +describe('WorkflowItemSearchResultDetailElementComponent', () => { beforeEach(async(() => { TestBed.configureTestingModule({ imports: [NoopAnimationsModule], - declarations: [WorkflowitemMyDSpaceResultListElementComponent], + declarations: [WorkflowItemSearchResultDetailElementComponent], providers: [ { provide: 'objectElementProvider', useValue: (mockResultObject) }, { provide: 'indexElementProvider', useValue: (compIndex) } ], schemas: [NO_ERRORS_SCHEMA] - }).overrideComponent(WorkflowitemMyDSpaceResultListElementComponent, { + }).overrideComponent(WorkflowItemSearchResultDetailElementComponent, { set: { changeDetection: ChangeDetectionStrategy.Default } }).compileComponents(); })); beforeEach(async(() => { - fixture = TestBed.createComponent(WorkflowitemMyDSpaceResultListElementComponent); + fixture = TestBed.createComponent(WorkflowItemSearchResultDetailElementComponent); component = fixture.componentInstance; })); diff --git a/src/app/shared/object-list/my-dspace-result-list-element/workflowitem-my-dspace-result/workflowitem-my-dspace-result-list-element.component.ts b/src/app/shared/object-detail/my-dspace-result-detail-element/workflow-item-search-result/workflow-item-search-result-detail-element.component.ts similarity index 54% rename from src/app/shared/object-list/my-dspace-result-list-element/workflowitem-my-dspace-result/workflowitem-my-dspace-result-list-element.component.ts rename to src/app/shared/object-detail/my-dspace-result-detail-element/workflow-item-search-result/workflow-item-search-result-detail-element.component.ts index b5d11b8b13..23a8ad9e18 100644 --- a/src/app/shared/object-list/my-dspace-result-list-element/workflowitem-my-dspace-result/workflowitem-my-dspace-result-list-element.component.ts +++ b/src/app/shared/object-detail/my-dspace-result-detail-element/workflow-item-search-result/workflow-item-search-result-detail-element.component.ts @@ -1,31 +1,28 @@ -import { Component } from '@angular/core'; +import { Component, Inject } from '@angular/core'; -import { Observable } from 'rxjs'; -import { find } from 'rxjs/operators'; - -import { renderElementsFor } from '../../../object-collection/shared/dso-element-decorator'; -import { MyDSpaceResultListElementComponent, } from '../my-dspace-result-list-element.component'; import { ViewMode } from '../../../../core/shared/view-mode.model'; -import { RemoteData } from '../../../../core/data/remote-data'; -import { isNotUndefined } from '../../../empty.util'; -import { WorkflowitemMyDSpaceResult } from '../../../object-collection/shared/workflowitem-my-dspace-result.model'; -import { WorkflowItem } from '../../../../core/submission/models/workflowitem.model'; import { Item } from '../../../../core/shared/item.model'; +import { WorkflowItem } from '../../../../core/submission/models/workflowitem.model'; +import { SearchResultDetailElementComponent } from '../search-result-detail-element.component'; import { MyDspaceItemStatusType } from '../../../object-collection/shared/mydspace-item-status/my-dspace-item-status-type'; -import { SetViewMode } from '../../../view-mode'; +import { Observable } from 'rxjs/internal/Observable'; +import { RemoteData } from '../../../../core/data/remote-data'; +import { find } from 'rxjs/operators'; +import { isNotUndefined } from '../../../empty.util'; +import { listableObjectComponent } from '../../../object-collection/shared/listable-object/listable-object.decorator'; +import { WorkflowItemSearchResult } from '../../../object-collection/shared/workflow-item-search-result.model'; /** - * This component renders workflowitem object for the mydspace result in the list view. + * This component renders workflowitem object for the search result in the detail view. */ @Component({ - selector: 'ds-workflowitem-my-dspace-result-list-element', - styleUrls: ['../my-dspace-result-list-element.component.scss'], - templateUrl: './workflowitem-my-dspace-result-list-element.component.html', + selector: 'ds-workflow-item-search-result-detail-element', + styleUrls: ['../search-result-detail-element.component.scss'], + templateUrl: './workflow-item-search-result-detail-element.component.html', }) -@renderElementsFor(WorkflowitemMyDSpaceResult, SetViewMode.List) -@renderElementsFor(WorkflowItem, SetViewMode.List) -export class WorkflowitemMyDSpaceResultListElementComponent extends MyDSpaceResultListElementComponent { +@listableObjectComponent(WorkflowItemSearchResult, ViewMode.DetailedListElement) +export class WorkflowItemSearchResultDetailElementComponent extends SearchResultDetailElementComponent { /** * The item object that belonging to the result object @@ -41,6 +38,7 @@ export class WorkflowitemMyDSpaceResultListElementComponent extends MyDSpaceResu * Initialize all instance variables */ ngOnInit() { + super.ngOnInit(); this.initItem(this.dso.item as Observable>); } diff --git a/src/app/shared/object-detail/my-dspace-result-detail-element/workflowitem-my-dspace-result/workflowitem-my-dspace-result-detail-element.component.ts b/src/app/shared/object-detail/my-dspace-result-detail-element/workflowitem-my-dspace-result/workflowitem-my-dspace-result-detail-element.component.ts deleted file mode 100644 index c28f044e6e..0000000000 --- a/src/app/shared/object-detail/my-dspace-result-detail-element/workflowitem-my-dspace-result/workflowitem-my-dspace-result-detail-element.component.ts +++ /dev/null @@ -1,62 +0,0 @@ -import { Component, Inject } from '@angular/core'; - -import { renderElementsFor } from '../../../object-collection/shared/dso-element-decorator'; -import { ViewMode } from '../../../../core/shared/view-mode.model'; -import { Item } from '../../../../core/shared/item.model'; -import { ListableObject } from '../../../object-collection/shared/listable-object.model'; -import { WorkflowitemMyDSpaceResult } from '../../../object-collection/shared/workflowitem-my-dspace-result.model'; -import { WorkflowItem } from '../../../../core/submission/models/workflowitem.model'; -import { MyDSpaceResultDetailElementComponent } from '../my-dspace-result-detail-element.component'; -import { MyDspaceItemStatusType } from '../../../object-collection/shared/mydspace-item-status/my-dspace-item-status-type'; -import { Observable } from 'rxjs/internal/Observable'; -import { RemoteData } from '../../../../core/data/remote-data'; -import { find } from 'rxjs/operators'; -import { isNotUndefined } from '../../../empty.util'; -import { SetViewMode } from '../../../view-mode'; - -/** - * This component renders workflowitem object for the mydspace result in the detail view. - */ -@Component({ - selector: 'ds-workflowitem-my-dspace-result-detail-element', - styleUrls: ['../my-dspace-result-detail-element.component.scss'], - templateUrl: './workflowitem-my-dspace-result-detail-element.component.html', -}) - -@renderElementsFor(WorkflowitemMyDSpaceResult, SetViewMode.Detail) -@renderElementsFor(WorkflowItem, SetViewMode.Detail) -export class WorkflowitemMyDSpaceResultDetailElementComponent extends MyDSpaceResultDetailElementComponent { - - /** - * The item object that belonging to the result object - */ - public item: Item; - - /** - * Represent item's status - */ - public status = MyDspaceItemStatusType.WORKFLOW; - - constructor(@Inject('objectElementProvider') public listable: ListableObject) { - super(listable); - } - - /** - * Initialize all instance variables - */ - ngOnInit() { - this.initItem(this.dso.item as Observable>); - } - - /** - * Retrieve item from result object - */ - initItem(item$: Observable>) { - item$.pipe( - find((rd: RemoteData) => rd.hasSucceeded && isNotUndefined(rd.payload)) - ).subscribe((rd: RemoteData) => { - this.item = rd.payload; - }); - } - -} diff --git a/src/app/shared/object-detail/my-dspace-result-detail-element/workspaceitem-my-dspace-result/workspaceitem-my-dspace-result-detail-element.component.html b/src/app/shared/object-detail/my-dspace-result-detail-element/workspace-item-search-result/workspace-item-search-result-detail-element.component.html similarity index 100% rename from src/app/shared/object-detail/my-dspace-result-detail-element/workspaceitem-my-dspace-result/workspaceitem-my-dspace-result-detail-element.component.html rename to src/app/shared/object-detail/my-dspace-result-detail-element/workspace-item-search-result/workspace-item-search-result-detail-element.component.html diff --git a/src/app/shared/object-detail/my-dspace-result-detail-element/workspace-item-search-result/workspace-item-search-result-detail-element.component.scss b/src/app/shared/object-detail/my-dspace-result-detail-element/workspace-item-search-result/workspace-item-search-result-detail-element.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/shared/object-list/my-dspace-result-list-element/workspaceitem-my-dspace-result/workspaceitem-my-dspace-result-list-element.component.spec.ts b/src/app/shared/object-detail/my-dspace-result-detail-element/workspace-item-search-result/workspace-item-search-result-detail-element.component.spec.ts similarity index 73% rename from src/app/shared/object-list/my-dspace-result-list-element/workspaceitem-my-dspace-result/workspaceitem-my-dspace-result-list-element.component.spec.ts rename to src/app/shared/object-detail/my-dspace-result-detail-element/workspace-item-search-result/workspace-item-search-result-detail-element.component.spec.ts index a1c2472d27..fb5793b3bb 100644 --- a/src/app/shared/object-list/my-dspace-result-list-element/workspaceitem-my-dspace-result/workspaceitem-my-dspace-result-list-element.component.spec.ts +++ b/src/app/shared/object-detail/my-dspace-result-detail-element/workspace-item-search-result/workspace-item-search-result-detail-element.component.spec.ts @@ -5,19 +5,18 @@ import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { of as observableOf } from 'rxjs'; import { Item } from '../../../../core/shared/item.model'; -import { WorkspaceitemMyDSpaceResultListElementComponent } from './workspaceitem-my-dspace-result-list-element.component'; -import { WorkspaceitemMyDSpaceResult } from '../../../object-collection/shared/workspaceitem-my-dspace-result.model'; +import { WorkspaceItemSearchResultDetailElementComponent } from './workspace-item-search-result-detail-element.component'; import { WorkspaceItem } from '../../../../core/submission/models/workspaceitem.model'; -import { RemoteData } from '../../../../core/data/remote-data'; import { MyDspaceItemStatusType } from '../../../object-collection/shared/mydspace-item-status/my-dspace-item-status-type'; import { createSuccessfulRemoteDataObject } from '../../../testing/utils'; +import { WorkflowItemSearchResult } from '../../../object-collection/shared/workflow-item-search-result.model'; -let component: WorkspaceitemMyDSpaceResultListElementComponent; -let fixture: ComponentFixture; +let component: WorkspaceItemSearchResultDetailElementComponent; +let fixture: ComponentFixture; const compIndex = 1; -const mockResultObject: WorkspaceitemMyDSpaceResult = new WorkspaceitemMyDSpaceResult(); +const mockResultObject: WorkflowItemSearchResult = new WorkflowItemSearchResult(); mockResultObject.hitHighlights = {}; const item = Object.assign(new Item(), { @@ -52,23 +51,23 @@ const item = Object.assign(new Item(), { const rd = createSuccessfulRemoteDataObject(item); mockResultObject.indexableObject = Object.assign(new WorkspaceItem(), { item: observableOf(rd) }); -describe('WorkspaceitemMyDSpaceResultListElementComponent', () => { +describe('WorkspaceItemSearchResultDetailElementComponent', () => { beforeEach(async(() => { TestBed.configureTestingModule({ imports: [NoopAnimationsModule], - declarations: [WorkspaceitemMyDSpaceResultListElementComponent], + declarations: [WorkspaceItemSearchResultDetailElementComponent], providers: [ { provide: 'objectElementProvider', useValue: (mockResultObject) }, { provide: 'indexElementProvider', useValue: (compIndex) } ], schemas: [NO_ERRORS_SCHEMA] - }).overrideComponent(WorkspaceitemMyDSpaceResultListElementComponent, { + }).overrideComponent(WorkspaceItemSearchResultDetailElementComponent, { set: { changeDetection: ChangeDetectionStrategy.Default } }).compileComponents(); })); beforeEach(async(() => { - fixture = TestBed.createComponent(WorkspaceitemMyDSpaceResultListElementComponent); + fixture = TestBed.createComponent(WorkspaceItemSearchResultDetailElementComponent); component = fixture.componentInstance; })); diff --git a/src/app/shared/object-list/my-dspace-result-list-element/workspaceitem-my-dspace-result/workspaceitem-my-dspace-result-list-element.component.ts b/src/app/shared/object-detail/my-dspace-result-detail-element/workspace-item-search-result/workspace-item-search-result-detail-element.component.ts similarity index 55% rename from src/app/shared/object-list/my-dspace-result-list-element/workspaceitem-my-dspace-result/workspaceitem-my-dspace-result-list-element.component.ts rename to src/app/shared/object-detail/my-dspace-result-detail-element/workspace-item-search-result/workspace-item-search-result-detail-element.component.ts index 118965c64a..746fd02889 100644 --- a/src/app/shared/object-list/my-dspace-result-list-element/workspaceitem-my-dspace-result/workspaceitem-my-dspace-result-list-element.component.ts +++ b/src/app/shared/object-detail/my-dspace-result-detail-element/workspace-item-search-result/workspace-item-search-result-detail-element.component.ts @@ -3,33 +3,32 @@ import { Component } from '@angular/core'; import { Observable } from 'rxjs'; import { find } from 'rxjs/operators'; -import { renderElementsFor } from '../../../object-collection/shared/dso-element-decorator'; -import { MyDSpaceResultListElementComponent, } from '../my-dspace-result-list-element.component'; -import { ViewMode } from '../../../../core/shared/view-mode.model'; import { WorkspaceItem } from '../../../../core/submission/models/workspaceitem.model'; -import { WorkspaceitemMyDSpaceResult } from '../../../object-collection/shared/workspaceitem-my-dspace-result.model'; +import { Item } from '../../../../core/shared/item.model'; import { RemoteData } from '../../../../core/data/remote-data'; import { isNotUndefined } from '../../../empty.util'; -import { Item } from '../../../../core/shared/item.model'; +import { SearchResultDetailElementComponent } from '../search-result-detail-element.component'; import { MyDspaceItemStatusType } from '../../../object-collection/shared/mydspace-item-status/my-dspace-item-status-type'; -import { SetViewMode } from '../../../view-mode'; +import { ViewMode } from '../../../../core/shared/view-mode.model'; +import { listableObjectComponent } from '../../../object-collection/shared/listable-object/listable-object.decorator'; +import { WorkspaceItemSearchResult } from '../../../object-collection/shared/workspace-item-search-result.model'; /** - * This component renders workspaceitem object for the mydspace result in the list view. + * This component renders workspace item object for the search result in the detail view. */ @Component({ - selector: 'ds-workspaceitem-my-dspace-result-list-element', - styleUrls: ['../my-dspace-result-list-element.component.scss', './workspaceitem-my-dspace-result-list-element.component.scss'], - templateUrl: './workspaceitem-my-dspace-result-list-element.component.html', + selector: 'ds-workspace-item-search-result-detail-element', + styleUrls: ['../search-result-detail-element.component.scss', './workspace-item-search-result-detail-element.component.scss'], + templateUrl: './workspace-item-search-result-detail-element.component.html', }) -@renderElementsFor(WorkspaceitemMyDSpaceResult, SetViewMode.List) -export class WorkspaceitemMyDSpaceResultListElementComponent extends MyDSpaceResultListElementComponent { +@listableObjectComponent(WorkspaceItemSearchResult, ViewMode.DetailedListElement) +export class WorkspaceItemSearchResultDetailElementComponent extends SearchResultDetailElementComponent { /** * The item object that belonging to the result object */ - item: Item; + public item: Item; /** * Represent item's status @@ -40,6 +39,7 @@ export class WorkspaceitemMyDSpaceResultListElementComponent extends MyDSpaceRes * Initialize all instance variables */ ngOnInit() { + super.ngOnInit(); this.initItem(this.dso.item as Observable>); } diff --git a/src/app/shared/object-detail/my-dspace-result-detail-element/workspaceitem-my-dspace-result/workspaceitem-my-dspace-result-detail-element.component.ts b/src/app/shared/object-detail/my-dspace-result-detail-element/workspaceitem-my-dspace-result/workspaceitem-my-dspace-result-detail-element.component.ts deleted file mode 100644 index af735ecb1e..0000000000 --- a/src/app/shared/object-detail/my-dspace-result-detail-element/workspaceitem-my-dspace-result/workspaceitem-my-dspace-result-detail-element.component.ts +++ /dev/null @@ -1,63 +0,0 @@ -import { Component, Inject } from '@angular/core'; - -import { Observable } from 'rxjs'; -import { find } from 'rxjs/operators'; - -import { renderElementsFor } from '../../../object-collection/shared/dso-element-decorator'; -import { - WorkspaceItem -} from '../../../../core/submission/models/workspaceitem.model'; -import { WorkspaceitemMyDSpaceResult } from '../../../object-collection/shared/workspaceitem-my-dspace-result.model'; -import { Item } from '../../../../core/shared/item.model'; -import { RemoteData } from '../../../../core/data/remote-data'; -import { isNotUndefined } from '../../../empty.util'; -import { ListableObject } from '../../../object-collection/shared/listable-object.model'; -import { MyDSpaceResultDetailElementComponent } from '../my-dspace-result-detail-element.component'; -import { MyDspaceItemStatusType } from '../../../object-collection/shared/mydspace-item-status/my-dspace-item-status-type'; -import { SetViewMode } from '../../../view-mode'; - -/** - * This component renders workspaceitem object for the mydspace result in the detail view. - */ -@Component({ - selector: 'ds-workspaceitem-my-dspace-result-detail-element', - styleUrls: ['../my-dspace-result-detail-element.component.scss', './workspaceitem-my-dspace-result-detail-element.component.scss'], - templateUrl: './workspaceitem-my-dspace-result-detail-element.component.html', -}) - -@renderElementsFor(WorkspaceitemMyDSpaceResult, SetViewMode.Detail) -@renderElementsFor(WorkspaceItem, SetViewMode.Detail) -export class WorkspaceitemMyDSpaceResultDetailElementComponent extends MyDSpaceResultDetailElementComponent { - - /** - * The item object that belonging to the result object - */ - public item: Item; - - /** - * Represent item's status - */ - status = MyDspaceItemStatusType.WORKSPACE; - - constructor(@Inject('objectElementProvider') public listable: ListableObject) { - super(listable); - } - - /** - * Initialize all instance variables - */ - ngOnInit() { - this.initItem(this.dso.item as Observable>); - } - - /** - * Retrieve item from result object - */ - initItem(item$: Observable>) { - item$.pipe( - find((rd: RemoteData) => rd.hasSucceeded && isNotUndefined(rd.payload)) - ).subscribe((rd: RemoteData) => { - this.item = rd.payload; - }); - } -} diff --git a/src/app/shared/object-detail/object-detail.component.html b/src/app/shared/object-detail/object-detail.component.html index a57a23027e..7fef7d9689 100644 --- a/src/app/shared/object-detail/object-detail.component.html +++ b/src/app/shared/object-detail/object-detail.component.html @@ -14,9 +14,9 @@
- +
- - + + diff --git a/src/app/shared/object-detail/object-detail.component.scss b/src/app/shared/object-detail/object-detail.component.scss index 9a077e3e08..e0a4e3abdc 100644 --- a/src/app/shared/object-detail/object-detail.component.scss +++ b/src/app/shared/object-detail/object-detail.component.scss @@ -1,9 +1,9 @@ @import '../../../styles/variables'; @import '../../../styles/mixins'; -ds-wrapper-detail-element ::ng-deep { +:host::ng-deep { div.thumbnail > img { height: $card-thumbnail-height; width: 100%; } -} +} \ No newline at end of file diff --git a/src/app/shared/object-detail/object-detail.component.spec.ts b/src/app/shared/object-detail/object-detail.component.spec.ts index 651e6a89a8..7bec565562 100644 --- a/src/app/shared/object-detail/object-detail.component.spec.ts +++ b/src/app/shared/object-detail/object-detail.component.spec.ts @@ -9,6 +9,7 @@ import { PaginatedList } from '../../core/data/paginated-list'; import { PageInfo } from '../../core/shared/page-info.model'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { createSuccessfulRemoteDataObject } from '../testing/utils'; +import { DSpaceObject } from '../../core/shared/dspace-object.model'; describe('ObjectDetailComponent', () => { let comp: ObjectDetailComponent; @@ -16,16 +17,16 @@ describe('ObjectDetailComponent', () => { const testEvent = {test: 'test'}; const testObjects = [ - { one: 1 }, - { two: 2 }, - { three: 3 }, - { four: 4 }, - { five: 5 }, - { six: 6 }, - { seven: 7 }, - { eight: 8 }, - { nine: 9 }, - { ten: 10 } + Object.assign (new DSpaceObject(), { one: 1 }), + Object.assign (new DSpaceObject(), { two: 2 }), + Object.assign (new DSpaceObject(), { three: 3 }), + Object.assign (new DSpaceObject(), { four: 4 }), + Object.assign (new DSpaceObject(), { five: 5 }), + Object.assign (new DSpaceObject(), { six: 6 }), + Object.assign (new DSpaceObject(), { seven: 7 }), + Object.assign (new DSpaceObject(), { eight: 8 }), + Object.assign (new DSpaceObject(), { nine: 9 }), + Object.assign (new DSpaceObject(), { ten: 10 }), ]; const pageInfo = Object.assign(new PageInfo(), {elementsPerPage: 1, totalElements: 10, totalPages: 10, currentPage: 1}) const mockRD = createSuccessfulRemoteDataObject(new PaginatedList(pageInfo, testObjects)); diff --git a/src/app/shared/object-detail/object-detail.component.ts b/src/app/shared/object-detail/object-detail.component.ts index 3187a2cd1b..fb68316251 100644 --- a/src/app/shared/object-detail/object-detail.component.ts +++ b/src/app/shared/object-detail/object-detail.component.ts @@ -15,6 +15,9 @@ import { fadeIn } from '../animations/fade'; import { ListableObject } from '../object-collection/shared/listable-object.model'; import { PaginationComponentOptions } from '../pagination/pagination-component-options.model'; +import { ViewMode } from '../../core/shared/view-mode.model'; +import { Context } from '../../core/shared/context.model'; +import { CollectionElementLinkType } from '../object-collection/collection-element-link.type'; /** * This component renders a paginated set of results in the detail view. @@ -28,6 +31,10 @@ import { PaginationComponentOptions } from '../pagination/pagination-component-o animations: [fadeIn] }) export class ObjectDetailComponent { + /** + * The view mode of this component + */ + viewMode = ViewMode.DetailedListElement; /** * Pagination options object @@ -49,6 +56,16 @@ export class ObjectDetailComponent { */ @Input() hidePagerWhenSinglePage = true; + /** + * The link type of the rendered listable elements + */ + @Input() linkType: CollectionElementLinkType; + + /** + * The context of the rendered listable elements + */ + @Input() context: Context; + /** * The list of objects to paginate */ diff --git a/src/app/shared/object-detail/wrapper-detail-element/wrapper-detail-element.component.html b/src/app/shared/object-detail/wrapper-detail-element/wrapper-detail-element.component.html deleted file mode 100644 index ef7254b97c..0000000000 --- a/src/app/shared/object-detail/wrapper-detail-element/wrapper-detail-element.component.html +++ /dev/null @@ -1 +0,0 @@ - diff --git a/src/app/shared/object-detail/wrapper-detail-element/wrapper-detail-element.component.scss b/src/app/shared/object-detail/wrapper-detail-element/wrapper-detail-element.component.scss deleted file mode 100644 index 51a7fc6a55..0000000000 --- a/src/app/shared/object-detail/wrapper-detail-element/wrapper-detail-element.component.scss +++ /dev/null @@ -1,2 +0,0 @@ -@import '../../../../styles/variables'; - diff --git a/src/app/shared/object-detail/wrapper-detail-element/wrapper-detail-element.component.spec.ts b/src/app/shared/object-detail/wrapper-detail-element/wrapper-detail-element.component.spec.ts deleted file mode 100644 index e54ae58398..0000000000 --- a/src/app/shared/object-detail/wrapper-detail-element/wrapper-detail-element.component.spec.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { async, ComponentFixture, TestBed } from '@angular/core/testing'; -import { NO_ERRORS_SCHEMA } from '@angular/core'; -import { By } from '@angular/platform-browser'; -import { ActivatedRoute, Router } from '@angular/router'; - -import { of as observableOf } from 'rxjs'; - -import { RouterStub } from '../../testing/router-stub'; -import { WrapperDetailElementComponent } from './wrapper-detail-element.component'; - -let wrapperDetailElementComponent: WrapperDetailElementComponent; -let fixture: ComponentFixture; -const queryParam = 'test query'; -const scopeParam = '7669c72a-3f2a-451f-a3b9-9210e7a4c02f'; -const activatedRouteStub = { - queryParams: observableOf({ - query: queryParam, - scope: scopeParam - }) -}; - -describe('WrapperDetailElementComponent', () => { - beforeEach(async(() => { - TestBed.configureTestingModule({ - declarations: [ WrapperDetailElementComponent ], - providers: [ - { provide: ActivatedRoute, useValue: activatedRouteStub }, - { provide: Router, useClass: RouterStub }, - { provide: 'objectElementProvider', useFactory: (WrapperDetailElementComponent)} - ], - - schemas: [ NO_ERRORS_SCHEMA ] - }).compileComponents(); // compile template and css - })); - - beforeEach(async(() => { - fixture = TestBed.createComponent(WrapperDetailElementComponent); - wrapperDetailElementComponent = fixture.componentInstance; - })); - - it('should show the wrapper element containing the detail object',() => { - expect(fixture.debugElement.query(By.css('ds-workspaceitem-my-dspace-result-detail-element'))).toBeDefined(); - }) -}); diff --git a/src/app/shared/object-detail/wrapper-detail-element/wrapper-detail-element.component.ts b/src/app/shared/object-detail/wrapper-detail-element/wrapper-detail-element.component.ts deleted file mode 100644 index 2ca8069b16..0000000000 --- a/src/app/shared/object-detail/wrapper-detail-element/wrapper-detail-element.component.ts +++ /dev/null @@ -1,57 +0,0 @@ -import { Component, Injector, Input, OnInit } from '@angular/core'; - -import { ViewMode } from '../../../core/shared/view-mode.model'; -import { GenericConstructor } from '../../../core/shared/generic-constructor'; -import { rendersDSOType } from '../../object-collection/shared/dso-element-decorator'; -import { ListableObject } from '../../object-collection/shared/listable-object.model'; -import { SetViewMode } from '../../view-mode'; - -/** - * This component renders a wrapper for an object in the detail view. - */ -@Component({ - selector: 'ds-wrapper-detail-element', - styleUrls: ['./wrapper-detail-element.component.scss'], - templateUrl: './wrapper-detail-element.component.html' -}) -export class WrapperDetailElementComponent implements OnInit { - - /** - * The listable object. - */ - @Input() object: ListableObject; - - /** - * The instance of the injector. - */ - objectInjector: Injector; - - detailElement: any; - - /** - * Initialize instance variables - * - * @param {Injector} injector - */ - constructor(private injector: Injector) { - } - - /** - * Initialize injector - */ - ngOnInit(): void { - this.objectInjector = Injector.create({ - providers: [{ provide: 'objectElementProvider', useFactory: () => (this.object), deps:[] }], - parent: this.injector - }); - this.detailElement = this.getDetailElement(); - } - - /** - * Return class name for the object to inject - */ - private getDetailElement(): string { - const f: GenericConstructor = this.object.constructor as GenericConstructor; - return rendersDSOType(f, SetViewMode.Detail); - } -} diff --git a/src/app/shared/object-grid/collection-grid-element/collection-grid-element.component.html b/src/app/shared/object-grid/collection-grid-element/collection-grid-element.component.html index 9fecb51b9a..0b1a85d0ef 100644 --- a/src/app/shared/object-grid/collection-grid-element/collection-grid-element.component.html +++ b/src/app/shared/object-grid/collection-grid-element/collection-grid-element.component.html @@ -1,14 +1,17 @@
- + + + + +

{{object.name}}

{{object.shortDescription}}

-
- View +
+ View
-
diff --git a/src/app/shared/object-grid/collection-grid-element/collection-grid-element.component.ts b/src/app/shared/object-grid/collection-grid-element/collection-grid-element.component.ts index af6027aa1a..6f8bf5264e 100644 --- a/src/app/shared/object-grid/collection-grid-element/collection-grid-element.component.ts +++ b/src/app/shared/object-grid/collection-grid-element/collection-grid-element.component.ts @@ -1,15 +1,18 @@ import { Component, Inject } from '@angular/core'; import { Collection } from '../../../core/shared/collection.model'; -import { renderElementsFor} from '../../object-collection/shared/dso-element-decorator'; -import { SetViewMode } from '../../view-mode'; import { AbstractListableElementComponent } from '../../object-collection/shared/object-collection-element/abstract-listable-element.component'; +import { ViewMode } from '../../../core/shared/view-mode.model'; +import { listableObjectComponent } from '../../object-collection/shared/listable-object/listable-object.decorator'; +/** + * Component representing a grid element for collection + */ @Component({ selector: 'ds-collection-grid-element', styleUrls: ['./collection-grid-element.component.scss'], templateUrl: './collection-grid-element.component.html' }) -@renderElementsFor(Collection, SetViewMode.Grid) +@listableObjectComponent(Collection, ViewMode.GridElement) export class CollectionGridElementComponent extends AbstractListableElementComponent {} diff --git a/src/app/shared/object-grid/community-grid-element/community-grid-element.component.html b/src/app/shared/object-grid/community-grid-element/community-grid-element.component.html index 31a9e8ad3d..eed29367fa 100644 --- a/src/app/shared/object-grid/community-grid-element/community-grid-element.component.html +++ b/src/app/shared/object-grid/community-grid-element/community-grid-element.component.html @@ -1,14 +1,17 @@
- - + + + + +

{{object.name}}

{{object.shortDescription}}

-
- View +
+ View
diff --git a/src/app/shared/object-grid/community-grid-element/community-grid-element.component.ts b/src/app/shared/object-grid/community-grid-element/community-grid-element.component.ts index 4f69e3e2c7..05c84b683b 100644 --- a/src/app/shared/object-grid/community-grid-element/community-grid-element.component.ts +++ b/src/app/shared/object-grid/community-grid-element/community-grid-element.component.ts @@ -1,15 +1,18 @@ -import { Component, Input, Inject } from '@angular/core'; +import { Component } from '@angular/core'; import { Community } from '../../../core/shared/community.model'; import { AbstractListableElementComponent } from '../../object-collection/shared/object-collection-element/abstract-listable-element.component'; -import { renderElementsFor} from '../../object-collection/shared/dso-element-decorator'; -import { SetViewMode } from '../../view-mode'; +import { ViewMode } from '../../../core/shared/view-mode.model'; +import { listableObjectComponent } from '../../object-collection/shared/listable-object/listable-object.decorator'; +/** + * Component representing a grid element for a community + */ @Component({ selector: 'ds-community-grid-element', styleUrls: ['./community-grid-element.component.scss'], templateUrl: './community-grid-element.component.html' }) -@renderElementsFor(Community, SetViewMode.Grid) +@listableObjectComponent(Community, ViewMode.GridElement) export class CommunityGridElementComponent extends AbstractListableElementComponent {} diff --git a/src/app/shared/object-grid/item-grid-element/item-grid-element.component.html b/src/app/shared/object-grid/item-grid-element/item-grid-element.component.html deleted file mode 100644 index 6bb2cfa99d..0000000000 --- a/src/app/shared/object-grid/item-grid-element/item-grid-element.component.html +++ /dev/null @@ -1,28 +0,0 @@ - -
- - - - -
-

{{object.firstMetadataValue('dc.title')}}

- - -

- {{author}} - ; - - {{object.firstMetadataValue("dc.date.issued")}} -

-
- - -

{{object.firstMetadataValue("dc.description.abstract")}}

-
- -
- View -
-
-
-
diff --git a/src/app/shared/object-grid/item-grid-element/item-grid-element.component.scss b/src/app/shared/object-grid/item-grid-element/item-grid-element.component.scss deleted file mode 100644 index 8b13789179..0000000000 --- a/src/app/shared/object-grid/item-grid-element/item-grid-element.component.scss +++ /dev/null @@ -1 +0,0 @@ - diff --git a/src/app/shared/object-grid/item-grid-element/item-grid-element.component.spec.ts b/src/app/shared/object-grid/item-grid-element/item-grid-element.component.spec.ts deleted file mode 100644 index 7b286cc415..0000000000 --- a/src/app/shared/object-grid/item-grid-element/item-grid-element.component.spec.ts +++ /dev/null @@ -1,114 +0,0 @@ -import { ItemGridElementComponent } from './item-grid-element.component'; -import { async, ComponentFixture, TestBed } from '@angular/core/testing'; -import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA } from '@angular/core'; -import { By } from '@angular/platform-browser'; -import { TruncatePipe } from '../../utils/truncate.pipe'; -import { Item } from '../../../core/shared/item.model'; -import { of as observableOf } from 'rxjs'; - -let itemGridElementComponent: ItemGridElementComponent; -let fixture: ComponentFixture; - -const mockItemWithAuthorAndDate: Item = Object.assign(new Item(), { - bitstreams: observableOf({}), - metadata: { - 'dc.contributor.author': [ - { - language: 'en_US', - value: 'Smith, Donald' - } - ], - 'dc.date.issued': [ - { - language: null, - value: '2015-06-26' - } - ] - } -}); -const mockItemWithoutAuthorAndDate: Item = Object.assign(new Item(), { - bitstreams: observableOf({}), - metadata: { - 'dc.title': [ - { - language: 'en_US', - value: 'This is just another title' - } - ], - 'dc.type': [ - { - language: null, - value: 'Article' - } - ] - } -}); - -describe('ItemGridElementComponent', () => { - beforeEach(async(() => { - TestBed.configureTestingModule({ - declarations: [ ItemGridElementComponent , TruncatePipe], - providers: [ - { provide: 'objectElementProvider', useValue: {mockItemWithAuthorAndDate}} - ], - - schemas: [ NO_ERRORS_SCHEMA ] - }).overrideComponent(ItemGridElementComponent, { - set: { changeDetection: ChangeDetectionStrategy.Default } - }).compileComponents(); - })); - - beforeEach(async(() => { - fixture = TestBed.createComponent(ItemGridElementComponent); - itemGridElementComponent = fixture.componentInstance; - - })); - - describe('When the item has an author', () => { - beforeEach(() => { - itemGridElementComponent.object = mockItemWithAuthorAndDate; - fixture.detectChanges(); - }); - - it('should show the author paragraph', () => { - const itemAuthorField = fixture.debugElement.query(By.css('p.item-authors')); - expect(itemAuthorField).not.toBeNull(); - }); - }); - - describe('When the item has no author', () => { - beforeEach(() => { - itemGridElementComponent.object = mockItemWithoutAuthorAndDate; - fixture.detectChanges(); - }); - - it('should not show the author paragraph', () => { - const itemAuthorField = fixture.debugElement.query(By.css('p.item-authors')); - expect(itemAuthorField).toBeNull(); - }); - }); - - describe('When the item has an issuedate', () => { - beforeEach(() => { - itemGridElementComponent.object = mockItemWithAuthorAndDate; - fixture.detectChanges(); - }); - - it('should show the issuedate span', () => { - const itemAuthorField = fixture.debugElement.query(By.css('span.item-date')); - expect(itemAuthorField).not.toBeNull(); - }); - }); - - describe('When the item has no issuedate', () => { - beforeEach(() => { - itemGridElementComponent.object = mockItemWithoutAuthorAndDate; - fixture.detectChanges(); - }); - - it('should not show the issuedate span', () => { - const dateField = fixture.debugElement.query(By.css('span.item-date')); - expect(dateField).toBeNull(); - }); - }); -}); diff --git a/src/app/shared/object-grid/item-grid-element/item-grid-element.component.ts b/src/app/shared/object-grid/item-grid-element/item-grid-element.component.ts deleted file mode 100644 index a4137b3c26..0000000000 --- a/src/app/shared/object-grid/item-grid-element/item-grid-element.component.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { Component, Input, Inject } from '@angular/core'; - -import { Item } from '../../../core/shared/item.model'; -import { renderElementsFor} from '../../object-collection/shared/dso-element-decorator'; -import { AbstractListableElementComponent } from '../../object-collection/shared/object-collection-element/abstract-listable-element.component'; -import { SetViewMode } from '../../view-mode'; - -@Component({ - selector: 'ds-item-grid-element', - styleUrls: ['./item-grid-element.component.scss'], - templateUrl: './item-grid-element.component.html' -}) - -@renderElementsFor(Item, SetViewMode.Grid) -export class ItemGridElementComponent extends AbstractListableElementComponent {} diff --git a/src/app/shared/object-grid/item-grid-element/item-types/publication/publication-grid-element.component.html b/src/app/shared/object-grid/item-grid-element/item-types/publication/publication-grid-element.component.html index e735dbf107..81ee3ebcce 100644 --- a/src/app/shared/object-grid/item-grid-element/item-types/publication/publication-grid-element.component.html +++ b/src/app/shared/object-grid/item-grid-element/item-types/publication/publication-grid-element.component.html @@ -1,34 +1 @@ - -
- -
- - -
-
-
- - -

-
-

- - {{dso.firstMetadataValue('dc.date.issued')}} - , - - - -

-

- - - -

-
- View -
-
-
-
+ diff --git a/src/app/shared/object-grid/item-grid-element/item-types/publication/publication-grid-element.component.spec.ts b/src/app/shared/object-grid/item-grid-element/item-types/publication/publication-grid-element.component.spec.ts index e0ba26fcfc..6171eb1e9d 100644 --- a/src/app/shared/object-grid/item-grid-element/item-types/publication/publication-grid-element.component.spec.ts +++ b/src/app/shared/object-grid/item-grid-element/item-types/publication/publication-grid-element.component.spec.ts @@ -1,4 +1,4 @@ -import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { async, TestBed } from '@angular/core/testing'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { TruncatePipe } from '../../../../utils/truncate.pipe'; import { TruncatableService } from '../../../../truncatable/truncatable.service'; @@ -6,16 +6,12 @@ import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA } from '@angular/core'; import { By } from '@angular/platform-browser'; import { PublicationGridElementComponent } from './publication-grid-element.component'; import { of as observableOf } from 'rxjs/internal/observable/of'; -import { ItemSearchResult } from '../../../../object-collection/shared/item-search-result.model'; import { Item } from '../../../../../core/shared/item.model'; -import { ITEM } from '../../../../items/switcher/item-type-switcher.component'; import { createSuccessfulRemoteDataObject$ } from '../../../../testing/utils'; import { PaginatedList } from '../../../../../core/data/paginated-list'; import { PageInfo } from '../../../../../core/shared/page-info.model'; -const mockItemWithMetadata: ItemSearchResult = new ItemSearchResult(); -mockItemWithMetadata.hitHighlights = {}; -mockItemWithMetadata.indexableObject = Object.assign(new Item(), { +const mockItem = Object.assign(new Item(), { bitstreams: createSuccessfulRemoteDataObject$(new PaginatedList(new PageInfo(), [])), metadata: { 'dc.title': [ @@ -45,83 +41,41 @@ mockItemWithMetadata.indexableObject = Object.assign(new Item(), { } }); -const mockItemWithoutMetadata: ItemSearchResult = new ItemSearchResult(); -mockItemWithoutMetadata.hitHighlights = {}; -mockItemWithoutMetadata.indexableObject = Object.assign(new Item(), { - bitstreams: createSuccessfulRemoteDataObject$(new PaginatedList(new PageInfo(), [])), - metadata: { - 'dc.title': [ - { - language: 'en_US', - value: 'This is just another title' - } - ] - } -}); +describe('PublicationGridElementComponent', () => { + let comp; + let fixture; -describe('PublicationGridElementComponent', getEntityGridElementTestComponent(PublicationGridElementComponent, mockItemWithMetadata, mockItemWithoutMetadata, ['authors', 'date', 'abstract'])); + const truncatableServiceStub: any = { + isCollapsed: (id: number) => observableOf(true), + }; -/** - * Create test cases for a grid component of an entity. - * @param component The component's class - * @param searchResultWithMetadata An ItemSearchResult containing an item with metadata that should be displayed in the grid element - * @param searchResultWithoutMetadata An ItemSearchResult containing an item that's missing the metadata that should be displayed in the grid element - * @param fieldsToCheck A list of fields to check. The tests expect to find html elements with class ".item-${field}", so make sure they exist in the html template of the grid element. - * For example: If one of the fields to check is labeled "authors", the html template should contain at least one element with class ".item-authors" that's - * present when the author metadata is available. - */ -export function getEntityGridElementTestComponent(component, searchResultWithMetadata: ItemSearchResult, searchResultWithoutMetadata: ItemSearchResult, fieldsToCheck: string[]) { - return () => { - let comp; - let fixture; + beforeEach(async(() => { + TestBed.configureTestingModule({ + imports: [NoopAnimationsModule], + declarations: [PublicationGridElementComponent, TruncatePipe], + providers: [ + { provide: TruncatableService, useValue: truncatableServiceStub }, + ], + schemas: [NO_ERRORS_SCHEMA] + }).overrideComponent(PublicationGridElementComponent, { + set: { changeDetection: ChangeDetectionStrategy.Default } + }).compileComponents(); + })); - const truncatableServiceStub: any = { - isCollapsed: (id: number) => observableOf(true), - }; + beforeEach(async(() => { + fixture = TestBed.createComponent(PublicationGridElementComponent); + comp = fixture.componentInstance; + })); - beforeEach(async(() => { - TestBed.configureTestingModule({ - imports: [NoopAnimationsModule], - declarations: [component, TruncatePipe], - providers: [ - { provide: TruncatableService, useValue: truncatableServiceStub }, - {provide: ITEM, useValue: searchResultWithoutMetadata} - ], - schemas: [NO_ERRORS_SCHEMA] - }).overrideComponent(component, { - set: { changeDetection: ChangeDetectionStrategy.Default } - }).compileComponents(); - })); - - beforeEach(async(() => { - fixture = TestBed.createComponent(component); - comp = fixture.componentInstance; - })); - - fieldsToCheck.forEach((field) => { - describe(`when the item has "${field}" metadata`, () => { - beforeEach(() => { - comp.dso = searchResultWithMetadata.indexableObject; - fixture.detectChanges(); - }); - - it(`should show the "${field}" field`, () => { - const itemAuthorField = fixture.debugElement.query(By.css(`.item-${field}`)); - expect(itemAuthorField).not.toBeNull(); - }); - }); - - describe(`when the item has no "${field}" metadata`, () => { - beforeEach(() => { - comp.dso = searchResultWithoutMetadata.indexableObject; - fixture.detectChanges(); - }); - - it(`should not show the "${field}" field`, () => { - const itemAuthorField = fixture.debugElement.query(By.css(`.item-${field}`)); - expect(itemAuthorField).toBeNull(); - }); - }); + describe(`when the publication is rendered`, () => { + beforeEach(() => { + comp.object = mockItem; + fixture.detectChanges(); }); - } -} + + it(`should contain a PublicationGridElementComponent`, () => { + const publicationGridElement = fixture.debugElement.query(By.css(`ds-publication-search-result-grid-element`)); + expect(publicationGridElement).not.toBeNull(); + }); + }); +}); diff --git a/src/app/shared/object-grid/item-grid-element/item-types/publication/publication-grid-element.component.ts b/src/app/shared/object-grid/item-grid-element/item-types/publication/publication-grid-element.component.ts index 1bcd028baf..8450150dcb 100644 --- a/src/app/shared/object-grid/item-grid-element/item-types/publication/publication-grid-element.component.ts +++ b/src/app/shared/object-grid/item-grid-element/item-types/publication/publication-grid-element.component.ts @@ -1,10 +1,12 @@ -import { TypedItemSearchResultGridElementComponent } from '../typed-item-search-result-grid-element.component'; -import { DEFAULT_ITEM_TYPE, ItemViewMode, rendersItemType } from '../../../../items/item-type-decorator'; import { Component } from '@angular/core'; import { focusShadow } from '../../../../animations/focus'; +import { ViewMode } from '../../../../../core/shared/view-mode.model'; +import { listableObjectComponent } from '../../../../object-collection/shared/listable-object/listable-object.decorator'; +import { AbstractListableElementComponent } from '../../../../object-collection/shared/object-collection-element/abstract-listable-element.component'; +import { Item } from '../../../../../core/shared/item.model'; -@rendersItemType('Publication', ItemViewMode.Card) -@rendersItemType(DEFAULT_ITEM_TYPE, ItemViewMode.Card) +@listableObjectComponent('Publication', ViewMode.GridElement) +@listableObjectComponent(Item, ViewMode.GridElement) @Component({ selector: 'ds-publication-grid-element', styleUrls: ['./publication-grid-element.component.scss'], @@ -14,5 +16,5 @@ import { focusShadow } from '../../../../animations/focus'; /** * The component for displaying a grid element for an item of the type Publication */ -export class PublicationGridElementComponent extends TypedItemSearchResultGridElementComponent { +export class PublicationGridElementComponent extends AbstractListableElementComponent { } diff --git a/src/app/shared/object-grid/item-grid-element/item-types/typed-item-search-result-grid-element.component.spec.ts b/src/app/shared/object-grid/item-grid-element/item-types/typed-item-search-result-grid-element.component.spec.ts deleted file mode 100644 index e4ace8d0b2..0000000000 --- a/src/app/shared/object-grid/item-grid-element/item-types/typed-item-search-result-grid-element.component.spec.ts +++ /dev/null @@ -1,83 +0,0 @@ -import { async, ComponentFixture, TestBed } from '@angular/core/testing'; -import { TruncatePipe } from '../../../utils/truncate.pipe'; -import { TruncatableService } from '../../../truncatable/truncatable.service'; -import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA } from '@angular/core'; -import { Item } from '../../../../core/shared/item.model'; -import { RemoteData } from '../../../../core/data/remote-data'; -import { PaginatedList } from '../../../../core/data/paginated-list'; -import { PageInfo } from '../../../../core/shared/page-info.model'; -import { ITEM } from '../../../items/switcher/item-type-switcher.component'; -import { ItemSearchResult } from '../../../object-collection/shared/item-search-result.model'; -import { createRelationshipsObservable } from '../../../../+item-page/simple/item-types/shared/item.component.spec'; -import { of as observableOf } from 'rxjs'; -import { MetadataMap } from '../../../../core/shared/metadata.models'; -import { TypedItemSearchResultGridElementComponent } from './typed-item-search-result-grid-element.component'; - -const mockItem: Item = Object.assign(new Item(), { - bitstreams: observableOf(new RemoteData(false, false, true, null, new PaginatedList(new PageInfo(), []))), - metadata: [], - relationships: createRelationshipsObservable() -}); -const mockSearchResult = { - indexableObject: mockItem as Item, - hitHighlights: new MetadataMap() -} as ItemSearchResult; - -describe('TypedItemSearchResultGridElementComponent', () => { - let comp: TypedItemSearchResultGridElementComponent; - let fixture: ComponentFixture; - - describe('when injecting an Item', () => { - beforeEach(async(() => { - TestBed.configureTestingModule({ - declarations: [TypedItemSearchResultGridElementComponent, TruncatePipe], - providers: [ - {provide: TruncatableService, useValue: {}}, - {provide: ITEM, useValue: mockItem} - ], - - schemas: [NO_ERRORS_SCHEMA] - }).overrideComponent(TypedItemSearchResultGridElementComponent, { - set: {changeDetection: ChangeDetectionStrategy.Default} - }).compileComponents(); - })); - - beforeEach(async(() => { - fixture = TestBed.createComponent(TypedItemSearchResultGridElementComponent); - comp = fixture.componentInstance; - })); - - it('should initiate item, object and dso correctly', () => { - expect(comp.item).toBe(mockItem); - expect(comp.dso).toBe(mockItem); - expect(comp.object.indexableObject).toBe(mockItem); - }) - }); - - describe('when injecting an ItemSearchResult', () => { - beforeEach(async(() => { - TestBed.configureTestingModule({ - declarations: [TypedItemSearchResultGridElementComponent, TruncatePipe], - providers: [ - {provide: TruncatableService, useValue: {}}, - {provide: ITEM, useValue: mockSearchResult} - ], - - schemas: [NO_ERRORS_SCHEMA] - }).overrideComponent(TypedItemSearchResultGridElementComponent, { - set: {changeDetection: ChangeDetectionStrategy.Default} - }).compileComponents(); - })); - - beforeEach(async(() => { - fixture = TestBed.createComponent(TypedItemSearchResultGridElementComponent); - comp = fixture.componentInstance; - })); - - it('should initiate item, object and dso correctly', () => { - expect(comp.item).toBe(mockItem); - expect(comp.dso).toBe(mockItem); - expect(comp.object.indexableObject).toBe(mockItem); - }) - }); -}); diff --git a/src/app/shared/object-grid/item-grid-element/item-types/typed-item-search-result-grid-element.component.ts b/src/app/shared/object-grid/item-grid-element/item-types/typed-item-search-result-grid-element.component.ts deleted file mode 100644 index f4f470c052..0000000000 --- a/src/app/shared/object-grid/item-grid-element/item-types/typed-item-search-result-grid-element.component.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { ItemSearchResult } from '../../../object-collection/shared/item-search-result.model'; -import { Item } from '../../../../core/shared/item.model'; -import { SearchResultGridElementComponent } from '../../search-result-grid-element/search-result-grid-element.component'; -import { TruncatableService } from '../../../truncatable/truncatable.service'; -import { Component, Inject } from '@angular/core'; -import { ITEM } from '../../../items/switcher/item-type-switcher.component'; -import { hasValue } from '../../../empty.util'; -import { MetadataMap } from '../../../../core/shared/metadata.models'; - -/** - * A generic component for displaying item grid elements - */ -@Component({ - selector: 'ds-item-search-result-grid-element', - template: '' -}) -export class TypedItemSearchResultGridElementComponent extends SearchResultGridElementComponent { - item: Item; - - constructor( - protected truncatableService: TruncatableService, - @Inject(ITEM) public obj: Item | ItemSearchResult, - ) { - super(undefined, truncatableService); - if (hasValue((obj as any).indexableObject)) { - this.object = obj as ItemSearchResult; - this.dso = this.object.indexableObject; - } else { - this.object = { - indexableObject: obj as Item, - hitHighlights: new MetadataMap() - }; - this.dso = obj as Item; - } - this.item = this.dso; - } -} diff --git a/src/app/shared/object-grid/object-grid.component.html b/src/app/shared/object-grid/object-grid.component.html index 9d1f8f5ea2..348536bfed 100644 --- a/src/app/shared/object-grid/object-grid.component.html +++ b/src/app/shared/object-grid/object-grid.component.html @@ -13,11 +13,11 @@
- +
- - + + diff --git a/src/app/shared/object-grid/object-grid.component.scss b/src/app/shared/object-grid/object-grid.component.scss index 8f19309d89..fb883a1f07 100644 --- a/src/app/shared/object-grid/object-grid.component.scss +++ b/src/app/shared/object-grid/object-grid.component.scss @@ -1,6 +1,6 @@ $ds-wrapper-grid-spacing: $spacer/2; -ds-wrapper-grid-element ::ng-deep { +:host ::ng-deep { div.thumbnail > img { height: $card-thumbnail-height; width: 100%; diff --git a/src/app/shared/object-grid/object-grid.component.ts b/src/app/shared/object-grid/object-grid.component.ts index e539ca5714..2da4abe13b 100644 --- a/src/app/shared/object-grid/object-grid.component.ts +++ b/src/app/shared/object-grid/object-grid.component.ts @@ -20,6 +20,9 @@ import { HostWindowService, WidthCategory } from '../host-window.service'; import { ListableObject } from '../object-collection/shared/listable-object.model'; import { PaginationComponentOptions } from '../pagination/pagination-component-options.model'; +import { ViewMode } from '../../core/shared/view-mode.model'; +import { Context } from '../../core/shared/context.model'; +import { CollectionElementLinkType } from '../object-collection/collection-element-link.type'; @Component({ changeDetection: ChangeDetectionStrategy.Default, @@ -31,17 +34,57 @@ import { PaginationComponentOptions } from '../pagination/pagination-component-o }) export class ObjectGridComponent implements OnInit { + /** + * The view mode of the this component + */ + viewMode = ViewMode.GridElement; + /** + * The current pagination configuration + */ @Input() config: PaginationComponentOptions; + + /** + * The current sort configuration + */ @Input() sortConfig: SortOptions; + + /** + * The whether or not the gear is hidden + */ @Input() hideGear = false; + + /** + * Whether or not the pager is visible when there is only a single page of results + */ @Input() hidePagerWhenSinglePage = true; + + /** + * The link type of the listable elements + */ + @Input() linkType: CollectionElementLinkType; + + /** + * The context of the listable elements + */ + @Input() context: Context; + + /** + * Behavior subject to output the current listable objects + */ private _objects$: BehaviorSubject>>; + /** + * Setter to make sure the observable is turned into an observable + * @param objects The new objects to output + */ @Input() set objects(objects: RemoteData>) { this._objects$.next(objects); } + /** + * Getter to return the current objects + */ get objects() { return this._objects$.getValue(); } @@ -76,7 +119,10 @@ export class ObjectGridComponent implements OnInit { */ @Output() sortDirectionChange: EventEmitter = new EventEmitter(); - @Output() paginationChange: EventEmitter = new EventEmitter(); + /** + * An event fired when on of the pagination parameters changes + */ + @Output() paginationChange: EventEmitter = new EventEmitter(); /** * An event fired when the sort field is changed. @@ -90,6 +136,9 @@ export class ObjectGridComponent implements OnInit { this._objects$ = new BehaviorSubject(undefined); } + /** + * Initialize the instance variables + */ ngOnInit(): void { const nbColumns$ = this.hostWindow.widthCategory.pipe( map((widthCat: WidthCategory) => { @@ -133,22 +182,40 @@ export class ObjectGridComponent implements OnInit { })); } + /** + * Emits the current page when it changes + * @param event The new page + */ onPageChange(event) { this.pageChange.emit(event); } - + /** + * Emits the current page size when it changes + * @param event The new page size + */ onPageSizeChange(event) { this.pageSizeChange.emit(event); } - + /** + * Emits the current sort direction when it changes + * @param event The new sort direction + */ onSortDirectionChange(event) { this.sortDirectionChange.emit(event); } + /** + * Emits the current sort field when it changes + * @param event The new sort field + */ onSortFieldChange(event) { this.sortFieldChange.emit(event); } + /** + * Emits the current pagination when it changes + * @param event The new pagination + */ onPaginationChange(event) { this.paginationChange.emit(event); } diff --git a/src/app/shared/object-grid/search-result-grid-element/collection-search-result/collection-search-result-grid-element.component.html b/src/app/shared/object-grid/search-result-grid-element/collection-search-result/collection-search-result-grid-element.component.html index 91548d945d..0c45316e30 100644 --- a/src/app/shared/object-grid/search-result-grid-element/collection-search-result/collection-search-result-grid-element.component.html +++ b/src/app/shared/object-grid/search-result-grid-element/collection-search-result/collection-search-result-grid-element.component.html @@ -1,13 +1,17 @@
- + + + + +

{{dso.name}}

{{dso.shortDescription}}

-
- View +
+ View
diff --git a/src/app/shared/object-grid/search-result-grid-element/collection-search-result/collection-search-result-grid-element.component.ts b/src/app/shared/object-grid/search-result-grid-element/collection-search-result/collection-search-result-grid-element.component.ts index 61cc5dca1c..a834327736 100644 --- a/src/app/shared/object-grid/search-result-grid-element/collection-search-result/collection-search-result-grid-element.component.ts +++ b/src/app/shared/object-grid/search-result-grid-element/collection-search-result/collection-search-result-grid-element.component.ts @@ -1,16 +1,18 @@ import { Component } from '@angular/core'; -import { renderElementsFor} from '../../../object-collection/shared/dso-element-decorator'; import { SearchResultGridElementComponent } from '../search-result-grid-element.component'; import { Collection } from '../../../../core/shared/collection.model'; -import { SetViewMode } from '../../../view-mode'; import { CollectionSearchResult } from '../../../object-collection/shared/collection-search-result.model'; +import { ViewMode } from '../../../../core/shared/view-mode.model'; +import { listableObjectComponent } from '../../../object-collection/shared/listable-object/listable-object.decorator'; @Component({ selector: 'ds-collection-search-result-grid-element', styleUrls: ['../search-result-grid-element.component.scss', 'collection-search-result-grid-element.component.scss'], templateUrl: 'collection-search-result-grid-element.component.html' }) - -@renderElementsFor(CollectionSearchResult, SetViewMode.Grid) +/** + * Component representing a grid element for a collection search result + */ +@listableObjectComponent(CollectionSearchResult, ViewMode.GridElement) export class CollectionSearchResultGridElementComponent extends SearchResultGridElementComponent {} diff --git a/src/app/shared/object-grid/search-result-grid-element/community-search-result/community-search-result-grid-element.component.html b/src/app/shared/object-grid/search-result-grid-element/community-search-result/community-search-result-grid-element.component.html index 95094a6fa1..d0a9aa700e 100644 --- a/src/app/shared/object-grid/search-result-grid-element/community-search-result/community-search-result-grid-element.component.html +++ b/src/app/shared/object-grid/search-result-grid-element/community-search-result/community-search-result-grid-element.component.html @@ -1,14 +1,17 @@
- - + + + + +

{{dso.name}}

{{dso.shortDescription}}

-
- View +
+ View
diff --git a/src/app/shared/object-grid/search-result-grid-element/community-search-result/community-search-result-grid-element.component.ts b/src/app/shared/object-grid/search-result-grid-element/community-search-result/community-search-result-grid-element.component.ts index d445e27ed6..e726c3e803 100644 --- a/src/app/shared/object-grid/search-result-grid-element/community-search-result/community-search-result-grid-element.component.ts +++ b/src/app/shared/object-grid/search-result-grid-element/community-search-result/community-search-result-grid-element.component.ts @@ -1,17 +1,18 @@ import { Component } from '@angular/core'; import { Community } from '../../../../core/shared/community.model'; -import { renderElementsFor } from '../../../object-collection/shared/dso-element-decorator'; import { SearchResultGridElementComponent } from '../search-result-grid-element.component'; -import { SetViewMode } from '../../../view-mode'; import { CommunitySearchResult } from '../../../object-collection/shared/community-search-result.model'; +import { ViewMode } from '../../../../core/shared/view-mode.model'; +import { listableObjectComponent } from '../../../object-collection/shared/listable-object/listable-object.decorator'; @Component({ selector: 'ds-community-search-result-grid-element', styleUrls: ['../search-result-grid-element.component.scss', 'community-search-result-grid-element.component.scss'], templateUrl: 'community-search-result-grid-element.component.html' }) - -@renderElementsFor(CommunitySearchResult, SetViewMode.Grid) +/** + * Component representing a grid element for a community search result + */ +@listableObjectComponent(CommunitySearchResult, ViewMode.GridElement) export class CommunitySearchResultGridElementComponent extends SearchResultGridElementComponent { - } diff --git a/src/app/shared/object-grid/search-result-grid-element/item-search-result/item-search-result-grid-element.component.html b/src/app/shared/object-grid/search-result-grid-element/item-search-result/item-search-result-grid-element.component.html deleted file mode 100644 index d433c7acf2..0000000000 --- a/src/app/shared/object-grid/search-result-grid-element/item-search-result/item-search-result-grid-element.component.html +++ /dev/null @@ -1 +0,0 @@ - diff --git a/src/app/shared/object-grid/search-result-grid-element/item-search-result/item-search-result-grid-element.component.scss b/src/app/shared/object-grid/search-result-grid-element/item-search-result/item-search-result-grid-element.component.scss deleted file mode 100644 index d61f3ccf55..0000000000 --- a/src/app/shared/object-grid/search-result-grid-element/item-search-result/item-search-result-grid-element.component.scss +++ /dev/null @@ -1,12 +0,0 @@ -.card { - a > div { - position: relative; - .thumbnail-overlay { - height: 100%; - position: absolute; - top: 0; - width: 100%; - background-color: map-get($theme-colors, primary); - } - } -} diff --git a/src/app/shared/object-grid/search-result-grid-element/item-search-result/item-search-result-grid-element.component.spec.ts b/src/app/shared/object-grid/search-result-grid-element/item-search-result/item-search-result-grid-element.component.spec.ts deleted file mode 100644 index 282478ec33..0000000000 --- a/src/app/shared/object-grid/search-result-grid-element/item-search-result/item-search-result-grid-element.component.spec.ts +++ /dev/null @@ -1,61 +0,0 @@ -import { ItemSearchResultGridElementComponent } from './item-search-result-grid-element.component'; -import { async, ComponentFixture, TestBed } from '@angular/core/testing'; -import { of as observableOf } from 'rxjs'; -import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA } from '@angular/core'; -import { By } from '@angular/platform-browser'; -import { TruncatePipe } from '../../../utils/truncate.pipe'; -import { Item } from '../../../../core/shared/item.model'; -import { TruncatableService } from '../../../truncatable/truncatable.service'; -import { NoopAnimationsModule } from '@angular/platform-browser/animations'; -import { ItemSearchResult } from '../../../object-collection/shared/item-search-result.model'; -import { ItemViewMode } from '../../../items/item-type-decorator'; - -let itemSearchResultGridElementComponent: ItemSearchResultGridElementComponent; -let fixture: ComponentFixture; - -const truncatableServiceStub: any = { - isCollapsed: (id: number) => observableOf(true), -}; - -const type = 'authorOfPublication'; - -const mockItemWithRelationshipType: ItemSearchResult = new ItemSearchResult(); -mockItemWithRelationshipType.hitHighlights = {}; -mockItemWithRelationshipType.indexableObject = Object.assign(new Item(), { - bitstreams: observableOf({}), - metadata: { - 'relationship.type': [ - { - language: 'en_US', - value: type - } - ] - } -}); - -describe('ItemSearchResultGridElementComponent', () => { - beforeEach(async(() => { - TestBed.configureTestingModule({ - imports: [NoopAnimationsModule], - declarations: [ItemSearchResultGridElementComponent, TruncatePipe], - providers: [ - { provide: TruncatableService, useValue: truncatableServiceStub }, - { provide: 'objectElementProvider', useValue: (mockItemWithRelationshipType) } - ], - schemas: [NO_ERRORS_SCHEMA] - }).overrideComponent(ItemSearchResultGridElementComponent, { - set: { changeDetection: ChangeDetectionStrategy.Default } - }).compileComponents(); - })); - - beforeEach(async(() => { - fixture = TestBed.createComponent(ItemSearchResultGridElementComponent); - itemSearchResultGridElementComponent = fixture.componentInstance; - })); - - it('should show send the object to item-type-switcher using viewMode "Card"', () => { - const itemTypeSwitcherComp = fixture.debugElement.query(By.css('ds-item-type-switcher')).componentInstance; - expect(itemTypeSwitcherComp.object).toBe(mockItemWithRelationshipType); - expect(itemTypeSwitcherComp.viewMode).toEqual(ItemViewMode.Card); - }); -}); diff --git a/src/app/shared/object-grid/search-result-grid-element/item-search-result/item-search-result-grid-element.component.ts b/src/app/shared/object-grid/search-result-grid-element/item-search-result/item-search-result-grid-element.component.ts deleted file mode 100644 index 7bbe41fe60..0000000000 --- a/src/app/shared/object-grid/search-result-grid-element/item-search-result/item-search-result-grid-element.component.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { Component } from '@angular/core'; - -import { renderElementsFor } from '../../../object-collection/shared/dso-element-decorator'; -import { SearchResultGridElementComponent } from '../search-result-grid-element.component'; -import { Item } from '../../../../core/shared/item.model'; -import { ItemSearchResult } from '../../../object-collection/shared/item-search-result.model'; -import { SetViewMode } from '../../../view-mode'; -import { focusShadow } from '../../../../shared/animations/focus'; -import { ItemViewMode } from '../../../items/item-type-decorator'; - -@Component({ - selector: 'ds-item-search-result-grid-element', - styleUrls: ['../search-result-grid-element.component.scss', 'item-search-result-grid-element.component.scss'], - templateUrl: 'item-search-result-grid-element.component.html', - animations: [focusShadow], -}) - -@renderElementsFor(ItemSearchResult, SetViewMode.Grid) -export class ItemSearchResultGridElementComponent extends SearchResultGridElementComponent { - viewMode = ItemViewMode.Card; -} diff --git a/src/app/shared/object-grid/search-result-grid-element/item-search-result/publication/publication-search-result-grid-element.component.html b/src/app/shared/object-grid/search-result-grid-element/item-search-result/publication/publication-search-result-grid-element.component.html new file mode 100644 index 0000000000..a00e30cbcd --- /dev/null +++ b/src/app/shared/object-grid/search-result-grid-element/item-search-result/publication/publication-search-result-grid-element.component.html @@ -0,0 +1,41 @@ + +
+ +
+ + +
+
+ +
+ + +
+
+
+ + +

+
+

+ + {{firstMetadataValue('dc.date.issued')}} + , + + + +

+

+ + + +

+
+ View +
+
+
+
diff --git a/src/app/shared/object-grid/search-result-grid-element/item-search-result/publication/publication-search-result-grid-element.component.scss b/src/app/shared/object-grid/search-result-grid-element/item-search-result/publication/publication-search-result-grid-element.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/shared/object-grid/search-result-grid-element/item-search-result/publication/publication-search-result-grid-element.component.spec.ts b/src/app/shared/object-grid/search-result-grid-element/item-search-result/publication/publication-search-result-grid-element.component.spec.ts new file mode 100644 index 0000000000..30bb2c9262 --- /dev/null +++ b/src/app/shared/object-grid/search-result-grid-element/item-search-result/publication/publication-search-result-grid-element.component.spec.ts @@ -0,0 +1,125 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { NoopAnimationsModule } from '@angular/platform-browser/animations'; +import { TruncatePipe } from '../../../../utils/truncate.pipe'; +import { TruncatableService } from '../../../../truncatable/truncatable.service'; +import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA } from '@angular/core'; +import { By } from '@angular/platform-browser'; +import { of as observableOf } from 'rxjs/internal/observable/of'; +import { ItemSearchResult } from '../../../../object-collection/shared/item-search-result.model'; +import { Item } from '../../../../../core/shared/item.model'; +import { createSuccessfulRemoteDataObject$ } from '../../../../testing/utils'; +import { PaginatedList } from '../../../../../core/data/paginated-list'; +import { PageInfo } from '../../../../../core/shared/page-info.model'; +import { PublicationSearchResultGridElementComponent } from './publication-search-result-grid-element.component'; + +const mockItemWithMetadata: ItemSearchResult = new ItemSearchResult(); +mockItemWithMetadata.hitHighlights = {}; +mockItemWithMetadata.indexableObject = Object.assign(new Item(), { + bitstreams: createSuccessfulRemoteDataObject$(new PaginatedList(new PageInfo(), [])), + metadata: { + 'dc.title': [ + { + language: 'en_US', + value: 'This is just another title' + } + ], + 'dc.contributor.author': [ + { + language: 'en_US', + value: 'Smith, Donald' + } + ], + 'dc.date.issued': [ + { + language: null, + value: '2015-06-26' + } + ], + 'dc.description.abstract': [ + { + language: 'en_US', + value: 'This is an abstract' + } + ] + } +}); + +const mockItemWithoutMetadata: ItemSearchResult = new ItemSearchResult(); +mockItemWithoutMetadata.hitHighlights = {}; +mockItemWithoutMetadata.indexableObject = Object.assign(new Item(), { + bitstreams: createSuccessfulRemoteDataObject$(new PaginatedList(new PageInfo(), [])), + metadata: { + 'dc.title': [ + { + language: 'en_US', + value: 'This is just another title' + } + ] + } +}); + +describe('PublicationGridElementComponent', getEntityGridElementTestComponent(PublicationSearchResultGridElementComponent, mockItemWithMetadata, mockItemWithoutMetadata, ['authors', 'date', 'abstract'])); + +/** + * Create test cases for a grid component of an entity. + * @param component The component's class + * @param searchResultWithMetadata An ItemSearchResult containing an item with metadata that should be displayed in the grid element + * @param searchResultWithoutMetadata An ItemSearchResult containing an item that's missing the metadata that should be displayed in the grid element + * @param fieldsToCheck A list of fields to check. The tests expect to find html elements with class ".item-${field}", so make sure they exist in the html template of the grid element. + * For example: If one of the fields to check is labeled "authors", the html template should contain at least one element with class ".item-authors" that's + * present when the author metadata is available. + */ +export function getEntityGridElementTestComponent(component, searchResultWithMetadata: ItemSearchResult, searchResultWithoutMetadata: ItemSearchResult, fieldsToCheck: string[]) { + return () => { + let comp; + let fixture; + + const truncatableServiceStub: any = { + isCollapsed: (id: number) => observableOf(true), + }; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + imports: [NoopAnimationsModule], + declarations: [component, TruncatePipe], + providers: [ + { provide: TruncatableService, useValue: truncatableServiceStub }, + ], + schemas: [NO_ERRORS_SCHEMA] + }).overrideComponent(component, { + set: { changeDetection: ChangeDetectionStrategy.Default } + }).compileComponents(); + })); + + beforeEach(async(() => { + fixture = TestBed.createComponent(component); + comp = fixture.componentInstance; + })); + + fieldsToCheck.forEach((field) => { + describe(`when the item has "${field}" metadata`, () => { + beforeEach(() => { + comp.object = searchResultWithMetadata; + fixture.detectChanges(); + }); + + it(`should show the "${field}" field`, () => { + const itemAuthorField = fixture.debugElement.query(By.css(`.item-${field}`)); + expect(itemAuthorField).not.toBeNull(); + }); + }); + + describe(`when the item has no "${field}" metadata`, () => { + beforeEach(() => { + comp.object = searchResultWithoutMetadata; + fixture.detectChanges(); + }); + + it(`should not show the "${field}" field`, () => { + const itemAuthorField = fixture.debugElement.query(By.css(`.item-${field}`)); + expect(itemAuthorField).toBeNull(); + }); + }); + }); + } +} diff --git a/src/app/shared/object-grid/search-result-grid-element/item-search-result/publication/publication-search-result-grid-element.component.ts b/src/app/shared/object-grid/search-result-grid-element/item-search-result/publication/publication-search-result-grid-element.component.ts new file mode 100644 index 0000000000..76618f18f2 --- /dev/null +++ b/src/app/shared/object-grid/search-result-grid-element/item-search-result/publication/publication-search-result-grid-element.component.ts @@ -0,0 +1,20 @@ +import { Component } from '@angular/core'; +import { focusShadow } from '../../../../animations/focus'; +import { ViewMode } from '../../../../../core/shared/view-mode.model'; +import { listableObjectComponent } from '../../../../object-collection/shared/listable-object/listable-object.decorator'; +import { SearchResultGridElementComponent } from '../../search-result-grid-element.component'; +import { Item } from '../../../../../core/shared/item.model'; +import { ItemSearchResult } from '../../../../object-collection/shared/item-search-result.model'; + +@listableObjectComponent('PublicationSearchResult', ViewMode.GridElement) +@Component({ + selector: 'ds-publication-search-result-grid-element', + styleUrls: ['./publication-search-result-grid-element.component.scss'], + templateUrl: './publication-search-result-grid-element.component.html', + animations: [focusShadow] +}) +/** + * The component for displaying a grid element for an item search result of the type Publication + */ +export class PublicationSearchResultGridElementComponent extends SearchResultGridElementComponent { +} diff --git a/src/app/shared/object-grid/search-result-grid-element/search-result-grid-element.component.ts b/src/app/shared/object-grid/search-result-grid-element/search-result-grid-element.component.ts index 63b2536043..75345338e7 100644 --- a/src/app/shared/object-grid/search-result-grid-element/search-result-grid-element.component.ts +++ b/src/app/shared/object-grid/search-result-grid-element/search-result-grid-element.component.ts @@ -1,9 +1,8 @@ -import { Component, Inject } from '@angular/core'; +import { Component, Inject, OnInit } from '@angular/core'; import { SearchResult } from '../../../+search-page/search-result.model'; import { DSpaceObject } from '../../../core/shared/dspace-object.model'; import { AbstractListableElementComponent } from '../../object-collection/shared/object-collection-element/abstract-listable-element.component'; -import { ListableObject } from '../../object-collection/shared/listable-object.model'; import { TruncatableService } from '../../truncatable/truncatable.service'; import { Observable } from 'rxjs'; import { Metadata } from '../../../core/shared/metadata.utils'; @@ -14,15 +13,30 @@ import { hasValue } from '../../empty.util'; template: `` }) -export class SearchResultGridElementComponent, K extends DSpaceObject> extends AbstractListableElementComponent { +export class SearchResultGridElementComponent, K extends DSpaceObject> extends AbstractListableElementComponent implements OnInit { + /** + * The DSpaceObject of the search result + */ dso: K; + + /** + * Whether or not the grid element is currently collapsed + */ isCollapsed$: Observable; - public constructor(@Inject('objectElementProvider') public listableObject: ListableObject, protected truncatableService: TruncatableService) { - super(listableObject); + public constructor(protected truncatableService: TruncatableService) { + super(); + if (hasValue(this.object)) { + this.isCollapsed$ = this.isCollapsed(); + } + } + + /** + * Retrieve the dso from the search result + */ + ngOnInit(): void { if (hasValue(this.object)) { this.dso = this.object.indexableObject; - this.isCollapsed$ = this.isCollapsed(); } } @@ -49,5 +63,4 @@ export class SearchResultGridElementComponent, K exten private isCollapsed(): Observable { return this.truncatableService.isCollapsed(this.dso.id); } - } diff --git a/src/app/shared/object-grid/wrapper-grid-element/wrapper-grid-element.component.html b/src/app/shared/object-grid/wrapper-grid-element/wrapper-grid-element.component.html deleted file mode 100644 index d6fd1cf9aa..0000000000 --- a/src/app/shared/object-grid/wrapper-grid-element/wrapper-grid-element.component.html +++ /dev/null @@ -1 +0,0 @@ - diff --git a/src/app/shared/object-grid/wrapper-grid-element/wrapper-grid-element.component.scss b/src/app/shared/object-grid/wrapper-grid-element/wrapper-grid-element.component.scss deleted file mode 100644 index 8b13789179..0000000000 --- a/src/app/shared/object-grid/wrapper-grid-element/wrapper-grid-element.component.scss +++ /dev/null @@ -1 +0,0 @@ - diff --git a/src/app/shared/object-grid/wrapper-grid-element/wrapper-grid-element.component.spec.ts b/src/app/shared/object-grid/wrapper-grid-element/wrapper-grid-element.component.spec.ts deleted file mode 100644 index 0a78c97209..0000000000 --- a/src/app/shared/object-grid/wrapper-grid-element/wrapper-grid-element.component.spec.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { WrapperGridElementComponent } from './wrapper-grid-element.component'; -import { async, ComponentFixture, TestBed } from '@angular/core/testing'; -import { of as observableOf } from 'rxjs'; -import { ActivatedRoute, Router } from '@angular/router'; -import { RouterStub } from '../../testing/router-stub'; -import { NO_ERRORS_SCHEMA } from '@angular/core'; -import { By } from '@angular/platform-browser'; - -let wrapperGridElementComponent: WrapperGridElementComponent; -let fixture: ComponentFixture; -const queryParam = 'test query'; -const scopeParam = '7669c72a-3f2a-451f-a3b9-9210e7a4c02f'; -const activatedRouteStub = { - queryParams: observableOf({ - query: queryParam, - scope: scopeParam - }) -}; - -describe('WrapperGridElementComponent', () => { - beforeEach(async(() => { - TestBed.configureTestingModule({ - declarations: [ WrapperGridElementComponent ], - providers: [ - { provide: ActivatedRoute, useValue: activatedRouteStub }, - { provide: Router, useClass: RouterStub }, - { provide: 'objectElementProvider', useFactory: (wrapperGridElementComponent)} - ], - - schemas: [ NO_ERRORS_SCHEMA ] - }).compileComponents(); // compile template and css - })); - - beforeEach(async(() => { - fixture = TestBed.createComponent(WrapperGridElementComponent); - wrapperGridElementComponent = fixture.componentInstance; - - })); - - it('should show the wrapper element containing the cards',() => { - expect(fixture.debugElement.query(By.css('ds-collection-grid-element'))).toBeDefined(); - }) -}) diff --git a/src/app/shared/object-grid/wrapper-grid-element/wrapper-grid-element.component.ts b/src/app/shared/object-grid/wrapper-grid-element/wrapper-grid-element.component.ts deleted file mode 100644 index 0a7312484f..0000000000 --- a/src/app/shared/object-grid/wrapper-grid-element/wrapper-grid-element.component.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { Component, Injector, Input, OnInit } from '@angular/core'; -import { SetViewMode } from '../../view-mode'; -import { GenericConstructor } from '../../../core/shared/generic-constructor'; -import { rendersDSOType } from '../../object-collection/shared/dso-element-decorator'; -import { ListableObject } from '../../object-collection/shared/listable-object.model'; - -@Component({ - selector: 'ds-wrapper-grid-element', - styleUrls: ['./wrapper-grid-element.component.scss'], - templateUrl: './wrapper-grid-element.component.html' -}) -export class WrapperGridElementComponent implements OnInit { - @Input() object: ListableObject; - objectInjector: Injector; - gridElement: any; - - constructor(private injector: Injector) { - } - - ngOnInit(): void { - this.objectInjector = Injector.create({ - providers: [{ provide: 'objectElementProvider', useFactory: () => (this.object), deps:[] }], - parent: this.injector - }); - this.gridElement = this.getGridElement(); - } - - getGridElement(): string { - const f: GenericConstructor = this.object.constructor as GenericConstructor; - return rendersDSOType(f, SetViewMode.Grid); - } -} diff --git a/src/app/shared/object-list/browse-entry-list-element/browse-entry-list-element.component.html b/src/app/shared/object-list/browse-entry-list-element/browse-entry-list-element.component.html index 0fad726777..e3455bf095 100644 --- a/src/app/shared/object-list/browse-entry-list-element/browse-entry-list-element.component.html +++ b/src/app/shared/object-list/browse-entry-list-element/browse-entry-list-element.component.html @@ -1,7 +1,10 @@
- - {{object.value}} - -   - {{object.count}} + + {{object.value}} + + + {{object.value}} + +   + {{object.count}}
diff --git a/src/app/shared/object-list/browse-entry-list-element/browse-entry-list-element.component.ts b/src/app/shared/object-list/browse-entry-list-element/browse-entry-list-element.component.ts index a32cfb333e..3c1ef298a8 100644 --- a/src/app/shared/object-list/browse-entry-list-element/browse-entry-list-element.component.ts +++ b/src/app/shared/object-list/browse-entry-list-element/browse-entry-list-element.component.ts @@ -1,10 +1,10 @@ import { Component, Input, Inject } from '@angular/core'; import { AbstractListableElementComponent } from '../../object-collection/shared/object-collection-element/abstract-listable-element.component'; -import { renderElementsFor } from '../../object-collection/shared/dso-element-decorator'; import { BrowseEntry } from '../../../core/shared/browse-entry.model'; import { ViewMode } from '../../../core/shared/view-mode.model'; -import { SetViewMode } from '../../view-mode'; +import { listableObjectComponent } from '../../object-collection/shared/listable-object/listable-object.decorator'; +import { Collection } from '../../../core/shared/collection.model'; @Component({ selector: 'ds-browse-entry-list-element', @@ -15,5 +15,5 @@ import { SetViewMode } from '../../view-mode'; /** * This component is automatically used to create a list view for BrowseEntry objects when used in ObjectCollectionComponent */ -@renderElementsFor(BrowseEntry, SetViewMode.List) +@listableObjectComponent(BrowseEntry, ViewMode.ListElement) export class BrowseEntryListElementComponent extends AbstractListableElementComponent {} diff --git a/src/app/shared/object-list/collection-list-element/collection-list-element.component.html b/src/app/shared/object-list/collection-list-element/collection-list-element.component.html index dec2794dca..c61adf5dad 100644 --- a/src/app/shared/object-list/collection-list-element/collection-list-element.component.html +++ b/src/app/shared/object-list/collection-list-element/collection-list-element.component.html @@ -1,6 +1,9 @@ - + {{object.name}} + + {{object.name}} +
{{object.shortDescription}}
diff --git a/src/app/shared/object-list/collection-list-element/collection-list-element.component.ts b/src/app/shared/object-list/collection-list-element/collection-list-element.component.ts index 3fe64f5bb9..48bd6697a0 100644 --- a/src/app/shared/object-list/collection-list-element/collection-list-element.component.ts +++ b/src/app/shared/object-list/collection-list-element/collection-list-element.component.ts @@ -1,15 +1,17 @@ import { Component, Inject } from '@angular/core'; import { Collection } from '../../../core/shared/collection.model'; -import { renderElementsFor } from '../../object-collection/shared/dso-element-decorator'; -import { SetViewMode } from '../../view-mode'; import { AbstractListableElementComponent } from '../../object-collection/shared/object-collection-element/abstract-listable-element.component'; +import { ViewMode } from '../../../core/shared/view-mode.model'; +import { listableObjectComponent } from '../../object-collection/shared/listable-object/listable-object.decorator'; @Component({ selector: 'ds-collection-list-element', styleUrls: ['./collection-list-element.component.scss'], templateUrl: './collection-list-element.component.html' }) - -@renderElementsFor(Collection, SetViewMode.List) +/** + * Component representing list element for a collection + */ +@listableObjectComponent(Collection, ViewMode.ListElement) export class CollectionListElementComponent extends AbstractListableElementComponent {} diff --git a/src/app/shared/object-list/community-list-element/community-list-element.component.html b/src/app/shared/object-list/community-list-element/community-list-element.component.html index 7582680fb2..af01999ca7 100644 --- a/src/app/shared/object-list/community-list-element/community-list-element.component.html +++ b/src/app/shared/object-list/community-list-element/community-list-element.component.html @@ -1,6 +1,9 @@ - + {{object.name}} + + {{object.name}} +
{{object.shortDescription}}
diff --git a/src/app/shared/object-list/community-list-element/community-list-element.component.ts b/src/app/shared/object-list/community-list-element/community-list-element.component.ts index 5e254cb1ac..aa583378de 100644 --- a/src/app/shared/object-list/community-list-element/community-list-element.component.ts +++ b/src/app/shared/object-list/community-list-element/community-list-element.component.ts @@ -2,14 +2,16 @@ import { Component, Input, Inject } from '@angular/core'; import { Community } from '../../../core/shared/community.model'; import { AbstractListableElementComponent } from '../../object-collection/shared/object-collection-element/abstract-listable-element.component'; -import { renderElementsFor } from '../../object-collection/shared/dso-element-decorator'; -import { SetViewMode } from '../../view-mode'; +import { ViewMode } from '../../../core/shared/view-mode.model'; +import { listableObjectComponent } from '../../object-collection/shared/listable-object/listable-object.decorator'; @Component({ selector: 'ds-community-list-element', styleUrls: ['./community-list-element.component.scss'], templateUrl: './community-list-element.component.html' }) - -@renderElementsFor(Community, SetViewMode.List) +/** + * Component representing a list element for a community + */ +@listableObjectComponent(Community, ViewMode.ListElement) export class CommunityListElementComponent extends AbstractListableElementComponent {} diff --git a/src/app/shared/object-list/item-list-element/item-list-element.component.html b/src/app/shared/object-list/item-list-element/item-list-element.component.html deleted file mode 100644 index d433c7acf2..0000000000 --- a/src/app/shared/object-list/item-list-element/item-list-element.component.html +++ /dev/null @@ -1 +0,0 @@ - diff --git a/src/app/shared/object-list/item-list-element/item-list-element.component.spec.ts b/src/app/shared/object-list/item-list-element/item-list-element.component.spec.ts deleted file mode 100644 index 2c0c8b0aa2..0000000000 --- a/src/app/shared/object-list/item-list-element/item-list-element.component.spec.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { async, ComponentFixture, TestBed } from '@angular/core/testing'; -import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA } from '@angular/core'; -import { ItemListElementComponent } from './item-list-element.component'; -import { Item } from '../../../core/shared/item.model'; -import { RemoteData } from '../../../core/data/remote-data'; -import { PaginatedList } from '../../../core/data/paginated-list'; -import { PageInfo } from '../../../core/shared/page-info.model'; -import { By } from '@angular/platform-browser'; -import { createRelationshipsObservable } from '../../../+item-page/simple/item-types/shared/item.component.spec'; -import { of as observableOf } from 'rxjs'; -import { createSuccessfulRemoteDataObject$ } from '../../testing/utils'; - -const mockItem: Item = Object.assign(new Item(), { - bitstreams: createSuccessfulRemoteDataObject$(new PaginatedList(new PageInfo(), [])), - metadata: [], - relationships: createRelationshipsObservable() -}); - -describe('ItemListElementComponent', () => { - let comp: ItemListElementComponent; - let fixture: ComponentFixture; - - beforeEach(async(() => { - TestBed.configureTestingModule({ - imports: [], - declarations: [ItemListElementComponent], - providers: [ - { provide: 'objectElementProvider', useValue: mockItem } - ], - schemas: [NO_ERRORS_SCHEMA] - }).overrideComponent(ItemListElementComponent, { - set: {changeDetection: ChangeDetectionStrategy.Default} - }).compileComponents(); - })); - - beforeEach(async(() => { - fixture = TestBed.createComponent(ItemListElementComponent); - comp = fixture.componentInstance; - fixture.detectChanges(); - })); - - it('should call an item-type-switcher component and pass the item', () => { - const itemTypeSwitcher = fixture.debugElement.query(By.css('ds-item-type-switcher')).componentInstance; - expect(itemTypeSwitcher.object).toBe(mockItem); - }); - -}); diff --git a/src/app/shared/object-list/item-list-element/item-list-element.component.ts b/src/app/shared/object-list/item-list-element/item-list-element.component.ts deleted file mode 100644 index 67a6256d43..0000000000 --- a/src/app/shared/object-list/item-list-element/item-list-element.component.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { Component } from '@angular/core'; - -import { Item } from '../../../core/shared/item.model'; -import { renderElementsFor } from '../../object-collection/shared/dso-element-decorator'; -import { AbstractListableElementComponent } from '../../object-collection/shared/object-collection-element/abstract-listable-element.component'; -import { SetViewMode } from '../../view-mode'; -import { ItemViewMode } from '../../items/item-type-decorator'; - -@Component({ - selector: 'ds-item-list-element', - styleUrls: ['./item-list-element.component.scss'], - templateUrl: './item-list-element.component.html' -}) - -/** - * The component used to list items depending on type - * Uses item-type-switcher to determine which components to use for displaying the list - */ -@renderElementsFor(Item, SetViewMode.List) -export class ItemListElementComponent extends AbstractListableElementComponent { - viewMode = ItemViewMode.Element; -} diff --git a/src/app/shared/object-list/item-list-element/item-types/publication/publication-list-element.component.html b/src/app/shared/object-list/item-list-element/item-types/publication/publication-list-element.component.html index d467edfb21..acc3ee4194 100644 --- a/src/app/shared/object-list/item-list-element/item-types/publication/publication-list-element.component.html +++ b/src/app/shared/object-list/item-list-element/item-types/publication/publication-list-element.component.html @@ -1,25 +1 @@ - - - - - (, ) - - - - ; - - - - -
- - -
-
+ \ No newline at end of file diff --git a/src/app/shared/object-list/item-list-element/item-types/publication/publication-list-element.component.spec.ts b/src/app/shared/object-list/item-list-element/item-types/publication/publication-list-element.component.spec.ts index 732fd0d4e4..4814123072 100644 --- a/src/app/shared/object-list/item-list-element/item-types/publication/publication-list-element.component.spec.ts +++ b/src/app/shared/object-list/item-list-element/item-types/publication/publication-list-element.component.spec.ts @@ -1,17 +1,13 @@ -import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { async, TestBed } from '@angular/core/testing'; import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA } from '@angular/core'; import { By } from '@angular/platform-browser'; import { PublicationListElementComponent } from './publication-list-element.component'; import { Item } from '../../../../../core/shared/item.model'; import { TruncatePipe } from '../../../../utils/truncate.pipe'; import { TruncatableService } from '../../../../truncatable/truncatable.service'; -import { ITEM } from '../../../../items/switcher/item-type-switcher.component'; import { of as observableOf } from 'rxjs'; -let publicationListElementComponent: PublicationListElementComponent; -let fixture: ComponentFixture; - -const mockItemWithMetadata: Item = Object.assign(new Item(), { +const mockItem: Item = Object.assign(new Item(), { bitstreams: observableOf({}), metadata: { 'dc.title': [ @@ -46,28 +42,22 @@ const mockItemWithMetadata: Item = Object.assign(new Item(), { ] } }); -const mockItemWithoutMetadata: Item = Object.assign(new Item(), { - bitstreams: observableOf({}), - metadata: { - 'dc.title': [ - { - language: 'en_US', - value: 'This is just another title' - } - ] - } -}); describe('PublicationListElementComponent', () => { + let comp; + let fixture; + + const truncatableServiceStub: any = { + isCollapsed: (id: number) => observableOf(true), + }; + beforeEach(async(() => { TestBed.configureTestingModule({ - declarations: [ PublicationListElementComponent , TruncatePipe], + declarations: [PublicationListElementComponent, TruncatePipe], providers: [ - { provide: ITEM, useValue: mockItemWithMetadata}, - { provide: TruncatableService, useValue: {} } + { provide: TruncatableService, useValue: truncatableServiceStub }, ], - - schemas: [ NO_ERRORS_SCHEMA ] + schemas: [NO_ERRORS_SCHEMA] }).overrideComponent(PublicationListElementComponent, { set: { changeDetection: ChangeDetectionStrategy.Default } }).compileComponents(); @@ -75,103 +65,18 @@ describe('PublicationListElementComponent', () => { beforeEach(async(() => { fixture = TestBed.createComponent(PublicationListElementComponent); - publicationListElementComponent = fixture.componentInstance; - + comp = fixture.componentInstance; })); - describe('When the item has an author', () => { + describe(`when the publication is rendered`, () => { beforeEach(() => { - publicationListElementComponent.item = mockItemWithMetadata; + comp.object = mockItem; fixture.detectChanges(); }); - it('should show the author paragraph', () => { - const itemAuthorField = fixture.debugElement.query(By.css('span.item-list-authors')); - expect(itemAuthorField).not.toBeNull(); - }); - }); - - describe('When the item has no author', () => { - beforeEach(() => { - publicationListElementComponent.item = mockItemWithoutMetadata; - fixture.detectChanges(); - }); - - it('should not show the author paragraph', () => { - const itemAuthorField = fixture.debugElement.query(By.css('span.item-list-authors')); - expect(itemAuthorField).toBeNull(); - }); - }); - - describe('When the item has a publisher', () => { - beforeEach(() => { - publicationListElementComponent.item = mockItemWithMetadata; - fixture.detectChanges(); - }); - - it('should show the publisher span', () => { - const publisherField = fixture.debugElement.query(By.css('span.item-list-publisher')); - expect(publisherField).not.toBeNull(); - }); - }); - - describe('When the item has no publisher', () => { - beforeEach(() => { - publicationListElementComponent.item = mockItemWithoutMetadata; - fixture.detectChanges(); - }); - - it('should not show the publisher span', () => { - const publisherField = fixture.debugElement.query(By.css('span.item-list-publisher')); - expect(publisherField).toBeNull(); - }); - }); - - describe('When the item has an issuedate', () => { - beforeEach(() => { - publicationListElementComponent.item = mockItemWithMetadata; - fixture.detectChanges(); - }); - - it('should show the issuedate span', () => { - const dateField = fixture.debugElement.query(By.css('span.item-list-date')); - expect(dateField).not.toBeNull(); - }); - }); - - describe('When the item has no issuedate', () => { - beforeEach(() => { - publicationListElementComponent.item = mockItemWithoutMetadata; - fixture.detectChanges(); - }); - - it('should not show the issuedate span', () => { - const dateField = fixture.debugElement.query(By.css('span.item-list-date')); - expect(dateField).toBeNull(); - }); - }); - - describe('When the item has an abstract', () => { - beforeEach(() => { - publicationListElementComponent.item = mockItemWithMetadata; - fixture.detectChanges(); - }); - - it('should show the abstract span', () => { - const abstractField = fixture.debugElement.query(By.css('div.item-list-abstract')); - expect(abstractField).not.toBeNull(); - }); - }); - - describe('When the item has no abstract', () => { - beforeEach(() => { - publicationListElementComponent.item = mockItemWithoutMetadata; - fixture.detectChanges(); - }); - - it('should not show the abstract span', () => { - const abstractField = fixture.debugElement.query(By.css('div.item-list-abstract')); - expect(abstractField).toBeNull(); + it(`should contain a PublicationListElementComponent`, () => { + const publicationListElement = fixture.debugElement.query(By.css(`ds-publication-search-result-list-element`)); + expect(publicationListElement).not.toBeNull(); }); }); }); diff --git a/src/app/shared/object-list/item-list-element/item-types/publication/publication-list-element.component.ts b/src/app/shared/object-list/item-list-element/item-types/publication/publication-list-element.component.ts index 4717ff1df2..59d0249aef 100644 --- a/src/app/shared/object-list/item-list-element/item-types/publication/publication-list-element.component.ts +++ b/src/app/shared/object-list/item-list-element/item-types/publication/publication-list-element.component.ts @@ -1,9 +1,11 @@ import { Component } from '@angular/core'; -import { DEFAULT_ITEM_TYPE, ItemViewMode, rendersItemType } from '../../../../items/item-type-decorator'; -import { TypedItemSearchResultListElementComponent } from '../typed-item-search-result-list-element.component'; +import { ViewMode } from '../../../../../core/shared/view-mode.model'; +import { listableObjectComponent } from '../../../../object-collection/shared/listable-object/listable-object.decorator'; +import { AbstractListableElementComponent } from '../../../../object-collection/shared/object-collection-element/abstract-listable-element.component'; +import { Item } from '../../../../../core/shared/item.model'; -@rendersItemType('Publication', ItemViewMode.Element) -@rendersItemType(DEFAULT_ITEM_TYPE, ItemViewMode.Element) +@listableObjectComponent('Publication', ViewMode.ListElement) +@listableObjectComponent(Item, ViewMode.ListElement) @Component({ selector: 'ds-publication-list-element', styleUrls: ['./publication-list-element.component.scss'], @@ -12,5 +14,5 @@ import { TypedItemSearchResultListElementComponent } from '../typed-item-search- /** * The component for displaying a list element for an item of the type Publication */ -export class PublicationListElementComponent extends TypedItemSearchResultListElementComponent { +export class PublicationListElementComponent extends AbstractListableElementComponent { } diff --git a/src/app/shared/object-list/item-list-element/item-types/typed-item-search-result-list-element.component.spec.ts b/src/app/shared/object-list/item-list-element/item-types/typed-item-search-result-list-element.component.spec.ts deleted file mode 100644 index 082347be0b..0000000000 --- a/src/app/shared/object-list/item-list-element/item-types/typed-item-search-result-list-element.component.spec.ts +++ /dev/null @@ -1,84 +0,0 @@ -import { async, ComponentFixture, TestBed } from '@angular/core/testing'; -import { TruncatePipe } from '../../../utils/truncate.pipe'; -import { TruncatableService } from '../../../truncatable/truncatable.service'; -import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA } from '@angular/core'; -import { TypedItemSearchResultListElementComponent } from './typed-item-search-result-list-element.component'; -import { Item } from '../../../../core/shared/item.model'; -import { RemoteData } from '../../../../core/data/remote-data'; -import { PaginatedList } from '../../../../core/data/paginated-list'; -import { PageInfo } from '../../../../core/shared/page-info.model'; -import { ITEM } from '../../../items/switcher/item-type-switcher.component'; -import { ItemSearchResult } from '../../../object-collection/shared/item-search-result.model'; -import { createRelationshipsObservable } from '../../../../+item-page/simple/item-types/shared/item.component.spec'; -import { of as observableOf } from 'rxjs'; -import { MetadataMap } from '../../../../core/shared/metadata.models'; -import { createSuccessfulRemoteDataObject$ } from '../../../testing/utils'; - -const mockItem: Item = Object.assign(new Item(), { - bitstreams: createSuccessfulRemoteDataObject$(new PaginatedList(new PageInfo(), [])), - metadata: [], - relationships: createRelationshipsObservable() -}); -const mockSearchResult = { - indexableObject: mockItem as Item, - hitHighlights: new MetadataMap() -} as ItemSearchResult; - -describe('TypedItemSearchResultListElementComponent', () => { - let comp: TypedItemSearchResultListElementComponent; - let fixture: ComponentFixture; - - describe('when injecting an Item', () => { - beforeEach(async(() => { - TestBed.configureTestingModule({ - declarations: [TypedItemSearchResultListElementComponent, TruncatePipe], - providers: [ - {provide: TruncatableService, useValue: {}}, - {provide: ITEM, useValue: mockItem} - ], - - schemas: [NO_ERRORS_SCHEMA] - }).overrideComponent(TypedItemSearchResultListElementComponent, { - set: {changeDetection: ChangeDetectionStrategy.Default} - }).compileComponents(); - })); - - beforeEach(async(() => { - fixture = TestBed.createComponent(TypedItemSearchResultListElementComponent); - comp = fixture.componentInstance; - })); - - it('should initiate item, object and dso correctly', () => { - expect(comp.item).toBe(mockItem); - expect(comp.dso).toBe(mockItem); - expect(comp.object.indexableObject).toBe(mockItem); - }) - }); - - describe('when injecting an ItemSearchResult', () => { - beforeEach(async(() => { - TestBed.configureTestingModule({ - declarations: [TypedItemSearchResultListElementComponent, TruncatePipe], - providers: [ - {provide: TruncatableService, useValue: {}}, - {provide: ITEM, useValue: mockSearchResult} - ], - - schemas: [NO_ERRORS_SCHEMA] - }).overrideComponent(TypedItemSearchResultListElementComponent, { - set: {changeDetection: ChangeDetectionStrategy.Default} - }).compileComponents(); - })); - - beforeEach(async(() => { - fixture = TestBed.createComponent(TypedItemSearchResultListElementComponent); - comp = fixture.componentInstance; - })); - - it('should initiate item, object and dso correctly', () => { - expect(comp.item).toBe(mockItem); - expect(comp.dso).toBe(mockItem); - expect(comp.object.indexableObject).toBe(mockItem); - }) - }); -}); diff --git a/src/app/shared/object-list/item-list-element/item-types/typed-item-search-result-list-element.component.ts b/src/app/shared/object-list/item-list-element/item-types/typed-item-search-result-list-element.component.ts deleted file mode 100644 index dd1b5a7e5f..0000000000 --- a/src/app/shared/object-list/item-list-element/item-types/typed-item-search-result-list-element.component.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { Component, Inject } from '@angular/core'; -import { Item } from '../../../../core/shared/item.model'; -import { hasValue } from '../../../empty.util'; -import { ITEM } from '../../../items/switcher/item-type-switcher.component'; -import { ItemSearchResult } from '../../../object-collection/shared/item-search-result.model'; -import { TruncatableService } from '../../../truncatable/truncatable.service'; -import { SearchResultListElementComponent } from '../../search-result-list-element/search-result-list-element.component'; -import { MetadataMap } from '../../../../core/shared/metadata.models'; - -/** - * A generic component for displaying item list elements - */ -@Component({ - selector: 'ds-item-search-result-list-element', - template: '' -}) -export class TypedItemSearchResultListElementComponent extends SearchResultListElementComponent { - item: Item; - - constructor( - protected truncatableService: TruncatableService, - @Inject(ITEM) public obj: Item | ItemSearchResult, - ) { - super(undefined, truncatableService); - if (hasValue((obj as any).indexableObject)) { - this.object = obj as ItemSearchResult; - this.dso = this.object.indexableObject; - } else { - this.object = { - indexableObject: obj as Item, - hitHighlights: new MetadataMap() - }; - this.dso = obj as Item; - } - this.item = this.dso; - } -} diff --git a/src/app/shared/object-list/item-type-badge/item-type-badge.component.html b/src/app/shared/object-list/item-type-badge/item-type-badge.component.html index 35d7663801..947970b7e1 100644 --- a/src/app/shared/object-list/item-type-badge/item-type-badge.component.html +++ b/src/app/shared/object-list/item-type-badge/item-type-badge.component.html @@ -1,3 +1,3 @@ -
+
{{ type.toLowerCase() + '.listelement.badge' | translate }}
diff --git a/src/app/shared/object-list/item-type-badge/item-type-badge.component.spec.ts b/src/app/shared/object-list/item-type-badge/item-type-badge.component.spec.ts index 04c40b73ff..35f283efe3 100644 --- a/src/app/shared/object-list/item-type-badge/item-type-badge.component.spec.ts +++ b/src/app/shared/object-list/item-type-badge/item-type-badge.component.spec.ts @@ -13,9 +13,7 @@ let fixture: ComponentFixture; const type = 'authorOfPublication'; -const mockItemWithRelationshipType: ItemSearchResult = new ItemSearchResult(); -mockItemWithRelationshipType.hitHighlights = {}; -mockItemWithRelationshipType.indexableObject = Object.assign(new Item(), { +const mockItemWithRelationshipType = Object.assign(new Item(), { bitstreams: observableOf({}), metadata: { 'relationship.type': [ @@ -27,9 +25,7 @@ mockItemWithRelationshipType.indexableObject = Object.assign(new Item(), { } }); -const mockItemWithoutRelationshipType: ItemSearchResult = new ItemSearchResult(); -mockItemWithoutRelationshipType.hitHighlights = {}; -mockItemWithoutRelationshipType.indexableObject = Object.assign(new Item(), { +const mockItemWithoutRelationshipType = Object.assign(new Item(), { bitstreams: observableOf({}), metadata: { 'dc.title': [ diff --git a/src/app/shared/object-list/item-type-badge/item-type-badge.component.ts b/src/app/shared/object-list/item-type-badge/item-type-badge.component.ts index 9ffba33758..5518ede202 100644 --- a/src/app/shared/object-list/item-type-badge/item-type-badge.component.ts +++ b/src/app/shared/object-list/item-type-badge/item-type-badge.component.ts @@ -7,6 +7,12 @@ import { DSpaceObject } from '../../../core/shared/dspace-object.model'; selector: 'ds-item-type-badge', templateUrl: './item-type-badge.component.html' }) +/** + * Component rendering the type of an item as a badge + */ export class ItemTypeBadgeComponent { - @Input() object: SearchResult; + /** + * The component used to retrieve the type from + */ + @Input() object: DSpaceObject; } diff --git a/src/app/shared/object-list/metadata-representation-list-element/item/item-metadata-list-element.component.html b/src/app/shared/object-list/metadata-representation-list-element/item/item-metadata-list-element.component.html index 764fdc1064..91219c7189 100644 --- a/src/app/shared/object-list/metadata-representation-list-element/item/item-metadata-list-element.component.html +++ b/src/app/shared/object-list/metadata-representation-list-element/item/item-metadata-list-element.component.html @@ -1,2 +1 @@ - - + diff --git a/src/app/shared/object-list/metadata-representation-list-element/item/item-metadata-list-element.component.spec.ts b/src/app/shared/object-list/metadata-representation-list-element/item/item-metadata-list-element.component.spec.ts index 269207bef8..c195268456 100644 --- a/src/app/shared/object-list/metadata-representation-list-element/item/item-metadata-list-element.component.spec.ts +++ b/src/app/shared/object-list/metadata-representation-list-element/item/item-metadata-list-element.component.spec.ts @@ -1,5 +1,4 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing'; -import { ITEM } from '../../../items/switcher/item-type-switcher.component'; import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA } from '@angular/core'; import { ItemMetadataListElementComponent } from './item-metadata-list-element.component'; import { By } from '@angular/platform-browser'; @@ -15,9 +14,6 @@ describe('ItemMetadataListElementComponent', () => { TestBed.configureTestingModule({ imports: [], declarations: [ItemMetadataListElementComponent], - providers: [ - { provide: ITEM, useValue: mockItemMetadataRepresentation } - ], schemas: [NO_ERRORS_SCHEMA] }).overrideComponent(ItemMetadataListElementComponent, { set: {changeDetection: ChangeDetectionStrategy.Default} @@ -27,12 +23,13 @@ describe('ItemMetadataListElementComponent', () => { beforeEach(async(() => { fixture = TestBed.createComponent(ItemMetadataListElementComponent); comp = fixture.componentInstance; + comp.metadataRepresentation = mockItemMetadataRepresentation; fixture.detectChanges(); })); - it('should call an item-type-switcher component and pass the item-metadata-representation', () => { - const itemTypeSwitcher = fixture.debugElement.query(By.css('ds-item-type-switcher')).nativeElement; - expect(itemTypeSwitcher.object).toBe(mockItemMetadataRepresentation); + it('should call a listable-object-component-loader component and pass the item-metadata-representation', () => { + const objectLoader = fixture.debugElement.query(By.css('ds-listable-object-component-loader')).nativeElement; + expect(objectLoader.object).toBe(mockItemMetadataRepresentation); }); }); diff --git a/src/app/shared/object-list/metadata-representation-list-element/item/item-metadata-list-element.component.ts b/src/app/shared/object-list/metadata-representation-list-element/item/item-metadata-list-element.component.ts index 084567a885..3be16bcb5e 100644 --- a/src/app/shared/object-list/metadata-representation-list-element/item/item-metadata-list-element.component.ts +++ b/src/app/shared/object-list/metadata-representation-list-element/item/item-metadata-list-element.component.ts @@ -1,9 +1,10 @@ import { MetadataRepresentationType } from '../../../../core/shared/metadata-representation/metadata-representation.model'; import { Component } from '@angular/core'; import { MetadataRepresentationListElementComponent } from '../metadata-representation-list-element.component'; -import { DEFAULT_ITEM_TYPE, ItemViewMode, rendersItemType } from '../../../items/item-type-decorator'; +import { ViewMode } from '../../../../core/shared/view-mode.model'; +import { metadataRepresentationComponent } from '../../../metadata-representation/metadata-representation.decorator'; -@rendersItemType(DEFAULT_ITEM_TYPE, ItemViewMode.Metadata, MetadataRepresentationType.Item) +@metadataRepresentationComponent('Publication', MetadataRepresentationType.Item) @Component({ selector: 'ds-item-metadata-list-element', templateUrl: './item-metadata-list-element.component.html' @@ -16,7 +17,7 @@ import { DEFAULT_ITEM_TYPE, ItemViewMode, rendersItemType } from '../../../items export class ItemMetadataListElementComponent extends MetadataRepresentationListElementComponent { /** * The view-mode we're currently on - * @type {ElementViewMode} + * @type {ViewMode} */ - viewMode = ItemViewMode.Element; + viewMode = ViewMode.ListElement; } diff --git a/src/app/shared/object-list/metadata-representation-list-element/item/item-metadata-representation-list-element.component.ts b/src/app/shared/object-list/metadata-representation-list-element/item/item-metadata-representation-list-element.component.ts index 0fdca0d429..6c4d300e99 100644 --- a/src/app/shared/object-list/metadata-representation-list-element/item/item-metadata-representation-list-element.component.ts +++ b/src/app/shared/object-list/metadata-representation-list-element/item/item-metadata-representation-list-element.component.ts @@ -1,6 +1,5 @@ import { MetadataRepresentationListElementComponent } from '../metadata-representation-list-element.component'; -import { Component, Inject } from '@angular/core'; -import { ITEM } from '../../../items/switcher/item-type-switcher.component'; +import { Component } from '@angular/core'; import { ItemMetadataRepresentation } from '../../../../core/shared/metadata-representation/item/item-metadata-representation.model'; @Component({ @@ -11,7 +10,5 @@ import { ItemMetadataRepresentation } from '../../../../core/shared/metadata-rep * An abstract class for displaying a single ItemMetadataRepresentation */ export class ItemMetadataRepresentationListElementComponent extends MetadataRepresentationListElementComponent { - constructor(@Inject(ITEM) public metadataRepresentation: ItemMetadataRepresentation) { - super(metadataRepresentation); - } + metadataRepresentation: ItemMetadataRepresentation; } diff --git a/src/app/shared/object-list/metadata-representation-list-element/metadata-representation-list-element.component.ts b/src/app/shared/object-list/metadata-representation-list-element/metadata-representation-list-element.component.ts index 2488db50b1..2e14485fbb 100644 --- a/src/app/shared/object-list/metadata-representation-list-element/metadata-representation-list-element.component.ts +++ b/src/app/shared/object-list/metadata-representation-list-element/metadata-representation-list-element.component.ts @@ -1,6 +1,5 @@ -import { Component, Inject } from '@angular/core'; +import { Component } from '@angular/core'; import { MetadataRepresentation } from '../../../core/shared/metadata-representation/metadata-representation.model'; -import { ITEM } from '../../items/switcher/item-type-switcher.component'; @Component({ selector: 'ds-metadata-representation-list-element', @@ -10,6 +9,8 @@ import { ITEM } from '../../items/switcher/item-type-switcher.component'; * An abstract class for displaying a single MetadataRepresentation */ export class MetadataRepresentationListElementComponent { - constructor(@Inject(ITEM) public metadataRepresentation: MetadataRepresentation) { - } + /** + * The metadata representation of this component + */ + metadataRepresentation: MetadataRepresentation; } diff --git a/src/app/shared/object-list/metadata-representation-list-element/plain-text/plain-text-metadata-list-element.component.spec.ts b/src/app/shared/object-list/metadata-representation-list-element/plain-text/plain-text-metadata-list-element.component.spec.ts index 42b9abde16..9a409aa147 100644 --- a/src/app/shared/object-list/metadata-representation-list-element/plain-text/plain-text-metadata-list-element.component.spec.ts +++ b/src/app/shared/object-list/metadata-representation-list-element/plain-text/plain-text-metadata-list-element.component.spec.ts @@ -2,7 +2,6 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA } from '@angular/core'; import { PlainTextMetadataListElementComponent } from './plain-text-metadata-list-element.component'; import { MetadatumRepresentation } from '../../../../core/shared/metadata-representation/metadatum/metadatum-representation.model'; -import { ITEM } from '../../../items/switcher/item-type-switcher.component'; const mockMetadataRepresentation = Object.assign(new MetadatumRepresentation('type'), { key: 'dc.contributor.author', @@ -17,9 +16,6 @@ describe('PlainTextMetadataListElementComponent', () => { TestBed.configureTestingModule({ imports: [], declarations: [PlainTextMetadataListElementComponent], - providers: [ - { provide: ITEM, useValue: mockMetadataRepresentation } - ], schemas: [NO_ERRORS_SCHEMA] }).overrideComponent(PlainTextMetadataListElementComponent, { set: {changeDetection: ChangeDetectionStrategy.Default} @@ -29,6 +25,7 @@ describe('PlainTextMetadataListElementComponent', () => { beforeEach(async(() => { fixture = TestBed.createComponent(PlainTextMetadataListElementComponent); comp = fixture.componentInstance; + comp.metadataRepresentation = mockMetadataRepresentation; fixture.detectChanges(); })); diff --git a/src/app/shared/object-list/metadata-representation-list-element/plain-text/plain-text-metadata-list-element.component.ts b/src/app/shared/object-list/metadata-representation-list-element/plain-text/plain-text-metadata-list-element.component.ts index 7c4785e37c..198c3712d9 100644 --- a/src/app/shared/object-list/metadata-representation-list-element/plain-text/plain-text-metadata-list-element.component.ts +++ b/src/app/shared/object-list/metadata-representation-list-element/plain-text/plain-text-metadata-list-element.component.ts @@ -1,11 +1,11 @@ import { MetadataRepresentationType } from '../../../../core/shared/metadata-representation/metadata-representation.model'; import { Component } from '@angular/core'; import { MetadataRepresentationListElementComponent } from '../metadata-representation-list-element.component'; -import { DEFAULT_ITEM_TYPE, ItemViewMode, rendersItemType } from '../../../items/item-type-decorator'; +import { metadataRepresentationComponent } from '../../../metadata-representation/metadata-representation.decorator'; -@rendersItemType(DEFAULT_ITEM_TYPE, ItemViewMode.Metadata, MetadataRepresentationType.PlainText) +@metadataRepresentationComponent('Publication', MetadataRepresentationType.PlainText) // For now, authority controlled fields are rendered the same way as plain text fields -@rendersItemType(DEFAULT_ITEM_TYPE, ItemViewMode.Metadata, MetadataRepresentationType.AuthorityControlled) +@metadataRepresentationComponent('Publication', MetadataRepresentationType.AuthorityControlled) @Component({ selector: 'ds-plain-text-metadata-list-element', templateUrl: './plain-text-metadata-list-element.component.html' diff --git a/src/app/shared/object-list/my-dspace-result-list-element/claimed-my-dspace-result/claimed-my-dspace-result-list-element.component.html b/src/app/shared/object-list/my-dspace-result-list-element/claimed-search-result/claimed-search-result-list-element.component.html similarity index 100% rename from src/app/shared/object-list/my-dspace-result-list-element/claimed-my-dspace-result/claimed-my-dspace-result-list-element.component.html rename to src/app/shared/object-list/my-dspace-result-list-element/claimed-search-result/claimed-search-result-list-element.component.html diff --git a/src/app/shared/object-list/my-dspace-result-list-element/claimed-my-dspace-result/claimed-my-dspace-result-list-element.component.spec.ts b/src/app/shared/object-list/my-dspace-result-list-element/claimed-search-result/claimed-search-result-list-element.component.spec.ts similarity index 71% rename from src/app/shared/object-list/my-dspace-result-list-element/claimed-my-dspace-result/claimed-my-dspace-result-list-element.component.spec.ts rename to src/app/shared/object-list/my-dspace-result-list-element/claimed-search-result/claimed-search-result-list-element.component.spec.ts index 5815cd5401..327bb750b1 100644 --- a/src/app/shared/object-list/my-dspace-result-list-element/claimed-my-dspace-result/claimed-my-dspace-result-list-element.component.spec.ts +++ b/src/app/shared/object-list/my-dspace-result-list-element/claimed-search-result/claimed-search-result-list-element.component.spec.ts @@ -5,20 +5,21 @@ import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { of as observableOf } from 'rxjs'; import { Item } from '../../../../core/shared/item.model'; -import { ClaimedMyDSpaceResultListElementComponent } from './claimed-my-dspace-result-list-element.component'; -import { ClaimedTaskMyDSpaceResult } from '../../../object-collection/shared/claimed-task-my-dspace-result.model'; +import { ClaimedSearchResultListElementComponent } from './claimed-search-result-list-element.component'; import { ClaimedTask } from '../../../../core/tasks/models/claimed-task-object.model'; -import { RemoteData } from '../../../../core/data/remote-data'; import { MyDspaceItemStatusType } from '../../../object-collection/shared/mydspace-item-status/my-dspace-item-status-type'; import { WorkflowItem } from '../../../../core/submission/models/workflowitem.model'; import { createSuccessfulRemoteDataObject } from '../../../testing/utils'; +import { ClaimedTaskSearchResult } from '../../../object-collection/shared/claimed-task-search-result.model'; +import { TruncatableAction } from '../../../truncatable/truncatable.actions'; +import { TruncatableService } from '../../../truncatable/truncatable.service'; -let component: ClaimedMyDSpaceResultListElementComponent; -let fixture: ComponentFixture; +let component: ClaimedSearchResultListElementComponent; +let fixture: ComponentFixture; const compIndex = 1; -const mockResultObject: ClaimedTaskMyDSpaceResult = new ClaimedTaskMyDSpaceResult(); +const mockResultObject: ClaimedTaskSearchResult = new ClaimedTaskSearchResult(); mockResultObject.hitHighlights = {}; const item = Object.assign(new Item(), { @@ -55,23 +56,22 @@ const workflowitem = Object.assign(new WorkflowItem(), { item: observableOf(rdIt const rdWorkflowitem = createSuccessfulRemoteDataObject(workflowitem); mockResultObject.indexableObject = Object.assign(new ClaimedTask(), { workflowitem: observableOf(rdWorkflowitem) }); -describe('ClaimedMyDSpaceResultListElementComponent', () => { +describe('ClaimedSearchResultListElementComponent', () => { beforeEach(async(() => { TestBed.configureTestingModule({ imports: [NoopAnimationsModule], - declarations: [ClaimedMyDSpaceResultListElementComponent], + declarations: [ClaimedSearchResultListElementComponent], providers: [ - { provide: 'objectElementProvider', useValue: (mockResultObject) }, - { provide: 'indexElementProvider', useValue: (compIndex) } + { provide: TruncatableService, useValue: {} }, ], schemas: [NO_ERRORS_SCHEMA] - }).overrideComponent(ClaimedMyDSpaceResultListElementComponent, { + }).overrideComponent(ClaimedSearchResultListElementComponent, { set: { changeDetection: ChangeDetectionStrategy.Default } }).compileComponents(); })); beforeEach(async(() => { - fixture = TestBed.createComponent(ClaimedMyDSpaceResultListElementComponent); + fixture = TestBed.createComponent(ClaimedSearchResultListElementComponent); component = fixture.componentInstance; })); diff --git a/src/app/shared/object-list/my-dspace-result-list-element/claimed-my-dspace-result/claimed-my-dspace-result-list-element.component.ts b/src/app/shared/object-list/my-dspace-result-list-element/claimed-search-result/claimed-search-result-list-element.component.ts similarity index 64% rename from src/app/shared/object-list/my-dspace-result-list-element/claimed-my-dspace-result/claimed-my-dspace-result-list-element.component.ts rename to src/app/shared/object-list/my-dspace-result-list-element/claimed-search-result/claimed-search-result-list-element.component.ts index 3423df7009..35371f40aa 100644 --- a/src/app/shared/object-list/my-dspace-result-list-element/claimed-my-dspace-result/claimed-my-dspace-result-list-element.component.ts +++ b/src/app/shared/object-list/my-dspace-result-list-element/claimed-search-result/claimed-search-result-list-element.component.ts @@ -4,30 +4,28 @@ import { Location, LocationStrategy, PathLocationStrategy } from '@angular/commo import { Observable } from 'rxjs'; import { find } from 'rxjs/operators'; -import { renderElementsFor } from '../../../object-collection/shared/dso-element-decorator'; -import { MyDSpaceResultListElementComponent, } from '../my-dspace-result-list-element.component'; import { ViewMode } from '../../../../core/shared/view-mode.model'; import { RemoteData } from '../../../../core/data/remote-data'; import { isNotUndefined } from '../../../empty.util'; import { WorkflowItem } from '../../../../core/submission/models/workflowitem.model'; import { ClaimedTask } from '../../../../core/tasks/models/claimed-task-object.model'; -import { ClaimedTaskMyDSpaceResult } from '../../../object-collection/shared/claimed-task-my-dspace-result.model'; import { MyDspaceItemStatusType } from '../../../object-collection/shared/mydspace-item-status/my-dspace-item-status-type'; -import { SetViewMode } from '../../../view-mode'; +import { listableObjectComponent } from '../../../object-collection/shared/listable-object/listable-object.decorator'; +import { ClaimedTaskSearchResult } from '../../../object-collection/shared/claimed-task-search-result.model'; +import { SearchResultListElementComponent } from '../../search-result-list-element/search-result-list-element.component'; /** - * This component renders claimed task object for the mydspace result in the list view. + * This component renders claimed task object for the search result in the list view. */ @Component({ - selector: 'ds-claimed-my-dspace-result-list-element', - styleUrls: ['../my-dspace-result-list-element.component.scss'], - templateUrl: './claimed-my-dspace-result-list-element.component.html', + selector: 'ds-claimed-search-result-list-element', + styleUrls: ['../../search-result-list-element/search-result-list-element.component.scss'], + templateUrl: './claimed-search-result-list-element.component.html', providers: [Location, { provide: LocationStrategy, useClass: PathLocationStrategy }] }) -@renderElementsFor(ClaimedTaskMyDSpaceResult, SetViewMode.List) -@renderElementsFor(ClaimedTask, SetViewMode.List) -export class ClaimedMyDSpaceResultListElementComponent extends MyDSpaceResultListElementComponent { +@listableObjectComponent(ClaimedTaskSearchResult, ViewMode.ListElement) +export class ClaimedSearchResultListElementComponent extends SearchResultListElementComponent { /** * A boolean representing if to show submitter information @@ -48,6 +46,7 @@ export class ClaimedMyDSpaceResultListElementComponent extends MyDSpaceResultLis * Initialize all instance variables */ ngOnInit() { + super.ngOnInit(); this.initWorkflowItem(this.dso.workflowitem as Observable>); } 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 13876ab46a..0395c8c84b 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 @@ -3,7 +3,7 @@ import { Component, Input } from '@angular/core'; import { Item } from '../../../../core/shared/item.model'; import { fadeInOut } from '../../../animations/fade'; import { MyDspaceItemStatusType } from '../../../object-collection/shared/mydspace-item-status/my-dspace-item-status-type'; -import { MyDSpaceResult } from '../../../../+my-dspace-page/my-dspace-result.model'; +import { SearchResult } from '../../../../+search-page/search-result.model'; /** * This component show metadata for the given item object in the list view. @@ -22,9 +22,9 @@ export class ItemListPreviewComponent { @Input() item: Item; /** - * The mydspace result object + * The search result object */ - @Input() object: MyDSpaceResult; + @Input() object: SearchResult; /** * Represent item's status diff --git a/src/app/shared/object-list/my-dspace-result-list-element/item-my-dspace-result/item-my-dspace-result-list-element.component.ts b/src/app/shared/object-list/my-dspace-result-list-element/item-my-dspace-result/item-my-dspace-result-list-element.component.ts deleted file mode 100644 index 3f2a439603..0000000000 --- a/src/app/shared/object-list/my-dspace-result-list-element/item-my-dspace-result/item-my-dspace-result-list-element.component.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { Component } from '@angular/core'; - -import { renderElementsFor } from '../../../object-collection/shared/dso-element-decorator'; -import { MyDSpaceResultListElementComponent, } from '../my-dspace-result-list-element.component'; -import { Item } from '../../../../core/shared/item.model'; -import { ItemMyDSpaceResult } from '../../../object-collection/shared/item-my-dspace-result.model'; -import { MyDspaceItemStatusType } from '../../../object-collection/shared/mydspace-item-status/my-dspace-item-status-type'; -import { SetViewMode } from '../../../view-mode'; - -/** - * This component renders item object for the mydspace result in the list view. - */ -@Component({ - selector: 'ds-workspaceitem-my-dspace-result-list-element', - styleUrls: ['../my-dspace-result-list-element.component.scss', './item-my-dspace-result-list-element.component.scss'], - templateUrl: './item-my-dspace-result-list-element.component.html' -}) - -@renderElementsFor(ItemMyDSpaceResult, SetViewMode.List) -export class ItemMyDSpaceResultListElementComponent extends MyDSpaceResultListElementComponent { - - /** - * Represent item's status - */ - public status = MyDspaceItemStatusType.ARCHIVED; - -} diff --git a/src/app/shared/object-list/my-dspace-result-list-element/item-my-dspace-result/item-my-dspace-result-list-element.component.html b/src/app/shared/object-list/my-dspace-result-list-element/item-search-result/item-search-result-list-element-submission.component.html similarity index 100% rename from src/app/shared/object-list/my-dspace-result-list-element/item-my-dspace-result/item-my-dspace-result-list-element.component.html rename to src/app/shared/object-list/my-dspace-result-list-element/item-search-result/item-search-result-list-element-submission.component.html diff --git a/src/app/shared/object-list/my-dspace-result-list-element/item-my-dspace-result/item-my-dspace-result-list-element.component.scss b/src/app/shared/object-list/my-dspace-result-list-element/item-search-result/item-search-result-list-element-submission.component.scss similarity index 100% rename from src/app/shared/object-list/my-dspace-result-list-element/item-my-dspace-result/item-my-dspace-result-list-element.component.scss rename to src/app/shared/object-list/my-dspace-result-list-element/item-search-result/item-search-result-list-element-submission.component.scss diff --git a/src/app/shared/object-list/my-dspace-result-list-element/item-my-dspace-result/item-my-dspace-result-list-element.component.spec.ts b/src/app/shared/object-list/my-dspace-result-list-element/item-search-result/item-search-result-list-element-submission.component.spec.ts similarity index 68% rename from src/app/shared/object-list/my-dspace-result-list-element/item-my-dspace-result/item-my-dspace-result-list-element.component.spec.ts rename to src/app/shared/object-list/my-dspace-result-list-element/item-search-result/item-search-result-list-element-submission.component.spec.ts index ea4f2d24f3..57c1a4706c 100644 --- a/src/app/shared/object-list/my-dspace-result-list-element/item-my-dspace-result/item-my-dspace-result-list-element.component.spec.ts +++ b/src/app/shared/object-list/my-dspace-result-list-element/item-search-result/item-search-result-list-element-submission.component.spec.ts @@ -5,16 +5,17 @@ import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { of as observableOf } from 'rxjs'; import { Item } from '../../../../core/shared/item.model'; -import { ItemMyDSpaceResultListElementComponent } from './item-my-dspace-result-list-element.component'; import { MyDspaceItemStatusType } from '../../../object-collection/shared/mydspace-item-status/my-dspace-item-status-type'; -import { ItemMyDSpaceResult } from '../../../object-collection/shared/item-my-dspace-result.model'; +import { ItemSearchResult } from '../../../object-collection/shared/item-search-result.model'; +import { ItemSearchResultListElementSubmissionComponent } from './item-search-result-list-element-submission.component'; +import { TruncatableService } from '../../../truncatable/truncatable.service'; -let component: ItemMyDSpaceResultListElementComponent; -let fixture: ComponentFixture; +let component: ItemSearchResultListElementSubmissionComponent; +let fixture: ComponentFixture; const compIndex = 1; -const mockResultObject: ItemMyDSpaceResult = new ItemMyDSpaceResult(); +const mockResultObject: ItemSearchResult = new ItemSearchResult(); mockResultObject.hitHighlights = {}; mockResultObject.indexableObject = Object.assign(new Item(), { @@ -51,19 +52,18 @@ describe('ItemMyDSpaceResultListElementComponent', () => { beforeEach(async(() => { TestBed.configureTestingModule({ imports: [NoopAnimationsModule], - declarations: [ItemMyDSpaceResultListElementComponent], + declarations: [ItemSearchResultListElementSubmissionComponent], providers: [ - { provide: 'objectElementProvider', useValue: (mockResultObject) }, - { provide: 'indexElementProvider', useValue: (compIndex) } + { provide: TruncatableService, useValue: {} }, ], schemas: [NO_ERRORS_SCHEMA] - }).overrideComponent(ItemMyDSpaceResultListElementComponent, { + }).overrideComponent(ItemSearchResultListElementSubmissionComponent, { set: { changeDetection: ChangeDetectionStrategy.Default } }).compileComponents(); })); beforeEach(async(() => { - fixture = TestBed.createComponent(ItemMyDSpaceResultListElementComponent); + fixture = TestBed.createComponent(ItemSearchResultListElementSubmissionComponent); component = fixture.componentInstance; })); diff --git a/src/app/shared/object-list/my-dspace-result-list-element/item-search-result/item-search-result-list-element-submission.component.ts b/src/app/shared/object-list/my-dspace-result-list-element/item-search-result/item-search-result-list-element-submission.component.ts new file mode 100644 index 0000000000..3ef45d1c47 --- /dev/null +++ b/src/app/shared/object-list/my-dspace-result-list-element/item-search-result/item-search-result-list-element-submission.component.ts @@ -0,0 +1,31 @@ +import { Component, OnInit } from '@angular/core'; + +import { Item } from '../../../../core/shared/item.model'; +import { MyDspaceItemStatusType } from '../../../object-collection/shared/mydspace-item-status/my-dspace-item-status-type'; +import { ViewMode } from '../../../../core/shared/view-mode.model'; +import { listableObjectComponent } from '../../../object-collection/shared/listable-object/listable-object.decorator'; +import { Context } from '../../../../core/shared/context.model'; +import { ItemSearchResult } from '../../../object-collection/shared/item-search-result.model'; +import { SearchResultListElementComponent } from '../../search-result-list-element/search-result-list-element.component'; + +/** + * This component renders item object for the search result in the list view for submission. + */ +@Component({ + selector: 'ds-item-search-result-list-element-submission', + styleUrls: ['../../search-result-list-element/search-result-list-element.component.scss', './item-search-result-list-element-submission.component.scss'], + templateUrl: './item-search-result-list-element-submission.component.html' +}) + +@listableObjectComponent(ItemSearchResult, ViewMode.ListElement, Context.Workspace) +@listableObjectComponent(ItemSearchResult, ViewMode.ListElement, Context.Workflow) +export class ItemSearchResultListElementSubmissionComponent extends SearchResultListElementComponent implements OnInit { + /** + * Represent item's status + */ + public status = MyDspaceItemStatusType.ARCHIVED; + + ngOnInit() { + super.ngOnInit(); + } +} diff --git a/src/app/shared/object-list/my-dspace-result-list-element/my-dspace-result-list-element.component.scss b/src/app/shared/object-list/my-dspace-result-list-element/my-dspace-result-list-element.component.scss deleted file mode 100644 index 4cd8a2b697..0000000000 --- a/src/app/shared/object-list/my-dspace-result-list-element/my-dspace-result-list-element.component.scss +++ /dev/null @@ -1 +0,0 @@ -@import '../search-result-list-element/search-result-list-element.component.scss'; diff --git a/src/app/shared/object-list/my-dspace-result-list-element/my-dspace-result-list-element.component.ts b/src/app/shared/object-list/my-dspace-result-list-element/my-dspace-result-list-element.component.ts deleted file mode 100644 index b2a5bf14fd..0000000000 --- a/src/app/shared/object-list/my-dspace-result-list-element/my-dspace-result-list-element.component.ts +++ /dev/null @@ -1,58 +0,0 @@ -import { Component, Inject } from '@angular/core'; - -import { MyDSpaceResult } from '../../../+my-dspace-page/my-dspace-result.model'; -import { AbstractListableElementComponent } from '../../object-collection/shared/object-collection-element/abstract-listable-element.component'; -import { ListableObject } from '../../object-collection/shared/listable-object.model'; -import { DSpaceObject } from '../../../core/shared/dspace-object.model'; -import { Metadata } from '../../../core/shared/metadata.utils'; - -@Component({ - selector: 'ds-my-dspace-result-list-element', - template: `` -}) -export class MyDSpaceResultListElementComponent, K extends DSpaceObject> extends AbstractListableElementComponent { - - /** - * The result element object - */ - dso: K; - - /** - * The array index of the result element - */ - dsoIndex: number; - - /** - * Initialize instance variables - * - * @param {ListableObject} listable - * @param {number} index - */ - public constructor(@Inject('objectElementProvider') public listable: ListableObject, - @Inject('indexElementProvider') public index: number) { - super(listable); - this.dso = this.object.indexableObject; - this.dsoIndex = this.index; - } - - /** - * Gets all matching metadata string values from hitHighlights or dso metadata, preferring hitHighlights. - * - * @param {string|string[]} keyOrKeys The metadata key(s) in scope. Wildcards are supported; see [[Metadata]]. - * @returns {string[]} the matching string values or an empty array. - */ - allMetadataValues(keyOrKeys: string | string[]): string[] { - return Metadata.allValues([this.object.hitHighlights, this.dso.metadata], keyOrKeys); - } - - /** - * Gets the first matching metadata string value from hitHighlights or dso metadata, preferring hitHighlights. - * - * @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(keyOrKeys: string | string[]): string { - return Metadata.firstValue([this.object.hitHighlights, this.dso.metadata], keyOrKeys); - } - -} diff --git a/src/app/shared/object-list/my-dspace-result-list-element/pool-my-dspace-result/pool-my-dspace-result-list-element.component.html b/src/app/shared/object-list/my-dspace-result-list-element/pool-search-result/pool-search-result-list-element.component.html similarity index 100% rename from src/app/shared/object-list/my-dspace-result-list-element/pool-my-dspace-result/pool-my-dspace-result-list-element.component.html rename to src/app/shared/object-list/my-dspace-result-list-element/pool-search-result/pool-search-result-list-element.component.html diff --git a/src/app/shared/object-detail/my-dspace-result-detail-element/pool-my-dspace-result/pool-my-dspace-result-detail-element.component.spec.ts b/src/app/shared/object-list/my-dspace-result-list-element/pool-search-result/pool-search-result-list-element.component.spec.ts similarity index 71% rename from src/app/shared/object-detail/my-dspace-result-detail-element/pool-my-dspace-result/pool-my-dspace-result-detail-element.component.spec.ts rename to src/app/shared/object-list/my-dspace-result-list-element/pool-search-result/pool-search-result-list-element.component.spec.ts index a031ac3a49..31f29439af 100644 --- a/src/app/shared/object-detail/my-dspace-result-detail-element/pool-my-dspace-result/pool-my-dspace-result-detail-element.component.spec.ts +++ b/src/app/shared/object-list/my-dspace-result-list-element/pool-search-result/pool-search-result-list-element.component.spec.ts @@ -5,20 +5,20 @@ import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { of as observableOf } from 'rxjs'; import { Item } from '../../../../core/shared/item.model'; -import { PoolMyDSpaceResultDetailElementComponent } from './pool-my-dspace-result-detail-lement.component'; -import { PoolTaskMyDSpaceResult } from '../../../object-collection/shared/pool-task-my-dspace-result.model'; +import { PoolSearchResultListElementComponent } from './pool-search-result-list-element.component'; import { PoolTask } from '../../../../core/tasks/models/pool-task-object.model'; -import { RemoteData } from '../../../../core/data/remote-data'; import { MyDspaceItemStatusType } from '../../../object-collection/shared/mydspace-item-status/my-dspace-item-status-type'; import { WorkflowItem } from '../../../../core/submission/models/workflowitem.model'; import { createSuccessfulRemoteDataObject } from '../../../testing/utils'; +import { PoolTaskSearchResult } from '../../../object-collection/shared/pool-task-search-result.model'; +import { TruncatableService } from '../../../truncatable/truncatable.service'; -let component: PoolMyDSpaceResultDetailElementComponent; -let fixture: ComponentFixture; +let component: PoolSearchResultListElementComponent; +let fixture: ComponentFixture; const compIndex = 1; -const mockResultObject: PoolTaskMyDSpaceResult = new PoolTaskMyDSpaceResult(); +const mockResultObject: PoolTaskSearchResult = new PoolTaskSearchResult(); mockResultObject.hitHighlights = {}; const item = Object.assign(new Item(), { @@ -55,23 +55,22 @@ const workflowitem = Object.assign(new WorkflowItem(), { item: observableOf(rdIt const rdWorkflowitem = createSuccessfulRemoteDataObject(workflowitem); mockResultObject.indexableObject = Object.assign(new PoolTask(), { workflowitem: observableOf(rdWorkflowitem) }); -describe('PoolMyDSpaceResultDetailElementComponent', () => { +describe('PoolSearchResultListElementComponent', () => { beforeEach(async(() => { TestBed.configureTestingModule({ imports: [NoopAnimationsModule], - declarations: [PoolMyDSpaceResultDetailElementComponent], + declarations: [PoolSearchResultListElementComponent], providers: [ - { provide: 'objectElementProvider', useValue: (mockResultObject) }, - { provide: 'indexElementProvider', useValue: (compIndex) } + { provide: TruncatableService, useValue: {} }, ], schemas: [NO_ERRORS_SCHEMA] - }).overrideComponent(PoolMyDSpaceResultDetailElementComponent, { + }).overrideComponent(PoolSearchResultListElementComponent, { set: { changeDetection: ChangeDetectionStrategy.Default } }).compileComponents(); })); beforeEach(async(() => { - fixture = TestBed.createComponent(PoolMyDSpaceResultDetailElementComponent); + fixture = TestBed.createComponent(PoolSearchResultListElementComponent); component = fixture.componentInstance; })); diff --git a/src/app/shared/object-list/my-dspace-result-list-element/pool-my-dspace-result/pool-my-dspace-result-list-element.component.ts b/src/app/shared/object-list/my-dspace-result-list-element/pool-search-result/pool-search-result-list-element.component.ts similarity index 53% rename from src/app/shared/object-list/my-dspace-result-list-element/pool-my-dspace-result/pool-my-dspace-result-list-element.component.ts rename to src/app/shared/object-list/my-dspace-result-list-element/pool-search-result/pool-search-result-list-element.component.ts index 0b60c60dc1..b34e23c3e6 100644 --- a/src/app/shared/object-list/my-dspace-result-list-element/pool-my-dspace-result/pool-my-dspace-result-list-element.component.ts +++ b/src/app/shared/object-list/my-dspace-result-list-element/pool-search-result/pool-search-result-list-element.component.ts @@ -1,32 +1,30 @@ -import { Component, Inject, OnInit } from '@angular/core'; +import { Component, OnInit } from '@angular/core'; import { Observable } from 'rxjs'; import { find } from 'rxjs/operators'; -import { renderElementsFor } from '../../../object-collection/shared/dso-element-decorator'; -import { MyDSpaceResultListElementComponent, } from '../my-dspace-result-list-element.component'; import { ViewMode } from '../../../../core/shared/view-mode.model'; import { RemoteData } from '../../../../core/data/remote-data'; import { isNotUndefined } from '../../../empty.util'; -import { ListableObject } from '../../../object-collection/shared/listable-object.model'; import { WorkflowItem } from '../../../../core/submission/models/workflowitem.model'; import { PoolTask } from '../../../../core/tasks/models/pool-task-object.model'; -import { PoolTaskMyDSpaceResult } from '../../../object-collection/shared/pool-task-my-dspace-result.model'; import { MyDspaceItemStatusType } from '../../../object-collection/shared/mydspace-item-status/my-dspace-item-status-type'; -import { SetViewMode } from '../../../view-mode'; +import { listableObjectComponent } from '../../../object-collection/shared/listable-object/listable-object.decorator'; +import { PoolTaskSearchResult } from '../../../object-collection/shared/pool-task-search-result.model'; +import { SearchResultListElementComponent } from '../../search-result-list-element/search-result-list-element.component'; +import { TruncatableService } from '../../../truncatable/truncatable.service'; /** - * This component renders pool task object for the mydspace result in the list view. + * This component renders pool task object for the search result in the list view. */ @Component({ - selector: 'ds-pool-my-dspace-result-list-element', - styleUrls: ['../my-dspace-result-list-element.component.scss'], - templateUrl: './pool-my-dspace-result-list-element.component.html', + selector: 'ds-pool-search-result-list-element', + styleUrls: ['../../search-result-list-element/search-result-list-element.component.scss'], + templateUrl: './pool-search-result-list-element.component.html', }) -@renderElementsFor(PoolTaskMyDSpaceResult, SetViewMode.List) -@renderElementsFor(PoolTask, SetViewMode.List) -export class PoolMyDSpaceResultListElementComponent extends MyDSpaceResultListElementComponent implements OnInit { +@listableObjectComponent(PoolTaskSearchResult, ViewMode.ListElement) +export class PoolSearchResultListElementComponent extends SearchResultListElementComponent implements OnInit { /** * A boolean representing if to show submitter information @@ -43,15 +41,20 @@ export class PoolMyDSpaceResultListElementComponent extends MyDSpaceResultListEl */ public workflowitem: WorkflowItem; - constructor(@Inject('objectElementProvider') public listable: ListableObject, - @Inject('indexElementProvider') public index: number) { - super(listable, index); + /** + * The index of this list element + */ + public index: number; + + constructor(protected truncatableService: TruncatableService) { + super(truncatableService); } /** * Initialize all instance variables */ ngOnInit() { + super.ngOnInit(); this.initWorkflowItem(this.dso.workflowitem as Observable>); } diff --git a/src/app/shared/object-list/my-dspace-result-list-element/workflowitem-my-dspace-result/workflowitem-my-dspace-result-list-element.component.html b/src/app/shared/object-list/my-dspace-result-list-element/workflow-item-search-result/workflow-item-search-result-list-element.component.html similarity index 100% rename from src/app/shared/object-list/my-dspace-result-list-element/workflowitem-my-dspace-result/workflowitem-my-dspace-result-list-element.component.html rename to src/app/shared/object-list/my-dspace-result-list-element/workflow-item-search-result/workflow-item-search-result-list-element.component.html diff --git a/src/app/shared/object-detail/my-dspace-result-detail-element/workflowitem-my-dspace-result/workflowitem-my-dspace-result-detail-element.component.spec.ts b/src/app/shared/object-list/my-dspace-result-list-element/workflow-item-search-result/workflow-item-search-result-list-element.component.spec.ts similarity index 67% rename from src/app/shared/object-detail/my-dspace-result-detail-element/workflowitem-my-dspace-result/workflowitem-my-dspace-result-detail-element.component.spec.ts rename to src/app/shared/object-list/my-dspace-result-list-element/workflow-item-search-result/workflow-item-search-result-list-element.component.spec.ts index 2a4b1321e2..4ecdbea4d6 100644 --- a/src/app/shared/object-detail/my-dspace-result-detail-element/workflowitem-my-dspace-result/workflowitem-my-dspace-result-detail-element.component.spec.ts +++ b/src/app/shared/object-list/my-dspace-result-list-element/workflow-item-search-result/workflow-item-search-result-list-element.component.spec.ts @@ -5,19 +5,19 @@ import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { of as observableOf } from 'rxjs'; import { Item } from '../../../../core/shared/item.model'; -import { WorkflowitemMyDSpaceResultDetailElementComponent } from './workflowitem-my-dspace-result-detail-element.component'; -import { WorkflowitemMyDSpaceResult } from '../../../object-collection/shared/workflowitem-my-dspace-result.model'; import { WorkflowItem } from '../../../../core/submission/models/workflowitem.model'; -import { RemoteData } from '../../../../core/data/remote-data'; import { MyDspaceItemStatusType } from '../../../object-collection/shared/mydspace-item-status/my-dspace-item-status-type'; import { createSuccessfulRemoteDataObject } from '../../../testing/utils'; +import { WorkflowItemSearchResultListElementComponent } from './workflow-item-search-result-list-element.component'; +import { WorkflowItemSearchResult } from '../../../object-collection/shared/workflow-item-search-result.model'; +import { TruncatableService } from '../../../truncatable/truncatable.service'; -let component: WorkflowitemMyDSpaceResultDetailElementComponent; -let fixture: ComponentFixture; +let component: WorkflowItemSearchResultListElementComponent; +let fixture: ComponentFixture; const compIndex = 1; -const mockResultObject: WorkflowitemMyDSpaceResult = new WorkflowitemMyDSpaceResult(); +const mockResultObject: WorkflowItemSearchResult = new WorkflowItemSearchResult(); mockResultObject.hitHighlights = {}; const item = Object.assign(new Item(), { @@ -52,23 +52,22 @@ const item = Object.assign(new Item(), { const rd = createSuccessfulRemoteDataObject(item); mockResultObject.indexableObject = Object.assign(new WorkflowItem(), { item: observableOf(rd) }); -describe('WorkflowitemMyDSpaceResultDetailElementComponent', () => { +describe('WorkflowItemSearchResultListElementComponent', () => { beforeEach(async(() => { TestBed.configureTestingModule({ imports: [NoopAnimationsModule], - declarations: [WorkflowitemMyDSpaceResultDetailElementComponent], + declarations: [WorkflowItemSearchResultListElementComponent], providers: [ - { provide: 'objectElementProvider', useValue: (mockResultObject) }, - { provide: 'indexElementProvider', useValue: (compIndex) } + { provide: TruncatableService, useValue: {} }, ], schemas: [NO_ERRORS_SCHEMA] - }).overrideComponent(WorkflowitemMyDSpaceResultDetailElementComponent, { + }).overrideComponent(WorkflowItemSearchResultListElementComponent, { set: { changeDetection: ChangeDetectionStrategy.Default } }).compileComponents(); })); beforeEach(async(() => { - fixture = TestBed.createComponent(WorkflowitemMyDSpaceResultDetailElementComponent); + fixture = TestBed.createComponent(WorkflowItemSearchResultListElementComponent); component = fixture.componentInstance; })); diff --git a/src/app/shared/object-list/my-dspace-result-list-element/workflow-item-search-result/workflow-item-search-result-list-element.component.ts b/src/app/shared/object-list/my-dspace-result-list-element/workflow-item-search-result/workflow-item-search-result-list-element.component.ts new file mode 100644 index 0000000000..faf03425f0 --- /dev/null +++ b/src/app/shared/object-list/my-dspace-result-list-element/workflow-item-search-result/workflow-item-search-result-list-element.component.ts @@ -0,0 +1,57 @@ +import { Component } from '@angular/core'; + +import { Observable } from 'rxjs'; +import { find } from 'rxjs/operators'; + +import { ViewMode } from '../../../../core/shared/view-mode.model'; +import { RemoteData } from '../../../../core/data/remote-data'; +import { isNotUndefined } from '../../../empty.util'; +import { WorkflowItem } from '../../../../core/submission/models/workflowitem.model'; +import { Item } from '../../../../core/shared/item.model'; +import { MyDspaceItemStatusType } from '../../../object-collection/shared/mydspace-item-status/my-dspace-item-status-type'; +import { listableObjectComponent } from '../../../object-collection/shared/listable-object/listable-object.decorator'; +import { WorkflowItemSearchResult } from '../../../object-collection/shared/workflow-item-search-result.model'; +import { SearchResultListElementComponent } from '../../search-result-list-element/search-result-list-element.component'; + +/** + * This component renders workflowitem object for the search result in the list view. + */ +@Component({ + selector: 'ds-workflow-item-my-dspace-result-list-element', + styleUrls: ['../../search-result-list-element/search-result-list-element.component.scss'], + templateUrl: './workflow-item-search-result-list-element.component.html', +}) + +@listableObjectComponent(WorkflowItemSearchResult, ViewMode.ListElement) +export class WorkflowItemSearchResultListElementComponent extends SearchResultListElementComponent { + + /** + * The item object that belonging to the result object + */ + public item: Item; + + /** + * Represent item's status + */ + public status = MyDspaceItemStatusType.WORKFLOW; + + /** + * Initialize all instance variables + */ + ngOnInit() { + super.ngOnInit(); + this.initItem(this.dso.item as Observable> ); + } + + /** + * Retrieve item from result object + */ + initItem(item$: Observable>) { + item$.pipe( + find((rd: RemoteData) => rd.hasSucceeded && isNotUndefined(rd.payload)) + ).subscribe((rd: RemoteData) => { + this.item = rd.payload; + }); + } + +} diff --git a/src/app/shared/object-list/my-dspace-result-list-element/workspaceitem-my-dspace-result/workspaceitem-my-dspace-result-list-element.component.html b/src/app/shared/object-list/my-dspace-result-list-element/workspace-item-search-result/workspace-item-search-result-list-element.component.html similarity index 100% rename from src/app/shared/object-list/my-dspace-result-list-element/workspaceitem-my-dspace-result/workspaceitem-my-dspace-result-list-element.component.html rename to src/app/shared/object-list/my-dspace-result-list-element/workspace-item-search-result/workspace-item-search-result-list-element.component.html diff --git a/src/app/shared/object-list/my-dspace-result-list-element/workspaceitem-my-dspace-result/workspaceitem-my-dspace-result-list-element.component.scss b/src/app/shared/object-list/my-dspace-result-list-element/workspace-item-search-result/workspace-item-search-result-list-element.component.scss similarity index 100% rename from src/app/shared/object-list/my-dspace-result-list-element/workspaceitem-my-dspace-result/workspaceitem-my-dspace-result-list-element.component.scss rename to src/app/shared/object-list/my-dspace-result-list-element/workspace-item-search-result/workspace-item-search-result-list-element.component.scss diff --git a/src/app/shared/object-detail/my-dspace-result-detail-element/workspaceitem-my-dspace-result/workspaceitem-my-dspace-result-detail-element.component.spec.ts b/src/app/shared/object-list/my-dspace-result-list-element/workspace-item-search-result/workspace-item-search-result-list-element.component.spec.ts similarity index 66% rename from src/app/shared/object-detail/my-dspace-result-detail-element/workspaceitem-my-dspace-result/workspaceitem-my-dspace-result-detail-element.component.spec.ts rename to src/app/shared/object-list/my-dspace-result-list-element/workspace-item-search-result/workspace-item-search-result-list-element.component.spec.ts index 0e16b9c0f6..349f32dfd6 100644 --- a/src/app/shared/object-detail/my-dspace-result-detail-element/workspaceitem-my-dspace-result/workspaceitem-my-dspace-result-detail-element.component.spec.ts +++ b/src/app/shared/object-list/my-dspace-result-list-element/workspace-item-search-result/workspace-item-search-result-list-element.component.spec.ts @@ -5,19 +5,19 @@ import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { of as observableOf } from 'rxjs'; import { Item } from '../../../../core/shared/item.model'; -import { WorkspaceitemMyDSpaceResultDetailElementComponent } from './workspaceitem-my-dspace-result-detail-element.component'; -import { WorkspaceitemMyDSpaceResult } from '../../../object-collection/shared/workspaceitem-my-dspace-result.model'; +import { WorkspaceItemSearchResultListElementComponent } from './workspace-item-search-result-list-element.component'; import { WorkspaceItem } from '../../../../core/submission/models/workspaceitem.model'; -import { RemoteData } from '../../../../core/data/remote-data'; import { MyDspaceItemStatusType } from '../../../object-collection/shared/mydspace-item-status/my-dspace-item-status-type'; import { createSuccessfulRemoteDataObject } from '../../../testing/utils'; +import { WorkflowItemSearchResult } from '../../../object-collection/shared/workflow-item-search-result.model'; +import { TruncatableService } from '../../../truncatable/truncatable.service'; -let component: WorkspaceitemMyDSpaceResultDetailElementComponent; -let fixture: ComponentFixture; +let component: WorkspaceItemSearchResultListElementComponent; +let fixture: ComponentFixture; const compIndex = 1; -const mockResultObject: WorkspaceitemMyDSpaceResult = new WorkspaceitemMyDSpaceResult(); +const mockResultObject: WorkflowItemSearchResult = new WorkflowItemSearchResult(); mockResultObject.hitHighlights = {}; const item = Object.assign(new Item(), { @@ -52,23 +52,22 @@ const item = Object.assign(new Item(), { const rd = createSuccessfulRemoteDataObject(item); mockResultObject.indexableObject = Object.assign(new WorkspaceItem(), { item: observableOf(rd) }); -describe('WorkspaceitemMyDSpaceResultDetailElementComponent', () => { +describe('WorkspaceItemSearchResultListElementComponent', () => { beforeEach(async(() => { TestBed.configureTestingModule({ imports: [NoopAnimationsModule], - declarations: [WorkspaceitemMyDSpaceResultDetailElementComponent], + declarations: [WorkspaceItemSearchResultListElementComponent], providers: [ - { provide: 'objectElementProvider', useValue: (mockResultObject) }, - { provide: 'indexElementProvider', useValue: (compIndex) } + { provide: TruncatableService, useValue: {} }, ], schemas: [NO_ERRORS_SCHEMA] - }).overrideComponent(WorkspaceitemMyDSpaceResultDetailElementComponent, { + }).overrideComponent(WorkspaceItemSearchResultListElementComponent, { set: { changeDetection: ChangeDetectionStrategy.Default } }).compileComponents(); })); beforeEach(async(() => { - fixture = TestBed.createComponent(WorkspaceitemMyDSpaceResultDetailElementComponent); + fixture = TestBed.createComponent(WorkspaceItemSearchResultListElementComponent); component = fixture.componentInstance; })); diff --git a/src/app/shared/object-list/my-dspace-result-list-element/workspace-item-search-result/workspace-item-search-result-list-element.component.ts b/src/app/shared/object-list/my-dspace-result-list-element/workspace-item-search-result/workspace-item-search-result-list-element.component.ts new file mode 100644 index 0000000000..830726c677 --- /dev/null +++ b/src/app/shared/object-list/my-dspace-result-list-element/workspace-item-search-result/workspace-item-search-result-list-element.component.ts @@ -0,0 +1,56 @@ +import { Component } from '@angular/core'; + +import { Observable } from 'rxjs'; +import { find } from 'rxjs/operators'; + +import { ViewMode } from '../../../../core/shared/view-mode.model'; +import { WorkspaceItem } from '../../../../core/submission/models/workspaceitem.model'; +import { RemoteData } from '../../../../core/data/remote-data'; +import { isNotUndefined } from '../../../empty.util'; +import { Item } from '../../../../core/shared/item.model'; +import { MyDspaceItemStatusType } from '../../../object-collection/shared/mydspace-item-status/my-dspace-item-status-type'; +import { listableObjectComponent } from '../../../object-collection/shared/listable-object/listable-object.decorator'; +import { WorkspaceItemSearchResult } from '../../../object-collection/shared/workspace-item-search-result.model'; +import { SearchResultListElementComponent } from '../../search-result-list-element/search-result-list-element.component'; + +/** + * This component renders workspaceitem object for the search result in the list view. + */ +@Component({ + selector: 'ds-workspace-item-search-result-list-element', + styleUrls: ['../../search-result-list-element/search-result-list-element.component.scss', './workspace-item-search-result-list-element.component.scss'], + templateUrl: './workspace-item-search-result-list-element.component.html', +}) + +@listableObjectComponent(WorkspaceItemSearchResult, ViewMode.ListElement) +export class WorkspaceItemSearchResultListElementComponent extends SearchResultListElementComponent { + + /** + * The item object that belonging to the result object + */ + item: Item; + + /** + * Represent item's status + */ + status = MyDspaceItemStatusType.WORKSPACE; + + /** + * Initialize all instance variables + */ + ngOnInit() { + super.ngOnInit(); + this.initItem(this.dso.item as Observable>); + } + + /** + * Retrieve item from result object + */ + initItem(item$: Observable>) { + item$.pipe( + find((rd: RemoteData) => rd.hasSucceeded && isNotUndefined(rd.payload)) + ).subscribe((rd: RemoteData) => { + this.item = rd.payload; + }); + } +} diff --git a/src/app/shared/object-list/object-list.component.html b/src/app/shared/object-list/object-list.component.html index 1fdc06d5bf..1d49ea09d7 100644 --- a/src/app/shared/object-list/object-list.component.html +++ b/src/app/shared/object-list/object-list.component.html @@ -12,7 +12,7 @@ (paginationChange)="onPaginationChange($event)">
  • - +
diff --git a/src/app/shared/object-list/object-list.component.ts b/src/app/shared/object-list/object-list.component.ts index afc376034f..1158085bb0 100644 --- a/src/app/shared/object-list/object-list.component.ts +++ b/src/app/shared/object-list/object-list.component.ts @@ -12,6 +12,9 @@ import { RemoteData } from '../../core/data/remote-data'; import { fadeIn } from '../animations/fade'; import { ListableObject } from '../object-collection/shared/listable-object.model'; import { PaginationComponentOptions } from '../pagination/pagination-component-options.model'; +import { ViewMode } from '../../core/shared/view-mode.model'; +import { Context } from '../../core/shared/context.model'; +import { CollectionElementLinkType } from '../object-collection/collection-element-link.type'; @Component({ changeDetection: ChangeDetectionStrategy.Default, @@ -22,17 +25,62 @@ import { PaginationComponentOptions } from '../pagination/pagination-component-o animations: [fadeIn] }) export class ObjectListComponent { + /** + * The view mode of the this component + */ + viewMode = ViewMode.ListElement; + /** + * The current pagination configuration + */ @Input() config: PaginationComponentOptions; + + /** + * The current sort configuration + */ @Input() sortConfig: SortOptions; + + /** + * Whether or not the list elements have a border + */ @Input() hasBorder = false; + + /** + * The whether or not the gear is hidden + */ @Input() hideGear = false; + + /** + * Whether or not the pager is visible when there is only a single page of results + */ @Input() hidePagerWhenSinglePage = true; + + /** + * The link type of the listable elements + */ + @Input() linkType: CollectionElementLinkType; + + /** + * The context of the listable elements + */ + @Input() context: Context; + + /** + * The current listable objects + */ private _objects: RemoteData>; + + /** + * Setter for the objects + * @param objects The new objects + */ @Input() set objects(objects: RemoteData>) { this._objects = objects; } + /** + * Getter to return the current objects + */ get objects() { return this._objects; } @@ -67,6 +115,9 @@ export class ObjectListComponent { */ @Output() sortDirectionChange: EventEmitter = new EventEmitter(); + /** + * An event fired when on of the pagination parameters changes + */ @Output() paginationChange: EventEmitter = new EventEmitter(); /** @@ -74,24 +125,42 @@ export class ObjectListComponent { * Event's payload equals to the newly selected sort field. */ @Output() sortFieldChange: EventEmitter = new EventEmitter(); - data: any = {}; + /** + * Emits the current page when it changes + * @param event The new page + */ onPageChange(event) { this.pageChange.emit(event); } + /** + * Emits the current page size when it changes + * @param event The new page size + */ onPageSizeChange(event) { this.pageSizeChange.emit(event); } - + /** + * Emits the current sort direction when it changes + * @param event The new sort direction + */ onSortDirectionChange(event) { this.sortDirectionChange.emit(event); } + /** + * Emits the current sort field when it changes + * @param event The new sort field + */ onSortFieldChange(event) { this.sortFieldChange.emit(event); } + /** + * Emits the current pagination when it changes + * @param event The new pagination + */ onPaginationChange(event) { this.paginationChange.emit(event); } diff --git a/src/app/shared/object-list/search-result-list-element/collection-search-result/collection-search-result-list-element.component.html b/src/app/shared/object-list/search-result-list-element/collection-search-result/collection-search-result-list-element.component.html index b4af631e83..3c787c47ce 100644 --- a/src/app/shared/object-list/search-result-list-element/collection-search-result/collection-search-result-list-element.component.html +++ b/src/app/shared/object-list/search-result-list-element/collection-search-result/collection-search-result-list-element.component.html @@ -1,2 +1,3 @@ - + +
diff --git a/src/app/shared/object-list/search-result-list-element/collection-search-result/collection-search-result-list-element.component.spec.ts b/src/app/shared/object-list/search-result-list-element/collection-search-result/collection-search-result-list-element.component.spec.ts index 7f5aaf5d9c..9de1e085b5 100644 --- a/src/app/shared/object-list/search-result-list-element/collection-search-result/collection-search-result-list-element.component.spec.ts +++ b/src/app/shared/object-list/search-result-list-element/collection-search-result/collection-search-result-list-element.component.spec.ts @@ -47,9 +47,7 @@ describe('CollectionSearchResultListElementComponent', () => { declarations: [ CollectionSearchResultListElementComponent, TruncatePipe ], providers: [ { provide: TruncatableService, useValue: truncatableServiceStub }, - { provide: 'objectElementProvider', useValue: (mockCollectionWithAbstract) } ], - schemas: [ NO_ERRORS_SCHEMA ] }).overrideComponent(CollectionSearchResultListElementComponent, { set: { changeDetection: ChangeDetectionStrategy.Default } @@ -59,6 +57,8 @@ describe('CollectionSearchResultListElementComponent', () => { beforeEach(async(() => { fixture = TestBed.createComponent(CollectionSearchResultListElementComponent); collectionSearchResultListElementComponent = fixture.componentInstance; + collectionSearchResultListElementComponent.object = mockCollectionWithAbstract; + fixture.detectChanges(); })); describe('When the collection has an abstract', () => { diff --git a/src/app/shared/object-list/search-result-list-element/collection-search-result/collection-search-result-list-element.component.ts b/src/app/shared/object-list/search-result-list-element/collection-search-result/collection-search-result-list-element.component.ts index 2205155bbd..9e09068ddf 100644 --- a/src/app/shared/object-list/search-result-list-element/collection-search-result/collection-search-result-list-element.component.ts +++ b/src/app/shared/object-list/search-result-list-element/collection-search-result/collection-search-result-list-element.component.ts @@ -1,17 +1,17 @@ import { Component } from '@angular/core'; - -import { renderElementsFor } from '../../../object-collection/shared/dso-element-decorator'; - import { SearchResultListElementComponent } from '../search-result-list-element.component'; import { Collection } from '../../../../core/shared/collection.model'; -import { SetViewMode } from '../../../view-mode'; import { CollectionSearchResult } from '../../../object-collection/shared/collection-search-result.model'; +import { ViewMode } from '../../../../core/shared/view-mode.model'; +import { listableObjectComponent } from '../../../object-collection/shared/listable-object/listable-object.decorator'; @Component({ selector: 'ds-collection-search-result-list-element', styleUrls: ['../search-result-list-element.component.scss', 'collection-search-result-list-element.component.scss'], templateUrl: 'collection-search-result-list-element.component.html' }) - -@renderElementsFor(CollectionSearchResult, SetViewMode.List) +/** + * Component representing a collection search result in list view + */ +@listableObjectComponent(CollectionSearchResult, ViewMode.ListElement) export class CollectionSearchResultListElementComponent extends SearchResultListElementComponent {} diff --git a/src/app/shared/object-list/search-result-list-element/community-search-result/community-search-result-list-element.component.html b/src/app/shared/object-list/search-result-list-element/community-search-result/community-search-result-list-element.component.html index 9444a63771..32834fefee 100644 --- a/src/app/shared/object-list/search-result-list-element/community-search-result/community-search-result-list-element.component.html +++ b/src/app/shared/object-list/search-result-list-element/community-search-result/community-search-result-list-element.component.html @@ -1,2 +1,3 @@ - + +
diff --git a/src/app/shared/object-list/search-result-list-element/community-search-result/community-search-result-list-element.component.spec.ts b/src/app/shared/object-list/search-result-list-element/community-search-result/community-search-result-list-element.component.spec.ts index 691a69dde4..2bf61c2ab9 100644 --- a/src/app/shared/object-list/search-result-list-element/community-search-result/community-search-result-list-element.component.spec.ts +++ b/src/app/shared/object-list/search-result-list-element/community-search-result/community-search-result-list-element.component.spec.ts @@ -47,7 +47,6 @@ describe('CommunitySearchResultListElementComponent', () => { declarations: [ CommunitySearchResultListElementComponent, TruncatePipe ], providers: [ { provide: TruncatableService, useValue: truncatableServiceStub }, - { provide: 'objectElementProvider', useValue: (mockCommunityWithAbstract) } ], schemas: [ NO_ERRORS_SCHEMA ] @@ -59,6 +58,8 @@ describe('CommunitySearchResultListElementComponent', () => { beforeEach(async(() => { fixture = TestBed.createComponent(CommunitySearchResultListElementComponent); communitySearchResultListElementComponent = fixture.componentInstance; + communitySearchResultListElementComponent.object = mockCommunityWithAbstract; + fixture.detectChanges(); })); describe('When the community has an abstract', () => { diff --git a/src/app/shared/object-list/search-result-list-element/community-search-result/community-search-result-list-element.component.ts b/src/app/shared/object-list/search-result-list-element/community-search-result/community-search-result-list-element.component.ts index 3f7e08d11c..b2fd695b39 100644 --- a/src/app/shared/object-list/search-result-list-element/community-search-result/community-search-result-list-element.component.ts +++ b/src/app/shared/object-list/search-result-list-element/community-search-result/community-search-result-list-element.component.ts @@ -1,19 +1,19 @@ import { Component } from '@angular/core'; - -import { renderElementsFor } from '../../../object-collection/shared/dso-element-decorator'; - import { SearchResultListElementComponent } from '../search-result-list-element.component'; import { Community } from '../../../../core/shared/community.model'; -import { SetViewMode } from '../../../view-mode'; import { CommunitySearchResult } from '../../../object-collection/shared/community-search-result.model'; +import { ViewMode } from '../../../../core/shared/view-mode.model'; +import { listableObjectComponent } from '../../../object-collection/shared/listable-object/listable-object.decorator'; @Component({ selector: 'ds-community-search-result-list-element', styleUrls: ['../search-result-list-element.component.scss', 'community-search-result-list-element.component.scss'], templateUrl: 'community-search-result-list-element.component.html' }) - -@renderElementsFor(CommunitySearchResult, SetViewMode.List) +/** + * Component representing a community search result in list view + */ +@listableObjectComponent(CommunitySearchResult, ViewMode.ListElement) export class CommunitySearchResultListElementComponent extends SearchResultListElementComponent { } diff --git a/src/app/shared/object-list/search-result-list-element/item-search-result/item-search-result-list-element.component.html b/src/app/shared/object-list/search-result-list-element/item-search-result/item-search-result-list-element.component.html deleted file mode 100644 index 051a27bde7..0000000000 --- a/src/app/shared/object-list/search-result-list-element/item-search-result/item-search-result-list-element.component.html +++ /dev/null @@ -1,2 +0,0 @@ - - diff --git a/src/app/shared/object-list/search-result-list-element/item-search-result/item-search-result-list-element.component.spec.ts b/src/app/shared/object-list/search-result-list-element/item-search-result/item-search-result-list-element.component.spec.ts deleted file mode 100644 index 8f41018404..0000000000 --- a/src/app/shared/object-list/search-result-list-element/item-search-result/item-search-result-list-element.component.spec.ts +++ /dev/null @@ -1,60 +0,0 @@ -import { ItemSearchResultListElementComponent } from './item-search-result-list-element.component'; -import { async, ComponentFixture, TestBed } from '@angular/core/testing'; -import { of as observableOf } from 'rxjs'; -import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA } from '@angular/core'; -import { By } from '@angular/platform-browser'; -import { TruncatePipe } from '../../../utils/truncate.pipe'; -import { Item } from '../../../../core/shared/item.model'; -import { TruncatableService } from '../../../truncatable/truncatable.service'; -import { NoopAnimationsModule } from '@angular/platform-browser/animations'; -import { ItemSearchResult } from '../../../object-collection/shared/item-search-result.model'; -import { TranslateModule } from '@ngx-translate/core'; - -let itemSearchResultListElementComponent: ItemSearchResultListElementComponent; -let fixture: ComponentFixture; - -const truncatableServiceStub: any = { - isCollapsed: (id: number) => observableOf(true), -}; - -const type = 'authorOfPublication'; - -const mockItemWithRelationshipType: ItemSearchResult = new ItemSearchResult(); -mockItemWithRelationshipType.hitHighlights = {}; -mockItemWithRelationshipType.indexableObject = Object.assign(new Item(), { - bitstreams: observableOf({}), - metadata: { - 'relationship.type': [ - { - language: 'en_US', - value: type - } - ] - } -}); - -describe('ItemSearchResultListElementComponent', () => { - beforeEach(async(() => { - TestBed.configureTestingModule({ - imports: [TranslateModule.forRoot(), NoopAnimationsModule], - declarations: [ItemSearchResultListElementComponent, TruncatePipe], - providers: [ - { provide: TruncatableService, useValue: truncatableServiceStub }, - { provide: 'objectElementProvider', useValue: (mockItemWithRelationshipType) } - ], - schemas: [NO_ERRORS_SCHEMA] - }).overrideComponent(ItemSearchResultListElementComponent, { - set: { changeDetection: ChangeDetectionStrategy.Default } - }).compileComponents(); - })); - - beforeEach(async(() => { - fixture = TestBed.createComponent(ItemSearchResultListElementComponent); - itemSearchResultListElementComponent = fixture.componentInstance; - })); - - it('should show a badge on top of the list element', () => { - const badge = fixture.debugElement.query(By.css('ds-item-type-badge')).componentInstance; - expect(badge.object).toBe(mockItemWithRelationshipType); - }); -}); diff --git a/src/app/shared/object-list/search-result-list-element/item-search-result/item-search-result-list-element.component.ts b/src/app/shared/object-list/search-result-list-element/item-search-result/item-search-result-list-element.component.ts deleted file mode 100644 index 5bd3c8ff5a..0000000000 --- a/src/app/shared/object-list/search-result-list-element/item-search-result/item-search-result-list-element.component.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { Component } from '@angular/core'; -import { DSpaceObject } from '../../../../core/shared/dspace-object.model'; -import { Item } from '../../../../core/shared/item.model'; -import { focusBackground } from '../../../animations/focus'; -import { hasValue } from '../../../empty.util'; - -import { renderElementsFor } from '../../../object-collection/shared/dso-element-decorator'; -import { ItemSearchResult } from '../../../object-collection/shared/item-search-result.model'; -import { SetViewMode } from '../../../view-mode'; -import { SearchResultListElementComponent } from '../search-result-list-element.component'; -import { ItemViewMode } from '../../../items/item-type-decorator'; - -@Component({ - selector: 'ds-item-search-result-list-element', - styleUrls: ['../search-result-list-element.component.scss', 'item-search-result-list-element.component.scss'], - templateUrl: 'item-search-result-list-element.component.html', - animations: [focusBackground], - -}) - -@renderElementsFor(ItemSearchResult, SetViewMode.List) -export class ItemSearchResultListElementComponent extends SearchResultListElementComponent { - viewMode = ItemViewMode.Element; - -} diff --git a/src/app/shared/object-list/search-result-list-element/item-search-result/item-types/publication/publication-search-result-list-element.component.html b/src/app/shared/object-list/search-result-list-element/item-search-result/item-types/publication/publication-search-result-list-element.component.html new file mode 100644 index 0000000000..3d2604585d --- /dev/null +++ b/src/app/shared/object-list/search-result-list-element/item-search-result/item-types/publication/publication-search-result-list-element.component.html @@ -0,0 +1,29 @@ + + + + + + + + (, ) + + + + ; + + + + +
+ + +
+
diff --git a/src/app/shared/object-list/search-result-list-element/item-search-result/item-types/publication/publication-search-result-list-element.component.scss b/src/app/shared/object-list/search-result-list-element/item-search-result/item-types/publication/publication-search-result-list-element.component.scss new file mode 100644 index 0000000000..5e4536cf95 --- /dev/null +++ b/src/app/shared/object-list/search-result-list-element/item-search-result/item-types/publication/publication-search-result-list-element.component.scss @@ -0,0 +1 @@ +@import '../../../../../../../styles/variables'; diff --git a/src/app/shared/object-list/search-result-list-element/item-search-result/item-types/publication/publication-search-result-list-element.component.spec.ts b/src/app/shared/object-list/search-result-list-element/item-search-result/item-types/publication/publication-search-result-list-element.component.spec.ts new file mode 100644 index 0000000000..82703f1ee0 --- /dev/null +++ b/src/app/shared/object-list/search-result-list-element/item-search-result/item-types/publication/publication-search-result-list-element.component.spec.ts @@ -0,0 +1,182 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA } from '@angular/core'; +import { By } from '@angular/platform-browser'; +import { of as observableOf } from 'rxjs'; +import { PublicationSearchResultListElementComponent } from './publication-search-result-list-element.component'; +import { Item } from '../../../../../../core/shared/item.model'; +import { TruncatePipe } from '../../../../../utils/truncate.pipe'; +import { TruncatableService } from '../../../../../truncatable/truncatable.service'; +import { ItemSearchResult } from '../../../../../object-collection/shared/item-search-result.model'; + +let publicationListElementComponent: PublicationSearchResultListElementComponent; +let fixture: ComponentFixture; + +const mockItemWithMetadata: ItemSearchResult = Object.assign(new ItemSearchResult(), { + indexableObject: + Object.assign(new Item(), { + bitstreams: observableOf({}), + 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' + } + ] + } + }) +}); +const mockItemWithoutMetadata: ItemSearchResult = Object.assign(new ItemSearchResult(), { + indexableObject: + Object.assign(new Item(), { + bitstreams: observableOf({}), + metadata: { + 'dc.title': [ + { + language: 'en_US', + value: 'This is just another title' + } + ] + } + }) +}); + +describe('PublicationListElementComponent', () => { + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [PublicationSearchResultListElementComponent, TruncatePipe], + providers: [ + { provide: TruncatableService, useValue: {} } + ], + + schemas: [NO_ERRORS_SCHEMA] + }).overrideComponent(PublicationSearchResultListElementComponent, { + set: { changeDetection: ChangeDetectionStrategy.Default } + }).compileComponents(); + })); + + beforeEach(async(() => { + fixture = TestBed.createComponent(PublicationSearchResultListElementComponent); + publicationListElementComponent = fixture.componentInstance; + + })); + + describe('When the item has an author', () => { + beforeEach(() => { + publicationListElementComponent.object = mockItemWithMetadata; + fixture.detectChanges(); + }); + + it('should show the author paragraph', () => { + const itemAuthorField = fixture.debugElement.query(By.css('span.item-list-authors')); + expect(itemAuthorField).not.toBeNull(); + }); + }); + + describe('When the item has no author', () => { + beforeEach(() => { + publicationListElementComponent.object = mockItemWithoutMetadata; + fixture.detectChanges(); + }); + + it('should not show the author paragraph', () => { + const itemAuthorField = fixture.debugElement.query(By.css('span.item-list-authors')); + expect(itemAuthorField).toBeNull(); + }); + }); + + describe('When the item has a publisher', () => { + beforeEach(() => { + publicationListElementComponent.object = mockItemWithMetadata; + fixture.detectChanges(); + }); + + it('should show the publisher span', () => { + const publisherField = fixture.debugElement.query(By.css('span.item-list-publisher')); + expect(publisherField).not.toBeNull(); + }); + }); + + describe('When the item has no publisher', () => { + beforeEach(() => { + publicationListElementComponent.object = mockItemWithoutMetadata; + fixture.detectChanges(); + }); + + it('should not show the publisher span', () => { + const publisherField = fixture.debugElement.query(By.css('span.item-list-publisher')); + expect(publisherField).toBeNull(); + }); + }); + + describe('When the item has an issuedate', () => { + beforeEach(() => { + publicationListElementComponent.object = mockItemWithMetadata; + fixture.detectChanges(); + }); + + it('should show the issuedate span', () => { + const dateField = fixture.debugElement.query(By.css('span.item-list-date')); + expect(dateField).not.toBeNull(); + }); + }); + + describe('When the item has no issuedate', () => { + beforeEach(() => { + publicationListElementComponent.object = mockItemWithoutMetadata; + fixture.detectChanges(); + }); + + it('should not show the issuedate span', () => { + const dateField = fixture.debugElement.query(By.css('span.item-list-date')); + expect(dateField).toBeNull(); + }); + }); + + describe('When the item has an abstract', () => { + beforeEach(() => { + publicationListElementComponent.object = mockItemWithMetadata; + fixture.detectChanges(); + }); + + it('should show the abstract span', () => { + const abstractField = fixture.debugElement.query(By.css('div.item-list-abstract')); + expect(abstractField).not.toBeNull(); + }); + }); + + describe('When the item has no abstract', () => { + beforeEach(() => { + publicationListElementComponent.object = mockItemWithoutMetadata; + fixture.detectChanges(); + }); + + it('should not show the abstract span', () => { + const abstractField = fixture.debugElement.query(By.css('div.item-list-abstract')); + expect(abstractField).toBeNull(); + }); + }); +}); diff --git a/src/app/shared/object-list/search-result-list-element/item-search-result/item-types/publication/publication-search-result-list-element.component.ts b/src/app/shared/object-list/search-result-list-element/item-search-result/item-types/publication/publication-search-result-list-element.component.ts new file mode 100644 index 0000000000..3e0db60b4c --- /dev/null +++ b/src/app/shared/object-list/search-result-list-element/item-search-result/item-types/publication/publication-search-result-list-element.component.ts @@ -0,0 +1,19 @@ +import { Component } from '@angular/core'; +import { listableObjectComponent } from '../../../../../object-collection/shared/listable-object/listable-object.decorator'; +import { ViewMode } from '../../../../../../core/shared/view-mode.model'; +import { ItemSearchResult } from '../../../../../object-collection/shared/item-search-result.model'; +import { SearchResultListElementComponent } from '../../../search-result-list-element.component'; +import { Item } from '../../../../../../core/shared/item.model'; + +@listableObjectComponent('PublicationSearchResult', ViewMode.ListElement) +@listableObjectComponent(ItemSearchResult, ViewMode.ListElement) +@Component({ + selector: 'ds-publication-search-result-list-element', + styleUrls: ['./publication-search-result-list-element.component.scss'], + templateUrl: './publication-search-result-list-element.component.html' +}) +/** + * The component for displaying a list element for an item search result of the type Publication + */ +export class PublicationSearchResultListElementComponent extends SearchResultListElementComponent { +} 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 7017f3f48b..93fc00bc87 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 @@ -1,26 +1,32 @@ -import { Component, Inject } from '@angular/core'; +import { Component, Inject, OnInit } from '@angular/core'; import { Observable } from 'rxjs'; import { SearchResult } from '../../../+search-page/search-result.model'; import { DSpaceObject } from '../../../core/shared/dspace-object.model'; import { hasValue } from '../../empty.util'; -import { ListableObject } from '../../object-collection/shared/listable-object.model'; import { AbstractListableElementComponent } from '../../object-collection/shared/object-collection-element/abstract-listable-element.component'; import { TruncatableService } from '../../truncatable/truncatable.service'; import { Metadata } from '../../../core/shared/metadata.utils'; -import { MetadataMap } from '../../../core/shared/metadata.models'; @Component({ selector: 'ds-search-result-list-element', template: `` }) -export class SearchResultListElementComponent, K extends DSpaceObject> extends AbstractListableElementComponent { +export class SearchResultListElementComponent, K extends DSpaceObject> extends AbstractListableElementComponent implements OnInit { + /** + * The DSpaceObject of the search result + */ dso: K; - metadata: MetadataMap; - public constructor(@Inject('objectElementProvider') public listable: ListableObject, protected truncatableService: TruncatableService) { - super(listable); + public constructor(protected truncatableService: TruncatableService) { + super(); + } + + /** + * Retrieve the dso from the search result + */ + ngOnInit(): void { if (hasValue(this.object)) { this.dso = this.object.indexableObject; } @@ -46,7 +52,11 @@ export class SearchResultListElementComponent, K exten return Metadata.firstValue([this.object.hitHighlights, this.dso.metadata], keyOrKeys); } + /** + * Emits if the list element is currently collapsed or not + */ isCollapsed(): Observable { return this.truncatableService.isCollapsed(this.dso.id); } + } diff --git a/src/app/shared/object-list/wrapper-list-element/wrapper-list-element.component.html b/src/app/shared/object-list/wrapper-list-element/wrapper-list-element.component.html deleted file mode 100644 index db87596f31..0000000000 --- a/src/app/shared/object-list/wrapper-list-element/wrapper-list-element.component.html +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/app/shared/object-list/wrapper-list-element/wrapper-list-element.component.scss b/src/app/shared/object-list/wrapper-list-element/wrapper-list-element.component.scss deleted file mode 100644 index 8b13789179..0000000000 --- a/src/app/shared/object-list/wrapper-list-element/wrapper-list-element.component.scss +++ /dev/null @@ -1 +0,0 @@ - diff --git a/src/app/shared/object-list/wrapper-list-element/wrapper-list-element.component.ts b/src/app/shared/object-list/wrapper-list-element/wrapper-list-element.component.ts deleted file mode 100644 index 29b1364a75..0000000000 --- a/src/app/shared/object-list/wrapper-list-element/wrapper-list-element.component.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { Component, Injector, Input, OnInit } from '@angular/core'; -import { SetViewMode } from '../../view-mode'; -import { GenericConstructor } from '../../../core/shared/generic-constructor'; -import { rendersDSOType } from '../../object-collection/shared/dso-element-decorator' -import { ListableObject } from '../../object-collection/shared/listable-object.model'; - -@Component({ - selector: 'ds-wrapper-list-element', - styleUrls: ['./wrapper-list-element.component.scss'], - templateUrl: './wrapper-list-element.component.html' -}) -export class WrapperListElementComponent implements OnInit { - @Input() object: ListableObject; - @Input() index: number; - objectInjector: Injector; - listElement: any; - - constructor(private injector: Injector) {} - - ngOnInit(): void { - this.objectInjector = Injector.create({ - providers: [ - { provide: 'objectElementProvider', useFactory: () => (this.object), deps:[] }, - { provide: 'indexElementProvider', useFactory: () => (this.index), deps:[] } - ], - parent: this.injector - }); - this.listElement = this.getListElement(); - } - - private getListElement(): string { - const f: GenericConstructor = this.object.constructor as GenericConstructor; - return rendersDSOType(f, SetViewMode.List); - } -} diff --git a/src/app/shared/shared.module.ts b/src/app/shared/shared.module.ts index ed9f8efa93..cce01012e5 100644 --- a/src/app/shared/shared.module.ts +++ b/src/app/shared/shared.module.ts @@ -9,8 +9,6 @@ import { NgbDatepickerModule, NgbModule, NgbTimepickerModule, NgbTypeaheadModule import { TranslateModule } from '@ngx-translate/core'; import { NgxPaginationModule } from 'ngx-pagination'; -import { ItemTypeSwitcherComponent } from './items/switcher/item-type-switcher.component'; -import { TypedItemSearchResultListElementComponent } from './object-list/item-list-element/item-types/typed-item-search-result-list-element.component'; import { PublicationListElementComponent } from './object-list/item-list-element/item-types/publication/publication-list-element.component'; import { FileUploadModule } from 'ng2-file-upload'; @@ -24,15 +22,11 @@ import { ConsolePipe } from './utils/console.pipe'; import { CollectionListElementComponent } from './object-list/collection-list-element/collection-list-element.component'; import { CommunityListElementComponent } from './object-list/community-list-element/community-list-element.component'; -import { ItemListElementComponent } from './object-list/item-list-element/item-list-element.component'; import { SearchResultListElementComponent } from './object-list/search-result-list-element/search-result-list-element.component'; -import { WrapperListElementComponent } from './object-list/wrapper-list-element/wrapper-list-element.component'; import { ObjectListComponent } from './object-list/object-list.component'; import { CollectionGridElementComponent } from './object-grid/collection-grid-element/collection-grid-element.component'; import { CommunityGridElementComponent } from './object-grid/community-grid-element/community-grid-element.component'; -import { ItemGridElementComponent } from './object-grid/item-grid-element/item-grid-element.component'; import { AbstractListableElementComponent } from './object-collection/shared/object-collection-element/abstract-listable-element.component'; -import { WrapperGridElementComponent } from './object-grid/wrapper-grid-element/wrapper-grid-element.component'; import { ObjectGridComponent } from './object-grid/object-grid.component'; import { ObjectCollectionComponent } from './object-collection/object-collection.component'; import { ComcolPageContentComponent } from './comcol-page-content/comcol-page-content.component'; @@ -81,12 +75,10 @@ import { DsDatePickerComponent } from './form/builder/ds-dynamic-form-ui/models/ import { DsDynamicLookupComponent } from './form/builder/ds-dynamic-form-ui/models/lookup/dynamic-lookup.component'; import { MockAdminGuard } from './mocks/mock-admin-guard.service'; import { AlertComponent } from './alert/alert.component'; -import { MyDSpaceResultListElementComponent } from './object-list/my-dspace-result-list-element/my-dspace-result-list-element.component'; -import { MyDSpaceResultDetailElementComponent } from './object-detail/my-dspace-result-detail-element/my-dspace-result-detail-element.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 { WrapperDetailElementComponent } from './object-detail/wrapper-detail-element/wrapper-detail-element.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'; @@ -128,7 +120,6 @@ import { CreateItemParentSelectorComponent } from './dso-selector/modal-wrappers import { CreateCollectionParentSelectorComponent } from './dso-selector/modal-wrappers/create-collection-parent-selector/create-collection-parent-selector.component'; import { CommunitySearchResultListElementComponent } from './object-list/search-result-list-element/community-search-result/community-search-result-list-element.component'; import { CollectionSearchResultListElementComponent } from './object-list/search-result-list-element/collection-search-result/collection-search-result-list-element.component'; -import { ItemSearchResultListElementComponent } from './object-list/search-result-list-element/item-search-result/item-search-result-list-element.component'; import { EditItemSelectorComponent } from './dso-selector/modal-wrappers/edit-item-selector/edit-item-selector.component'; import { EditCommunitySelectorComponent } from './dso-selector/modal-wrappers/edit-community-selector/edit-community-selector.component'; import { EditCollectionSelectorComponent } from './dso-selector/modal-wrappers/edit-collection-selector/edit-collection-selector.component'; @@ -143,9 +134,16 @@ import { ItemSelectComponent } from './object-select/item-select/item-select.com import { CollectionSelectComponent } from './object-select/collection-select/collection-select.component'; import { FilterInputSuggestionsComponent } from './input-suggestions/filter-suggestions/filter-input-suggestions.component'; import { DsoInputSuggestionsComponent } from './input-suggestions/dso-input-suggestions/dso-input-suggestions.component'; -import { TypedItemSearchResultGridElementComponent } from './object-grid/item-grid-element/item-types/typed-item-search-result-grid-element.component'; import { PublicationGridElementComponent } from './object-grid/item-grid-element/item-types/publication/publication-grid-element.component'; import { ItemTypeBadgeComponent } from './object-list/item-type-badge/item-type-badge.component'; +import { MetadataRepresentationLoaderComponent } from './metadata-representation/metadata-representation-loader.component'; +import { MetadataRepresentationDirective } from './metadata-representation/metadata-representation.directive'; +import { ListableObjectComponentLoaderComponent } from './object-collection/shared/listable-object/listable-object-component-loader.component'; +import { PublicationSearchResultListElementComponent } from './object-list/search-result-list-element/item-search-result/item-types/publication/publication-search-result-list-element.component'; +import { PublicationSearchResultGridElementComponent } from './object-grid/search-result-grid-element/item-search-result/publication/publication-search-result-grid-element.component'; +import { ListableObjectDirective } from './object-collection/shared/listable-object/listable-object.directive'; +import { CommunitySearchResultGridElementComponent } from './object-grid/search-result-grid-element/community-search-result/community-search-result-grid-element.component'; +import { CollectionSearchResultGridElementComponent } from './object-grid/search-result-grid-element/collection-search-result/collection-search-result-grid-element.component'; import { ItemMetadataRepresentationListElementComponent } from './object-list/metadata-representation-list-element/item/item-metadata-representation-list-element.component'; const MODULES = [ @@ -227,16 +225,12 @@ const COMPONENTS = [ ObjectDetailComponent, ObjectGridComponent, AbstractListableElementComponent, - WrapperListElementComponent, - WrapperDetailElementComponent, - WrapperGridElementComponent, ObjectCollectionComponent, PaginationComponent, SearchFormComponent, ThumbnailComponent, GridThumbnailComponent, UploaderComponent, - WrapperListElementComponent, ItemListPreviewComponent, MyDSpaceItemStatusComponent, ItemSubmitterComponent, @@ -266,34 +260,38 @@ const COMPONENTS = [ EditItemSelectorComponent, CommunitySearchResultListElementComponent, CollectionSearchResultListElementComponent, - ItemSearchResultListElementComponent, - TypedItemSearchResultListElementComponent, - TypedItemSearchResultGridElementComponent, - ItemTypeSwitcherComponent, + CommunitySearchResultGridElementComponent, + CollectionSearchResultGridElementComponent, + ListableObjectComponentLoaderComponent, + CollectionListElementComponent, + CommunityListElementComponent, + CollectionGridElementComponent, + CommunityGridElementComponent, BrowseByComponent, ItemTypeBadgeComponent, ItemSelectComponent, - CollectionSelectComponent + CollectionSelectComponent, + MetadataRepresentationLoaderComponent ]; const ENTRY_COMPONENTS = [ // put shared entry components (components that are created dynamically) here - ItemListElementComponent, CollectionListElementComponent, CommunityListElementComponent, - MyDSpaceResultListElementComponent, SearchResultListElementComponent, CommunitySearchResultListElementComponent, CollectionSearchResultListElementComponent, - ItemSearchResultListElementComponent, - ItemGridElementComponent, CollectionGridElementComponent, CommunityGridElementComponent, + CommunitySearchResultGridElementComponent, + CollectionSearchResultGridElementComponent, SearchResultGridElementComponent, PublicationListElementComponent, PublicationGridElementComponent, + PublicationSearchResultListElementComponent, + PublicationSearchResultGridElementComponent, BrowseEntryListElementComponent, - MyDSpaceResultDetailElementComponent, + SearchResultDetailElementComponent, SearchResultGridElementComponent, DsDynamicListComponent, DsDynamicLookupComponent, @@ -343,7 +341,9 @@ const DIRECTIVES = [ AuthorityConfidenceStateDirective, InListValidator, AutoFocusDirective, - RoleDirective + RoleDirective, + MetadataRepresentationDirective, + ListableObjectDirective ]; @NgModule({ @@ -356,7 +356,8 @@ const DIRECTIVES = [ ...COMPONENTS, ...DIRECTIVES, ...ENTRY_COMPONENTS, - ...SHARED_ITEM_PAGE_COMPONENTS + ...SHARED_ITEM_PAGE_COMPONENTS, + PublicationSearchResultListElementComponent ], providers: [ ...PROVIDERS diff --git a/src/app/shared/testing/search-service-stub.ts b/src/app/shared/testing/search-service-stub.ts index d886604ef2..b64fdd1330 100644 --- a/src/app/shared/testing/search-service-stub.ts +++ b/src/app/shared/testing/search-service-stub.ts @@ -1,22 +1,22 @@ import {of as observableOf, Observable , BehaviorSubject } from 'rxjs'; -import { SetViewMode } from '../view-mode'; +import { ViewMode } from '../../core/shared/view-mode.model'; export class SearchServiceStub { - private _viewMode: SetViewMode; + private _viewMode: ViewMode; private subject?: BehaviorSubject = new BehaviorSubject(this.testViewMode); viewMode = this.subject.asObservable(); constructor(private searchLink: string = '/search') { - this.setViewMode(SetViewMode.List); + this.setViewMode(ViewMode.ListElement); } - getViewMode(): Observable { + getViewMode(): Observable { return this.viewMode; } - setViewMode(viewMode: SetViewMode) { + setViewMode(viewMode: ViewMode) { this.testViewMode = viewMode; } @@ -24,11 +24,11 @@ export class SearchServiceStub { return null; } - get testViewMode(): SetViewMode { + get testViewMode(): ViewMode { return this._viewMode; } - set testViewMode(viewMode: SetViewMode) { + set testViewMode(viewMode: ViewMode) { this._viewMode = viewMode; this.subject.next(viewMode); } diff --git a/src/app/shared/testing/utils.ts b/src/app/shared/testing/utils.ts index 4a551582ee..afd048096a 100644 --- a/src/app/shared/testing/utils.ts +++ b/src/app/shared/testing/utils.ts @@ -121,3 +121,14 @@ export function createPendingRemoteDataObject(object?: T): RemoteData { export function createPendingRemoteDataObject$(object?: T): Observable> { return observableOf(createPendingRemoteDataObject(object)); } + +/** + * Creates a jasmine spy for an exported function + * @param target The object to spy on + * @param prop The property/function to spy on + */ +export function spyOnExported(target: T, prop: keyof T): jasmine.Spy { + const spy = jasmine.createSpy(`${prop}Spy`); + spyOnProperty(target, prop).and.returnValue(spy); + return spy; +} diff --git a/src/app/shared/view-mode-switch/view-mode-switch.component.html b/src/app/shared/view-mode-switch/view-mode-switch.component.html index 905cf29bac..b4c1c18d4f 100644 --- a/src/app/shared/view-mode-switch/view-mode-switch.component.html +++ b/src/app/shared/view-mode-switch/view-mode-switch.component.html @@ -1,31 +1,31 @@
- - - diff --git a/src/app/shared/view-mode-switch/view-mode-switch.component.spec.ts b/src/app/shared/view-mode-switch/view-mode-switch.component.spec.ts index 2fe405de3f..cc0175231e 100644 --- a/src/app/shared/view-mode-switch/view-mode-switch.component.spec.ts +++ b/src/app/shared/view-mode-switch/view-mode-switch.component.spec.ts @@ -8,8 +8,8 @@ import { ChangeDetectionStrategy, Component } from '@angular/core'; import { SearchService } from '../../+search-page/search-service/search.service'; import { ViewModeSwitchComponent } from './view-mode-switch.component'; -import { SetViewMode } from '../view-mode'; import { SearchServiceStub } from '../testing/search-service-stub'; +import { ViewMode } from '../../core/shared/view-mode.model'; @Component({ template: '' }) class DummyComponent { } @@ -55,19 +55,19 @@ describe('ViewModeSwitchComponent', () => { }); it('should set list button as active when on list mode', fakeAsync(() => { - searchService.setViewMode(SetViewMode.List); + searchService.setViewMode(ViewMode.ListElement); tick(); fixture.detectChanges(); - expect(comp.currentMode).toBe(SetViewMode.List); + expect(comp.currentMode).toBe(ViewMode.ListElement); expect(listButton.classList).toContain('active'); expect(gridButton.classList).not.toContain('active'); })); it('should set grid button as active when on grid mode', fakeAsync(() => { - searchService.setViewMode(SetViewMode.Grid); + searchService.setViewMode(ViewMode.GridElement); tick(); fixture.detectChanges(); - expect(comp.currentMode).toBe(SetViewMode.Grid); + expect(comp.currentMode).toBe(ViewMode.GridElement); expect(listButton.classList).not.toContain('active'); expect(gridButton.classList).toContain('active'); })); diff --git a/src/app/shared/view-mode-switch/view-mode-switch.component.ts b/src/app/shared/view-mode-switch/view-mode-switch.component.ts index dc355c6409..d406573646 100644 --- a/src/app/shared/view-mode-switch/view-mode-switch.component.ts +++ b/src/app/shared/view-mode-switch/view-mode-switch.component.ts @@ -22,16 +22,26 @@ export class ViewModeSwitchComponent implements OnInit, OnDestroy { */ @Input() inPlaceSearch; - currentMode: ViewMode = ViewMode.List; + /** + * The current view mode + */ + currentMode: ViewMode = ViewMode.ListElement; + + /** + * All available view modes + */ viewModeEnum = ViewMode; private sub: Subscription; constructor(private searchService: SearchService) { } + /** + * Initialize the instance variables + */ ngOnInit(): void { if (isEmpty(this.viewModeList)) { - this.viewModeList = [ViewMode.List, ViewMode.Grid]; + this.viewModeList = [ViewMode.ListElement, ViewMode.GridElement]; } this.sub = this.searchService.getViewMode().subscribe((viewMode: ViewMode) => { @@ -39,6 +49,10 @@ export class ViewModeSwitchComponent implements OnInit, OnDestroy { }); } + /** + * Switch view modes + * @param viewMode The new view mode + */ switchViewTo(viewMode: ViewMode) { this.searchService.setViewMode(viewMode, this.getSearchLinkParts()); } @@ -49,6 +63,10 @@ export class ViewModeSwitchComponent implements OnInit, OnDestroy { } } + /** + * Whether or not to show a certain view mode + * @param viewMode The view mode to check for + */ isToShow(viewMode: ViewMode) { return this.viewModeList && this.viewModeList.includes(viewMode); } diff --git a/src/app/shared/view-mode.ts b/src/app/shared/view-mode.ts deleted file mode 100644 index 826d467d6f..0000000000 --- a/src/app/shared/view-mode.ts +++ /dev/null @@ -1,15 +0,0 @@ -/** - * Enum used for defining the view-mode of a set of elements - * List Display the elements in a (vertical) list - * Grid Display the elements in a grid - */ -export enum SetViewMode { - List = 'list', - Grid = 'grid', - Detail = 'detail' -} - -/** - * ViewMode refers to either a SetViewMode or ElementViewMode - */ -export type ViewMode = SetViewMode; diff --git a/themes/mantis/app/+item-page/simple/item-page.component.html b/themes/mantis/app/+item-page/simple/item-page.component.html index 472df7c78e..83f910e0cd 100644 --- a/themes/mantis/app/+item-page/simple/item-page.component.html +++ b/themes/mantis/app/+item-page/simple/item-page.component.html @@ -1,7 +1,7 @@
- +
diff --git a/themes/mantis/app/+item-page/simple/item-types/publication/publication.component.html b/themes/mantis/app/+item-page/simple/item-types/publication/publication.component.html index b7e2dbad39..35dc903432 100644 --- a/themes/mantis/app/+item-page/simple/item-types/publication/publication.component.html +++ b/themes/mantis/app/+item-page/simple/item-types/publication/publication.component.html @@ -1,57 +1,57 @@ -
+a
- +
- - - - + + + - -
- - + - - - + +
@@ -63,19 +63,19 @@
diff --git a/themes/mantis/app/entity-groups/journal-entities/item-pages/journal-issue/journal-issue.component.html b/themes/mantis/app/entity-groups/journal-entities/item-pages/journal-issue/journal-issue.component.html index 03f5e35335..9fa80d9c3c 100644 --- a/themes/mantis/app/entity-groups/journal-entities/item-pages/journal-issue/journal-issue.component.html +++ b/themes/mantis/app/entity-groups/journal-entities/item-pages/journal-issue/journal-issue.component.html @@ -4,11 +4,11 @@
- + @@ -17,37 +17,37 @@

{{'journalissue.page.titleprefix' | translate}} + [mdValues]="object?.allMetadata(['dc.title'])">

- - - -
- - - @@ -62,13 +62,13 @@
diff --git a/themes/mantis/app/entity-groups/journal-entities/item-pages/journal-volume/journal-volume.component.html b/themes/mantis/app/entity-groups/journal-entities/item-pages/journal-volume/journal-volume.component.html index 19950818a1..99d92d2af8 100644 --- a/themes/mantis/app/entity-groups/journal-entities/item-pages/journal-volume/journal-volume.component.html +++ b/themes/mantis/app/entity-groups/journal-entities/item-pages/journal-volume/journal-volume.component.html @@ -8,7 +8,7 @@ @@ -17,22 +17,22 @@

{{'journalvolume.page.titleprefix' | translate}} + [mdValues]="object?.allMetadata(['dc.title'])">

- -
- @@ -47,13 +47,13 @@
diff --git a/themes/mantis/app/entity-groups/journal-entities/item-pages/journal/journal.component.html b/themes/mantis/app/entity-groups/journal-entities/item-pages/journal/journal.component.html index 41d7b96c1d..1b8a283da9 100644 --- a/themes/mantis/app/entity-groups/journal-entities/item-pages/journal/journal.component.html +++ b/themes/mantis/app/entity-groups/journal-entities/item-pages/journal/journal.component.html @@ -3,11 +3,11 @@
- + @@ -16,26 +16,26 @@

{{'journal.page.titleprefix' | translate}} + [mdValues]="object?.allMetadata(['dc.title'])">

- - -
- @@ -50,7 +50,7 @@
@@ -61,7 +61,7 @@

{{"item.page.journal.search.title" | translate}}

-
diff --git a/themes/mantis/app/entity-groups/research-entities/item-pages/orgunit/orgunit.component.html b/themes/mantis/app/entity-groups/research-entities/item-pages/orgunit/orgunit.component.html index aa6aa695b4..15529a1bd5 100644 --- a/themes/mantis/app/entity-groups/research-entities/item-pages/orgunit/orgunit.component.html +++ b/themes/mantis/app/entity-groups/research-entities/item-pages/orgunit/orgunit.component.html @@ -4,12 +4,12 @@
- @@ -18,29 +18,29 @@

{{'orgunit.page.titleprefix' | translate}} + [mdValues]="object?.allMetadata(['organization.legalName'])">

- - -
- - @@ -55,19 +55,19 @@
diff --git a/themes/mantis/app/entity-groups/research-entities/item-pages/person/person.component.html b/themes/mantis/app/entity-groups/research-entities/item-pages/person/person.component.html index 34b7a9efa5..bb5cb1b787 100644 --- a/themes/mantis/app/entity-groups/research-entities/item-pages/person/person.component.html +++ b/themes/mantis/app/entity-groups/research-entities/item-pages/person/person.component.html @@ -4,12 +4,12 @@
- @@ -17,37 +17,37 @@

{{'person.page.titleprefix' | translate}} + [mdValues]="[object?.firstMetadata('person.familyName'), object?.firstMetadata('person.givenName')]" [separator]="', '">

- - + - - +
- - - @@ -62,13 +62,13 @@
@@ -79,7 +79,7 @@

{{"item.page.person.search.title" | translate}}

-
diff --git a/themes/mantis/app/entity-groups/research-entities/item-pages/project/project.component.html b/themes/mantis/app/entity-groups/research-entities/item-pages/project/project.component.html index dd48455b0d..31ba79a158 100644 --- a/themes/mantis/app/entity-groups/research-entities/item-pages/project/project.component.html +++ b/themes/mantis/app/entity-groups/research-entities/item-pages/project/project.component.html @@ -4,50 +4,50 @@

- {{'project.page.titleprefix' | translate}} + {{'project.page.titleprefix' | translate}}

- - - + - +
- - - @@ -62,19 +62,19 @@