From 2f2b23d506283e839729aee73511c0d4017c2a4a Mon Sep 17 00:00:00 2001 From: nsemets Date: Thu, 1 Oct 2026 16:22:36 +0300 Subject: [PATCH 1/2] fix(new-registration): added policy text and checkbox --- .../new-registration.component.html | 53 +++++++++++++++---- .../new-registration.component.spec.ts | 19 ++++++- .../new-registration.component.ts | 29 ++++++++-- src/assets/i18n/en.json | 20 ++++++- 4 files changed, 103 insertions(+), 18 deletions(-) diff --git a/src/app/features/registries/components/new-registration/new-registration.component.html b/src/app/features/registries/components/new-registration/new-registration.component.html index b6bbed2da..25a9aab44 100644 --- a/src/app/features/registries/components/new-registration/new-registration.component.html +++ b/src/app/features/registries/components/new-registration/new-registration.component.html @@ -2,15 +2,45 @@
-
-

- {{ 'registries.new.registrySubmissionInfo' | translate }} - {{ 'common.links.clickHere' | translate }} - {{ 'registries.new.hostedRegistriesLink' | translate }} -

-
+
+ +
+

{{ 'registries.new.policy.intro' | translate }}

+

{{ 'registries.new.policy.preregistration' | translate }}

+ +
+

{{ 'registries.new.policy.acceptableTitle' | translate }}

+
    +
  • {{ 'registries.new.policy.acceptable.notBegun' | translate }}
  • +
  • {{ 'registries.new.policy.acceptable.underway' | translate }}
  • +
  • {{ 'registries.new.policy.acceptable.concluded' | translate }}
  • +
+
+ +
+

{{ 'registries.new.policy.unacceptableTitle' | translate }}

+
    +
  • {{ 'registries.new.policy.unacceptable.papers' | translate }}
  • +
  • {{ 'registries.new.policy.unacceptable.otherOutputs' | translate }}
  • +
+
+ +

{{ 'registries.new.policy.alternative' | translate }}

+
+ +
+ + +
+
-
@if (!isProjectReadOnly()) {

{{ 'registries.new.steps.title' | translate }} 1

@@ -80,9 +110,12 @@

{{ 'registries.new.steps.title' | translate }} {{ fromProject()
diff --git a/src/app/features/registries/components/new-registration/new-registration.component.spec.ts b/src/app/features/registries/components/new-registration/new-registration.component.spec.ts index eb0d3cc64..a6a5b5e3d 100644 --- a/src/app/features/registries/components/new-registration/new-registration.component.spec.ts +++ b/src/app/features/registries/components/new-registration/new-registration.component.spec.ts @@ -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' }) ); @@ -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)); }); diff --git a/src/app/features/registries/components/new-registration/new-registration.component.ts b/src/app/features/registries/components/new-registration/new-registration.component.ts index 95cdc1ae6..6b1d8e66c 100644 --- a/src/app/features/registries/components/new-registration/new-registration.component.ts +++ b/src/app/features/registries/components/new-registration/new-registration.component.ts @@ -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'; @@ -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, @@ -58,11 +71,17 @@ export class NewRegistrationComponent { private readonly filter$ = new Subject(); 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(); @@ -82,7 +101,7 @@ export class NewRegistrationComponent { } createDraft() { - if (this.draftForm.invalid) { + if (this.isCreateDraftDisabled()) { return; } diff --git a/src/assets/i18n/en.json b/src/assets/i18n/en.json index a0688e3ae..27f5b1ddd 100644 --- a/src/assets/i18n/en.json +++ b/src/assets/i18n/en.json @@ -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 OSF Registry 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 OSF Registry 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?", From 2c087d9d6521a75f25364bdffe2bc385f27f3908 Mon Sep 17 00:00:00 2001 From: nsemets Date: Thu, 1 Oct 2026 17:23:33 +0300 Subject: [PATCH 2/2] fix(registry): updated translations --- src/assets/i18n/en.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/assets/i18n/en.json b/src/assets/i18n/en.json index 27f5b1ddd..113afb819 100644 --- a/src/assets/i18n/en.json +++ b/src/assets/i18n/en.json @@ -2194,7 +2194,7 @@ "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 OSF Registry include:", + "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.", @@ -2204,7 +2204,7 @@ "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 OSF Registry include:" + "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.", "selectProject": "Select your project",