fix reports

This commit is contained in:
Фролов 2021-09-23 14:18:46 +05:00
parent f46d94f547
commit bb73a17a77
4 changed files with 227 additions and 170 deletions

View File

@ -97,3 +97,20 @@ export const formatBytes = (bytes:number) => {
else else
return `${(bytes/1024/1024).toFixed(2)}Mb` return `${(bytes/1024/1024).toFixed(2)}Mb`
} }
export const formatTimespan = (seconds:number) => {
const days = Math.floor(seconds / 86400)
seconds = seconds % 86400
const hours = Math.floor(seconds / 3600)
seconds = seconds % 3600
const minutes = Math.floor(seconds / 60)
seconds = seconds % 60
let formatedTimespan = ''
if(days > 0)
formatedTimespan += days + ' '
formatedTimespan += hours.toString().padStart(2,'0') + ':' +
minutes.toString().padStart(2,'0') + ':' +
seconds.toString().padStart(2,'0')
return formatedTimespan
}

View File

@ -1,28 +1,34 @@
import { Progress } from "antd" import { Progress, Button } from "antd"
import { download, notify } from "../../components/factory" import { download, notify } from "../../components/factory"
export const getReportFile = async (idWell, reportName) => { export const getReportFile = async (fileInfo) => {
try { try {
await download(`/api/well/${idWell}/report/${reportName}`, reportName) await download(`/api/well/${fileInfo.idWell}/files/${fileInfo.id}`)
} catch (error) { } catch (error) {
notify(`Не удалось скачать отчет ${reportName} по скважине (${idWell})`, 'error') notify(`Не удалось скачать отчет ${fileInfo.name} по скважине (${fileInfo.idWell})`, 'error')
console.log(error) console.log(error)
} }
} }
export const ReportCreationNotify = ({idWell, progressData}) => { export const ReportCreationNotify = ({progressData}) => {
progressData = progressData ?? {progress: 0.0, operation: 'Создание отчета', reportName: ''} progressData = progressData ?? {progress: 0.0, operation: 'Создание отчета'}
let downloadButton = null
if (progressData.file)
downloadButton = <Button
type="link"
onClick={_ => {getReportFile(progressData.file)}}
download={progressData.file.name}>
{progressData.file.name}
</Button>
const progressText = `${progressData.operation} стр ${progressData.currentPage} из ${progressData.totalPages}`
return ( return (
<> <>
<Progress percent={ progressData.progress } /> <Progress percent={ progressData.progress } />
<br /> <br/>
<span> { progressData.operation } </span> <span>{progressText}</span>
<br /> {downloadButton}
<button onClick={event => {getReportFile(idWell, progressData.reportName)}}
download={progressData.reportName}>
{ progressData.reportName }
</button>
</> </>
) )
} }

View File

@ -0,0 +1,91 @@
import { useState, useEffect } from "react"
import { Table, makeDateSorter, makeNumericSorter, formatDate} from "../../components/Table"
import { Button, Tooltip } from "antd"
import { FilePdfOutlined, FileTextOutlined} from '@ant-design/icons'
import { ReportService } from "../../services/api"
import { invokeWebApiWrapperAsync, download, formatTimespan} from "../../components/factory"
import LoaderPortal from "../../components/LoaderPortal"
import moment from "moment"
const imgPaths = {
".pdf": <FilePdfOutlined/>,
".las": <FileTextOutlined />,
}
const handleFileDownload = async (idWell, idFile) => {
invokeWebApiWrapperAsync(
async () => {
await download(`/api/well/${idWell}/files/${idFile}`)
},
null,
`Не удалось скачать файл ${idFile}`
)
}
const columns = [
{
title: "Название",
dataIndex: "name",
key: "name",
render: (name, report) => (
<Button
type="link"
icon={imgPaths[report.format]}
onClick={(_) => handleFileDownload(report.idWell, report.id)}
download={name}
>
{name}
</Button>
),
},
{
title: <Tooltip title="Дата формирования">Сформирован</Tooltip>,
dataIndex: "date",
key: "date",
sorter: makeDateSorter('date'),
render: date=>moment(date).format(formatDate),
},
{
title: <Tooltip title="Дата начала периода рапорта">С</Tooltip>,
dataIndex: "begin",
key: "begin",
sorter: makeDateSorter('begin'),
render: date=>moment(date).format(formatDate),
},
{
title: <Tooltip title="Дата окончания периода рапорта">По</Tooltip>,
dataIndex: "end",
key: "end",
sorter: makeDateSorter('end'),
render: date=>moment(date).format(formatDate),
},
{
title: <Tooltip title="шаг сетки графиков">шаг, сек</Tooltip>,
dataIndex: "step",
key: "step",
sorter: makeNumericSorter('step'),
render: step => formatTimespan(step)
},
]
export const Reports = ({idWell}) => {
const [reports, setReports] = useState([])
const [showLoader, setShowLoader] = useState(false)
useEffect(()=>invokeWebApiWrapperAsync(async()=>{
const reportsResponse = await ReportService.getAllReportsNamesByWell(idWell)
const reports = reportsResponse.map(r => ({...r, key: r.id?? r.name?? r.date}))
setReports(reports)
},setShowLoader), [idWell])
return (
<LoaderPortal show={showLoader}>
<Table
size='small' bordered
columns={columns}
dataSource={reports}
pagination={{pageSize:13}}/>
</LoaderPortal>)
}

View File

@ -1,20 +1,13 @@
import { useState, useEffect } from "react" import { useState, useEffect } from "react"
import { import { DatePicker, Radio, Button, Select, notification } from "antd"
Form,
DatePicker,
Radio,
Button,
Select,
Table,
notification,
} from "antd"
import "moment/locale/ru" import "moment/locale/ru"
import moment from "moment" import moment from "moment"
import { Subscribe } from "../../services/signalr" import { Subscribe } from "../../services/signalr"
import LoaderPortal from "../../components/LoaderPortal" import LoaderPortal from "../../components/LoaderPortal"
import { ReportService } from "../../services/api" import { ReportService } from "../../services/api"
import { ReportCreationNotify, getReportFile } from "./ReportCreationNotify" import { ReportCreationNotify } from "./ReportCreationNotify"
import { invokeWebApiWrapperAsync, notify} from "../../components/factory" import { invokeWebApiWrapperAsync, notify } from "../../components/factory"
import { Reports } from "./Reports"
const { RangePicker } = DatePicker const { RangePicker } = DatePicker
const { Option } = Select const { Option } = Select
@ -32,20 +25,20 @@ const timePeriodNames = [
{ label: "1 неделя", value: 604800 }, { label: "1 неделя", value: 604800 },
] ]
const imgPaths = {
".pdf": "/images/pdf.png",
".las": "/images/las.png",
}
const dateTimeFormat = "DD.MM.YYYY hh:mm:ss" const dateTimeFormat = "DD.MM.YYYY hh:mm:ss"
export default function Report({ idWell }) { export default function Report({ idWell }) {
const [aviableDateRange, setAviableDateRange] = useState([moment(),moment()]) const [aviableDateRange, setAviableDateRange] = useState([
const [filterDateRange, setFilterDateRange] = useState([moment().subtract(1, "days"),moment(),]) moment(),
moment(),
])
const [filterDateRange, setFilterDateRange] = useState([
moment().subtract(1, "days").startOf("day"),
moment().startOf("day"),
])
const [step, setStep] = useState(timePeriodNames[2].value) const [step, setStep] = useState(timePeriodNames[2].value)
const [format, setFormat] = useState(0) const [format, setFormat] = useState(0)
const [pagesCount, setPagesCount] = useState(0) const [pagesCount, setPagesCount] = useState(0)
const [suitableReports, setSuitableReports] = useState([])
const [showLoader, setShowLoader] = useState(false) const [showLoader, setShowLoader] = useState(false)
const periodOptions = timePeriodNames.map((item) => ( const periodOptions = timePeriodNames.map((item) => (
@ -54,47 +47,15 @@ export default function Report({ idWell }) {
</Option> </Option>
)) ))
const columns = [ const handleReportCreation = async () => {
{
title: "",
dataIndex: "reportFormat",
key: "reportFormat",
render: (format) => (
<img src={imgPaths[format]} width="50" alt={format}></img>
),
},
{
title: "Параметры отчета",
dataIndex: "reportParams",
key: "reportParams",
},
{
title: "Название отчета",
dataIndex: "reportName",
key: "reportName",
render: (reportName) => (
<Button
onClick={(_) => getReportFile(idWell, reportName)}
download={reportName}
>
{reportName}
</Button>
),
},
]
const handleReportCreation = async (values) => {
let begin = filterDateRange[0].toISOString() let begin = filterDateRange[0].toISOString()
let end = filterDateRange[1].toISOString() let end = filterDateRange[1].toISOString()
try { try {
const idUser = localStorage["userId"]
const taskId = await ReportService.createReport( const taskId = await ReportService.createReport(
idWell, idWell,
idUser, step,
values.step, format,
values.format,
begin, begin,
end end
) )
@ -111,9 +72,11 @@ export default function Report({ idWell }) {
></ReportCreationNotify> ></ReportCreationNotify>
), ),
duration: 0, duration: 0,
onClose: unSubscribeReportHub,
}) })
if (progressData.reportName?.length) unSubscribeReportHub() if (progressData.file)
unSubscribeReportHub()
} }
} }
@ -138,109 +101,93 @@ export default function Report({ idWell }) {
return current < aviableDateRange[0] || current > aviableDateRange[1] return current < aviableDateRange[0] || current > aviableDateRange[1]
} }
const updateSuitableReports = (suitableReports) => { useEffect(
const reports = suitableReports?.map(report => { () =>
const creationDate = new Date(report.begin).toLocaleString() invokeWebApiWrapperAsync(async () => {
const begin = new Date(report.begin).toLocaleString() const datesRangeResponse = await ReportService.getReportsDateRange(
const end = new Date(report.end).toLocaleString() idWell
const step = timePeriodNames[report.step] )
const reportParams = `Дата создания: ${creationDate}, Данные от ${begin} до ${end}, Шаг: ${step}`
return {
key: report.id,
reportFormat: report.format,
reportParams: reportParams,
reportName: report.name,
}})
setSuitableReports(reports??[])
}
const updateAviableDatesRange = (aviableDatesRange) =>{
const datesRange = [ const datesRange = [
moment(aviableDatesRange.from), moment(datesRangeResponse.from),
moment(aviableDatesRange.to) moment(datesRangeResponse.to),
] ]
let from = moment(aviableDatesRange.to)
from = from.subtract(1, "days")
if (from < datesRange[0])
from = datesRange[0]
const filterDateDefaults = [from, moment(aviableDatesRange.to)]
setFilterDateRange(filterDateDefaults)
setAviableDateRange(datesRange) setAviableDateRange(datesRange)
}
useEffect(() => invokeWebApiWrapperAsync(async() => { let from = moment(datesRangeResponse.to)
const aviableDatesRange = await ReportService.getReportsDateRange(idWell) from = from.subtract(1, "days")
updateAviableDatesRange(aviableDatesRange) if (from < datesRange[0]) from = datesRange[0]
const suitableReports = await ReportService.getSuitableReportsNames(idWell, 4294967295, 3, '0001-01-01T00:00:00.000Z', '9999-01-01T00:00:00.000Z')
updateSuitableReports(suitableReports)
}), [idWell])
useEffect(() => invokeWebApiWrapperAsync(async() => { const filterDateDefaults = [
if(!filterDateRange || filterDateRange.length < 2) from.startOf("day"),
return moment(datesRangeResponse.to).startOf("day"),
]
setFilterDateRange(filterDateDefaults)
}, setShowLoader),
[idWell]
)
useEffect(
() =>
invokeWebApiWrapperAsync(
async () => {
if (!filterDateRange || filterDateRange.length < 2) return
const begin = filterDateRange[0].toISOString() const begin = filterDateRange[0].toISOString()
const end = filterDateRange[1].toISOString() const end = filterDateRange[1].toISOString()
const pagesCount = await ReportService.getReportSize(idWell, step, format, begin, end) const pagesCount = await ReportService.getReportSize(
idWell,
step,
format,
begin,
end
)
setPagesCount(pagesCount) setPagesCount(pagesCount)
}, },
setShowLoader, setShowLoader,
`Не удалось получить предварительные параметры отчета c `Не удалось получить предварительные параметры отчета c
${filterDateRange[0].format(dateTimeFormat)} по ${filterDateRange[0].format(dateTimeFormat)} по
${filterDateRange[1].format(dateTimeFormat)}` ${filterDateRange[1].format(dateTimeFormat)}`
), [filterDateRange, step, format, idWell]) ),
[filterDateRange, step, format, idWell]
)
return ( return (
<div>
<LoaderPortal show={showLoader}> <LoaderPortal show={showLoader}>
<div className="w-100 mt-20px"> <div className="w-100 mt-20px mb-20px d-flex">
<Form <div>
layout="vertical" <div>Диапазон дат отчета</div>
name="reportForm"
initialValues={{ remember: true }}
onFinish={handleReportCreation}
>
<div className={"d-flex"}>
<Form.Item
label="Диапазон дат отчета"
name="period"
initialValue={filterDateRange}
>
<RangePicker <RangePicker
disabledDate={disabledDate} disabledDate={disabledDate}
allowClear={false} allowClear={false}
onCalendarChange={(dates) => { onCalendarChange={setFilterDateRange}
setFilterDateRange(dates)
}}
value = {filterDateRange}
showTime showTime
value={filterDateRange}
/> />
</Form.Item> </div>
<Form.Item <div className="ml-30px">
label="Шаг графиков" <div>Шаг графиков</div>
name="step" <Select style={{ width: "8rem" }}
initialValue={step} onChange={e=>{
className="ml-30px" setStep(e)
> }}
<Select onChange={setStep}>{periodOptions}</Select> value={step}>
</Form.Item> {periodOptions}
<Form.Item </Select>
label="Формат отчета" </div>
name="format"
initialValue={format} <div className="ml-30px">
<div>Формат отчета</div>
<Radio.Group
onChange={(e) => setFormat(e.target.value)} onChange={(e) => setFormat(e.target.value)}
className="ml-30px" value={format}
> >
<Radio.Group>
<Radio.Button value={0}>PDF</Radio.Button> <Radio.Button value={0}>PDF</Radio.Button>
<Radio.Button value={1}>LAS</Radio.Button> <Radio.Button value={1}>LAS</Radio.Button>
</Radio.Group> </Radio.Group>
</Form.Item> </div>
<Button <div className="ml-30px">
type="primary" <div>&nbsp;</div>
htmlType="submit" <Button type="primary" onClick={handleReportCreation}>
className="mt-30px ml-30px"
>
<span>Получить рапорт</span> <span>Получить рапорт</span>
<span className={"ml-5px"}>({pagesCount} стр.)</span> <span className={"ml-5px"}>({pagesCount} стр.)</span>
<span <span
@ -251,13 +198,9 @@ export default function Report({ idWell }) {
</span> </span>
</Button> </Button>
</div> </div>
</Form>
</div> </div>
<br />
<h3>Отчеты с аналогичными параметрами, доступные для скачивания:</h3>{" "}
<br />
<Table dataSource={suitableReports} columns={columns} />
</LoaderPortal> </LoaderPortal>
<Reports idWell={idWell} />
</div>
) )
} }