Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
18d44e7
refactor(preprints-state): Renamed Preprints -> PreprintProviders
rrromchIk Jul 3, 2025
31bc13f
Merge branch 'main' into feat/submit-preprint
rrromchIk Jul 3, 2025
187896c
refactor(preprints-services): Renamed services to have 'preprints' pr…
rrromchIk Jul 3, 2025
0665024
fix(json-api-post): Fixed errors during to merge conflict
rrromchIk Jul 3, 2025
13e082d
refactor(preprints-state): Renamed Preprints -> PreprintProviders
rrromchIk Jul 3, 2025
a55bd93
refactor(preprints-models): Decomposed, used shared models. Moved som…
rrromchIk Jul 3, 2025
cf8cd63
refactor(router): Moved preprint routes to root folder of feature
rrromchIk Jul 3, 2025
c27d8da
refactor(preprints-components): Rename and reorganize component files…
rrromchIk Jul 3, 2025
f6bfb32
fix(preprints-models): Removed unused model
rrromchIk Jul 3, 2025
189d6cb
refactor(license): Made license more reusable by removing card wrapper
rrromchIk Jul 3, 2025
fe5e33e
refactor(metadata-license): Removed redundant wrapper
rrromchIk Jul 3, 2025
04d15f2
fix(comments): Fixed comments
rrromchIk Jul 3, 2025
ec9c9fb
feat(author-assertions): Partly implemented step with missing availab…
rrromchIk Jul 3, 2025
14051fe
refactor(validators): Moved linkValidator from helper function to sha…
rrromchIk Jul 3, 2025
ddd89b2
feat(array-input): Implemented reusable component for array input
rrromchIk Jul 3, 2025
d547779
feat(array-input): Used array-input for data links and prereg links
rrromchIk Jul 3, 2025
97e73e9
Merge branch 'main' into feat/submit-preprint
rrromchIk Jul 3, 2025
1ad7a34
Merge branch 'main' into feat/submit-preprint
rrromchIk Jul 4, 2025
83a6b8e
refactor(author-assertions): Refactored step. Fixed minor issues
rrromchIk Jul 4, 2025
26e4f44
fix(translations): Update URL validation message for clarity
rrromchIk Jul 4, 2025
3959764
fix(comments): Fixed comments
rrromchIk Jul 4, 2025
011a608
refactor(subjects): Refactored shared subjects component and service
rrromchIk Jul 4, 2025
4732431
feat(metadata-subjects): Implemented Subjects section on metadata step
rrromchIk Jul 4, 2025
ad6ce17
Merge branch 'main' into feat/submit-preprint
rrromchIk Jul 4, 2025
970d9b8
fix(discover-state): Removed selectSnapshot that selects data within …
rrromchIk Jul 4, 2025
6f3d20f
feat(regions): Introduced shared state for fetching regions
rrromchIk Jul 7, 2025
91bc446
feat(supplements): Implemented template for 'Choose existing' option
rrromchIk Jul 7, 2025
7864e8f
refactor(add-project-form): Refactored form component to be more reus…
rrromchIk Jul 7, 2025
05f7f65
refactor(node-models): Reorganized shared node models
rrromchIk Jul 7, 2025
2083379
feat(supplements-step): Implemented connecting project step
rrromchIk Jul 7, 2025
01a604a
Merge branch 'refs/heads/main' into feat/submit-preprint
rrromchIk Jul 7, 2025
deae84c
fix(conflict): Fixed things after merge conflict
rrromchIk Jul 7, 2025
39c0b45
fix(conflict): Fixed things after merge conflict
rrromchIk Jul 7, 2025
dc24f68
fix(registries-subjects): Use constant for OSF provider ID in fetchSu…
rrromchIk Jul 8, 2025
b5ea752
Merge branch 'main' into feat/submit-preprint
rrromchIk Jul 8, 2025
587f639
fix(submit-preprint): Fixes after merge conflict
rrromchIk Jul 8, 2025
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
2 changes: 2 additions & 0 deletions src/app/core/constants/ngxs-states.constant.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { NotificationSubscriptionState } from '@osf/features/settings/notificati
import { ProfileSettingsState } from '@osf/features/settings/profile-settings/store/profile-settings.state';
import { AddonsState, InstitutionsState } from '@shared/stores';
import { LicensesState } from '@shared/stores/licenses';
import { RegionsState } from '@shared/stores/regions';

export const STATES = [
AuthState,
Expand All @@ -31,4 +32,5 @@ export const STATES = [
RegistrationsState,
ProjectMetadataState,
LicensesState,
RegionsState,
];
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<osf-add-project-form [templates]="templates()" [projectForm]="projectForm" />
<div class="flex justify-content-end gap-2 mt-4">
<p-button
class="w-12rem btn-full-width"
[label]="'myProjects.createProject.actions.cancel' | translate"
severity="info"
(click)="dialogRef.close()"
[disabled]="isProjectSubmitting()"
/>
<p-button
class="w-12rem btn-full-width"
[label]="'myProjects.createProject.actions.create' | translate"
[disabled]="!projectForm.valid || isProjectSubmitting()"
[loading]="isProjectSubmitting()"
(click)="submitForm()"
/>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';

import { CreateProjectDialogComponent } from './create-project-dialog.component';

describe('CreateProjectDialogComponent', () => {
let component: CreateProjectDialogComponent;
let fixture: ComponentFixture<CreateProjectDialogComponent>;

beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [CreateProjectDialogComponent],
}).compileComponents();

fixture = TestBed.createComponent(CreateProjectDialogComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import { createDispatchMap, select } from '@ngxs/store';

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

import { Button } from 'primeng/button';
import { DynamicDialogRef } from 'primeng/dynamicdialog';

import { ChangeDetectionStrategy, Component, computed, inject, OnInit } from '@angular/core';
import { FormControl, FormGroup, Validators } from '@angular/forms';

import { MY_PROJECTS_TABLE_PARAMS } from '@core/constants';
import { CreateProject, GetMyProjects, MyProjectsSelectors } from '@osf/features/my-projects/store';
import { AddProjectFormComponent } from '@shared/components';
import { ProjectFormControls } from '@shared/enums';
import { IdName, ProjectForm } from '@shared/models';
import { CustomValidators } from '@shared/utils';

@Component({
selector: 'osf-create-project-dialog',
imports: [AddProjectFormComponent, Button, TranslatePipe],
templateUrl: './create-project-dialog.component.html',
styleUrl: './create-project-dialog.component.scss',
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class CreateProjectDialogComponent implements OnInit {
protected readonly dialogRef = inject(DynamicDialogRef);

private actions = createDispatchMap({
getMyProjects: GetMyProjects,
createProject: CreateProject,
});

private projects = select(MyProjectsSelectors.getProjects);

readonly templates = computed(() => {
return this.projects().map(
(project) =>
({
id: project.id,
name: project.title,
}) as IdName
);
});
readonly isProjectSubmitting = select(MyProjectsSelectors.isProjectSubmitting);

readonly projectForm = new FormGroup<ProjectForm>({
[ProjectFormControls.Title]: new FormControl('', {
nonNullable: true,
validators: [CustomValidators.requiredTrimmed()],
}),
[ProjectFormControls.StorageLocation]: new FormControl('', {
nonNullable: true,
validators: [Validators.required],
}),
[ProjectFormControls.Affiliations]: new FormControl<string[]>([], {
nonNullable: true,
}),
[ProjectFormControls.Description]: new FormControl('', {
nonNullable: true,
}),
[ProjectFormControls.Template]: new FormControl('', {
nonNullable: true,
}),
});

ngOnInit(): void {
this.actions.getMyProjects(1, MY_PROJECTS_TABLE_PARAMS.rows, {});
}

submitForm(): void {
if (this.projectForm.invalid) {
this.projectForm.markAllAsTouched();
return;
}

const formValue = this.projectForm.getRawValue();

this.actions
.createProject(
formValue.title,
formValue.description,
formValue.template,
formValue.storageLocation,
formValue.affiliations
)
.subscribe({
next: () => {
this.actions.getMyProjects(1, MY_PROJECTS_TABLE_PARAMS.rows, {});
this.dialogRef.close();
},
});
}
}
1 change: 1 addition & 0 deletions src/app/features/my-projects/components/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { CreateProjectDialogComponent } from './create-project-dialog/create-project-dialog.component';
25 changes: 0 additions & 25 deletions src/app/features/my-projects/models/create-project.model.ts

This file was deleted.

1 change: 0 additions & 1 deletion src/app/features/my-projects/models/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
export * from './create-project.model';
export * from './my-projects.models';
export * from './my-projects-endpoint.type';
export * from './my-projects-search-filters.models';
Expand Down
11 changes: 4 additions & 7 deletions src/app/features/my-projects/my-projects.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,12 @@ import { ActivatedRoute, Router } from '@angular/router';

import { MY_PROJECTS_TABLE_PARAMS } from '@osf/core/constants';
import { parseQueryFilterParams } from '@osf/core/helpers';
import { AddProjectFormComponent, MyProjectsTableComponent, SubHeaderComponent } from '@osf/shared/components';
import { CreateProjectDialogComponent } from '@osf/features/my-projects/components';
import { MyProjectsTableComponent, SubHeaderComponent } from '@osf/shared/components';
import { ResourceType, SortOrder } from '@osf/shared/enums';
import { QueryParams, TableParameters, TabOption } from '@osf/shared/models';
import { IS_MEDIUM, IS_WEB, IS_XSMALL } from '@osf/shared/utils';
import { IS_XSMALL } from '@osf/shared/utils';

import { FetchUserInstitutions } from '../../shared/stores/institutions';
import { CollectionsSelectors, GetBookmarksCollectionId } from '../collections/store';

import { MyProjectsItem, MyProjectsSearchFilters } from './models';
Expand Down Expand Up @@ -73,8 +73,6 @@ export class MyProjectsComponent implements OnInit {

protected readonly defaultTabValue = 0;
protected readonly isLoading = signal(false);
protected readonly isDesktop = toSignal(inject(IS_WEB));
protected readonly isTablet = toSignal(inject(IS_MEDIUM));
protected readonly isMobile = toSignal(inject(IS_XSMALL));
protected readonly tabOptions: TabOption[] = [
{
Expand Down Expand Up @@ -128,7 +126,6 @@ export class MyProjectsComponent implements OnInit {
}

ngOnInit(): void {
this.#store.dispatch(new FetchUserInstitutions());
this.#store.dispatch(new GetBookmarksCollectionId());
}

Expand Down Expand Up @@ -339,7 +336,7 @@ export class MyProjectsComponent implements OnInit {
protected createProject(): void {
const dialogWidth = this.isMobile() ? '95vw' : '850px';

this.#dialogService.open(AddProjectFormComponent, {
this.#dialogService.open(CreateProjectDialogComponent, {
width: dialogWidth,
focusOnShow: false,
header: this.#translateService.instant('myProjects.header.createProject'),
Expand Down
3 changes: 1 addition & 2 deletions src/app/features/my-projects/services/my-projects.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,10 @@ import { JsonApiResponse } from '@core/models';
import { JsonApiService } from '@osf/core/services';
import { SparseCollectionsResponseJsonApi } from '@osf/features/collections/models';
import { ResourceType, SortOrder } from '@osf/shared/enums';
import { NodeResponseModel, UpdateNodeRequestModel } from '@shared/models';
import { CreateProjectPayloadJsoApi, NodeResponseModel, UpdateNodeRequestModel } from '@shared/models';

import { MyProjectsMapper } from '../mappers';
import {
CreateProjectPayloadJsoApi,
EndpointType,
MyProjectsItem,
MyProjectsItemGetResponseJsonApi,
Expand Down
5 changes: 5 additions & 0 deletions src/app/features/my-projects/store/my-projects.selectors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ export class MyProjectsSelectors {
return state.projects.data;
}

@Selector([MyProjectsState])
static isProjectSubmitting(state: MyProjectsStateModel): boolean {
return state.projects.isSubmitting || false;
}

@Selector([MyProjectsState])
static getRegistrations(state: MyProjectsStateModel): MyProjectsItem[] {
return state.registrations.data;
Expand Down
3 changes: 2 additions & 1 deletion src/app/features/my-projects/store/my-projects.state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ export class MyProjectsState {
ctx.patchState({
projects: {
...state.projects,
isLoading: true,
isSubmitting: true,
},
});

Expand All @@ -246,6 +246,7 @@ export class MyProjectsState {
projects: {
data: [project, ...state.projects.data],
isLoading: false,
isSubmitting: false,
error: null,
},
totalProjects: state.totalProjects + 1,
Expand Down
2 changes: 2 additions & 0 deletions src/app/features/preprints/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ export { PreprintProviderFooterComponent } from './preprint-provider-footer/prep
export { PreprintProviderHeroComponent } from './preprint-provider-hero/preprint-provider-hero.component';
export { PreprintServicesComponent } from './preprint-services/preprint-services.component';
export { PreprintsHelpDialogComponent } from './preprints-help-dialog/preprints-help-dialog.component';
export { AuthorAssertionsStepComponent } from './stepper/author-assertion-step/author-assertions-step.component';
export { SupplementsStepComponent } from './stepper/supplements-step/supplements-step.component';
export { PreprintsFilterChipsComponent } from '@osf/features/preprints/components/filters/preprints-filter-chips/preprints-filter-chips.component';
export { PreprintsResourcesComponent } from '@osf/features/preprints/components/filters/preprints-resources/preprints-resources.component';
export { PreprintsResourcesFiltersComponent } from '@osf/features/preprints/components/filters/preprints-resources-filters/preprints-resources-filters.component';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ <h2>Publication DOI</h2>
</div>
</p-card>

<div class="m-t-24">
<osf-preprints-subjects />
</div>

<p-card styleClass="m-t-24" class="card">
<div>
<h2>Tags (optional)</h2>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { Tooltip } from 'primeng/tooltip';
import { ChangeDetectionStrategy, Component, HostListener, OnInit, output } from '@angular/core';
import { FormControl, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms';

import { PreprintsSubjectsComponent } from '@osf/features/preprints/components/stepper/metadata-step/preprints-subjects/preprints-subjects.component';
import { formInputLimits } from '@osf/features/preprints/constants';
import { MetadataForm, Preprint } from '@osf/features/preprints/models';
import {
Expand Down Expand Up @@ -44,6 +45,7 @@ import { ContributorsComponent } from './contributors/contributors.component';
Tooltip,
LicenseComponent,
TagsInputComponent,
PreprintsSubjectsComponent,
],
templateUrl: './metadata-step.component.html',
styleUrl: './metadata-step.component.scss',
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<osf-subjects
[areSubjectsUpdating]="isSubjectsUpdating()"
[selected]="selectedSubjects()"
(loadChildren)="getSubjectChildren($event)"
(searchChanged)="searchSubjects($event)"
(updateSelection)="updateSelectedSubjects($event)"
/>
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';

import { PreprintsSubjectsComponent } from './preprints-subjects.component';

describe('RegistriesSubjectsComponent', () => {
let component: PreprintsSubjectsComponent;
let fixture: ComponentFixture<PreprintsSubjectsComponent>;

beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [PreprintsSubjectsComponent],
}).compileComponents();

fixture = TestBed.createComponent(PreprintsSubjectsComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { createDispatchMap, select } from '@ngxs/store';

import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core';

import {
FetchPreprintsSubjects,
SubmitPreprintSelectors,
UpdatePreprintsSubjects,
} from '@osf/features/preprints/store/submit-preprint';
import { SubjectsComponent } from '@osf/shared/components';
import { Subject } from '@osf/shared/models';
import { FetchChildrenSubjects, FetchSubjects } from '@osf/shared/stores';

@Component({
selector: 'osf-preprints-subjects',
imports: [SubjectsComponent],
templateUrl: './preprints-subjects.component.html',
styleUrl: './preprints-subjects.component.scss',
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class PreprintsSubjectsComponent implements OnInit {
private readonly selectedProviderId = select(SubmitPreprintSelectors.getSelectedProviderId);
protected selectedSubjects = select(SubmitPreprintSelectors.getSelectedSubjects);
protected isSubjectsUpdating = select(SubmitPreprintSelectors.isSubjectsUpdating);

protected actions = createDispatchMap({
fetchSubjects: FetchSubjects,
fetchPreprintsSubjects: FetchPreprintsSubjects,
fetchChildrenSubjects: FetchChildrenSubjects,
updatePreprintsSubjects: UpdatePreprintsSubjects,
});

ngOnInit(): void {
this.actions.fetchSubjects(this.selectedProviderId()!);
this.actions.fetchPreprintsSubjects();
}

getSubjectChildren(parentId: string) {
this.actions.fetchChildrenSubjects(parentId);
}

searchSubjects(search: string) {
this.actions.fetchSubjects(search);
}

updateSelectedSubjects(subjects: Subject[]) {
this.actions.updatePreprintsSubjects(subjects);
}
}
Loading