Refactor documents

This commit is contained in:
Фролов 2021-08-17 16:46:46 +05:00
parent 29537b8d5a
commit 2418d13e75
6 changed files with 155 additions and 122 deletions

View File

@ -1,19 +1,17 @@
import { Form, Upload, Button} from 'antd' import { Upload, Button } from 'antd'
import { UploadOutlined} from '@ant-design/icons' import { UploadOutlined } from '@ant-design/icons'
import { useState } from 'react' import { useState } from 'react'
import { upload } from './factory' import { upload } from './factory'
export default function UploadForm({url, onUploadStart, onUploadComplete, onUploadError}) { export default function UploadForm({url, onUploadStart, onUploadComplete, onUploadError}) {
const [isSubmitButtonEnabled, setSubmitButtonEnabled] = useState(false) const [fileList, setfileList] = useState([])
const [form] = Form.useForm();
const handleFileSend = async (values) => { const handleFileSend = async (values) => {
if(onUploadStart) if(onUploadStart)
onUploadStart() onUploadStart()
try { try {
const values = await form.validateFields();
const formData = new FormData() const formData = new FormData()
values.file.fileList.forEach((val) => { fileList.forEach((val) => {
formData.append("files", val.originFileObj); formData.append("files", val.originFileObj);
}); });
await upload(url, formData) await upload(url, formData)
@ -21,36 +19,27 @@ export default function UploadForm({url, onUploadStart, onUploadComplete, onUplo
if(onUploadError) if(onUploadError)
onUploadError(error) onUploadError(error)
} finally { } finally {
form.resetFields() setfileList([])
if(onUploadComplete) if(onUploadComplete)
onUploadComplete() onUploadComplete()
} }
} }
const isSendButtonEnabled = fileList.length > 0
return( return(
<Form <div style={{display: 'flex'}}>
form={form} <Upload
onFinish={handleFileSend} name ="file"
style={{display: 'flex'}}> fileList={fileList}
<Form.Item onChange={(props) => setfileList(props.fileList)}>
name="file" <Button icon={<UploadOutlined/>}>Загрузить файл</Button>
style={{marginBottom: 0}} </Upload>
rules={[{ required: true, message: 'Выберите файл' }]}> <Button type="primary"
<Upload disabled={!isSendButtonEnabled}
name ="file" style={{marginLeft: '10px', display:isSendButtonEnabled?'':'none'}}
onChange={(props) => setSubmitButtonEnabled(props.fileList.length > 0)}> onClick={handleFileSend}>
<Button icon={<UploadOutlined/>}>Загрузить файл</Button> Отправить
</Upload> </Button>
</Form.Item> </div>
<Form.Item style={{marginBottom: 0}}>
<Button
type="primary"
htmlType="submit"
disabled={!isSubmitButtonEnabled}
style={{marginLeft: '10px', display:isSubmitButtonEnabled?'':'none'}}>
Отправить
</Button>
</Form.Item>
</Form>
) )
} }

View File

@ -1,115 +1,169 @@
import {useState, useEffect} from "react" import { useState, useEffect } from "react"
import {Table, DatePicker, Button, Form} from 'antd' import { DatePicker, Button, Input } from "antd"
import moment from 'moment' import moment from "moment"
import { FileService } from '../../services/api' import { FileService } from "../../services/api"
import { updateFromWebApiWrapperAsync, download, makePaginationObject} from '../../components/factory' import {
import UploadForm from '../../components/UploadForm' updateFromWebApiWrapperAsync,
import LoaderPortal from '../../components/LoaderPortal' download,
makePaginationObject,
} from "../../components/factory"
import { EditableTable } from "../../components/EditableTable"
import UploadForm from "../../components/UploadForm"
import LoaderPortal from "../../components/LoaderPortal"
const pageSize = 12 const pageSize = 12
const {RangePicker} = DatePicker; const { RangePicker } = DatePicker
const { Search } = Input
export default function DocumentsTemplate({idCategory, idWell}) { export default function DocumentsTemplate({ idCategory, idWell }) {
const [page, setPage] = useState(1) const [page, setPage] = useState(1)
const [range, setRange] = useState([]) const [dataRange, setDataRange] = useState([])
const [company, setCompany] = useState([])
const [pagination, setPagination] = useState(null) const [pagination, setPagination] = useState(null)
const [files, setFiles] = useState([]) const [files, setFiles] = useState([])
const [showLoader, setShowLoader] = useState(false) const [showLoader, setShowLoader] = useState(false)
const uploadUrl = `/api/well/${idWell}/files/?idCategory=${idCategory}` const uploadUrl = `/api/well/${idWell}/files/?idCategory=${idCategory}`
const handleFileNameCLick = async (_, row) => { const handleFileDownload = async (_, row) => {
updateFromWebApiWrapperAsync(async ()=>{ updateFromWebApiWrapperAsync(
await download(`/api/well/${idWell}/files/${row.id}`) async () => {
}, await download(`/api/well/${idWell}/files/${row.id}`)
setShowLoader, },
`Не удалось скачать файл ${row}`) setShowLoader,
`Не удалось скачать файл ${row}`
)
} }
const handleUploadComplete = () => {
update()
}
const handleFileDelete = (file) => {
//FileService.delete(idWell, file.id)
update()
}
const hanleCompanySearch = (value, _) => {
setCompany(value)
}
const columns = [ const columns = [
{ {
title: 'Документ', title: "Документ",
key: 'document', key: "document",
dataIndex: 'name', dataIndex: "name",
render: (name, row) => render: (name, row) => (
<Button onClick={ev => handleFileNameCLick(ev, row)} download={name}>{name}</Button> <Button type="link" onClick={(ev) => handleFileDownload(ev, row)} download={name}>
{name}
</Button>),
}, },
{ {
title: 'Дата загрузки', title: "Дата загрузки",
key: 'uploadDate', key: "uploadDate",
dataIndex: 'uploadDate', dataIndex: "uploadDate",
render: (item) => moment.utc(item).local().format('DD MMM YYYY, HH:mm:ss') render: (item) =>
moment.utc(item).local().format("DD MMM YYYY, HH:mm:ss"),
}, },
{ {
title: 'Ф.И.О.', title: "Ф.И.О.",
key: 'userName', key: "userName",
dataIndex: 'userName', dataIndex: "userName",
} },
]; {
title: "Компания",
key: "company",
dataIndex: "company",
},
]
const addKeysAndUpdateFiles = (items) =>{ const addKeysAndUpdateFiles = (items) => {
const mappedFiles = items?.map(fileInfo => ({key: fileInfo.id, begin: fileInfo.date, ...fileInfo})) const mappedFiles = items?.map((fileInfo) => ({
setFiles(mappedFiles??[]) key: fileInfo.id,
begin: fileInfo.date,
...fileInfo,
}))
setFiles(mappedFiles ?? [])
} }
useEffect(() => { const update = () => {
let begin = null let begin = null
let end = null let end = null
if (range?.length > 1) { if (dataRange?.length > 1) {
begin = range[0].toISOString() begin = dataRange[0].toISOString()
end = range[1].toISOString() end = dataRange[1].toISOString()
} }
updateFromWebApiWrapperAsync( updateFromWebApiWrapperAsync(
async ()=>{ async () => {
const paginatedFiles = await FileService.getFilesInfo( const paginatedFiles = await FileService.getFilesInfo(
`${idWell}`, idWell,
(page - 1) * pageSize, (page - 1) * pageSize,
pageSize, pageSize,
idCategory, idCategory,
begin, begin,
end) end
if(!paginatedFiles) )
return if (!paginatedFiles) return
addKeysAndUpdateFiles(paginatedFiles?.items) addKeysAndUpdateFiles(paginatedFiles?.items)
const newPagination = makePaginationObject(paginatedFiles) const newPagination = makePaginationObject(paginatedFiles)
setPagination(newPagination) setPagination(newPagination)
}, },
setShowLoader, setShowLoader,
`Не удалось загрузить файлы по скважине "${idWell}"`) `Не удалось загрузить файлы по скважине "${idWell}"`
}, [idWell, range, page, idCategory]) )
}
return ( useEffect(update, [idWell, dataRange, page, idCategory, company])
const companies = [...new Set(files.map(file=>file.company))]
.filter(company=>company)
const DataListCompanies = <datalist id="listCompanies">
{companies.map((company, i)=><option key={company} value={company}>{company}</option>)}
</datalist>
return (
<LoaderPortal show={showLoader}> <LoaderPortal show={showLoader}>
<Form <div style={{margin:16, display:'flex'}}>
layout="vertical"> <div>
<div className='d-flex'> <span>Фильтр по дате</span>
<Form.Item <div>
label="Фильтр документов"> <RangePicker showTime onChange={setDataRange} />
<RangePicker </div>
showTime </div>
onChange={setRange}/> &nbsp;
</Form.Item> <div>
<Form.Item <span>Фильтр по компании</span>
label="Загрузка документов"> <Search
<UploadForm list='listCompanies'
url={uploadUrl} placeholder="Фильтр по компании"
onUploadStart={()=>setShowLoader(true)} onSearch={hanleCompanySearch}/>
onUploadComplete={()=>setShowLoader(false)}/> {DataListCompanies}
</Form.Item> </div>
</div> &nbsp;&nbsp;
</Form> <div>
<span>Загрузка</span>
<UploadForm
url={uploadUrl}
onUploadStart={() => setShowLoader(true)}
onUploadComplete={handleUploadComplete}/>
</div>
</div>
<Table <EditableTable
columns={columns} columns={columns}
dataSource={files} dataSource={files}
size={'small'} size={"small"}
pagination={{ pagination={{
...pagination, ...pagination,
showSizeChanger: false, showSizeChanger: false,
onChange: (page) => setPage(page)}} onChange: (page) => setPage(page),
}}
onRowDelete={handleFileDelete}
rowKey={(record) => record.id} rowKey={(record) => record.id}
/> />
</LoaderPortal>); </LoaderPortal>
} )
}

View File

@ -14,12 +14,12 @@ export default function MenuDocuments({idWell}) {
selectable={true} selectable={true}
className="well_menu" className="well_menu"
selectedKeys={[category]}> selectedKeys={[category]}>
{makeMenuItems('documentsPageMenu', rootPath)} {makeMenuItems(rootPath)}
</Menu> </Menu>
<Layout> <Layout>
<Content className="site-layout-background"> <Content className="site-layout-background">
<Switch> <Switch>
{makeRouteItems('documentsPageMenu', `${rootPath}`, idWell)} {makeRouteItems(rootPath, idWell)}
</Switch> </Switch>
</Content> </Content>
</Layout> </Layout>

View File

@ -13,17 +13,17 @@ export const documentCategories = [
{id:7, key:'master', title:'Мастер'}, {id:7, key:'master', title:'Мастер'},
] ]
const makeMenuItem = (keyPrefix, keyValue, rootPath, title, other) => ( const makeMenuItem = (keyValue, rootPath, title, other) => (
<Menu.Item className="ant-menu-item" <Menu.Item className="ant-menu-item"
key={`${keyPrefix}/${keyValue}/menuItem`} key={`${keyValue}`}
{...other}> {...other}>
<Link to={{pathname: `${rootPath}/${keyValue}`}}>{title}</Link> <Link to={{pathname: `${rootPath}/${keyValue}`}}>{title}</Link>
</Menu.Item>) </Menu.Item>)
const makeRouteItem = (keyPrefix, keyValue, rootPath, other) => ( const makeRouteItem = (keyValue, rootPath, other) => (
<Route <Route
path={`${rootPath}/${keyValue}`} path={`${rootPath}/${keyValue}`}
key={`${keyPrefix}/${keyValue}/routeItem`}> key={`${keyValue}`}>
<DocumentsTemplate {...other}/> <DocumentsTemplate {...other}/>
</Route>) </Route>)
@ -42,17 +42,17 @@ const formatRoutePath = (rootPath) =>{
const getCategoriesByUserRole = (role) => documentCategories const getCategoriesByUserRole = (role) => documentCategories
.filter(cat => !cat.roles || cat.roles.includes('*') || cat.roles.includes(role)) .filter(cat => !cat.roles || cat.roles.includes('*') || cat.roles.includes(role))
export const makeMenuItems = (keyPrefix, rootPath) => { export const makeMenuItems = (rootPath) => {
const root = formatRoutePath(rootPath) const root = formatRoutePath(rootPath)
const categories = getCategoriesByUserRole(localStorage['roleName']) const categories = getCategoriesByUserRole(localStorage['roleName'])
return categories.map(category => return categories.map(category =>
makeMenuItem(keyPrefix, category.key, root, category.title, {icon:<FolderOutlined/>})) makeMenuItem(category.key, root, category.title, {icon:<FolderOutlined/>}))
} }
export const makeRouteItems = (keyPrefix, rootPath, idWell) => { export const makeRouteItems = (rootPath, idWell) => {
const root = formatRoutePath(rootPath) const root = formatRoutePath(rootPath)
const categories = getCategoriesByUserRole(localStorage['roleName']) const categories = getCategoriesByUserRole(localStorage['roleName'])
const routes = categories.map(category => const routes = categories.map(category =>
makeRouteItem(keyPrefix, category.key, root, {idCategory: category.id, idWell: idWell})) makeRouteItem(category.key, root, {idCategory: category.id, idWell: idWell}))
return routes; return routes;
} }

View File

@ -53,15 +53,14 @@ export default function Well() {
title={ title={
<Link <Link
to={{ pathname: `${rootPath}/document/fluidService` }} to={{ pathname: `${rootPath}/document/fluidService` }}
className="linkDocuments" className="linkDocuments">
>
Документы Документы
</Link> </Link>
} }
icon={<FolderOutlined />} icon={<FolderOutlined />}
selectable={true} selectable={true}
> >
{makeMenuItems('documentsSubMenu', `${rootPath}/document`)} {makeMenuItems(rootPath)}
</SubMenu> </SubMenu>
<Menu.Item key="8" icon={<FolderOutlined />}> <Menu.Item key="8" icon={<FolderOutlined />}>
<Link to={{ pathname: `${rootPath}/smbo` }}>СМБО</Link> <Link to={{ pathname: `${rootPath}/smbo` }}>СМБО</Link>

View File

@ -1,9 +0,0 @@
.grid_container{
display: grid;
column-gap: 4px;
row-gap: 4px;
/* grid-template-columns: repeat(6, 1fr);
grid-template-rows: repeat(9, 1fr); */
justify-items: stretch;
align-items: stretch;
}