From 3f9595928e6c61c363c9b083f379617fbc976ec4 Mon Sep 17 00:00:00 2001 From: PotapovaA Date: Thu, 25 Jun 2026 11:20:29 +0300 Subject: [PATCH 1/2] =?UTF-8?q?=D1=8D=D1=82=D0=B0=D0=BF=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- web/src/api/form_sheet.js | 7 +++- .../RealtimeTable/RealtimeTable.jsx | 3 +- .../AuditLogsPage/AuditLogsPage.jsx | 4 +- .../components/AuditLogsTable.jsx | 9 ++--- .../AuditLogsPage/constants/auditLogs.jsx | 6 +-- .../AuditLogsPage/constants/configEvent.jsx | 16 ++++++-- .../AuditLogsPage/utils/transformers.jsx | 37 ++++++++++++++++++- .../components/StyledTable/TableFooter.jsx | 4 +- web/src/pages/DictVspPage/DictVspPage.jsx | 2 +- .../DictsNavigatorPage/DictsNavigatorPage.jsx | 9 +++-- 10 files changed, 75 insertions(+), 22 deletions(-) diff --git a/web/src/api/form_sheet.js b/web/src/api/form_sheet.js index 4d6220e..73a5bab 100644 --- a/web/src/api/form_sheet.js +++ b/web/src/api/form_sheet.js @@ -1,4 +1,4 @@ -import api from './client'; +import api from "./client"; export const FormsSheetApi = { get(formId, sheetName, params) { @@ -9,7 +9,10 @@ export const FormsSheetApi = { export(formId, sheetName, params = {}) { return api.get(`export/form/${formId}/sheet/${sheetName}`, { params, - responseType: 'blob', + responseType: "blob", }); }, + getExpenseItem(itemId) { + return api.get(`/expense-item/${itemId}`).then((r) => r.data); + }, }; diff --git a/web/src/components/RealtimeTable/RealtimeTable.jsx b/web/src/components/RealtimeTable/RealtimeTable.jsx index 8a0e1c3..d1fc390 100644 --- a/web/src/components/RealtimeTable/RealtimeTable.jsx +++ b/web/src/components/RealtimeTable/RealtimeTable.jsx @@ -151,7 +151,7 @@ const RealtimeTable = ({ formType, formId, sheetName, direction }) => { if (isPinned) { const colId = table.getState().columnPinning.left[index]; const column = table.getColumn(colId); - return column.columnDef.size; + return column?.getSize() ?? 150; } const allCols = [...table.getLeftVisibleLeafColumns(), ...table.getCenterVisibleLeafColumns()] return allCols[index]?.getSize() ?? 150; @@ -243,7 +243,6 @@ const RealtimeTable = ({ formType, formId, sheetName, direction }) => { toast.error('Ошибка редактирования ячейки'); } }, [dataEditingCells, editingCell]); - console.log(editingCell) useEffect(() => { if (table && data && columns.length !== 0) { diff --git a/web/src/pages/AdminPanel/AuditLogsPage/AuditLogsPage.jsx b/web/src/pages/AdminPanel/AuditLogsPage/AuditLogsPage.jsx index e8fe696..ffffcd6 100644 --- a/web/src/pages/AdminPanel/AuditLogsPage/AuditLogsPage.jsx +++ b/web/src/pages/AdminPanel/AuditLogsPage/AuditLogsPage.jsx @@ -137,7 +137,9 @@ const AuditLogsPage = () => { return ( - + diff --git a/web/src/pages/AdminPanel/AuditLogsPage/components/AuditLogsTable.jsx b/web/src/pages/AdminPanel/AuditLogsPage/components/AuditLogsTable.jsx index 5e1c533..683daab 100644 --- a/web/src/pages/AdminPanel/AuditLogsPage/components/AuditLogsTable.jsx +++ b/web/src/pages/AdminPanel/AuditLogsPage/components/AuditLogsTable.jsx @@ -77,9 +77,9 @@ const AuditLogsTable = ({ {row.original.user ? row.original.user.full_name + - ' (' + - row.original.user.email + - ')' + ' (' + + row.original.user.email + + ')' : '-'} @@ -118,8 +118,7 @@ const AuditLogsTable = ({ size: 250, Cell: ({ row }) => ( - {getRussianNamesForType(row.original.action) || - row.original.event_type} + {getRussianNamesForType(row.original.action) } ), enableColumnActions: false, diff --git a/web/src/pages/AdminPanel/AuditLogsPage/constants/auditLogs.jsx b/web/src/pages/AdminPanel/AuditLogsPage/constants/auditLogs.jsx index f79554a..a00c098 100644 --- a/web/src/pages/AdminPanel/AuditLogsPage/constants/auditLogs.jsx +++ b/web/src/pages/AdminPanel/AuditLogsPage/constants/auditLogs.jsx @@ -1,21 +1,19 @@ export const DEFAULT_ACTIONS = { ROW_CREATE: 'Создание строки', ROW_DELETE: 'Удаление строки', - ACCESS_WINDOW_CHANGE: 'Изменение окна доступа', ACCESS_EXTEND: 'Расширение доступа', + ACCESS_WINDOW_CHANGE: 'Изменение окна доступа', USER_ROLE_CHANGE: 'Изменение роли пользователя', CREATE_TASK: 'Создание задачи', UPDATE_TASK: 'Обновление задачи', DELETE_TASK: 'Удаление задачи', USER_CREATE: 'Создание пользователя', - LOGIN: 'Вход в систему', USER_ACCESS_GRANTED: 'Предоставление доступа к ССП/РФ', USER_ACCESS_REVOKED: 'Отмена доступа к ССП/РФ', VSP_CREATE: 'Создание ВСП', }; export const ENTITY_RUSSIAN_NAMES = { - LOGIN: 'Вход в систему', ROW: 'строки', PROJECT: 'проекта', TABLE: 'таблицы', @@ -26,6 +24,7 @@ export const ENTITY_RUSSIAN_NAMES = { USER_ACCESS: 'доступа к ССП/РФ', USER: 'пользователя', ACCESS_WINDOW: 'окна доступа', + ACCESS: 'окна доступа', USER_ROLE: 'роли пользователя', VSP: 'ВСП', }; @@ -38,6 +37,7 @@ export const ACTION_RUSSIAN_NAMES = { GET: 'Получение', GRANTED: 'Предоставление', REVOKED: 'Отмена', + EXTEND: 'Расширение', }; export const getRussianNamesForType = (name) => { diff --git a/web/src/pages/AdminPanel/AuditLogsPage/constants/configEvent.jsx b/web/src/pages/AdminPanel/AuditLogsPage/constants/configEvent.jsx index 8948f2b..48b0616 100644 --- a/web/src/pages/AdminPanel/AuditLogsPage/constants/configEvent.jsx +++ b/web/src/pages/AdminPanel/AuditLogsPage/constants/configEvent.jsx @@ -56,11 +56,15 @@ export const EVENT_CONFIGS = { }, ROW_CREATE: { sheet: "Лист", - expense_item_id: 'Статья расходов' + expense_item_id: 'Статья расходов', + form_id: 'Информация о задаче', + direction: 'Направление', }, ROW_DELETE: { sheet: "Лист", - expense_item_id: 'Статья расходов' + expense_item_id: 'Статья расходов', + form_id: 'Информация о задаче', + direction: 'Направление', }, PROJECT_CREATE: { "name": "Название", @@ -71,5 +75,11 @@ export const EVENT_CONFIGS = { "name": "Название", "year": "Год", "org_unit_id": "СПП/РФ", - } + }, + ACCESS_EXTEND:{ + form_id: 'Информация о задаче', + closes_at_after: 'Дата закрытия', + closes_at_before: 'Дата открытия', + phase_name: 'Названия этапа' + }, }; diff --git a/web/src/pages/AdminPanel/AuditLogsPage/utils/transformers.jsx b/web/src/pages/AdminPanel/AuditLogsPage/utils/transformers.jsx index 9f388aa..e3d123c 100644 --- a/web/src/pages/AdminPanel/AuditLogsPage/utils/transformers.jsx +++ b/web/src/pages/AdminPanel/AuditLogsPage/utils/transformers.jsx @@ -1,8 +1,10 @@ import { DictVspApi } from '../../../../api/dict-vsp'; +import { FormsSheetApi } from '../../../../api/form_sheet'; +import { FormsApi } from '../../../../api/forms'; import { SspApi } from '../../../../api/ssp'; import { TasksApi } from '../../../../api/tasks'; import { UsersApi } from '../../../../api/users'; -import { ROLES_ID_RUSSIAN_NAME, SHEET_NAME } from '../../../../constants'; +import { DIRECTION_TRANSLATE, FROM_TYPE_TRANSLATE, ROLES_ID_RUSSIAN_NAME, SHEET_NAME } from '../../../../constants'; export const VALUE_TRANSFORMERS = { Роль: transformRole, @@ -14,6 +16,9 @@ export const VALUE_TRANSFORMERS = { 'Создана для СПП/РФ': transformSspsDict, 'Лист': transformSheet, 'СПП/РФ': transformSsp, + 'Статья расходов': transformExpense, + 'Информация о задаче': transformForm, + 'Направление': transformDirection }; export function transformRole(value) { @@ -83,3 +88,33 @@ export async function transformSspsDict(ssps) { export function transformSheet(value) { return SHEET_NAME[value] || 'Лист не найден'; } + +export async function transformExpense(itemId) { + if (!itemId) { + return 'нет информации' + } + const res = await FormsSheetApi.getExpenseItem(itemId); + const expense = res.result; + return expense.name; +} + +export async function transformForm(formId) { + if (!formId) { + return 'нет информации' + } + const res = await FormsApi.getForm(formId); + const form = res.result; + const formInfo = { + 'название': FROM_TYPE_TRANSLATE[form.form_type_code], + 'ССП/РФ': form.org_unit.title, + 'Год': form.year, + } + return formInfo +} + +export function transformDirection(direction){ + if (!direction){ + return '-'; + } + return DIRECTION_TRANSLATE[direction]; +} \ No newline at end of file diff --git a/web/src/pages/AdminPanel/components/StyledTable/TableFooter.jsx b/web/src/pages/AdminPanel/components/StyledTable/TableFooter.jsx index fe0f8fa..1fc9aef 100644 --- a/web/src/pages/AdminPanel/components/StyledTable/TableFooter.jsx +++ b/web/src/pages/AdminPanel/components/StyledTable/TableFooter.jsx @@ -95,7 +95,9 @@ const TableFooter = ({ - + {/* */} - + {user.role_id !== ROLES_NAME_ID.executor_rf && (

Открыть справочник объектов

From 761a435b989f7a4de46a47ddd5130abf8bbf4272 Mon Sep 17 00:00:00 2001 From: PotapovaA Date: Thu, 25 Jun 2026 18:20:18 +0300 Subject: [PATCH 2/2] AURORA-1134 --- web/src/api/stages.js | 7 +- web/src/components/Stages/AddStagesModal.jsx | 14 +-- .../components/common/TaskCardComponent.jsx | 4 +- web/src/constants.jsx | 2 +- .../AuditLogsPage/AuditLogsPage.jsx | 2 +- .../components/AuditLogsFilters.jsx | 26 ----- .../components/JsonViewModal.jsx | 39 +++++-- .../AuditLogsPage/constants/auditLogs.jsx | 15 +-- .../AuditLogsPage/constants/configEvent.jsx | 38 +++++-- .../AuditLogsPage/utils/transformers.jsx | 100 +++++++++++++++++- .../AdminPanel/UsersPage/ModalEditUserSsp.jsx | 15 ++- .../UsersPage/UserTable/EditUserModal.jsx | 4 +- .../AutocompleteForChangeOptions.jsx | 2 +- web/src/pages/TaskPage/TaskPage.jsx | 4 +- web/src/pages/TasksPage/TasksPage.jsx | 6 +- 15 files changed, 185 insertions(+), 93 deletions(-) diff --git a/web/src/api/stages.js b/web/src/api/stages.js index 8fb0ecd..d680d97 100644 --- a/web/src/api/stages.js +++ b/web/src/api/stages.js @@ -5,13 +5,10 @@ export const StagesApi = { return api.post(`/stages/form/${formId}`, payload).then((r) => r.data); }, updateStage(payload) { - const { budget_form_id, sheet, phase_code, opens_at, closes_at } = payload; + const { budget_form_id, sheet, phase_code } = payload; return api - .patch(`/stages/form/${budget_form_id}/${sheet}/${phase_code}`, { - opens_at, - closes_at, - }) + .patch(`/stages/form/${budget_form_id}/${sheet}/${phase_code}`, payload) .then((r) => r.data); }, deleteStage(formId, sheet, phaseCode) { diff --git a/web/src/components/Stages/AddStagesModal.jsx b/web/src/components/Stages/AddStagesModal.jsx index f4ac2ca..4b61bee 100644 --- a/web/src/components/Stages/AddStagesModal.jsx +++ b/web/src/components/Stages/AddStagesModal.jsx @@ -55,17 +55,9 @@ export const AddStagesModal = ({ try { const { config } = await import(`../RealtimeTable/constants/${formType}/${sheetObj.sheet}.js`); setColumnsConfig(config.config); - - // Если есть сохраненные выбранные колонки для этого листа - if (stage?.column_keys) { - setSelectedColumns(stage.column_keys); - } else { - setSelectedColumns([]); - } } catch (error) { console.error(`Failed to load config for ${formType}/${selectedSheet}:`, error); setColumnsConfig({ columns: [], colors: {} }); - setSelectedColumns([]); } }; @@ -79,10 +71,7 @@ export const AddStagesModal = ({ setStageName(stage.phase_code ?? ''); setSelectedSheet(stage.sheet ?? null); setSelectedRole(stage.role ?? null); - - if (stage.column_keys) { - setSelectedColumns(stage.column_keys.map(c => 'data.' + c)); - } + setSelectedColumns(stage.column_keys.map(c => 'data.' + c)); } else { setStartDate(null); setEndDate(null); @@ -201,6 +190,7 @@ export const AddStagesModal = ({ placeholder="Введите название этапа" fullWidth size="small" + disabled={stage !== null} />
diff --git a/web/src/components/common/TaskCardComponent.jsx b/web/src/components/common/TaskCardComponent.jsx index 473a34f..ad629ed 100644 --- a/web/src/components/common/TaskCardComponent.jsx +++ b/web/src/components/common/TaskCardComponent.jsx @@ -26,7 +26,7 @@ import { formatDate } from '../../utils/formatDate'; import { IconWithContent } from './IconWithContent'; import { Chip } from '../styles/StyledChip'; import { ExportButton } from '../common/Buttons/ButtonsActions'; -import { FROM_TYPE_TRANSLATE } from '../../constants'; +import { FORM_TYPE_TRANSLATE } from '../../constants'; const TaskCard = styled.div` width: 26.8rem; @@ -100,7 +100,7 @@ export const TaskCardComponent = ({ const [isEditModalOpen, setEditModalOpen] = useState(false); const [editedTitle, setEditedTitle] = useState(''); - const [currentTitle, setCurrentTitle] = useState(FROM_TYPE_TRANSLATE[form_type_code] ||''); + const [currentTitle, setCurrentTitle] = useState(FORM_TYPE_TRANSLATE[form_type_code] ||''); const [isChecked, setIsChecked] = useState(false); useEffect(() => { diff --git a/web/src/constants.jsx b/web/src/constants.jsx index c009ff3..65e8351 100644 --- a/web/src/constants.jsx +++ b/web/src/constants.jsx @@ -36,7 +36,7 @@ export const EDIT_ACCESS_RUSSIAN = { }; export const FORM_TYPE_OPTIONS = ['FORM_1', 'FORM_2', 'FORM_3', 'FORM_4']; -export const FROM_TYPE_TRANSLATE = { 'FORM_1': 'Смета ССП', 'FORM_2': 'Смета РФ', 'FORM_3': 'Программа развитие ПРРС', 'FORM_4': 'Проектная деятельность' }; +export const FORM_TYPE_TRANSLATE = { 'FORM_1': 'Смета ССП', 'FORM_2': 'Смета РФ', 'FORM_3': 'Программа развитие ПРРС', 'FORM_4': 'Проектная деятельность' }; export const DIRECTION_TRANSLATE = { 'Support': 'Поддержка', 'Development': 'Развитие' }; export const ORG_UNIT_TYPE_OPTIONS = [ diff --git a/web/src/pages/AdminPanel/AuditLogsPage/AuditLogsPage.jsx b/web/src/pages/AdminPanel/AuditLogsPage/AuditLogsPage.jsx index ffffcd6..9df17cb 100644 --- a/web/src/pages/AdminPanel/AuditLogsPage/AuditLogsPage.jsx +++ b/web/src/pages/AdminPanel/AuditLogsPage/AuditLogsPage.jsx @@ -70,7 +70,7 @@ const AuditLogsPage = () => { limit: rowsPerPage, user_id: selectedUser?.id, org_unit_id: selectedSsp?.id, - event_type: selectedEventType?.id, + event: selectedEventType?.id, date_from: dateFrom ? dateFrom.toISOString() : undefined, date_to: dateTo ? dateTo.toISOString() : undefined, task_id: taskId ? taskId : undefined, diff --git a/web/src/pages/AdminPanel/AuditLogsPage/components/AuditLogsFilters.jsx b/web/src/pages/AdminPanel/AuditLogsPage/components/AuditLogsFilters.jsx index 5fd8407..e48d33b 100644 --- a/web/src/pages/AdminPanel/AuditLogsPage/components/AuditLogsFilters.jsx +++ b/web/src/pages/AdminPanel/AuditLogsPage/components/AuditLogsFilters.jsx @@ -177,32 +177,6 @@ const AuditLogsFilters = ({ spacing={'1rem'} sx={{ width: '100%', alignItems: 'end' }} > - - Поиск по контексту (ID задачи) - - - - Поиск по контексту (ID формы) - - { @@ -36,6 +36,7 @@ const JsonViewModal = ({ open, onClose, jsonData, eventType }) => { async function extractInfo(data, type) { data = JSON.parse(data); const config = EVENT_CONFIGS[type] || {}; + const configForMultDependents = EVENT_CONFIGS_MULT_DEPENDENTS[type] || {}; const result = {}; // Функция для рекурсивного обхода всех узлов @@ -46,16 +47,33 @@ const JsonViewModal = ({ open, onClose, jsonData, eventType }) => { const currentPath = path ? `${path}.${key}` : key; if (config[currentPath] || config[key]) { - const configKey = config[currentPath] || config[key]; let value = obj[key]; + const configKey = config[currentPath] || config[key]; // Применяем преобразование, если есть функция для этого ключа if (VALUE_TRANSFORMERS[configKey] && value) { - const transformer = VALUE_TRANSFORMERS[configKey]; - if (transformer.constructor.name === 'AsyncFunction') { - value = await transformer(value); - } else { - value = transformer(value); + try { + // Собираем зависимости для трансформера + // По умолчанию передаём только текущее значение + const dependents = [value]; + + // Если для этого ключа есть дополнительные зависимости (другие поля) + if (configForMultDependents[configKey] || configForMultDependents[configKey]) { + configForMultDependents[configKey].forEach(d => { + // Добавляем значения из зависимых полей (в корне data) + dependents.push(data[d]); + }); + } + + const transformer = VALUE_TRANSFORMERS[configKey]; + if (transformer.constructor.name === 'AsyncFunction') { + value = await transformer(...dependents); + } else { + value = transformer(...dependents); + } + } catch (error) { + console.error(`Ошибка в трансформере для ключа "${configKey}":`, error); + value = '—'; } } @@ -69,8 +87,11 @@ const JsonViewModal = ({ open, onClose, jsonData, eventType }) => { } } - // Начинаем обход с основного объекта - await traverseAndExtract(data); + try { + await traverseAndExtract(data); + } catch (error) { + return JSON.stringify({ error: 'Ошибка при извлечении данных' }, null, 2); + } return JSON.stringify(result, null, 2); } diff --git a/web/src/pages/AdminPanel/AuditLogsPage/constants/auditLogs.jsx b/web/src/pages/AdminPanel/AuditLogsPage/constants/auditLogs.jsx index a00c098..344a520 100644 --- a/web/src/pages/AdminPanel/AuditLogsPage/constants/auditLogs.jsx +++ b/web/src/pages/AdminPanel/AuditLogsPage/constants/auditLogs.jsx @@ -1,16 +1,17 @@ export const DEFAULT_ACTIONS = { ROW_CREATE: 'Создание строки', ROW_DELETE: 'Удаление строки', - ACCESS_EXTEND: 'Расширение доступа', - ACCESS_WINDOW_CHANGE: 'Изменение окна доступа', + ACCESS_EXTEND: 'Продление этапа', + ACCESS_WINDOW_CHANGE: 'Изменение этапа', USER_ROLE_CHANGE: 'Изменение роли пользователя', CREATE_TASK: 'Создание задачи', - UPDATE_TASK: 'Обновление задачи', - DELETE_TASK: 'Удаление задачи', + // UPDATE_TASK: 'Обновление задачи', //сейчас нет события + // DELETE_TASK: 'Удаление задачи', USER_CREATE: 'Создание пользователя', USER_ACCESS_GRANTED: 'Предоставление доступа к ССП/РФ', USER_ACCESS_REVOKED: 'Отмена доступа к ССП/РФ', VSP_CREATE: 'Создание ВСП', + VSP_UPDATE: 'Обновление ВСП', }; export const ENTITY_RUSSIAN_NAMES = { @@ -23,8 +24,8 @@ export const ENTITY_RUSSIAN_NAMES = { TASK: 'задачи', USER_ACCESS: 'доступа к ССП/РФ', USER: 'пользователя', - ACCESS_WINDOW: 'окна доступа', - ACCESS: 'окна доступа', + ACCESS_WINDOW: 'этапа', + ACCESS: 'этапа', USER_ROLE: 'роли пользователя', VSP: 'ВСП', }; @@ -37,7 +38,7 @@ export const ACTION_RUSSIAN_NAMES = { GET: 'Получение', GRANTED: 'Предоставление', REVOKED: 'Отмена', - EXTEND: 'Расширение', + EXTEND: 'Продление', }; export const getRussianNamesForType = (name) => { diff --git a/web/src/pages/AdminPanel/AuditLogsPage/constants/configEvent.jsx b/web/src/pages/AdminPanel/AuditLogsPage/constants/configEvent.jsx index 48b0616..5ded6f4 100644 --- a/web/src/pages/AdminPanel/AuditLogsPage/constants/configEvent.jsx +++ b/web/src/pages/AdminPanel/AuditLogsPage/constants/configEvent.jsx @@ -6,12 +6,11 @@ export const EVENT_CONFIGS = { entity_id: 'Пользователь', }, VSP_CREATE: { - ssp_id: 'Региональный филиал', reg_number: 'Регистрационный номер ВСП', vsp_type: 'Вид ВСП', address: 'Адрес ВСП', - approved_format: 'Утвержденный формат', - open_date: 'Дата открытия ВСП', + format: 'Утвержденный формат', + opened_at: 'Дата открытия ВСП', notes: 'Примечания', location_form: 'Форма расположения ВСП', numbers: 'Штатная численность ВСП', @@ -22,14 +21,16 @@ export const EVENT_CONFIGS = { branch_name: 'Региональный филиал ', closed_at: 'Дата закрытия ВСП', user_email: 'Почта пользователя', + staff_count: 'Кол-во работников', + placement_type: 'Тип размещение', + is_active: 'Активный', }, VSP_UPDATE: { - ssp_id: 'Региональный филиал', reg_number: 'Регистрационный номер ВСП', vsp_type: 'Вид ВСП', address: 'Адрес ВСП', - approved_format: 'Утвержденный формат', - open_date: 'Дата открытия ВСП', + format: 'Утвержденный формат', + opened_at: 'Дата открытия ВСП', notes: 'Примечания', location_form: 'Форма расположения ВСП', numbers: 'Штатная численность ВСП', @@ -37,9 +38,12 @@ export const EVENT_CONFIGS = { rent_contract_num: 'Номер договора аренды', rent_end_date: 'Срок окончания договора аренды', system_code: 'Код РФ', - branch_name: 'Региональный филиал ', + 'changes.branch_name': 'Региональный филиал ', closed_at: 'Дата закрытия ВСП', user_email: 'Почта пользователя', + staff_count: 'Кол-во работников', + placement_type: 'Тип размещение', + is_active: 'Активный', }, USER_ACCESS_GRANTED: { entity_id: 'Пользователь', @@ -76,10 +80,26 @@ export const EVENT_CONFIGS = { "year": "Год", "org_unit_id": "СПП/РФ", }, - ACCESS_EXTEND:{ + ACCESS_EXTEND: { form_id: 'Информация о задаче', closes_at_after: 'Дата закрытия', closes_at_before: 'Дата открытия', - phase_name: 'Названия этапа' + phase_name: 'Названия этапа', + sheet: "Лист", + }, + ACCESS_WINDOW_CHANGE: { + form_id: 'Информация о задаче', + closes_at: 'Дата закрытия', + open_at: 'Дата открытия', + phase_name: 'Названия этапа', + role: 'Для роли', + column_keys: 'Колонки в этапе', + action: 'Действие', + sheet: "Лист", }, }; +export const EVENT_CONFIGS_MULT_DEPENDENTS = { + ACCESS_WINDOW_CHANGE: { + 'Колонки в этапе': ['form_id', 'sheet'] + }, +} \ No newline at end of file diff --git a/web/src/pages/AdminPanel/AuditLogsPage/utils/transformers.jsx b/web/src/pages/AdminPanel/AuditLogsPage/utils/transformers.jsx index e3d123c..ed49884 100644 --- a/web/src/pages/AdminPanel/AuditLogsPage/utils/transformers.jsx +++ b/web/src/pages/AdminPanel/AuditLogsPage/utils/transformers.jsx @@ -4,7 +4,7 @@ import { FormsApi } from '../../../../api/forms'; import { SspApi } from '../../../../api/ssp'; import { TasksApi } from '../../../../api/tasks'; import { UsersApi } from '../../../../api/users'; -import { DIRECTION_TRANSLATE, FROM_TYPE_TRANSLATE, ROLES_ID_RUSSIAN_NAME, SHEET_NAME } from '../../../../constants'; +import { DIRECTION_TRANSLATE, FORM_TYPE_TRANSLATE, ROLES_ID_RUSSIAN_NAME, SHEET_NAME, STAGE_ROLE_RUSSIAN_NAME } from '../../../../constants'; export const VALUE_TRANSFORMERS = { Роль: transformRole, @@ -18,12 +18,28 @@ export const VALUE_TRANSFORMERS = { 'СПП/РФ': transformSsp, 'Статья расходов': transformExpense, 'Информация о задаче': transformForm, - 'Направление': transformDirection + 'Направление': transformDirection, + 'Для роли': transformRoleChanges, + 'Колонки в этапе': transformColumns, + 'Форма': transformFormType, }; export function transformRole(value) { return ROLES_ID_RUSSIAN_NAME[value] || 'Роль не найдена'; } +export function transformFormType(value) { + return FORM_TYPE_TRANSLATE[value] || 'Форма не найдена'; +} + +export function transformRoleChanges(value) { + if (typeof value === 'string') { + return STAGE_ROLE_RUSSIAN_NAME[value] + } + return { + before: STAGE_ROLE_RUSSIAN_NAME[value.before], + after: STAGE_ROLE_RUSSIAN_NAME[value.after], + } +} export async function transformUser(userId) { try { @@ -105,16 +121,90 @@ export async function transformForm(formId) { const res = await FormsApi.getForm(formId); const form = res.result; const formInfo = { - 'название': FROM_TYPE_TRANSLATE[form.form_type_code], + 'название': FORM_TYPE_TRANSLATE[form.form_type_code], 'ССП/РФ': form.org_unit.title, 'Год': form.year, } return formInfo } -export function transformDirection(direction){ - if (!direction){ +export function transformDirection(direction) { + if (!direction) { return '-'; } return DIRECTION_TRANSLATE[direction]; +} + +export async function transformColumns(cols, formId, sheet) { + if (!formId || !sheet) return cols; + const res = await FormsApi.getForm(formId); + const form = res.result; + const formType = form.form_type_code; + + const { config } = await import(`../../../../components/RealtimeTable/constants/${formType}/${sheet}.js`); + const columns = config.config.columns; + function findColumnAndHeaders(columns, targetAccessorKey) { + + // Рекурсивная функция для поиска колонки и сбора родителей + function searchRecursively(columnsArray, path = []) { + for (let column of columnsArray) { + // Проверяем текущую колонку + if (column.accessorKey === targetAccessorKey) { + // Нашли целевую колонку, возвращаем путь с заголовками + return { + found: true, + headers: [...path, column.header], + column: column + }; + } + + // Если у колонки есть вложенные колонки, ищем в них + if (column.columns && Array.isArray(column.columns)) { + const result = searchRecursively(column.columns, [...path, column.header]); + if (result.found) { + return result; + } + } + } + + return { found: false }; + } + + const result = searchRecursively(columns); + + if (result.found) { + return { + headers: result.headers, + column: result.column, + path: result.headers.join(' → ') + }; + } else { + return { + headers: [], + column: null, + path: null, + error: `Колонка с accessorKey "${targetAccessorKey}" не найдена` + }; + } + } + if (Array.isArray(cols)) { + const res = []; + cols.forEach(c => { + res.push(findColumnAndHeaders(columns, "data." + c).path || ''); + }) + return res; + } + + const translateColsAfter = []; + const translateColsBefore = []; + + cols.after.forEach(c => { + translateColsAfter.push(findColumnAndHeaders(columns, "data." + c).path || ''); + }) + cols.before.forEach(c => { + translateColsBefore.push(findColumnAndHeaders(columns, "data." + c).path || ''); + }) + + // Пример использования: + return { after: translateColsAfter, before: translateColsBefore }; } \ No newline at end of file diff --git a/web/src/pages/AdminPanel/UsersPage/ModalEditUserSsp.jsx b/web/src/pages/AdminPanel/UsersPage/ModalEditUserSsp.jsx index 08e2963..1cd01dd 100644 --- a/web/src/pages/AdminPanel/UsersPage/ModalEditUserSsp.jsx +++ b/web/src/pages/AdminPanel/UsersPage/ModalEditUserSsp.jsx @@ -20,6 +20,10 @@ export const ModalEditUserSsp = ({ const [selectedType, setSelectedType] = useState('rf'); // 'rf' или 'ssp' useEffect(() => { + if (!open) { + setCurUser(null); + return; + } setCurUser(user); try { if (user && user.role_id == ROLES_NAME_ID.executor_rf) { @@ -29,7 +33,7 @@ export const ModalEditUserSsp = ({ } catch { setSelectedType('rf'); } - }, [user]); + }, [user, open]); useEffect(() => { if (!deps) return; @@ -75,14 +79,9 @@ export const ModalEditUserSsp = ({ }, [depsData]); const sspForDfip = useMemo(() => { - if (!curUser) return []; - if (newDepsData.update.length > 0) { - return newDepsData.update.map( - (sId) => deps.filter((dep) => dep.id == sId)[0], - ); - } + if (!curUser|| !open) return []; return curUser.org_units ?? []; - }, [curUser, deps, newDepsData]); + }, [curUser, deps, newDepsData, open]); const handleTypeChange = (value) => { setSelectedType(value); diff --git a/web/src/pages/AdminPanel/UsersPage/UserTable/EditUserModal.jsx b/web/src/pages/AdminPanel/UsersPage/UserTable/EditUserModal.jsx index ef06a2b..9c32b5c 100644 --- a/web/src/pages/AdminPanel/UsersPage/UserTable/EditUserModal.jsx +++ b/web/src/pages/AdminPanel/UsersPage/UserTable/EditUserModal.jsx @@ -359,8 +359,8 @@ export const EditUserModal = ({ customSize={58.13} > - - + + {renderField('ФИО', 'full_name', editUser.full_name)} {renderField('Почта', 'email', editUser.email, 'email')} diff --git a/web/src/pages/AdminPanel/components/AutocompleteForChangeOptions.jsx b/web/src/pages/AdminPanel/components/AutocompleteForChangeOptions.jsx index 217eacc..e9684ff 100644 --- a/web/src/pages/AdminPanel/components/AutocompleteForChangeOptions.jsx +++ b/web/src/pages/AdminPanel/components/AutocompleteForChangeOptions.jsx @@ -105,7 +105,7 @@ export const AutocompleteForChangeOptions = ({ if (option.email) { label += ` (${option.email})`; } - return label; + return label ?? '-'; }} onChange={handleSelect} inputValue={inputValue} diff --git a/web/src/pages/TaskPage/TaskPage.jsx b/web/src/pages/TaskPage/TaskPage.jsx index 2993547..ae3fcb7 100644 --- a/web/src/pages/TaskPage/TaskPage.jsx +++ b/web/src/pages/TaskPage/TaskPage.jsx @@ -22,13 +22,13 @@ import { ModalCreateProject } from './ModalCreateProject'; import { ExportWithTextButton } from '../../components/common/Buttons/ButtonsActions'; import { exportSingleForm } from '../../utils/exportForm'; import TablesList from '../../components/common/TableList/TableList'; -import { DIRECTION_TRANSLATE, FROM_TYPE_TRANSLATE, SHEET_NAME } from '../../constants'; +import { DIRECTION_TRANSLATE, FORM_TYPE_TRANSLATE, SHEET_NAME } from '../../constants'; const TaskInfo = ({ task }) => { const portalContent = ( - {FROM_TYPE_TRANSLATE[task.form_type_code] || ''} + {FORM_TYPE_TRANSLATE[task.form_type_code] || ''} ); diff --git a/web/src/pages/TasksPage/TasksPage.jsx b/web/src/pages/TasksPage/TasksPage.jsx index 0a06126..00f8933 100644 --- a/web/src/pages/TasksPage/TasksPage.jsx +++ b/web/src/pages/TasksPage/TasksPage.jsx @@ -26,7 +26,7 @@ import { FORM_TYPE_OPTIONS, ORG_UNIT_TYPE_OPTIONS, ROLES_NAME_ID, - FROM_TYPE_TRANSLATE + FORM_TYPE_TRANSLATE } from '../../constants'; import { useAuth } from '../../app/context/AuthProvider'; import { SspApi } from '../../api/ssp'; @@ -414,7 +414,7 @@ export default function TasksPage() { onChange={(e) => handleFormChange('formTypeCode', e.target.value)} renderValue={(selected) => selected ? ( - FROM_TYPE_TRANSLATE[selected] + FORM_TYPE_TRANSLATE[selected] ) : ( Не выбрана ) @@ -424,7 +424,7 @@ export default function TasksPage() { > {FORM_TYPE_OPTIONS.map((formType) => ( - {FROM_TYPE_TRANSLATE[formType]} + {FORM_TYPE_TRANSLATE[formType]} ))}