From d7f8a62732811aae446e3aee99c86c3130416fd7 Mon Sep 17 00:00:00 2001 From: nsemets Date: Sat, 4 Oct 2025 18:42:30 +0300 Subject: [PATCH] fix(project-settings): fixed project settings bug --- .../services/preprints-projects.service.ts | 14 +- .../settings-project-form-card.component.html | 7 +- .../settings-project-form-card.component.ts | 6 +- .../settings/mappers/settings.mapper.ts | 7 +- .../settings/models/node-details.model.ts | 1 + .../models/project-details-json-api.model.ts | 16 +-- .../settings/services/settings.service.ts | 1 + .../shared/mappers/regions/regions-mapper.ts | 9 +- .../nodes/base-node-embeds-json-api.model.ts | 2 +- .../models/nodes/nodes-json-api.model.ts | 123 ++---------------- src/assets/i18n/en.json | 1 + 11 files changed, 50 insertions(+), 137 deletions(-) diff --git a/src/app/features/preprints/services/preprints-projects.service.ts b/src/app/features/preprints/services/preprints-projects.service.ts index 11c458b66..f1855f187 100644 --- a/src/app/features/preprints/services/preprints-projects.service.ts +++ b/src/app/features/preprints/services/preprints-projects.service.ts @@ -4,7 +4,13 @@ import { inject, Injectable } from '@angular/core'; import { ENVIRONMENT } from '@core/provider/environment.provider'; import { Primitive, StringOrNull } from '@osf/shared/helpers'; -import { ApiData, CreateProjectPayloadJsoApi, IdName, JsonApiResponse, NodeData } from '@osf/shared/models'; +import { + ApiData, + CreateProjectPayloadJsoApi, + IdName, + NodeResponseJsonApi, + NodesResponseJsonApi, +} from '@osf/shared/models'; import { JsonApiService } from '@osf/shared/services'; import { PreprintsMapper } from '../mappers'; @@ -29,7 +35,7 @@ export class PreprintsProjectsService { params['filter[title]'] = searchTerm; } - return this.jsonApiService.get>(`${this.apiUrl}/users/me/nodes/`, params).pipe( + return this.jsonApiService.get(`${this.apiUrl}/users/me/nodes/`, params).pipe( map((response) => { return response.data.map((item) => ({ id: item.id, @@ -40,7 +46,7 @@ export class PreprintsProjectsService { } getProjectById(projectId: string): Observable { - return this.jsonApiService.get>(`${this.apiUrl}/nodes/${projectId}/`).pipe( + return this.jsonApiService.get(`${this.apiUrl}/nodes/${projectId}/`).pipe( map((response) => { return { id: response.data.id, @@ -114,7 +120,7 @@ export class PreprintsProjectsService { }, }; - return this.jsonApiService.post>(`${this.apiUrl}/nodes/`, payload).pipe( + return this.jsonApiService.post(`${this.apiUrl}/nodes/`, payload).pipe( map((response) => { return { id: response.data.id, diff --git a/src/app/features/project/settings/components/settings-project-form-card/settings-project-form-card.component.html b/src/app/features/project/settings/components/settings-project-form-card/settings-project-form-card.component.html index 10152dd42..6dcfc1e3b 100644 --- a/src/app/features/project/settings/components/settings-project-form-card/settings-project-form-card.component.html +++ b/src/app/features/project/settings/components/settings-project-form-card/settings-project-form-card.component.html @@ -34,12 +34,7 @@

{{ 'myProjects.settings.project' | translate }}

- +
diff --git a/src/app/features/project/settings/components/settings-project-form-card/settings-project-form-card.component.ts b/src/app/features/project/settings/components/settings-project-form-card/settings-project-form-card.component.ts index 88a057170..d7b0e22a7 100644 --- a/src/app/features/project/settings/components/settings-project-form-card/settings-project-form-card.component.ts +++ b/src/app/features/project/settings/components/settings-project-form-card/settings-project-form-card.component.ts @@ -4,7 +4,7 @@ import { Button } from 'primeng/button'; import { Card } from 'primeng/card'; import { Textarea } from 'primeng/textarea'; -import { ChangeDetectionStrategy, Component, effect, input, output } from '@angular/core'; +import { ChangeDetectionStrategy, Component, computed, effect, input, output } from '@angular/core'; import { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms'; import { TextInputComponent } from '@osf/shared/components'; @@ -34,6 +34,10 @@ export class SettingsProjectFormCardComponent { [ProjectFormControls.Description]: new FormControl(''), }); + deleteLabel = computed(() => + this.projectDetails().parentId ? 'myProjects.settings.deleteComponent' : 'myProjects.settings.deleteProject' + ); + constructor() { this.setupFormEffects(); } diff --git a/src/app/features/project/settings/mappers/settings.mapper.ts b/src/app/features/project/settings/mappers/settings.mapper.ts index 7c2622753..0188f518e 100644 --- a/src/app/features/project/settings/mappers/settings.mapper.ts +++ b/src/app/features/project/settings/mappers/settings.mapper.ts @@ -1,5 +1,6 @@ import { UserPermissions } from '@osf/shared/enums'; import { InstitutionsMapper } from '@osf/shared/mappers'; +import { RegionsMapper } from '@osf/shared/mappers/regions'; import { NodeDataJsonApi, @@ -32,14 +33,12 @@ export class SettingsMapper { title: data.attributes.title, description: data.attributes.description, isPublic: data.attributes.public, - region: { - id: data.embeds?.region.data.id, - name: data.embeds?.region.data.attributes.name, - }, + region: RegionsMapper.getRegion(data?.embeds?.region?.data), affiliatedInstitutions: data.embeds ? InstitutionsMapper.fromInstitutionsResponse(data.embeds.affiliated_institutions) : [], currentUserPermissions: data.attributes.current_user_permissions as UserPermissions[], + parentId: data.relationships.parent?.data?.id, lastFetched: Date.now(), }; } diff --git a/src/app/features/project/settings/models/node-details.model.ts b/src/app/features/project/settings/models/node-details.model.ts index e5e9799a6..867093806 100644 --- a/src/app/features/project/settings/models/node-details.model.ts +++ b/src/app/features/project/settings/models/node-details.model.ts @@ -8,5 +8,6 @@ export interface NodeDetailsModel { region: IdName; affiliatedInstitutions: Institution[]; currentUserPermissions: string[]; + parentId?: string; lastFetched: number; } diff --git a/src/app/features/project/settings/models/project-details-json-api.model.ts b/src/app/features/project/settings/models/project-details-json-api.model.ts index bbfff660f..bae19f9f8 100644 --- a/src/app/features/project/settings/models/project-details-json-api.model.ts +++ b/src/app/features/project/settings/models/project-details-json-api.model.ts @@ -1,19 +1,19 @@ -import { InstitutionsJsonApiResponse, NodeData, ResponseDataJsonApi } from '@osf/shared/models'; +import { + BaseNodeDataJsonApi, + InstitutionsJsonApiResponse, + RegionDataJsonApi, + ResponseDataJsonApi, +} from '@osf/shared/models'; export type NodeResponseJsonApi = ResponseDataJsonApi; -export interface NodeDataJsonApi extends NodeData { +export interface NodeDataJsonApi extends BaseNodeDataJsonApi { embeds: NodeEmbedsJsonApi; } interface NodeEmbedsJsonApi { region: { - data: { - id: string; - attributes: { - name: string; - }; - }; + data: RegionDataJsonApi; }; affiliated_institutions: InstitutionsJsonApiResponse; } diff --git a/src/app/features/project/settings/services/settings.service.ts b/src/app/features/project/settings/services/settings.service.ts index 28e8fb5af..9c5dd4a79 100644 --- a/src/app/features/project/settings/services/settings.service.ts +++ b/src/app/features/project/settings/services/settings.service.ts @@ -71,6 +71,7 @@ export class SettingsService { const params = { 'embed[]': ['affiliated_institutions', 'region'], }; + return this.jsonApiService .get(`${this.apiUrl}/nodes/${projectId}/`, params) .pipe(map((response) => SettingsMapper.fromNodeResponse(response.data))); diff --git a/src/app/shared/mappers/regions/regions-mapper.ts b/src/app/shared/mappers/regions/regions-mapper.ts index 41399c48f..4b2c371c6 100644 --- a/src/app/shared/mappers/regions/regions-mapper.ts +++ b/src/app/shared/mappers/regions/regions-mapper.ts @@ -1,4 +1,4 @@ -import { IdName, RegionsResponseJsonApi } from '@osf/shared/models'; +import { IdName, RegionDataJsonApi, RegionsResponseJsonApi } from '@osf/shared/models'; export class RegionsMapper { static fromRegionsResponseJsonApi(response: RegionsResponseJsonApi): IdName[] { @@ -7,4 +7,11 @@ export class RegionsMapper { name: data.attributes.name, })); } + + static getRegion(data: RegionDataJsonApi): IdName { + return { + id: data.id, + name: data.attributes.name, + }; + } } diff --git a/src/app/shared/models/nodes/base-node-embeds-json-api.model.ts b/src/app/shared/models/nodes/base-node-embeds-json-api.model.ts index 0fff1e7ce..8c128c33c 100644 --- a/src/app/shared/models/nodes/base-node-embeds-json-api.model.ts +++ b/src/app/shared/models/nodes/base-node-embeds-json-api.model.ts @@ -1,6 +1,6 @@ import { IdentifierAttributes } from '@shared/models'; -export interface BaseNodeEmbeds { +export interface BaseNodeEmbedsJsonApi { bibliographic_contributors?: { data: ContributorResource[]; }; diff --git a/src/app/shared/models/nodes/nodes-json-api.model.ts b/src/app/shared/models/nodes/nodes-json-api.model.ts index 7a87a5b8c..8e75ce771 100644 --- a/src/app/shared/models/nodes/nodes-json-api.model.ts +++ b/src/app/shared/models/nodes/nodes-json-api.model.ts @@ -1,19 +1,12 @@ -export interface NodeData { - id: string; - type: 'nodes'; - attributes: NodeAttributes; - relationships: NodeRelationships; - links: NodeLinks; - lastFetched?: number; -} +import { ResponseJsonApi } from '../common'; -export interface NodeResponseModel { - data: NodeData; - meta: NodeMeta; -} +import { BaseNodeDataJsonApi } from './base-node-data-json-api.model'; + +export type NodesResponseJsonApi = ResponseJsonApi; +export type NodeResponseJsonApi = ResponseJsonApi; export interface UpdateNodeRequestModel { - data: UpdateNodeData; + data: UpdateNodeDataJsonApi; } export interface CreateProjectPayloadJsoApi { @@ -42,109 +35,15 @@ export interface CreateProjectPayloadJsoApi { }; } -interface NodeAttributes { - title: string; - description: string; - category: string; - custom_citation: string | null; - date_created: string; - date_modified: string; - registration: boolean; - preprint: boolean; - fork: boolean; - collection: boolean; - tags: string[]; - access_requests_enabled: boolean; - node_license: unknown | null; - current_user_can_comment: boolean; - current_user_permissions: string[]; - current_user_is_contributor: boolean; - current_user_is_contributor_or_group_member: boolean; - wiki_enabled: boolean; - public: boolean; - subjects: unknown[]; -} - -interface RelationshipLinks { - related: { - href: string; - meta: Record; - }; - self?: { - href: string; - meta: Record; - }; -} - -interface NodeRelationships { - children: { links: RelationshipLinks }; - comments: { links: RelationshipLinks }; - contributors: { links: RelationshipLinks }; - bibliographic_contributors: { links: RelationshipLinks }; - implicit_contributors: { links: RelationshipLinks }; - files: { links: RelationshipLinks }; - settings: { - links: RelationshipLinks; - data: { id: string; type: 'node-setting' }; - }; - wikis: { links: RelationshipLinks }; - forks: { links: RelationshipLinks }; - groups: { links: RelationshipLinks }; - node_links: { links: RelationshipLinks }; - linked_by_nodes: { links: RelationshipLinks }; - linked_by_registrations: { links: RelationshipLinks }; - parent: { - links: RelationshipLinks; - data: { id: string; type: 'nodes' }; - }; - identifiers: { links: RelationshipLinks }; - affiliated_institutions: { links: RelationshipLinks }; - draft_registrations: { links: RelationshipLinks }; - registrations: { links: RelationshipLinks }; - region: { - links: RelationshipLinks; - data: { id: string; type: 'regions' }; - }; - root: { - links: RelationshipLinks; - data: { id: string; type: 'nodes' }; - }; - logs: { links: RelationshipLinks }; - linked_nodes: { links: RelationshipLinks }; - linked_registrations: { links: RelationshipLinks }; - view_only_links: { links: RelationshipLinks }; - citation: { - links: RelationshipLinks; - data: { id: string; type: 'citation' }; - }; - preprints: { links: RelationshipLinks }; - storage: { - links: RelationshipLinks; - data: { id: string; type: 'node-storage' }; - }; - cedar_metadata_records: { links: RelationshipLinks }; - subjects_acceptable: { links: RelationshipLinks }; -} - -interface NodeLinks { - html: string; - self: string; - iri: string; -} - -interface NodeMeta { - version: string; +interface UpdateNodeDataJsonApi { + id: string; + type: 'nodes'; + attributes: UpdateNodeAttributesJsonApi; } -interface UpdateNodeAttributes { +interface UpdateNodeAttributesJsonApi { description?: string; tags?: string[]; public?: boolean; title?: string; } - -interface UpdateNodeData { - type: 'nodes'; - id: string; - attributes: UpdateNodeAttributes; -} diff --git a/src/assets/i18n/en.json b/src/assets/i18n/en.json index bf213b6f6..56023883d 100644 --- a/src/assets/i18n/en.json +++ b/src/assets/i18n/en.json @@ -442,6 +442,7 @@ "project": "Project", "saveChanges": "Save Changes", "deleteProject": "Delete Project", + "deleteComponent": "Delete Component", "viewOnlyLinks": "View-only Links", "viewOnlySubtitle": "Create a link to share this project so those who have the link can view—but not edit—the project.", "viewOnlyTable": {