diff --git a/src/components/AnalysisOperationTime.jsx b/src/components/AnalysisOperationTime.jsx index cdf0d81..518a0c3 100644 --- a/src/components/AnalysisOperationTime.jsx +++ b/src/components/AnalysisOperationTime.jsx @@ -1,58 +1,40 @@ -import { useParams } from "react-router-dom" -import { DatePicker } from 'antd'; -import { notify } from "../components/factory" -import { useState, useEffect } from 'react' -import { TelemetryAnalyticsService } from '../services/api' -import { ChartOperationTime } from './charts/ChartOperationTime' -import LoaderPortal from '../components/LoaderPortal' import moment from 'moment' +import { DatePicker } from 'antd' +import { useState, useEffect } from 'react' +import { useParams } from 'react-router-dom' + +import LoaderPortal from '@components/LoaderPortal' +import { invokeWebApiWrapperAsync } from '@components/factory' +import { TelemetryAnalyticsService } from '@api' +import { ChartOperationTime } from './charts/ChartOperationTime' const { RangePicker } = DatePicker -const lines = [{ labelAccessorName: "processName", pieceAccessorName: "duration" }] +const lines = [{ labelAccessorName: 'processName', pieceAccessorName: 'duration' }] -export function AnalysisOperationTime() { - let { id } = useParams() +export const AnalysisOperationTime = () => { + const { id } = useParams() const [operationTimeData, setOperationTimeData] = useState([]) const [loader, setLoader] = useState(false) const [range, setRange] = useState([moment().subtract(1,'days'), moment()]) - const onChangeRange = (range) => { - setRange(range) - } - - const handleReceiveOperationTimeData = (data) => { - setOperationTimeData(data) - } - - useEffect(() => { - setLoader(true) - let begin = null - let end = null - if (range?.length > 1) { - begin = range[0].toISOString() - end = range[1].toISOString() - } - TelemetryAnalyticsService.getOperationsSummary(id, begin, end) - .then(handleReceiveOperationTimeData) - .catch(error => { - notify(`Не удалось получить данные для Анализа Операция-Время по скважине "${id}" за период с ${begin} по ${end}`, - 'warning') - console.log(error) - }) - .finally(setLoader(false)) - }, [id, range]) + useEffect(() => invokeWebApiWrapperAsync( + async () => { + const begin = range?.length > 1 ? range[0].toISOString() : null + const end = range?.length > 1 ? range[1].toISOString() : null + const summary = await TelemetryAnalyticsService.getOperationsSummary(id, begin, end) + setOperationTimeData(summary) + }, + setLoader, + `Не удалось получить данные для Анализа Операция-Время по скважине '${id}' за период с ${begin} по ${end}` + ), [id, range]) return ( - - + setRange(range)} /> + ) -} \ No newline at end of file +} + +export default AnalysisOperationTime diff --git a/src/components/ChangePassword.tsx b/src/components/ChangePassword.tsx index 2f7b556..8cd1e63 100644 --- a/src/components/ChangePassword.tsx +++ b/src/components/ChangePassword.tsx @@ -2,13 +2,13 @@ import { memo, useState } from 'react' import { useForm } from 'antd/lib/form/Form' import { Form, Input, Modal, FormProps } from 'antd' -import { AuthService, UserDto } from '../services/api' -import { passwordRules, createPasswordRules } from '../utils/validationRules' +import { AuthService, UserDto } from '@api' +import { getUserId, getUserLogin } from '@utils/storage' +import { passwordRules, createPasswordRules } from '@utils/validationRules' import LoaderPortal from './LoaderPortal' import { invokeWebApiWrapperAsync } from './factory' import { UserView } from './views' -import { getUserId, getUserLogin } from '../utils/storage' const formLayout: FormProps = { labelCol: { span: 11 }, wrapperCol: { span: 16 } } diff --git a/src/components/Display.jsx b/src/components/Display.jsx index 065ccf2..77d1a1b 100644 --- a/src/components/Display.jsx +++ b/src/components/Display.jsx @@ -1,90 +1,86 @@ -import { useState, useEffect } from 'react'; +import moment from 'moment' +import { useState, useEffect, memo } from 'react' import {CaretUpOutlined, CaretDownOutlined, CaretRightOutlined} from '@ant-design/icons' -import moment from 'moment'; -import '../styles/display.css' -export const formatNumber = (value, format) => +import '@styles/display.css' + +export const formatNumber = (value, format) => Number.isInteger(format) && Number.isFinite(value) ? (+value).toFixed(format) : (+value).toPrecision(4) -export const ValueDisplay = ({prefix, value, suffix, isArrowVisible, format, enumeration}) => { +const iconStyle = { color:'#0008' } +const displayValueStyle = { display: 'flex', flexGrow: 1 } + +export const ValueDisplay = ({ prefix, value, suffix, isArrowVisible, format, enumeration }) => { const [val, setVal] = useState('---') - const [arrowState, setArrowState] = useState({ + const [arrowState, setArrowState] = useState({ preVal: NaN, preTimestamp: Date.now(), direction: 0, }) - useEffect(()=>{ - if(value === undefined || value === null || value === '-' || value === '--'){ - setVal('---') - return - } + useEffect(() => { + setVal((preVal) => { + if ((value ?? '-') === '-' || value === '--') return '---' + if (enumeration?.[value]) return enumeration[value] - if(enumeration && enumeration[value]){ - setVal(enumeration[value]) - return - } + if (Number.isFinite(+value)) { + if (isArrowVisible && (arrowState.preTimestamp + 1000 < Date.now())) { + let direction = 0 + if (value > arrowState.preVal) + direction = 1 + if (value < arrowState.preVal) + direction = -1 - if(Number.isFinite(+value)){ - if ((isArrowVisible) && (arrowState.preTimestamp + 1000 < Date.now())) - { - let direction = 0 - if (value > arrowState.preVal) - direction = 1 - if (value < arrowState.preVal) - direction = -1 + setArrowState({ + preVal: value, + preTimestamp: Date.now(), + direction: direction, + }) + } - setArrowState({ - preVal: value, - preTimestamp: Date.now(), - direction: direction, - }) + return formatNumber(value, format) } - setVal(formatNumber(value, format)) - return - } - - if(value.length > 4){ - let valueDate = moment(value) - if(valueDate.isValid()){ - setVal(valueDate.format(format)) - return + if (value.length > 4) { + const valueDate = moment(value) + if (valueDate.isValid()) + return valueDate.format(format) } - } - setVal(value) + return value + }) },[value, isArrowVisible, arrowState, format, enumeration]) let arrow = null if(isArrowVisible) switch (arrowState.direction){ case 0: - arrow = + arrow = break case 1: - arrow = + arrow = break case -1: - arrow = + arrow = break default: break - } + } - return({prefix} {val} {suffix}{arrow}) + return( + + {prefix} {val} {suffix}{arrow} + + ) } -export const Display = (props)=>{ - const {label} = props - - return
-
{label}
-
- -
+export const Display = memo(({ className, label, ...other })=> ( +
+
{label}
+
+
- -} \ No newline at end of file +
+)) diff --git a/src/components/ErrorFetch.js b/src/components/ErrorFetch.js index 5f4cdbd..b4f2bed 100644 --- a/src/components/ErrorFetch.js +++ b/src/components/ErrorFetch.js @@ -1,7 +1,9 @@ export class ErrorFetch extends Error { constructor(status, message) { - super(message); - this.name = "ErrorFetch" + super(message) + this.name = 'ErrorFetch' this.status = status } -} \ No newline at end of file +} + +export default ErrorFetch diff --git a/src/components/Grid.tsx b/src/components/Grid.tsx index 3b653c4..81783ab 100644 --- a/src/components/Grid.tsx +++ b/src/components/Grid.tsx @@ -1,34 +1,28 @@ -import React from 'react' +import React, { HTMLAttributes, memo } from 'react' -interface ComponentProps { - children?: React.ReactNode - style?: React.CSSProperties - [other: string]: any -} +export type ComponentProps = HTMLAttributes -interface GridItemProps extends ComponentProps { - children?: React.ReactNode - style?: React.CSSProperties +export type GridItemProps = ComponentProps & { row: number col: number rowSpan?: number colSpan?: number } -const gridDefaultStyle = { +export const gridDefaultStyle = { display: 'grid', margin: '8px', justifyItems: 'stretch', alignItems: 'stretch', } -export const Grid = ({ children, style, ...other }: ComponentProps) => ( +export const Grid = memo(({ children, style, ...other }) => (
{children}
-) +)) -export const GridItem = ({ children, row, col, rowSpan, colSpan, style, ...other }: GridItemProps) => { +export const GridItem = memo(({ children, row, col, rowSpan, colSpan, style, ...other }) => { const localRow = +row const localCol = +col const localColSpan = colSpan ? colSpan - 1 : 0 @@ -42,13 +36,15 @@ export const GridItem = ({ children, row, col, rowSpan, colSpan, style, ...other ...style, } - return
- {children} -
-} + return ( +
+ {children} +
+ ) +}) -export const Flex = ({ children, style, ...other } : ComponentProps) => ( +export const Flex = memo(({ children, style, ...other }) => (
{children}
-) +)) diff --git a/src/components/Layout/AdminLayoutPortal.tsx b/src/components/Layout/AdminLayoutPortal.tsx index 3125e97..72442d8 100644 --- a/src/components/Layout/AdminLayoutPortal.tsx +++ b/src/components/Layout/AdminLayoutPortal.tsx @@ -2,7 +2,7 @@ import { memo, ReactNode } from 'react' import { Link } from 'react-router-dom' import { Button, Layout, LayoutProps } from 'antd' -import PageHeader from '../PageHeader' +import PageHeader from '@components/PageHeader' export type AdminLayoutPortalProps = LayoutProps & { title?: ReactNode diff --git a/src/components/Layout/LayoutPortal.tsx b/src/components/Layout/LayoutPortal.tsx index e0f32a5..438acf9 100644 --- a/src/components/Layout/LayoutPortal.tsx +++ b/src/components/Layout/LayoutPortal.tsx @@ -1,8 +1,8 @@ import { memo, ReactNode } from 'react' import { Layout, LayoutProps } from 'antd' -import PageHeader from '../PageHeader' -import WellTreeSelector from '../WellTreeSelector' +import PageHeader from '@components/PageHeader' +import WellTreeSelector from '@components/WellTreeSelector' export type LayoutPortalProps = LayoutProps & { title?: ReactNode diff --git a/src/components/Loader.jsx b/src/components/Loader.jsx deleted file mode 100644 index 7c9a0ac..0000000 --- a/src/components/Loader.jsx +++ /dev/null @@ -1,4 +0,0 @@ -/* original from https://loading.io/css/ */ -export default function Loader(){ - return(
) -} \ No newline at end of file diff --git a/src/components/Loader.tsx b/src/components/Loader.tsx new file mode 100644 index 0000000..9bbbfcf --- /dev/null +++ b/src/components/Loader.tsx @@ -0,0 +1,9 @@ +import { memo, HTMLAttributes } from 'react' + +export const Loader = memo>(({ ...other }) => ( +
+
+
+)) + +export default Loader diff --git a/src/components/LoaderPortal.tsx b/src/components/LoaderPortal.tsx index 6fff91d..5b3e784 100644 --- a/src/components/LoaderPortal.tsx +++ b/src/components/LoaderPortal.tsx @@ -1,13 +1,13 @@ +import { HTMLAttributes, ReactNode } from 'react' + import Loader from './Loader' -type LoaderPortalProps = { +type LoaderPortalProps = HTMLAttributes & { show?: boolean, fade?: boolean, - children: any, - [other: string]: any } -export const LoaderPortal: React.FC = ({show, fade=true, children, ...other}) => ( +export const LoaderPortal: React.FC = ({ show, fade = true, children, ...other }) => (
{children}
{show && fade &&
} diff --git a/src/components/PeriodPicker.tsx b/src/components/PeriodPicker.tsx index 90ff7d6..0d0827e 100644 --- a/src/components/PeriodPicker.tsx +++ b/src/components/PeriodPicker.tsx @@ -1,4 +1,5 @@ -import { Select } from 'antd' +import { memo } from 'react' +import { Select, SelectProps } from 'antd' export const defaultPeriod = 600 @@ -13,19 +14,18 @@ const timePeriodCollection = [ { value: 86400, label: '24 часа' } ] -type PeriodPickerProps = { - defaultValue?: number - onChange?: (value: number) => void - [other: string]: any +export type PeriodPickerProps = SelectProps & { + defaultValue?: VT + onChange?: (value: VT) => void } -export const PeriodPicker = ({ defaultValue = defaultPeriod, onChange, ...other }: PeriodPickerProps) => ( +export const PeriodPicker = memo(({ defaultValue = defaultPeriod, onChange, ...other }) => ( - {options} - -} diff --git a/src/components/Table/index.tsx b/src/components/Table/index.tsx index e010866..c263f33 100644 --- a/src/components/Table/index.tsx +++ b/src/components/Table/index.tsx @@ -1,14 +1,15 @@ import { memo, useEffect, useState, ReactNode } from 'react' -import { InputNumber, Select, Table as RawTable, Tag, SelectProps } from 'antd' +import { InputNumber, Select, Table as RawTable, Tag, SelectProps, TableProps } from 'antd' +import { SelectValue } from 'antd/lib/select' import { OptionsType } from 'rc-select/lib/interface' +import { Rule } from 'rc-field-form/lib/interface' + import { tryAddKeys } from './EditableTable' import { makeNumericSorter, makeStringSorter } from './sorters' -import { Rule } from 'rc-field-form/lib/interface' -import { SelectValue } from 'antd/lib/select' + export { makeDateSorter, makeNumericSorter, makeStringSorter } from './sorters' export { EditableTable, makeActionHandler } from './EditableTable' export { DatePickerWrapper } from './DatePickerWrapper' -export { SelectFromDictionary } from './SelectFromDictionary' export const RegExpIsFloat = /^[-+]?\d+\.?\d*$/ @@ -17,7 +18,7 @@ export const defaultPagination = { showSizeChanger: true, } -export const makeNumericRender = (fixed?: number) => (value: any, row: object): ReactNode => { +export const makeNumericRender = (fixed?: number) => (value: any, _: object): ReactNode => { let val = '-' if ((value ?? null) !== null && Number.isFinite(+value)) { val = (fixed ?? null) !== null @@ -225,8 +226,9 @@ export const makeSelectColumn = ( const makeTagInput = >(value_key: string, label_key: string) => memo<{ options: T[], value?: T[], - onChange?: (values: T[]) => void -}>(({ options, value, onChange }) => { + onChange?: (values: T[]) => void, + other?: SelectProps, +}>(({ options, value, onChange, other }) => { const [selectOptions, setSelectOptions] = useState([]) const [selectedValue, setSelectedValue] = useState([]) @@ -259,6 +261,7 @@ const makeTagInput = >(value_key: string, label_ke return (