diff --git a/src/components/UploadForm.tsx b/src/components/UploadForm.tsx index 3ec99a5..12bfef4 100644 --- a/src/components/UploadForm.tsx +++ b/src/components/UploadForm.tsx @@ -1,15 +1,17 @@ -import { memo, useCallback, useState } from 'react' +import { memo, useCallback, useEffect, useMemo, useState } from 'react' import { Upload, Button } from 'antd' import { UploadOutlined } from '@ant-design/icons' import { UploadFile } from 'antd/lib/upload/interface' +import { RcFile } from 'antd/lib/upload' -import { upload } from './factory' +import { notify, upload } from './factory' import { ErrorFetch } from './ErrorFetch' export type UploadFormProps = { url: string disabled?: boolean accept?: string + mimeTypes?: string | string[] style?: CSSStyleSheet formData: FormData onUploadStart?: () => void @@ -18,14 +20,25 @@ export type UploadFormProps = { onUploadError?: (error: unknown) => void } -export const UploadForm = memo(({ url, disabled, accept, style, formData, onUploadStart, onUploadSuccess, onUploadComplete, onUploadError }) => { +export const UploadForm = memo(({ url, disabled, style, formData, mimeTypes, onUploadStart, onUploadSuccess, onUploadComplete, onUploadError }) => { const [fileList, setfileList] = useState[]>([]) + const checkMimeTypes = useCallback((file: RcFile) => { + const isAccepted = !mimeTypes || mimeTypes.includes(file.type) + if (isAccepted) return false + notify(`"${file.name}" является файлом неподходящего типа`, 'error') + return Upload.LIST_IGNORE + }, [mimeTypes]) + + const accept = useMemo(() => Array.isArray(mimeTypes) ? mimeTypes.join(',') : mimeTypes, [mimeTypes]) + + useEffect(() => console.log(fileList), [fileList]) + const handleFileSend = useCallback(async () => { onUploadStart?.() try { const formDataLocal = new FormData() - fileList.forEach((val) => formDataLocal.append('files', String(val.originFileObj))) + fileList.forEach((val) => formDataLocal.append('files', val.originFileObj as Blob)) if(formData) for(const propName in formData) @@ -58,6 +71,7 @@ export const UploadForm = memo(({ url, disabled, accept, style, disabled={disabled} fileList={fileList} onChange={(props) => setfileList(props.fileList)} + beforeUpload={checkMimeTypes} > diff --git a/src/components/factory.ts b/src/components/factory.ts index 3d5abfa..635b2c2 100755 --- a/src/components/factory.ts +++ b/src/components/factory.ts @@ -11,12 +11,14 @@ const notificationTypeDictionary = new Map([ ['open' , { notifyInstance: notification.info , caption: '' }], ]) +export type NotifyType = 'error' | 'warning' | 'info' + /** * Вызов оповещений всплывающим окошком. * @param body string или ReactNode * @param notifyType для параметра типа. Допустимые значение 'error', 'warning', 'info' */ -export const notify = (body: ReactNode, notifyType: string = 'info', other?: any) => { +export const notify = (body: ReactNode, notifyType: NotifyType = 'info', other?: any) => { if (!body) return const instance = notificationTypeDictionary.get(notifyType) ?? diff --git a/src/pages/Documents/DocumentsTemplate.jsx b/src/pages/Documents/DocumentsTemplate.jsx index a540975..d831508 100755 --- a/src/pages/Documents/DocumentsTemplate.jsx +++ b/src/pages/Documents/DocumentsTemplate.jsx @@ -31,7 +31,7 @@ const columns = [ makeColumn('Компания', 'company', { render: (_, record) => }) ] -export const DocumentsTemplate = ({ idCategory, idWell: wellId, accept, headerChild, customColumns, beforeTable, onChange, tableName }) => { +export const DocumentsTemplate = ({ idCategory, idWell: wellId, mimeTypes, headerChild, customColumns, beforeTable, onChange, tableName }) => { const [page, setPage] = useState(1) const [filterDataRange, setFilterDataRange] = useState([]) const [filterCompanyName, setFilterCompanyName] = useState([]) @@ -134,7 +134,7 @@ export const DocumentsTemplate = ({ idCategory, idWell: wellId, accept, headerCh Загрузка setShowLoader(true)} onUploadComplete={update} /> diff --git a/src/pages/DrillingProgram/CategoryEditor.jsx b/src/pages/DrillingProgram/CategoryEditor.jsx index 13f0ddf..8c3b7ff 100755 --- a/src/pages/DrillingProgram/CategoryEditor.jsx +++ b/src/pages/DrillingProgram/CategoryEditor.jsx @@ -28,9 +28,12 @@ export const CategoryEditor = memo(({ visible, category, onClosed }) => { const [showLoader, setShowLoader] = useState(false) const [searchValue, setSearchValue] = useState('') const [subject, setSubject] = useState(null) + const [needUpdate, setNeedUpdate] = useState(false) const idWell = useContext(IdWellContext) + useEffect(() => visible && setNeedUpdate(false), [visible]) + useEffect(() => invokeWebApiWrapperAsync( async () => { const filteredUsers = users.filter(({ user }) => user && [ @@ -108,6 +111,7 @@ export const CategoryEditor = memo(({ visible, category, onClosed }) => { prevUsers[userIdx].status = status return [...prevUsers] }) + setNeedUpdate(true) }, setShowLoader, <> @@ -138,9 +142,9 @@ export const CategoryEditor = memo(({ visible, category, onClosed }) => { const onSearchTextChange = useCallback((e) => subject?.next(e?.target?.value), [subject]) const onModalClosed = useCallback(() => { - onClosed?.() + onClosed?.(needUpdate) calcUsers() - }, [onClosed, calcUsers]) + }, [onClosed, calcUsers, needUpdate]) return ( setIsUploading(true)} onUploadComplete={onUploadComplete} diff --git a/src/pages/DrillingProgram/index.jsx b/src/pages/DrillingProgram/index.jsx index ae3a530..2b8aa69 100755 --- a/src/pages/DrillingProgram/index.jsx +++ b/src/pages/DrillingProgram/index.jsx @@ -8,9 +8,9 @@ import { ReloadOutlined, WarningOutlined, } from '@ant-design/icons' -import { memo, useCallback, useContext, useEffect, useMemo, useState } from 'react' +import { memo, useCallback, useEffect, useMemo, useState } from 'react' -import { IdWellContext } from '@asb/context' +import { useIdWell } from '@asb/context' import LoaderPortal from '@components/LoaderPortal' import { downloadFile, formatBytes, invokeWebApiWrapperAsync } from '@components/factory' import { arrayOrDefault, formatDate } from '@utils' @@ -23,20 +23,22 @@ import CategoryHistory from './CategoryHistory' import '@styles/drilling_program.less' -const idStateNotInitialized = 0 -const idStateApproving = 1 -const idStateCreating = 2 -const idStateReady = 3 -const idStateError = 4 -const idStateUnknown = -1 +const ID_STATE = { + NotInitialized: 0, + Approving: 1, + Creating: 2, + Ready: 3, + Error: 4, + Unknown: -1, +} -const stateString = { - [idStateNotInitialized]: { icon: CloseOutlined, text: 'Не настроена' }, - [idStateApproving]: { icon: AuditOutlined, text: 'Согласовывается' }, - [idStateCreating]: { icon: LoadingOutlined, text: 'Формируется' }, - [idStateReady]: { icon: CheckOutlined, text: 'Сформирована' }, - [idStateError]: { icon: WarningOutlined, text: 'Ошибка формирования' }, - [idStateUnknown]: { icon: WarningOutlined, text: 'Неизвестно' }, +const STATE_STRING = { + [ID_STATE.NotInitialized]: { icon: CloseOutlined, text: 'Не настроена' }, + [ID_STATE.Approving]: { icon: AuditOutlined, text: 'Согласовывается' }, + [ID_STATE.Creating]: { icon: LoadingOutlined, text: 'Формируется' }, + [ID_STATE.Ready]: { icon: CheckOutlined, text: 'Сформирована' }, + [ID_STATE.Error]: { icon: WarningOutlined, text: 'Ошибка формирования' }, + [ID_STATE.Unknown]: { icon: WarningOutlined, text: 'Неизвестно' }, } export const DrillingProgram = memo(() => { @@ -47,7 +49,7 @@ export const DrillingProgram = memo(() => { const [categories, setCategories] = useState([]) const [data, setData] = useState({}) - const idWell = useContext(IdWellContext) + const idWell = useIdWell() const { idState, @@ -57,8 +59,8 @@ export const DrillingProgram = memo(() => { error, } = useMemo(() => data, [data]) - const stateId = useMemo(() => idState ?? idStateUnknown, [idState]) - const state = useMemo(() => stateString[stateId], [stateId]) + const stateId = useMemo(() => idState ?? ID_STATE.Unknown, [idState]) + const state = useMemo(() => STATE_STRING[stateId], [stateId]) const StateIcon = useMemo(() => state.icon, [state?.icon]) const updateData = useCallback(async () => await invokeWebApiWrapperAsync( @@ -89,9 +91,10 @@ export const DrillingProgram = memo(() => { setHistoryVisible(!!catId) }, []) - const onEditorClosed = useCallback(() => { + const onEditorClosed = useCallback((needUpdate) => { setEditorVisible(false) - updateData() + if (needUpdate) + updateData() }, [updateData]) return ( @@ -107,7 +110,7 @@ export const DrillingProgram = memo(() => { )}
- {stateId === idStateReady ? ( + {stateId === ID_STATE.Ready ? ( <>