From df9eeae0479d13b34f60c259a1e0cd6bbcc6d73e Mon Sep 17 00:00:00 2001 From: goodm2ice Date: Mon, 20 Dec 2021 12:44:07 +0500 Subject: [PATCH] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D1=8B=20=D0=BD=D0=BE=D0=B2=D1=8B=D0=B5=20=D1=82=D0=B8?= =?UTF-8?q?=D0=BF=D1=8B=20=D0=B4=D0=BE=D0=BA=D1=83=D0=BC=D0=B5=D0=BD=D1=82?= =?UTF-8?q?=D0=BE=D0=B2,=20=D0=BA=D0=BE=D1=81=D0=BC=D0=B5=D1=82=D0=B8?= =?UTF-8?q?=D0=BA=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/Documents/DocumentsTemplate.jsx | 174 ++++++++---------- src/pages/Documents/DrillingProgram.jsx | 155 ++++++++-------- src/pages/Documents/index.jsx | 79 ++++++-- src/pages/Documents/menuItems.jsx | 50 ------ src/pages/TelemetryView/SetpointSender.jsx | 3 +- src/pages/Well.jsx | 199 ++++++++++----------- 6 files changed, 322 insertions(+), 338 deletions(-) delete mode 100644 src/pages/Documents/menuItems.jsx diff --git a/src/pages/Documents/DocumentsTemplate.jsx b/src/pages/Documents/DocumentsTemplate.jsx index fb8eff9..a7908d8 100644 --- a/src/pages/Documents/DocumentsTemplate.jsx +++ b/src/pages/Documents/DocumentsTemplate.jsx @@ -1,22 +1,50 @@ -import { useState, useEffect } from "react" -import { DatePicker, Button, Input } from "antd" -import moment from "moment" -import { FileService } from "../../services/api" -import { - invokeWebApiWrapperAsync, - downloadFile, - formatBytes, -} from "../../components/factory" -import { EditableTable, makePaginationObject } from "../../components/Table" -import {UploadForm} from "../../components/UploadForm" -import LoaderPortal from "../../components/LoaderPortal" -import {UserView} from '../../components/UserView' -import {CompanyView} from '../../components/CompanyView' +import moment from 'moment' +import { useState, useEffect } from 'react' +import { DatePicker, Button, Input } from 'antd' +import { FileService } from '../../services/api' +import { invokeWebApiWrapperAsync, downloadFile, formatBytes } from '../../components/factory' +import { EditableTable, makePaginationObject } from '../../components/Table' +import { UploadForm } from '../../components/UploadForm' +import LoaderPortal from '../../components/LoaderPortal' +import { UserView } from '../../components/UserView' +import { CompanyView } from '../../components/CompanyView' const pageSize = 12 const { RangePicker } = DatePicker const { Search } = Input +const columns = [ + { + title: 'Документ', + key: 'document', + dataIndex: 'name', + render: (name, row) => ( + + ), + }, { + title: 'Дата загрузки', + key: 'uploadDate', + dataIndex: 'uploadDate', + render: item => moment.utc(item).local().format('DD MMM YYYY, HH:mm:ss'), + }, { + title: 'Размер', + key: 'size', + dataIndex: 'size', + render: item => formatBytes(item) + }, { + title: 'Автор', + key: 'author', + dataIndex: 'author', + render: item => + }, { + title: 'Компания', + key: 'company', + render: (_, record) => + } +] + export default function DocumentsTemplate({ idCategory, idWell, accept, headerChild, customColumns, beforeTable, onChange}) { const [page, setPage] = useState(1) const [filterDataRange, setFilterDataRange] = useState([]) @@ -28,59 +56,17 @@ export default function DocumentsTemplate({ idCategory, idWell, accept, headerCh const uploadUrl = `/api/well/${idWell}/files/?idCategory=${idCategory}` - const handleUploadComplete = () => { - update() - } + const handleUploadComplete = () => update() const handleFileDelete = async (file) => { await FileService.delete(idWell, file.id) update() } - const hanleCompanySearch = (value, _) => { - setFilterCompanyName(value) - } + const hanleCompanySearch = (value, _) => setFilterCompanyName(value) + const hanleFileNameSearch = (value, _) => setFilterFileName(value) - const hanleFileNameSearch = (value, _) => { - setFilterFileName(value) - } - - const columns = [ - { - title: "Документ", - key: "document", - dataIndex: "name", - render: (name, row) => ( - ), - }, - { - title: "Дата загрузки", - key: "uploadDate", - dataIndex: "uploadDate", - render: item => - moment.utc(item).local().format("DD MMM YYYY, HH:mm:ss"), - }, - { - title: "Размер", - key: "size", - dataIndex: "size", - render: item => formatBytes(item) - }, - { - title: "Автор", - key: "author", - dataIndex: "author", - render: item => - }, - { - title: "Компания", - key: "company", - render: (_, record) => - }, - ...(customColumns??[]) - ] + const mergedColumns = [...columns, ...(customColumns ?? [])] const update = () => { let begin = null @@ -93,7 +79,7 @@ export default function DocumentsTemplate({ idCategory, idWell, accept, headerCh invokeWebApiWrapperAsync( async () => { const paginatedFiles = await FileService.getFilesInfo( - idWell, + idWell, idCategory, filterCompanyName, filterFileName, @@ -103,10 +89,9 @@ export default function DocumentsTemplate({ idCategory, idWell, accept, headerCh pageSize, ) - if (!paginatedFiles) - return - - const filesInfos = paginatedFiles.items??[] + if (!paginatedFiles) return + + const filesInfos = paginatedFiles.items ?? [] setFiles(filesInfos) const newPagination = makePaginationObject(paginatedFiles) setPagination(newPagination) @@ -117,51 +102,47 @@ export default function DocumentsTemplate({ idCategory, idWell, accept, headerCh } useEffect(update, [idWell, idCategory, page, filterDataRange, filterCompanyName, filterFileName]) - useEffect(()=>{ - if(onChange) - onChange(files) - }, [files, onChange]) + useEffect(() => onChange?.(files), [files, onChange]) - const companies = [...new Set(files.map(file=>file.company))] - .filter(company=>company) - - const DataListCompanies = - {companies.map((company)=>)} - - - const filenames = [...new Set(files.map(file=>file.name))] - .filter(name=>name) - - const DataListFileNames = - {filenames.map((name)=>)} - + const companies = [...new Set(files.map(file => file.company))].filter(company => company) + const filenames = [...new Set(files.map(file => file.name))].filter(name => name) return ( -
+
Фильтр по дате
-
+
 
Фильтр по компании - {DataListCompanies} -
+ list={'listCompanies'} + placeholder={'Фильтр по компании'} + onSearch={hanleCompanySearch} + /> + + {companies.map((company) => ( + + ))} + +
 
Фильтр по имени файла - {DataListFileNames} + list={'listFileNames'} + placeholder={'Фильтр по имени файла'} + onSearch={hanleFileNameSearch} + /> + + {filenames.map((name) => ( + + ))} +
  
@@ -170,16 +151,17 @@ export default function DocumentsTemplate({ idCategory, idWell, accept, headerCh url={uploadUrl} accept={accept} onUploadStart={() => setShowLoader(true)} - onUploadComplete={handleUploadComplete}/> + onUploadComplete={handleUploadComplete} + />
   {headerChild} {beforeTable} invokeWebApiWrapperAsync( async () => { @@ -26,73 +26,76 @@ export default function DrillingProgram({idWell}) { setWellLabel(well.caption ?? `${idWell}`) }, setShowLoader, - `Не удалось загрузить название скважины "${idWell}"` + `Не удалось загрузить название скважины '${idWell}'` ), [idWell]) - - const urlDownloadProgram =`/api/well/${idWell}/drillingProgram` - const downloadProgram = () => invokeWebApiWrapperAsync(async()=>{ - await download(urlDownloadProgram) - }, - setShowLoader, - "Не удалось загрузить программу бурения") + const urlDownloadProgram = `/api/well/${idWell}/drillingProgram` - const openProgramPreview = () => invokeWebApiWrapperAsync(async()=>{ + const downloadProgram = () => invokeWebApiWrapperAsync( + async () => await download(urlDownloadProgram), + setShowLoader, + 'Не удалось загрузить программу бурения' + ) + + const openProgramPreview = () => invokeWebApiWrapperAsync( + async() => { const filWebUrl = await DrillingProgramService.getOrCreateSharedUrl(idWell) if(filWebUrl && filWebUrl.length > 0) - window.open(filWebUrl, '_blank'); + window.open(filWebUrl, '_blank') else - throw new Error("Сервер вернул плохую ссылку") - }, - setShowLoader, - "Не удалось создать быстрый просмотр программы") + throw new Error('Сервер вернул плохую ссылку') + }, + setShowLoader, + 'Не удалось создать быстрый просмотр программы' + ) - const filesUpdated = (files) =>{ - if(!files || files.length === 0){ + const filesUpdated = (files) => { + if (!files || files.length === 0) { setTooltip('Нет файлов для формирования программы') selDownloadButtonEnabled(false) return } - + const isAllFilesAreExcel = files.every(fileInfo => fileInfo?.name.toLowerCase().endsWith('.xlsx')) const isAnyFileMarked = files.some(file => file?.fileMarks.some(m => m?.idMarkType === 1 && !m?.isDeleted)) - if(isAllFilesAreExcel && isAnyFileMarked){ + if (isAllFilesAreExcel && isAnyFileMarked) { setTooltip('Программа доступна для скачивания') selDownloadButtonEnabled(true) - } - else{ + } else { setTooltip('Список файлов содержит недопустимые типы файлов') } const last = files.reduce((pre, cur) => pre.uploadDate > cur.uploadDate ? pre : cur) - setLastUpdatedFile(last); + setLastUpdatedFile(last) } const customColumns = [ { - title: "Метки", - key: "fileMarks", + title: 'Метки', + key: 'fileMarks', render: (_, record) => renderMarksColumn(record?.id, record?.fileMarks) }, ] - + const renderMarksColumn=(idFile, marks)=>{ const validMarks = marks?.filter(m => !(m?.isDeleted)) if(validMarks?.length) return validMarks.map(mark => deleteMark(mark.id)}/>) - return true && - addMarkToFile(idFile)}> - + return ( + addMarkToFile(idFile)}> + + ) } const addMarkToFile = async (idFile) => { const mark = { idFile: idFile, idMarkType: 1, - isDeleted:false, - comment: ''} + isDeleted: false, + comment: '', + } await DrillingProgramService.createFileMark(idWell, mark) selDownloadButtonEnabled(true) setChildKey(Date.now()) @@ -103,51 +106,59 @@ export default function DrillingProgram({idWell}) { setChildKey(Date.now()) } - const downloadButton =
- Программа бурения - - - - - - - - - - -
+ + + + + + + + + ) const lastUpdatedFileView = lastUpdatedFile && Последнее изменние: -  "{lastUpdatedFile.name}" +  '{lastUpdatedFile.name}'  [{formatBytes(lastUpdatedFile.size)}]  загружен: {new Date(lastUpdatedFile.uploadDate).toLocaleString()}  автор: - + - return( + return ( + - ) -} \ No newline at end of file + key = {childKey} + /> + + ) +} diff --git a/src/pages/Documents/index.jsx b/src/pages/Documents/index.jsx index c873118..08a3c63 100644 --- a/src/pages/Documents/index.jsx +++ b/src/pages/Documents/index.jsx @@ -1,27 +1,68 @@ -import {Layout, Menu} from "antd"; -import {Switch, useParams} from "react-router-dom"; -import {makeMenuItems, makeRouteItems} from './menuItems' +import path from 'path' +import { memo } from 'react' +import { Layout, Menu } from 'antd' +import { FolderOutlined } from '@ant-design/icons' +import { Switch, useParams, Link, Route } from 'react-router-dom' +import { PrivateMenuItem } from '../../components/Private' +import { isInRole } from '../../utils/PermissionService' +import DocumentsTemplate from './DocumentsTemplate' const { Content } = Layout -export default function MenuDocuments({idWell}) { - let {category} = useParams() +export const documentCategories = [ + { id: 1, key: 'fluidService', title: 'Растворный сервис' }, + { id: 2, key: 'cementing', title: 'Цементирование' }, + { id: 3, key: 'nnb', title: 'ННБ' }, + { id: 4, key: 'gti', title: 'ГТИ' }, + { id: 5, key: 'documentsForWell', title: 'Документы по скважине' }, + { id: 6, key: 'supervisor', title: 'Супервайзер' }, + { id: 7, key: 'master', title: 'Мастер' }, + { id: 8, key: 'toolService', title: 'Долотный сервис' }, + { id: 9, key: 'drillService', title: 'Буровой подрядчик' }, + { id: 9, key: 'closingService', title: 'Сервис по заканчиванию скважины' }, +] + +const getUserCategories = () => documentCategories.filter(cat => isInRole(cat.roles)) + +export const makeMenuItems = (root, cats) => { + const categories = cats ?? getUserCategories() + return categories.map(category => ( + }> + {category.title} + + )) +} + +export const MenuDocuments = memo(({ idWell }) => { + const { category } = useParams() const rootPath = `/well/${idWell}` - return(<> - - {makeMenuItems(rootPath)} - - - - - {makeRouteItems(rootPath, idWell)} + const root = path.join(rootPath, '/document') + const categories = getUserCategories() + + return ( + <> + + {makeMenuItems(root, categories)} + + + + + {categories.map(category => ( + + + + ))} - ) -} + + ) +}) + +export default MenuDocuments diff --git a/src/pages/Documents/menuItems.jsx b/src/pages/Documents/menuItems.jsx deleted file mode 100644 index 976d34b..0000000 --- a/src/pages/Documents/menuItems.jsx +++ /dev/null @@ -1,50 +0,0 @@ -import path from 'path' -import { FolderOutlined } from '@ant-design/icons' -import { Link, Route } from 'react-router-dom' -import { PrivateMenuItem } from '../../components/Private' -import { getUserRoles, isInRole } from "../../utils/PermissionService"; -import DocumentsTemplate from './DocumentsTemplate' - -export const documentCategories = [ - { id: 1, key: 'fluidService', title: 'Растворный сервис' }, - { id: 2, key: 'cementing', title: 'Цементирование' }, - { id: 3, key: 'nnb', title: 'ННБ' }, - { id: 4, key: 'gti', title: 'ГТИ' }, - { id: 5, key: 'documentsForWell', title: 'Документы по скважине' }, - { id: 6, key: 'supervisor', title: 'Супервайзер' }, - { id: 7, key: 'master', title: 'Мастер' }, -] - -const makeMenuItem = (keyValue, rootPath, title, other) => ( - - {title} - -) - -const makeRouteItem = (keyValue, rootPath, other) => ( - - - -) - -const getCategoriesByUserRole = (role) => documentCategories.filter(cat => isInRole(cat.roles)) - -export const makeMenuItems = (rootPath) => { - const root = path.join(rootPath, '/document') - const categories = getCategoriesByUserRole(getUserRoles()) - return categories.map(category => - makeMenuItem(category.key, root, category.title, {icon:})) -} - -export const makeRouteItems = (rootPath, idWell) => { - const root = path.join(rootPath, '/document') - const categories = getCategoriesByUserRole(getUserRoles()) - const routes = categories.map(category => makeRouteItem(category.key, root, { - idCategory: category.id, - idWell: idWell - })) - return routes -} diff --git a/src/pages/TelemetryView/SetpointSender.jsx b/src/pages/TelemetryView/SetpointSender.jsx index 6ad3b2e..8757e5d 100644 --- a/src/pages/TelemetryView/SetpointSender.jsx +++ b/src/pages/TelemetryView/SetpointSender.jsx @@ -3,7 +3,7 @@ import { Select, Modal, Input, InputNumber } from 'antd' import { SetpointsService } from '../../services/api' import LoaderPortal from '../../components/LoaderPortal' import { invokeWebApiWrapperAsync } from '../../components/factory' -import { makeNumericRender, EditableTable, makeNumericInput } from '../../components/Table' +import { makeNumericRender, EditableTable } from '../../components/Table' import { PeriodPicker, defaultPeriod } from '../../components/PeriodPicker' import { Grid, GridItem } from '../../components/Grid' @@ -54,6 +54,7 @@ export const SetpointSender = ({ idWell, onClose, visible, setpointNames }) => { const onModalOk = () => invokeWebApiWrapperAsync( async () => { + // eslint-disable-next-line no-sequences const setpointsObject = setpoints.reduce((obj, sp) => (obj[sp.name] = sp.value, obj), {}) const request = { uploadDate: new Date(), diff --git a/src/pages/Well.jsx b/src/pages/Well.jsx index f5ac3a0..2567b63 100644 --- a/src/pages/Well.jsx +++ b/src/pages/Well.jsx @@ -1,4 +1,4 @@ -import { Layout, Menu } from "antd"; +import { Layout, Menu } from 'antd' import { FolderOutlined, FundViewOutlined, @@ -6,112 +6,111 @@ import { FilePdfOutlined, DatabaseOutlined, ExperimentOutlined, - //FundProjectionScreenOutlined -} from "@ant-design/icons"; -import { Link, Redirect, Route, Switch, useParams } from "react-router-dom"; -import TelemetryView from "./TelemetryView"; -import Messages from "./Messages"; -import Report from "./Report"; -import Archive from "./Archive"; -import Documents from "./Documents"; -import Measure from "./Measure"; -import { makeMenuItems } from "./Documents/menuItems"; -import WellOperations from "./WellOperations"; -import DrillingProgram from "./Documents/DrillingProgram"; -import TelemetryAnalysis from "./TelemetryAnalysis" -import {PrivateMenuItem} from '../components/Private' + FundProjectionScreenOutlined, +} from '@ant-design/icons' +import { Link, Redirect, Route, Switch, useParams } from 'react-router-dom' +import { PrivateMenuItem } from '../components/Private' +import TelemetryView from './TelemetryView' +import Messages from './Messages' +import Report from './Report' +import Archive from './Archive' +import Documents from './Documents' +import Measure from './Measure' +import WellOperations from './WellOperations' +import TelemetryAnalysis from './TelemetryAnalysis' +import { makeMenuItems } from './Documents/' +import DrillingProgram from './Documents/DrillingProgram' -const { Content } = Layout; +const { Content } = Layout export default function Well() { - let { idWell, tab } = useParams(); - const rootPath = `/well/${idWell}`; + const { idWell, tab } = useParams() + const rootPath = `/well/${idWell}` - const { SubMenu } = Menu; + const { SubMenu } = Menu - return - + + }> + Мониторинг + + }> + Сообщения + + }> + Рапорт + + }> + Операции по скважине + + }> + Архив + + } roles={'admin'}> + Операции по телеметрии + + + Документы + + } + icon={} selectable={true} - selectedKeys={[tab]} - className="well_menu" > - }> - Мониторинг - - } roles={[]}> - Сообщения - - }> - Рапорт - - }> - Операции по скважине - - }> - Архив - - {/* }> - Операции по телеметрии - */} - - Документы - - } - icon={} - selectable={true} - > - {makeMenuItems(rootPath)} - - }> - Измерения - - }> - Программа бурения - - + {makeMenuItems(rootPath)} + + }> + Измерения + + }> + Программа бурения + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ) }