From 2a72c38040ef12e291a92962ed6d5d59687becfe Mon Sep 17 00:00:00 2001 From: DarKylX Date: Sun, 18 Oct 2026 14:34:03 +0300 Subject: [PATCH] fix: explain submitted drafts excluded from expert allocation --- .../program/evaluation-workspace.model.ts | 7 ++++ .../management/experts/experts.component.html | 31 ++++++++++++++++-- .../experts/experts.component.spec.ts | 32 +++++++++++++++++++ 3 files changed, 67 insertions(+), 3 deletions(-) diff --git a/projects/social_platform/src/app/domain/program/evaluation-workspace.model.ts b/projects/social_platform/src/app/domain/program/evaluation-workspace.model.ts index 776f1cb5e..0aa577f7b 100644 --- a/projects/social_platform/src/app/domain/program/evaluation-workspace.model.ts +++ b/projects/social_platform/src/app/domain/program/evaluation-workspace.model.ts @@ -18,6 +18,7 @@ export interface ExpertWorkspace { managedEvaluation: boolean; submittedProjects: number; projectsMissingExperts?: number; + unavailableProjects?: UnavailableEvaluationProject[]; missingAssignments: number; readyProjects: number; experts: ExpertRow[]; @@ -45,8 +46,14 @@ export interface AllocationPlan { planToken: string; assignments: { projectId: number; projectName: string; expertId: number; expertName: string }[]; shortages: { projectId: number; projectName: string; missing: number }[]; + unavailableProjects?: UnavailableEvaluationProject[]; load: { expertId: number; name: string; before: number; after: number }[]; } +export interface UnavailableEvaluationProject { + projectId: number; + projectName: string; + reason: "draft"; +} export interface QuotaPreview { revision: string; requiredEvaluators: number; diff --git a/projects/social_platform/src/app/ui/pages/program/management/experts/experts.component.html b/projects/social_platform/src/app/ui/pages/program/management/experts/experts.component.html index d3ad30a9c..08b5a8911 100644 --- a/projects/social_platform/src/app/ui/pages/program/management/experts/experts.component.html +++ b/projects/social_platform/src/app/ui/pages/program/management/experts/experts.component.html @@ -50,7 +50,17 @@

Эксперты

Можно распределить автоматически или назначить вручную.

} @else if (state.submittedProjects) { -

Для всех сданных проектов выбран нужный состав экспертов.

+

Для всех доступных к оценке проектов выбран нужный состав экспертов.

+ } + @if (state.unavailableProjects?.length) { +

+ Среди сданных проектов есть черновики. Они станут доступны экспертам после публикации + автором: + @for (project of state.unavailableProjects; track project.projectId) { + {{ project.projectName }}{{ $last ? "." : ", " }} + } +

} @@ -316,6 +326,20 @@

{{ dialogTitle() }}

} } @case ("auto") { + @if ((plan()?.unavailableProjects ?? snapshot()?.unavailableProjects)?.length) { +
+ Эти проекты пока недоступны экспертам: + @for ( + project of plan()?.unavailableProjects ?? snapshot()?.unavailableProjects; + track project.projectId + ) { +

{{ project.projectName }} — черновик. Автору нужно опубликовать проект.

+ } +

+ Распределим остальные сданные проекты. Уже выбранные эксперты и оценки сохранятся. +

+
+ } @if (plan(); as preview) { @if (preview.shortages.length) {

@@ -352,7 +376,8 @@

Кто будет оценивать проекты

} @if (!preview.assignments.length && !preview.shortages.length) {

- Для всех проектов уже выбран нужный состав экспертов. Добавлять никого не нужно. + Для всех доступных к оценке проектов уже выбран нужный состав экспертов. Добавлять + никого не нужно.

} @@ -387,7 +412,7 @@

Кто будет оценивать проекты

{{ snapshot()?.submittedProjects }} проектов.

} @else { -

Для всех сданных проектов уже выбран нужный состав экспертов.

+

Для всех доступных к оценке проектов уже выбран нужный состав экспертов.

} } diff --git a/projects/social_platform/src/app/ui/pages/program/management/experts/experts.component.spec.ts b/projects/social_platform/src/app/ui/pages/program/management/experts/experts.component.spec.ts index ea5b41055..ca50e5d93 100644 --- a/projects/social_platform/src/app/ui/pages/program/management/experts/experts.component.spec.ts +++ b/projects/social_platform/src/app/ui/pages/program/management/experts/experts.component.spec.ts @@ -8,6 +8,38 @@ import { ManagementExpertsComponent } from "./experts.component"; import { ExpertWorkspace, AssignmentOptions } from "@domain/program/evaluation-workspace.model"; describe("Управление экспертами", () => { + it("объясняет исключённый черновик в составе и пустом плане распределения", async () => { + const { fixture, component } = setup(); + const unavailableProjects = [ + { projectId: 99, projectName: "Проект-черновик", reason: "draft" as const }, + ]; + component.snapshot.update(state => ({ ...state!, unavailableProjects })); + fixture.detectChanges(); + expect(fixture.nativeElement.querySelector(".experts__quota").textContent).toContain( + "Среди сданных проектов есть черновики", + ); + component.open("auto"); + fixture.detectChanges(); + await new Promise(resolve => setTimeout(resolve, 0)); + fixture.detectChanges(); + let dialog = document.querySelector(".experts__dialog")!; + expect(dialog.textContent).toContain("Проект-черновик — черновик"); + component.plan.set({ + revision: "v1", + planToken: "signed", + assignments: [], + shortages: [], + load: [], + unavailableProjects, + }); + fixture.detectChanges(); + dialog = document.querySelector(".experts__dialog")!; + expect(dialog.textContent).toContain("Для всех доступных к оценке проектов"); + expect(dialog.textContent).toContain("Автору нужно опубликовать проект"); + expect((dialog.querySelector("button[appButton=primary]") as HTMLButtonElement).disabled).toBe( + true, + ); + }); it("различает нехватку состава экспертов и полученные оценки", () => { const { fixture, component } = setup(); component.snapshot.update(state => ({