From e90cad7e88a5feb14ade28ecf4b7829b49d46560 Mon Sep 17 00:00:00 2001 From: "gorbenko.pavel" Date: Wed, 26 Aug 2026 10:43:40 +0500 Subject: [PATCH] =?UTF-8?q?fix:=20=D1=82=D0=B0=D0=B1=D0=BB=D0=B8=D1=86?= =?UTF-8?q?=D0=B0=20=D0=BE=D1=80=D0=B3=D0=B0=D0=BD=D0=B8=D0=B7=D0=B0=D1=86?= =?UTF-8?q?=D0=B8=D0=B9=20=E2=80=94=20=C2=AB=D0=A1=D1=82=D1=80=D1=83=D0=BA?= =?UTF-8?q?=D1=82=D1=83=D1=80=D0=BD=D0=BE=D0=B5=20=D0=BF=D0=BE=D0=B4=D1=80?= =?UTF-8?q?=D0=B0=D0=B7=D0=B4=D0=B5=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=C2=BB,?= =?UTF-8?q?=20=D0=B4=D0=BE=D0=BB=D0=B6=D0=BD=D0=BE=D1=81=D1=82=D0=B8=20?= =?UTF-8?q?=D0=B2=D1=81=D0=B5=20=D1=80=D0=B5=D0=B4=D0=B0=D0=BA=D1=82=D0=B8?= =?UTF-8?q?=D1=80=D1=83=D0=B5=D0=BC=D1=8B,=20=D0=B1=D0=B5=D0=B7=20=D0=BB?= =?UTF-8?q?=D0=B8=D1=88=D0=BD=D0=B5=D0=B9=20=D0=BF=D0=BE=D0=B4=D0=BF=D0=B8?= =?UTF-8?q?=D1=81=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Три правки в OrganizationsTable по месту (без изменений схемы/формата хранения — поле по-прежнему называется department, источник тот же Section): 1. Заголовок колонки «Департамент» → «Структурное подразделение». 2. Должность редактируема В КАЖДОЙ строке, не только у первой (основной) компании — справочник не всегда точен, поправить нужно любую. На маршрут и валидацию по-прежнему влияет только должность ПЕРВОЙ записи (primaryPosition) — остальные редактируются, но ни на что не влияют. onChangePosition получил индекс строки вместо неявного «всегда нулевая». 3. Убрана обёртка FormField с подписью «Организация · подразделение · должность *» над таблицей — избыточна, у таблицы уже есть заголовки колонок. full-ширина (grid-column: 1/-1) взята напрямую в CSS, без FormField (у него label обязателен). Co-Authored-By: Claude Opus 5 --- .../requestPortal/forms/Dismissal/README.md | 26 +++++++------- .../sections/OrganizationsTable.module.scss | 8 +++++ .../Dismissal/sections/OrganizationsTable.tsx | 34 ++++++++++++------- .../Dismissal/sections/RequestSection.tsx | 6 ++-- 4 files changed, 46 insertions(+), 28 deletions(-) diff --git a/src/webparts/requestPortal/forms/Dismissal/README.md b/src/webparts/requestPortal/forms/Dismissal/README.md index 28e3e2d..8be7d0b 100644 --- a/src/webparts/requestPortal/forms/Dismissal/README.md +++ b/src/webparts/requestPortal/forms/Dismissal/README.md @@ -28,20 +28,22 @@ RequestTypeId» в `docs/forms.md`). Тип заведён в админке app People-picker (`Employee`), маршрут резолвится по e-mail **выбранного** сотрудника, reloadKey матрицы включает `data.Employee` и должность основной компании (см. ниже). - **Автоподстановка при выборе сотрудника:** вся таблица организаций — из ОДНОГО - справочника `Employee/ByEmail` (`shared/dictionary`) — см. «Организация · - подразделение · должность». -- **«Организация · подразделение · должность»** (`OrganizationsTable`, - `forms/Dismissal/sections/`) — ЕДИНСТВЕННОЕ место для компании, департамента и + справочника `Employee/ByEmail` (`shared/dictionary`) — см. ниже. +- **Таблица организаций** (`OrganizationsTable`, `forms/Dismissal/sections/`, без + подписи над собой — у неё уже есть заголовки колонок «Компания» / «Структурное + подразделение» / «Должность») — ЕДИНСТВЕННОЕ место для компании, подразделения и должности, и на форме подачи (редактируемая), и в режиме просмотра (read-only) — отдельных полей для них нет (были бы дублированием). `data.Organization: - IOrganizationRecord[]` — массив `{company, department, position}`, компания и - департамент по каждой строке read-only; редактируется только должность ПЕРВОЙ - (основной) записи — `primaryPosition(data.Organization)`, используется маршрутом - (условие «IsManager») и обязательна валидацией; должности остальных компаний - (совместитель) — информационные. Справочник ничего не вернул (сотрудник не найден - в api.tnsu.kz) — таблица всё равно рендерится одной строкой с прочерками вместо - компании/департамента и редактируемой должностью: иначе такому человеку нечем было - бы заполнить обязательное поле. + IOrganizationRecord[]` — массив `{company, department, position}`; поле называется + `department` (тот же справочник `Section`, что и раньше — см. следующий абзац), + колонка называется «Структурное подразделение», и то и другое read-only. Должность + редактируема В ЛЮБОЙ строке (справочник не всегда точен), но маршрут (условие + «IsManager») и обязательность по валидации завязаны ТОЛЬКО на должность ПЕРВОЙ + (основной) записи — `primaryPosition(data.Organization)`; должности остальных + компаний правятся, но ни на что не влияют. Справочник ничего не вернул (сотрудник + не найден в api.tnsu.kz) — таблица всё равно рендерится одной строкой с прочерками + вместо компании/подразделения и редактируемой должностью: иначе такому человеку + нечем было бы заполнить обязательное поле. **Хранение в SharePoint — три ПАРАЛЛЕЛЬНЫХ JSON-столбца**, не один общий блок: `Organization`/`Department`/`Position` — каждый содержит JSON-массив строк diff --git a/src/webparts/requestPortal/forms/Dismissal/sections/OrganizationsTable.module.scss b/src/webparts/requestPortal/forms/Dismissal/sections/OrganizationsTable.module.scss index ae32ded..53de8a3 100644 --- a/src/webparts/requestPortal/forms/Dismissal/sections/OrganizationsTable.module.scss +++ b/src/webparts/requestPortal/forms/Dismissal/sections/OrganizationsTable.module.scss @@ -1,5 +1,13 @@ @import '../../../../../styles/design-tokens'; +// Занять обе колонки сетки формы — то же, что даёт проп full у FormField +// (._full_1wk7n_8{grid-column:1/-1} в @tnsu/ui-kit), без самого FormField: +// подпись над таблицей не нужна, у неё уже есть заголовки колонок. +.wrapper { + grid-column: 1 / -1; + min-width: 0; +} + .table { width: 100%; border-collapse: collapse; diff --git a/src/webparts/requestPortal/forms/Dismissal/sections/OrganizationsTable.tsx b/src/webparts/requestPortal/forms/Dismissal/sections/OrganizationsTable.tsx index dbaeaeb..184cdd3 100644 --- a/src/webparts/requestPortal/forms/Dismissal/sections/OrganizationsTable.tsx +++ b/src/webparts/requestPortal/forms/Dismissal/sections/OrganizationsTable.tsx @@ -1,18 +1,18 @@ import * as React from 'react'; -import { FormField, Icon, TextInput } from '../../../shared/ui'; +import { Icon, TextInput } from '../../../shared/ui'; import { IOrganizationRecord } from '../model'; import styles from './OrganizationsTable.module.scss'; interface IOrganizationsTableProps { records: IOrganizationRecord[]; /** - * Должность ПЕРВОЙ (основной) компании редактируема — единственная ячейка - * таблицы, у которой это так: маршрут согласования резолвится по НЕЙ (см. - * DismissalForm — fieldValues.Position), должности остальных компаний - * (совместитель) — только для просмотра, ставить им что-то в соответствие - * незачем. Не задано — вся таблица read-only (режим просмотра, DismissalView). + * Должность любой строки можно поправить — справочник не всегда точен, а + * условие маршрута «IsManager» резолвится по должности ПЕРВОЙ (основной) + * компании (см. DismissalForm — primaryPosition/fieldValues.Position), так + * что расхождение со справочником там, где оно есть, важно уметь исправить. + * Не задано — вся таблица read-only (режим просмотра, DismissalView). */ - onChangePosition?: (value: string) => void; + onChangePosition?: (index: number, value: string) => void; /** * Убрать компанию из заявления — есть только на форме подачи (см. * DismissalForm.handleRemoveOrganization), не в режиме просмотра: там состав @@ -22,7 +22,7 @@ interface IOrganizationsTableProps { } /** - * Организации сотрудника — ЕДИНСТВЕННОЕ место для компании/департамента/ + * Организации сотрудника — ЕДИНСТВЕННОЕ место для компании/подразделения/ * должности, и на форме подачи (редактируемая — см. onChangePosition/onRemove), * и в режиме просмотра заявки (read-only, те же данные из сохранённой заявки, * а не live-запрос к справочнику — см. DismissalView). Раньше это были @@ -42,17 +42,21 @@ interface IOrganizationsTableProps { * редактируемой должностью: без этого заявление на человека без карточки в * справочнике нельзя было бы подать вовсе (некуда вписать должность вручную — * а маршрут согласования без неё не резолвит условие «IsManager»). + * + * Без обёртки FormField/подписи над таблицей намеренно — у нёе уже есть + * заголовки колонок, дублировать их общей подписью незачем; full-ширина взята + * напрямую (см. .wrapper), а не через FormField (там label обязателен). */ export const OrganizationsTable: React.FC = ({ records, onChangePosition, onRemove }) => { const rows = records.length > 0 ? records : [undefined]; return ( - +
- + {onRemove && @@ -62,9 +66,13 @@ export const OrganizationsTable: React.FC = ({ records - {i === 0 && onChangePosition ? ( + {onChangePosition ? ( ) : ( @@ -88,6 +96,6 @@ export const OrganizationsTable: React.FC = ({ records ))}
КомпанияДепартаментСтруктурное подразделение Должность}
{r?.company || '—'} {r?.department || '—'} - + onChangePosition(i, v)} + placeholder="Введите должность" + /> {r?.position || '—'}
- +
); }; diff --git a/src/webparts/requestPortal/forms/Dismissal/sections/RequestSection.tsx b/src/webparts/requestPortal/forms/Dismissal/sections/RequestSection.tsx index b7186c3..3b65fe8 100644 --- a/src/webparts/requestPortal/forms/Dismissal/sections/RequestSection.tsx +++ b/src/webparts/requestPortal/forms/Dismissal/sections/RequestSection.tsx @@ -37,7 +37,7 @@ export const RequestSection: React.FC = ({ placeholder={EMPLOYEE_PLACEHOLDER} />
- {/* ЕДИНСТВЕННОЕ место для компании/департамента/должности — и на форме + {/* ЕДИНСТВЕННОЕ место для компании/подразделения/должности — и на форме подачи (редактируемая, onRemoveOrganization задан), и в просмотре (read-only, ничего не передано). Отдельных полей для них нет — были бы дублированием того, что уже показывает эта таблица. */} @@ -45,11 +45,11 @@ export const RequestSection: React.FC = ({ records={data.Organization} onChangePosition={ onRemoveOrganization && - ((v) => + ((i, v) => set( 'Organization', data.Organization.length > 0 - ? data.Organization.map((r, i) => (i === 0 ? { ...r, position: v } : r)) + ? data.Organization.map((r, ri) => (ri === i ? { ...r, position: v } : r)) : [{ company: '', department: '', position: v }] )) }