Skip to content

Commit 850a973

Browse files
[DURACOM-453] add metadata security and finilize edit mode
1 parent 2edc805 commit 850a973

75 files changed

Lines changed: 1762 additions & 206 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

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

Lines changed: 88 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ import {
1010
} from '@angular/core';
1111
import { AuthService } from '@dspace/core/auth/auth.service';
1212
import { ObjectCacheService } from '@dspace/core/cache/object-cache.service';
13+
import { ConfigObject } from '@dspace/core/config/models/config.model';
14+
import { SubmissionDefinitionModel } from '@dspace/core/config/models/config-submission-definition.model';
15+
import { SubmissionDefinitionsConfigDataService } from '@dspace/core/config/submission-definitions-config-data.service';
1316
import { CollectionDataService } from '@dspace/core/data/collection-data.service';
1417
import { EntityTypeDataService } from '@dspace/core/data/entity-type-data.service';
1518
import { RequestService } from '@dspace/core/data/request.service';
@@ -25,6 +28,7 @@ import {
2528
} from '@dspace/shared/utils/empty.util';
2629
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
2730
import {
31+
DynamicCheckboxModel,
2832
DynamicFormControlModel,
2933
DynamicFormOptionConfig,
3034
DynamicFormService,
@@ -34,16 +38,24 @@ import {
3438
TranslateModule,
3539
TranslateService,
3640
} from '@ngx-translate/core';
37-
import { Observable } from 'rxjs';
41+
import {
42+
catchError,
43+
combineLatest,
44+
Observable,
45+
of,
46+
} from 'rxjs';
3847

3948
import { ComColFormComponent } from '../../shared/comcol/comcol-forms/comcol-form/comcol-form.component';
4049
import { ComcolPageLogoComponent } from '../../shared/comcol/comcol-page-logo/comcol-page-logo.component';
4150
import { FormComponent } from '../../shared/form/form.component';
4251
import { UploaderComponent } from '../../shared/upload/uploader/uploader.component';
4352
import { VarDirective } from '../../shared/utils/var.directive';
4453
import {
54+
collectionFormCorrectionSubmissionDefinitionSelectionConfig,
4555
collectionFormEntityTypeSelectionConfig,
4656
collectionFormModels,
57+
collectionFormSharedWorkspaceCheckboxConfig,
58+
collectionFormSubmissionDefinitionSelectionConfig,
4759
} from './collection-form.models';
4860

4961
/**
@@ -79,6 +91,20 @@ export class CollectionFormComponent extends ComColFormComponent<Collection> imp
7991
*/
8092
entityTypeSelection: DynamicSelectModel<string> = new DynamicSelectModel(collectionFormEntityTypeSelectionConfig);
8193

94+
/**
95+
* The dynamic form field used for submission definition selection
96+
* @type {DynamicSelectModel<string>}
97+
*/
98+
submissionDefinitionSelection: DynamicSelectModel<string> = new DynamicSelectModel(collectionFormSubmissionDefinitionSelectionConfig);
99+
100+
/**
101+
* The dynamic form field used for correction submission definition selection
102+
* @type {DynamicSelectModel<string>}
103+
*/
104+
correctionSubmissionDefinitionSelection: DynamicSelectModel<string> = new DynamicSelectModel(collectionFormCorrectionSubmissionDefinitionSelectionConfig);
105+
106+
sharedWorkspaceChekbox: DynamicCheckboxModel = new DynamicCheckboxModel(collectionFormSharedWorkspaceCheckboxConfig);
107+
82108
/**
83109
* The dynamic form fields used for creating/editing a collection
84110
* @type {DynamicFormControlModel[]}
@@ -94,6 +120,7 @@ export class CollectionFormComponent extends ComColFormComponent<Collection> imp
94120
protected objectCache: ObjectCacheService,
95121
protected entityTypeService: EntityTypeDataService,
96122
protected chd: ChangeDetectorRef,
123+
protected submissionDefinitionService: SubmissionDefinitionsConfigDataService,
97124
protected modalService: NgbModal) {
98125
super(formService, translate, notificationsService, authService, requestService, objectCache, modalService);
99126
}
@@ -117,35 +144,76 @@ export class CollectionFormComponent extends ComColFormComponent<Collection> imp
117144

118145
initializeForm() {
119146
let currentRelationshipValue: MetadataValue[];
147+
let currentDefinitionValue: MetadataValue[];
148+
let currentCorrectionDefinitionValue: MetadataValue[];
149+
let currentSharedWorkspaceValue: MetadataValue[];
120150
if (this.dso && this.dso.metadata) {
121151
currentRelationshipValue = this.dso.metadata['dspace.entity.type'];
152+
currentDefinitionValue = this.dso.metadata['cris.submission.definition'];
153+
currentCorrectionDefinitionValue = this.dso.metadata['cris.submission.definition-correction'];
154+
currentSharedWorkspaceValue = this.dso.metadata['cris.workspace.shared'];
122155
}
123156

124157
const entities$: Observable<ItemType[]> = this.entityTypeService.findAll({ elementsPerPage: 100, currentPage: 1 }).pipe(
125158
getFirstSucceededRemoteListPayload(),
126159
);
127160

128-
// retrieve all entity types to populate the dropdowns selection
129-
entities$.subscribe((entityTypes: ItemType[]) => {
130-
131-
entityTypes = entityTypes.filter((type: ItemType) => type.label !== NONE_ENTITY_TYPE);
132-
entityTypes.forEach((type: ItemType, index: number) => {
133-
this.entityTypeSelection.add({
134-
disabled: false,
135-
label: type.label,
136-
value: type.label,
137-
} as DynamicFormOptionConfig<string>);
138-
if (currentRelationshipValue && currentRelationshipValue.length > 0 && currentRelationshipValue[0].value === type.label) {
139-
this.entityTypeSelection.select(index);
140-
this.entityTypeSelection.disabled = true;
141-
}
142-
});
161+
const definitions$: Observable<ConfigObject[]> = this.submissionDefinitionService
162+
.findAll({ elementsPerPage: 100, currentPage: 1 }).pipe(
163+
getFirstSucceededRemoteListPayload(),
164+
catchError(() => of([])),
165+
);
166+
167+
// retrieve all entity types and submission definitions to populate the dropdowns selection
168+
combineLatest([entities$, definitions$])
169+
.subscribe(([entityTypes, definitions]: [ItemType[], SubmissionDefinitionModel[]]) => {
170+
171+
const sortedEntityTypes = entityTypes
172+
.filter((type: ItemType) => type.label !== NONE_ENTITY_TYPE)
173+
.sort((a, b) => a.label.localeCompare(b.label));
174+
175+
sortedEntityTypes.forEach((type: ItemType, index: number) => {
176+
this.entityTypeSelection.add({
177+
disabled: false,
178+
label: type.label,
179+
value: type.label,
180+
} as DynamicFormOptionConfig<string>);
181+
if (currentRelationshipValue && currentRelationshipValue.length > 0 && currentRelationshipValue[0].value === type.label) {
182+
this.entityTypeSelection.select(index);
183+
this.entityTypeSelection.disabled = true;
184+
}
185+
});
143186

144-
this.formModel = entityTypes.length === 0 ? collectionFormModels : [...collectionFormModels, this.entityTypeSelection];
187+
definitions.forEach((definition: SubmissionDefinitionModel, index: number) => {
188+
this.submissionDefinitionSelection.add({
189+
disabled: false,
190+
label: definition.name,
191+
value: definition.name,
192+
} as DynamicFormOptionConfig<string>);
193+
this.correctionSubmissionDefinitionSelection.add({
194+
disabled: false,
195+
label: definition.name,
196+
value: definition.name,
197+
} as DynamicFormOptionConfig<string>);
198+
if (currentDefinitionValue && currentDefinitionValue.length > 0 && currentDefinitionValue[0].value === definition.name) {
199+
this.submissionDefinitionSelection.select(index);
200+
}
201+
if (currentCorrectionDefinitionValue && currentCorrectionDefinitionValue.length > 0 && currentCorrectionDefinitionValue[0].value === definition.name) {
202+
this.correctionSubmissionDefinitionSelection.select(index);
203+
}
204+
});
145205

146-
super.ngOnInit();
147-
this.chd.detectChanges();
148-
});
206+
this.formModel = entityTypes.length === 0 ?
207+
[...collectionFormModels, this.submissionDefinitionSelection, this.correctionSubmissionDefinitionSelection, this.sharedWorkspaceChekbox] :
208+
[...collectionFormModels, this.entityTypeSelection, this.submissionDefinitionSelection, this.correctionSubmissionDefinitionSelection, this.sharedWorkspaceChekbox];
209+
210+
super.ngOnInit();
211+
212+
if (currentSharedWorkspaceValue && currentSharedWorkspaceValue.length > 0) {
213+
this.sharedWorkspaceChekbox.value = currentSharedWorkspaceValue[0].value === 'true';
214+
}
215+
this.chd.detectChanges();
216+
});
149217

150218
}
151219
}

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

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import {
2+
DynamicCheckboxModelConfig,
23
DynamicFormControlModel,
34
DynamicInputModel,
45
DynamicSelectModelConfig,
@@ -10,6 +11,38 @@ import { environment } from '../../../environments/environment';
1011
export const collectionFormEntityTypeSelectionConfig: DynamicSelectModelConfig<string> = {
1112
id: 'entityType',
1213
name: 'dspace.entity.type',
14+
required: true,
15+
disabled: false,
16+
validators: {
17+
required: null,
18+
},
19+
errorMessages: {
20+
required: 'collection.form.errors.entityType.required',
21+
},
22+
};
23+
24+
export const collectionFormSubmissionDefinitionSelectionConfig: DynamicSelectModelConfig<string> = {
25+
id: 'submissionDefinition',
26+
name: 'cris.submission.definition',
27+
required: true,
28+
disabled: false,
29+
validators: {
30+
required: null,
31+
},
32+
errorMessages: {
33+
required: 'collection.form.errors.submissionDefinition.required',
34+
},
35+
};
36+
export const collectionFormCorrectionSubmissionDefinitionSelectionConfig: DynamicSelectModelConfig<string> = {
37+
id: 'correctionSubmissionDefinition',
38+
name: 'cris.submission.definition-correction',
39+
required: false,
40+
disabled: false,
41+
};
42+
43+
export const collectionFormSharedWorkspaceCheckboxConfig: DynamicCheckboxModelConfig = {
44+
id: 'sharedWorkspace',
45+
name: 'cris.workspace.shared',
1346
disabled: false,
1447
};
1548

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import { Injectable } from '@angular/core';
2+
import { FollowLinkConfig } from '@dspace/core/shared/follow-link-config.model';
3+
import { Observable } from 'rxjs';
4+
import {
5+
mergeMap,
6+
take,
7+
} from 'rxjs/operators';
8+
9+
import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service';
10+
import { ObjectCacheService } from '../cache/object-cache.service';
11+
import { FindListOptions } from '../data/find-list-options.model';
12+
import { PaginatedList } from '../data/paginated-list.model';
13+
import { RemoteData } from '../data/remote-data';
14+
import { RequestService } from '../data/request.service';
15+
import { HALEndpointService } from '../shared/hal-endpoint.service';
16+
import { ConfigDataService } from './config-data.service';
17+
import { ConfigObject } from './models/config.model';
18+
19+
@Injectable({ providedIn: 'root' })
20+
export class SubmissionDefinitionsConfigDataService extends ConfigDataService {
21+
constructor(
22+
protected requestService: RequestService,
23+
protected rdbService: RemoteDataBuildService,
24+
protected objectCache: ObjectCacheService,
25+
protected halService: HALEndpointService,
26+
) {
27+
super('submissiondefinitions', requestService, rdbService, objectCache, halService);
28+
}
29+
30+
findAll(options: FindListOptions = {}, useCachedVersionIfAvailable = true, reRequestOnStale = true, ...linksToFollow: FollowLinkConfig<ConfigObject>[]): Observable<RemoteData<PaginatedList<ConfigObject>>> {
31+
return this.getBrowseEndpoint(options).pipe(
32+
take(1),
33+
mergeMap((href: string) => super.findListByHref(href, options, useCachedVersionIfAvailable, reRequestOnStale, ...linksToFollow)),
34+
);
35+
}
36+
}

src/app/core/data-services-map.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ import { VERSION_HISTORY } from './shared/version-history.resource-type';
5959
import { USAGE_REPORT } from './statistics/models/usage-report.resource-type';
6060
import { CorrectionType } from './submission/models/correctiontype.model';
6161
import { EditItem } from './submission/models/edititem.model';
62+
import { METADATA_SECURITY_TYPE } from './submission/models/metadata-security-config.resource-type';
6263
import { SUBMISSION_CC_LICENSE } from './submission/models/submission-cc-licence.resource-type';
6364
import { SUBMISSION_CC_LICENSE_URL } from './submission/models/submission-cc-licence-link.resource-type';
6465
import {
@@ -140,4 +141,5 @@ export const LAZY_DATA_SERVICES: LazyDataServicesMap = new Map([
140141
[CorrectionType.type.value, () => import('./submission/correctiontype-data.service').then(m => m.CorrectionTypeDataService)],
141142
[AUDIT.value, () => import('./data/audit-data.service').then(m => m.AuditDataService)],
142143
[EditItem.type.value, () => import('./submission/edititem-data.service').then(m => m.EditItemDataService)],
144+
[METADATA_SECURITY_TYPE.value, () => import('./submission/metadatasecurityconfig-data.service').then(m => m.MetadataSecurityConfigurationService)],
143145
]);

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

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,21 +33,26 @@ export class FormFieldMetadataValueObject implements MetadataValueInterface {
3333
confidence: ConfidenceType;
3434
place: number;
3535
label: string;
36+
securityLevel: number;
37+
source: string;
3638
otherInformation: OtherInformation;
3739

3840
constructor(value: any = null,
3941
language: any = null,
42+
securityLevel: any = null,
4043
authority: string = null,
4144
display: string = null,
4245
place: number = 0,
4346
confidence: number = null,
4447
otherInformation: any = null,
45-
metadata: string = null) {
48+
source: string = null,
49+
metadata: string = null,
50+
) {
4651
this.value = isNotNull(value) ? ((typeof value === 'string') ? value.trim() : value) : null;
4752
this.language = language;
4853
this.authority = authority;
4954
this.display = display || value;
50-
55+
this.securityLevel = securityLevel;
5156
this.confidence = confidence;
5257
if (Metadata.hasValidAuthority(authority) && (isEmpty(confidence) || confidence === -1)) {
5358
this.confidence = ConfidenceType.CF_ACCEPTED;
@@ -61,7 +66,7 @@ export class FormFieldMetadataValueObject implements MetadataValueInterface {
6166
if (isNotEmpty(metadata)) {
6267
this.metadata = metadata;
6368
}
64-
69+
this.source = source;
6570
this.otherInformation = otherInformation;
6671
}
6772

@@ -100,6 +105,14 @@ export class FormFieldMetadataValueObject implements MetadataValueInterface {
100105
return this.hasValue() && this.value === PLACEHOLDER_PARENT_METADATA;
101106
}
102107

108+
/**
109+
* Returns true if this object value contains a placeholder
110+
*/
111+
hasSecurityLevel() {
112+
return isNotEmpty(this.securityLevel);
113+
}
114+
115+
103116
/**
104117
* Returns true if this Metadatum's authority key starts with 'virtual::'
105118
*/

src/app/core/shared/metadata.models.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,10 @@ export class MetadataValue implements MetadataValueInterface {
5656
/** The authority confidence value */
5757
@autoserialize
5858
confidence: number;
59+
60+
/** The security level value */
61+
@autoserialize
62+
securityLevel: number;
5963
}
6064

6165
/** Constraints for matching metadata values. */
@@ -104,6 +108,9 @@ export class MetadatumViewModel {
104108

105109
/** The authority confidence value */
106110
confidence: number;
111+
112+
/** The security level value */
113+
securityLevel: number;
107114
}
108115

109116
/** Serializer used for MetadataMaps.
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import { Injectable } from '@angular/core';
2+
import { Observable } from 'rxjs';
3+
4+
import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service';
5+
import { ObjectCacheService } from '../cache/object-cache.service';
6+
import { IdentifiableDataService } from '../data/base/identifiable-data.service';
7+
import { RemoteData } from '../data/remote-data';
8+
import { RequestService } from '../data/request.service';
9+
import { HALEndpointService } from '../shared/hal-endpoint.service';
10+
import { MetadataSecurityConfiguration } from './models/metadata-security-configuration';
11+
12+
/**
13+
* A service that provides methods to make REST requests with securitysettings endpoint.
14+
*/
15+
@Injectable({
16+
providedIn: 'root',
17+
})
18+
export class MetadataSecurityConfigurationService extends IdentifiableDataService<MetadataSecurityConfiguration> {
19+
20+
constructor(
21+
protected requestService: RequestService,
22+
protected rdbService: RemoteDataBuildService,
23+
protected objectCache: ObjectCacheService,
24+
protected halService: HALEndpointService,
25+
) {
26+
super('securitysettings', requestService, rdbService, objectCache, halService);
27+
}
28+
29+
/**
30+
* It provides the configuration for metadata security
31+
* @param entityType
32+
*/
33+
findById(entityType: string): Observable<RemoteData<MetadataSecurityConfiguration>> {
34+
return super.findById(entityType);
35+
}
36+
}
37+
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import { ResourceType } from '../../shared/resource-type';
2+
3+
4+
export const METADATA_SECURITY_TYPE = new ResourceType('securitysetting');

0 commit comments

Comments
 (0)