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

View File

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

View File

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

View File

@ -13,17 +13,17 @@ export const documentCategories = [
{id:7, key:'master', title:'Мастер'},
]
const makeMenuItem = (keyPrefix, keyValue, rootPath, title, other) => (
const makeMenuItem = (keyValue, rootPath, title, other) => (
<Menu.Item className="ant-menu-item"
key={`${keyPrefix}/${keyValue}/menuItem`}
key={`${keyValue}`}
{...other}>
<Link to={{pathname: `${rootPath}/${keyValue}`}}>{title}</Link>
</Menu.Item>)
const makeRouteItem = (keyPrefix, keyValue, rootPath, other) => (
const makeRouteItem = (keyValue, rootPath, other) => (
<Route
path={`${rootPath}/${keyValue}`}
key={`${keyPrefix}/${keyValue}/routeItem`}>
key={`${keyValue}`}>
<DocumentsTemplate {...other}/>
</Route>)
@ -42,17 +42,17 @@ const formatRoutePath = (rootPath) =>{
const getCategoriesByUserRole = (role) => documentCategories
.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 categories = getCategoriesByUserRole(localStorage['roleName'])
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 categories = getCategoriesByUserRole(localStorage['roleName'])
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;
}

View File

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