mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-07 01:54:15 +00:00
Merge pull request #3138 from 4Science/task/main/DURACOM-282
Fix error which prevent submitter to deposit a new item
This commit is contained in:
@@ -340,4 +340,384 @@ describe('jsonPatchOperationsReducer test suite', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('dedupeOperationEntries', () => {
|
||||||
|
it('should not remove duplicated keys if operations are not sequential', () => {
|
||||||
|
initState = {
|
||||||
|
sections: {
|
||||||
|
children: {
|
||||||
|
publicationStep: {
|
||||||
|
body: [
|
||||||
|
{
|
||||||
|
operation: {
|
||||||
|
op: 'add',
|
||||||
|
path: '/sections/publicationStep/dc.date.issued',
|
||||||
|
value: [
|
||||||
|
{
|
||||||
|
value: '2024-06',
|
||||||
|
language: null,
|
||||||
|
authority: null,
|
||||||
|
display: '2024-06',
|
||||||
|
confidence: -1,
|
||||||
|
place: 0,
|
||||||
|
otherInformation: null,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
timeCompleted: timestampBeforeStart,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
operation: {
|
||||||
|
op: 'replace',
|
||||||
|
path: '/sections/publicationStep/dc.date.issued/0',
|
||||||
|
value: {
|
||||||
|
value: '2023-06-19',
|
||||||
|
language: null,
|
||||||
|
authority: null,
|
||||||
|
display: '2023-06-19',
|
||||||
|
confidence: -1,
|
||||||
|
place: 0,
|
||||||
|
otherInformation: null,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
timeCompleted: timestampBeforeStart,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
} as JsonPatchOperationsEntry,
|
||||||
|
},
|
||||||
|
transactionStartTime: null,
|
||||||
|
commitPending: false,
|
||||||
|
} as JsonPatchOperationsResourceEntry,
|
||||||
|
};
|
||||||
|
|
||||||
|
const value = [
|
||||||
|
{
|
||||||
|
value: '2024-06-19',
|
||||||
|
language: null,
|
||||||
|
authority: null,
|
||||||
|
display: '2024-06-19',
|
||||||
|
confidence: -1,
|
||||||
|
place: 0,
|
||||||
|
otherInformation: null,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
const action = new NewPatchAddOperationAction(
|
||||||
|
'sections',
|
||||||
|
'publicationStep',
|
||||||
|
'/sections/publicationStep/dc.date.issued',
|
||||||
|
value);
|
||||||
|
const newState = jsonPatchOperationsReducer(initState, action);
|
||||||
|
|
||||||
|
const expectedBody: any = [
|
||||||
|
{
|
||||||
|
'operation': {
|
||||||
|
'op': 'add',
|
||||||
|
'path': '/sections/publicationStep/dc.date.issued',
|
||||||
|
'value': [
|
||||||
|
{
|
||||||
|
'value': '2024-06',
|
||||||
|
'language': null,
|
||||||
|
'authority': null,
|
||||||
|
'display': '2024-06',
|
||||||
|
'confidence': -1,
|
||||||
|
'place': 0,
|
||||||
|
'otherInformation': null,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
'timeCompleted': timestampBeforeStart,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'operation': {
|
||||||
|
'op': 'replace',
|
||||||
|
'path': '/sections/publicationStep/dc.date.issued/0',
|
||||||
|
'value': {
|
||||||
|
'value': '2023-06-19',
|
||||||
|
'language': null,
|
||||||
|
'authority': null,
|
||||||
|
'display': '2023-06-19',
|
||||||
|
'confidence': -1,
|
||||||
|
'place': 0,
|
||||||
|
'otherInformation': null,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'timeCompleted': timestampBeforeStart,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'operation': {
|
||||||
|
'op': 'add',
|
||||||
|
'path': '/sections/publicationStep/dc.date.issued',
|
||||||
|
'value': [
|
||||||
|
{
|
||||||
|
'value': '2024-06-19',
|
||||||
|
'language': null,
|
||||||
|
'authority': null,
|
||||||
|
'display': '2024-06-19',
|
||||||
|
'confidence': -1,
|
||||||
|
'place': 0,
|
||||||
|
'otherInformation': null,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
'timeCompleted': timestampBeforeStart,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
expect(newState.sections.children.publicationStep.body).toEqual(expectedBody);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should remove duplicated keys if operations are sequential', () => {
|
||||||
|
initState = {
|
||||||
|
sections: {
|
||||||
|
children: {
|
||||||
|
publicationStep: {
|
||||||
|
body: [
|
||||||
|
{
|
||||||
|
operation: {
|
||||||
|
op: 'add',
|
||||||
|
path: '/sections/publicationStep/dc.date.issued',
|
||||||
|
value: [
|
||||||
|
{
|
||||||
|
value: '2024-06',
|
||||||
|
language: null,
|
||||||
|
authority: null,
|
||||||
|
display: '2024-06',
|
||||||
|
confidence: -1,
|
||||||
|
place: 0,
|
||||||
|
otherInformation: null,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
timeCompleted: timestampBeforeStart,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
operation: {
|
||||||
|
op: 'replace',
|
||||||
|
path: '/sections/publicationStep/dc.date.issued/0',
|
||||||
|
value: {
|
||||||
|
value: '2023-06-19',
|
||||||
|
language: null,
|
||||||
|
authority: null,
|
||||||
|
display: '2023-06-19',
|
||||||
|
confidence: -1,
|
||||||
|
place: 0,
|
||||||
|
otherInformation: null,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
timeCompleted: timestampBeforeStart,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'operation': {
|
||||||
|
'op': 'add',
|
||||||
|
'path': '/sections/publicationStep/dc.date.issued',
|
||||||
|
'value': [
|
||||||
|
{
|
||||||
|
'value': '2024-06-19',
|
||||||
|
'language': null,
|
||||||
|
'authority': null,
|
||||||
|
'display': '2024-06-19',
|
||||||
|
'confidence': -1,
|
||||||
|
'place': 0,
|
||||||
|
'otherInformation': null,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
'timeCompleted': timestampBeforeStart,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
} as JsonPatchOperationsEntry,
|
||||||
|
},
|
||||||
|
transactionStartTime: null,
|
||||||
|
commitPending: false,
|
||||||
|
} as JsonPatchOperationsResourceEntry,
|
||||||
|
};
|
||||||
|
|
||||||
|
const value = [
|
||||||
|
{
|
||||||
|
value: '2024-06-20',
|
||||||
|
language: null,
|
||||||
|
authority: null,
|
||||||
|
display: '2024-06-20',
|
||||||
|
confidence: -1,
|
||||||
|
place: 0,
|
||||||
|
otherInformation: null,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
const action = new NewPatchAddOperationAction(
|
||||||
|
'sections',
|
||||||
|
'publicationStep',
|
||||||
|
'/sections/publicationStep/dc.date.issued',
|
||||||
|
value);
|
||||||
|
const newState = jsonPatchOperationsReducer(initState, action);
|
||||||
|
|
||||||
|
const expectedBody: any = [
|
||||||
|
{
|
||||||
|
'operation': {
|
||||||
|
'op': 'add',
|
||||||
|
'path': '/sections/publicationStep/dc.date.issued',
|
||||||
|
'value': [
|
||||||
|
{
|
||||||
|
'value': '2024-06',
|
||||||
|
'language': null,
|
||||||
|
'authority': null,
|
||||||
|
'display': '2024-06',
|
||||||
|
'confidence': -1,
|
||||||
|
'place': 0,
|
||||||
|
'otherInformation': null,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
'timeCompleted': timestampBeforeStart,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'operation': {
|
||||||
|
'op': 'replace',
|
||||||
|
'path': '/sections/publicationStep/dc.date.issued/0',
|
||||||
|
'value': {
|
||||||
|
'value': '2023-06-19',
|
||||||
|
'language': null,
|
||||||
|
'authority': null,
|
||||||
|
'display': '2023-06-19',
|
||||||
|
'confidence': -1,
|
||||||
|
'place': 0,
|
||||||
|
'otherInformation': null,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'timeCompleted': timestampBeforeStart,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'operation': {
|
||||||
|
'op': 'add',
|
||||||
|
'path': '/sections/publicationStep/dc.date.issued',
|
||||||
|
'value': [
|
||||||
|
{
|
||||||
|
'value': '2024-06-20',
|
||||||
|
'language': null,
|
||||||
|
'authority': null,
|
||||||
|
'display': '2024-06-20',
|
||||||
|
'confidence': -1,
|
||||||
|
'place': 0,
|
||||||
|
'otherInformation': null,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
'timeCompleted': timestampBeforeStart,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
expect(newState.sections.children.publicationStep.body).toEqual(expectedBody);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should remove duplicated keys if all operations have same key', () => {
|
||||||
|
initState = {
|
||||||
|
sections: {
|
||||||
|
children: {
|
||||||
|
publicationStep: {
|
||||||
|
body: [
|
||||||
|
{
|
||||||
|
operation: {
|
||||||
|
op: 'add',
|
||||||
|
path: '/sections/publicationStep/dc.date.issued',
|
||||||
|
value: [
|
||||||
|
{
|
||||||
|
value: '2024',
|
||||||
|
language: null,
|
||||||
|
authority: null,
|
||||||
|
display: '2024-06',
|
||||||
|
confidence: -1,
|
||||||
|
place: 0,
|
||||||
|
otherInformation: null,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
timeCompleted: timestampBeforeStart,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'operation': {
|
||||||
|
'op': 'add',
|
||||||
|
'path': '/sections/publicationStep/dc.date.issued',
|
||||||
|
'value': [
|
||||||
|
{
|
||||||
|
'value': '2024-06',
|
||||||
|
'language': null,
|
||||||
|
'authority': null,
|
||||||
|
'display': '2024-06',
|
||||||
|
'confidence': -1,
|
||||||
|
'place': 0,
|
||||||
|
'otherInformation': null,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
'timeCompleted': timestampBeforeStart,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'operation': {
|
||||||
|
'op': 'add',
|
||||||
|
'path': '/sections/publicationStep/dc.date.issued',
|
||||||
|
'value': [
|
||||||
|
{
|
||||||
|
'value': '2024-06-19',
|
||||||
|
'language': null,
|
||||||
|
'authority': null,
|
||||||
|
'display': '2024-06-19',
|
||||||
|
'confidence': -1,
|
||||||
|
'place': 0,
|
||||||
|
'otherInformation': null,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
'timeCompleted': timestampBeforeStart,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
} as JsonPatchOperationsEntry,
|
||||||
|
},
|
||||||
|
transactionStartTime: null,
|
||||||
|
commitPending: false,
|
||||||
|
} as JsonPatchOperationsResourceEntry,
|
||||||
|
};
|
||||||
|
|
||||||
|
const value = [
|
||||||
|
{
|
||||||
|
value: '2024-06-20',
|
||||||
|
language: null,
|
||||||
|
authority: null,
|
||||||
|
display: '2024-06-20',
|
||||||
|
confidence: -1,
|
||||||
|
place: 0,
|
||||||
|
otherInformation: null,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
const action = new NewPatchAddOperationAction(
|
||||||
|
'sections',
|
||||||
|
'publicationStep',
|
||||||
|
'/sections/publicationStep/dc.date.issued',
|
||||||
|
value);
|
||||||
|
const newState = jsonPatchOperationsReducer(initState, action);
|
||||||
|
|
||||||
|
const expectedBody: any = [
|
||||||
|
{
|
||||||
|
'operation': {
|
||||||
|
'op': 'add',
|
||||||
|
'path': '/sections/publicationStep/dc.date.issued',
|
||||||
|
'value': [
|
||||||
|
{
|
||||||
|
'value': '2024-06-20',
|
||||||
|
'language': null,
|
||||||
|
'authority': null,
|
||||||
|
'display': '2024-06-20',
|
||||||
|
'confidence': -1,
|
||||||
|
'place': 0,
|
||||||
|
'otherInformation': null,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
'timeCompleted': timestampBeforeStart,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
expect(newState.sections.children.publicationStep.body).toEqual(expectedBody);
|
||||||
|
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@@ -406,14 +406,18 @@ function addOperationToList(body: JsonPatchOperationObject[], actionType, target
|
|||||||
* @returns deduped JSON patch operation object entries
|
* @returns deduped JSON patch operation object entries
|
||||||
*/
|
*/
|
||||||
function dedupeOperationEntries(body: JsonPatchOperationObject[]): JsonPatchOperationObject[] {
|
function dedupeOperationEntries(body: JsonPatchOperationObject[]): JsonPatchOperationObject[] {
|
||||||
const ops = new Map<string, any>();
|
const ops = new Map<string, number>();
|
||||||
for (let i = body.length - 1; i >= 0; i--) {
|
for (let i = body.length - 1; i >= 0; i--) {
|
||||||
const patch = body[i].operation;
|
const patch = body[i].operation;
|
||||||
const key = `${patch.op}-${patch.path}`;
|
const key = `${patch.op}-${patch.path}`;
|
||||||
if (!ops.has(key)) {
|
if (!ops.has(key)) {
|
||||||
ops.set(key, patch);
|
ops.set(key, i);
|
||||||
} else {
|
} else {
|
||||||
body.splice(i, 1);
|
const entry = ops.get(key);
|
||||||
|
if (entry - 1 === i) {
|
||||||
|
body.splice(i, 1);
|
||||||
|
ops.set(key, i);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -8,7 +8,10 @@ import {
|
|||||||
|
|
||||||
import { getDSORoute } from '../../app-routing-paths';
|
import { getDSORoute } from '../../app-routing-paths';
|
||||||
import { Breadcrumb } from '../../breadcrumbs/breadcrumb/breadcrumb.model';
|
import { Breadcrumb } from '../../breadcrumbs/breadcrumb/breadcrumb.model';
|
||||||
import { hasValue } from '../../shared/empty.util';
|
import {
|
||||||
|
hasValue,
|
||||||
|
isEmpty,
|
||||||
|
} from '../../shared/empty.util';
|
||||||
import { SubmissionService } from '../../submission/submission.service';
|
import { SubmissionService } from '../../submission/submission.service';
|
||||||
import { BreadcrumbsProviderService } from '../breadcrumbs/breadcrumbsProviderService';
|
import { BreadcrumbsProviderService } from '../breadcrumbs/breadcrumbsProviderService';
|
||||||
import { DSOBreadcrumbsService } from '../breadcrumbs/dso-breadcrumbs.service';
|
import { DSOBreadcrumbsService } from '../breadcrumbs/dso-breadcrumbs.service';
|
||||||
@@ -46,6 +49,10 @@ export class SubmissionParentBreadcrumbsService implements BreadcrumbsProviderSe
|
|||||||
* @param submissionObject The {@link SubmissionObject} for which the parent breadcrumb structure needs to be created
|
* @param submissionObject The {@link SubmissionObject} for which the parent breadcrumb structure needs to be created
|
||||||
*/
|
*/
|
||||||
getBreadcrumbs(submissionObject: SubmissionObject): Observable<Breadcrumb[]> {
|
getBreadcrumbs(submissionObject: SubmissionObject): Observable<Breadcrumb[]> {
|
||||||
|
if (isEmpty(submissionObject)) {
|
||||||
|
return observableOf([]);
|
||||||
|
}
|
||||||
|
|
||||||
return combineLatest([
|
return combineLatest([
|
||||||
(submissionObject.collection as Observable<RemoteData<Collection>>).pipe(
|
(submissionObject.collection as Observable<RemoteData<Collection>>).pipe(
|
||||||
getFirstCompletedRemoteData(),
|
getFirstCompletedRemoteData(),
|
||||||
|
@@ -13,6 +13,7 @@ import {
|
|||||||
isNotEmpty,
|
isNotEmpty,
|
||||||
} from '../../shared/empty.util';
|
} from '../../shared/empty.util';
|
||||||
import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service';
|
import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service';
|
||||||
|
import { ErrorResponse } from '../cache/response.models';
|
||||||
import { RemoteData } from '../data/remote-data';
|
import { RemoteData } from '../data/remote-data';
|
||||||
import {
|
import {
|
||||||
DeleteRequest,
|
DeleteRequest,
|
||||||
@@ -23,6 +24,7 @@ import {
|
|||||||
SubmissionRequest,
|
SubmissionRequest,
|
||||||
} from '../data/request.models';
|
} from '../data/request.models';
|
||||||
import { RequestService } from '../data/request.service';
|
import { RequestService } from '../data/request.service';
|
||||||
|
import { RequestError } from '../data/request-error.model';
|
||||||
import { RestRequest } from '../data/rest-request.model';
|
import { RestRequest } from '../data/rest-request.model';
|
||||||
import { HttpOptions } from '../dspace-rest/dspace-rest.service';
|
import { HttpOptions } from '../dspace-rest/dspace-rest.service';
|
||||||
import { HALEndpointService } from '../shared/hal-endpoint.service';
|
import { HALEndpointService } from '../shared/hal-endpoint.service';
|
||||||
@@ -57,7 +59,7 @@ export class SubmissionRestService {
|
|||||||
getFirstCompletedRemoteData(),
|
getFirstCompletedRemoteData(),
|
||||||
map((response: RemoteData<SubmissionResponse>) => {
|
map((response: RemoteData<SubmissionResponse>) => {
|
||||||
if (response.hasFailed) {
|
if (response.hasFailed) {
|
||||||
throw new Error(response.errorMessage);
|
throw new ErrorResponse({ statusText: response.errorMessage, statusCode: response.statusCode } as RequestError);
|
||||||
} else {
|
} else {
|
||||||
return hasValue(response.payload) ? response.payload.dataDefinition : response.payload;
|
return hasValue(response.payload) ? response.payload.dataDefinition : response.payload;
|
||||||
}
|
}
|
||||||
|
@@ -227,20 +227,21 @@ export class SubmissionSectionUploadComponent extends SectionModelComponent {
|
|||||||
this.changeDetectorRef.detectChanges();
|
this.changeDetectorRef.detectChanges();
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
|
||||||
// retrieve submission's bitstream data from state
|
// retrieve submission's bitstream data from state
|
||||||
combineLatest([this.configMetadataForm$,
|
combineLatest([
|
||||||
this.bitstreamService.getUploadedFilesData(this.submissionId, this.sectionData.id)]).pipe(
|
this.configMetadataForm$,
|
||||||
filter(([configMetadataForm, { files }]: [SubmissionFormsModel, WorkspaceitemSectionUploadObject]) => {
|
this.bitstreamService.getUploadedFilesData(this.submissionId, this.sectionData.id),
|
||||||
return isNotEmpty(configMetadataForm) && isNotEmpty(files);
|
]).pipe(
|
||||||
|
filter(([configMetadataForm, sectionUploadObject]: [SubmissionFormsModel, WorkspaceitemSectionUploadObject]) => {
|
||||||
|
return isNotEmpty(configMetadataForm) && isNotEmpty(sectionUploadObject);
|
||||||
}),
|
}),
|
||||||
distinctUntilChanged())
|
distinctUntilChanged(),
|
||||||
.subscribe(([configMetadataForm, { primary, files }]: [SubmissionFormsModel, WorkspaceitemSectionUploadObject]) => {
|
).subscribe(([configMetadataForm, { primary, files }]: [SubmissionFormsModel, WorkspaceitemSectionUploadObject]) => {
|
||||||
this.primaryBitstreamUUID = primary;
|
this.primaryBitstreamUUID = primary;
|
||||||
this.fileList = files;
|
this.fileList = files;
|
||||||
this.fileNames = Array.from(files, file => this.getFileName(configMetadataForm, file));
|
this.fileNames = Array.from(files, file => this.getFileName(configMetadataForm, file));
|
||||||
},
|
this.changeDetectorRef.detectChanges();
|
||||||
),
|
}),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user