Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,8 @@ <h1 class="collections-heading flex align-items-center">{{ collectionProvider()?
[stepperActiveValue]="stepperActiveValue()"
[targetStepValue]="AddToCollectionSteps.CollectionMetadata"
[isDisabled]="isCollectionMetadataDisabled()"
[primaryCollectionId]="primaryCollectionId()"
[isCedarMode]="isCedarMode()"
[cedarTemplate]="requiredMetadataTemplate()"
[existingCedarRecord]="existingCedarRecord()"
(metadataSaved)="handleCollectionMetadataSaved($event)"
(cedarDataSaved)="handleCedarDataSaved($event)"
(stepChange)="handleChangeStep($event)"
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { MockComponents, MockProvider } from 'ng-mocks';
import { of, Subject, throwError } from 'rxjs';

import { ComponentFixture, TestBed } from '@angular/core/testing';
import { FormGroup } from '@angular/forms';
import { ActivatedRoute, Router } from '@angular/router';

import { UserSelectors } from '@core/store/user';
Expand Down Expand Up @@ -51,7 +50,6 @@ const DEFAULT_SIGNALS: SignalOverride[] = [
{ selector: CollectionsSelectors.getRequiredMetadataTemplate, value: null },
{ selector: ProjectsSelectors.getSelectedProject, value: MOCK_PROJECT },
{ selector: UserSelectors.getCurrentUser, value: MOCK_USER },
{ selector: UserSelectors.getActiveFlags, value: [] },
{ selector: MetadataSelectors.getCedarRecords, value: [] },
{ selector: AddToCollectionSelectors.getCurrentCollectionSubmission, value: null },
];
Expand Down Expand Up @@ -175,16 +173,6 @@ describe('AddToCollectionComponent', () => {
expect(component.projectContributorsSaved()).toBe(true);
});

it('should handle collection metadata saved', () => {
const { component } = setup();
const mockForm = new FormGroup({});
component.handleCollectionMetadataSaved(mockForm);

expect(component.collectionMetadataForm).toBe(mockForm);
expect(component.collectionMetadataSaved()).toBe(true);
expect(component.stepperActiveValue()).toBe(AddToCollectionSteps.Complete);
});

it('should handle cedar data saved', () => {
const { component } = setup();
const mockCedarData: CedarRecordDataBinding = {
Expand Down Expand Up @@ -283,11 +271,10 @@ describe('AddToCollectionComponent', () => {
);
});

it('should update submission and navigate on success in edit mode', () => {
it('should navigate on success in edit mode', () => {
const { component, mockToastService, mockLoaderService, mockRouter } = setup({
routeParams: { id: 'project-1', providerId: 'provider-1' },
});
vi.spyOn(component.actions, 'updateCollectionSubmission').mockReturnValue(of(void 0));

component.handleAddToCollection();

Expand All @@ -299,11 +286,20 @@ describe('AddToCollectionComponent', () => {
expect(mockRouter.navigate).toHaveBeenCalledWith(['project-1', 'overview']);
});

it('should show error toast when update fails in edit mode', () => {
it('should show error toast when saving cedar record fails in edit mode', () => {
const { component, mockToastService } = setup({
routeParams: { id: 'project-1', providerId: 'provider-1' },
selectorOverrides: [
{ selector: CollectionsSelectors.getRequiredMetadataTemplate, value: { id: 'template-123' } },
],
});
vi.spyOn(component.actions, 'updateCollectionSubmission').mockReturnValue(throwError(() => new Error('fail')));
const mockCedarData: CedarRecordDataBinding = {
data: {} as CedarRecordDataBinding['data'],
id: 'template-123',
isPublished: false,
};
component.handleCedarDataSaved(mockCedarData);
vi.spyOn(component.actions, 'createCedarRecord').mockReturnValue(throwError(() => new Error('fail')));

component.handleAddToCollection();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,8 @@ import {
signal,
} from '@angular/core';
import { takeUntilDestroyed, toSignal } from '@angular/core/rxjs-interop';
import { FormGroup } from '@angular/forms';
import { ActivatedRoute, Router, RouterLink } from '@angular/router';

import { ENVIRONMENT } from '@core/provider/environment.provider';
import { UserSelectors } from '@core/store/user';
import { CedarMetadataRecordData, CedarRecordDataBinding } from '@osf/features/metadata/models';
import {
Expand All @@ -43,7 +41,6 @@ import { LoaderService } from '@osf/shared/services/loader.service';
import { ToastService } from '@osf/shared/services/toast.service';
import { CollectionsSelectors, GetCollectionProvider } from '@osf/shared/stores/collections';
import { ProjectsSelectors, SetSelectedProject } from '@osf/shared/stores/projects';
import { COLLECTION_SUBMISSION_WITH_CEDAR } from '@shared/constants/feature-flags.const';

import { AddToCollectionSteps } from '../../enums';
import { RemoveCollectionSubmissionPayload } from '../../models/remove-collection-submission-payload.model';
Expand All @@ -53,7 +50,6 @@ import {
ClearAddToCollectionState,
GetCurrentCollectionSubmission,
RemoveCollectionSubmission,
UpdateCollectionSubmission,
} from '../../store/add-to-collection';

import { AddToCollectionConfirmationDialogComponent } from './add-to-collection-confirmation-dialog/add-to-collection-confirmation-dialog.component';
Expand Down Expand Up @@ -91,22 +87,18 @@ export class AddToCollectionComponent implements CanDeactivateComponent {
private readonly headerStyleHelper = inject(HeaderStyleService);
private readonly platformId = inject(PLATFORM_ID);
private readonly isBrowser = isPlatformBrowser(this.platformId);
private readonly environment = inject(ENVIRONMENT);

readonly selectedProjectId = toSignal<string | null>(
this.route.params.pipe(map((params) => params['id'])) ?? of(null)
);

readonly AddToCollectionSteps = AddToCollectionSteps;

collectionMetadataForm = new FormGroup({});

isProviderLoading = select(CollectionsSelectors.getCollectionProviderLoading);
collectionProvider = select(CollectionsSelectors.getCollectionProvider);
requiredMetadataTemplate = select(CollectionsSelectors.getRequiredMetadataTemplate);
selectedProject = select(ProjectsSelectors.getSelectedProject);
currentUser = select(UserSelectors.getCurrentUser);
activeFlags = select(UserSelectors.getActiveFlags);
currentCollectionSubmission = select(AddToCollectionSelectors.getCurrentCollectionSubmission);
cedarRecords = select(MetadataSelectors.getCedarRecords);

Expand All @@ -125,9 +117,6 @@ export class AddToCollectionComponent implements CanDeactivateComponent {
isCollectionMetadataDisabled = computed(
() => !this.selectedProject() || !this.projectMetadataSaved() || !this.projectContributorsSaved()
);
isCedarMode = computed(
() => this.activeFlags().includes(COLLECTION_SUBMISSION_WITH_CEDAR) && !!this.requiredMetadataTemplate()
);
existingCedarRecord = computed<CedarMetadataRecordData | null>(() => {
const records = this.cedarRecords();
const templateId = this.requiredMetadataTemplate()?.id;
Expand All @@ -138,7 +127,6 @@ export class AddToCollectionComponent implements CanDeactivateComponent {
readonly actions = createDispatchMap({
getCollectionProvider: GetCollectionProvider,
clearAddToCollectionState: ClearAddToCollectionState,
updateCollectionSubmission: UpdateCollectionSubmission,
deleteCollectionSubmission: RemoveCollectionSubmission,
setSelectedProject: SetSelectedProject,
getCurrentCollectionSubmission: GetCurrentCollectionSubmission,
Expand Down Expand Up @@ -195,12 +183,6 @@ export class AddToCollectionComponent implements CanDeactivateComponent {
this.projectContributorsSaved.set(true);
}

handleCollectionMetadataSaved(form: FormGroup): void {
this.collectionMetadataForm = form;
this.collectionMetadataSaved.set(true);
this.stepperActiveValue.set(AddToCollectionSteps.Complete);
}

handleCedarDataSaved(data: CedarRecordDataBinding): void {
this.pendingCedarData.set(data);
this.collectionMetadataSaved.set(true);
Expand All @@ -212,17 +194,13 @@ export class AddToCollectionComponent implements CanDeactivateComponent {
collectionId: this.primaryCollectionId() || '',
projectId: this.selectedProject()?.id || '',
userId: this.currentUser()?.id || '',
collectionMetadata: this.isCedarMode() ? {} : this.collectionMetadataForm.value || {},
};

const isEditMode = this.isEditMode();

if (isEditMode) {
if (this.isEditMode()) {
this.loaderService.show();

this.saveCedarRecordIfNeeded()
.pipe(
switchMap(() => this.actions.updateCollectionSubmission(payload)),
finalize(() => this.loaderService.hide()),
takeUntilDestroyed(this.destroyRef)
)
Expand Down Expand Up @@ -298,8 +276,6 @@ export class AddToCollectionComponent implements CanDeactivateComponent {
}

private saveCedarRecordIfNeeded(): Observable<unknown> {
if (!this.isCedarMode()) return of(null);

const cedarData = this.pendingCedarData();
const projectId = this.selectedProject()?.id;
const templateId = this.requiredMetadataTemplate()?.id;
Expand Down Expand Up @@ -352,8 +328,7 @@ export class AddToCollectionComponent implements CanDeactivateComponent {

effect(() => {
const projectId = this.selectedProjectId();
const isCedar = this.isCedarMode();
if (isCedar && projectId) {
if (projectId) {
this.actions.getCedarRecords(projectId, ResourceType.Project);
}
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,27 +11,15 @@ <h3>{{ 'collections.addToCollection.collectionMetadata' | translate }}</h3>

@if (!isDisabled() && !isStepActive()) {
@if (collectionMetadataSaved()) {
@if (isCedarMode()) {
@let cedarTpl = cedarTemplate();
@let cedarTpl = cedarTemplate();

@if (cedarTpl) {
<cedar-artifact-viewer
#cedarViewer
[config]="cedarViewerConfig"
[templateObject]="cedarTpl.attributes.template"
[instanceObject]="cedarFormData()"
></cedar-artifact-viewer>
}
} @else {
@for (filterEntry of availableFilterEntries(); track filterEntry.key) {
<div>
<p class="font-bold">{{ filterEntry.labelKey | translate }}</p>

<p class="mt-2">
{{ collectionMetadataForm().get(filterEntry.key)?.value }}
</p>
</div>
}
@if (cedarTpl) {
<cedar-artifact-viewer
#cedarViewer
[config]="cedarViewerConfig"
[templateObject]="cedarTpl.attributes.template"
[instanceObject]="cedarFormData()"
></cedar-artifact-viewer>
}
}

Expand All @@ -48,62 +36,32 @@ <h3>{{ 'collections.addToCollection.collectionMetadata' | translate }}</h3>

<p-step-panel [value]="targetStepValue()" class="p-0">
<ng-template #content>
@if (isCedarMode()) {
@let cedarTpl = cedarTemplate();

@if (cedarTpl) {
@if (isStepActive()) {
<div class="cedar-editor-container mt-3">
<cedar-embeddable-editor
#cedarEditor
[config]="cedarConfig"
[templateObject]="cedarTpl.attributes.template"
[metadata]="cedarFormData()"
(change)="onCedarChange($event)"
(keyup)="onCedarChange($event)"
></cedar-embeddable-editor>
</div>
}
@let cedarTpl = cedarTemplate();

<div class="flex justify-content-end gap-3 mt-4">
<p-button
severity="info"
[label]="'common.buttons.discardChanges' | translate"
(onClick)="handleDiscardChanges()"
/>
<p-button [label]="'common.buttons.saveAndContinue' | translate" (onClick)="handleSaveCedarMetadata()" />
@if (cedarTpl) {
@if (isStepActive()) {
<div class="cedar-editor-container mt-3">
<cedar-embeddable-editor
#cedarEditor
[config]="cedarConfig"
[templateObject]="cedarTpl.attributes.template"
[metadata]="cedarFormData()"
(change)="onCedarChange($event)"
(keyup)="onCedarChange($event)"
></cedar-embeddable-editor>
</div>
} @else {
<p class="mt-3">{{ 'collections.addToCollection.cedarFormNotAvailable' | translate }}</p>
}
} @else {
<form [formGroup]="collectionMetadataForm()" class="grid row-gap-2 mt-3">
@for (filterEntry of availableFilterEntries(); track filterEntry.key) {
<div class="flex flex-column gap-1 col-12 md:col-6">
<label [for]="filterEntry.key">{{ filterEntry.labelKey | translate }}</label>
<p-select
[id]="filterEntry.key"
[options]="filterEntry.options"
[formControlName]="filterEntry.key"
[placeholder]="filterEntry.labelKey | translate"
appendTo="body"
></p-select>
</div>
}
</form>

<div class="flex justify-content-end gap-3 mt-4">
<p-button
severity="info"
[label]="'common.buttons.discardChanges' | translate"
(onClick)="handleDiscardChanges()"
/>
<p-button
[label]="'common.buttons.saveAndContinue' | translate"
[disabled]="!collectionMetadataForm().valid"
(onClick)="handleSaveMetadata()"
/>
<p-button [label]="'common.buttons.saveAndContinue' | translate" (onClick)="handleSaveCedarMetadata()" />
</div>
} @else {
<p class="mt-3">{{ 'collections.addToCollection.cedarFormNotAvailable' | translate }}</p>
}
</ng-template>
</p-step-panel>
Expand Down
Loading
Loading