Skip to content

Commit c74c178

Browse files
117287: Removed method calls returning observables from the metadata registry
1 parent b55686e commit c74c178

7 files changed

Lines changed: 267 additions & 196 deletions

File tree

src/app/admin/admin-registries/metadata-registry/metadata-registry.component.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,11 @@ <h2 id="header" class="border-bottom pb-2">{{'admin.registries.metadata.head' |
2727
</thead>
2828
<tbody>
2929
<tr *ngFor="let schema of (metadataSchemas | async)?.payload?.page"
30-
[ngClass]="{'table-primary' : isActive(schema) | async}">
30+
[ngClass]="{'table-primary' : (activeMetadataSchema$ | async)?.id === schema.id}">
3131
<td>
3232
<label class="mb-0">
3333
<input type="checkbox"
34-
[checked]="isSelected(schema) | async"
34+
[checked]="(selectedMetadataSchemaIDs$ | async)?.includes(schema.id)"
3535
(change)="selectMetadataSchema(schema, $event)"
3636
>
3737
</label>

src/app/admin/admin-registries/metadata-registry/metadata-registry.component.spec.ts

Lines changed: 15 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import { MetadataRegistryComponent } from './metadata-registry.component';
22
import { ComponentFixture, inject, TestBed, waitForAsync } from '@angular/core/testing';
33
import { of as observableOf } from 'rxjs';
4-
import { buildPaginatedList } from '../../../core/data/paginated-list.model';
54
import { TranslateModule } from '@ngx-translate/core';
65
import { By } from '@angular/platform-browser';
76
import { CommonModule } from '@angular/common';
@@ -15,18 +14,21 @@ import { HostWindowService } from '../../../shared/host-window.service';
1514
import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA } from '@angular/core';
1615
import { NotificationsService } from '../../../shared/notifications/notifications.service';
1716
import { NotificationsServiceStub } from '../../../shared/testing/notifications-service.stub';
18-
import { RestResponse } from '../../../core/cache/response.models';
1917
import { MetadataSchema } from '../../../core/metadata/metadata-schema.model';
2018
import { createSuccessfulRemoteDataObject$ } from '../../../shared/remote-data.utils';
2119
import { PaginationService } from '../../../core/pagination/pagination.service';
2220
import { PaginationServiceStub } from '../../../shared/testing/pagination-service.stub';
21+
import { RegistryServiceStub } from '../../../shared/testing/registry.service.stub';
22+
import { createPaginatedList } from '../../../shared/testing/utils.test';
2323

2424
describe('MetadataRegistryComponent', () => {
2525
let comp: MetadataRegistryComponent;
2626
let fixture: ComponentFixture<MetadataRegistryComponent>;
27-
let registryService: RegistryService;
28-
let paginationService;
29-
const mockSchemasList = [
27+
28+
let paginationService: PaginationServiceStub;
29+
let registryService: RegistryServiceStub;
30+
31+
const mockSchemasList: MetadataSchema[] = [
3032
{
3133
id: 1,
3234
_links: {
@@ -47,32 +49,18 @@ describe('MetadataRegistryComponent', () => {
4749
prefix: 'mock',
4850
namespace: 'http://dspace.org/mockschema'
4951
}
50-
];
51-
const mockSchemas = createSuccessfulRemoteDataObject$(buildPaginatedList(null, mockSchemasList));
52-
/* eslint-disable no-empty,@typescript-eslint/no-empty-function */
53-
const registryServiceStub = {
54-
getMetadataSchemas: () => mockSchemas,
55-
getActiveMetadataSchema: () => observableOf(undefined),
56-
getSelectedMetadataSchemas: () => observableOf([]),
57-
editMetadataSchema: (schema) => {
58-
},
59-
cancelEditMetadataSchema: () => {
60-
},
61-
deleteMetadataSchema: () => observableOf(new RestResponse(true, 200, 'OK')),
62-
deselectAllMetadataSchema: () => {
63-
},
64-
clearMetadataSchemaRequests: () => observableOf(undefined)
65-
};
66-
/* eslint-enable no-empty, @typescript-eslint/no-empty-function */
67-
68-
paginationService = new PaginationServiceStub();
52+
] as MetadataSchema[];
6953

7054
beforeEach(waitForAsync(() => {
55+
paginationService = new PaginationServiceStub();
56+
registryService = new RegistryServiceStub();
57+
spyOn(registryService, 'getMetadataSchemas').and.returnValue(createSuccessfulRemoteDataObject$(createPaginatedList(mockSchemasList)));
58+
7159
TestBed.configureTestingModule({
7260
imports: [CommonModule, RouterTestingModule.withRoutes([]), TranslateModule.forRoot(), NgbModule],
7361
declarations: [MetadataRegistryComponent, PaginationComponent, EnumKeysPipe],
7462
providers: [
75-
{ provide: RegistryService, useValue: registryServiceStub },
63+
{ provide: RegistryService, useValue: registryService },
7664
{ provide: HostWindowService, useValue: new HostWindowServiceStub(0) },
7765
{ provide: PaginationService, useValue: paginationService },
7866
{ provide: NotificationsService, useValue: new NotificationsServiceStub() }
@@ -123,7 +111,7 @@ describe('MetadataRegistryComponent', () => {
123111
}));
124112

125113
it('should cancel editing the selected schema when clicked again', waitForAsync(() => {
126-
spyOn(registryService, 'getActiveMetadataSchema').and.returnValue(observableOf(mockSchemasList[0] as MetadataSchema));
114+
comp.activeMetadataSchema$ = observableOf(mockSchemasList[0] as MetadataSchema);
127115
spyOn(registryService, 'cancelEditMetadataSchema');
128116
row.click();
129117
fixture.detectChanges();
@@ -138,7 +126,7 @@ describe('MetadataRegistryComponent', () => {
138126

139127
beforeEach(() => {
140128
spyOn(registryService, 'deleteMetadataSchema').and.callThrough();
141-
spyOn(registryService, 'getSelectedMetadataSchemas').and.returnValue(observableOf(selectedSchemas as MetadataSchema[]));
129+
comp.selectedMetadataSchemaIDs$ = observableOf(selectedSchemas.map((selectedSchema: MetadataSchema) => selectedSchema.id));
142130
comp.deleteSchemas();
143131
fixture.detectChanges();
144132
});
Lines changed: 56 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
1-
import { Component } from '@angular/core';
1+
import { Component, OnInit, OnDestroy } from '@angular/core';
22
import { RegistryService } from '../../../core/registry/registry.service';
3-
import { BehaviorSubject, combineLatest as observableCombineLatest, Observable, zip } from 'rxjs';
3+
import { BehaviorSubject, Observable, zip, Subscription } from 'rxjs';
44
import { RemoteData } from '../../../core/data/remote-data';
55
import { PaginatedList } from '../../../core/data/paginated-list.model';
66
import { PaginationComponentOptions } from '../../../shared/pagination/pagination-component-options.model';
77
import { filter, map, switchMap, take } from 'rxjs/operators';
8-
import { hasValue } from '../../../shared/empty.util';
98
import { NotificationsService } from '../../../shared/notifications/notifications.service';
10-
import { Router } from '@angular/router';
119
import { TranslateService } from '@ngx-translate/core';
1210
import { MetadataSchema } from '../../../core/metadata/metadata-schema.model';
1311
import { toFindListOptions } from '../../../shared/pagination/pagination.utils';
@@ -24,13 +22,23 @@ import { PaginationService } from '../../../core/pagination/pagination.service';
2422
* A component used for managing all existing metadata schemas within the repository.
2523
* The admin can create, edit or delete metadata schemas here.
2624
*/
27-
export class MetadataRegistryComponent {
25+
export class MetadataRegistryComponent implements OnDestroy, OnInit {
2826

2927
/**
3028
* A list of all the current metadata schemas within the repository
3129
*/
3230
metadataSchemas: Observable<RemoteData<PaginatedList<MetadataSchema>>>;
3331

32+
/**
33+
* The {@link MetadataSchema}that is being edited
34+
*/
35+
activeMetadataSchema$: Observable<MetadataSchema>;
36+
37+
/**
38+
* The selected {@link MetadataSchema} IDs
39+
*/
40+
selectedMetadataSchemaIDs$: Observable<number[]>;
41+
3442
/**
3543
* Pagination config used to display the list of metadata schemas
3644
*/
@@ -40,15 +48,25 @@ export class MetadataRegistryComponent {
4048
});
4149

4250
/**
43-
* Whether or not the list of MetadataSchemas needs an update
51+
* Whether the list of MetadataSchemas needs an update
4452
*/
4553
needsUpdate$: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(true);
4654

47-
constructor(private registryService: RegistryService,
48-
private notificationsService: NotificationsService,
49-
private router: Router,
50-
private paginationService: PaginationService,
51-
private translateService: TranslateService) {
55+
subscriptions: Subscription[] = [];
56+
57+
constructor(
58+
protected registryService: RegistryService,
59+
protected notificationsService: NotificationsService,
60+
protected paginationService: PaginationService,
61+
protected translateService: TranslateService,
62+
) {
63+
}
64+
65+
ngOnInit(): void {
66+
this.activeMetadataSchema$ = this.registryService.getActiveMetadataSchema();
67+
this.selectedMetadataSchemaIDs$ = this.registryService.getSelectedMetadataSchemas().pipe(
68+
map((schemas: MetadataSchema[]) => schemas.map((schema: MetadataSchema) => schema.id)),
69+
);
5270
this.updateSchemas();
5371
}
5472

@@ -77,30 +95,13 @@ export class MetadataRegistryComponent {
7795
* @param schema
7896
*/
7997
editSchema(schema: MetadataSchema) {
80-
this.getActiveSchema().pipe(take(1)).subscribe((activeSchema) => {
98+
this.subscriptions.push(this.activeMetadataSchema$.pipe(take(1)).subscribe((activeSchema: MetadataSchema) => {
8199
if (schema === activeSchema) {
82100
this.registryService.cancelEditMetadataSchema();
83101
} else {
84102
this.registryService.editMetadataSchema(schema);
85103
}
86-
});
87-
}
88-
89-
/**
90-
* Checks whether the given metadata schema is active (being edited)
91-
* @param schema
92-
*/
93-
isActive(schema: MetadataSchema): Observable<boolean> {
94-
return this.getActiveSchema().pipe(
95-
map((activeSchema) => schema === activeSchema)
96-
);
97-
}
98-
99-
/**
100-
* Gets the active metadata schema (being edited)
101-
*/
102-
getActiveSchema(): Observable<MetadataSchema> {
103-
return this.registryService.getActiveMetadataSchema();
104+
}));
104105
}
105106

106107
/**
@@ -114,42 +115,25 @@ export class MetadataRegistryComponent {
114115
this.registryService.deselectMetadataSchema(schema);
115116
}
116117

117-
/**
118-
* Checks whether a given metadata schema is selected in the list (checkbox)
119-
* @param schema
120-
*/
121-
isSelected(schema: MetadataSchema): Observable<boolean> {
122-
return this.registryService.getSelectedMetadataSchemas().pipe(
123-
map((schemas) => schemas.find((selectedSchema) => selectedSchema === schema) != null)
124-
);
125-
}
126-
127118
/**
128119
* Delete all the selected metadata schemas
129120
*/
130121
deleteSchemas() {
131-
this.registryService.getSelectedMetadataSchemas().pipe(take(1)).subscribe(
132-
(schemas) => {
133-
const tasks$ = [];
134-
for (const schema of schemas) {
135-
if (hasValue(schema.id)) {
136-
tasks$.push(this.registryService.deleteMetadataSchema(schema.id).pipe(getFirstCompletedRemoteData()));
137-
}
138-
}
139-
zip(...tasks$).subscribe((responses: RemoteData<NoContent>[]) => {
140-
const successResponses = responses.filter((response: RemoteData<NoContent>) => response.hasSucceeded);
141-
const failedResponses = responses.filter((response: RemoteData<NoContent>) => response.hasFailed);
142-
if (successResponses.length > 0) {
143-
this.showNotification(true, successResponses.length);
144-
}
145-
if (failedResponses.length > 0) {
146-
this.showNotification(false, failedResponses.length);
147-
}
148-
this.registryService.deselectAllMetadataSchema();
149-
this.registryService.cancelEditMetadataSchema();
150-
});
122+
this.subscriptions.push(this.selectedMetadataSchemaIDs$.pipe(
123+
take(1),
124+
switchMap((schemaIDs: number[]) => zip(schemaIDs.map((schemaID: number) => this.registryService.deleteMetadataSchema(schemaID).pipe(getFirstCompletedRemoteData())))),
125+
).subscribe((responses: RemoteData<NoContent>[]) => {
126+
const successResponses: RemoteData<NoContent>[] = responses.filter((response: RemoteData<NoContent>) => response.hasSucceeded);
127+
const failedResponses: RemoteData<NoContent>[] = responses.filter((response: RemoteData<NoContent>) => response.hasFailed);
128+
if (successResponses.length > 0) {
129+
this.showNotification(true, successResponses.length);
151130
}
152-
);
131+
if (failedResponses.length > 0) {
132+
this.showNotification(false, failedResponses.length);
133+
}
134+
this.registryService.deselectAllMetadataSchema();
135+
this.registryService.cancelEditMetadataSchema();
136+
}));
153137
}
154138

155139
/**
@@ -160,20 +144,20 @@ export class MetadataRegistryComponent {
160144
showNotification(success: boolean, amount: number) {
161145
const prefix = 'admin.registries.schema.notification';
162146
const suffix = success ? 'success' : 'failure';
163-
const messages = observableCombineLatest(
164-
this.translateService.get(success ? `${prefix}.${suffix}` : `${prefix}.${suffix}`),
165-
this.translateService.get(`${prefix}.deleted.${suffix}`, {amount: amount})
166-
);
167-
messages.subscribe(([head, content]) => {
168-
if (success) {
169-
this.notificationsService.success(head, content);
170-
} else {
171-
this.notificationsService.error(head, content);
172-
}
173-
});
147+
148+
const head: string = this.translateService.instant(success ? `${prefix}.${suffix}` : `${prefix}.${suffix}`);
149+
const content: string = this.translateService.instant(`${prefix}.deleted.${suffix}`, {amount: amount});
150+
151+
if (success) {
152+
this.notificationsService.success(head, content);
153+
} else {
154+
this.notificationsService.error(head, content);
155+
}
174156
}
157+
175158
ngOnDestroy(): void {
176159
this.paginationService.clearPagination(this.config.id);
160+
this.subscriptions.map((subscription: Subscription) => subscription.unsubscribe());
177161
}
178162

179163
}

src/app/admin/admin-registries/metadata-registry/metadata-schema-form/metadata-schema-form.component.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<div *ngIf="registryService.getActiveMetadataSchema() | async; then editheader; else createHeader"></div>
1+
<div *ngIf="activeMetadataSchema$ | async; then editheader; else createHeader"></div>
22

33
<ng-template #createHeader>
44
<h4>{{messagePrefix + '.create' | translate}}</h4>

src/app/admin/admin-registries/metadata-registry/metadata-schema-form/metadata-schema-form.component.spec.ts

Lines changed: 11 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { ComponentFixture, inject, TestBed, waitForAsync } from '@angular/core/testing';
22
import { MetadataSchemaFormComponent } from './metadata-schema-form.component';
3-
import { NO_ERRORS_SCHEMA } from '@angular/core';
3+
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
44
import { CommonModule } from '@angular/common';
55
import { RouterTestingModule } from '@angular/router/testing';
66
import { TranslateModule } from '@ngx-translate/core';
@@ -10,41 +10,26 @@ import { RegistryService } from '../../../../core/registry/registry.service';
1010
import { FormBuilderService } from '../../../../shared/form/builder/form-builder.service';
1111
import { of as observableOf } from 'rxjs';
1212
import { MetadataSchema } from '../../../../core/metadata/metadata-schema.model';
13+
import { RegistryServiceStub } from '../../../../shared/testing/registry.service.stub';
14+
import { getMockFormBuilderService } from '../../../../shared/mocks/form-builder-service.mock';
1315

1416
describe('MetadataSchemaFormComponent', () => {
1517
let component: MetadataSchemaFormComponent;
1618
let fixture: ComponentFixture<MetadataSchemaFormComponent>;
17-
let registryService: RegistryService;
1819

19-
/* eslint-disable no-empty,@typescript-eslint/no-empty-function */
20-
const registryServiceStub = {
21-
getActiveMetadataSchema: () => observableOf(undefined),
22-
createOrUpdateMetadataSchema: (schema: MetadataSchema) => observableOf(schema),
23-
cancelEditMetadataSchema: () => {
24-
},
25-
clearMetadataSchemaRequests: () => observableOf(undefined)
26-
};
27-
const formBuilderServiceStub = {
28-
createFormGroup: () => {
29-
return {
30-
patchValue: () => {
31-
},
32-
reset(_value?: any, _options?: { onlySelf?: boolean; emitEvent?: boolean; }): void {
33-
},
34-
};
35-
}
36-
};
37-
/* eslint-enable no-empty, @typescript-eslint/no-empty-function */
20+
let registryService: RegistryServiceStub;
3821

3922
beforeEach(waitForAsync(() => {
23+
registryService = new RegistryServiceStub();
24+
4025
return TestBed.configureTestingModule({
4126
imports: [CommonModule, RouterTestingModule.withRoutes([]), TranslateModule.forRoot(), NgbModule],
4227
declarations: [MetadataSchemaFormComponent, EnumKeysPipe],
4328
providers: [
44-
{ provide: RegistryService, useValue: registryServiceStub },
45-
{ provide: FormBuilderService, useValue: formBuilderServiceStub }
29+
{ provide: RegistryService, useValue: registryService },
30+
{ provide: FormBuilderService, useValue: getMockFormBuilderService() }
4631
],
47-
schemas: [NO_ERRORS_SCHEMA]
32+
schemas: [CUSTOM_ELEMENTS_SCHEMA],
4833
}).compileComponents();
4934
}));
5035

@@ -75,7 +60,7 @@ describe('MetadataSchemaFormComponent', () => {
7560

7661
describe('without an active schema', () => {
7762
beforeEach(() => {
78-
spyOn(registryService, 'getActiveMetadataSchema').and.returnValue(observableOf(undefined));
63+
component.activeMetadataSchema$ = observableOf(undefined);
7964
component.onSubmit();
8065
fixture.detectChanges();
8166
});
@@ -94,7 +79,7 @@ describe('MetadataSchemaFormComponent', () => {
9479
} as MetadataSchema);
9580

9681
beforeEach(() => {
97-
spyOn(registryService, 'getActiveMetadataSchema').and.returnValue(observableOf(expectedWithId));
82+
component.activeMetadataSchema$ = observableOf(expectedWithId);
9883
component.onSubmit();
9984
fixture.detectChanges();
10085
});

0 commit comments

Comments
 (0)