From a60af8c7465a628811a9fed05f85da029bb3a53f Mon Sep 17 00:00:00 2001 From: mkovalua Date: Thu, 8 Oct 2026 19:05:30 +0300 Subject: [PATCH] Rejected registrations disappearing for registration providers (update front end PART rejected registration label and registration overview description ) --- .../registry-overview.component.spec.ts | 9 ++++++ .../registry-overview.component.ts | 6 +++- .../status-badge.component.spec.ts | 7 +++++ .../shared/constants/registration-statuses.ts | 1 + src/app/shared/enums/registry-status.enum.ts | 1 + .../map-registry-status.mapper.spec.ts | 30 +++++++++++++++++++ .../map-registry-status.mapper.ts | 2 ++ src/assets/i18n/en.json | 6 ++++ 8 files changed, 61 insertions(+), 1 deletion(-) create mode 100644 src/app/shared/mappers/registration/map-registry-status.mapper.spec.ts diff --git a/src/app/features/registry/pages/registry-overview/registry-overview.component.spec.ts b/src/app/features/registry/pages/registry-overview/registry-overview.component.spec.ts index d8833dd28..b54daa675 100644 --- a/src/app/features/registry/pages/registry-overview/registry-overview.component.spec.ts +++ b/src/app/features/registry/pages/registry-overview/registry-overview.component.spec.ts @@ -184,6 +184,15 @@ describe('RegistryOverviewComponent', () => { expect(component.canMakeDecision()).toBe(false); }); + it('should compute canMakeDecision as false for a rejected registration in moderator mode', () => { + const { component } = setup({ + registry: { ...MOCK_REGISTRATION_OVERVIEW_MODEL, reviewsState: RegistrationReviewStates.Rejected }, + queryParams: { mode: 'moderator' }, + }); + + expect(component.canMakeDecision()).toBe(false); + }); + it('should compute canUpdate as true when admin access and provider updates are allowed', () => { const { component } = setup({ registry: MOCK_REGISTRATION_OVERVIEW_MODEL, diff --git a/src/app/features/registry/pages/registry-overview/registry-overview.component.ts b/src/app/features/registry/pages/registry-overview/registry-overview.component.ts index fcf3bbac3..c3ede2ca4 100644 --- a/src/app/features/registry/pages/registry-overview/registry-overview.component.ts +++ b/src/app/features/registry/pages/registry-overview/registry-overview.component.ts @@ -111,7 +111,11 @@ export class RegistryOverviewComponent implements OnInit, OnDestroy { readonly showToolbar = computed(() => !this.registry()?.archiving && !this.registry()?.withdrawn); readonly isInitialState = computed(() => this.registry()?.reviewsState === RegistrationReviewStates.Initial); readonly canMakeDecision = computed( - () => !this.registry()?.archiving && !this.registry()?.withdrawn && this.isModeration() + () => + !this.registry()?.archiving && + !this.registry()?.withdrawn && + this.registry()?.reviewsState !== RegistrationReviewStates.Rejected && + this.isModeration() ); readonly canUpdate = computed(() => this.hasAdminAccess() && this.allowUpdates()); diff --git a/src/app/shared/components/status-badge/status-badge.component.spec.ts b/src/app/shared/components/status-badge/status-badge.component.spec.ts index 929db9184..fe5f99415 100644 --- a/src/app/shared/components/status-badge/status-badge.component.spec.ts +++ b/src/app/shared/components/status-badge/status-badge.component.spec.ts @@ -37,6 +37,13 @@ describe('StatusBadgeComponent', () => { expect(component.severity()).toBe('success'); }); + it('should map rejected status to label and severity', () => { + setup(RegistryStatus.Rejected); + + expect(component.label()).toBe('shared.statuses.rejected'); + expect(component.severity()).toBe('danger'); + }); + it('should not render tag when status label is empty', () => { setup(RegistryStatus.None); diff --git a/src/app/shared/constants/registration-statuses.ts b/src/app/shared/constants/registration-statuses.ts index d83bd52e5..3e9661d91 100644 --- a/src/app/shared/constants/registration-statuses.ts +++ b/src/app/shared/constants/registration-statuses.ts @@ -21,6 +21,7 @@ export const RegistryStatusMap: Record = { [RegistryStatus.InProgress]: { label: 'shared.statuses.inProgress', severity: 'info' }, [RegistryStatus.PendingModeration]: { label: 'shared.statuses.pendingModeration', severity: 'warn' }, [RegistryStatus.Withdrawn]: { label: 'shared.statuses.withdrawn', severity: 'danger' }, + [RegistryStatus.Rejected]: { label: 'shared.statuses.rejected', severity: 'danger' }, [RegistryStatus.UpdatePendingApproval]: { label: 'shared.statuses.updatePendingApproval', severity: 'warn' }, [RegistryStatus.InitialApproved]: { label: 'shared.statuses.initialApproved', severity: 'warn' }, }; diff --git a/src/app/shared/enums/registry-status.enum.ts b/src/app/shared/enums/registry-status.enum.ts index 003f36295..f9c8fba21 100644 --- a/src/app/shared/enums/registry-status.enum.ts +++ b/src/app/shared/enums/registry-status.enum.ts @@ -12,6 +12,7 @@ export enum RegistryStatus { InProgress = 'inProgress', PendingModeration = 'pendingModeration', Withdrawn = 'withdrawn', + Rejected = 'rejected', UpdatePendingApproval = 'updatePendingApproval', InitialApproved = 'initialApproved', } diff --git a/src/app/shared/mappers/registration/map-registry-status.mapper.spec.ts b/src/app/shared/mappers/registration/map-registry-status.mapper.spec.ts new file mode 100644 index 000000000..99e66db7d --- /dev/null +++ b/src/app/shared/mappers/registration/map-registry-status.mapper.spec.ts @@ -0,0 +1,30 @@ +import { RegistrationReviewStates } from '@osf/shared/enums/registration-review-states.enum'; +import { RegistryStatus } from '@osf/shared/enums/registry-status.enum'; +import { RevisionReviewStates } from '@osf/shared/enums/revision-review-states.enum'; +import { RegistrationAttributesJsonApi } from '@shared/models/registration/registration-json-api.model'; + +import { MapRegistryStatus } from './map-registry-status.mapper'; + +describe('MapRegistryStatus', () => { + function attributes(overrides: Partial): RegistrationAttributesJsonApi { + return overrides as RegistrationAttributesJsonApi; + } + + it('should map a moderator-rejected registration to the rejected status', () => { + const status = MapRegistryStatus( + attributes({ + reviews_state: RegistrationReviewStates.Rejected, + revision_state: 'moderator_rejected' as RevisionReviewStates, + }) + ); + + expect(status).toBe(RegistryStatus.Rejected); + }); + + it('should keep mapping an accepted registration to the accepted status', () => { + const status = MapRegistryStatus( + attributes({ reviews_state: RegistrationReviewStates.Accepted, revision_state: RevisionReviewStates.Approved }) + ); + expect(status).toBe(RegistryStatus.Accepted); + }); +}); diff --git a/src/app/shared/mappers/registration/map-registry-status.mapper.ts b/src/app/shared/mappers/registration/map-registry-status.mapper.ts index 94e3c5da4..b44bb0e05 100644 --- a/src/app/shared/mappers/registration/map-registry-status.mapper.ts +++ b/src/app/shared/mappers/registration/map-registry-status.mapper.ts @@ -42,6 +42,8 @@ export function MapRegistryStatus( return RegistryStatus.PendingWithdraw; } else if (registry.reviews_state === RegistrationReviewStates.Withdrawn) { return RegistryStatus.Withdrawn; + } else if (registry.reviews_state === RegistrationReviewStates.Rejected) { + return RegistryStatus.Rejected; } else if ( registry.reviews_state === RegistrationReviewStates.Initial && registry.revision_state === RevisionReviewStates.Approved diff --git a/src/assets/i18n/en.json b/src/assets/i18n/en.json index 26437b779..485bac0d8 100644 --- a/src/assets/i18n/en.json +++ b/src/assets/i18n/en.json @@ -2333,6 +2333,11 @@ "short": "Pending withdraw request", "text": "Pending withdrawal" }, + "rejected": { + "long": "This registration was not accepted by the registry moderators and is visible only to its contributors and the registry moderators. Its draft was returned to the contributors so they can make edits and resubmit.", + "short": "Rejected by moderators", + "text": "Rejected" + }, "updatePendingApproval": { "long": "This registration has an update that is waiting for approval from its contributors. Updates will be made available once approved.", "short": "Update pending approval", @@ -2938,6 +2943,7 @@ "pendingRegistrationApproval": "Pending registration approval", "pendingWithdraw": "Pending withdrawal", "pendingWithdrawRequest": "Pending withdraw request", + "rejected": "Rejected", "unapproved": "Unapproved", "updatePendingApproval": "Update pending approval", "withdrawn": "Withdrawn"