Skip to content

Commit a84e2d3

Browse files
[DURACOM-453] fix issue with missing collection step in edit mode, refactor visibility to use utils, adapt tests, remove non-existing metadata in config example,add edit item breadcrumb resolver
1 parent 8982db7 commit a84e2d3

34 files changed

Lines changed: 719 additions & 648 deletions

config/config.example.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -431,7 +431,6 @@ item:
431431
# Metdadata list to be displayed for entities without a specific configuration
432432
fallbackMetdataList:
433433
- dc.description.abstract
434-
- dc.description.note
435434
# Configuration for each entity type
436435
entityDataConfig:
437436
- entityType: Person

src/app/collection-page/collection-form/collection-form.component.ts

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import {
44
Component,
55
Input,
66
OnChanges,
7+
OnDestroy,
78
OnInit,
89
SimpleChange,
910
SimpleChanges,
@@ -23,6 +24,7 @@ import { MetadataValue } from '@dspace/core/shared/metadata.models';
2324
import { getFirstSucceededRemoteListPayload } from '@dspace/core/shared/operators';
2425
import {
2526
hasNoValue,
27+
hasValue,
2628
isNotNull,
2729
} from '@dspace/shared/utils/empty.util';
2830
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
@@ -42,6 +44,7 @@ import {
4244
forkJoin,
4345
Observable,
4446
of,
47+
Subscription,
4548
} from 'rxjs';
4649

4750
import { ComColFormComponent } from '../../shared/comcol/comcol-forms/comcol-form/comcol-form.component';
@@ -72,7 +75,7 @@ import {
7275
VarDirective,
7376
],
7477
})
75-
export class CollectionFormComponent extends ComColFormComponent<Collection> implements OnInit, OnChanges {
78+
export class CollectionFormComponent extends ComColFormComponent<Collection> implements OnInit, OnChanges, OnDestroy {
7679
/**
7780
* @type {Collection} A new collection when a collection is being created, an existing Input collection when a collection is being edited
7881
*/
@@ -103,6 +106,13 @@ export class CollectionFormComponent extends ComColFormComponent<Collection> imp
103106
*/
104107
formModel: DynamicFormControlModel[];
105108

109+
/**
110+
* Subscription to unsubscribe on destroy
111+
*
112+
* @private
113+
*/
114+
private initSubscription: Subscription;
115+
106116
public constructor(protected formService: DynamicFormService,
107117
protected translate: TranslateService,
108118
protected notificationsService: NotificationsService,
@@ -134,6 +144,16 @@ export class CollectionFormComponent extends ComColFormComponent<Collection> imp
134144
}
135145
}
136146

147+
/**
148+
* Clean up eventual subscription when component gets destroyed
149+
*/
150+
ngOnDestroy() {
151+
super.ngOnDestroy();
152+
if (hasValue(this.initSubscription)) {
153+
this.initSubscription.unsubscribe();
154+
}
155+
}
156+
137157
initializeForm() {
138158
let currentRelationshipValue: MetadataValue[];
139159
let currentDefinitionValue: MetadataValue[];
@@ -155,7 +175,7 @@ export class CollectionFormComponent extends ComColFormComponent<Collection> imp
155175
);
156176

157177
// retrieve all entity types and submission definitions to populate the dropdowns selection
158-
forkJoin({
178+
this.initSubscription = forkJoin({
159179
entityTypes: entities$,
160180
definitions: definitions$,
161181
}).subscribe(({ entityTypes, definitions }: {entityTypes: ItemType[]; definitions: ConfigObject[]}) => {
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import {
2+
EnvironmentInjector,
3+
runInInjectionContext,
4+
} from '@angular/core';
5+
import { TestBed } from '@angular/core/testing';
6+
import { editItemBreadcrumbResolver } from '@dspace/core/breadcrumbs/edit-item-breadcrumb.resolver';
7+
import { Item } from '@dspace/core/shared/item.model';
8+
import { getTestScheduler } from 'jasmine-marbles';
9+
import { of } from 'rxjs';
10+
11+
import { ItemDataService } from '../data/item-data.service';
12+
import { createSuccessfulRemoteDataObject$ } from '../utilities/remote-data.utils';
13+
import { DSOBreadcrumbsService } from './dso-breadcrumbs.service';
14+
15+
describe('editItemBreadcrumbResolver', () => {
16+
describe('resolve', () => {
17+
let resolver: any;
18+
let dsoBreadcrumbService: any;
19+
let itemDataService: any;
20+
let testItem: Item;
21+
let uuid: string;
22+
let breadcrumbUrl: string;
23+
let currentUrl: string;
24+
25+
beforeEach(() => {
26+
uuid = '1234-65487-12354-1235';
27+
breadcrumbUrl = `/items/${uuid}`;
28+
currentUrl = `${breadcrumbUrl}/edit`;
29+
testItem = Object.assign(new Item(), {
30+
uuid: uuid,
31+
type: 'item',
32+
});
33+
34+
itemDataService = {
35+
findById: () => createSuccessfulRemoteDataObject$(testItem),
36+
};
37+
38+
dsoBreadcrumbService = {
39+
getRepresentativeName: () => testItem.uuid,
40+
getBreadcrumbs: () => of({ provider: dsoBreadcrumbService, key: testItem, url: breadcrumbUrl }),
41+
};
42+
43+
TestBed.configureTestingModule({
44+
providers: [
45+
{ provide: DSOBreadcrumbsService, useValue: dsoBreadcrumbService },
46+
{ provide: ItemDataService, useValue: itemDataService },
47+
],
48+
});
49+
50+
resolver = editItemBreadcrumbResolver;
51+
});
52+
53+
it('should resolve a breadcrumb config for the correct uuid', () => {
54+
const injector = TestBed.inject(EnvironmentInjector);
55+
const resolvedConfig = runInInjectionContext(injector, () =>
56+
resolver({ params: { id: testItem.uuid + ':FULL' } } as any, { url: currentUrl } as any),
57+
);
58+
const expectedConfig = { provider: dsoBreadcrumbService, key: testItem, url: breadcrumbUrl };
59+
getTestScheduler().expectObservable(resolvedConfig).toBe('(a|)', { a: expectedConfig });
60+
});
61+
});
62+
});
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import {
2+
ActivatedRouteSnapshot,
3+
ResolveFn,
4+
RouterStateSnapshot,
5+
} from '@angular/router';
6+
import { itemBreadcrumbResolver } from '@dspace/core/breadcrumbs/item-breadcrumb.resolver';
7+
import { Observable } from 'rxjs';
8+
9+
import { Item } from '../shared/item.model';
10+
import { BreadcrumbConfig } from './models/breadcrumb-config.model';
11+
12+
/**
13+
* The resolve function that resolves the BreadcrumbConfig object for an Item in edit mode
14+
*/
15+
export const editItemBreadcrumbResolver: ResolveFn<BreadcrumbConfig<Item>> = (
16+
route: ActivatedRouteSnapshot,
17+
state: RouterStateSnapshot,
18+
): Observable<BreadcrumbConfig<Item>> => {
19+
const routeWithCorrectId = Object.assign(route, {
20+
params: {
21+
...route.params,
22+
id: route.params.id.split(':')[0],
23+
},
24+
});
25+
26+
return itemBreadcrumbResolver(routeWithCorrectId, state) as Observable<BreadcrumbConfig<Item>>;
27+
};

src/app/core/config/models/config-submission-section.model.ts

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,26 @@ import {
66

77
import { typedObject } from '../../cache/builders/build-decorators';
88
import { HALLink } from '../../shared/hal-link.model';
9-
import {
10-
SectionScope,
11-
SectionVisibility,
12-
} from '../../submission/models/section-visibility.model';
9+
import { SectionScope } from '../../submission/models/section-visibility.model';
1310
import { SectionsType } from '../../submission/sections-type';
1411
import { ConfigObject } from './config.model';
1512
import { SUBMISSION_SECTION_TYPE } from './config-type';
1613

14+
/**
15+
* An Enum defining the possible visibility values
16+
*/
17+
export enum SubmissionVisibilityValue {
18+
ReadOnly = 'read-only',
19+
Hidden = 'hidden'
20+
}
21+
22+
/**
23+
* An interface that define section visibility and its properties.
24+
*/
25+
export interface SubmissionVisibilityType {
26+
[scope: string]: SubmissionVisibilityValue;
27+
}
28+
1729
@typedObject
1830
@inheritSerialization(ConfigObject)
1931
export class SubmissionSectionModel extends ConfigObject {
@@ -31,6 +43,12 @@ export class SubmissionSectionModel extends ConfigObject {
3143
@autoserialize
3244
mandatory: boolean;
3345

46+
/**
47+
* A boolean representing if this submission section is opened or collapsed by default
48+
*/
49+
@autoserialize
50+
opened: boolean;
51+
3452
/**
3553
* The submission scope for this section
3654
*/
@@ -44,10 +62,10 @@ export class SubmissionSectionModel extends ConfigObject {
4462
sectionType: SectionsType;
4563

4664
/**
47-
* The [SectionVisibility] object for this section
65+
* The [SubmissionVisibilityType] object for this section
4866
*/
4967
@autoserialize
50-
visibility: SectionVisibility;
68+
visibility: SubmissionVisibilityType;
5169

5270
/**
5371
* The {@link HALLink}s for this SubmissionSectionModel

src/app/core/shared/form/models/form-field.model.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1+
import { SubmissionVisibilityType } from '@dspace/core/config/models/config-submission-section.model';
12
import { autoserialize } from 'cerialize';
23

34
import { FormRowModel } from '../../../config/models/config-submission-form.model';
4-
import { SectionVisibility } from '../../../submission/models/section-visibility.model';
55
import { RelationshipOptions } from '../../relationship-options.model';
66
import { LanguageCode } from './form-field-language-value.model';
77

@@ -130,5 +130,10 @@ export class FormFieldModel {
130130
* The visibility object for this field
131131
*/
132132
@autoserialize
133-
visibility: SectionVisibility;
133+
visibility: SubmissionVisibilityType;
134+
135+
/**
136+
* The security config values
137+
*/
138+
securityConfigLevel?: number[];
134139
}

src/app/core/submission/models/submission-section-object.model.ts

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
1+
import { SubmissionVisibilityType } from '@dspace/core/config/models/config-submission-section.model';
2+
13
import { SectionsType } from '../sections-type';
2-
import {
3-
SectionScope,
4-
SectionVisibility,
5-
} from './section-visibility.model';
64
import { SubmissionSectionError } from './submission-section-error.model';
75
import { WorkspaceitemSectionDataType } from './workspaceitem-sections.model';
86

@@ -26,9 +24,9 @@ export interface SubmissionSectionObject {
2624
mandatory: boolean;
2725

2826
/**
29-
* The submission scope for this section
27+
* A boolean representing if this section is opened or collapsed by default
3028
*/
31-
scope: SectionScope;
29+
opened: boolean;
3230

3331
/**
3432
* The section type
@@ -38,7 +36,7 @@ export interface SubmissionSectionObject {
3836
/**
3937
* The section visibility
4038
*/
41-
visibility: SectionVisibility;
39+
visibility: SubmissionVisibilityType;
4240

4341
/**
4442
* A boolean representing if this section is collapsed

src/app/core/submission/submission-rest.service.ts

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -93,12 +93,14 @@ export class SubmissionRestService {
9393
* The owning collection for the object
9494
* @param projections
9595
*/
96-
protected getEndpointByIDHref(endpoint, resourceID, collectionId?: string, projections: string[] = []): string {
96+
protected getEndpointByIDHref(endpoint, resourceID, collectionId?: string, projections: string[] = [], isEditMode = false): string {
9797
let url = isNotEmpty(resourceID) ? `${endpoint}/${resourceID}` : `${endpoint}`;
98-
url = new URLCombiner(url, '?embed=item,sections,collection').toString();
98+
if (!isEditMode) {
99+
url = new URLCombiner(url, '?embed=item,sections,collection').toString();
100+
}
99101

100-
projections.forEach((projection) => {
101-
url = new URLCombiner(url, '&projection=' + projection).toString();
102+
projections.forEach((projection, index) => {
103+
url = new URLCombiner(url, ((index === 0 && isEditMode) ? '?' : '&') + 'projection=' + projection).toString();
102104
});
103105
if (collectionId) {
104106
url = new URLCombiner(url, `&owningCollection=${collectionId}`).toString();
@@ -140,9 +142,9 @@ export class SubmissionRestService {
140142
* @return Observable<SubmitDataResponseDefinitionObject>
141143
* server response
142144
*/
143-
public getDataById(linkName: string, id: string, useCachedVersionIfAvailable = false, projections: string[] = []): Observable<SubmitDataResponseDefinitionObject> {
145+
public getDataById(linkName: string, id: string, useCachedVersionIfAvailable = false, projections: string[] = [], isEditMode = false): Observable<SubmitDataResponseDefinitionObject> {
144146
return this.halService.getEndpoint(linkName).pipe(
145-
map((endpointURL: string) => this.getEndpointByIDHref(endpointURL, id, null, projections)),
147+
map((endpointURL: string) => this.getEndpointByIDHref(endpointURL, id, null, projections, isEditMode)),
146148
filter((href: string) => isNotEmpty(href)),
147149
distinctUntilChanged(),
148150
mergeMap((endpointURL: string) => {
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
export enum SubmissionScopeType {
2-
WorkspaceItem = 'WORKSPACE',
3-
WorkflowItem = 'WORKFLOW',
4-
EditItem = 'EDIT'
2+
WorkspaceItem = 'submission',
3+
WorkflowItem = 'workflow',
4+
EditItem = 'edit'
55
}

src/app/core/testing/submission-service.stub.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ export class SubmissionServiceStub {
2323
getSubmissionDepositProcessingStatus = jasmine.createSpy('getSubmissionDepositProcessingStatus');
2424
hasUnsavedModification = jasmine.createSpy('hasUnsavedModification');
2525
isSectionHidden = jasmine.createSpy('isSectionHidden');
26+
isSectionReadOnly = jasmine.createSpy('isSectionReadOnly');
2627
isSubmissionLoading = jasmine.createSpy('isSubmissionLoading');
2728
notifyNewSection = jasmine.createSpy('notifyNewSection');
2829
redirectToMyDSpace = jasmine.createSpy('redirectToMyDSpace');

0 commit comments

Comments
 (0)