Skip to content

Commit 4655dae

Browse files
committed
feat(ENG-9827): fix conflicts
1 parent 323a6a1 commit 4655dae

7 files changed

Lines changed: 111 additions & 26 deletions

File tree

src/app/features/collections/components/add-to-collection/add-to-collection-confirmation-dialog/add-to-collection-confirmation-dialog.component.spec.ts

Lines changed: 57 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@ import { of, throwError } from 'rxjs';
99
import { ComponentFixture, TestBed } from '@angular/core/testing';
1010

1111
import { CreateCollectionSubmission } from '@osf/features/collections/store/add-to-collection/add-to-collection.actions';
12+
import { CreateCedarMetadataRecord } from '@osf/features/metadata/store';
1213
import { UpdateProjectPublicStatus } from '@osf/features/project/overview/store';
14+
import { ResourceType } from '@osf/shared/enums/resource-type.enum';
1315
import { ToastService } from '@osf/shared/services/toast.service';
1416

1517
import { provideOSFCore } from '@testing/osf.testing.provider';
@@ -19,20 +21,33 @@ import { ToastServiceMock, ToastServiceMockType } from '@testing/providers/toast
1921

2022
import { AddToCollectionConfirmationDialogComponent } from './add-to-collection-confirmation-dialog.component';
2123

24+
const MOCK_CEDAR_DATA = {
25+
data: { '@context': {} },
26+
id: 'template-1',
27+
isPublished: true,
28+
} as any;
29+
2230
describe('AddToCollectionConfirmationDialogComponent', () => {
2331
let component: AddToCollectionConfirmationDialogComponent;
2432
let fixture: ComponentFixture<AddToCollectionConfirmationDialogComponent>;
2533
let store: Store;
2634
let dialogRef: DynamicDialogRef;
2735
let toastService: ToastServiceMockType;
28-
let dialogConfig: { data: { payload?: unknown; project?: { id: string; isPublic: boolean } } };
36+
let dialogConfig: {
37+
data: {
38+
payload?: unknown;
39+
project?: { id: string; isPublic: boolean };
40+
cedarData?: unknown;
41+
};
42+
};
2943

3044
beforeEach(() => {
3145
toastService = ToastServiceMock.simple();
3246
dialogConfig = {
3347
data: {
3448
payload: { title: 'Submission' },
3549
project: { id: 'project-1', isPublic: false },
50+
cedarData: null,
3651
},
3752
};
3853

@@ -69,13 +84,14 @@ describe('AddToCollectionConfirmationDialogComponent', () => {
6984
expect(toastService.showSuccess).not.toHaveBeenCalled();
7085
});
7186

72-
it('should update project public status and create submission when project is private', () => {
87+
it('should update project public status then create submission when project is private and no Cedar data', () => {
7388
vi.spyOn(store, 'dispatch').mockReturnValue(of(void 0));
7489

7590
component.handleAddToCollectionConfirm();
7691

7792
expect(store.dispatch).toHaveBeenCalledWith(new UpdateProjectPublicStatus([{ id: 'project-1', public: true }]));
7893
expect(store.dispatch).toHaveBeenCalledWith(new CreateCollectionSubmission({ title: 'Submission' } as any));
94+
expect(store.dispatch).not.toHaveBeenCalledWith(expect.any(CreateCedarMetadataRecord));
7995
expect(dialogRef.close).toHaveBeenCalledWith(true);
8096
expect(toastService.showSuccess).toHaveBeenCalledWith('collections.addToCollection.confirmationDialogToastMessage');
8197
expect(component.isSubmitting()).toBe(false);
@@ -92,6 +108,29 @@ describe('AddToCollectionConfirmationDialogComponent', () => {
92108
expect(dialogRef.close).toHaveBeenCalledWith(true);
93109
});
94110

111+
it('should create Cedar record before submission when cedarData is present', () => {
112+
dialogConfig.data.cedarData = MOCK_CEDAR_DATA;
113+
vi.spyOn(store, 'dispatch').mockReturnValue(of(void 0));
114+
115+
component.handleAddToCollectionConfirm();
116+
117+
expect(store.dispatch).toHaveBeenCalledWith(
118+
new CreateCedarMetadataRecord(MOCK_CEDAR_DATA, 'project-1', ResourceType.Project)
119+
);
120+
expect(store.dispatch).toHaveBeenCalledWith(new CreateCollectionSubmission({ title: 'Submission' } as any));
121+
expect(dialogRef.close).toHaveBeenCalledWith(true);
122+
});
123+
124+
it('should not create Cedar record when cedarData is null', () => {
125+
dialogConfig.data.cedarData = null;
126+
vi.spyOn(store, 'dispatch').mockReturnValue(of(void 0));
127+
128+
component.handleAddToCollectionConfirm();
129+
130+
expect(store.dispatch).not.toHaveBeenCalledWith(expect.any(CreateCedarMetadataRecord));
131+
expect(store.dispatch).toHaveBeenCalledWith(new CreateCollectionSubmission({ title: 'Submission' } as any));
132+
});
133+
95134
it('should reset submitting state on error', () => {
96135
vi.spyOn(store, 'dispatch').mockImplementation((action) => {
97136
if (action instanceof CreateCollectionSubmission) {
@@ -106,4 +145,20 @@ describe('AddToCollectionConfirmationDialogComponent', () => {
106145
expect(dialogRef.close).not.toHaveBeenCalled();
107146
expect(toastService.showSuccess).not.toHaveBeenCalled();
108147
});
148+
149+
it('should reset submitting state on Cedar record creation error', () => {
150+
dialogConfig.data.cedarData = MOCK_CEDAR_DATA;
151+
vi.spyOn(store, 'dispatch').mockImplementation((action) => {
152+
if (action instanceof CreateCedarMetadataRecord) {
153+
return throwError(() => new Error('cedar fail'));
154+
}
155+
return of(void 0);
156+
});
157+
158+
component.handleAddToCollectionConfirm();
159+
160+
expect(component.isSubmitting()).toBe(false);
161+
expect(dialogRef.close).not.toHaveBeenCalled();
162+
expect(toastService.showSuccess).not.toHaveBeenCalled();
163+
});
109164
});

src/app/features/collections/components/add-to-collection/add-to-collection-confirmation-dialog/add-to-collection-confirmation-dialog.component.ts

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,16 @@ import { TranslatePipe } from '@ngx-translate/core';
55
import { Button } from 'primeng/button';
66
import { DynamicDialogConfig, DynamicDialogRef } from 'primeng/dynamicdialog';
77

8-
import { forkJoin, of } from 'rxjs';
8+
import { Observable, of, switchMap } from 'rxjs';
99

1010
import { ChangeDetectionStrategy, Component, DestroyRef, inject, signal } from '@angular/core';
1111
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
1212

1313
import { CreateCollectionSubmission } from '@osf/features/collections/store/add-to-collection/add-to-collection.actions';
14+
import { CedarRecordDataBinding } from '@osf/features/metadata/models';
15+
import { CreateCedarMetadataRecord } from '@osf/features/metadata/store';
1416
import { UpdateProjectPublicStatus } from '@osf/features/project/overview/store';
17+
import { ResourceType } from '@osf/shared/enums/resource-type.enum';
1518
import { ToastService } from '@osf/shared/services/toast.service';
1619

1720
@Component({
@@ -30,26 +33,33 @@ export class AddToCollectionConfirmationDialogComponent {
3033
actions = createDispatchMap({
3134
createCollectionSubmission: CreateCollectionSubmission,
3235
updateProjectPublicStatus: UpdateProjectPublicStatus,
36+
createCedarRecord: CreateCedarMetadataRecord,
3337
});
3438

3539
handleAddToCollectionConfirm(): void {
3640
const payload = this.config.data.payload;
3741
const project = this.config.data.project;
42+
const cedarData = this.config.data.cedarData as CedarRecordDataBinding | null | undefined;
3843

3944
if (!payload || !project) return;
4045

4146
this.isSubmitting.set(true);
4247
const projectPayload = [{ id: project.id as string, public: true }];
4348

44-
const updatePublicStatus$ = project.isPublic ? of(null) : this.actions.updateProjectPublicStatus(projectPayload);
49+
const updatePublicStatus$: Observable<unknown> = project.isPublic
50+
? of(null)
51+
: this.actions.updateProjectPublicStatus(projectPayload);
4552

46-
const createSubmission$ = this.actions.createCollectionSubmission(payload);
53+
const createCedar$: Observable<unknown> = cedarData
54+
? this.actions.createCedarRecord(cedarData, project.id as string, ResourceType.Project)
55+
: of(null);
4756

48-
forkJoin({
49-
publicStatusUpdate: updatePublicStatus$,
50-
collectionSubmission: createSubmission$,
51-
})
52-
.pipe(takeUntilDestroyed(this.destroyRef))
57+
updatePublicStatus$
58+
.pipe(
59+
switchMap(() => createCedar$),
60+
switchMap(() => this.actions.createCollectionSubmission(payload)),
61+
takeUntilDestroyed(this.destroyRef)
62+
)
5363
.subscribe({
5464
next: () => {
5565
this.isSubmitting.set(false);

src/app/features/collections/components/add-to-collection/add-to-collection.component.ts

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -211,19 +211,18 @@ export class AddToCollectionComponent implements CanDeactivateComponent {
211211
const payload = {
212212
collectionId: this.primaryCollectionId() || '',
213213
projectId: this.selectedProject()?.id || '',
214-
collectionMetadata: this.isCedarMode() ? {} : this.collectionMetadataForm.value || {},
215214
userId: this.currentUser()?.id || '',
215+
collectionMetadata: this.isCedarMode() ? {} : this.collectionMetadataForm.value || {},
216216
};
217217

218218
const isEditMode = this.isEditMode();
219219

220220
if (isEditMode) {
221221
this.loaderService.show();
222222

223-
this.actions
224-
.updateCollectionSubmission(payload)
223+
this.saveCedarRecordIfNeeded()
225224
.pipe(
226-
switchMap(() => this.saveCedarRecordIfNeeded()),
225+
switchMap(() => this.actions.updateCollectionSubmission(payload)),
227226
finalize(() => this.loaderService.hide()),
228227
takeUntilDestroyed(this.destroyRef)
229228
)
@@ -242,7 +241,11 @@ export class AddToCollectionComponent implements CanDeactivateComponent {
242241
.open(AddToCollectionConfirmationDialogComponent, {
243242
header: 'collections.addToCollection.confirmationDialogHeader',
244243
width: '500px',
245-
data: { payload, project: this.selectedProject() },
244+
data: {
245+
payload,
246+
project: this.selectedProject(),
247+
cedarData: this.pendingCedarData(),
248+
},
246249
})
247250
.onClose.pipe(
248251
filter((res) => !!res),
@@ -277,13 +280,13 @@ export class AddToCollectionComponent implements CanDeactivateComponent {
277280
.onClose.pipe(
278281
filter((res: RemoveFromCollectionDialogResult) => res?.confirmed),
279282
switchMap((res) => {
280-
const payload: RemoveCollectionSubmissionPayload = {
283+
const removePayload: RemoveCollectionSubmissionPayload = {
281284
projectId,
282285
collectionId,
283286
comment: res?.comment || '',
284287
};
285-
286-
return this.actions.deleteCollectionSubmission(payload);
288+
this.loaderService.show();
289+
return this.actions.deleteCollectionSubmission(removePayload);
287290
}),
288291
takeUntilDestroyed(this.destroyRef)
289292
)

src/app/features/collections/components/add-to-collection/collection-metadata-step/collection-metadata-step.component.spec.ts

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,13 @@ describe('CollectionMetadataStepComponent', () => {
2020
let component: CollectionMetadataStepComponent;
2121
let fixture: ComponentFixture<CollectionMetadataStepComponent>;
2222

23-
function setup(isCedarMode = false, cedarTemplate: CedarMetadataDataTemplateJsonApi | null = null) {
23+
function setup(
24+
options: {
25+
isCedarMode?: boolean;
26+
cedarTemplate?: CedarMetadataDataTemplateJsonApi | null;
27+
existingCedarRecord?: CedarMetadataRecordData | null;
28+
} = {}
29+
) {
2430
TestBed.configureTestingModule({
2531
imports: [CollectionMetadataStepComponent, MockComponents(StepPanel, Step, StepItem)],
2632
providers: [
@@ -43,9 +49,15 @@ describe('CollectionMetadataStepComponent', () => {
4349
fixture.componentRef.setInput('targetStepValue', 1);
4450
fixture.componentRef.setInput('isDisabled', false);
4551
fixture.componentRef.setInput('primaryCollectionId', 'test-collection-id');
46-
fixture.componentRef.setInput('isCedarMode', isCedarMode);
47-
if (cedarTemplate) {
48-
fixture.componentRef.setInput('cedarTemplate', cedarTemplate);
52+
53+
if (options.isCedarMode !== undefined) {
54+
fixture.componentRef.setInput('isCedarMode', options.isCedarMode);
55+
}
56+
if (options.cedarTemplate !== undefined) {
57+
fixture.componentRef.setInput('cedarTemplate', options.cedarTemplate);
58+
}
59+
if (options.existingCedarRecord !== undefined) {
60+
fixture.componentRef.setInput('existingCedarRecord', options.existingCedarRecord);
4961
}
5062

5163
fixture.detectChanges();
@@ -66,6 +78,10 @@ describe('CollectionMetadataStepComponent', () => {
6678
expect(component.isCedarMode()).toBe(false);
6779
});
6880

81+
it('should default isCedarMode to false', () => {
82+
expect(component.isCedarMode()).toBe(false);
83+
});
84+
6985
it('should handle save metadata in filter mode', () => {
7086
const mockForm = new FormGroup({});
7187
component.collectionMetadataForm.set(mockForm);
@@ -128,7 +144,7 @@ describe('CollectionMetadataStepComponent', () => {
128144

129145
describe('CEDAR mode', () => {
130146
beforeEach(() => {
131-
setup(true, MOCK_CEDAR_TEMPLATE);
147+
setup({ isCedarMode: true, cedarTemplate: MOCK_CEDAR_TEMPLATE });
132148
});
133149

134150
it('should initialize in CEDAR mode', () => {

src/app/features/collections/components/add-to-collection/collection-metadata-step/collection-metadata-step.component.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,7 @@ export class CollectionMetadataStepComponent {
149149
};
150150

151151
this.collectionMetadataSaved.set(true);
152+
this.metadataSaved.emit(this.collectionMetadataForm());
152153
this.cedarDataSaved.emit(cedarData);
153154
this.stepChange.emit(AddToCollectionSteps.Complete);
154155
}

src/app/shared/mappers/collections/collections.mapper.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,7 @@ export class CollectionsMapper {
243243

244244
static toCollectionSubmissionRequest(payload: CollectionSubmissionPayload): CollectionSubmissionPayloadJsonApi {
245245
const collectionId = payload.collectionId;
246-
const collectionsMetadata = convertToSnakeCase(payload.collectionMetadata);
246+
const collectionsMetadata = payload.collectionMetadata ? convertToSnakeCase(payload.collectionMetadata) : {};
247247

248248
return {
249249
data: {
@@ -271,7 +271,7 @@ export class CollectionsMapper {
271271
}
272272

273273
static collectionSubmissionUpdateRequest(payload: CollectionSubmissionPayload) {
274-
const collectionsMetadata = convertToSnakeCase(payload.collectionMetadata);
274+
const collectionsMetadata = payload.collectionMetadata ? convertToSnakeCase(payload.collectionMetadata) : {};
275275

276276
return {
277277
data: {

src/app/shared/models/collections/collection-submission-payload.model.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@ export interface CollectionSubmissionPayload {
22
collectionId: string;
33
projectId: string;
44
userId: string;
5-
collectionMetadata: Record<string, string>;
5+
collectionMetadata?: Record<string, string>;
66
}

0 commit comments

Comments
 (0)