* Изменена сигнатура функций makeNumericColumn и её обёрток

* Улучшено отображение некоторых элементов
This commit is contained in:
Александр Сироткин 2022-12-13 18:28:30 +05:00
parent d235b01c80
commit f4adb528ca
37 changed files with 247 additions and 283 deletions

10
.vscode/settings.json vendored
View File

@ -1,6 +1,14 @@
{ {
"cSpell.words": [ "cSpell.words": [
"день" "день",
"КНБК",
"САУБ",
"antd",
"Poprompt",
"saub",
"setpoint",
"Setpoints",
"usehooks"
], ],
"liveServer.settings.port": 5501 "liveServer.settings.port": 5501
} }

View File

@ -24,6 +24,7 @@ export const makeDateColumn = <T extends unknown>(
other?: ColumnProps<T>, other?: ColumnProps<T>,
pickerOther?: DatePickerWrapperProps, pickerOther?: DatePickerWrapperProps,
) => makeColumn<T>(title, key, { ) => makeColumn<T>(title, key, {
editable: true,
...other, ...other,
render: (date) => ( render: (date) => (
<div className={'text-align-r-container'}> <div className={'text-align-r-container'}>

View File

@ -9,7 +9,6 @@ import { OmitExtends } from '@utils/types'
export * from './date' export * from './date'
export * from './time' export * from './time'
export * from './numeric' export * from './numeric'
export * from './plan_fact'
export * from './select' export * from './select'
export * from './tag' export * from './tag'
export * from './text' export * from './text'
@ -45,6 +44,7 @@ export const makeColumn = <T = any>(title: ReactNode, key: Key, other?: ColumnPr
title: title, title: title,
key: key, key: key,
dataIndex: key, dataIndex: key,
render: (value: T) => value,
...other, ...other,
}) })

View File

@ -1,4 +1,3 @@
import { ColumnFilterItem } from 'antd/lib/table/interface'
import { InputNumber } from 'antd' import { InputNumber } from 'antd'
import { Key, ReactNode } from 'react' import { Key, ReactNode } from 'react'
@ -46,18 +45,17 @@ export const makeNumericColumnOptions = <T extends number>(fixed?: number, sorte
export const makeNumericColumn = <T extends number>( export const makeNumericColumn = <T extends number>(
title: ReactNode, title: ReactNode,
key: Key, key: Key,
filters?: ColumnFilterItem[],
filterDelegate?: FilterGenerator<T>,
renderDelegate?: RenderMethod<T>, renderDelegate?: RenderMethod<T>,
filterDelegate?: FilterGenerator<T>,
width?: string | number, width?: string | number,
other?: ColumnProps<T>, other?: ColumnProps<T>,
) => makeColumn(title, key, { ) => makeColumn(title, key, {
filters, editable: true,
onFilter: filterDelegate ? filterDelegate(key) : undefined, onFilter: filterDelegate ? filterDelegate(key) : undefined,
sorter: makeNumericSorter(key), sorter: makeNumericSorter(key),
width, width,
input: <InputNumber style={{ width: '100%' }}/>, input: <InputNumber style={{ width: '100%' }} defaultValue={0} />,
render: renderDelegate ?? makeNumericRender<T>(2), render: renderDelegate || makeNumericRender<T>(2),
align: 'right', align: 'right',
...other ...other
}) })
@ -65,54 +63,78 @@ export const makeNumericColumn = <T extends number>(
export const makeNumericColumnPlanFact = <T extends number>( export const makeNumericColumnPlanFact = <T extends number>(
title: ReactNode, title: ReactNode,
key: Key, key: Key,
filters?: ColumnFilterItem[],
filterDelegate?: FilterGenerator<T>,
renderDelegate?: RenderMethod<T>, renderDelegate?: RenderMethod<T>,
filterDelegate?: FilterGenerator<T>,
width?: string | number,
other?: ColumnProps<T>,
) => {
return {
title,
children: [
makeNumericColumn<T>('План', `${key}.plan`, renderDelegate, filterDelegate, width, other),
makeNumericColumn<T>('Факт', `${key}.fact`, renderDelegate, filterDelegate, width, other),
]
}
}
/**
* @deprecated Для значений типа план/факт появилась модель `PlanFactDto`, использование 2 полей с суффиксами неактуально
* @param title Заголовок столбца
* @param key Ключ столбца
* @param filters Список значений для фильтрации
* @param filterDelegate Метод фильтрации
* @param renderDelegate Render-метод отображения ячейки
* @param width Ширина столбца
* @param other Дополнительные опции
* @returns Объект-столбец для таблицы
*/
export const makeNumericColumnPlanFactOld = <T extends number>(
title: ReactNode,
key: Key,
renderDelegate?: RenderMethod<T>,
filterDelegate?: FilterGenerator<T>,
width?: string | number, width?: string | number,
other?: ColumnProps<T>, other?: ColumnProps<T>,
) => makeGroupColumn(title, [ ) => makeGroupColumn(title, [
makeNumericColumn<T>('п', key + 'Plan', filters, filterDelegate, renderDelegate, width, other), makeNumericColumn<T>('План', key + 'Plan', renderDelegate, filterDelegate, width, other),
makeNumericColumn<T>('ф', key + 'Fact', filters, filterDelegate, renderDelegate, width, other), makeNumericColumn<T>('Факт', key + 'Fact', renderDelegate, filterDelegate, width, other),
]) ])
export const makeNumericStartEnd = <T extends number>( export const makeNumericStartEnd = <T extends number>(
title: ReactNode, title: ReactNode,
key: Key, key: Key,
fixed: number, fixed: number,
filters?: ColumnFilterItem[],
filterDelegate?: FilterGenerator<T>,
renderDelegate?: RenderMethod<T>, renderDelegate?: RenderMethod<T>,
filterDelegate?: FilterGenerator<T>,
width?: string | number, width?: string | number,
) => makeGroupColumn(title, [ ) => makeGroupColumn(title, [
makeNumericColumn<T>('старт', key + 'Start', filters, filterDelegate, renderDelegate, width, makeNumericColumnOptions(fixed, key + 'Start')), makeNumericColumn<T>('старт', key + 'Start', renderDelegate, filterDelegate, width, makeNumericColumnOptions(fixed, key + 'Start')),
makeNumericColumn<T>('конец', key + 'End', filters, filterDelegate, renderDelegate, width, makeNumericColumnOptions(fixed, key + 'End')) makeNumericColumn<T>('конец', key + 'End', renderDelegate, filterDelegate, width, makeNumericColumnOptions(fixed, key + 'End'))
]) ])
export const makeNumericMinMax = <T extends number>( export const makeNumericMinMax = <T extends number>(
title: ReactNode, title: ReactNode,
key: Key, key: Key,
fixed: number, fixed: number,
filters?: ColumnFilterItem[],
filterDelegate?: FilterGenerator<T>,
renderDelegate?: RenderMethod<T>, renderDelegate?: RenderMethod<T>,
filterDelegate?: FilterGenerator<T>,
width?: string | number, width?: string | number,
) => makeGroupColumn(title, [ ) => makeGroupColumn(title, [
makeNumericColumn<T>('мин', key + 'Min', filters, filterDelegate, renderDelegate, width, makeNumericColumnOptions(fixed, key + 'Min')), makeNumericColumn<T>('мин', key + 'Min', renderDelegate, filterDelegate, width, makeNumericColumnOptions(fixed, key + 'Min')),
makeNumericColumn<T>('макс', key + 'Max', filters, filterDelegate, renderDelegate, width, makeNumericColumnOptions(fixed, key + 'Max')), makeNumericColumn<T>('макс', key + 'Max', renderDelegate, filterDelegate, width, makeNumericColumnOptions(fixed, key + 'Max')),
]) ])
export const makeNumericAvgRange = <T extends number>( export const makeNumericAvgRange = <T extends number>(
title: ReactNode, title: ReactNode,
key: Key, key: Key,
fixed: number, fixed: number,
filters?: ColumnFilterItem[],
filterDelegate?: FilterGenerator<T>,
renderDelegate?: RenderMethod<T>, renderDelegate?: RenderMethod<T>,
filterDelegate?: FilterGenerator<T>,
width?: string | number, width?: string | number,
) => makeGroupColumn(title, [ ) => makeGroupColumn(title, [
makeNumericColumn<T>('мин', `${key}.min`, filters, filterDelegate, renderDelegate, width, makeNumericColumnOptions(fixed, `${key}.min`)), makeNumericColumn<T>('мин', `${key}.min`, renderDelegate, filterDelegate, width, makeNumericColumnOptions(fixed, `${key}.min`)),
makeNumericColumn<T>('сред', `${key}.avg`, filters, filterDelegate, renderDelegate, width, makeNumericColumnOptions(fixed, `${key}.avg`)), makeNumericColumn<T>('сред', `${key}.avg`, renderDelegate, filterDelegate, width, makeNumericColumnOptions(fixed, `${key}.avg`)),
makeNumericColumn<T>('макс', `${key}.max`, filters, filterDelegate, renderDelegate, width, makeNumericColumnOptions(fixed, `${key}.max`)), makeNumericColumn<T>('макс', `${key}.max`, renderDelegate, filterDelegate, width, makeNumericColumnOptions(fixed, `${key}.max`)),
]) ])
export default makeNumericColumn export default makeNumericColumn

View File

@ -1,22 +0,0 @@
import { Key, ReactNode } from 'react'
import { ColumnProps, makeColumn } from '.'
export const makeColumnsPlanFact = <T,>(
title: string | ReactNode,
key: Key | [Key, Key],
columsOther?: ColumnProps<T> | [ColumnProps<T>, ColumnProps<T>],
) => {
const keys = Array.isArray(key) ? key : [`${key}Plan`, `${key}Fact`]
const others = Array.isArray(columsOther) ? columsOther : [columsOther, columsOther]
return {
title,
children: [
makeColumn<T>('план', keys[0], others[0]),
makeColumn<T>('факт', keys[1], others[1]),
]
}
}
export default makeColumnsPlanFact

View File

@ -1,9 +1,17 @@
import { Select, SelectProps } from 'antd' import { Select, SelectProps } from 'antd'
import { DefaultOptionType, SelectValue } from 'antd/lib/select' import { DefaultOptionType, SelectValue } from 'antd/lib/select'
import { Key, ReactNode } from 'react' import { Key, ReactNode, useMemo } from 'react'
import { ColumnProps, makeColumn } from '.' import { ColumnProps, makeColumn } from '.'
const findOption = <T extends DefaultOptionType>(value: any, options: T[] | undefined) =>
options?.find((option) => String(option?.value) === String(value))
const SelectWrapper = ({ value, options, ...other }: SelectProps) => {
const selectValue = useMemo(() => findOption(value, options)?.label, [value, options])
return <Select value={selectValue} options={options} {...other} />
}
export const makeSelectColumn = <T extends DefaultOptionType>( export const makeSelectColumn = <T extends DefaultOptionType>(
title: ReactNode, title: ReactNode,
key: Key, key: Key,
@ -12,10 +20,11 @@ export const makeSelectColumn = <T extends DefaultOptionType>(
other?: ColumnProps<T>, other?: ColumnProps<T>,
selectOther?: SelectProps<SelectValue> selectOther?: SelectProps<SelectValue>
) => makeColumn(title, key, { ) => makeColumn(title, key, {
editable: true,
...other, ...other,
input: <Select options={options} {...selectOther}/>, input: <SelectWrapper options={options} {...selectOther}/>,
render: (value, dataset, index) => { render: (value, dataset, index) => {
const item = options?.find(option => String(option?.value) === String(value)) const item = findOption(value, options)
return other?.render?.(item, dataset, index) ?? item?.label ?? defaultValue?.label ?? value?.label ?? '--' return other?.render?.(item, dataset, index) ?? item?.label ?? defaultValue?.label ?? value?.label ?? '--'
} }
}) })

View File

@ -65,6 +65,7 @@ export const makeTagColumn = <T extends DataType>(
const InputComponent = makeTagInput<T>(value_key, label_key) const InputComponent = makeTagInput<T>(value_key, label_key)
return makeColumn(title, dataIndex, { return makeColumn(title, dataIndex, {
editable: true,
...other, ...other,
render: (item: T[] | undefined, dataset, index) => item?.map((elm: T) => <Tag key={elm[label_key]} color={'blue'}>{other?.render?.(elm, dataset, index) ?? elm[label_key]}</Tag>) ?? '-', render: (item: T[] | undefined, dataset, index) => item?.map((elm: T) => <Tag key={elm[label_key]} color={'blue'}>{other?.render?.(elm, dataset, index) ?? elm[label_key]}</Tag>) ?? '-',
input: <InputComponent {...tagOther} options={options} />, input: <InputComponent {...tagOther} options={options} />,

View File

@ -1,3 +1,4 @@
import { Tooltip } from 'antd'
import { ColumnFilterItem } from 'antd/lib/table/interface' import { ColumnFilterItem } from 'antd/lib/table/interface'
import { Key, ReactNode } from 'react' import { Key, ReactNode } from 'react'
@ -15,6 +16,18 @@ export const makeStringSorter = <T extends string>(key: Key): SorterMethod<T> =>
return String(vA).localeCompare(String(vB)) return String(vA).localeCompare(String(vB))
} }
export const makeTextRender = <T extends string>(def = '---', stringCutter?: (text: string) => string) => (value: T) => {
if (!value) return def
if (stringCutter) {
return (
<Tooltip title={value}>
{stringCutter(value)}
</Tooltip>
)
}
return value
}
export const makeFilterTextMatch = <T extends unknown>(key: keyof DataType<T>) => export const makeFilterTextMatch = <T extends unknown>(key: keyof DataType<T>) =>
(filterValue: T, dataItem: DataType<T>) => dataItem[key] === filterValue (filterValue: T, dataItem: DataType<T>) => dataItem[key] === filterValue
@ -26,10 +39,11 @@ export const makeTextColumn = <T extends unknown = any>(
render?: RenderMethod<T>, render?: RenderMethod<T>,
other?: ColumnProps other?: ColumnProps
) => makeColumn(title, key, { ) => makeColumn(title, key, {
editable: true,
filters, filters,
onFilter: filters ? makeFilterTextMatch(key) : undefined, onFilter: filters ? makeFilterTextMatch(key) : undefined,
sorter: sorter ?? makeStringSorter(key), sorter: sorter || makeStringSorter(key),
render: render, render: render || makeTextRender(),
...other ...other
}) })

View File

@ -24,6 +24,7 @@ export const makeTimeColumn = <T extends TimeDto>(
other?: ColumnProps, other?: ColumnProps,
pickerOther?: TimePickerWrapperProps, pickerOther?: TimePickerWrapperProps,
) => makeColumn<T>(title, key, { ) => makeColumn<T>(title, key, {
editable: true,
...other, ...other,
render: (time) => ( render: (time) => (
<div className={'text-align-r-container'}> <div className={'text-align-r-container'}>

View File

@ -3,11 +3,12 @@ import { Input } from 'antd'
import { import {
EditableTable, EditableTable,
makeColumn,
makeSelectColumn, makeSelectColumn,
makeStringSorter, makeStringSorter,
defaultPagination, defaultPagination,
makeTimezoneColumn makeTimezoneColumn,
makeNumericColumn,
makeTextColumn
} from '@components/Table' } from '@components/Table'
import { invokeWebApiWrapperAsync } from '@components/factory' import { invokeWebApiWrapperAsync } from '@components/factory'
import { AdminClusterService, AdminDepositService } from '@api' import { AdminClusterService, AdminDepositService } from '@api'
@ -30,17 +31,11 @@ const ClusterController = memo(() => {
const clusterColumns = useMemo(() => [ const clusterColumns = useMemo(() => [
makeSelectColumn('Месторождение', 'idDeposit', deposits, '--', { makeSelectColumn('Месторождение', 'idDeposit', deposits, '--', {
width: 200, width: 200,
editable: true,
sorter: makeStringSorter('idDeposit') sorter: makeStringSorter('idDeposit')
}), }),
makeColumn('Название', 'caption', { makeTextColumn('Название', 'caption', undefined, undefined, undefined, { width: 200, formItemRules: min1 }),
width: 200, makeNumericColumn('Широта', 'latitude', coordsFormat, undefined, 150),
editable: true, makeNumericColumn('Долгота', 'longitude', coordsFormat, undefined, 150),
sorter: makeStringSorter('caption'),
formItemRules: min1,
}),
makeColumn('Широта', 'latitude', { width: 150, editable: true, render: coordsFormat }),
makeColumn('Долгота', 'longitude', { width: 150, editable: true, render: coordsFormat }),
makeTimezoneColumn('Зона', 'timezone', null, true, { width: 150 }), makeTimezoneColumn('Зона', 'timezone', null, true, { width: 150 }),
], [deposits]) ], [deposits])

View File

@ -3,10 +3,9 @@ import { Input } from 'antd'
import { import {
EditableTable, EditableTable,
makeColumn,
makeStringSorter,
makeSelectColumn, makeSelectColumn,
defaultPagination defaultPagination,
makeTextColumn
} from '@components/Table' } from '@components/Table'
import { invokeWebApiWrapperAsync } from '@components/factory' import { invokeWebApiWrapperAsync } from '@components/factory'
import { AdminCompanyService, AdminCompanyTypeService } from '@api' import { AdminCompanyService, AdminCompanyTypeService } from '@api'
@ -37,16 +36,8 @@ const CompanyController = memo(() => {
})) }))
setColumns([ setColumns([
makeColumn('Название', 'caption', { makeTextColumn('Название', 'caption', undefined, undefined, undefined, { width: 200, formItemRules: min1 }),
width: 200, makeSelectColumn('Тип компании', 'idCompanyType', companyTypes, null, { width: 200 }),
editable: true,
sorter: makeStringSorter('caption'),
formItemRules: min1,
}),
makeSelectColumn('Тип компании', 'idCompanyType', companyTypes, null, {
width: 200,
editable: true
}),
]) ])
await updateTable() await updateTable()

View File

@ -1,19 +1,14 @@
import { memo, useCallback, useEffect, useMemo, useState } from 'react' import { memo, useCallback, useEffect, useMemo, useState } from 'react'
import { Input } from 'antd' import { Input } from 'antd'
import { EditableTable, makeColumn, makeStringSorter, defaultPagination } from '@components/Table' import { EditableTable, defaultPagination, makeTextColumn } from '@components/Table'
import { invokeWebApiWrapperAsync } from '@components/factory' import { invokeWebApiWrapperAsync } from '@components/factory'
import { arrayOrDefault, withPermissions } from '@utils' import { arrayOrDefault, withPermissions } from '@utils'
import { min1 } from '@utils/validationRules' import { min1 } from '@utils/validationRules'
import { AdminCompanyTypeService } from '@api' import { AdminCompanyTypeService } from '@api'
const columns = [ const columns = [
makeColumn('Название', 'caption', { makeTextColumn('Название', 'caption', undefined, undefined, undefined, { width: 200, formItemRules: min1 }),
width: 200,
editable: true,
sorter: makeStringSorter('caption'),
formItemRules: min1,
}),
] ]
const CompanyTypeController = memo(() => { const CompanyTypeController = memo(() => {

View File

@ -2,15 +2,15 @@ import { memo, useCallback, useEffect, useMemo, useState } from 'react'
import { Input } from 'antd' import { Input } from 'antd'
import { invokeWebApiWrapperAsync } from '@components/factory' import { invokeWebApiWrapperAsync } from '@components/factory'
import { EditableTable, makeColumn, defaultPagination, makeTimezoneColumn } from '@components/Table' import { EditableTable, defaultPagination, makeTimezoneColumn, makeTextColumn, makeNumericColumn } from '@components/Table'
import { arrayOrDefault, coordsFormat, withPermissions } from '@utils' import { arrayOrDefault, coordsFormat, withPermissions } from '@utils'
import { min1 } from '@utils/validationRules' import { min1 } from '@utils/validationRules'
import { AdminDepositService } from '@api' import { AdminDepositService } from '@api'
const depositColumns = [ const depositColumns = [
makeColumn('Название', 'caption', { width: 200, editable: true, formItemRules: min1 }), makeTextColumn('Название', 'caption', undefined, undefined, undefined, { width: 200, formItemRules: min1 }),
makeColumn('Широта', 'latitude', { width: 150, editable: true, render: coordsFormat }), makeNumericColumn('Широта', 'latitude', coordsFormat, undefined, 150),
makeColumn('Долгота', 'longitude', { width: 150, editable: true, render: coordsFormat }), makeNumericColumn('Долгота', 'longitude', coordsFormat, undefined, 150),
makeTimezoneColumn('Зона', 'timezone', null, true, { width: 150 }), makeTimezoneColumn('Зона', 'timezone', null, true, { width: 150 }),
] ]

View File

@ -1,23 +1,15 @@
import { memo, useCallback, useEffect, useMemo, useState } from 'react' import { memo, useCallback, useEffect, useMemo, useState } from 'react'
import { Input } from 'antd' import { Input } from 'antd'
import { EditableTable, makeColumn, makeStringSorter } from '@components/Table' import { EditableTable, makeTextColumn } from '@components/Table'
import { invokeWebApiWrapperAsync } from '@components/factory' import { invokeWebApiWrapperAsync } from '@components/factory'
import { arrayOrDefault, withPermissions } from '@utils' import { arrayOrDefault, withPermissions } from '@utils'
import { min1 } from '@utils/validationRules' import { min1 } from '@utils/validationRules'
import { AdminPermissionService } from '@api' import { AdminPermissionService } from '@api'
const columns = [ const columns = [
makeColumn('Название', 'name', { makeTextColumn('Название', 'name', undefined, undefined, undefined, { isRequired: true, formItemRules: min1 }),
editable: true, makeTextColumn('Описание', 'description'),
sorter: makeStringSorter('name'),
isRequired: true,
formItemRules: min1,
}),
makeColumn('Описание', 'description', {
editable: true,
sorter: makeStringSorter('description'),
}),
] ]
const PermissionController = memo(() => { const PermissionController = memo(() => {

View File

@ -19,15 +19,13 @@ const RoleController = memo(() => {
)), [roles, searchValue]) )), [roles, searchValue])
const columns = useMemo(() => [ const columns = useMemo(() => [
makeTextColumn('Название', 'caption', null, null, null, { width: 100, editable: true, formItemRules: min1 }), makeTextColumn('Название', 'caption', null, null, null, { width: 100, formItemRules: min1 }),
makeTagColumn('Включённые роли', 'roles', roles, 'id', 'caption', { makeTagColumn('Включённые роли', 'roles', roles, 'id', 'caption', {
width: 400, width: 400,
editable: true,
render: (role) => <RoleView role={role} /> render: (role) => <RoleView role={role} />
}, { allowClear: true }), }, { allowClear: true }),
makeTagColumn('Разрешения', 'permissions', permissions, 'id', 'name', { makeTagColumn('Разрешения', 'permissions', permissions, 'id', 'name', {
width: 600, width: 600,
editable: true,
render: (permission) => <PermissionView info={permission} />, render: (permission) => <PermissionView info={permission} />,
}), }),
], [roles, permissions]) ], [roles, permissions])

View File

@ -50,7 +50,7 @@ const TelemetryController = memo(() => {
const columns = useMemo(() => [ const columns = useMemo(() => [
makeColumn('', 'hasParent', { render: mergeRender }), makeColumn('', 'hasParent', { render: mergeRender }),
makeNumericColumn('ID', 'id', null, null, makeNumericRender(0)), makeNumericColumn('ID', 'id', makeNumericRender(0)),
makeTextColumn('UID', 'remoteUid'), makeTextColumn('UID', 'remoteUid'),
makeTextColumn('Назначена на скважину', 'realWell'), makeTextColumn('Назначена на скважину', 'realWell'),
makeDateColumn('Дата начала бурения', 'drillingStartDate'), makeDateColumn('Дата начала бурения', 'drillingStartDate'),

View File

@ -115,7 +115,6 @@ const UserController = memo(() => {
setColumns([ setColumns([
makeTextColumn('Логин', 'login', null, null, null, { makeTextColumn('Логин', 'login', null, null, null, {
editable: true,
formItemRules: [ formItemRules: [
{ required: true }, { required: true },
...createLoginRules, ...createLoginRules,
@ -130,41 +129,34 @@ const UserController = memo(() => {
], ],
}), }),
makeTextColumn('Фамилия', 'surname', filters.surname, null, null, { makeTextColumn('Фамилия', 'surname', filters.surname, null, null, {
editable: true,
formItemRules: [{ required: true }, ...nameRules], formItemRules: [{ required: true }, ...nameRules],
filterSearch: true, filterSearch: true,
onFilter: makeTextOnFilter('surname'), onFilter: makeTextOnFilter('surname'),
}), }),
makeTextColumn('Имя', 'name', filters.name, null, null, { makeTextColumn('Имя', 'name', filters.name, null, null, {
editable: true,
formItemRules: nameRules, formItemRules: nameRules,
filterSearch: true, filterSearch: true,
onFilter: makeTextOnFilter('name'), onFilter: makeTextOnFilter('name'),
}), }),
makeTextColumn('Отчество', 'patronymic', filters.partonymic, null, null, { makeTextColumn('Отчество', 'patronymic', filters.partonymic, null, null, {
editable: true,
formItemRules: nameRules, formItemRules: nameRules,
filterSearch: true, filterSearch: true,
onFilter: makeTextOnFilter('patronymic'), onFilter: makeTextOnFilter('patronymic'),
}), }),
makeTextColumn('E-mail', 'email', filters.email, null, null, { makeTextColumn('E-mail', 'email', filters.email, null, null, {
editable: true,
formItemRules: [{ required: true }, ...emailRules], formItemRules: [{ required: true }, ...emailRules],
filterSearch: true, filterSearch: true,
onFilter: makeTextOnFilter('email'), onFilter: makeTextOnFilter('email'),
}), }),
makeTextColumn('Номер телефона', 'phone', null, null, null, { makeTextColumn('Номер телефона', 'phone', null, null, null, {
editable: true,
formItemRules: phoneRules, formItemRules: phoneRules,
}), }),
makeTextColumn('Должность', 'position', null, null, null, { editable: true }), makeTextColumn('Должность', 'position', null, null, null),
makeTextColumn('Роли', 'roleNames', roleFilters, null, rolesRender, { makeTextColumn('Роли', 'roleNames', roleFilters, null, rolesRender, {
editable: true,
input: <RoleTag roles={roles} />, input: <RoleTag roles={roles} />,
onFilter: makeArrayOnFilter('roleNames'), onFilter: makeArrayOnFilter('roleNames'),
}), }),
makeSelectColumn('Компания', 'idCompany', companies, '--', { makeSelectColumn('Компания', 'idCompany', companies, '--', {
editable: true,
sorter: makeNumericSorter('idCompany'), sorter: makeNumericSorter('idCompany'),
}) })
]) ])

View File

@ -12,11 +12,12 @@ import {
EditableTable, EditableTable,
makeColumn, makeColumn,
makeSelectColumn, makeSelectColumn,
makeStringSorter,
makeNumericSorter, makeNumericSorter,
makeTagColumn, makeTagColumn,
defaultPagination, defaultPagination,
makeTimezoneColumn, makeTimezoneColumn,
makeTextColumn,
makeNumericColumn,
} from '@components/Table' } from '@components/Table'
import { invokeWebApiWrapperAsync } from '@components/factory' import { invokeWebApiWrapperAsync } from '@components/factory'
import { TelemetryView, CompanyView } from '@components/views' import { TelemetryView, CompanyView } from '@components/views'
@ -81,23 +82,11 @@ const WellController = memo(() => {
})) }))
setColumns([ setColumns([
makeSelectColumn('Куст', 'idCluster', clusters, '--', { makeSelectColumn('Куст', 'idCluster', clusters, '--', { width: '5rem', sorter: makeNumericSorter('idCluster') }),
width: '5rem', makeTextColumn('Название', 'caption', undefined, undefined, undefined, { width: '5rem' }),
editable: true, makeSelectColumn('Тип', 'idWellType', wellTypes, '--', { width: 150, sorter: makeNumericSorter('idWellType') }),
sorter: makeNumericSorter('idCluster'), makeNumericColumn('Широта', 'latitude', coordsFormat, undefined, 150),
}), makeNumericColumn('Долгота', 'longitude', coordsFormat, undefined, 150),
makeColumn('Название', 'caption', {
width: '5rem',
editable: true,
sorter: makeStringSorter('caption'),
}),
makeSelectColumn('Тип', 'idWellType', wellTypes, '--', {
width: 150,
editable: true,
sorter: makeNumericSorter('idWellType'),
}),
makeColumn('Широта', 'latitude', { width: 150, editable: true, render: coordsFormat }),
makeColumn('Долгота', 'longitude', { width: 150, editable: true, render: coordsFormat }),
makeColumn('Телеметрия', 'telemetry', { makeColumn('Телеметрия', 'telemetry', {
editable: true, editable: true,
render: (telemetry) => <TelemetryView telemetry={telemetry} />, render: (telemetry) => <TelemetryView telemetry={telemetry} />,
@ -105,7 +94,6 @@ const WellController = memo(() => {
}, ), }, ),
makeTimezoneColumn('Зона', 'timezone', null, true, { width: 170 }), makeTimezoneColumn('Зона', 'timezone', null, true, { width: 170 }),
makeTagColumn('Компании', 'companies', companies, 'id', 'caption', { makeTagColumn('Компании', 'companies', companies, 'id', 'caption', {
editable: true,
render: (company) => <CompanyView company={company} />, render: (company) => <CompanyView company={company} />,
}), }),
]) ])

View File

@ -7,7 +7,7 @@ import {
makeTextColumn, makeTextColumn,
makeGroupColumn, makeGroupColumn,
makeColumn, makeColumn,
makeNumericColumnPlanFact, makeNumericColumnPlanFactOld,
Table, Table,
makeNumericRender, makeNumericRender,
makeNumericColumn, makeNumericColumn,
@ -117,7 +117,10 @@ const ClusterWells = memo(({ statsWells }) => {
const columns = useMemo(() => [ const columns = useMemo(() => [
makeTextColumn('скв №', 'caption', null, null, makeTextColumn('скв №', 'caption', null, null,
(_, item) => ( (_, item) => (
<Link to={{ pathname: `/well/${item.id}`, state: { from: location.pathname }}} style={{display: 'flex', alignItems: 'center'}}> <Link
to={{ pathname: `/well/${item.id}`, state: { from: location.pathname }}}
style={{ display: 'flex', alignItems: 'center' }}
>
<PointerIcon <PointerIcon
state={item.idState === 1 ? 'active' : 'unknown'} state={item.idState === 1 ? 'active' : 'unknown'}
width={32} width={32}
@ -133,10 +136,10 @@ const ClusterWells = memo(({ statsWells }) => {
makeDateColumn('начало', 'factStart'), makeDateColumn('начало', 'factStart'),
makeDateColumn('окончание', 'factEnd'), makeDateColumn('окончание', 'factEnd'),
]), ]),
makeNumericColumnPlanFact('Продолжительность, сут', 'period', filtersMinMax, makeFilterMinMaxFunction, numericRender), makeNumericColumnPlanFactOld('Продолжительность, сут', 'period', numericRender, makeFilterMinMaxFunction, { filters: filtersMinMax }),
makeNumericColumnPlanFact('МСП, м/ч', 'rateOfPenetration', filtersMinMax, makeFilterMinMaxFunction, numericRender), makeNumericColumnPlanFactOld('МСП, м/ч', 'rateOfPenetration', numericRender, makeFilterMinMaxFunction, { filters: filtersMinMax }),
makeNumericColumnPlanFact('Рейсовая скорость, м/ч', 'routeSpeed', filtersMinMax, makeFilterMinMaxFunction, numericRender), makeNumericColumnPlanFactOld('Рейсовая скорость, м/ч', 'routeSpeed', numericRender, makeFilterMinMaxFunction, { filters: filtersMinMax }),
makeNumericColumn('НПВ, ч', 'notProductiveTimeFact', filtersMinMax, makeFilterMinMaxFunction, numericRender), makeNumericColumn('НПВ, ч', 'notProductiveTimeFact', numericRender, makeFilterMinMaxFunction, { filters: filtersMinMax }),
makeColumn('TVD', 'tvd', { align: 'center', render: (_, value) => ( makeColumn('TVD', 'tvd', { align: 'center', render: (_, value) => (
<Button onClick={() => { <Button onClick={() => {
setSelectedWell(value) setSelectedWell(value)

View File

@ -1,14 +1,14 @@
import { memo, useMemo } from 'react' import { memo, useMemo } from 'react'
import { Table, makeTextColumn, makeNumericColumnPlanFact } from '@components/Table' import { Table, makeTextColumn, makeNumericColumnPlanFactOld } from '@components/Table'
import { getPrecision } from '@utils/functions' import { getPrecision } from '@utils/functions'
const columns = [ const columns = [
makeTextColumn('Конструкция секции', 'sectionType'), makeTextColumn('Конструкция секции', 'sectionType'),
makeTextColumn('Операция', 'operationName'), makeTextColumn('Операция', 'operationName'),
makeNumericColumnPlanFact('Глубина забоя', 'depth', null, null, (number) => getPrecision(number)), makeNumericColumnPlanFactOld('Глубина забоя', 'depth', (number) => getPrecision(number)),
makeNumericColumnPlanFact('Часы', 'durationHours', null, null, (number) => getPrecision(number)), makeNumericColumnPlanFactOld('Часы', 'durationHours', (number) => getPrecision(number)),
makeNumericColumnPlanFact('Комментарий', 'comment', null, null, (text) => text ?? '-') makeNumericColumnPlanFactOld('Комментарий', 'comment', (text) => text ?? '-'),
] ]
export const WellOperationsTable = memo(({ wellOperations }) => { export const WellOperationsTable = memo(({ wellOperations }) => {

View File

@ -18,7 +18,7 @@ const columns = [
makeNumericColumn('Проходка, м', 'sumDepthInterval'), makeNumericColumn('Проходка, м', 'sumDepthInterval'),
makeNumericColumn('Время работы, ч', 'usedTimeHours'), makeNumericColumn('Время работы, ч', 'usedTimeHours'),
makeNumericColumn('Кол-во запусков', 'operationCount'), makeNumericColumn('Кол-во запусков', 'operationCount'),
makeNumericColumn('Коэф. использования, %', 'kUsage', undefined, undefined, (value) => numericRender(value * 100)), makeNumericColumn('Коэф. использования, %', 'kUsage', (value) => numericRender(value * 100)),
] ]
const getSubsystemState = (subsystem) => { const getSubsystemState = (subsystem) => {

View File

@ -21,13 +21,13 @@ const speedNumericRender = (section) => numericRender(section?.speed)
const makeSectionSorter = (key, name) => (a, b) => (a?.[key]?.[name] ?? 0) - (b?.[key]?.[name] ?? 0) const makeSectionSorter = (key, name) => (a, b) => (a?.[key]?.[name] ?? 0) - (b?.[key]?.[name] ?? 0)
export const makeSectionColumn = (title, key, { speedRender } = {}) => makeGroupColumn(title, [ export const makeSectionColumn = (title, key, { speedRender } = {}) => makeGroupColumn(title, [
makeNumericColumn('Проходка', key, null, null, (section => numericRender(section?.depth)), 100, { makeNumericColumn('Проходка', key, (section => numericRender(section?.depth)), undefined, 100, {
sorter: makeSectionSorter(key, 'depth'), sorter: makeSectionSorter(key, 'depth'),
}), }),
makeNumericColumn('Время', key, null, null, (section => numericRender(section?.time)), 100, { makeNumericColumn('Время', key, (section => numericRender(section?.time)), undefined, 100, {
sorter: makeSectionSorter(key, 'time'), sorter: makeSectionSorter(key, 'time'),
}), }),
makeNumericColumn((<>V<sub>рейсовая</sub></>), key, null, null, speedRender ?? speedNumericRender, 100, { makeNumericColumn((<>V<sub>рейсовая</sub></>), key, speedRender ?? speedNumericRender, undefined, 100, {
sorter: makeSectionSorter(key, 'speed'), sorter: makeSectionSorter(key, 'speed'),
}), }),
]) ])
@ -37,7 +37,7 @@ export const defaultColumns = [
makeTextColumn('Скважина', 'caption', null, null, null, { fixed: 'left', width: 100 }), makeTextColumn('Скважина', 'caption', null, null, null, { fixed: 'left', width: 100 }),
] ]
const scrollSettings = { scrollToFirstRowOnChange: true, x: 100, y: 200 } const scrollSettings = { scrollToFirstRowOnChange: true, x: 100, y: '25vh' }
const summaryColSpan = 1 /// TODO: Когда добавится куст изменить на 2 const summaryColSpan = 1 /// TODO: Когда добавится куст изменить на 2
const getWellData = async (wellsList) => { const getWellData = async (wellsList) => {

View File

@ -5,8 +5,9 @@ import { Button, Badge, Divider, Modal, Row, Col } from 'antd'
import { useWell } from '@asb/context' import { useWell } from '@asb/context'
import LoaderPortal from '@components/LoaderPortal' import LoaderPortal from '@components/LoaderPortal'
import SuspenseFallback from '@components/SuspenseFallback'
import { invokeWebApiWrapperAsync } from '@components/factory' import { invokeWebApiWrapperAsync } from '@components/factory'
import { Table, makeTextColumn, makeNumericColumnPlanFact, makeNumericColumn } from '@components/Table' import { Table, makeTextColumn, makeNumericColumnPlanFactOld, makeNumericColumn } from '@components/Table'
import { WellCompositeService } from '@api' import { WellCompositeService } from '@api'
import { import {
hasPermission, hasPermission,
@ -17,7 +18,6 @@ import {
} from '@utils' } from '@utils'
import NewParamsTable from './NewParamsTable' import NewParamsTable from './NewParamsTable'
import SuspenseFallback from '@asb/components/SuspenseFallback'
const Tvd = lazy(() => import('@pages/Well/WellOperations/Tvd')) const Tvd = lazy(() => import('@pages/Well/WellOperations/Tvd'))
const CompaniesTable = lazy(() => import('@pages/Cluster/CompaniesTable')) const CompaniesTable = lazy(() => import('@pages/Cluster/CompaniesTable'))
@ -146,15 +146,15 @@ const WellCompositeSections = memo(({ statsWells, selectedSections }) => {
makeTextColumn('скв №', 'caption', null, null, makeTextColumn('скв №', 'caption', null, null,
(text, item) => <Link to={{ pathname: `/well/${item?.id}`, state: { from: location.pathname }}}>{text ?? '-'}</Link> (text, item) => <Link to={{ pathname: `/well/${item?.id}`, state: { from: location.pathname }}}>{text ?? '-'}</Link>
), ),
makeTextColumn('Секция', 'sectionType', filtersSectionsType, sortBySectionId, (text) => text ?? '-'), makeTextColumn('Секция', 'sectionType', filtersSectionsType, sortBySectionId, (text) => text ?? '-', { width: 100 }),
makeNumericColumnPlanFact('Глубина, м', 'sectionWellDepth', filtersMinMax, makeFilterMinMaxFunction), makeNumericColumnPlanFactOld('Глубина, м', 'sectionWellDepth', undefined, makeFilterMinMaxFunction, undefined, { filters: filtersMinMax }),
makeNumericColumnPlanFact('Продолжительность, ч', 'sectionBuildDays', filtersMinMax, makeFilterMinMaxFunction), makeNumericColumnPlanFactOld('Продолжительность, ч', 'sectionBuildDays', undefined, makeFilterMinMaxFunction, undefined, { filters: filtersMinMax }),
makeNumericColumnPlanFact('МСП, м/ч', 'sectionRateOfPenetration', filtersMinMax, makeFilterMinMaxFunction), makeNumericColumnPlanFactOld('МСП, м/ч', 'sectionRateOfPenetration', undefined, makeFilterMinMaxFunction, undefined, { filters: filtersMinMax }),
makeNumericColumnPlanFact('Рейсовая скорость, м/ч', 'sectionRouteSpeed', filtersMinMax, makeFilterMinMaxFunction), makeNumericColumnPlanFactOld('Рейсовая скорость, м/ч', 'sectionRouteSpeed', undefined, makeFilterMinMaxFunction, undefined, { filters: filtersMinMax }),
makeNumericColumnPlanFact('Спуск КНБК, м/ч', 'sectionBhaDownSpeed', filtersMinMax, makeFilterMinMaxFunction), makeNumericColumnPlanFactOld('Спуск КНБК, м/ч', 'sectionBhaDownSpeed', undefined, makeFilterMinMaxFunction, undefined, { filters: filtersMinMax }),
makeNumericColumnPlanFact('Подъем КНБК, м/ч', 'sectionBhaUpSpeed', filtersMinMax, makeFilterMinMaxFunction), makeNumericColumnPlanFactOld('Подъем КНБК, м/ч', 'sectionBhaUpSpeed', undefined, makeFilterMinMaxFunction, undefined, { filters: filtersMinMax }),
makeNumericColumnPlanFact('Скорость спуска ОК, м/ч', 'sectionCasingDownSpeed', filtersMinMax, makeFilterMinMaxFunction), makeNumericColumnPlanFactOld('Скорость спуска ОК, м/ч', 'sectionCasingDownSpeed', undefined, makeFilterMinMaxFunction, undefined, { filters: filtersMinMax }),
makeNumericColumn('НПВ, ч', 'nonProductiveHours', filtersMinMax, makeFilterMinMaxFunction, null, '80px'), makeNumericColumn('НПВ, ч', 'nonProductiveHours', undefined, makeFilterMinMaxFunction, '80px', { filters: filtersMinMax }),
{ {
title: 'TVD', title: 'TVD',
render: (value) => ( render: (value) => (
@ -200,11 +200,11 @@ const WellCompositeSections = memo(({ statsWells, selectedSections }) => {
dataSource={rows} dataSource={rows}
size={'small'} size={'small'}
bordered bordered
scroll={{ x: true, y: 620 }} scroll={{ x: true, y: '30vh' }}
rowSelection={rowSelection} rowSelection={rowSelection}
pagination={false} pagination={false}
/> />
<Divider /> <Divider style={{ marginTop: 0 }} />
<Badge.Ribbon text={'комбинированная скважина'} color={'gray'}> <Badge.Ribbon text={'комбинированная скважина'} color={'gray'}>
<h3>Выбранные секции</h3> <h3>Выбранные секции</h3>
</Badge.Ribbon> </Badge.Ribbon>
@ -214,7 +214,7 @@ const WellCompositeSections = memo(({ statsWells, selectedSections }) => {
rowSelection={rowSelection} rowSelection={rowSelection}
size={'small'} size={'small'}
bordered bordered
scroll={{ x: true }} scroll={{ x: true, y: '30vh' }}
pagination={false} pagination={false}
/> />
<Row justify={'end'} style={{ margin: '1rem 0' }}> <Row justify={'end'} style={{ margin: '1rem 0' }}>

View File

@ -40,7 +40,7 @@ export const DocumentsTemplate = ({ idCategory, well: givenWell, mimeTypes, head
), ),
}, },
makeDateColumn('Дата загрузки', 'uploadDate'), makeDateColumn('Дата загрузки', 'uploadDate'),
makeNumericColumn('Размер', 'size', null, null, (value) => formatBytes(value)), makeNumericColumn('Размер', 'size', (value) => formatBytes(value)),
makeColumn('Автор', 'author', { render: item => <UserView user={item}/> }), makeColumn('Автор', 'author', { render: item => <UserView user={item}/> }),
makeColumn('Компания', 'company', { render: (_, record) => <CompanyView company={record?.author?.company}/> }), makeColumn('Компания', 'company', { render: (_, record) => <CompanyView company={record?.author?.company}/> }),
...(customColumns ?? []) ...(customColumns ?? [])

View File

@ -29,7 +29,7 @@ const categoryDictionary = {
// Конфигурация таблицы // Конфигурация таблицы
export const makeMessageColumns = (idWell) => [ export const makeMessageColumns = (idWell) => [
makeDateColumn('Дата', 'date', undefined, undefined, { width: '120px' }), makeDateColumn('Дата', 'date', undefined, undefined, { width: '120px' }),
makeNumericColumn('Глубина, м', 'wellDepth', null, null, (depth, item) => ( makeNumericColumn('Глубина, м', 'wellDepth', (depth, item) => (
<Tooltip title={'Нажмите для перехода в архив'}> <Tooltip title={'Нажмите для перехода в архив'}>
<Link <Link
style={{ color: 'inherit'}} style={{ color: 'inherit'}}
@ -40,7 +40,7 @@ export const makeMessageColumns = (idWell) => [
{depth.toFixed(2)} {depth.toFixed(2)}
</Link> </Link>
</Tooltip> </Tooltip>
), '7rem'), ), undefined, '7rem'),
makeColumn('Категория', 'categoryId', { makeColumn('Категория', 'categoryId', {
width: '8rem', width: '8rem',
render: (_, item) => categoryDictionary[item.categoryId].title, render: (_, item) => categoryDictionary[item.categoryId].title,

View File

@ -26,10 +26,10 @@ const tableColumns = [
<div className={'table_color'} style={{ backgroundColor }} /> <div className={'table_color'} style={{ backgroundColor }} />
)}), )}),
makeTextColumn('Подсистема', 'subsystemName'), makeTextColumn('Подсистема', 'subsystemName'),
makeNumericColumn('Использование, %', 'kUsage', undefined, undefined, val => (+val * 100).toFixed(2), 200), makeNumericColumn('Использование, %', 'kUsage', val => (+val * 100).toFixed(2), undefined, 200),
makeNumericColumn('Проходка, м', 'sumDepthInterval', undefined, undefined, undefined, 200), makeNumericColumn('Проходка, м', 'sumDepthInterval', undefined, undefined, 200),
makeNumericColumn('Время работы, ч', 'usedTimeHours', undefined, undefined, undefined, 200), makeNumericColumn('Время работы, ч', 'usedTimeHours', undefined, undefined, 200),
makeNumericColumn('Кол-во запусков', 'operationCount', undefined, undefined, makeNumericRender(0), 200), makeNumericColumn('Кол-во запусков', 'operationCount', makeNumericRender(0), undefined, 200),
] ]
// Выбор доступен только до текущей даты // Выбор доступен только до текущей даты

View File

@ -5,14 +5,13 @@ import { EditableTable, makeTextColumn } from '@components/Table'
import { DrillerService } from '@api' import { DrillerService } from '@api'
const columnOptions = { const columnOptions = {
editable: true,
formItemRules: [{ message: 'Обязательное поле!', required: true }] formItemRules: [{ message: 'Обязательное поле!', required: true }]
} }
const columns = [ const columns = [
makeTextColumn('Фамилия', 'surname', undefined, undefined, undefined, columnOptions), makeTextColumn('Фамилия', 'surname', undefined, undefined, undefined, columnOptions),
makeTextColumn('Имя', 'name', undefined, undefined, undefined, columnOptions), makeTextColumn('Имя', 'name', undefined, undefined, undefined, columnOptions),
makeTextColumn('Отчество', 'patronymic', undefined, undefined, undefined, { editable: true }), makeTextColumn('Отчество', 'patronymic'),
] ]
const rowClassName = (record) => record.has ? 'driller_list_active' : '' const rowClassName = (record) => record.has ? 'driller_list_active' : ''

View File

@ -14,7 +14,6 @@ import { arrayOrDefault } from '@utils'
import { ScheduleService } from '@api' import { ScheduleService } from '@api'
const columnOptions = { const columnOptions = {
editable: true,
formItemRules: [{ message: 'Обязательное поле!', required: true }] formItemRules: [{ message: 'Обязательное поле!', required: true }]
} }

View File

@ -24,11 +24,11 @@ const makeDrillerSorter = (key) => (a, b) => {
export const columns = [ export const columns = [
makeTextColumn('Бурильщик', 'driller', null, makeDrillerSorter('driller'), drillerRender, { width: 200 }), makeTextColumn('Бурильщик', 'driller', null, makeDrillerSorter('driller'), drillerRender, { width: 200 }),
makeNumericColumn('Кол-во операций', 'count', null, null, (value) => parseInt(value), 150), makeNumericColumn('Кол-во операций', 'count', (value) => parseInt(value), undefined, 150),
makeNumericColumn('Среднее по ключевому показателю', 'averageValue', null, null, numericRender, 150), makeNumericColumn('Среднее по ключевому показателю', 'averageValue', numericRender, undefined, 150),
makeNumericColumn('Среднее целевого показателя', 'averageTargetValue', null, null, numericRender, 150), makeNumericColumn('Среднее целевого показателя', 'averageTargetValue', numericRender, undefined, 150),
makeNumericColumn('Эффективность (%)', 'efficiency', null, null, numericRender, 150), makeNumericColumn('Эффективность (%)', 'efficiency', numericRender, undefined, 150),
makeNumericColumn('Коэффициент потерь', 'loss', null, null, numericRender, 100), makeNumericColumn('Коэффициент потерь', 'loss', numericRender, undefined, 100),
] ]
export const OperationsTable = memo(({ data, height, ...other }) => ( export const OperationsTable = memo(({ data, height, ...other }) => (

View File

@ -8,7 +8,6 @@ import { DetectedOperationService, OperationValueService } from '@api'
import { arrayOrDefault } from '@utils' import { arrayOrDefault } from '@utils'
const columnOptions = { const columnOptions = {
editable: true,
formItemRules: [{ message: 'Обязательное поле!', required: true }] formItemRules: [{ message: 'Обязательное поле!', required: true }]
} }
@ -72,11 +71,11 @@ export const TargetEditor = memo(({ loading, onChange }) => {
filterOption: (input, option) => filterOption: (input, option) =>
String(option?.label ?? '').toLowerCase().indexOf(input.toLowerCase()) >= 0 String(option?.label ?? '').toLowerCase().indexOf(input.toLowerCase()) >= 0
}), }),
makeNumericColumn('Цель', 'targetValue', undefined, undefined, numericRender, 150, columnOptions), makeNumericColumn('Цель', 'targetValue', numericRender, undefined, 150, columnOptions),
makeNumericColumn('Норм.', 'standardValue', undefined, undefined, numericRender, 150, columnOptions), makeNumericColumn('Норм.', 'standardValue', numericRender, undefined, 150, columnOptions),
makeGroupColumn('Глубина, м', [ makeGroupColumn('Глубина, м', [
makeNumericColumn('Начало', 'depthStart', undefined, undefined, numericRender, 150, columnOptions), makeNumericColumn('Начало', 'depthStart', numericRender, undefined, 150, columnOptions),
makeNumericColumn('Окончание', 'depthEnd', undefined, undefined, numericRender, 150, columnOptions), makeNumericColumn('Окончание', 'depthEnd', numericRender, undefined, 150, columnOptions),
]), ]),
]) ])
}, },

View File

@ -1,11 +1,11 @@
import { memo, useCallback, useMemo, useState } from 'react' import { memo, useCallback, useMemo, useState } from 'react'
import { Select, Modal, Input, InputNumber } from 'antd' import { Modal, Input } from 'antd'
import { useWell } from '@asb/context' import { useWell } from '@asb/context'
import { Grid, GridItem } from '@components/Grid' import { Grid, GridItem } from '@components/Grid'
import LoaderPortal from '@components/LoaderPortal' import LoaderPortal from '@components/LoaderPortal'
import { invokeWebApiWrapperAsync } from '@components/factory' import { invokeWebApiWrapperAsync } from '@components/factory'
import { makeNumericRender, EditableTable } from '@components/Table' import { makeNumericRender, EditableTable, makeSelectColumn, makeNumericColumn } from '@components/Table'
import { PeriodPicker, defaultPeriod } from '@components/selectors/PeriodPicker' import { PeriodPicker, defaultPeriod } from '@components/selectors/PeriodPicker'
import { SetpointsService } from '@api' import { SetpointsService } from '@api'
@ -19,24 +19,8 @@ export const SetpointSender = memo(({ onClose, visible, setpointNames }) => {
const [well] = useWell() const [well] = useWell()
const addingColumns = useMemo(() => [ const addingColumns = useMemo(() => [
{ makeSelectColumn('Наименование уставки', 'name', setpointNames, undefined, { width: 200, isRequired: true }),
title: 'Наименование уставки', makeNumericColumn('Значение', 'value', makeNumericRender(1), undefined, 125, { isRequired: true, align: 'right' }),
dataIndex: 'name',
editable: true,
isRequired: true,
width: 200,
input: <Select options={setpointNames} />,
render: (val) => setpointNames.find((name) => name.value === val)?.label
}, {
title: 'Значение',
dataIndex: 'value',
editable: true,
isRequired: true,
width: 125,
input: <InputNumber style={{ width: '100%' }} formatter={value => `${value}`.replace(',', '.')}/>,
render: makeNumericRender(1),
align: 'right'
}
], [setpointNames]) ], [setpointNames])
const onAdd = useCallback(async (sp) => setSetpoints((prevSp) => { const onAdd = useCallback(async (sp) => setSetpoints((prevSp) => {

View File

@ -5,9 +5,9 @@ import { Grid, GridItem } from '@components/Grid'
import { getChartIcon, makeDisplayValue } from '@utils' import { getChartIcon, makeDisplayValue } from '@utils'
import moment from 'moment' import moment from 'moment'
const defaultFormater = makeDisplayValue({ def: '---', fixed: 2 }) const defaultFormatter = makeDisplayValue({ def: '---', fixed: 2 })
const defaultValueRender = (v, unit) => ( const defaultValueRender = (v, unit) => (
<>{defaultFormater(v)} {unit ?? ''}</> <>{defaultFormatter(v)} {unit ?? ''}</>
) )
export const cursorRender = (group, data, flowData) => { export const cursorRender = (group, data, flowData) => {
@ -17,7 +17,7 @@ export const cursorRender = (group, data, flowData) => {
const firstChart = group.charts[0] const firstChart = group.charts[0]
const y = firstChart.y(d) const y = firstChart.y(d)
const yDate = moment(y) const yDate = moment(y)
const flow = flowData.filter((row) => yDate.isBetween(row.dateStart, row.dateEnd, 's', '[]')) const flow = flowData?.filter((row) => yDate.isBetween(row.dateStart, row.dateEnd, 's', '[]'))
const yValue = firstChart.yAxis.format?.(y) ?? defaultValueRender(y, firstChart.yAxis.unit) const yValue = firstChart.yAxis.format?.(y) ?? defaultValueRender(y, firstChart.yAxis.unit)
const xFormat = (chart) => { const xFormat = (chart) => {
const v = chart.x(d) const v = chart.x(d)
@ -42,13 +42,13 @@ export const cursorRender = (group, data, flowData) => {
{group.charts.filter((chart) => chart.type === 'rect_area').map((chart, i) => { {group.charts.filter((chart) => chart.type === 'rect_area').map((chart, i) => {
const minX = getByAccessor(chart.minXAccessor) const minX = getByAccessor(chart.minXAccessor)
const maxX = getByAccessor(chart.maxXAccessor) const maxX = getByAccessor(chart.maxXAccessor)
const value = (row) => <span>{defaultFormater(minX(row))} - {defaultFormater(maxX(row))}</span> const value = (row) => <span>{defaultFormatter(minX(row))} - {defaultFormatter(maxX(row))}</span>
return ( return (
<Fragment key={chart.key}> <Fragment key={chart.key}>
<GridItem row={i+2} col={1} style={{ padding: '2px 0' }}>{getChartIcon(chart)}</GridItem> <GridItem row={i+2} col={1} style={{ padding: '2px 0' }}>{getChartIcon(chart)}</GridItem>
<GridItem row={i+2} col={2}>{chart.shortLabel || chart.label}</GridItem> <GridItem row={i+2} col={2}>{chart.shortLabel || chart.label}</GridItem>
{flow.map((row, j) => ( {flow?.map((row, j) => (
<GridItem key={`${j}`} row={i+2+(j++)} col={3} style={{ paddingRight: 0, textAlign: 'end' }}> <GridItem key={`${j}`} row={i+2+(j++)} col={3} style={{ paddingRight: 0, textAlign: 'end' }}>
{chart.xAxis.format?.(row) ?? value(row)} {chart.xAxis.format?.(row) ?? value(row)}
</GridItem> </GridItem>

View File

@ -31,26 +31,20 @@ const dayWithoutNptRender = (_, row) => dayRender((row.day ?? 0) - (row.nptHours
const generateColumns = (showNpt = false, categories = [], sectionTypes = []) => [ const generateColumns = (showNpt = false, categories = [], sectionTypes = []) => [
makeSelectColumn('Конструкция секции', 'idWellSectionType', sectionTypes, undefined, { makeSelectColumn('Конструкция секции', 'idWellSectionType', sectionTypes, undefined, {
sorter: makeNumericSorter('idWellSectionType'), sorter: makeNumericSorter('idWellSectionType'),
editable: true,
width: 160, width: 160,
}), }),
makeSelectColumn('Операция', 'idCategory', categories, undefined, { makeSelectColumn('Операция', 'idCategory', categories, undefined, {
sorter: makeNumericSorter('idCategory'), sorter: makeNumericSorter('idCategory'),
editable: true,
width: 200, width: 200,
}), }),
makeTextColumn('Доп. инфо', 'categoryInfo', null, null, null, { editable: true, width: 300, input: <TextArea/> }), makeTextColumn('Доп. инфо', 'categoryInfo', null, null, null, { width: 300, input: <TextArea/> }),
makeColumn('Глубина забоя на начало, м', 'depthStart', makeNumericColumnOptions(2, 'depthStart')), makeNumericColumn('Глубина забоя на начало, м', 'depthStart'),
makeColumn('Глубина забоя при завершении, м', 'depthEnd', makeNumericColumnOptions(2, 'depthEnd')), makeNumericColumn('Глубина забоя при завершении, м', 'depthEnd'),
makeDateColumn('Время начала', 'dateStart', undefined, undefined, { makeDateColumn('Время начала', 'dateStart', undefined, undefined, { width: 170, initialValue: moment().format() }),
editable: true, makeNumericColumn('День', 'day', dayRender, undefined, 80),
width: 170, showNpt && makeNumericColumn('День без НПВ', 'dayWithoutNpt', dayWithoutNptRender, undefined, 80),
initialValue: moment().format(), makeNumericColumn('Часы', 'durationHours', undefined, undefined, 70),
}), makeTextColumn('Комментарий', 'comment', null, null, null, { input: <TextArea /> }),
makeNumericColumn('День', 'day', null, null, dayRender, 80),
showNpt && makeNumericColumn('День без НПВ', 'dayWithoutNpt', null, null, dayWithoutNptRender, 80),
makeColumn('Часы', 'durationHours', { ...makeNumericColumnOptions(2, 'durationHours'), width: 70 }),
makeTextColumn('Комментарий', 'comment', null, null, null, { editable: true, input: <TextArea/> }),
].filter(Boolean) ].filter(Boolean)
export const WellOperationsEditor = memo(({ idType, showNpt, ...other }) => { export const WellOperationsEditor = memo(({ idType, showNpt, ...other }) => {

View File

@ -4,15 +4,15 @@ import { FilterOutlined } from '@ant-design/icons'
import LoaderPortal from '@components/LoaderPortal' import LoaderPortal from '@components/LoaderPortal'
import { invokeWebApiWrapperAsync } from '@components/factory' import { invokeWebApiWrapperAsync } from '@components/factory'
import { makeDateColumn, makeNumericColumn, makeNumericRender, makeTextColumn, Table } from '@components/Table' import { makeDateColumn, makeNumericColumn, makeTextColumn, Table } from '@components/Table'
import '@styles/pages/tvd.less' import '@styles/pages/tvd.less'
export const columns = [ export const columns = [
makeTextColumn('Конструкция секции', 'wellSectionTypeName', null, null, null, { width: 140 }), makeTextColumn('Конструкция секции', 'wellSectionTypeName', null, null, null, { width: 140 }),
makeNumericColumn('Глубина', 'depth', null, null, null, 80), makeNumericColumn('Глубина', 'depth', undefined, undefined, 80),
makeDateColumn('Дата начала', 'date', false, undefined, { width: 90 }), makeDateColumn('Дата начала', 'date', false, undefined, { width: 90 }),
makeNumericColumn('Длительность (ч)', 'durationHours', null, null, makeNumericRender(2), 120), makeNumericColumn('Длительность (ч)', 'durationHours', undefined, undefined, 120),
makeTextColumn('Доп. инфо', 'categoryInfo', null, null, null), makeTextColumn('Доп. инфо', 'categoryInfo', null, null, null),
makeTextColumn('Комментарий', 'comment'), makeTextColumn('Комментарий', 'comment'),
] ]

View File

@ -18,9 +18,9 @@ const tableColumns = [
<div style={{ backgroundColor: d, padding: '5px 0' }} /> <div style={{ backgroundColor: d, padding: '5px 0' }} />
) }), ) }),
makeTextColumn('Название', 'category', undefined, undefined, undefined, { width: 300 }), makeTextColumn('Название', 'category', undefined, undefined, undefined, { width: 300 }),
makeNumericColumn('Время, мин', 'minutesTotal', undefined, undefined, undefined, 100), makeNumericColumn('Время, мин', 'minutesTotal', undefined, undefined, 100),
makeNumericColumn('Кол-во', 'count', undefined, undefined, (d) => d ? d.toString() : '---', 100), makeNumericColumn('Кол-во', 'count', (d) => d ? d.toString() : '---', undefined, 100),
makeNumericColumn('Процент, %', 'percent', undefined, undefined, (d) => d ? d.toFixed(2) : '---', 100) makeNumericColumn('Процент, %', 'percent', (d) => d ? d.toFixed(2) : '---', undefined, 100),
] ]
export const TLPie = memo(({ well }) => { export const TLPie = memo(({ well }) => {

View File

@ -3,22 +3,21 @@ import { useState, useEffect, memo } from 'react'
import { useWell } from '@asb/context' import { useWell } from '@asb/context'
import LoaderPortal from '@components/LoaderPortal' import LoaderPortal from '@components/LoaderPortal'
import { invokeWebApiWrapperAsync } from '@components/factory' import { invokeWebApiWrapperAsync } from '@components/factory'
import { Table, makeColumn, makeColumnsPlanFact, makeNumericRender } from '@components/Table' import { Table, makeColumn, makeNumericRender, makeNumericColumnPlanFactOld } from '@components/Table'
import { calcDuration } from '@utils' import { calcDuration } from '@utils'
import { OperationStatService } from '@api' import { OperationStatService } from '@api'
const numericRender = makeNumericRender(2) const numericRender = makeNumericRender(2)
const columns = [ const columns = [
makeColumn('Тип секции', 'sectionType'), makeColumn('Тип секции', 'sectionType'),
makeColumnsPlanFact('Глубина, м' ,'wellDepth', { render: numericRender }), makeNumericColumnPlanFactOld('Глубина, м', 'wellDepth', numericRender),
makeColumnsPlanFact('Часы' ,'duration', { render: numericRender }), makeNumericColumnPlanFactOld('Часы', 'duration', numericRender),
makeColumnsPlanFact('МСП, м/ч' ,'rop', { render: numericRender }), makeNumericColumnPlanFactOld('МСП, м/ч', 'rop', numericRender),
makeColumnsPlanFact('Рейсовая скорость, м/ч','routeSpeed', { render: numericRender }), makeNumericColumnPlanFactOld('Рейсовая скорость, м/ч', 'routeSpeed', numericRender),
makeColumnsPlanFact('Подъем КНБК, м/ч' ,'bhaUpSpeed', { render: numericRender }), makeNumericColumnPlanFactOld('Подъем КНБК, м/ч', 'bhaUpSpeed', numericRender),
makeColumnsPlanFact('Спуск КНБК, м/ч' ,'bhaDownSpeed', { render: numericRender }), makeNumericColumnPlanFactOld('Спуск КНБК, м/ч', 'bhaDownSpeed', numericRender),
makeColumnsPlanFact('Спуск ОК, м/ч' ,'casingDownSpeed', { render: numericRender }), makeNumericColumnPlanFactOld('Спуск ОК, м/ч', 'casingDownSpeed', numericRender),
] ]
export const WellSectionsStat = memo(() => { export const WellSectionsStat = memo(() => {

View File

@ -39,6 +39,8 @@
} }
.loader-content{ .loader-content{
width: 100%;
height: 100%;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
grid-column-start: 1; grid-column-start: 1;