From e2bd55e5b184e21b77120764e10dd099f7d31adc Mon Sep 17 00:00:00 2001 From: Veronika Tsygankova Date: Fri, 5 Jun 2026 13:04:47 +0300 Subject: [PATCH] =?UTF-8?q?[AURORA-1057]=20-=20=D0=B4=D0=BE=D0=B1=D0=B0?= =?UTF-8?q?=D0=B2=D0=BB=D0=B5=D0=BD=20=D1=8D=D0=BA=D1=81=D0=BF=D0=BE=D1=80?= =?UTF-8?q?=D1=82=20=D1=82=D0=B0=D0=B1=D0=BB=D0=B8=D1=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- web/src/api/form_sheet.js | 8 +- .../RealtimeTable/RealtimeTable.jsx | 3 + .../SettingPanel/SettingPanel.jsx | 21 +++ web/src/components/common/Buttons/Buttons.jsx | 11 +- web/src/components/common/ExportFormModal.jsx | 150 ------------------ web/src/pages/TaskPage/TaskPage.jsx | 13 +- web/src/pages/TasksPage.jsx | 54 +------ web/src/utils/exportForm.js | 48 ++++++ 8 files changed, 94 insertions(+), 214 deletions(-) delete mode 100644 web/src/components/common/ExportFormModal.jsx create mode 100644 web/src/utils/exportForm.js diff --git a/web/src/api/form_sheet.js b/web/src/api/form_sheet.js index 9213a35..4d6220e 100644 --- a/web/src/api/form_sheet.js +++ b/web/src/api/form_sheet.js @@ -3,7 +3,13 @@ import api from './client'; export const FormsSheetApi = { get(formId, sheetName, params) { return api - .get(`/form/${formId}/sheet/${sheetName}`,params) + .get(`/form/${formId}/sheet/${sheetName}`, params) .then((r) => r.data); }, + export(formId, sheetName, params = {}) { + return api.get(`export/form/${formId}/sheet/${sheetName}`, { + params, + responseType: 'blob', + }); + }, }; diff --git a/web/src/components/RealtimeTable/RealtimeTable.jsx b/web/src/components/RealtimeTable/RealtimeTable.jsx index 654b88a..b860bca 100644 --- a/web/src/components/RealtimeTable/RealtimeTable.jsx +++ b/web/src/components/RealtimeTable/RealtimeTable.jsx @@ -251,6 +251,9 @@ const RealtimeTable = ({ formType, formId, sheetName, direction }) => { onAddRow={handleAddRow} onDeleteRow={handleDeleteRow} isLoadingData={isLoadingData} + formId={formId} + sheetName={sheetName} + direction={direction} />
diff --git a/web/src/components/RealtimeTable/SettingPanel/SettingPanel.jsx b/web/src/components/RealtimeTable/SettingPanel/SettingPanel.jsx index 6477c84..ecfa843 100644 --- a/web/src/components/RealtimeTable/SettingPanel/SettingPanel.jsx +++ b/web/src/components/RealtimeTable/SettingPanel/SettingPanel.jsx @@ -17,6 +17,8 @@ import { import CollapsibleTree from './CollapsibleTree'; import ZoomSlider from './ZoomSlider'; import SearchComponent from '../../common/SearchComponent'; +import { ExportDefaultButton } from '../../common/Buttons/ButtonsActions'; +import { exportSheet } from '../../../utils/exportForm'; const SettingPanel = ({ selectedColumn, @@ -32,8 +34,12 @@ const SettingPanel = ({ onAddRow, onDeleteRow, isLoadingData, + formId, + sheetName, + direction, }) => { const [isPinned, setIsPinned] = useState(false); + const [isExporting, setIsExporting] = useState(false); const [columnTree, setColumnTree] = useState(); const [selectedColumnIds, setSelectedColumnIds] = useState(); const [showColumnFilters, setShowColumnFilters] = useState(false); @@ -70,6 +76,13 @@ const SettingPanel = ({ const handleClickDeleteFormula = () => { }; + const handleExport = async () => { + if (!formId || !sheetName || isExporting) return; + setIsExporting(true); + await exportSheet(formId, sheetName, direction); + setIsExporting(false); + }; + return ( <> @@ -156,6 +169,14 @@ const SettingPanel = ({ + + + + diff --git a/web/src/components/common/Buttons/Buttons.jsx b/web/src/components/common/Buttons/Buttons.jsx index 079463c..4242ccc 100644 --- a/web/src/components/common/Buttons/Buttons.jsx +++ b/web/src/components/common/Buttons/Buttons.jsx @@ -115,16 +115,11 @@ export const DefaultOutlinedButton = styled(Button)(({ width, height }) => ({ color: '#323031', '&:hover': { - background: '#4a5565', - color: 'white', - '& svg path': { - color: 'white !important', - fill: 'white !important', - stroke: 'white !important', - }, + background: '#f3f3f5', + borderColor: 'rgba(0, 0, 0, 0.2)', }, '&:active': { - background: '#f3f3f5', + background: '#e7e7ea', }, '&.Mui-disabled': { diff --git a/web/src/components/common/ExportFormModal.jsx b/web/src/components/common/ExportFormModal.jsx deleted file mode 100644 index ab5ea79..0000000 --- a/web/src/components/common/ExportFormModal.jsx +++ /dev/null @@ -1,150 +0,0 @@ -import { useEffect, useState } from 'react'; -import { - Box, - Button, - FormControl, - FormLabel, - MenuItem, - Select, -} from '@mui/material'; -import Modal from './Modal/Modal'; -import { TasksApi } from '../../api/tasks'; -import { downloadFile } from '../../utils/downloadFile'; -import { getApiErrorMessage } from '../../utils/getApiErrorMessage'; -import { toast } from 'react-toastify'; - -const DIRECTION_OPTIONS = [ - { value: 'Development', label: 'Development' }, - { value: 'Support', label: 'Support' }, -]; - -export const ExportFormModal = ({ - open, - onClose, - onSuccess, - taskId, - taskTitle = 'form', - formIds, - fileName = 'Задачи', -}) => { - const isBulk = Boolean(formIds?.length); - const [direction, setDirection] = useState(''); - const [loading, setLoading] = useState(false); - - useEffect(() => { - if (open) { - setDirection(''); - setLoading(false); - } - }, [open]); - - const handleClose = () => { - if (!loading) { - onClose(); - } - }; - - const handleExport = async () => { - setLoading(true); - try { - const params = direction ? { direction } : {}; - - if (isBulk) { - const response = await TasksApi.exportTasks( - { form_ids: formIds }, - params, - ); - await downloadFile(response, fileName, 'xlsx'); - } else if (taskId) { - const response = await TasksApi.exportTask(taskId, params); - await downloadFile(response, taskTitle, 'xlsx'); - } - - onSuccess?.(); - onClose(); - } catch (error) { - const message = await getApiErrorMessage( - error, - 'Ошибка при скачивании файла', - ); - toast.error(message); - } finally { - setLoading(false); - } - }; - - return ( - - - - - } - > - - - direction - - - - - - - ); -}; diff --git a/web/src/pages/TaskPage/TaskPage.jsx b/web/src/pages/TaskPage/TaskPage.jsx index 7e740bc..3891cc5 100644 --- a/web/src/pages/TaskPage/TaskPage.jsx +++ b/web/src/pages/TaskPage/TaskPage.jsx @@ -20,7 +20,7 @@ import { PrimaryOutlinedButton } from '../../components/common/Buttons/Buttons'; import { FormsApi } from '../../api/forms'; import { ModalCreateProject } from './ModalCreateProject'; import { ExportWithTextButton } from '../../components/common/Buttons/ButtonsActions'; -import { ExportFormModal } from '../../components/common/ExportFormModal'; +import { exportSingleForm } from '../../utils/exportForm'; import TablesList from '../../components/common/TableList/TableList'; import { SHEET_NAME } from '../../constants'; @@ -55,7 +55,6 @@ export default function TaskPage() { const [query, setQuery] = useState(''); const [modalStageOpen, setModalStageOpen] = useState(false); const [modalProjectOpen, setModalProjectOpen] = useState(false); - const [exportModalOpen, setExportModalOpen] = useState(false); const [tempProjects, setTempProjects] = useState([]); const [projects, setProjects] = useState([]); @@ -148,7 +147,9 @@ export default function TaskPage() { onChange={setQuery} /> - setExportModalOpen(true)} /> + exportSingleForm(taskId, task?.title ?? 'form')} + /> setModalStageOpen(true)} @@ -173,12 +174,6 @@ export default function TaskPage() { /> - setExportModalOpen(false)} - taskId={taskId} - taskTitle={task?.title ?? 'form'} - /> ); } \ No newline at end of file diff --git a/web/src/pages/TasksPage.jsx b/web/src/pages/TasksPage.jsx index 8f5a579..f007b84 100644 --- a/web/src/pages/TasksPage.jsx +++ b/web/src/pages/TasksPage.jsx @@ -31,7 +31,7 @@ import { ExportExitButton, ExportWithTextButton, } from '../components/common/Buttons/ButtonsActions'; -import { ExportFormModal } from '../components/common/ExportFormModal'; +import { exportBulkForms, exportSingleForm } from '../utils/exportForm'; import { WhitePlus } from '../components/common/icons/icons'; export default function TasksPage() { @@ -60,13 +60,6 @@ export default function TasksPage() { const [exportMode, setExportMode] = useState(false); const [exportList, setExportList] = useState([]); - const [exportModal, setExportModal] = useState({ - open: false, - taskId: null, - taskTitle: null, - formIds: null, - }); - const openModal = () => { setModalOpen(true); }; @@ -190,31 +183,13 @@ export default function TasksPage() { } }; - const openBulkExportModal = () => { - setExportModal({ - open: true, - taskId: null, - taskTitle: null, - formIds: exportList, - }); + const handleBulkExport = async () => { + await exportBulkForms(exportList); + setExportMode(false); }; - const openSingleExportModal = (taskId, taskTitle) => { - setExportModal({ - open: true, - taskId, - taskTitle, - formIds: null, - }); - }; - - const closeExportModal = () => { - setExportModal({ - open: false, - taskId: null, - taskTitle: null, - formIds: null, - }); + const handleSingleExport = (taskId, taskTitle) => { + exportSingleForm(taskId, taskTitle); }; // Calculate total pages @@ -256,7 +231,7 @@ export default function TasksPage() { <> setExportMode(false)} /> @@ -280,7 +255,7 @@ export default function TasksPage() { onAddForExport={(checked) => { handleChangeToExportList(t.id, checked); }} - onExportClick={openSingleExportModal} + onExportClick={handleSingleExport} /> ))} @@ -461,19 +436,6 @@ export default function TasksPage() {
- { - if (exportModal.formIds?.length) { - setExportMode(false); - } - closeExportModal(); - }} - taskId={exportModal.taskId} - taskTitle={exportModal.taskTitle ?? 'form'} - formIds={exportModal.formIds} - /> ); } diff --git a/web/src/utils/exportForm.js b/web/src/utils/exportForm.js new file mode 100644 index 0000000..56eba58 --- /dev/null +++ b/web/src/utils/exportForm.js @@ -0,0 +1,48 @@ +import { FormsSheetApi } from '../api/form_sheet'; +import { TasksApi } from '../api/tasks'; +import { downloadFile } from './downloadFile'; +import { getApiErrorMessage } from './getApiErrorMessage'; +import { toast } from 'react-toastify'; + +export const exportSingleForm = async (taskId, taskTitle) => { + try { + const response = await TasksApi.exportTask(taskId); + await downloadFile(response, taskTitle, 'xlsx'); + } catch (error) { + const message = await getApiErrorMessage( + error, + 'Ошибка при скачивании файла', + ); + toast.error(message); + } +}; + +export const exportSheet = async (formId, sheetName, direction) => { + try { + const normalizedDirection = + direction && direction !== 'null' ? direction : undefined; + const params = normalizedDirection ? { direction: normalizedDirection } : {}; + const response = await FormsSheetApi.export(formId, sheetName, params); + await downloadFile(response, sheetName, 'xlsx'); + } catch (error) { + const message = await getApiErrorMessage( + error, + 'Ошибка при скачивании файла', + ); + toast.error(message); + } +}; + +export const exportBulkForms = async (formIds, fileName = 'Задачи') => { + try { + const response = await TasksApi.exportTasks({ form_ids: formIds }); + await downloadFile(response, fileName, 'xlsx'); + } catch (error) { + const message = await getApiErrorMessage( + error, + 'Ошибка при скачивании файла', + ); + toast.error(message); + throw error; + } +};