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 @@ -2,15 +2,45 @@
<section class="h-full" data-test-new-registration-form>
<osf-sub-header [title]="'registries.new.addNewRegistry' | translate" />

<section class="flex flex-column lg:flex-row flex-1 p-5 gap-4 bg-white w-full">
<p>
{{ 'registries.new.registrySubmissionInfo' | translate }}
<a class="font-bold" href="https://help.osf.io/"> {{ 'common.links.clickHere' | translate }}</a>
{{ 'registries.new.hostedRegistriesLink' | translate }}
</p>
</section>
<section class="flex flex-column flex-1 gap-4 w-full bg-white p-3 md:p-4 lg:p-5">
<p-card class="w-full" data-test-registration-policy>
<div class="flex flex-column gap-3">
<h2>{{ 'registries.new.policy.intro' | translate }}</h2>
<p>{{ 'registries.new.policy.preregistration' | translate }}</p>

<div>
<p class="mb-2">{{ 'registries.new.policy.acceptableTitle' | translate }}</p>
<ul class="flex flex-column gap-1 pl-5">
<li class="list-disc">{{ 'registries.new.policy.acceptable.notBegun' | translate }}</li>
<li class="list-disc">{{ 'registries.new.policy.acceptable.underway' | translate }}</li>
<li class="list-disc">{{ 'registries.new.policy.acceptable.concluded' | translate }}</li>
</ul>
</div>

<div>
<p class="mb-2">{{ 'registries.new.policy.unacceptableTitle' | translate }}</p>
<ul class="flex flex-column gap-1 pl-5">
<li class="list-disc">{{ 'registries.new.policy.unacceptable.papers' | translate }}</li>
<li class="list-disc">{{ 'registries.new.policy.unacceptable.otherOutputs' | translate }}</li>
</ul>
</div>

<p>{{ 'registries.new.policy.alternative' | translate }}</p>
</div>

<div class="flex align-items-center gap-2 mt-4">
<p-checkbox
data-test-policy-acknowledgment
[(ngModel)]="policyAcknowledged"
binary="true"
inputId="policy-acknowledgment"
/>
<label for="policy-acknowledgment" class="font-bold m-0 cursor-pointer">
{{ 'registries.new.policy.checkbox' | translate }}
</label>
</div>
</p-card>

<section class="flex flex-column flex-1 p-5 gap-4 w-full bg-white">
@if (!isProjectReadOnly()) {
<p-card class="w-full">
<h2 class="mb-4">{{ 'registries.new.steps.title' | translate }} 1</h2>
Expand Down Expand Up @@ -80,9 +110,12 @@ <h2 class="mb-4">{{ 'registries.new.steps.title' | translate }} {{ fromProject()
<div class="flex justify-content-end">
<p-button
data-test-start-registration-button
[label]="'registries.new.createDraft' | translate"
[disabled]="draftForm.invalid"
type="submit"
[pTooltip]="'registries.new.policy.createDraftTooltip' | translate"
[tooltipDisabled]="policyAcknowledged()"
tooltipPosition="top"
[label]="'registries.new.createDraft' | translate"
[disabled]="isCreateDraftDisabled()"
[loading]="isDraftSubmitting()"
/>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -159,14 +159,16 @@ describe('NewRegistrationComponent', () => {
expect(component.draftForm.get('project')?.validator).toBeNull();
});

it('should dispatch createDraft and navigate when form is valid', () => {
it('should dispatch createDraft and navigate when form is valid and policy is acknowledged', () => {
setup();
component.draftForm.patchValue({ providerSchema: 'schema-1', project: 'proj-1' });
component.fromProject.set(true);
component.policyAcknowledged.set(true);
(store.dispatch as Mock).mockClear();

component.createDraft();

expect(component.isCreateDraftDisabled()).toBe(false);
expect(store.dispatch).toHaveBeenCalledWith(
new CreateDraft({ registrationSchemaId: 'schema-1', provider: 'prov-1', projectId: 'proj-1' })
);
Expand All @@ -176,10 +178,25 @@ describe('NewRegistrationComponent', () => {
it('should not dispatch createDraft when form is invalid', () => {
setup();
component.draftForm.patchValue({ providerSchema: '' });
component.policyAcknowledged.set(true);
(store.dispatch as Mock).mockClear();

component.createDraft();

expect(component.isCreateDraftDisabled()).toBe(true);
expect(store.dispatch).not.toHaveBeenCalledWith(expect.any(CreateDraft));
});

it('should not dispatch createDraft when policy is not acknowledged', () => {
setup();
component.draftForm.patchValue({ providerSchema: 'schema-1', project: 'proj-1' });
component.fromProject.set(true);
component.policyAcknowledged.set(false);
(store.dispatch as Mock).mockClear();

component.createDraft();

expect(component.isCreateDraftDisabled()).toBe(true);
expect(store.dispatch).not.toHaveBeenCalledWith(expect.any(CreateDraft));
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@ import { TranslatePipe } from '@ngx-translate/core';

import { Button } from 'primeng/button';
import { Card } from 'primeng/card';
import { Checkbox } from 'primeng/checkbox';
import { Select } from 'primeng/select';
import { Tooltip } from 'primeng/tooltip';

import { debounceTime, distinctUntilChanged, filter, Subject, take } from 'rxjs';
import { debounceTime, distinctUntilChanged, filter, map, Subject, take } from 'rxjs';

import { ChangeDetectionStrategy, Component, computed, DestroyRef, effect, inject, signal } from '@angular/core';
import { takeUntilDestroyed, toObservable } from '@angular/core/rxjs-interop';
import { FormBuilder, ReactiveFormsModule, Validators } from '@angular/forms';
import { takeUntilDestroyed, toObservable, toSignal } from '@angular/core/rxjs-interop';
import { FormBuilder, FormsModule, ReactiveFormsModule, Validators } from '@angular/forms';
import { ActivatedRoute, Router } from '@angular/router';

import { UserSelectors } from '@core/store/user';
Expand All @@ -23,7 +25,18 @@ import { CreateDraft, GetProjects, GetProviderSchemas, RegistriesSelectors } fro

@Component({
selector: 'osf-new-registration',
imports: [Button, Card, Select, ReactiveFormsModule, LoadingSpinnerComponent, SubHeaderComponent, TranslatePipe],
imports: [
Button,
Card,
Checkbox,
Select,
Tooltip,
FormsModule,
ReactiveFormsModule,
LoadingSpinnerComponent,
SubHeaderComponent,
TranslatePipe,
],
templateUrl: './new-registration.component.html',
styleUrl: './new-registration.component.scss',
changeDetection: ChangeDetectionStrategy.OnPush,
Expand Down Expand Up @@ -58,11 +71,17 @@ export class NewRegistrationComponent {
private readonly filter$ = new Subject<string>();

readonly fromProject = signal(this.projectId !== undefined);
readonly policyAcknowledged = signal(false);
readonly draftForm = this.fb.group({
providerSchema: ['', Validators.required],
project: [this.projectId || ''],
});

readonly isFormValid = toSignal(this.draftForm.statusChanges.pipe(map(() => this.draftForm.valid)), {
initialValue: this.draftForm.valid,
});
readonly isCreateDraftDisabled = computed(() => !this.isFormValid() || !this.policyAcknowledged());

constructor() {
this.loadInitialData();
this.setupDefaultSchema();
Expand All @@ -82,7 +101,7 @@ export class NewRegistrationComponent {
}

createDraft() {
if (this.draftForm.invalid) {
if (this.isCreateDraftDisabled()) {
return;
}

Expand Down
20 changes: 18 additions & 2 deletions src/assets/i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -2188,9 +2188,25 @@
"addNewRegistry": "Add New Registration",
"createDraft": "Create draft",
"createdSuccessfully": "Draft created successfully",
"hostedRegistriesLink": "Learn more about other hosted registries.",
"policy": {
"acceptable": {
"concluded": "Plans for research that has concluded, with disclosure that they are submitted retrospectively",
"notBegun": "Plans for research that has not yet begun",
"underway": "Plans for research that is underway, with explanation of the current state of the study"
},
"acceptableTitle": "Acceptable submissions to the registries on OSF include:",
"alternative": "Seek alternative paper sharing services and repositories for these uses.",
"checkbox": "I understand and confirm that I am submitting a research plan, and I am not submitting a paper, preprint, or other research output that is not associated with a research plan.",
"createDraftTooltip": "Read the information above. Click the checkbox if you understand and acknowledge that you are submitting a research plan.",
"intro": "Registration on OSF is for submitting research plans.",
"preregistration": "Ideally, registrations are submitted prior to observing the outcomes of the research, and include a description of what the research is, how it will be done, and how it will be analyzed. These are preregistrations.",
"unacceptable": {
"otherOutputs": "Any other research outputs (e.g., data) that are not a part of the research plan",
"papers": "Papers or preprints, including those reporting research outcomes, commentaries, proofs, or other theoretical pieces"
},
"unacceptableTitle": "Unacceptable submissions to the registries on OSF include:"
},
"registryClosedForSubmissions": "This registry is closed for new submissions. Please start a new registration with a different registry.",
"registrySubmissionInfo": "You are submitting to OSF Registries.",
"selectProject": "Select your project",
"steps": {
"existingProjectQuestion": "Do you have content for registration in an existing OSF project?",
Expand Down
Loading