Skip to content
Merged
64 changes: 33 additions & 31 deletions src/app/features/preprints/constants/submit-preprint-steps.const.ts
Original file line number Diff line number Diff line change
@@ -1,33 +1,35 @@
import { SubmitSteps } from '@osf/features/preprints/enums';
import { CustomOption } from '@shared/models';
import { StepOption } from '@shared/models';

export const submitPreprintSteps: CustomOption<SubmitSteps>[] = Object.entries(SubmitSteps)
.filter(([, value]) => typeof value === 'number')
.map(([, value]) => {
let label = '';
switch (value) {
case SubmitSteps.TitleAndAbstract:
label = 'Title and Abstract';
break;
case SubmitSteps.File:
label = 'File';
break;
case SubmitSteps.Metadata:
label = 'Metadata';
break;
case SubmitSteps.AuthorAssertions:
label = 'Author Assertions';
break;
case SubmitSteps.Supplements:
label = 'Supplements';
break;
case SubmitSteps.Review:
label = 'Review';
break;
}

return {
label,
value: value as SubmitSteps,
};
});
export const submitPreprintSteps: StepOption[] = [
{
index: SubmitSteps.TitleAndAbstract,
label: 'Title and Abstract',
value: SubmitSteps.TitleAndAbstract,
},
{
index: SubmitSteps.File,
label: 'File',
value: SubmitSteps.File,
},
{
index: SubmitSteps.Metadata,
label: 'Metadata',
value: SubmitSteps.Metadata,
},
{
index: SubmitSteps.AuthorAssertions,
label: 'Author Assertions',
value: SubmitSteps.AuthorAssertions,
},
{
index: SubmitSteps.Supplements,
label: 'Supplements',
value: SubmitSteps.Supplements,
},
{
index: SubmitSteps.Review,
label: 'Review',
value: SubmitSteps.Review,
},
];
Original file line number Diff line number Diff line change
Expand Up @@ -29,21 +29,21 @@ <h1 class="preprint-provider-name">{{ 'Add a ' + preprintProvider()!.preprintWor
</section>

<section class="flex-1 bg-white px-3 py-4 md:py-4 md:px-4">
@switch (currentStep()) {
@switch (currentStep().value) {
@case (SubmitStepsEnum.TitleAndAbstract) {
<osf-title-and-abstract-step (nextClicked)="currentStep.set(SubmitStepsEnum.File)" />
<osf-title-and-abstract-step (nextClicked)="currentStep.set(submitPreprintSteps[SubmitStepsEnum.File])" />
}
@case (SubmitStepsEnum.File) {
<osf-file-step
(nextClicked)="currentStep.set(SubmitStepsEnum.Metadata)"
(backClicked)="currentStep.set(SubmitStepsEnum.TitleAndAbstract)"
(nextClicked)="currentStep.set(submitPreprintSteps[SubmitStepsEnum.Metadata])"
(backClicked)="currentStep.set(submitPreprintSteps[SubmitStepsEnum.TitleAndAbstract])"
/>
}
@case (SubmitStepsEnum.Metadata) {
<osf-preprint-metadata (nextClicked)="currentStep.set(SubmitStepsEnum.AuthorAssertions)" />
<osf-preprint-metadata (nextClicked)="currentStep.set(submitPreprintSteps[SubmitStepsEnum.AuthorAssertions])" />
}
@case (SubmitStepsEnum.AuthorAssertions) {
<osf-author-assertions-step (nextClicked)="currentStep.set(SubmitStepsEnum.Supplements)" />
<osf-author-assertions-step (nextClicked)="currentStep.set(submitPreprintSteps[SubmitStepsEnum.Supplements])" />
}
@default {
<p>No such step</p>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import {
ResetStateAndDeletePreprint,
SetSelectedPreprintProviderId,
} from '@osf/features/preprints/store/submit-preprint';
import { StepOption } from '@osf/shared/models';
import { StepperComponent } from '@shared/components';
import { BrandService } from '@shared/services';
import { BrowserTabHelper, HeaderStyleHelper, IS_WEB } from '@shared/utils';
Expand Down Expand Up @@ -66,7 +67,7 @@ export class SubmitPreprintStepperComponent implements OnInit, OnDestroy {

preprintProvider = select(PreprintProvidersSelectors.getPreprintProviderDetails(this.providerId()));
isPreprintProviderLoading = select(PreprintProvidersSelectors.isPreprintProviderDetailsLoading);
currentStep = signal<number>(0);
currentStep = signal<StepOption>(submitPreprintSteps[0]);
isWeb = toSignal(inject(IS_WEB));

constructor() {
Expand Down Expand Up @@ -97,8 +98,9 @@ export class SubmitPreprintStepperComponent implements OnInit, OnDestroy {
this.actions.resetStateAndDeletePreprint();
}

stepChange(step: number) {
if (step >= this.currentStep()) {
stepChange(step: StepOption): void {
const currentStepIndex = this.currentStep()?.index ?? 0;
if (step.index >= currentStepIndex) {
return;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ import { RegistriesSelectors } from '../../store';
})
export class CustomStepComponent {
private readonly route = inject(ActivatedRoute);
step = signal(this.route.snapshot.params['step'].split('-')[0]);
step = signal(this.route.snapshot.params['step']);
protected readonly pages = select(RegistriesSelectors.getPagesSchema);
currentPage = computed(() => this.pages()[this.step() - 1]);
protected readonly FieldType = FieldType;
Expand All @@ -50,7 +50,7 @@ export class CustomStepComponent {

constructor() {
this.route.params.pipe(takeUntilDestroyed()).subscribe((params) => {
this.step.set(+params['step'].split('-')[0]);
this.step.set(+params['step']);
});
}
}
78 changes: 53 additions & 25 deletions src/app/features/registries/components/drafts/drafts.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@ import { createDispatchMap, select } from '@ngxs/store';

import { TranslatePipe, TranslateService } from '@ngx-translate/core';

import { tap } from 'rxjs';
import { filter, tap } from 'rxjs';

import { ChangeDetectionStrategy, Component, computed, effect, inject, Signal, signal } from '@angular/core';
import { ActivatedRoute, Router, RouterOutlet } from '@angular/router';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { ActivatedRoute, NavigationEnd, Router, RouterOutlet } from '@angular/router';

import { StepperComponent, SubHeaderComponent } from '@osf/shared/components';
import { StepOption } from '@osf/shared/models';
Expand All @@ -30,6 +31,7 @@ export class DraftsComponent {

protected readonly pages = select(RegistriesSelectors.getPagesSchema);
protected readonly draftRegistration = select(RegistriesSelectors.getDraftRegistration);
protected stepsValidation = select(RegistriesSelectors.getStepsValidation);

private readonly actions = createDispatchMap({
getSchemaBlocks: FetchSchemaBlocks,
Expand All @@ -40,26 +42,59 @@ export class DraftsComponent {
return this.router.url.includes('/review');
}

defaultSteps: StepOption[] = defaultSteps.map((step) => ({
...step,
label: this.translateService.instant(step.label),
}));
defaultSteps: StepOption[] = [];

steps: Signal<StepOption[]> = computed(() => {
const customSteps = this.pages().map((page) => ({
label: page.title,
value: page.id,
this.defaultSteps = defaultSteps.map((step) => ({
...step,
label: this.translateService.instant(step.label),
invalid: this.stepsValidation()?.[step.index]?.invalid || false,
}));
return [this.defaultSteps[0], ...customSteps, this.defaultSteps[1]];

const customSteps = this.pages().map((page, index) => {
return {
index: index + 1,
label: page.title,
value: page.id,
routeLink: `${index + 1}`,
invalid: this.stepsValidation()?.[index + 1]?.invalid || false,
};
});
return [
this.defaultSteps[0],
...customSteps,
{ ...this.defaultSteps[1], index: customSteps.length + 1, invalid: false },
];
});

currentStep = signal(
this.route.snapshot.children[0]?.params['step'] ? +this.route.snapshot.children[0]?.params['step'].split('-')[0] : 0
currentStepIndex = signal(
this.route.snapshot.firstChild?.params['step'] ? +this.route.snapshot.firstChild?.params['step'] : 0
);

registrationId = this.route.snapshot.children[0]?.params['id'] || '';
currentStep = computed(() => {
return this.steps()[this.currentStepIndex()];
});

registrationId = this.route.snapshot.firstChild?.params['id'] || '';

constructor() {
this.router.events
.pipe(
takeUntilDestroyed(),
filter((event): event is NavigationEnd => event instanceof NavigationEnd)
)
.subscribe(() => {
const step = this.route.firstChild?.snapshot.params['step'];
if (step) {
this.currentStepIndex.set(+step);
} else if (this.isReviewPage) {
const reviewStepIndex = this.pages().length + 1;
this.currentStepIndex.set(reviewStepIndex);
} else {
this.currentStepIndex.set(0);
}
});

this.loaderService.show();
if (!this.draftRegistration()) {
this.actions.getDraftRegistration(this.registrationId);
Expand All @@ -79,24 +114,17 @@ export class DraftsComponent {
});

effect(() => {
const reviewStepNumber = this.pages().length + 1;
const reviewStepIndex = this.pages().length + 1;
if (this.isReviewPage) {
this.currentStep.set(reviewStepNumber);
this.currentStepIndex.set(reviewStepIndex);
}
});
}

stepChange(step: number): void {
stepChange(step: StepOption): void {
// [NM] TODO: before navigating, validate the current step
this.currentStep.set(step);
const pageStep = this.steps()[step];

let pageLink = '';
if (!pageStep.value) {
pageLink = `${pageStep.routeLink}`;
} else {
pageLink = `${step}-${pageStep.value}`;
}
this.currentStepIndex.set(step.index);
const pageLink = this.steps()[step.index].routeLink;
this.router.navigate([`/registries/drafts/${this.registrationId}/`, pageLink]);
}
}
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
<section class="flex flex-column bg-white flex-1 h-full p-5 gap-4 w-full">
<section>
<h2 class="mb-2">{{ 'registries.metadata.title' | translate }}</h2>
<p class="mb-4">{{ 'registries.metadata.description' | translate }}</p>
<p-card class="w-full">
<form [formGroup]="metadataForm" (ngSubmit)="submitMetadata()" class="flex flex-column gap-4">
<form [formGroup]="metadataForm" (ngSubmit)="submitMetadata()" class="flex flex-column gap-4">
<section>
<h2 class="mb-2">{{ 'registries.metadata.title' | translate }}</h2>
<p class="mb-4">{{ 'registries.metadata.description' | translate }}</p>
<p-card class="w-full">
<osf-text-input
label="common.labels.title"
[control]="metadataForm.controls['title']"
[maxLength]="inputLimits.fullName.maxLength"
>
</osf-text-input>
<div>
<div class="mt-2">
<label for="project-description-id">{{ 'common.labels.description' | translate }}</label>
<textarea
id="project-description-id"
Expand All @@ -20,18 +20,26 @@ <h2 class="mb-2">{{ 'registries.metadata.title' | translate }}</h2>
cols="30"
pTextarea
></textarea>
@if (
metadataForm.controls['description'].errors?.['required'] &&
(metadataForm.controls['description'].touched || metadataForm.controls['description'].dirty)
) {
<p-message class="simple-variant flex mt-1" severity="error" variant="simple" size="small">
{{ INPUT_VALIDATION_MESSAGES.required | translate }}
</p-message>
}
</div>
<div class="flex justify-content-end"></div>
</form>
</p-card>
</section>
<osf-contributors></osf-contributors>
<osf-registries-license></osf-registries-license>
<osf-registries-subjects></osf-registries-subjects>
<osf-registries-tags></osf-registries-tags>
<div class="flex justify-content-end">
<p-button [label]="'registries.deleteDraft' | translate" severity="danger" (click)="deleteDraft()" class="mr-2">
</p-button>
<p-button [label]="'common.buttons.next' | translate" type="submit" [disabled]="metadataForm.invalid"></p-button>
</div>
</p-card>
</section>
<osf-contributors></osf-contributors>
<osf-registries-license [control]="metadataForm.controls['license']"></osf-registries-license>
<osf-registries-subjects [control]="metadataForm.controls['subjects']"></osf-registries-subjects>
<osf-registries-tags></osf-registries-tags>
<div class="flex justify-content-end">
<p-button [label]="'registries.deleteDraft' | translate" severity="danger" (click)="deleteDraft()" class="mr-2">
</p-button>
<p-button [label]="'common.buttons.next' | translate" type="submit"></p-button>
</div>
</form>
</section>
Loading