From 4f95f1b3ac726a83ac7414c1da2429fc3d99ff31 Mon Sep 17 00:00:00 2001 From: nsemets Date: Fri, 5 Sep 2025 19:02:10 +0300 Subject: [PATCH 1/5] fix(metadata): updated metadata --- .../metadata-description.component.html | 2 +- .../metadata-doi/metadata-doi.component.html | 25 ---- .../metadata-doi.component.spec.ts | 49 ------- .../metadata-doi/metadata-doi.component.ts | 28 ---- .../metadata-funding.component.html | 14 +- .../metadata-publication-doi.component.html | 2 +- ...tadata-resource-information.component.html | 2 +- ...metadata-resource-information.component.ts | 1 + ...ffiliated-institutions-dialog.component.ts | 2 +- .../description-dialog.component.html | 4 +- .../description-dialog.component.ts | 16 +-- .../funding-dialog.component.html | 9 +- .../funding-dialog.component.ts | 33 ++--- .../license-dialog.component.html | 4 +- .../license-dialog.component.ts | 8 +- .../publication-doi-dialog.component.html | 9 +- .../publication-doi-dialog.component.ts | 4 +- ...resource-information-dialog.component.html | 12 +- .../resource-information-dialog.component.ts | 16 +-- .../resource-tooltip-info.component.html | 2 +- .../features/metadata/metadata.component.ts | 21 +-- .../models/description-result.model.ts | 3 + .../metadata/models/funding-dialog.model.ts | 2 +- src/app/features/metadata/models/index.ts | 2 + .../models/resource-information-form.model.ts | 6 + .../metadata/services/metadata.service.ts | 2 + .../features/metadata/store/metadata.model.ts | 33 +++++ .../metadata/store/metadata.selectors.ts | 5 - .../features/metadata/store/metadata.state.ts | 121 +++++++----------- .../add-contributor-item.component.html | 2 +- .../add-contributor-item.component.ts | 2 +- ...registered-contributor-dialog.component.ts | 6 +- .../contributors-list.component.ts | 10 +- src/assets/i18n/en.json | 3 +- 34 files changed, 182 insertions(+), 278 deletions(-) delete mode 100644 src/app/features/metadata/components/metadata-doi/metadata-doi.component.html delete mode 100644 src/app/features/metadata/components/metadata-doi/metadata-doi.component.spec.ts delete mode 100644 src/app/features/metadata/components/metadata-doi/metadata-doi.component.ts create mode 100644 src/app/features/metadata/models/description-result.model.ts create mode 100644 src/app/features/metadata/models/resource-information-form.model.ts diff --git a/src/app/features/metadata/components/metadata-description/metadata-description.component.html b/src/app/features/metadata/components/metadata-description/metadata-description.component.html index d682bd318..845f1d4bd 100644 --- a/src/app/features/metadata/components/metadata-description/metadata-description.component.html +++ b/src/app/features/metadata/components/metadata-description/metadata-description.component.html @@ -6,7 +6,7 @@

{{ 'project.overview.metadata.description' | translate }}

} diff --git a/src/app/features/metadata/components/metadata-doi/metadata-doi.component.html b/src/app/features/metadata/components/metadata-doi/metadata-doi.component.html deleted file mode 100644 index 53b86d20e..000000000 --- a/src/app/features/metadata/components/metadata-doi/metadata-doi.component.html +++ /dev/null @@ -1,25 +0,0 @@ - -
-

{{ 'project.overview.metadata.doi' | translate }}

- - @if (doi()) { - - } @else { - - } -
- - @if (doi()) { -
-

{{ doi() }}

-
- } @else { -
-

{{ 'project.overview.metadata.noDoi' | translate }}

-
- } -
diff --git a/src/app/features/metadata/components/metadata-doi/metadata-doi.component.spec.ts b/src/app/features/metadata/components/metadata-doi/metadata-doi.component.spec.ts deleted file mode 100644 index f01e791d9..000000000 --- a/src/app/features/metadata/components/metadata-doi/metadata-doi.component.spec.ts +++ /dev/null @@ -1,49 +0,0 @@ -import { ComponentFixture, TestBed } from '@angular/core/testing'; - -import { MOCK_PROJECT_OVERVIEW, TranslateServiceMock } from '@osf/shared/mocks'; - -import { MetadataDoiComponent } from './metadata-doi.component'; - -describe('MetadataDoiComponent', () => { - let component: MetadataDoiComponent; - let fixture: ComponentFixture; - - const mockDoi: string | undefined = MOCK_PROJECT_OVERVIEW.doi; - - beforeEach(async () => { - await TestBed.configureTestingModule({ - imports: [MetadataDoiComponent], - providers: [TranslateServiceMock], - }).compileComponents(); - - fixture = TestBed.createComponent(MetadataDoiComponent); - component = fixture.componentInstance; - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); - - it('should set current input', () => { - fixture.componentRef.setInput('doi', mockDoi); - fixture.detectChanges(); - - expect(component.doi()).toEqual(mockDoi); - }); - - it('should emit editDoi event when onCreateDoi is called', () => { - const emitSpy = jest.spyOn(component.editDoi, 'emit'); - - component.onCreateDoi(); - - expect(emitSpy).toHaveBeenCalled(); - }); - - it('should emit editDoi event when onEditDoi is called', () => { - const emitSpy = jest.spyOn(component.editDoi, 'emit'); - - component.onEditDoi(); - - expect(emitSpy).toHaveBeenCalled(); - }); -}); diff --git a/src/app/features/metadata/components/metadata-doi/metadata-doi.component.ts b/src/app/features/metadata/components/metadata-doi/metadata-doi.component.ts deleted file mode 100644 index 753aa23e8..000000000 --- a/src/app/features/metadata/components/metadata-doi/metadata-doi.component.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { TranslatePipe } from '@ngx-translate/core'; - -import { ConfirmationService } from 'primeng/api'; -import { Button } from 'primeng/button'; -import { Card } from 'primeng/card'; - -import { ChangeDetectionStrategy, Component, input, output } from '@angular/core'; - -@Component({ - selector: 'osf-metadata-doi', - imports: [Button, Card, TranslatePipe], - providers: [ConfirmationService], - templateUrl: './metadata-doi.component.html', - changeDetection: ChangeDetectionStrategy.OnPush, -}) -export class MetadataDoiComponent { - editDoi = output(); - - doi = input.required(); - - onCreateDoi(): void { - this.editDoi.emit(); - } - - onEditDoi(): void { - this.editDoi.emit(); - } -} diff --git a/src/app/features/metadata/components/metadata-funding/metadata-funding.component.html b/src/app/features/metadata/components/metadata-funding/metadata-funding.component.html index ba2827069..67f7d77ca 100644 --- a/src/app/features/metadata/components/metadata-funding/metadata-funding.component.html +++ b/src/app/features/metadata/components/metadata-funding/metadata-funding.component.html @@ -6,7 +6,7 @@

{{ 'project.overview.metadata.fundingSupport' | translate }}

} @@ -22,23 +22,21 @@

{{ 'project.overview.metadata.fundingSupport' | translate }}

@if (funder.awardUri) {

{{ 'files.detail.resourceMetadata.fields.awardUri' | translate }}: - {{ funder.awardTitle }} + + {{ funder.awardUri }} +

} @if (funder.awardNumber) { -

{{ 'files.detail.resourceMetadata.fields.awardNumber' | translate }} : {{ funder.awardNumber }}

- } - - @if (funder.awardUri) { - {{ funder.awardUri }} +

{{ 'files.detail.resourceMetadata.fields.awardNumber' | translate }}: {{ funder.awardNumber }}

} } } @else {
-

{{ 'project.overview.metadata.noSupplements' | translate }}

+

{{ 'project.overview.metadata.noInformation' | translate }}

} diff --git a/src/app/features/metadata/components/metadata-publication-doi/metadata-publication-doi.component.html b/src/app/features/metadata/components/metadata-publication-doi/metadata-publication-doi.component.html index 4f8ac7ebf..c4b3cb17f 100644 --- a/src/app/features/metadata/components/metadata-publication-doi/metadata-publication-doi.component.html +++ b/src/app/features/metadata/components/metadata-publication-doi/metadata-publication-doi.component.html @@ -6,7 +6,7 @@

{{ 'project.overview.metadata.publication' | translate }}

} diff --git a/src/app/features/metadata/components/metadata-resource-information/metadata-resource-information.component.html b/src/app/features/metadata/components/metadata-resource-information/metadata-resource-information.component.html index af8017a95..b31512d64 100644 --- a/src/app/features/metadata/components/metadata-resource-information/metadata-resource-information.component.html +++ b/src/app/features/metadata/components/metadata-resource-information/metadata-resource-information.component.html @@ -14,7 +14,7 @@

} diff --git a/src/app/features/metadata/components/metadata-resource-information/metadata-resource-information.component.ts b/src/app/features/metadata/components/metadata-resource-information/metadata-resource-information.component.ts index 0f8cca45a..f4c3c6ff7 100644 --- a/src/app/features/metadata/components/metadata-resource-information/metadata-resource-information.component.ts +++ b/src/app/features/metadata/components/metadata-resource-information/metadata-resource-information.component.ts @@ -22,6 +22,7 @@ export class MetadataResourceInformationComponent { customItemMetadata = input.required(); readonly = input(false); showResourceInfo = output(); + readonly languageCodes = languageCodes; readonly resourceTypes = RESOURCE_TYPE_OPTIONS; diff --git a/src/app/features/metadata/dialogs/affiliated-institutions-dialog/affiliated-institutions-dialog.component.ts b/src/app/features/metadata/dialogs/affiliated-institutions-dialog/affiliated-institutions-dialog.component.ts index 7011d4f1b..5f08d5cd0 100644 --- a/src/app/features/metadata/dialogs/affiliated-institutions-dialog/affiliated-institutions-dialog.component.ts +++ b/src/app/features/metadata/dialogs/affiliated-institutions-dialog/affiliated-institutions-dialog.component.ts @@ -10,7 +10,7 @@ import { ReactiveFormsModule } from '@angular/forms'; import { AffiliatedInstitutionSelectComponent } from '@osf/shared/components'; import { Institution } from '@osf/shared/models'; -import { InstitutionsSelectors } from '@osf/shared/stores/institutions'; +import { InstitutionsSelectors } from '@osf/shared/stores'; @Component({ selector: 'osf-affiliated-institutions-dialog', diff --git a/src/app/features/metadata/dialogs/description-dialog/description-dialog.component.html b/src/app/features/metadata/dialogs/description-dialog/description-dialog.component.html index b8a523efe..591756ac2 100644 --- a/src/app/features/metadata/dialogs/description-dialog/description-dialog.component.html +++ b/src/app/features/metadata/dialogs/description-dialog/description-dialog.component.html @@ -9,7 +9,7 @@ >
- - + +
diff --git a/src/app/features/metadata/dialogs/description-dialog/description-dialog.component.ts b/src/app/features/metadata/dialogs/description-dialog/description-dialog.component.ts index 96dd8f8ec..4174bd1e6 100644 --- a/src/app/features/metadata/dialogs/description-dialog/description-dialog.component.ts +++ b/src/app/features/metadata/dialogs/description-dialog/description-dialog.component.ts @@ -8,7 +8,8 @@ import { ChangeDetectionStrategy, Component, inject, OnInit } from '@angular/cor import { FormControl, ReactiveFormsModule } from '@angular/forms'; import { ProjectOverview } from '@osf/features/project/overview/models'; -import { CustomValidators } from '@osf/shared/helpers'; + +import { DescriptionResultModel } from '../../models'; @Component({ selector: 'osf-description-dialog', @@ -18,13 +19,10 @@ import { CustomValidators } from '@osf/shared/helpers'; changeDetection: ChangeDetectionStrategy.OnPush, }) export class DescriptionDialogComponent implements OnInit { - protected dialogRef = inject(DynamicDialogRef); - protected config = inject(DynamicDialogConfig); + dialogRef = inject(DynamicDialogRef); + config = inject(DynamicDialogConfig); - descriptionControl = new FormControl('', { - nonNullable: true, - validators: [CustomValidators.requiredTrimmed], - }); + descriptionControl = new FormControl(''); get currentMetadata(): ProjectOverview | null { return this.config.data ? this.config.data.currentMetadata || null : null; @@ -37,9 +35,7 @@ export class DescriptionDialogComponent implements OnInit { } save(): void { - if (this.descriptionControl.valid) { - this.dialogRef.close(this.descriptionControl.value); - } + this.dialogRef.close({ value: this.descriptionControl.value } as DescriptionResultModel); } cancel(): void { diff --git a/src/app/features/metadata/dialogs/funding-dialog/funding-dialog.component.html b/src/app/features/metadata/dialogs/funding-dialog/funding-dialog.component.html index 822c65337..33a353b0b 100644 --- a/src/app/features/metadata/dialogs/funding-dialog/funding-dialog.component.html +++ b/src/app/features/metadata/dialogs/funding-dialog/funding-dialog.component.html @@ -19,6 +19,8 @@ filterBy="label" [showClear]="true" [loading]="fundersLoading()" + [autoOptionFocus]="false" + resetFilterOnHide="false" (onChange)="onFunderSelected($event.value, $index)" (onFilter)="onFunderSearch($event.filter)" /> @@ -51,7 +53,7 @@ severity="danger" [label]="'common.buttons.remove' | translate" size="small" - (click)="removeFundingEntry($index)" + (onClick)="removeFundingEntry($index)" /> } @@ -63,14 +65,13 @@
- +
diff --git a/src/app/features/metadata/dialogs/funding-dialog/funding-dialog.component.ts b/src/app/features/metadata/dialogs/funding-dialog/funding-dialog.component.ts index a29b730ed..da758e84a 100644 --- a/src/app/features/metadata/dialogs/funding-dialog/funding-dialog.component.ts +++ b/src/app/features/metadata/dialogs/funding-dialog/funding-dialog.component.ts @@ -13,17 +13,11 @@ import { ChangeDetectionStrategy, Component, DestroyRef, effect, inject, OnInit, import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { FormArray, FormControl, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms'; -import { - Funder, - FunderOption, - FundingDialogResult, - FundingEntryForm, - FundingForm, - SupplementData, -} from '@osf/features/metadata/models'; -import { GetFundersList, MetadataSelectors } from '@osf/features/metadata/store'; import { CustomValidators } from '@osf/shared/helpers'; +import { Funder, FunderOption, FundingDialogResult, FundingEntryForm, FundingForm, SupplementData } from '../../models'; +import { GetFundersList, MetadataSelectors } from '../../store'; + @Component({ selector: 'osf-funding-dialog', imports: [Button, Select, InputText, TranslatePipe, ReactiveFormsModule], @@ -35,22 +29,16 @@ export class FundingDialogComponent implements OnInit { config = inject(DynamicDialogConfig); destroyRef = inject(DestroyRef); - actions = createDispatchMap({ - getFundersList: GetFundersList, - }); + actions = createDispatchMap({ getFundersList: GetFundersList }); fundersList = select(MetadataSelectors.getFundersList); fundersLoading = select(MetadataSelectors.getFundersLoading); funderOptions = signal([]); - fundingForm = new FormGroup({ - fundingEntries: new FormArray>([]), - }); + fundingForm = new FormGroup({ fundingEntries: new FormArray>([]) }); private searchSubject = new Subject(); - readonly linkValidators = [CustomValidators.linkValidator(), CustomValidators.requiredTrimmed()]; - constructor() { effect(() => { const funders = this.fundersList() || []; @@ -79,7 +67,7 @@ export class FundingDialogComponent implements OnInit { this.actions.getFundersList(); const configFunders = this.config.data?.funders; - if (configFunders && configFunders.length > 0) { + if (configFunders?.length > 0) { configFunders.forEach((funder: Funder) => { this.addFundingEntry({ funderName: funder.funderName || '', @@ -96,9 +84,7 @@ export class FundingDialogComponent implements OnInit { this.searchSubject .pipe(debounceTime(300), distinctUntilChanged(), takeUntilDestroyed(this.destroyRef)) - .subscribe((searchQuery) => { - this.actions.getFundersList(searchQuery); - }); + .subscribe((searchQuery) => this.actions.getFundersList(searchQuery)); } onFunderSearch(searchTerm: string): void { @@ -107,8 +93,7 @@ export class FundingDialogComponent implements OnInit { private createFundingEntryGroup(supplement?: SupplementData): FormGroup { return new FormGroup({ - funderName: new FormControl(supplement?.funderName ?? '', { - nonNullable: true, + funderName: new FormControl(supplement?.funderName ?? null, { validators: [Validators.required], }), funderIdentifier: new FormControl(supplement?.funderIdentifier ?? '', { @@ -123,7 +108,7 @@ export class FundingDialogComponent implements OnInit { }), awardUri: new FormControl(supplement?.url || supplement?.awardUri || '', { nonNullable: true, - validators: this.linkValidators, + validators: [CustomValidators.linkValidator(), CustomValidators.requiredTrimmed()], }), awardNumber: new FormControl(supplement?.awardNumber || '', { nonNullable: true, diff --git a/src/app/features/metadata/dialogs/license-dialog/license-dialog.component.html b/src/app/features/metadata/dialogs/license-dialog/license-dialog.component.html index bdb569f11..d36bed309 100644 --- a/src/app/features/metadata/dialogs/license-dialog/license-dialog.component.html +++ b/src/app/features/metadata/dialogs/license-dialog/license-dialog.component.html @@ -20,10 +20,10 @@

{{ 'project.metadata.license.dialog.chooseLicense.label' | tran }
- + diff --git a/src/app/features/metadata/dialogs/license-dialog/license-dialog.component.ts b/src/app/features/metadata/dialogs/license-dialog/license-dialog.component.ts index 6e5a55cbd..9f1b8774a 100644 --- a/src/app/features/metadata/dialogs/license-dialog/license-dialog.component.ts +++ b/src/app/features/metadata/dialogs/license-dialog/license-dialog.component.ts @@ -19,12 +19,10 @@ import { LicensesSelectors, LoadAllLicenses } from '@shared/stores/licenses'; changeDetection: ChangeDetectionStrategy.OnPush, }) export class LicenseDialogComponent implements OnInit { - protected dialogRef = inject(DynamicDialogRef); - protected config = inject(DynamicDialogConfig); + dialogRef = inject(DynamicDialogRef); + config = inject(DynamicDialogConfig); - protected actions = createDispatchMap({ - loadLicenses: LoadAllLicenses, - }); + actions = createDispatchMap({ loadLicenses: LoadAllLicenses }); licenses = select(LicensesSelectors.getLicenses); licensesLoading = select(LicensesSelectors.getLoading); diff --git a/src/app/features/metadata/dialogs/publication-doi-dialog/publication-doi-dialog.component.html b/src/app/features/metadata/dialogs/publication-doi-dialog/publication-doi-dialog.component.html index a1c63e4e4..216b7797c 100644 --- a/src/app/features/metadata/dialogs/publication-doi-dialog/publication-doi-dialog.component.html +++ b/src/app/features/metadata/dialogs/publication-doi-dialog/publication-doi-dialog.component.html @@ -7,8 +7,13 @@ [placeholder]="'project.metadata.doi.dialog.placeholder' | translate" /> +
- - + +
diff --git a/src/app/features/metadata/dialogs/publication-doi-dialog/publication-doi-dialog.component.ts b/src/app/features/metadata/dialogs/publication-doi-dialog/publication-doi-dialog.component.ts index 6e3e8bdb4..d43ac4042 100644 --- a/src/app/features/metadata/dialogs/publication-doi-dialog/publication-doi-dialog.component.ts +++ b/src/app/features/metadata/dialogs/publication-doi-dialog/publication-doi-dialog.component.ts @@ -19,8 +19,8 @@ import { CustomValidators } from '@osf/shared/helpers'; changeDetection: ChangeDetectionStrategy.OnPush, }) export class PublicationDoiDialogComponent { - protected dialogRef = inject(DynamicDialogRef); - protected config = inject(DynamicDialogConfig); + dialogRef = inject(DynamicDialogRef); + config = inject(DynamicDialogConfig); publicationDoiControl = new FormControl(this.config.data.publicationDoi || '', { nonNullable: true, diff --git a/src/app/features/metadata/dialogs/resource-information-dialog/resource-information-dialog.component.html b/src/app/features/metadata/dialogs/resource-information-dialog/resource-information-dialog.component.html index 45ee9b76f..d5a9d26f5 100644 --- a/src/app/features/metadata/dialogs/resource-information-dialog/resource-information-dialog.component.html +++ b/src/app/features/metadata/dialogs/resource-information-dialog/resource-information-dialog.component.html @@ -23,6 +23,8 @@ + > + + {{ option.label }} + +
-
- +
+
diff --git a/src/app/features/metadata/dialogs/resource-information-dialog/resource-information-dialog.component.ts b/src/app/features/metadata/dialogs/resource-information-dialog/resource-information-dialog.component.ts index ef4d0e90d..c82ad5d28 100644 --- a/src/app/features/metadata/dialogs/resource-information-dialog/resource-information-dialog.component.ts +++ b/src/app/features/metadata/dialogs/resource-information-dialog/resource-information-dialog.component.ts @@ -7,15 +7,11 @@ import { Select } from 'primeng/select'; import { ChangeDetectionStrategy, Component, inject, OnInit } from '@angular/core'; import { FormControl, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms'; -import { RESOURCE_TYPE_OPTIONS } from '@osf/features/metadata/constants'; -import { CustomItemMetadataRecord } from '@osf/features/metadata/models'; -import { languageCodes } from '@shared/constants'; -import { LanguageCodeModel } from '@shared/models'; +import { languageCodes } from '@osf/shared/constants'; +import { LanguageCodeModel } from '@osf/shared/models'; -interface ResourceInformationForm { - resourceType: FormControl; - resourceLanguage: FormControl; -} +import { RESOURCE_TYPE_OPTIONS } from '../../constants'; +import { CustomItemMetadataRecord, ResourceInformationForm } from '../../models'; @Component({ selector: 'osf-resource-information-dialog', @@ -24,8 +20,8 @@ interface ResourceInformationForm { changeDetection: ChangeDetectionStrategy.OnPush, }) export class ResourceInformationDialogComponent implements OnInit { - protected dialogRef = inject(DynamicDialogRef); - protected config = inject(DynamicDialogConfig); + dialogRef = inject(DynamicDialogRef); + config = inject(DynamicDialogConfig); resourceForm = new FormGroup({ resourceType: new FormControl('', { diff --git a/src/app/features/metadata/dialogs/resource-tooltip-info/resource-tooltip-info.component.html b/src/app/features/metadata/dialogs/resource-tooltip-info/resource-tooltip-info.component.html index 0612e8f5a..30b5db0c8 100644 --- a/src/app/features/metadata/dialogs/resource-tooltip-info/resource-tooltip-info.component.html +++ b/src/app/features/metadata/dialogs/resource-tooltip-info/resource-tooltip-info.component.html @@ -18,5 +18,5 @@
- +
diff --git a/src/app/features/metadata/metadata.component.ts b/src/app/features/metadata/metadata.component.ts index a500bfcc3..a2c638d68 100644 --- a/src/app/features/metadata/metadata.component.ts +++ b/src/app/features/metadata/metadata.component.ts @@ -48,7 +48,12 @@ import { ResourceInformationDialogComponent, ResourceInfoTooltipComponent, } from './dialogs'; -import { CedarMetadataDataTemplateJsonApi, CedarMetadataRecordData, CedarRecordDataBinding } from './models'; +import { + CedarMetadataDataTemplateJsonApi, + CedarMetadataRecordData, + CedarRecordDataBinding, + DescriptionResultModel, +} from './models'; import { CreateCedarMetadataRecord, CreateDoi, @@ -147,8 +152,8 @@ export class MetadataComponent implements OnInit { hideEditDoi = computed(() => { return ( - !!(this.metadata()?.identifiers?.length && this.resourceType() === ResourceType.Project) || - !this.metadata()?.public + this.resourceType() === ResourceType.Project && + (!!this.metadata()?.identifiers?.length || !this.metadata()?.public) ); }); @@ -309,19 +314,15 @@ export class MetadataComponent implements OnInit { }); dialogRef.onClose .pipe( - filter((result) => !!result), + filter((result: DescriptionResultModel) => !!result), switchMap((result) => { if (this.resourceId) { - return this.actions.updateMetadata(this.resourceId, this.resourceType(), { description: result }); + return this.actions.updateMetadata(this.resourceId, this.resourceType(), { description: result.value }); } return EMPTY; }) ) - .subscribe({ - next: () => { - this.toastService.showSuccess('project.metadata.description.updated'); - }, - }); + .subscribe(() => this.toastService.showSuccess('project.metadata.description.updated')); } openEditResourceInformationDialog(): void { diff --git a/src/app/features/metadata/models/description-result.model.ts b/src/app/features/metadata/models/description-result.model.ts new file mode 100644 index 000000000..5f09149a7 --- /dev/null +++ b/src/app/features/metadata/models/description-result.model.ts @@ -0,0 +1,3 @@ +export interface DescriptionResultModel { + value: string; +} diff --git a/src/app/features/metadata/models/funding-dialog.model.ts b/src/app/features/metadata/models/funding-dialog.model.ts index 5ef8b527f..3762902b1 100644 --- a/src/app/features/metadata/models/funding-dialog.model.ts +++ b/src/app/features/metadata/models/funding-dialog.model.ts @@ -3,7 +3,7 @@ import { FormArray, FormControl, FormGroup } from '@angular/forms'; import { Funder } from './metadata.model'; export interface FundingEntryForm { - funderName: FormControl; + funderName: FormControl; funderIdentifier: FormControl; funderIdentifierType: FormControl; awardTitle: FormControl; diff --git a/src/app/features/metadata/models/index.ts b/src/app/features/metadata/models/index.ts index 42fe457b8..eea8ea80e 100644 --- a/src/app/features/metadata/models/index.ts +++ b/src/app/features/metadata/models/index.ts @@ -1,4 +1,6 @@ export * from './cedar-metadata-template.model'; +export * from './description-result.model'; export * from './funding-dialog.model'; export * from './metadata.model'; export * from './metadata-json-api.model'; +export * from './resource-information-form.model'; diff --git a/src/app/features/metadata/models/resource-information-form.model.ts b/src/app/features/metadata/models/resource-information-form.model.ts new file mode 100644 index 000000000..c67c4d946 --- /dev/null +++ b/src/app/features/metadata/models/resource-information-form.model.ts @@ -0,0 +1,6 @@ +import { FormControl } from '@angular/forms'; + +export interface ResourceInformationForm { + resourceType: FormControl; + resourceLanguage: FormControl; +} diff --git a/src/app/features/metadata/services/metadata.service.ts b/src/app/features/metadata/services/metadata.service.ts index 3a605d956..015adee1c 100644 --- a/src/app/features/metadata/services/metadata.service.ts +++ b/src/app/features/metadata/services/metadata.service.ts @@ -143,6 +143,7 @@ export class MetadataService { const baseUrl = `${this.apiUrl}/${this.urlMap.get(resourceType)}/${resourceId}/`; const params = this.getMetadataParams(resourceType); + return this.jsonApiService .patch(baseUrl, payload, params) .pipe(map((response) => MetadataMapper.fromMetadataApiResponse(response))); @@ -179,6 +180,7 @@ export class MetadataService { const baseUrl = `${this.apiUrl}/${this.urlMap.get(resourceType)}/${resourceId}/`; const params = this.getMetadataParams(resourceType); + return this.jsonApiService .patch(baseUrl, payload, params) .pipe(map((response) => MetadataMapper.fromMetadataApiResponse(response))); diff --git a/src/app/features/metadata/store/metadata.model.ts b/src/app/features/metadata/store/metadata.model.ts index 9fc0e3ec5..21c6080f1 100644 --- a/src/app/features/metadata/store/metadata.model.ts +++ b/src/app/features/metadata/store/metadata.model.ts @@ -16,3 +16,36 @@ export interface MetadataStateModel { cedarRecord: AsyncStateModel; cedarRecords: AsyncStateModel; } + +export const METADATA_STATE_DEFAULTS: MetadataStateModel = { + metadata: { + data: null, + isLoading: false, + error: null, + }, + customMetadata: { + data: null, + isLoading: false, + error: null, + }, + fundersList: { + data: [], + isLoading: false, + error: null, + }, + cedarTemplates: { + data: null, + isLoading: false, + error: null, + }, + cedarRecord: { + data: null, + isLoading: false, + error: null, + }, + cedarRecords: { + data: [], + isLoading: false, + error: null, + }, +}; diff --git a/src/app/features/metadata/store/metadata.selectors.ts b/src/app/features/metadata/store/metadata.selectors.ts index 4cdb143b9..a65a967ae 100644 --- a/src/app/features/metadata/store/metadata.selectors.ts +++ b/src/app/features/metadata/store/metadata.selectors.ts @@ -24,11 +24,6 @@ export class MetadataSelectors { return state.metadata?.isSubmitting || state.customMetadata?.isSubmitting || false; } - @Selector([MetadataState]) - static getError(state: MetadataStateModel) { - return state.metadata?.error ?? null; - } - @Selector([MetadataState]) static getFundersList(state: MetadataStateModel) { return state.fundersList.data; diff --git a/src/app/features/metadata/store/metadata.state.ts b/src/app/features/metadata/store/metadata.state.ts index aa8c6545d..05301ed11 100644 --- a/src/app/features/metadata/store/metadata.state.ts +++ b/src/app/features/metadata/store/metadata.state.ts @@ -23,20 +23,11 @@ import { UpdateResourceDetails, UpdateResourceLicense, } from './metadata.actions'; -import { MetadataStateModel } from './metadata.model'; - -const initialState: MetadataStateModel = { - metadata: { data: null, isLoading: false, error: null }, - customMetadata: { data: null, isLoading: false, error: null }, - fundersList: { data: [], isLoading: false, error: null }, - cedarTemplates: { data: null, isLoading: false, error: null }, - cedarRecord: { data: null, isLoading: false, error: null }, - cedarRecords: { data: [], isLoading: false, error: null }, -}; +import { METADATA_STATE_DEFAULTS, MetadataStateModel } from './metadata.model'; @State({ name: 'metadata', - defaults: initialState, + defaults: METADATA_STATE_DEFAULTS, }) @Injectable() export class MetadataState { @@ -54,16 +45,14 @@ export class MetadataState { }); return this.metadataService.getResourceMetadata(action.resourceId, action.resourceType).pipe( - tap({ - next: (resource) => { - ctx.patchState({ - metadata: { - data: resource as Metadata, - isLoading: false, - error: null, - }, - }); - }, + tap((resource) => { + ctx.patchState({ + metadata: { + data: resource as Metadata, + isLoading: false, + error: null, + }, + }); }), catchError((error) => handleSectionError(ctx, 'metadata', error)) ); @@ -78,12 +67,10 @@ export class MetadataState { }); return this.metadataService.getCustomItemMetadata(action.guid).pipe( - tap({ - next: (response) => { - ctx.patchState({ - customMetadata: { data: response, isLoading: false, error: null }, - }); - }, + tap((response) => { + ctx.patchState({ + customMetadata: { data: response, isLoading: false, error: null }, + }); }), catchError((error) => handleSectionError(ctx, 'customMetadata', error)) ); @@ -98,12 +85,10 @@ export class MetadataState { }); return this.metadataService.updateCustomItemMetadata(action.guid, action.metadata).pipe( - tap({ - next: (response) => { - ctx.patchState({ - customMetadata: { data: response, isLoading: false, error: null }, - }); - }, + tap((response) => { + ctx.patchState({ + customMetadata: { data: response, isLoading: false, error: null }, + }); }), catchError((error) => handleSectionError(ctx, 'customMetadata', error)) ); @@ -116,13 +101,11 @@ export class MetadataState { }); return this.metadataService.createDoi(action.resourceId, action.resourceType).pipe( - tap({ - next: () => { - ctx.patchState({ - metadata: { ...ctx.getState().metadata, isLoading: false, error: null }, - }); - ctx.dispatch(new GetResourceMetadata(action.resourceId, action.resourceType)); - }, + tap(() => { + ctx.patchState({ + metadata: { ...ctx.getState().metadata, isLoading: false, error: null }, + }); + ctx.dispatch(new GetResourceMetadata(action.resourceId, action.resourceType)); }), catchError((error) => handleSectionError(ctx, 'metadata', error)) ); @@ -135,12 +118,10 @@ export class MetadataState { }); return this.metadataService.getFundersList(action.search).pipe( - tap({ - next: (response) => { - ctx.patchState({ - fundersList: { data: response.message.items, isLoading: false, error: null }, - }); - }, + tap((response) => { + ctx.patchState({ + fundersList: { data: response.message.items, isLoading: false, error: null }, + }); }), catchError((error) => handleSectionError(ctx, 'fundersList', error)) ); @@ -273,21 +254,19 @@ export class MetadataState { }); return this.metadataService.updateResourceDetails(action.resourceId, action.resourceType, action.updates).pipe( - tap({ - next: (updatedResource) => { - const currentResource = ctx.getState().metadata.data; + tap((updatedResource) => { + const currentResource = ctx.getState().metadata.data; - ctx.patchState({ - metadata: { - data: { - ...currentResource, - ...updatedResource, - }, - error: null, - isLoading: false, + ctx.patchState({ + metadata: { + data: { + ...currentResource, + ...updatedResource, }, - }); - }, + error: null, + isLoading: false, + }, + }); }), catchError((error) => handleSectionError(ctx, 'metadata', error)) ); @@ -306,21 +285,19 @@ export class MetadataState { return this.metadataService .updateResourceLicense(action.resourceId, action.resourceType, action.licenseId, action.licenseOptions) .pipe( - tap({ - next: (updatedResource) => { - const currentResource = ctx.getState().metadata.data; + tap((updatedResource) => { + const currentResource = ctx.getState().metadata.data; - ctx.patchState({ - metadata: { - data: { - ...currentResource, - ...updatedResource, - }, - error: null, - isLoading: false, + ctx.patchState({ + metadata: { + data: { + ...currentResource, + ...updatedResource, }, - }); - }, + error: null, + isLoading: false, + }, + }); }), catchError((error) => handleSectionError(ctx, 'metadata', error)) ); diff --git a/src/app/shared/components/contributors/add-contributor-item/add-contributor-item.component.html b/src/app/shared/components/contributors/add-contributor-item/add-contributor-item.component.html index af20bec0d..7db188f99 100644 --- a/src/app/shared/components/contributors/add-contributor-item/add-contributor-item.component.html +++ b/src/app/shared/components/contributors/add-contributor-item/add-contributor-item.component.html @@ -26,7 +26,7 @@
(); - protected readonly permissionsOptions = PERMISSION_OPTIONS; + readonly permissionsOptions = PERMISSION_OPTIONS; } diff --git a/src/app/shared/components/contributors/add-unregistered-contributor-dialog/add-unregistered-contributor-dialog.component.ts b/src/app/shared/components/contributors/add-unregistered-contributor-dialog/add-unregistered-contributor-dialog.component.ts index 3662dec60..0f11ef454 100644 --- a/src/app/shared/components/contributors/add-unregistered-contributor-dialog/add-unregistered-contributor-dialog.component.ts +++ b/src/app/shared/components/contributors/add-unregistered-contributor-dialog/add-unregistered-contributor-dialog.component.ts @@ -20,9 +20,9 @@ import { ContributorAddModel, ContributorDialogAddModel, UnregisteredContributor changeDetection: ChangeDetectionStrategy.OnPush, }) export class AddUnregisteredContributorDialogComponent { - protected dialogRef = inject(DynamicDialogRef); - protected contributorForm!: FormGroup; - protected inputLimits = InputLimits; + dialogRef = inject(DynamicDialogRef); + contributorForm!: FormGroup; + inputLimits = InputLimits; constructor() { this.initForm(); diff --git a/src/app/shared/components/contributors/contributors-list/contributors-list.component.ts b/src/app/shared/components/contributors/contributors-list/contributors-list.component.ts index 02797def1..9bc8c42eb 100644 --- a/src/app/shared/components/contributors/contributors-list/contributors-list.component.ts +++ b/src/app/shared/components/contributors/contributors-list/contributors-list.component.ts @@ -36,16 +36,16 @@ export class ContributorsListComponent { dialogService = inject(DialogService); translateService = inject(TranslateService); - protected readonly tableParams = signal({ ...MY_PROJECTS_TABLE_PARAMS }); - protected readonly permissionsOptions: SelectOption[] = PERMISSION_OPTIONS; + readonly tableParams = signal({ ...MY_PROJECTS_TABLE_PARAMS }); + readonly permissionsOptions: SelectOption[] = PERMISSION_OPTIONS; skeletonData: ContributorModel[] = Array.from({ length: 3 }, () => ({}) as ContributorModel); - protected removeContributor(contributor: ContributorModel) { + removeContributor(contributor: ContributorModel) { this.remove.emit(contributor); } - protected openEducationHistory(contributor: ContributorModel) { + openEducationHistory(contributor: ContributorModel) { this.dialogService.open(EducationHistoryDialogComponent, { width: '552px', data: contributor.education, @@ -57,7 +57,7 @@ export class ContributorsListComponent { }); } - protected openEmploymentHistory(contributor: ContributorModel) { + openEmploymentHistory(contributor: ContributorModel) { this.dialogService.open(EmploymentHistoryDialogComponent, { width: '552px', data: contributor.employment, diff --git a/src/assets/i18n/en.json b/src/assets/i18n/en.json index 90ef1fbbc..e47cc055f 100644 --- a/src/assets/i18n/en.json +++ b/src/assets/i18n/en.json @@ -506,7 +506,7 @@ "cancel": "Cancel", "next": "Next", "selectPermissions": "Please select which permissions you want to give to contributor", - "bibliographicCOntributor": "Bibliographic Contributor", + "bibliographicContributor": "Bibliographic Contributor", "addUnregisteredContributor": "Add Unregistered Contributor", "addRegisteredContributor": "Add Registered Contributor", "unregisteredContributorNotification": "We will notify the user that they have been added to your project" @@ -611,6 +611,7 @@ "noSubjects": "No subjects", "noTags": "No tags", "noSupplements": "No supplements", + "noInformation": "No information", "noAffiliatedInstitutions": "No affiliated institutions", "resourceInformation": "Resource Information", "resourceType": "Resource type", From c9516677c5c885fa9f2019d04e533e5e24005db9 Mon Sep 17 00:00:00 2001 From: nsemets Date: Fri, 5 Sep 2025 19:54:06 +0300 Subject: [PATCH 2/5] fix(metadata): fixes --- .../metadata-contributors.component.html | 2 +- .../metadata-contributors.component.ts | 3 ++- .../metadata-funding/metadata-funding.component.ts | 2 +- .../metadata-license/metadata-license.component.html | 2 +- .../metadata-publication-doi.component.html | 8 ++++++-- 5 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/app/features/metadata/components/metadata-contributors/metadata-contributors.component.html b/src/app/features/metadata/components/metadata-contributors/metadata-contributors.component.html index ca74df140..f1f26d9a2 100644 --- a/src/app/features/metadata/components/metadata-contributors/metadata-contributors.component.html +++ b/src/app/features/metadata/components/metadata-contributors/metadata-contributors.component.html @@ -15,7 +15,7 @@

{{ 'project.overview.metadata.contributors' | translate }}

@for (contributor of contributors(); track contributor.id) { } diff --git a/src/app/features/metadata/components/metadata-contributors/metadata-contributors.component.ts b/src/app/features/metadata/components/metadata-contributors/metadata-contributors.component.ts index 6c0502d4e..843e7b16e 100644 --- a/src/app/features/metadata/components/metadata-contributors/metadata-contributors.component.ts +++ b/src/app/features/metadata/components/metadata-contributors/metadata-contributors.component.ts @@ -4,12 +4,13 @@ import { Button } from 'primeng/button'; import { Card } from 'primeng/card'; import { ChangeDetectionStrategy, Component, input, output } from '@angular/core'; +import { RouterLink } from '@angular/router'; import { ContributorModel } from '@osf/shared/models'; @Component({ selector: 'osf-metadata-contributors', - imports: [Button, Card, TranslatePipe], + imports: [Button, Card, TranslatePipe, RouterLink], templateUrl: './metadata-contributors.component.html', changeDetection: ChangeDetectionStrategy.OnPush, }) diff --git a/src/app/features/metadata/components/metadata-funding/metadata-funding.component.ts b/src/app/features/metadata/components/metadata-funding/metadata-funding.component.ts index 841411028..38764938f 100644 --- a/src/app/features/metadata/components/metadata-funding/metadata-funding.component.ts +++ b/src/app/features/metadata/components/metadata-funding/metadata-funding.component.ts @@ -5,7 +5,7 @@ import { Card } from 'primeng/card'; import { ChangeDetectionStrategy, Component, input, output } from '@angular/core'; -import { Funder } from '@osf/features/metadata/models'; +import { Funder } from '../../models'; @Component({ selector: 'osf-metadata-funding', diff --git a/src/app/features/metadata/components/metadata-license/metadata-license.component.html b/src/app/features/metadata/components/metadata-license/metadata-license.component.html index 8dbf3c5eb..91982195f 100644 --- a/src/app/features/metadata/components/metadata-license/metadata-license.component.html +++ b/src/app/features/metadata/components/metadata-license/metadata-license.component.html @@ -6,7 +6,7 @@

{{ 'project.overview.metadata.license' | translate }}

}
diff --git a/src/app/features/metadata/components/metadata-publication-doi/metadata-publication-doi.component.html b/src/app/features/metadata/components/metadata-publication-doi/metadata-publication-doi.component.html index c4b3cb17f..52681361c 100644 --- a/src/app/features/metadata/components/metadata-publication-doi/metadata-publication-doi.component.html +++ b/src/app/features/metadata/components/metadata-publication-doi/metadata-publication-doi.component.html @@ -15,7 +15,9 @@

{{ 'project.overview.metadata.publication' | translate }}

@for (identifier of identifiers()!; track identifier.id) { @if (identifier.category === 'doi') { - {{ doiHost + identifier.value }} + + {{ doiHost + identifier.value }} + } }
@@ -27,7 +29,9 @@

{{ 'project.overview.metadata.publication' | translate }}

} @else {
@if (publicationDoi()) { - {{ doiHost + publicationDoi() }} + + {{ doiHost + publicationDoi() }} + } @else {

{{ 'project.overview.metadata.noPublicationDoi' | translate }}

} From 46d5015686315563bf357c4c6c54fae53076af17 Mon Sep 17 00:00:00 2001 From: nsemets Date: Mon, 8 Sep 2025 13:41:50 +0300 Subject: [PATCH 3/5] fix(my-profile): fixed route --- .../features/profile/pages/my-profile/my-profile.component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/features/profile/pages/my-profile/my-profile.component.ts b/src/app/features/profile/pages/my-profile/my-profile.component.ts index 995ba7c3b..358adfbe1 100644 --- a/src/app/features/profile/pages/my-profile/my-profile.component.ts +++ b/src/app/features/profile/pages/my-profile/my-profile.component.ts @@ -39,6 +39,6 @@ export class MyProfileComponent implements OnInit { } toProfileSettings() { - this.router.navigate(['settings/profile-settings']); + this.router.navigate(['settings/profile']); } } From 5962b0a4bf6140fa93fd10480f0c812c1e4949ac Mon Sep 17 00:00:00 2001 From: nsemets Date: Mon, 8 Sep 2025 15:26:34 +0300 Subject: [PATCH 4/5] fix(models): updated some models --- .../project-metadata-step.component.ts | 26 +- .../models/project-metadata-form.model.ts | 4 +- .../services/add-to-collection.service.ts | 4 +- .../services/project-metadata-form.service.ts | 8 +- .../add-to-collection.model.ts | 4 +- .../metadata-license.component.ts | 4 +- .../license-dialog.component.ts | 4 +- .../metadata/models/metadata.model.ts | 4 +- .../metadata-step/metadata-step.component.ts | 12 +- .../preprints/models/preprint.models.ts | 4 +- .../services/preprint-licenses.service.ts | 4 +- .../preprint-stepper.model.ts | 4 +- .../mappers/project-overview.mapper.ts | 4 +- .../models/project-overview.models.ts | 4 +- .../registries-license.component.ts | 14 +- .../registries/mappers/licenses.mapper.ts | 4 +- .../registries/services/licenses.service.ts | 4 +- .../registries/store/registries.model.ts | 8 +- .../registries/store/registries.selectors.ts | 10 +- .../mappers/registry-metadata.mapper.ts | 4 +- .../models/registry-overview.models.ts | 4 +- .../services/registry-metadata.service.ts | 223 ------------------ .../tokens-list/tokens-list.component.ts | 2 +- .../addons/addon-card/addon-card.component.ts | 8 +- .../addon-terms/addon-terms.component.ts | 2 +- .../folder-selector.component.ts | 28 +-- .../bar-chart/bar-chart.component.ts | 4 +- .../add-contributor-dialog.component.ts | 30 +-- ...registered-contributor-dialog.component.ts | 5 +- .../contributors-list.component.ts | 9 +- .../doughnut-chart.component.ts | 4 +- .../education-history-dialog.component.ts | 7 +- .../employment-history-dialog.component.ts | 7 +- .../license/license.component.spec.ts | 4 +- .../components/license/license.component.ts | 12 +- .../line-chart/line-chart.component.ts | 4 +- .../make-decision-dialog.component.ts | 38 +-- .../my-projects-table.component.ts | 6 +- .../password-input-hint.component.ts | 2 +- .../pie-chart/pie-chart.component.ts | 4 +- .../file-secondary-metadata.component.ts | 4 +- .../preprint-secondary-metadata.component.ts | 4 +- .../project-secondary-metadata.component.ts | 4 +- ...gistration-secondary-metadata.component.ts | 4 +- .../user-secondary-metadata.component.ts | 4 +- .../resource-card.component.spec.ts | 6 +- .../resource-card/resource-card.component.ts | 31 ++- .../resource-metadata.component.scss | 5 - .../search-results-container.component.ts | 10 +- .../status-badge/status-badge.component.ts | 1 + src/app/shared/constants/index.ts | 1 + .../constants/resource-card-labels.const.ts | 12 + src/app/shared/mappers/licenses.mapper.ts | 6 +- .../shared/mappers/search/search.mapper.ts | 4 +- src/app/shared/mocks/license.mock.ts | 4 +- src/app/shared/mocks/resource.mock.ts | 6 +- src/app/shared/models/license.model.ts | 2 +- .../shared/models/search/resource.model.ts | 9 +- src/app/shared/services/licenses.service.ts | 4 +- src/app/shared/stores/addons/addons.models.ts | 69 ++++++ src/app/shared/stores/addons/addons.state.ts | 73 +----- .../stores/citations/citations.model.ts | 30 ++- .../stores/citations/citations.state.ts | 35 +-- .../stores/collections/collections.state.ts | 29 +-- .../stores/contributors/contributors.model.ts | 8 +- .../stores/contributors/contributors.state.ts | 30 +-- .../global-search/global-search.model.ts | 6 +- .../global-search/global-search.selectors.ts | 8 +- .../institutions-search.model.ts | 8 + .../institutions-search.state.ts | 14 +- .../shared/stores/licenses/licenses.model.ts | 12 +- .../stores/licenses/licenses.selectors.ts | 4 +- .../shared/stores/licenses/licenses.state.ts | 14 +- .../stores/node-links/node-links.actions.ts | 2 +- .../shared/stores/projects/projects.model.ts | 17 +- .../shared/stores/projects/projects.state.ts | 24 +- .../shared/stores/regions/regions.model.ts | 8 + .../shared/stores/regions/regions.state.ts | 10 +- .../shared/stores/subjects/subjects.model.ts | 18 ++ .../shared/stores/subjects/subjects.state.ts | 26 +- src/app/shared/stores/wiki/wiki.model.ts | 42 ++++ src/app/shared/stores/wiki/wiki.state.ts | 59 +---- 82 files changed, 477 insertions(+), 727 deletions(-) delete mode 100644 src/app/features/registry/services/registry-metadata.service.ts create mode 100644 src/app/shared/constants/resource-card-labels.const.ts diff --git a/src/app/features/collections/components/add-to-collection/project-metadata-step/project-metadata-step.component.ts b/src/app/features/collections/components/add-to-collection/project-metadata-step/project-metadata-step.component.ts index 94d669a26..6fe5c6b1e 100644 --- a/src/app/features/collections/components/add-to-collection/project-metadata-step/project-metadata-step.component.ts +++ b/src/app/features/collections/components/add-to-collection/project-metadata-step/project-metadata-step.component.ts @@ -36,7 +36,7 @@ import { AddToCollectionSelectors } from '@osf/features/collections/store/add-to import { TagsInputComponent, TextInputComponent, TruncatedTextComponent } from '@shared/components'; import { InputLimits } from '@shared/constants'; import { ResourceType } from '@shared/enums'; -import { License } from '@shared/models'; +import { LicenseModel } from '@shared/models'; import { Project } from '@shared/models/projects'; import { InterpolatePipe } from '@shared/pipes'; import { ToastService } from '@shared/services'; @@ -74,14 +74,14 @@ export class ProjectMetadataStepComponent { private readonly toastService = inject(ToastService); private readonly destroyRef = inject(DestroyRef); private readonly formService = inject(ProjectMetadataFormService); - protected readonly currentYear = new Date(); + readonly currentYear = new Date(); - protected readonly ProjectMetadataFormControls = ProjectMetadataFormControls; - protected readonly inputLimits = InputLimits; + readonly ProjectMetadataFormControls = ProjectMetadataFormControls; + readonly inputLimits = InputLimits; - protected readonly selectedProject = select(ProjectsSelectors.getSelectedProject); - protected readonly collectionLicenses = select(AddToCollectionSelectors.getCollectionLicenses); - protected readonly isSelectedProjectUpdateSubmitting = select(ProjectsSelectors.getSelectedProjectUpdateSubmitting); + readonly selectedProject = select(ProjectsSelectors.getSelectedProject); + readonly collectionLicenses = select(AddToCollectionSelectors.getCollectionLicenses); + readonly isSelectedProjectUpdateSubmitting = select(ProjectsSelectors.getSelectedProjectUpdateSubmitting); stepperActiveValue = input.required(); targetStepValue = input.required(); @@ -91,21 +91,21 @@ export class ProjectMetadataStepComponent { stepChange = output(); metadataSaved = output(); - protected actions = createDispatchMap({ + actions = createDispatchMap({ updateCollectionSubmissionMetadata: UpdateProjectMetadata, getAllContributors: GetAllContributors, getCollectionLicenses: GetCollectionLicenses, clearProjects: ClearProjects, }); - protected readonly projectMetadataForm: FormGroup = this.formService.createForm(); - protected readonly projectTags = signal([]); - protected readonly selectedLicense = signal(null); + readonly projectMetadataForm: FormGroup = this.formService.createForm(); + readonly projectTags = signal([]); + readonly selectedLicense = signal(null); private readonly projectMetadataFormValue = toSignal(this.projectMetadataForm.valueChanges); private readonly initialProjectMetadataFormValues = signal(null); - protected readonly projectLicense = computed(() => { + readonly projectLicense = computed(() => { const project = this.selectedProject(); return project ? (this.collectionLicenses().find((license) => license.id === project.licenseId) ?? null) : null; }); @@ -131,7 +131,7 @@ export class ProjectMetadataStepComponent { } handleSelectCollectionLicense(event: SelectChangeEvent): void { - const license = event.value as License; + const license = event.value as LicenseModel; const project = this.selectedProject(); if (!license || !project) return; diff --git a/src/app/features/collections/models/project-metadata-form.model.ts b/src/app/features/collections/models/project-metadata-form.model.ts index bdb1d0073..d9cb52cee 100644 --- a/src/app/features/collections/models/project-metadata-form.model.ts +++ b/src/app/features/collections/models/project-metadata-form.model.ts @@ -1,12 +1,12 @@ import { FormControl } from '@angular/forms'; import { ProjectMetadataFormControls } from '@osf/features/collections/enums'; -import { License } from '@shared/models'; +import { LicenseModel } from '@shared/models'; export interface ProjectMetadataForm { [ProjectMetadataFormControls.Title]: FormControl; [ProjectMetadataFormControls.Description]: FormControl; - [ProjectMetadataFormControls.License]: FormControl; + [ProjectMetadataFormControls.License]: FormControl; [ProjectMetadataFormControls.Tags]: FormControl; [ProjectMetadataFormControls.LicenseYear]: FormControl; [ProjectMetadataFormControls.CopyrightHolders]: FormControl; diff --git a/src/app/features/collections/services/add-to-collection.service.ts b/src/app/features/collections/services/add-to-collection.service.ts index 1e92bb57d..6e4afe441 100644 --- a/src/app/features/collections/services/add-to-collection.service.ts +++ b/src/app/features/collections/services/add-to-collection.service.ts @@ -3,7 +3,7 @@ import { map, Observable } from 'rxjs'; import { inject, Injectable } from '@angular/core'; import { CollectionsMapper, LicensesMapper } from '@shared/mappers'; -import { CollectionSubmissionPayload, License, LicensesResponseJsonApi } from '@shared/models'; +import { CollectionSubmissionPayload, LicenseModel, LicensesResponseJsonApi } from '@shared/models'; import { JsonApiService } from '@shared/services'; import { environment } from 'src/environments/environment'; @@ -15,7 +15,7 @@ export class AddToCollectionService { private apiUrl = environment.apiUrl; private readonly jsonApiService = inject(JsonApiService); - fetchCollectionLicenses(providerId: string): Observable { + fetchCollectionLicenses(providerId: string): Observable { return this.jsonApiService .get(`${this.apiUrl}/providers/collections/${providerId}/licenses/`, { 'page[size]': 100, diff --git a/src/app/features/collections/services/project-metadata-form.service.ts b/src/app/features/collections/services/project-metadata-form.service.ts index 5286a0e69..75fb6e2cf 100644 --- a/src/app/features/collections/services/project-metadata-form.service.ts +++ b/src/app/features/collections/services/project-metadata-form.service.ts @@ -4,7 +4,7 @@ import { FormControl, FormGroup, Validators } from '@angular/forms'; import { ProjectMetadataFormControls } from '@osf/features/collections/enums'; import { ProjectMetadataForm } from '@osf/features/collections/models'; import { CustomValidators } from '@osf/shared/helpers'; -import { License, ProjectMetadataUpdatePayload } from '@shared/models'; +import { LicenseModel, ProjectMetadataUpdatePayload } from '@shared/models'; import { Project } from '@shared/models/projects'; @Injectable({ @@ -40,7 +40,7 @@ export class ProjectMetadataFormService { }); } - updateLicenseValidators(form: FormGroup, license: License): void { + updateLicenseValidators(form: FormGroup, license: LicenseModel): void { const yearControl = form.get(ProjectMetadataFormControls.LicenseYear); const copyrightHoldersControl = form.get(ProjectMetadataFormControls.CopyrightHolders); @@ -56,7 +56,7 @@ export class ProjectMetadataFormService { populateFormFromProject( form: FormGroup, project: Project, - license: License | null + license: LicenseModel | null ): { tags: string[] } { const tags = project.tags || []; @@ -73,7 +73,7 @@ export class ProjectMetadataFormService { return { tags }; } - patchLicenseData(form: FormGroup, license: License, project: Project): void { + patchLicenseData(form: FormGroup, license: LicenseModel, project: Project): void { form.patchValue({ [ProjectMetadataFormControls.License]: license, [ProjectMetadataFormControls.LicenseYear]: diff --git a/src/app/features/collections/store/add-to-collection/add-to-collection.model.ts b/src/app/features/collections/store/add-to-collection/add-to-collection.model.ts index 5db47bc61..422f95e34 100644 --- a/src/app/features/collections/store/add-to-collection/add-to-collection.model.ts +++ b/src/app/features/collections/store/add-to-collection/add-to-collection.model.ts @@ -1,6 +1,6 @@ -import { License } from '@shared/models'; +import { LicenseModel } from '@shared/models'; import { AsyncStateModel } from '@shared/models/store'; export interface AddToCollectionStateModel { - collectionLicenses: AsyncStateModel; + collectionLicenses: AsyncStateModel; } diff --git a/src/app/features/metadata/components/metadata-license/metadata-license.component.ts b/src/app/features/metadata/components/metadata-license/metadata-license.component.ts index a3012dc5f..a51bd19d2 100644 --- a/src/app/features/metadata/components/metadata-license/metadata-license.component.ts +++ b/src/app/features/metadata/components/metadata-license/metadata-license.component.ts @@ -5,7 +5,7 @@ import { Card } from 'primeng/card'; import { ChangeDetectionStrategy, Component, input, output } from '@angular/core'; -import { License } from '@shared/models'; +import { LicenseModel } from '@shared/models'; @Component({ selector: 'osf-metadata-license', @@ -16,5 +16,5 @@ import { License } from '@shared/models'; export class MetadataLicenseComponent { openEditLicenseDialog = output(); hideEditLicense = input(false); - license = input(null); + license = input(null); } diff --git a/src/app/features/metadata/dialogs/license-dialog/license-dialog.component.ts b/src/app/features/metadata/dialogs/license-dialog/license-dialog.component.ts index 9f1b8774a..6d3d62153 100644 --- a/src/app/features/metadata/dialogs/license-dialog/license-dialog.component.ts +++ b/src/app/features/metadata/dialogs/license-dialog/license-dialog.component.ts @@ -9,7 +9,7 @@ import { ChangeDetectionStrategy, Component, inject, OnInit, signal, viewChild } import { Metadata } from '@osf/features/metadata/models'; import { LicenseComponent, LoadingSpinnerComponent } from '@osf/shared/components'; -import { License, LicenseOptions } from '@shared/models'; +import { LicenseModel, LicenseOptions } from '@shared/models'; import { LicensesSelectors, LoadAllLicenses } from '@shared/stores/licenses'; @Component({ @@ -55,7 +55,7 @@ export class LicenseDialogComponent implements OnInit { } } - onSelectLicense(license: License): void { + onSelectLicense(license: LicenseModel): void { this.selectedLicenseId.set(license.id); } diff --git a/src/app/features/metadata/models/metadata.model.ts b/src/app/features/metadata/models/metadata.model.ts index 2a7ebe55b..89733a129 100644 --- a/src/app/features/metadata/models/metadata.model.ts +++ b/src/app/features/metadata/models/metadata.model.ts @@ -1,4 +1,4 @@ -import { ContributorModel, Identifier, Institution, License } from '@osf/shared/models'; +import { ContributorModel, Identifier, Institution, LicenseModel } from '@osf/shared/models'; export interface Metadata { id: string; @@ -8,7 +8,7 @@ export interface Metadata { resourceType?: string; resourceLanguage?: string; publicationDoi?: string; - license: License | null; + license: LicenseModel | null; category?: string; dateCreated: string; dateModified: string; diff --git a/src/app/features/preprints/components/stepper/metadata-step/metadata-step.component.ts b/src/app/features/preprints/components/stepper/metadata-step/metadata-step.component.ts index 091eed446..746473467 100644 --- a/src/app/features/preprints/components/stepper/metadata-step/metadata-step.component.ts +++ b/src/app/features/preprints/components/stepper/metadata-step/metadata-step.component.ts @@ -24,7 +24,7 @@ import { import { CustomValidators, findChangedFields } from '@osf/shared/helpers'; import { IconComponent, LicenseComponent, TagsInputComponent, TextInputComponent } from '@shared/components'; import { INPUT_VALIDATION_MESSAGES } from '@shared/constants'; -import { License, LicenseOptions } from '@shared/models'; +import { LicenseModel, LicenseOptions } from '@shared/models'; import { CustomConfirmationService, ToastService } from '@shared/services'; import { ContributorsComponent } from './contributors/contributors.component'; @@ -64,10 +64,10 @@ export class MetadataStepComponent implements OnInit { saveLicense: SaveLicense, }); - protected metadataForm!: FormGroup; - protected inputLimits = formInputLimits; - protected readonly INPUT_VALIDATION_MESSAGES = INPUT_VALIDATION_MESSAGES; - protected today = new Date(); + metadataForm!: FormGroup; + inputLimits = formInputLimits; + readonly INPUT_VALIDATION_MESSAGES = INPUT_VALIDATION_MESSAGES; + today = new Date(); licenses = select(PreprintStepperSelectors.getLicenses); createdPreprint = select(PreprintStepperSelectors.getPreprint); @@ -129,7 +129,7 @@ export class MetadataStepComponent implements OnInit { this.actions.saveLicense(licenseDetails.id, licenseDetails.licenseOptions); } - selectLicense(license: License) { + selectLicense(license: LicenseModel) { if (license.requiredFields.length) { return; } diff --git a/src/app/features/preprints/models/preprint.models.ts b/src/app/features/preprints/models/preprint.models.ts index 11a7283bd..9349e07b8 100644 --- a/src/app/features/preprints/models/preprint.models.ts +++ b/src/app/features/preprints/models/preprint.models.ts @@ -1,6 +1,6 @@ import { UserPermissions } from '@osf/shared/enums'; import { BooleanOrNull, StringOrNull } from '@osf/shared/helpers'; -import { IdName, License, LicenseOptions } from '@osf/shared/models'; +import { IdName, LicenseModel, LicenseOptions } from '@osf/shared/models'; import { ApplicabilityStatus, PreregLinkInfo, ReviewsState } from '../enums'; @@ -40,7 +40,7 @@ export interface Preprint { preregLinks: string[]; preregLinkInfo: PreregLinkInfo | null; metrics?: PreprintMetrics; - embeddedLicense?: License; + embeddedLicense?: LicenseModel; preprintDoiLink?: string; articleDoiLink?: string; } diff --git a/src/app/features/preprints/services/preprint-licenses.service.ts b/src/app/features/preprints/services/preprint-licenses.service.ts index 68ea35c34..d69c7da83 100644 --- a/src/app/features/preprints/services/preprint-licenses.service.ts +++ b/src/app/features/preprints/services/preprint-licenses.service.ts @@ -10,7 +10,7 @@ import { PreprintRelationshipsJsonApi, } from '@osf/features/preprints/models'; import { LicensesMapper } from '@shared/mappers'; -import { ApiData, License, LicenseOptions, LicensesResponseJsonApi } from '@shared/models'; +import { ApiData, LicenseModel, LicenseOptions, LicensesResponseJsonApi } from '@shared/models'; import { JsonApiService } from '@shared/services'; import { environment } from 'src/environments/environment'; @@ -22,7 +22,7 @@ export class PreprintLicensesService { private apiUrl = environment.apiUrl; private readonly jsonApiService = inject(JsonApiService); - getLicenses(providerId: string): Observable { + getLicenses(providerId: string): Observable { return this.jsonApiService .get(`${this.apiUrl}/providers/preprints/${providerId}/licenses/`, { 'page[size]': 100, diff --git a/src/app/features/preprints/store/preprint-stepper/preprint-stepper.model.ts b/src/app/features/preprints/store/preprint-stepper/preprint-stepper.model.ts index fc7db2382..5e3a6b628 100644 --- a/src/app/features/preprints/store/preprint-stepper/preprint-stepper.model.ts +++ b/src/app/features/preprints/store/preprint-stepper/preprint-stepper.model.ts @@ -2,7 +2,7 @@ import { PreprintFileSource } from '@osf/features/preprints/enums'; import { Preprint, PreprintFilesLinks } from '@osf/features/preprints/models'; import { StringOrNull } from '@shared/helpers'; import { AsyncStateModel, IdName, OsfFile } from '@shared/models'; -import { License } from '@shared/models/license.model'; +import { LicenseModel } from '@shared/models/license.model'; export interface PreprintStepperStateModel { selectedProviderId: StringOrNull; @@ -12,7 +12,7 @@ export interface PreprintStepperStateModel { preprintFiles: AsyncStateModel; availableProjects: AsyncStateModel; projectFiles: AsyncStateModel; - licenses: AsyncStateModel; + licenses: AsyncStateModel; currentFolder: OsfFile | null; preprintProject: AsyncStateModel; hasBeenSubmitted: boolean; diff --git a/src/app/features/project/overview/mappers/project-overview.mapper.ts b/src/app/features/project/overview/mappers/project-overview.mapper.ts index 71028fc32..aee91a847 100644 --- a/src/app/features/project/overview/mappers/project-overview.mapper.ts +++ b/src/app/features/project/overview/mappers/project-overview.mapper.ts @@ -1,5 +1,5 @@ import { InstitutionsMapper } from '@shared/mappers'; -import { License } from '@shared/models'; +import { LicenseModel } from '@shared/models'; import { ProjectOverview, ProjectOverviewGetResponseJsonApi } from '../models'; @@ -26,7 +26,7 @@ export class ProjectOverviewMapper { year: response.attributes.node_license.year, } : undefined, - license: response.embeds.license?.data?.attributes as License, + license: response.embeds.license?.data?.attributes as LicenseModel, doi: response.attributes.doi, publicationDoi: response.attributes.publication_doi, analyticsKey: response.attributes.analytics_key, diff --git a/src/app/features/project/overview/models/project-overview.models.ts b/src/app/features/project/overview/models/project-overview.models.ts index eee1224ef..be943dcc3 100644 --- a/src/app/features/project/overview/models/project-overview.models.ts +++ b/src/app/features/project/overview/models/project-overview.models.ts @@ -5,7 +5,7 @@ import { Institution, InstitutionsJsonApiResponse, JsonApiResponseWithMeta, - License, + LicenseModel, LicensesOption, MetaAnonymousJsonApi, } from '@osf/shared/models'; @@ -35,7 +35,7 @@ export interface ProjectOverview { tags: string[]; accessRequestsEnabled: boolean; nodeLicense?: LicensesOption; - license?: License; + license?: LicenseModel; doi?: string; publicationDoi?: string; storage?: { diff --git a/src/app/features/registries/components/metadata/registries-license/registries-license.component.ts b/src/app/features/registries/components/metadata/registries-license/registries-license.component.ts index 83be58e7e..b45fb5ac5 100644 --- a/src/app/features/registries/components/metadata/registries-license/registries-license.component.ts +++ b/src/app/features/registries/components/metadata/registries-license/registries-license.component.ts @@ -13,7 +13,7 @@ import { FetchLicenses, RegistriesSelectors, SaveLicense } from '@osf/features/r import { LicenseComponent } from '@osf/shared/components'; import { INPUT_VALIDATION_MESSAGES, InputLimits } from '@osf/shared/constants'; import { CustomValidators } from '@osf/shared/helpers'; -import { License, LicenseOptions } from '@osf/shared/models'; +import { LicenseModel, LicenseOptions } from '@osf/shared/models'; import { environment } from 'src/environments/environment'; @@ -31,12 +31,12 @@ export class RegistriesLicenseComponent { private readonly draftId = this.route.snapshot.params['id']; private readonly fb = inject(FormBuilder); - protected actions = createDispatchMap({ fetchLicenses: FetchLicenses, saveLicense: SaveLicense }); - protected licenses = select(RegistriesSelectors.getLicenses); - protected inputLimits = InputLimits; + actions = createDispatchMap({ fetchLicenses: FetchLicenses, saveLicense: SaveLicense }); + licenses = select(RegistriesSelectors.getLicenses); + inputLimits = InputLimits; - protected selectedLicense = select(RegistriesSelectors.getSelectedLicense); - protected draftRegistration = select(RegistriesSelectors.getDraftRegistration); + selectedLicense = select(RegistriesSelectors.getSelectedLicense); + draftRegistration = select(RegistriesSelectors.getDraftRegistration); currentYear = new Date(); licenseYear = this.currentYear; @@ -72,7 +72,7 @@ export class RegistriesLicenseComponent { this.actions.saveLicense(this.draftId, licenseDetails.id, licenseDetails.licenseOptions); } - selectLicense(license: License) { + selectLicense(license: LicenseModel) { if (license.requiredFields.length) { return; } diff --git a/src/app/features/registries/mappers/licenses.mapper.ts b/src/app/features/registries/mappers/licenses.mapper.ts index 27e12fd9a..8072bc716 100644 --- a/src/app/features/registries/mappers/licenses.mapper.ts +++ b/src/app/features/registries/mappers/licenses.mapper.ts @@ -1,7 +1,7 @@ -import { License, LicensesResponseJsonApi } from '@osf/shared/models'; +import { LicenseModel, LicensesResponseJsonApi } from '@osf/shared/models'; export class LicensesMapper { - static fromLicensesResponse(response: LicensesResponseJsonApi): License[] { + static fromLicensesResponse(response: LicensesResponseJsonApi): LicenseModel[] { return response.data.map((item) => ({ id: item.id, name: item.attributes.name, diff --git a/src/app/features/registries/services/licenses.service.ts b/src/app/features/registries/services/licenses.service.ts index 2b35cb689..50091bd4a 100644 --- a/src/app/features/registries/services/licenses.service.ts +++ b/src/app/features/registries/services/licenses.service.ts @@ -7,7 +7,7 @@ import { CreateRegistrationPayloadJsonApi, DraftRegistrationDataJsonApi, DraftRegistrationModel, - License, + LicenseModel, LicenseOptions, LicensesResponseJsonApi, } from '@osf/shared/models'; @@ -24,7 +24,7 @@ export class LicensesService { private apiUrl = environment.apiUrl; private readonly jsonApiService = inject(JsonApiService); - getLicenses(providerId: string): Observable { + getLicenses(providerId: string): Observable { return this.jsonApiService .get(`${this.apiUrl}/providers/registrations/${providerId}/licenses/`, { params: { diff --git a/src/app/features/registries/store/registries.model.ts b/src/app/features/registries/store/registries.model.ts index fbcb38242..4ebee0edb 100644 --- a/src/app/features/registries/store/registries.model.ts +++ b/src/app/features/registries/store/registries.model.ts @@ -2,12 +2,12 @@ import { AsyncStateModel, AsyncStateWithTotalCount, DraftRegistrationModel, - License, + LicenseModel, OsfFile, PageSchema, RegistrationCard, RegistrationModel, - Resource, + ResourceModel, SchemaResponse, } from '@shared/models'; @@ -18,8 +18,8 @@ export interface RegistriesStateModel { projects: AsyncStateModel; draftRegistration: AsyncStateModel; registration: AsyncStateModel; - registries: AsyncStateModel; - licenses: AsyncStateModel; + registries: AsyncStateModel; + licenses: AsyncStateModel; pagesSchema: AsyncStateModel; stepsValidation: Record; draftRegistrations: AsyncStateWithTotalCount; diff --git a/src/app/features/registries/store/registries.selectors.ts b/src/app/features/registries/store/registries.selectors.ts index ba24b69d2..57772458d 100644 --- a/src/app/features/registries/store/registries.selectors.ts +++ b/src/app/features/registries/store/registries.selectors.ts @@ -2,12 +2,12 @@ import { Selector } from '@ngxs/store'; import { DraftRegistrationModel, - License, + LicenseModel, OsfFile, PageSchema, RegistrationCard, RegistrationModel, - Resource, + ResourceModel, SchemaResponse, } from '@shared/models'; @@ -58,7 +58,7 @@ export class RegistriesSelectors { } @Selector([RegistriesState]) - static getRegistries(state: RegistriesStateModel): Resource[] { + static getRegistries(state: RegistriesStateModel): ResourceModel[] { return state.registries.data; } @@ -68,7 +68,7 @@ export class RegistriesSelectors { } @Selector([RegistriesState]) - static getLicenses(state: RegistriesStateModel): License[] { + static getLicenses(state: RegistriesStateModel): LicenseModel[] { return state.licenses.data; } @@ -78,7 +78,7 @@ export class RegistriesSelectors { } @Selector([RegistriesState]) - static getRegistrationLicense(state: RegistriesStateModel): License | null { + static getRegistrationLicense(state: RegistriesStateModel): LicenseModel | null { return state.licenses.data.find((l) => l.id === state.draftRegistration.data?.license.id) || null; } diff --git a/src/app/features/registry/mappers/registry-metadata.mapper.ts b/src/app/features/registry/mappers/registry-metadata.mapper.ts index 9a7250f15..594ba27b7 100644 --- a/src/app/features/registry/mappers/registry-metadata.mapper.ts +++ b/src/app/features/registry/mappers/registry-metadata.mapper.ts @@ -1,7 +1,7 @@ import { ProjectOverviewContributor } from '@osf/features/project/overview/models'; import { ReviewPermissionsMapper } from '@osf/shared/mappers'; import { RegistrationReviewStates, RegistryStatus, RevisionReviewStates } from '@shared/enums'; -import { License, ProviderDataJsonApi } from '@shared/models'; +import { LicenseModel, ProviderDataJsonApi } from '@shared/models'; import { BibliographicContributor, @@ -37,7 +37,7 @@ export class RegistryMetadataMapper { }); } - let license: License | undefined; + let license: LicenseModel | undefined; let licenseUrl: string | undefined; if (embeds && embeds['license']) { diff --git a/src/app/features/registry/models/registry-overview.models.ts b/src/app/features/registry/models/registry-overview.models.ts index 1785d38c8..778b13fad 100644 --- a/src/app/features/registry/models/registry-overview.models.ts +++ b/src/app/features/registry/models/registry-overview.models.ts @@ -2,7 +2,7 @@ import { ProjectOverviewContributor } from '@osf/features/project/overview/model import { RegistrationQuestions, RegistrySubject } from '@osf/features/registry/models'; import { IdTypeModel, - License, + LicenseModel, LicensesOption, MetaAnonymousJsonApi, ProviderModel, @@ -30,7 +30,7 @@ export interface RegistryOverview { isFork: boolean; accessRequestsEnabled: boolean; nodeLicense?: LicensesOption; - license?: License; + license?: LicenseModel; licenseUrl?: string; identifiers?: { id: string; diff --git a/src/app/features/registry/services/registry-metadata.service.ts b/src/app/features/registry/services/registry-metadata.service.ts deleted file mode 100644 index c472629b7..000000000 --- a/src/app/features/registry/services/registry-metadata.service.ts +++ /dev/null @@ -1,223 +0,0 @@ -import { Observable } from 'rxjs'; -import { map } from 'rxjs/operators'; - -import { inject, Injectable } from '@angular/core'; - -import { - CedarMetadataRecord, - CedarMetadataRecordJsonApi, - CedarMetadataTemplateJsonApi, -} from '@osf/features/project/metadata/models'; -import { JsonApiService } from '@osf/shared/services'; -import { InstitutionsMapper } from '@shared/mappers'; -import { Institution, InstitutionsJsonApiResponse, License } from '@shared/models'; - -import { RegistryMetadataMapper } from '../mappers'; -import { - BibliographicContributor, - BibliographicContributorsJsonApi, - CustomItemMetadataRecord, - CustomItemMetadataResponse, - RegistryContributorAddRequest, - RegistryContributorJsonApiResponse, - RegistryContributorUpdateRequest, - RegistryOverview, - RegistrySubjectsJsonApi, - UserInstitutionsResponse, -} from '../models'; - -import { environment } from 'src/environments/environment'; - -@Injectable({ - providedIn: 'root', -}) -export class RegistryMetadataService { - private readonly jsonApiService = inject(JsonApiService); - private readonly apiUrl = environment.apiUrl; - - getBibliographicContributors(registryId: string, page = 1, pageSize = 100): Observable { - const params: Record = { - 'fields[contributors]': 'index,users', - 'fields[users]': 'full_name', - page: page, - 'page[size]': pageSize, - }; - - return this.jsonApiService - .get( - `${this.apiUrl}/registrations/${registryId}/bibliographic_contributors/`, - params - ) - .pipe(map((response) => RegistryMetadataMapper.mapBibliographicContributors(response))); - } - - getCustomItemMetadata(guid: string): Observable { - return this.jsonApiService.get(`${this.apiUrl}/custom_item_metadata_records/${guid}/`); - } - - updateCustomItemMetadata(guid: string, metadata: CustomItemMetadataRecord): Observable { - return this.jsonApiService.patch( - `${this.apiUrl}/custom_item_metadata_records/${guid}/`, - { - data: { - id: guid, - type: 'custom-item-metadata-records', - attributes: metadata, - relationships: {}, - }, - } - ); - } - - getRegistryForMetadata(registryId: string): Observable { - const params: Record = { - 'embed[]': ['contributors', 'affiliated_institutions', 'identifiers', 'license', 'subjects_acceptable'], - 'fields[institutions]': 'assets,description,name', - 'fields[users]': 'family_name,full_name,given_name,middle_name', - 'fields[subjects]': 'text,taxonomy', - }; - - return this.jsonApiService - .get<{ data: Record }>(`${environment.apiUrl}/registrations/${registryId}/`, params) - .pipe(map((response) => RegistryMetadataMapper.fromMetadataApiResponse(response.data))); - } - - updateRegistryDetails(registryId: string, updates: Partial>): Observable { - const payload = { - data: { - id: registryId, - type: 'registrations', - attributes: updates, - }, - }; - - return this.jsonApiService - .patch>(`${this.apiUrl}/registrations/${registryId}`, payload) - .pipe(map((response) => RegistryMetadataMapper.fromMetadataApiResponse(response))); - } - - getUserInstitutions(userId: string, page = 1, pageSize = 10): Observable { - const params = { - page: page.toString(), - 'page[size]': pageSize.toString(), - }; - - return this.jsonApiService.get(`${this.apiUrl}/users/${userId}/institutions/`, { - params, - }); - } - - getRegistrySubjects(registryId: string, page = 1, pageSize = 100): Observable { - const params: Record = { - 'page[size]': pageSize, - page: page, - }; - - return this.jsonApiService.get( - `${this.apiUrl}/registrations/${registryId}/subjects/`, - params - ); - } - - getRegistryCedarMetadataRecords(registryId: string): Observable { - const params: Record = { - embed: 'template', - 'page[size]': 20, - }; - - return this.jsonApiService.get( - `${this.apiUrl}/registrations/${registryId}/cedar_metadata_records/`, - params - ); - } - - getCedarMetadataTemplates(url?: string): Observable { - return this.jsonApiService.get( - url || `${environment.apiDomainUrl}/_/cedar_metadata_templates/?adapterOptions[sort]=schema_name` - ); - } - - createCedarMetadataRecord(data: CedarMetadataRecord): Observable { - return this.jsonApiService.post(`${environment.apiDomainUrl}/_/cedar_metadata_records/`, data); - } - - updateCedarMetadataRecord(data: CedarMetadataRecord, recordId: string): Observable { - return this.jsonApiService.patch( - `${environment.apiDomainUrl}/_/cedar_metadata_records/${recordId}/`, - data - ); - } - - updateRegistrySubjects( - registryId: string, - subjects: { type: string; id: string }[] - ): Observable<{ data: { type: string; id: string }[] }> { - return this.jsonApiService.patch<{ data: { type: string; id: string }[] }>( - `${this.apiUrl}/registrations/${registryId}/relationships/subjects/`, - { - data: subjects, - } - ); - } - - updateRegistryInstitutions( - registryId: string, - institutions: { type: string; id: string }[] - ): Observable<{ data: { type: string; id: string }[] }> { - return this.jsonApiService.patch<{ data: { type: string; id: string }[] }>( - `${this.apiUrl}/registrations/${registryId}/relationships/institutions/`, - { - data: institutions, - } - ); - } - - getLicenseFromUrl(licenseUrl: string): Observable { - return this.jsonApiService.get<{ data: Record }>(licenseUrl).pipe( - map((response) => { - const licenseData = response.data; - const attributes = licenseData['attributes'] as Record; - - return { - id: licenseData['id'] as string, - name: attributes['name'] as string, - text: attributes['text'] as string, - url: attributes['url'] as string, - requiredFields: (attributes['required_fields'] as string[]) || [], - } as License; - }) - ); - } - - getRegistryInstitutions(registryId: string, page = 1, pageSize = 100): Observable { - const params: Record = { - page: page, - 'page[size]': pageSize, - }; - - return this.jsonApiService - .get(`${this.apiUrl}/registrations/${registryId}/institutions/`, params) - .pipe(map((response) => InstitutionsMapper.fromInstitutionsResponse(response))); - } - - updateRegistryContributor( - registryId: string, - contributorId: string, - updateData: RegistryContributorUpdateRequest - ): Observable { - return this.jsonApiService.patch( - `${this.apiUrl}/registrations/${registryId}/contributors/${contributorId}/`, - updateData - ); - } - - addRegistryContributor( - registryId: string, - contributorData: RegistryContributorAddRequest - ): Observable { - return this.jsonApiService.post( - `${this.apiUrl}/registrations/${registryId}/contributors/`, - contributorData - ); - } -} diff --git a/src/app/features/settings/tokens/pages/tokens-list/tokens-list.component.ts b/src/app/features/settings/tokens/pages/tokens-list/tokens-list.component.ts index 12b081d8d..46c794d28 100644 --- a/src/app/features/settings/tokens/pages/tokens-list/tokens-list.component.ts +++ b/src/app/features/settings/tokens/pages/tokens-list/tokens-list.component.ts @@ -26,7 +26,7 @@ export class TokensListComponent implements OnInit { private readonly customConfirmationService = inject(CustomConfirmationService); private readonly toastService = inject(ToastService); - protected readonly isLoading = select(TokensSelectors.isTokensLoading); + readonly isLoading = select(TokensSelectors.isTokensLoading); tokens = select(TokensSelectors.getTokens); diff --git a/src/app/shared/components/addons/addon-card/addon-card.component.ts b/src/app/shared/components/addons/addon-card/addon-card.component.ts index eddb6a78f..f2818d02e 100644 --- a/src/app/shared/components/addons/addon-card/addon-card.component.ts +++ b/src/app/shared/components/addons/addon-card/addon-card.component.ts @@ -28,12 +28,8 @@ export class AddonCardComponent { readonly cardButtonLabel = input(''); readonly showDangerButton = input(false); - protected readonly addonTypeString = computed(() => { - return getAddonTypeString(this.card()); - }); - protected readonly isConfiguredAddon = computed(() => { - return isConfiguredAddon(this.card()); - }); + readonly addonTypeString = computed(() => getAddonTypeString(this.card())); + readonly isConfiguredAddon = computed(() => isConfiguredAddon(this.card())); onConnectAddon(): void { const addon = this.card(); diff --git a/src/app/shared/components/addons/addon-terms/addon-terms.component.ts b/src/app/shared/components/addons/addon-terms/addon-terms.component.ts index 3dca0178d..c1888d4e6 100644 --- a/src/app/shared/components/addons/addon-terms/addon-terms.component.ts +++ b/src/app/shared/components/addons/addon-terms/addon-terms.component.ts @@ -17,7 +17,7 @@ import { AddonModel, AddonTerm, AuthorizedAccountModel } from '@shared/models'; }) export class AddonTermsComponent { addon = input(null); - protected terms = computed(() => { + terms = computed(() => { const addon = this.addon(); if (!addon) { return []; diff --git a/src/app/shared/components/addons/folder-selector/folder-selector.component.ts b/src/app/shared/components/addons/folder-selector/folder-selector.component.ts index 115ac1739..3aae2cca9 100644 --- a/src/app/shared/components/addons/folder-selector/folder-selector.component.ts +++ b/src/app/shared/components/addons/folder-selector/folder-selector.component.ts @@ -27,8 +27,8 @@ import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { FormControl, FormsModule, ReactiveFormsModule } from '@angular/forms'; import { OperationNames } from '@osf/features/project/addons/enums'; -import { OperationInvokeData, StorageItemModel } from '@shared/models'; -import { AddonsSelectors } from '@shared/stores/addons'; +import { OperationInvokeData, StorageItemModel } from '@osf/shared/models'; +import { AddonsSelectors } from '@osf/shared/stores'; import { GoogleFilePickerComponent } from './google-file-picker/google-file-picker.component'; @@ -65,15 +65,15 @@ export class FolderSelectorComponent implements OnInit { operationInvoke = output(); save = output(); cancelSelection = output(); - protected readonly OperationNames = OperationNames; - protected hasInputChanged = signal(false); - protected hasFolderChanged = signal(false); + readonly OperationNames = OperationNames; + hasInputChanged = signal(false); + hasFolderChanged = signal(false); public selectedRootFolder = signal(null); - protected breadcrumbItems = signal([]); - protected initiallySelectedFolder = select(AddonsSelectors.getSelectedFolder); - protected isOperationInvocationSubmitting = select(AddonsSelectors.getOperationInvocationSubmitting); - protected isSubmitting = select(AddonsSelectors.getCreatedOrUpdatedConfiguredAddonSubmitting); - protected readonly homeBreadcrumb: MenuItem = { + breadcrumbItems = signal([]); + initiallySelectedFolder = select(AddonsSelectors.getSelectedFolder); + isOperationInvocationSubmitting = select(AddonsSelectors.getOperationInvocationSubmitting); + isSubmitting = select(AddonsSelectors.getCreatedOrUpdatedConfiguredAddonSubmitting); + readonly homeBreadcrumb: MenuItem = { id: '/', label: this.translateService.instant('settings.addons.configureAddon.home'), state: { @@ -98,11 +98,11 @@ export class FolderSelectorComponent implements OnInit { }); } - protected readonly isFormValid = computed(() => { + readonly isFormValid = computed(() => { return this.isCreateMode() ? this.hasFolderChanged() : this.hasInputChanged() || this.hasFolderChanged(); }); - protected handleCreateOperationInvocation( + handleCreateOperationInvocation( operationName: OperationNames, itemId: string, itemName?: string, @@ -118,12 +118,12 @@ export class FolderSelectorComponent implements OnInit { this.trimBreadcrumbs(itemId); } - protected handleSave(): void { + handleSave(): void { this.selectedRootFolderId.set(this.selectedRootFolder()?.itemId || ''); this.save.emit(); } - protected handleCancel(): void { + handleCancel(): void { this.cancelSelection.emit(); } diff --git a/src/app/shared/components/bar-chart/bar-chart.component.ts b/src/app/shared/components/bar-chart/bar-chart.component.ts index c0ea0ba43..e47946b32 100644 --- a/src/app/shared/components/bar-chart/bar-chart.component.ts +++ b/src/app/shared/components/bar-chart/bar-chart.component.ts @@ -49,8 +49,8 @@ export class BarChartComponent implements OnInit { orientation = input<'horizontal' | 'vertical'>('horizontal'); showExpandedSection = input(false); - protected options = signal({}); - protected data = signal({} as ChartData); + options = signal({}); + data = signal({} as ChartData); platformId = inject(PLATFORM_ID); cd = inject(ChangeDetectorRef); diff --git a/src/app/shared/components/contributors/add-contributor-dialog/add-contributor-dialog.component.ts b/src/app/shared/components/contributors/add-contributor-dialog/add-contributor-dialog.component.ts index 71845666c..6c497e4b8 100644 --- a/src/app/shared/components/contributors/add-contributor-dialog/add-contributor-dialog.component.ts +++ b/src/app/shared/components/contributors/add-contributor-dialog/add-contributor-dialog.component.ts @@ -13,11 +13,13 @@ import { ChangeDetectionStrategy, Component, DestroyRef, inject, OnDestroy, OnIn import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { FormControl, FormsModule } from '@angular/forms'; -import { CustomPaginatorComponent, LoadingSpinnerComponent, SearchInputComponent } from '@osf/shared/components'; -import { AddContributorType, AddDialogState } from '@osf/shared/enums/contributors'; +import { AddContributorType, AddDialogState } from '@osf/shared/enums'; import { ContributorAddModel, ContributorDialogAddModel } from '@osf/shared/models'; import { ClearUsers, ContributorsSelectors, SearchUsers } from '@osf/shared/stores'; +import { CustomPaginatorComponent } from '../../custom-paginator/custom-paginator.component'; +import { LoadingSpinnerComponent } from '../../loading-spinner/loading-spinner.component'; +import { SearchInputComponent } from '../../search-input/search-input.component'; import { AddContributorItemComponent } from '../add-contributor-item/add-contributor-item.component'; @Component({ @@ -37,24 +39,24 @@ import { AddContributorItemComponent } from '../add-contributor-item/add-contrib changeDetection: ChangeDetectionStrategy.OnPush, }) export class AddContributorDialogComponent implements OnInit, OnDestroy { - protected dialogRef = inject(DynamicDialogRef); + dialogRef = inject(DynamicDialogRef); private readonly destroyRef = inject(DestroyRef); readonly config = inject(DynamicDialogConfig); - protected users = select(ContributorsSelectors.getUsers); - protected isLoading = select(ContributorsSelectors.isUsersLoading); - protected totalUsersCount = select(ContributorsSelectors.getUsersTotalCount); - protected isInitialState = signal(true); + users = select(ContributorsSelectors.getUsers); + isLoading = select(ContributorsSelectors.isUsersLoading); + totalUsersCount = select(ContributorsSelectors.getUsersTotalCount); + isInitialState = signal(true); - protected currentState = signal(AddDialogState.Search); - protected currentPage = signal(1); - protected first = signal(0); - protected pageSize = signal(10); + currentState = signal(AddDialogState.Search); + currentPage = signal(1); + first = signal(0); + pageSize = signal(10); - protected selectedUsers = signal([]); - protected searchControl = new FormControl(''); + selectedUsers = signal([]); + searchControl = new FormControl(''); - protected actions = createDispatchMap({ searchUsers: SearchUsers, clearUsers: ClearUsers }); + actions = createDispatchMap({ searchUsers: SearchUsers, clearUsers: ClearUsers }); get isSearchState() { return this.currentState() === AddDialogState.Search; diff --git a/src/app/shared/components/contributors/add-unregistered-contributor-dialog/add-unregistered-contributor-dialog.component.ts b/src/app/shared/components/contributors/add-unregistered-contributor-dialog/add-unregistered-contributor-dialog.component.ts index 0f11ef454..e47f70cc8 100644 --- a/src/app/shared/components/contributors/add-unregistered-contributor-dialog/add-unregistered-contributor-dialog.component.ts +++ b/src/app/shared/components/contributors/add-unregistered-contributor-dialog/add-unregistered-contributor-dialog.component.ts @@ -6,12 +6,13 @@ import { DynamicDialogRef } from 'primeng/dynamicdialog'; import { ChangeDetectionStrategy, Component, inject } from '@angular/core'; import { FormControl, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms'; -import { TextInputComponent } from '@osf/shared/components'; import { InputLimits } from '@osf/shared/constants'; -import { AddContributorType, ContributorPermission } from '@osf/shared/enums/contributors'; +import { AddContributorType, ContributorPermission } from '@osf/shared/enums'; import { CustomValidators } from '@osf/shared/helpers'; import { ContributorAddModel, ContributorDialogAddModel, UnregisteredContributorForm } from '@osf/shared/models'; +import { TextInputComponent } from '../../text-input/text-input.component'; + @Component({ selector: 'osf-add-unregistered-contributor-dialog', imports: [Button, ReactiveFormsModule, TranslatePipe, TextInputComponent], diff --git a/src/app/shared/components/contributors/contributors-list/contributors-list.component.ts b/src/app/shared/components/contributors/contributors-list/contributors-list.component.ts index 9bc8c42eb..d751ab5c0 100644 --- a/src/app/shared/components/contributors/contributors-list/contributors-list.component.ts +++ b/src/app/shared/components/contributors/contributors-list/contributors-list.component.ts @@ -10,14 +10,13 @@ import { Tooltip } from 'primeng/tooltip'; import { ChangeDetectionStrategy, Component, inject, input, output, signal } from '@angular/core'; import { FormsModule } from '@angular/forms'; -import { - EducationHistoryDialogComponent, - EmploymentHistoryDialogComponent, - SelectComponent, -} from '@osf/shared/components'; import { MY_PROJECTS_TABLE_PARAMS, PERMISSION_OPTIONS } from '@osf/shared/constants'; import { ContributorModel, SelectOption, TableParameters } from '@osf/shared/models'; +import { EducationHistoryDialogComponent } from '../../education-history-dialog/education-history-dialog.component'; +import { EmploymentHistoryDialogComponent } from '../../employment-history-dialog/employment-history-dialog.component'; +import { SelectComponent } from '../../select/select.component'; + @Component({ selector: 'osf-contributors-list', imports: [TranslatePipe, FormsModule, TableModule, Tooltip, Checkbox, Skeleton, Button, SelectComponent], diff --git a/src/app/shared/components/doughnut-chart/doughnut-chart.component.ts b/src/app/shared/components/doughnut-chart/doughnut-chart.component.ts index 928a18898..718d71c16 100644 --- a/src/app/shared/components/doughnut-chart/doughnut-chart.component.ts +++ b/src/app/shared/components/doughnut-chart/doughnut-chart.component.ts @@ -48,8 +48,8 @@ export class DoughnutChartComponent implements OnInit { showLegend = input(false); showExpandedSection = input(false); - protected options = signal({}); - protected data = signal({} as ChartData); + options = signal({}); + data = signal({} as ChartData); ngOnInit() { this.initChart(); diff --git a/src/app/shared/components/education-history-dialog/education-history-dialog.component.ts b/src/app/shared/components/education-history-dialog/education-history-dialog.component.ts index 26870d2dc..f61dc8de4 100644 --- a/src/app/shared/components/education-history-dialog/education-history-dialog.component.ts +++ b/src/app/shared/components/education-history-dialog/education-history-dialog.component.ts @@ -5,9 +5,10 @@ import { DynamicDialogConfig, DynamicDialogRef } from 'primeng/dynamicdialog'; import { ChangeDetectionStrategy, Component, inject, signal } from '@angular/core'; -import { EducationHistoryComponent } from '@osf/shared/components'; import { Education } from '@osf/shared/models'; +import { EducationHistoryComponent } from '../education-history/education-history.component'; + @Component({ selector: 'osf-education-history-dialog', imports: [Button, TranslatePipe, EducationHistoryComponent], @@ -16,9 +17,9 @@ import { Education } from '@osf/shared/models'; changeDetection: ChangeDetectionStrategy.OnPush, }) export class EducationHistoryDialogComponent { - protected dialogRef = inject(DynamicDialogRef); + dialogRef = inject(DynamicDialogRef); private readonly config = inject(DynamicDialogConfig); - protected readonly educationHistory = signal([]); + readonly educationHistory = signal([]); constructor() { this.educationHistory.set(this.config.data); diff --git a/src/app/shared/components/employment-history-dialog/employment-history-dialog.component.ts b/src/app/shared/components/employment-history-dialog/employment-history-dialog.component.ts index 6c924d32a..08d8ab01b 100644 --- a/src/app/shared/components/employment-history-dialog/employment-history-dialog.component.ts +++ b/src/app/shared/components/employment-history-dialog/employment-history-dialog.component.ts @@ -5,9 +5,10 @@ import { DynamicDialogConfig, DynamicDialogRef } from 'primeng/dynamicdialog'; import { ChangeDetectionStrategy, Component, inject, signal } from '@angular/core'; -import { EmploymentHistoryComponent } from '@osf/shared/components'; import { Employment } from '@osf/shared/models'; +import { EmploymentHistoryComponent } from '../employment-history/employment-history.component'; + @Component({ selector: 'osf-employment-history-dialog', imports: [Button, TranslatePipe, EmploymentHistoryComponent], @@ -17,8 +18,8 @@ import { Employment } from '@osf/shared/models'; }) export class EmploymentHistoryDialogComponent { private readonly config = inject(DynamicDialogConfig); - protected dialogRef = inject(DynamicDialogRef); - protected readonly employmentHistory = signal([]); + readonly employmentHistory = signal([]); + dialogRef = inject(DynamicDialogRef); constructor() { this.employmentHistory.set(this.config.data); diff --git a/src/app/shared/components/license/license.component.spec.ts b/src/app/shared/components/license/license.component.spec.ts index d853093c2..b529ca46a 100644 --- a/src/app/shared/components/license/license.component.spec.ts +++ b/src/app/shared/components/license/license.component.spec.ts @@ -4,14 +4,14 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { LicenseComponent, TextInputComponent, TruncatedTextComponent } from '@shared/components'; import { MOCK_LICENSE, TranslateServiceMock } from '@shared/mocks'; -import { License, LicenseOptions } from '@shared/models'; +import { LicenseModel, LicenseOptions } from '@shared/models'; import { InterpolatePipe } from '@shared/pipes'; describe('LicenseComponent', () => { let component: LicenseComponent; let fixture: ComponentFixture; - const mockLicenses: License[] = [ + const mockLicenses: LicenseModel[] = [ { ...MOCK_LICENSE, id: 'license-1', diff --git a/src/app/shared/components/license/license.component.ts b/src/app/shared/components/license/license.component.ts index 0485c5c78..4034674e5 100644 --- a/src/app/shared/components/license/license.component.ts +++ b/src/app/shared/components/license/license.component.ts @@ -11,7 +11,7 @@ import { FormControl, FormGroup, FormsModule, ReactiveFormsModule } from '@angul import { CustomValidators, StringOrNullOrUndefined } from '@osf/shared/helpers'; import { InputLimits } from '@shared/constants'; -import { License, LicenseForm, LicenseOptions } from '@shared/models'; +import { LicenseForm, LicenseModel, LicenseOptions } from '@shared/models'; import { InterpolatePipe } from '@shared/pipes'; import { TextInputComponent } from '../text-input/text-input.component'; @@ -38,14 +38,14 @@ import { TruncatedTextComponent } from '../truncated-text/truncated-text.compone export class LicenseComponent { selectedLicenseId = input(null); selectedLicenseOptions = input(null); - licenses = input.required(); + licenses = input.required(); isSubmitting = input(false); showInternalButtons = input(true); fullWidthSelect = input(false); - selectedLicense = model(null); + selectedLicense = model(null); createLicense = output<{ id: string; licenseOptions: LicenseOptions }>(); - selectLicense = output(); - protected inputLimits = InputLimits; + selectLicense = output(); + inputLimits = InputLimits; saveButtonDisabled = signal(false); currentYear = new Date(); @@ -93,7 +93,7 @@ export class LicenseComponent { }); } - onSelectLicense(license: License): void { + onSelectLicense(license: LicenseModel): void { this.selectLicense.emit(license); } diff --git a/src/app/shared/components/line-chart/line-chart.component.ts b/src/app/shared/components/line-chart/line-chart.component.ts index 0336624ee..fe6ce3438 100644 --- a/src/app/shared/components/line-chart/line-chart.component.ts +++ b/src/app/shared/components/line-chart/line-chart.component.ts @@ -35,8 +35,8 @@ export class LineChartComponent implements OnInit { showLegend = input(false); showGrid = input(false); - protected options = signal({}); - protected data = signal({} as ChartData); + options = signal({}); + data = signal({} as ChartData); platformId = inject(PLATFORM_ID); cd = inject(ChangeDetectorRef); diff --git a/src/app/shared/components/make-decision-dialog/make-decision-dialog.component.ts b/src/app/shared/components/make-decision-dialog/make-decision-dialog.component.ts index 8099eaedf..7183e016c 100644 --- a/src/app/shared/components/make-decision-dialog/make-decision-dialog.component.ts +++ b/src/app/shared/components/make-decision-dialog/make-decision-dialog.component.ts @@ -15,9 +15,9 @@ import { CollectionsModerationSelectors, CreateCollectionSubmissionAction, } from '@osf/features/moderation/store/collections-moderation'; +import { ModerationDecisionFormControls, ModerationSubmitType } from '@osf/shared/enums'; import { DateAgoPipe } from '@osf/shared/pipes'; -import { ModerationDecisionFormControls, ModerationSubmitType } from '@shared/enums'; -import { CollectionsSelectors } from '@shared/stores'; +import { CollectionsSelectors } from '@osf/shared/stores'; @Component({ selector: 'osf-make-decision-dialog', @@ -28,37 +28,37 @@ import { CollectionsSelectors } from '@shared/stores'; }) export class MakeDecisionDialogComponent implements OnInit { private readonly fb = inject(FormBuilder); - protected readonly config = inject(DynamicDialogConfig); - protected readonly dialogRef = inject(DynamicDialogRef); - protected readonly ModerationSubmitType = ModerationSubmitType; - protected readonly SubmissionReviewStatus = SubmissionReviewStatus; - protected readonly ModerationDecisionFormControls = ModerationDecisionFormControls; - protected collectionProvider = select(CollectionsSelectors.getCollectionProvider); - protected currentReviewAction = select(CollectionsModerationSelectors.getCurrentReviewAction); - - protected isSubmitting = select(CollectionsModerationSelectors.getCollectionSubmissionSubmitting); - protected requestForm!: FormGroup; - - protected actions = createDispatchMap({ + readonly config = inject(DynamicDialogConfig); + readonly dialogRef = inject(DynamicDialogRef); + readonly ModerationSubmitType = ModerationSubmitType; + readonly SubmissionReviewStatus = SubmissionReviewStatus; + readonly ModerationDecisionFormControls = ModerationDecisionFormControls; + collectionProvider = select(CollectionsSelectors.getCollectionProvider); + currentReviewAction = select(CollectionsModerationSelectors.getCurrentReviewAction); + + isSubmitting = select(CollectionsModerationSelectors.getCollectionSubmissionSubmitting); + requestForm!: FormGroup; + + actions = createDispatchMap({ createSubmissionAction: CreateCollectionSubmissionAction, }); - protected isHybridModeration = computed(() => { + isHybridModeration = computed(() => { const provider = this.collectionProvider(); return provider?.reviewsWorkflow === ModerationType.Hybrid || !provider?.reviewsWorkflow; }); - protected isPreModeration = computed(() => { + isPreModeration = computed(() => { const provider = this.collectionProvider(); return provider?.reviewsWorkflow === ModerationType.Pre; }); - protected isPostModeration = computed(() => { + isPostModeration = computed(() => { const provider = this.collectionProvider(); return provider?.reviewsWorkflow === ModerationType.Post; }); - protected isPendingStatus = computed(() => { + isPendingStatus = computed(() => { return this.currentReviewAction()?.toState === SubmissionReviewStatus.Pending; }); @@ -66,7 +66,7 @@ export class MakeDecisionDialogComponent implements OnInit { this.initForm(); } - protected handleSubmission(): void { + handleSubmission(): void { const targetId = this.currentReviewAction()?.targetId; if (this.requestForm.valid && targetId) { const formData = this.requestForm.value; diff --git a/src/app/shared/components/my-projects-table/my-projects-table.component.ts b/src/app/shared/components/my-projects-table/my-projects-table.component.ts index f553444df..2413698b8 100644 --- a/src/app/shared/components/my-projects-table/my-projects-table.component.ts +++ b/src/app/shared/components/my-projects-table/my-projects-table.component.ts @@ -36,15 +36,15 @@ export class MyProjectsTableComponent { skeletonData: MyResourcesItem[] = Array.from({ length: 10 }, () => ({}) as MyResourcesItem); - protected onPageChange(event: TablePageEvent): void { + onPageChange(event: TablePageEvent): void { this.pageChange.emit(event); } - protected onSort(event: SortEvent): void { + onSort(event: SortEvent): void { this.sort.emit(event); } - protected onItemClick(item: MyResourcesItem): void { + onItemClick(item: MyResourcesItem): void { this.itemClick.emit(item); } } diff --git a/src/app/shared/components/password-input-hint/password-input-hint.component.ts b/src/app/shared/components/password-input-hint/password-input-hint.component.ts index 3fda421ca..14a2f865d 100644 --- a/src/app/shared/components/password-input-hint/password-input-hint.component.ts +++ b/src/app/shared/components/password-input-hint/password-input-hint.component.ts @@ -2,7 +2,7 @@ import { TranslatePipe } from '@ngx-translate/core'; import { ChangeDetectionStrategy, Component, input } from '@angular/core'; -import { BooleanOrNullOrUndefined } from '@osf/shared/helpers/types.helper'; +import { BooleanOrNullOrUndefined } from '@osf/shared/helpers'; @Component({ selector: 'osf-password-input-hint', diff --git a/src/app/shared/components/pie-chart/pie-chart.component.ts b/src/app/shared/components/pie-chart/pie-chart.component.ts index d71bc015d..88144f29c 100644 --- a/src/app/shared/components/pie-chart/pie-chart.component.ts +++ b/src/app/shared/components/pie-chart/pie-chart.component.ts @@ -35,8 +35,8 @@ export class PieChartComponent implements OnInit { datasets = input([]); showLegend = input(false); - protected options = signal({}); - protected data = signal({} as ChartData); + options = signal({}); + data = signal({} as ChartData); platformId = inject(PLATFORM_ID); cd = inject(ChangeDetectorRef); diff --git a/src/app/shared/components/resource-card/components/file-secondary-metadata/file-secondary-metadata.component.ts b/src/app/shared/components/resource-card/components/file-secondary-metadata/file-secondary-metadata.component.ts index fe4c66819..f015564bf 100644 --- a/src/app/shared/components/resource-card/components/file-secondary-metadata/file-secondary-metadata.component.ts +++ b/src/app/shared/components/resource-card/components/file-secondary-metadata/file-secondary-metadata.component.ts @@ -2,7 +2,7 @@ import { TranslatePipe } from '@ngx-translate/core'; import { ChangeDetectionStrategy, Component, input } from '@angular/core'; -import { Resource } from '@shared/models'; +import { ResourceModel } from '@shared/models'; @Component({ selector: 'osf-file-secondary-metadata', @@ -12,5 +12,5 @@ import { Resource } from '@shared/models'; changeDetection: ChangeDetectionStrategy.OnPush, }) export class FileSecondaryMetadataComponent { - resource = input.required(); + resource = input.required(); } diff --git a/src/app/shared/components/resource-card/components/preprint-secondary-metadata/preprint-secondary-metadata.component.ts b/src/app/shared/components/resource-card/components/preprint-secondary-metadata/preprint-secondary-metadata.component.ts index f19c1e182..aaac6b0f7 100644 --- a/src/app/shared/components/resource-card/components/preprint-secondary-metadata/preprint-secondary-metadata.component.ts +++ b/src/app/shared/components/resource-card/components/preprint-secondary-metadata/preprint-secondary-metadata.component.ts @@ -2,7 +2,7 @@ import { TranslatePipe } from '@ngx-translate/core'; import { ChangeDetectionStrategy, Component, input } from '@angular/core'; -import { Resource } from '@shared/models'; +import { ResourceModel } from '@shared/models'; @Component({ selector: 'osf-preprint-secondary-metadata', @@ -12,5 +12,5 @@ import { Resource } from '@shared/models'; changeDetection: ChangeDetectionStrategy.OnPush, }) export class PreprintSecondaryMetadataComponent { - resource = input.required(); + resource = input.required(); } diff --git a/src/app/shared/components/resource-card/components/project-secondary-metadata/project-secondary-metadata.component.ts b/src/app/shared/components/resource-card/components/project-secondary-metadata/project-secondary-metadata.component.ts index 853781312..49eebe9f3 100644 --- a/src/app/shared/components/resource-card/components/project-secondary-metadata/project-secondary-metadata.component.ts +++ b/src/app/shared/components/resource-card/components/project-secondary-metadata/project-secondary-metadata.component.ts @@ -3,7 +3,7 @@ import { TranslatePipe } from '@ngx-translate/core'; import { ChangeDetectionStrategy, Component, computed, input } from '@angular/core'; import { languageCodes } from '@shared/constants'; -import { Resource } from '@shared/models'; +import { ResourceModel } from '@shared/models'; @Component({ selector: 'osf-project-secondary-metadata', @@ -13,7 +13,7 @@ import { Resource } from '@shared/models'; changeDetection: ChangeDetectionStrategy.OnPush, }) export class ProjectSecondaryMetadataComponent { - resource = input.required(); + resource = input.required(); languageFromCode = computed(() => { const resourceLanguage = this.resource().language; diff --git a/src/app/shared/components/resource-card/components/registration-secondary-metadata/registration-secondary-metadata.component.ts b/src/app/shared/components/resource-card/components/registration-secondary-metadata/registration-secondary-metadata.component.ts index 5580b53fe..b5a610a09 100644 --- a/src/app/shared/components/resource-card/components/registration-secondary-metadata/registration-secondary-metadata.component.ts +++ b/src/app/shared/components/resource-card/components/registration-secondary-metadata/registration-secondary-metadata.component.ts @@ -2,7 +2,7 @@ import { TranslatePipe } from '@ngx-translate/core'; import { ChangeDetectionStrategy, Component, input } from '@angular/core'; -import { Resource } from '@shared/models'; +import { ResourceModel } from '@shared/models'; @Component({ selector: 'osf-registration-secondary-metadata', @@ -12,5 +12,5 @@ import { Resource } from '@shared/models'; changeDetection: ChangeDetectionStrategy.OnPush, }) export class RegistrationSecondaryMetadataComponent { - resource = input.required(); + resource = input.required(); } diff --git a/src/app/shared/components/resource-card/components/user-secondary-metadata/user-secondary-metadata.component.ts b/src/app/shared/components/resource-card/components/user-secondary-metadata/user-secondary-metadata.component.ts index 7006b8347..93f131d1d 100644 --- a/src/app/shared/components/resource-card/components/user-secondary-metadata/user-secondary-metadata.component.ts +++ b/src/app/shared/components/resource-card/components/user-secondary-metadata/user-secondary-metadata.component.ts @@ -4,7 +4,7 @@ import { Skeleton } from 'primeng/skeleton'; import { ChangeDetectionStrategy, Component, input } from '@angular/core'; -import { Resource, UserRelatedCounts } from '@shared/models'; +import { ResourceModel, UserRelatedCounts } from '@shared/models'; @Component({ selector: 'osf-user-secondary-metadata', @@ -14,7 +14,7 @@ import { Resource, UserRelatedCounts } from '@shared/models'; changeDetection: ChangeDetectionStrategy.OnPush, }) export class UserSecondaryMetadataComponent { - resource = input.required(); + resource = input.required(); isDataLoading = input(true); userRelatedCounts = input(null); } diff --git a/src/app/shared/components/resource-card/resource-card.component.spec.ts b/src/app/shared/components/resource-card/resource-card.component.spec.ts index 6d797ef0b..7c08e3f89 100644 --- a/src/app/shared/components/resource-card/resource-card.component.spec.ts +++ b/src/app/shared/components/resource-card/resource-card.component.spec.ts @@ -9,7 +9,7 @@ import { IS_XSMALL } from '@osf/shared/helpers'; import { ResourceCardComponent } from '@shared/components'; import { ResourceType } from '@shared/enums'; import { MOCK_AGENT_RESOURCE, MOCK_RESOURCE, MOCK_USER_RELATED_COUNTS, TranslateServiceMock } from '@shared/mocks'; -import { Resource } from '@shared/models'; +import { ResourceModel } from '@shared/models'; import { ResourceCardService } from '@shared/services'; describe.skip('ResourceCardComponent', () => { @@ -18,8 +18,8 @@ describe.skip('ResourceCardComponent', () => { const mockUserCounts = MOCK_USER_RELATED_COUNTS; - const mockResource: Resource = MOCK_RESOURCE; - const mockAgentResource: Resource = MOCK_AGENT_RESOURCE; + const mockResource: ResourceModel = MOCK_RESOURCE; + const mockAgentResource: ResourceModel = MOCK_AGENT_RESOURCE; beforeEach(async () => { await TestBed.configureTestingModule({ diff --git a/src/app/shared/components/resource-card/resource-card.component.ts b/src/app/shared/components/resource-card/resource-card.component.ts index 468123b91..0534ddabc 100644 --- a/src/app/shared/components/resource-card/resource-card.component.ts +++ b/src/app/shared/components/resource-card/resource-card.component.ts @@ -11,11 +11,19 @@ import { toSignal } from '@angular/core/rxjs-interop'; import { getPreprintDocumentType } from '@osf/features/preprints/helpers'; import { PreprintProviderDetails } from '@osf/features/preprints/models'; +import { CardLabelTranslationKeys } from '@osf/shared/constants'; +import { ResourceType } from '@osf/shared/enums'; import { IS_XSMALL } from '@osf/shared/helpers'; -import { DataResourcesComponent } from '@shared/components'; -import { ResourceType } from '@shared/enums'; -import { AbsoluteUrlName, IsContainedBy, QualifiedAttribution, Resource, UserRelatedCounts } from '@shared/models'; -import { ResourceCardService } from '@shared/services'; +import { + AbsoluteUrlName, + IsContainedBy, + QualifiedAttribution, + ResourceModel, + UserRelatedCounts, +} from '@osf/shared/models'; +import { ResourceCardService } from '@osf/shared/services'; + +import { DataResourcesComponent } from '../data-resources/data-resources.component'; import { FileSecondaryMetadataComponent } from './components/file-secondary-metadata/file-secondary-metadata.component'; import { PreprintSecondaryMetadataComponent } from './components/preprint-secondary-metadata/preprint-secondary-metadata.component'; @@ -23,17 +31,6 @@ import { ProjectSecondaryMetadataComponent } from './components/project-secondar import { RegistrationSecondaryMetadataComponent } from './components/registration-secondary-metadata/registration-secondary-metadata.component'; import { UserSecondaryMetadataComponent } from './components/user-secondary-metadata/user-secondary-metadata.component'; -export const CardLabelTranslationKeys: Partial> = { - [ResourceType.Project]: 'resourceCard.type.project', - [ResourceType.ProjectComponent]: 'resourceCard.type.projectComponent', - [ResourceType.Registration]: 'resourceCard.type.registration', - [ResourceType.RegistrationComponent]: 'resourceCard.type.registrationComponent', - [ResourceType.Preprint]: 'resourceCard.type.preprint', - [ResourceType.File]: 'resourceCard.type.file', - [ResourceType.Agent]: 'resourceCard.type.user', - [ResourceType.Null]: 'resourceCard.type.null', -}; - @Component({ selector: 'osf-resource-card', imports: [ @@ -61,7 +58,7 @@ export class ResourceCardComponent { private translateService = inject(TranslateService); ResourceType = ResourceType; isSmall = toSignal(inject(IS_XSMALL)); - resource = input.required(); + resource = input.required(); provider = input(); userRelatedCounts = signal(null); @@ -172,7 +169,7 @@ export class ResourceCardComponent { }); } - private getSortedContributors(base: Resource | IsContainedBy) { + private getSortedContributors(base: ResourceModel | IsContainedBy) { const objectOrder = Object.fromEntries( base.qualifiedAttribution.map((item: QualifiedAttribution) => [item.agentId, item.order]) ); diff --git a/src/app/shared/components/resource-metadata/resource-metadata.component.scss b/src/app/shared/components/resource-metadata/resource-metadata.component.scss index 318ef5009..e69de29bb 100644 --- a/src/app/shared/components/resource-metadata/resource-metadata.component.scss +++ b/src/app/shared/components/resource-metadata/resource-metadata.component.scss @@ -1,5 +0,0 @@ -@use "styles/variables" as var; - -.metadata { - color: var.$dark-blue-1; -} diff --git a/src/app/shared/components/search-results-container/search-results-container.component.ts b/src/app/shared/components/search-results-container/search-results-container.component.ts index 18697dc2f..11502fb0f 100644 --- a/src/app/shared/components/search-results-container/search-results-container.component.ts +++ b/src/app/shared/components/search-results-container/search-results-container.component.ts @@ -18,11 +18,11 @@ import { import { FormsModule } from '@angular/forms'; import { PreprintProviderDetails } from '@osf/features/preprints/models'; -import { LoadingSpinnerComponent } from '@shared/components'; -import { searchSortingOptions } from '@shared/constants'; -import { ResourceType } from '@shared/enums'; -import { Resource, TabOption } from '@shared/models'; +import { searchSortingOptions } from '@osf/shared/constants'; +import { ResourceType } from '@osf/shared/enums'; +import { ResourceModel, TabOption } from '@osf/shared/models'; +import { LoadingSpinnerComponent } from '../loading-spinner/loading-spinner.component'; import { ResourceCardComponent } from '../resource-card/resource-card.component'; import { SelectComponent } from '../select/select.component'; @@ -46,7 +46,7 @@ import { SelectComponent } from '../select/select.component'; changeDetection: ChangeDetectionStrategy.OnPush, }) export class SearchResultsContainerComponent { - resources = input([]); + resources = input([]); areResourcesLoading = input(false); searchCount = input(0); selectedSort = input(''); diff --git a/src/app/shared/components/status-badge/status-badge.component.ts b/src/app/shared/components/status-badge/status-badge.component.ts index b135950d1..2e6fe03ff 100644 --- a/src/app/shared/components/status-badge/status-badge.component.ts +++ b/src/app/shared/components/status-badge/status-badge.component.ts @@ -18,6 +18,7 @@ import { RegistryStatusMap } from './default-statuses'; }) export class StatusBadgeComponent { status = input.required(); + get label(): string { return RegistryStatusMap[this.status()]?.label ?? 'Unknown'; } diff --git a/src/app/shared/constants/index.ts b/src/app/shared/constants/index.ts index 1d6cc079b..5d262e421 100644 --- a/src/app/shared/constants/index.ts +++ b/src/app/shared/constants/index.ts @@ -13,6 +13,7 @@ export * from './osf-resource-types.const'; export * from './pie-chart-palette'; export * from './pie-chart-palette'; export * from './registry-services-icons.const'; +export * from './resource-card-labels.const'; export * from './resource-types.const'; export * from './scientists.const'; export * from './search-sort-options.const'; diff --git a/src/app/shared/constants/resource-card-labels.const.ts b/src/app/shared/constants/resource-card-labels.const.ts new file mode 100644 index 000000000..7b002e21c --- /dev/null +++ b/src/app/shared/constants/resource-card-labels.const.ts @@ -0,0 +1,12 @@ +import { ResourceType } from '../enums'; + +export const CardLabelTranslationKeys: Partial> = { + [ResourceType.Project]: 'resourceCard.type.project', + [ResourceType.ProjectComponent]: 'resourceCard.type.projectComponent', + [ResourceType.Registration]: 'resourceCard.type.registration', + [ResourceType.RegistrationComponent]: 'resourceCard.type.registrationComponent', + [ResourceType.Preprint]: 'resourceCard.type.preprint', + [ResourceType.File]: 'resourceCard.type.file', + [ResourceType.Agent]: 'resourceCard.type.user', + [ResourceType.Null]: 'resourceCard.type.null', +}; diff --git a/src/app/shared/mappers/licenses.mapper.ts b/src/app/shared/mappers/licenses.mapper.ts index 3dea667d8..aafaf8d67 100644 --- a/src/app/shared/mappers/licenses.mapper.ts +++ b/src/app/shared/mappers/licenses.mapper.ts @@ -1,11 +1,11 @@ -import { License, LicenseDataJsonApi, LicensesResponseJsonApi } from '../models'; +import { LicenseDataJsonApi, LicenseModel, LicensesResponseJsonApi } from '../models'; export class LicensesMapper { - static fromLicensesResponse(response: LicensesResponseJsonApi): License[] { + static fromLicensesResponse(response: LicensesResponseJsonApi): LicenseModel[] { return response.data.map((item) => LicensesMapper.fromLicenseDataJsonApi(item)); } - static fromLicenseDataJsonApi(data: LicenseDataJsonApi): License { + static fromLicenseDataJsonApi(data: LicenseDataJsonApi): LicenseModel { return { id: data?.id, name: data?.attributes?.name, diff --git a/src/app/shared/mappers/search/search.mapper.ts b/src/app/shared/mappers/search/search.mapper.ts index db51cefea..9a0495932 100644 --- a/src/app/shared/mappers/search/search.mapper.ts +++ b/src/app/shared/mappers/search/search.mapper.ts @@ -1,7 +1,7 @@ import { ResourceType } from '@shared/enums'; -import { IndexCardDataJsonApi, Resource } from '@shared/models'; +import { IndexCardDataJsonApi, ResourceModel } from '@shared/models'; -export function MapResources(indexCardData: IndexCardDataJsonApi): Resource { +export function MapResources(indexCardData: IndexCardDataJsonApi): ResourceModel { const resourceMetadata = indexCardData.attributes.resourceMetadata; const resourceIdentifier = indexCardData.attributes.resourceIdentifier; return { diff --git a/src/app/shared/mocks/license.mock.ts b/src/app/shared/mocks/license.mock.ts index d63b0caaf..089bd710e 100644 --- a/src/app/shared/mocks/license.mock.ts +++ b/src/app/shared/mocks/license.mock.ts @@ -1,6 +1,6 @@ -import { License } from '@shared/models'; +import { LicenseModel } from '@shared/models'; -export const MOCK_LICENSE: License = { +export const MOCK_LICENSE: LicenseModel = { id: '5c20a0307f39c2c3df0814ae', name: 'Apache License, 2.0', requiredFields: ['copyrightHolders', 'year'], diff --git a/src/app/shared/mocks/resource.mock.ts b/src/app/shared/mocks/resource.mock.ts index bef43ccbc..43255215b 100644 --- a/src/app/shared/mocks/resource.mock.ts +++ b/src/app/shared/mocks/resource.mock.ts @@ -1,7 +1,7 @@ import { ResourceType } from '@shared/enums'; -import { Resource, ResourceOverview } from '@shared/models'; +import { ResourceModel, ResourceOverview } from '@shared/models'; -export const MOCK_RESOURCE: Resource = { +export const MOCK_RESOURCE: ResourceModel = { id: 'https://api.osf.io/v2/resources/resource-123', resourceType: ResourceType.Registration, title: 'Test Resource', @@ -26,7 +26,7 @@ export const MOCK_RESOURCE: Resource = { hasSupplementalResource: true, }; -export const MOCK_AGENT_RESOURCE: Resource = { +export const MOCK_AGENT_RESOURCE: ResourceModel = { id: 'https://api.osf.io/v2/users/user-123', resourceType: ResourceType.Agent, title: 'Test User', diff --git a/src/app/shared/models/license.model.ts b/src/app/shared/models/license.model.ts index 2e7db89a3..c9da318ac 100644 --- a/src/app/shared/models/license.model.ts +++ b/src/app/shared/models/license.model.ts @@ -1,4 +1,4 @@ -export interface License { +export interface LicenseModel { id: string; name: string; requiredFields: string[]; diff --git a/src/app/shared/models/search/resource.model.ts b/src/app/shared/models/search/resource.model.ts index 724cc6e8a..181fc2899 100644 --- a/src/app/shared/models/search/resource.model.ts +++ b/src/app/shared/models/search/resource.model.ts @@ -1,7 +1,8 @@ -import { ResourceType } from '@shared/enums'; -import { DiscoverableFilter } from '@shared/models'; +import { ResourceType } from '@osf/shared/enums'; -export interface Resource { +import { DiscoverableFilter } from './discaverable-filter.model'; + +export interface ResourceModel { absoluteUrl: string; resourceType: ResourceType; name?: string; @@ -55,7 +56,7 @@ export interface AbsoluteUrlName { } export interface ResourcesData { - resources: Resource[]; + resources: ResourceModel[]; filters: DiscoverableFilter[]; count: number; first: string; diff --git a/src/app/shared/services/licenses.service.ts b/src/app/shared/services/licenses.service.ts index 0b5bd0a01..b17f176e2 100644 --- a/src/app/shared/services/licenses.service.ts +++ b/src/app/shared/services/licenses.service.ts @@ -4,7 +4,7 @@ import { HttpClient } from '@angular/common/http'; import { inject, Injectable } from '@angular/core'; import { LicensesMapper } from '@shared/mappers'; -import { License, LicensesResponseJsonApi } from '@shared/models'; +import { LicenseModel, LicensesResponseJsonApi } from '@shared/models'; import { environment } from 'src/environments/environment'; @@ -15,7 +15,7 @@ export class LicensesService { private readonly http = inject(HttpClient); private readonly baseUrl = environment.apiUrl; - getAllLicenses(): Observable { + getAllLicenses(): Observable { return this.http .get(`${this.baseUrl}/licenses/?page[size]=20`) .pipe(map((licenses) => LicensesMapper.fromLicensesResponse(licenses))); diff --git a/src/app/shared/stores/addons/addons.models.ts b/src/app/shared/stores/addons/addons.models.ts index 2834fd1b3..da54b5d40 100644 --- a/src/app/shared/stores/addons/addons.models.ts +++ b/src/app/shared/stores/addons/addons.models.ts @@ -81,3 +81,72 @@ export interface AddonsStateModel { */ selectedFolderOperationInvocation: AsyncStateModel; } + +export const ADDONS_DEFAULTS: AddonsStateModel = { + storageAddons: { + data: [], + isLoading: false, + error: null, + }, + citationAddons: { + data: [], + isLoading: false, + error: null, + }, + authorizedStorageAddons: { + data: [], + isLoading: false, + isSubmitting: false, + error: null, + }, + authorizedCitationAddons: { + data: [], + isLoading: false, + isSubmitting: false, + error: null, + }, + configuredStorageAddons: { + data: [], + isLoading: false, + error: null, + }, + configuredCitationAddons: { + data: [], + isLoading: false, + error: null, + }, + addonsUserReference: { + data: [], + isLoading: false, + error: null, + }, + addonsResourceReference: { + data: [], + isLoading: false, + error: null, + }, + createdUpdatedAuthorizedAddon: { + data: null, + isLoading: false, + isSubmitting: false, + error: null, + }, + createdUpdatedConfiguredAddon: { + data: null, + isLoading: false, + isSubmitting: false, + error: null, + }, + operationInvocation: { + data: null, + isLoading: false, + isSubmitting: false, + error: null, + }, + selectedFolderOperationInvocation: { + data: null, + isLoading: false, + isSubmitting: false, + error: null, + }, +}; diff --git a/src/app/shared/stores/addons/addons.state.ts b/src/app/shared/stores/addons/addons.state.ts index e7d1fe182..43644f554 100644 --- a/src/app/shared/stores/addons/addons.state.ts +++ b/src/app/shared/stores/addons/addons.state.ts @@ -6,7 +6,7 @@ import { inject, Injectable } from '@angular/core'; import { handleSectionError } from '@osf/shared/helpers'; import { AuthorizedAccountModel } from '@osf/shared/models'; -import { AddonsService } from '@shared/services'; +import { AddonsService } from '@osf/shared/services'; import { ClearConfiguredAddons, @@ -28,76 +28,7 @@ import { UpdateAuthorizedAddon, UpdateConfiguredAddon, } from './addons.actions'; -import { AddonsStateModel } from './addons.models'; - -const ADDONS_DEFAULTS: AddonsStateModel = { - storageAddons: { - data: [], - isLoading: false, - error: null, - }, - citationAddons: { - data: [], - isLoading: false, - error: null, - }, - authorizedStorageAddons: { - data: [], - isLoading: false, - isSubmitting: false, - error: null, - }, - authorizedCitationAddons: { - data: [], - isLoading: false, - isSubmitting: false, - error: null, - }, - configuredStorageAddons: { - data: [], - isLoading: false, - error: null, - }, - configuredCitationAddons: { - data: [], - isLoading: false, - error: null, - }, - addonsUserReference: { - data: [], - isLoading: false, - error: null, - }, - addonsResourceReference: { - data: [], - isLoading: false, - error: null, - }, - createdUpdatedAuthorizedAddon: { - data: null, - isLoading: false, - isSubmitting: false, - error: null, - }, - createdUpdatedConfiguredAddon: { - data: null, - isLoading: false, - isSubmitting: false, - error: null, - }, - operationInvocation: { - data: null, - isLoading: false, - isSubmitting: false, - error: null, - }, - selectedFolderOperationInvocation: { - data: null, - isLoading: false, - isSubmitting: false, - error: null, - }, -}; +import { ADDONS_DEFAULTS, AddonsStateModel } from './addons.models'; /** * NGXS state class for managing addon-related data and actions. diff --git a/src/app/shared/stores/citations/citations.model.ts b/src/app/shared/stores/citations/citations.model.ts index 0f5a91097..eacf653fe 100644 --- a/src/app/shared/stores/citations/citations.model.ts +++ b/src/app/shared/stores/citations/citations.model.ts @@ -1,5 +1,4 @@ -import { CitationStyle, DefaultCitation, StyledCitation } from '@shared/models'; -import { AsyncStateModel } from '@shared/models/store'; +import { AsyncStateModel, CitationStyle, DefaultCitation, StyledCitation } from '@osf/shared/models'; export interface CitationsStateModel { defaultCitations: AsyncStateModel; @@ -7,3 +6,30 @@ export interface CitationsStateModel { styledCitation: AsyncStateModel; customCitation: AsyncStateModel; } + +export const CITATIONS_DEFAULTS: CitationsStateModel = { + defaultCitations: { + data: [], + isLoading: false, + isSubmitting: false, + error: null, + }, + citationStyles: { + data: [], + isLoading: false, + isSubmitting: false, + error: null, + }, + styledCitation: { + data: null, + isLoading: false, + isSubmitting: false, + error: null, + }, + customCitation: { + data: '', + isLoading: false, + isSubmitting: false, + error: null, + }, +}; diff --git a/src/app/shared/stores/citations/citations.state.ts b/src/app/shared/stores/citations/citations.state.ts index 54a67a9d9..8f242cf68 100644 --- a/src/app/shared/stores/citations/citations.state.ts +++ b/src/app/shared/stores/citations/citations.state.ts @@ -4,9 +4,9 @@ import { catchError, forkJoin, Observable, tap } from 'rxjs'; import { inject, Injectable } from '@angular/core'; -import { CitationTypes } from '@shared/enums'; -import { handleSectionError } from '@shared/helpers'; -import { CitationsService } from '@shared/services/citations.service'; +import { CitationTypes } from '@osf/shared/enums'; +import { handleSectionError } from '@osf/shared/helpers'; +import { CitationsService } from '@osf/shared/services/citations.service'; import { ClearStyledCitation, @@ -15,34 +15,7 @@ import { GetStyledCitation, UpdateCustomCitation, } from './citations.actions'; -import { CitationsStateModel } from './citations.model'; - -const CITATIONS_DEFAULTS: CitationsStateModel = { - defaultCitations: { - data: [], - isLoading: false, - isSubmitting: false, - error: null, - }, - citationStyles: { - data: [], - isLoading: false, - isSubmitting: false, - error: null, - }, - styledCitation: { - data: null, - isLoading: false, - isSubmitting: false, - error: null, - }, - customCitation: { - data: '', - isLoading: false, - isSubmitting: false, - error: null, - }, -}; +import { CITATIONS_DEFAULTS, CitationsStateModel } from './citations.model'; @State({ name: 'citations', diff --git a/src/app/shared/stores/collections/collections.state.ts b/src/app/shared/stores/collections/collections.state.ts index 36fe4cef0..7c6289a54 100644 --- a/src/app/shared/stores/collections/collections.state.ts +++ b/src/app/shared/stores/collections/collections.state.ts @@ -1,10 +1,11 @@ import { Action, State, StateContext } from '@ngxs/store'; -import { catchError, forkJoin, of, switchMap, tap, throwError } from 'rxjs'; +import { catchError, forkJoin, of, switchMap, tap } from 'rxjs'; import { inject, Injectable } from '@angular/core'; -import { CollectionsService } from '@shared/services'; +import { handleSectionError } from '@osf/shared/helpers'; +import { CollectionsService } from '@osf/shared/services'; import { ClearCollections, @@ -97,7 +98,7 @@ export class CollectionsState { }, }); }), - catchError((error) => this.handleError(ctx, 'currentProjectSubmissions', error)) + catchError((error) => handleSectionError(ctx, 'currentProjectSubmissions', error)) ); } @@ -130,7 +131,7 @@ export class CollectionsState { }, }); }), - catchError((error) => this.handleError(ctx, 'collectionDetails', error)) + catchError((error) => handleSectionError(ctx, 'collectionDetails', error)) ); } @@ -324,7 +325,7 @@ export class CollectionsState { }, }); }), - catchError((error) => this.handleError(ctx, 'collectionSubmissions', error)) + catchError((error) => handleSectionError(ctx, 'collectionSubmissions', error)) ); } @@ -348,23 +349,7 @@ export class CollectionsState { }, }); }), - catchError((error) => this.handleError(ctx, 'userCollectionSubmissions', error)) + catchError((error) => handleSectionError(ctx, 'userCollectionSubmissions', error)) ); } - - private handleError(ctx: StateContext, section: keyof CollectionsStateModel, error: Error) { - const state = ctx.getState(); - if (section !== 'sortBy' && section !== 'searchText' && section !== 'page' && section !== 'totalSubmissions') { - ctx.patchState({ - [section]: { - ...state[section], - isLoading: false, - isSubmitting: false, - error: error.message, - }, - }); - } - - return throwError(() => error); - } } diff --git a/src/app/shared/stores/contributors/contributors.model.ts b/src/app/shared/stores/contributors/contributors.model.ts index 88dffccad..34baade41 100644 --- a/src/app/shared/stores/contributors/contributors.model.ts +++ b/src/app/shared/stores/contributors/contributors.model.ts @@ -1,5 +1,5 @@ import { ContributorAddModel, ContributorModel } from '@osf/shared/models'; -import { AsyncStateModel } from '@osf/shared/models/store'; +import { AsyncStateModel, AsyncStateWithTotalCount } from '@osf/shared/models/store'; export interface ContributorsStateModel { contributorsList: AsyncStateModel & { @@ -7,12 +7,10 @@ export interface ContributorsStateModel { permissionFilter: string | null; bibliographyFilter: boolean | null; }; - users: AsyncStateModel & { - totalCount: number; - }; + users: AsyncStateWithTotalCount; } -export const DefaultState = { +export const CONTRIBUTORS_STATE_DEFAULTS: ContributorsStateModel = { contributorsList: { data: [], isLoading: false, diff --git a/src/app/shared/stores/contributors/contributors.state.ts b/src/app/shared/stores/contributors/contributors.state.ts index 787821c46..4009b8965 100644 --- a/src/app/shared/stores/contributors/contributors.state.ts +++ b/src/app/shared/stores/contributors/contributors.state.ts @@ -1,9 +1,10 @@ import { Action, State, StateContext } from '@ngxs/store'; -import { catchError, of, tap, throwError } from 'rxjs'; +import { catchError, of, tap } from 'rxjs'; import { inject, Injectable } from '@angular/core'; +import { handleSectionError } from '@osf/shared/helpers'; import { ContributorsService } from '@osf/shared/services'; import { @@ -18,11 +19,11 @@ import { UpdatePermissionFilter, UpdateSearchValue, } from './contributors.actions'; -import { ContributorsStateModel, DefaultState } from './contributors.model'; +import { CONTRIBUTORS_STATE_DEFAULTS, ContributorsStateModel } from './contributors.model'; @State({ name: 'contributors', - defaults: { ...DefaultState }, + defaults: CONTRIBUTORS_STATE_DEFAULTS, }) @Injectable() export class ContributorsState { @@ -50,7 +51,7 @@ export class ContributorsState { }, }); }), - catchError((error) => this.handleError(ctx, 'contributorsList', error)) + catchError((error) => handleSectionError(ctx, 'contributorsList', error)) ); } @@ -78,7 +79,7 @@ export class ContributorsState { }, }); }), - catchError((error) => this.handleError(ctx, 'contributorsList', error)) + catchError((error) => handleSectionError(ctx, 'contributorsList', error)) ); } @@ -108,7 +109,7 @@ export class ContributorsState { }, }); }), - catchError((error) => this.handleError(ctx, 'contributorsList', error)) + catchError((error) => handleSectionError(ctx, 'contributorsList', error)) ); } @@ -136,7 +137,7 @@ export class ContributorsState { }, }); }), - catchError((error) => this.handleError(ctx, 'contributorsList', error)) + catchError((error) => handleSectionError(ctx, 'contributorsList', error)) ); } @@ -184,7 +185,7 @@ export class ContributorsState { }, }); }), - catchError((error) => this.handleError(ctx, 'users', error)) + catchError((error) => handleSectionError(ctx, 'users', error)) ); } @@ -195,17 +196,6 @@ export class ContributorsState { @Action(ResetContributorsState) resetState(ctx: StateContext) { - ctx.setState({ ...DefaultState }); - } - - private handleError(ctx: StateContext, section: 'contributorsList' | 'users', error: Error) { - ctx.patchState({ - [section]: { - ...ctx.getState()[section], - isLoading: false, - error: error.message, - }, - }); - return throwError(() => error); + ctx.setState({ ...CONTRIBUTORS_STATE_DEFAULTS }); } } diff --git a/src/app/shared/stores/global-search/global-search.model.ts b/src/app/shared/stores/global-search/global-search.model.ts index 09718c516..1ab86ef04 100644 --- a/src/app/shared/stores/global-search/global-search.model.ts +++ b/src/app/shared/stores/global-search/global-search.model.ts @@ -1,9 +1,9 @@ +import { ResourceType } from '@osf/shared/enums'; import { StringOrNull } from '@osf/shared/helpers'; -import { AsyncStateModel, DiscoverableFilter, Resource, SelectOption } from '@osf/shared/models'; -import { ResourceType } from '@shared/enums'; +import { AsyncStateModel, DiscoverableFilter, ResourceModel, SelectOption } from '@osf/shared/models'; export interface GlobalSearchStateModel { - resources: AsyncStateModel; + resources: AsyncStateModel; filters: DiscoverableFilter[]; defaultFilterValues: Record; filterValues: Record; diff --git a/src/app/shared/stores/global-search/global-search.selectors.ts b/src/app/shared/stores/global-search/global-search.selectors.ts index 4c858b33a..943adf5ad 100644 --- a/src/app/shared/stores/global-search/global-search.selectors.ts +++ b/src/app/shared/stores/global-search/global-search.selectors.ts @@ -1,15 +1,15 @@ import { Selector } from '@ngxs/store'; -import { ResourceType } from '@shared/enums'; -import { StringOrNull } from '@shared/helpers'; -import { DiscoverableFilter, Resource, SelectOption } from '@shared/models'; +import { ResourceType } from '@osf/shared/enums'; +import { StringOrNull } from '@osf/shared/helpers'; +import { DiscoverableFilter, ResourceModel, SelectOption } from '@osf/shared/models'; import { GlobalSearchStateModel } from './global-search.model'; import { GlobalSearchState } from './global-search.state'; export class GlobalSearchSelectors { @Selector([GlobalSearchState]) - static getResources(state: GlobalSearchStateModel): Resource[] { + static getResources(state: GlobalSearchStateModel): ResourceModel[] { return state.resources.data; } diff --git a/src/app/shared/stores/institutions-search/institutions-search.model.ts b/src/app/shared/stores/institutions-search/institutions-search.model.ts index 8b31455f2..7d4208344 100644 --- a/src/app/shared/stores/institutions-search/institutions-search.model.ts +++ b/src/app/shared/stores/institutions-search/institutions-search.model.ts @@ -3,3 +3,11 @@ import { AsyncStateModel, Institution } from '@shared/models'; export interface InstitutionsSearchModel { institution: AsyncStateModel; } + +export const INSTITUTIONS_SEARCH_STATE_DEFAULTS: InstitutionsSearchModel = { + institution: { + data: {} as Institution, + isLoading: false, + error: null, + }, +}; diff --git a/src/app/shared/stores/institutions-search/institutions-search.state.ts b/src/app/shared/stores/institutions-search/institutions-search.state.ts index 47a1bda45..143ecfec5 100644 --- a/src/app/shared/stores/institutions-search/institutions-search.state.ts +++ b/src/app/shared/stores/institutions-search/institutions-search.state.ts @@ -1,21 +1,20 @@ import { Action, State, StateContext } from '@ngxs/store'; import { patch } from '@ngxs/store/operators'; -import { catchError, tap, throwError } from 'rxjs'; +import { catchError, tap } from 'rxjs'; import { inject, Injectable } from '@angular/core'; +import { handleSectionError } from '@osf/shared/helpers'; import { Institution } from '@osf/shared/models'; import { InstitutionsService } from '@osf/shared/services'; import { FetchInstitutionById } from './institutions-search.actions'; -import { InstitutionsSearchModel } from './institutions-search.model'; +import { INSTITUTIONS_SEARCH_STATE_DEFAULTS, InstitutionsSearchModel } from './institutions-search.model'; @State({ name: 'institutionsSearch', - defaults: { - institution: { data: {} as Institution, isLoading: false, error: null }, - }, + defaults: INSTITUTIONS_SEARCH_STATE_DEFAULTS, }) @Injectable() export class InstitutionsSearchState { @@ -33,10 +32,7 @@ export class InstitutionsSearchState { }) ); }), - catchError((error) => { - ctx.patchState({ institution: { ...ctx.getState().institution, isLoading: false, error } }); - return throwError(() => error); - }) + catchError((error) => handleSectionError(ctx, 'institution', error)) ); } } diff --git a/src/app/shared/stores/licenses/licenses.model.ts b/src/app/shared/stores/licenses/licenses.model.ts index df59b5987..932ebb747 100644 --- a/src/app/shared/stores/licenses/licenses.model.ts +++ b/src/app/shared/stores/licenses/licenses.model.ts @@ -1,5 +1,13 @@ -import { AsyncStateModel, License } from '@shared/models'; +import { AsyncStateModel, LicenseModel } from '@osf/shared/models'; export interface LicensesStateModel { - licenses: AsyncStateModel; + licenses: AsyncStateModel; } + +export const LICENSES_STATE_DEFAULTS: LicensesStateModel = { + licenses: { + data: [], + isLoading: false, + error: null, + }, +}; diff --git a/src/app/shared/stores/licenses/licenses.selectors.ts b/src/app/shared/stores/licenses/licenses.selectors.ts index b54440484..2d5739743 100644 --- a/src/app/shared/stores/licenses/licenses.selectors.ts +++ b/src/app/shared/stores/licenses/licenses.selectors.ts @@ -1,13 +1,13 @@ import { Selector } from '@ngxs/store'; -import { License } from '@osf/shared/models'; +import { LicenseModel } from '@osf/shared/models'; import { LicensesStateModel } from './licenses.model'; import { LicensesState } from './licenses.state'; export class LicensesSelectors { @Selector([LicensesState]) - static getLicenses(state: LicensesStateModel): License[] { + static getLicenses(state: LicensesStateModel): LicenseModel[] { return state.licenses.data; } diff --git a/src/app/shared/stores/licenses/licenses.state.ts b/src/app/shared/stores/licenses/licenses.state.ts index 4cbd08514..bc078dd80 100644 --- a/src/app/shared/stores/licenses/licenses.state.ts +++ b/src/app/shared/stores/licenses/licenses.state.ts @@ -5,22 +5,14 @@ import { catchError, tap } from 'rxjs/operators'; import { inject, Injectable } from '@angular/core'; -import { LicensesService } from '@shared/services'; +import { LicensesService } from '@osf/shared/services'; import { LoadAllLicenses } from './licenses.actions'; -import { LicensesStateModel } from './licenses.model'; - -const defaultState: LicensesStateModel = { - licenses: { - data: [], - isLoading: false, - error: null, - }, -}; +import { LICENSES_STATE_DEFAULTS, LicensesStateModel } from './licenses.model'; @State({ name: 'licenses', - defaults: defaultState, + defaults: LICENSES_STATE_DEFAULTS, }) @Injectable() export class LicensesState { diff --git a/src/app/shared/stores/node-links/node-links.actions.ts b/src/app/shared/stores/node-links/node-links.actions.ts index 7430983d6..da48a8ba7 100644 --- a/src/app/shared/stores/node-links/node-links.actions.ts +++ b/src/app/shared/stores/node-links/node-links.actions.ts @@ -1,4 +1,4 @@ -import { ComponentOverview, MyResourcesItem } from '@shared/models'; +import { ComponentOverview, MyResourcesItem } from '@osf/shared/models'; export class CreateNodeLink { static readonly type = '[Node Links] Create Node Link'; diff --git a/src/app/shared/stores/projects/projects.model.ts b/src/app/shared/stores/projects/projects.model.ts index 4112568ca..cca209928 100644 --- a/src/app/shared/stores/projects/projects.model.ts +++ b/src/app/shared/stores/projects/projects.model.ts @@ -1,7 +1,20 @@ -import { AsyncStateModel } from '@osf/shared/models'; -import { Project } from '@osf/shared/models/projects'; +import { AsyncStateModel, Project } from '@osf/shared/models'; export interface ProjectsStateModel { projects: AsyncStateModel; selectedProject: AsyncStateModel; } + +export const PROJECTS_STATE_DEFAULTS: ProjectsStateModel = { + projects: { + data: [], + isLoading: false, + error: null, + }, + selectedProject: { + data: null, + isLoading: false, + isSubmitting: false, + error: null, + }, +}; diff --git a/src/app/shared/stores/projects/projects.state.ts b/src/app/shared/stores/projects/projects.state.ts index 5c8da41b4..37f6b9d94 100644 --- a/src/app/shared/stores/projects/projects.state.ts +++ b/src/app/shared/stores/projects/projects.state.ts @@ -4,29 +4,15 @@ import { catchError, tap } from 'rxjs'; import { inject, Injectable } from '@angular/core'; -import { handleSectionError } from '@shared/helpers'; -import { ProjectsService } from '@shared/services/projects.service'; +import { handleSectionError } from '@osf/shared/helpers'; +import { ProjectsService } from '@osf/shared/services/projects.service'; import { ClearProjects, GetProjects, SetSelectedProject, UpdateProjectMetadata } from './projects.actions'; -import { ProjectsStateModel } from './projects.model'; - -const PROJECTS_DEFAULTS: ProjectsStateModel = { - projects: { - data: [], - isLoading: false, - error: null, - }, - selectedProject: { - data: null, - isLoading: false, - isSubmitting: false, - error: null, - }, -}; +import { PROJECTS_STATE_DEFAULTS, ProjectsStateModel } from './projects.model'; @State({ name: 'projects', - defaults: PROJECTS_DEFAULTS, + defaults: PROJECTS_STATE_DEFAULTS, }) @Injectable() export class ProjectsState { @@ -96,6 +82,6 @@ export class ProjectsState { @Action(ClearProjects) clearProjects(ctx: StateContext) { - ctx.patchState(PROJECTS_DEFAULTS); + ctx.patchState(PROJECTS_STATE_DEFAULTS); } } diff --git a/src/app/shared/stores/regions/regions.model.ts b/src/app/shared/stores/regions/regions.model.ts index c7ec6e970..e31587434 100644 --- a/src/app/shared/stores/regions/regions.model.ts +++ b/src/app/shared/stores/regions/regions.model.ts @@ -3,3 +3,11 @@ import { AsyncStateModel, IdName } from '@shared/models'; export interface RegionsStateModel { regions: AsyncStateModel; } + +export const REGIONS_STATE_DEFAULTS = { + regions: { + data: [], + isLoading: false, + error: null, + }, +}; diff --git a/src/app/shared/stores/regions/regions.state.ts b/src/app/shared/stores/regions/regions.state.ts index 93954d888..1c6574646 100644 --- a/src/app/shared/stores/regions/regions.state.ts +++ b/src/app/shared/stores/regions/regions.state.ts @@ -9,17 +9,11 @@ import { handleSectionError } from '@osf/shared/helpers'; import { RegionsService } from '@osf/shared/services'; import { FetchRegions } from './regions.actions'; -import { RegionsStateModel } from './regions.model'; +import { REGIONS_STATE_DEFAULTS, RegionsStateModel } from './regions.model'; @State({ name: 'regions', - defaults: { - regions: { - data: [], - isLoading: false, - error: null, - }, - }, + defaults: REGIONS_STATE_DEFAULTS, }) @Injectable() export class RegionsState { diff --git a/src/app/shared/stores/subjects/subjects.model.ts b/src/app/shared/stores/subjects/subjects.model.ts index 13b9f3e88..a412febfc 100644 --- a/src/app/shared/stores/subjects/subjects.model.ts +++ b/src/app/shared/stores/subjects/subjects.model.ts @@ -5,3 +5,21 @@ export interface SubjectsModel { searchedSubjects: AsyncStateModel; selectedSubjects: AsyncStateModel; } + +export const SUBJECT_STATE_DEFAULTS: SubjectsModel = { + subjects: { + data: [], + isLoading: false, + error: null, + }, + searchedSubjects: { + data: [], + isLoading: false, + error: null, + }, + selectedSubjects: { + data: [], + isLoading: false, + error: null, + }, +}; diff --git a/src/app/shared/stores/subjects/subjects.state.ts b/src/app/shared/stores/subjects/subjects.state.ts index edd3c1517..dc0a9a07b 100644 --- a/src/app/shared/stores/subjects/subjects.state.ts +++ b/src/app/shared/stores/subjects/subjects.state.ts @@ -4,8 +4,8 @@ import { catchError, tap, throwError } from 'rxjs'; import { inject, Injectable } from '@angular/core'; -import { SubjectModel } from '@shared/models'; -import { SubjectsService } from '@shared/services'; +import { SubjectModel } from '@osf/shared/models'; +import { SubjectsService } from '@osf/shared/services'; import { FetchChildrenSubjects, @@ -13,29 +13,11 @@ import { FetchSubjects, UpdateResourceSubjects, } from './subjects.actions'; -import { SubjectsModel } from './subjects.model'; - -const initialState: SubjectsModel = { - subjects: { - data: [], - isLoading: false, - error: null, - }, - searchedSubjects: { - data: [], - isLoading: false, - error: null, - }, - selectedSubjects: { - data: [], - isLoading: false, - error: null, - }, -}; +import { SUBJECT_STATE_DEFAULTS, SubjectsModel } from './subjects.model'; @State({ name: 'subjects', - defaults: initialState, + defaults: SUBJECT_STATE_DEFAULTS, }) @Injectable() export class SubjectsState { diff --git a/src/app/shared/stores/wiki/wiki.model.ts b/src/app/shared/stores/wiki/wiki.model.ts index e8a09223d..3763a1c0f 100644 --- a/src/app/shared/stores/wiki/wiki.model.ts +++ b/src/app/shared/stores/wiki/wiki.model.ts @@ -24,3 +24,45 @@ export interface WikiStateModel { compareVersionContent: AsyncStateModel; isAnonymous: boolean; } + +export const WIKI_STATE_DEFAULTS: WikiStateModel = { + homeWikiContent: { + data: '', + isLoading: false, + error: null, + }, + wikiModes: { + view: true, + edit: false, + compare: false, + }, + wikiList: { + data: [], + isLoading: false, + error: null, + isSubmitting: false, + }, + componentsWikiList: { + data: [], + isLoading: false, + error: null, + }, + currentWikiId: '', + previewContent: '', + wikiVersions: { + data: [], + isLoading: false, + error: null, + }, + versionContent: { + data: '', + isLoading: false, + error: null, + }, + compareVersionContent: { + data: '', + isLoading: false, + error: null, + }, + isAnonymous: false, +}; diff --git a/src/app/shared/stores/wiki/wiki.state.ts b/src/app/shared/stores/wiki/wiki.state.ts index d876bc4a5..c8ac48f07 100644 --- a/src/app/shared/stores/wiki/wiki.state.ts +++ b/src/app/shared/stores/wiki/wiki.state.ts @@ -21,53 +21,11 @@ import { ToggleMode, UpdateWikiPreviewContent, } from './wiki.actions'; -import { WikiStateModel } from './wiki.model'; - -const DefaultState: WikiStateModel = { - homeWikiContent: { - data: '', - isLoading: false, - error: null, - }, - wikiModes: { - view: true, - edit: false, - compare: false, - }, - wikiList: { - data: [], - isLoading: false, - error: null, - isSubmitting: false, - }, - componentsWikiList: { - data: [], - isLoading: false, - error: null, - }, - currentWikiId: '', - previewContent: '', - wikiVersions: { - data: [], - isLoading: false, - error: null, - }, - versionContent: { - data: '', - isLoading: false, - error: null, - }, - compareVersionContent: { - data: '', - isLoading: false, - error: null, - }, - isAnonymous: false, -}; +import { WIKI_STATE_DEFAULTS, WikiStateModel } from './wiki.model'; @State({ name: 'wiki', - defaults: { ...DefaultState }, + defaults: WIKI_STATE_DEFAULTS, }) @Injectable() export class WikiState { @@ -152,18 +110,7 @@ export class WikiState { @Action(ClearWiki) clearWiki(ctx: StateContext) { - ctx.patchState({ - homeWikiContent: { ...DefaultState.homeWikiContent }, - wikiModes: { ...DefaultState.wikiModes }, - wikiList: { ...DefaultState.wikiList }, - componentsWikiList: { ...DefaultState.componentsWikiList }, - currentWikiId: DefaultState.currentWikiId, - previewContent: DefaultState.previewContent, - wikiVersions: { ...DefaultState.wikiVersions }, - versionContent: { ...DefaultState.versionContent }, - compareVersionContent: { ...DefaultState.compareVersionContent }, - isAnonymous: DefaultState.isAnonymous, - }); + ctx.setState(WIKI_STATE_DEFAULTS); } @Action(ToggleMode) From 4ae167278579855a4fbb0d1b0ee148157d9b0ab4 Mon Sep 17 00:00:00 2001 From: nsemets Date: Mon, 8 Sep 2025 15:42:32 +0300 Subject: [PATCH 5/5] fix(tests): fixed unit tests --- .../metadata-contributors.component.spec.ts | 5 ++++- .../description-dialog/description-dialog.component.spec.ts | 4 ++-- .../dialogs/funding-dialog/funding-dialog.component.spec.ts | 4 ++-- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/app/features/metadata/components/metadata-contributors/metadata-contributors.component.spec.ts b/src/app/features/metadata/components/metadata-contributors/metadata-contributors.component.spec.ts index 41957ce27..dd353aa61 100644 --- a/src/app/features/metadata/components/metadata-contributors/metadata-contributors.component.spec.ts +++ b/src/app/features/metadata/components/metadata-contributors/metadata-contributors.component.spec.ts @@ -1,4 +1,7 @@ +import { MockProvider } from 'ng-mocks'; + import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { ActivatedRoute } from '@angular/router'; import { ContributorModel } from '@osf/shared/models'; import { MOCK_CONTRIBUTOR, TranslateServiceMock } from '@shared/mocks'; @@ -14,7 +17,7 @@ describe('MetadataContributorsComponent', () => { beforeEach(async () => { await TestBed.configureTestingModule({ imports: [MetadataContributorsComponent], - providers: [TranslateServiceMock], + providers: [TranslateServiceMock, MockProvider(ActivatedRoute)], }).compileComponents(); fixture = TestBed.createComponent(MetadataContributorsComponent); diff --git a/src/app/features/metadata/dialogs/description-dialog/description-dialog.component.spec.ts b/src/app/features/metadata/dialogs/description-dialog/description-dialog.component.spec.ts index 8edd8a37f..82e3f30eb 100644 --- a/src/app/features/metadata/dialogs/description-dialog/description-dialog.component.spec.ts +++ b/src/app/features/metadata/dialogs/description-dialog/description-dialog.component.spec.ts @@ -39,9 +39,9 @@ describe('DescriptionDialogComponent', () => { it('should handle save with valid form', () => { const dialogRef = TestBed.inject(DynamicDialogRef); jest.spyOn(dialogRef, 'close'); - const validDescription = 'Valid description'; + const validDescription = { value: 'Valid description' }; - component.descriptionControl.setValue(validDescription); + component.descriptionControl.setValue(validDescription.value); component.save(); expect(dialogRef.close).toHaveBeenCalledWith(validDescription); diff --git a/src/app/features/metadata/dialogs/funding-dialog/funding-dialog.component.spec.ts b/src/app/features/metadata/dialogs/funding-dialog/funding-dialog.component.spec.ts index 2b93a9345..3054bbaf2 100644 --- a/src/app/features/metadata/dialogs/funding-dialog/funding-dialog.component.spec.ts +++ b/src/app/features/metadata/dialogs/funding-dialog/funding-dialog.component.spec.ts @@ -49,7 +49,7 @@ describe('FundingDialogComponent', () => { expect(component.fundingEntries.length).toBe(initialLength + 1); const entry = component.fundingEntries.at(component.fundingEntries.length - 1); - expect(entry.get('funderName')?.value).toBe(''); + expect(entry.get('funderName')?.value).toBe(null); expect(entry.get('awardTitle')?.value).toBe(''); }); @@ -263,7 +263,7 @@ describe('FundingDialogComponent', () => { component.addFundingEntry(); const entry = component.fundingEntries.at(initialLength); - expect(entry.get('funderName')?.value).toBe(''); + expect(entry.get('funderName')?.value).toBe(null); expect(entry.get('funderIdentifier')?.value).toBe(''); expect(entry.get('funderIdentifierType')?.value).toBe('DOI'); expect(entry.get('awardTitle')?.value).toBe('');