diff --git a/src/components/Layout/LayoutPortal.tsx b/src/components/Layout/LayoutPortal.tsx
index 438acf9..15de833 100644
--- a/src/components/Layout/LayoutPortal.tsx
+++ b/src/components/Layout/LayoutPortal.tsx
@@ -2,7 +2,7 @@ import { memo, ReactNode } from 'react'
import { Layout, LayoutProps } from 'antd'
import PageHeader from '@components/PageHeader'
-import WellTreeSelector from '@components/WellTreeSelector'
+import WellTreeSelector from '@components/selectors/WellTreeSelector'
export type LayoutPortalProps = LayoutProps & {
title?: ReactNode
diff --git a/src/components/Table/Columns/date.tsx b/src/components/Table/Columns/date.tsx
new file mode 100644
index 0000000..c388cf6
--- /dev/null
+++ b/src/components/Table/Columns/date.tsx
@@ -0,0 +1,25 @@
+import { ReactNode } from 'react'
+
+import { formatDate } from '@utils'
+
+import makeColumn, { columnPropsOther } from '.'
+import { DatePickerWrapper, makeDateSorter } from '..'
+
+export const makeDateColumn = (
+ title: ReactNode,
+ key: string,
+ utc?: boolean,
+ format?: string,
+ other?: columnPropsOther
+) => makeColumn(title, key, {
+ ...other,
+ render: (date) => (
+
+ {formatDate(date, utc, format) ?? '-'}
+
+ ),
+ sorter: makeDateSorter(key),
+ input: ,
+})
+
+export default makeDateColumn
diff --git a/src/components/Table/Columns/index.ts b/src/components/Table/Columns/index.ts
index fd0b327..babb1fd 100644
--- a/src/components/Table/Columns/index.ts
+++ b/src/components/Table/Columns/index.ts
@@ -2,6 +2,7 @@ import { ReactNode } from 'react'
import { Rule } from 'antd/lib/form'
import { ColumnProps } from 'antd/lib/table'
+export { makeDateColumn } from './date'
export {
RegExpIsFloat,
makeNumericRender,
diff --git a/src/components/Table/Columns/select.tsx b/src/components/Table/Columns/select.tsx
index 85c8e5a..393d6a8 100644
--- a/src/components/Table/Columns/select.tsx
+++ b/src/components/Table/Columns/select.tsx
@@ -14,8 +14,8 @@ export const makeSelectColumn = (
...other,
input: ,
render: (value) => {
- const item = options?.find(option => option?.value === value)
- return other?.render?.(item?.value) ?? item?.label ?? defaultValue ?? value ?? '--'
+ const item = options?.find(option => option?.value === value)
+ return other?.render?.(item?.value) ?? item?.label ?? defaultValue ?? value ?? '--'
}
})
diff --git a/src/components/Table/DatePickerWrapper.tsx b/src/components/Table/DatePickerWrapper.tsx
index 76b195b..a453fbc 100644
--- a/src/components/Table/DatePickerWrapper.tsx
+++ b/src/components/Table/DatePickerWrapper.tsx
@@ -6,8 +6,8 @@ import moment, { Moment } from 'moment'
import { defaultFormat } from '@utils'
export type DatePickerWrapperProps = PickerDateProps & {
- value: Moment,
- onChange: (date: Moment | null) => any
+ value?: Moment,
+ onChange?: (date: Moment | null) => any
isUTC?: boolean
}
@@ -17,7 +17,7 @@ export const DatePickerWrapper = memo(({ value, onChange
allowClear={false}
format={defaultFormat}
defaultValue={moment()}
- onChange={(date) => onChange(date)}
+ onChange={(date) => onChange?.(date)}
value={isUTC ? moment.utc(value).local() : moment(value)}
{...other}
/>
diff --git a/src/components/Table/EditableTable.jsx b/src/components/Table/EditableTable.jsx
index ff2378d..e93a36d 100644
--- a/src/components/Table/EditableTable.jsx
+++ b/src/components/Table/EditableTable.jsx
@@ -188,6 +188,7 @@ export const EditableTable = memo(({
return {
...col,
onCell: (record) => ({
+ ...col.onCell?.(record),
editing: isEditing(record),
record,
dataIndex: col.dataIndex ?? col.key,
diff --git a/src/components/Table/index.tsx b/src/components/Table/index.tsx
index 095c825..2e1fc8e 100644
--- a/src/components/Table/index.tsx
+++ b/src/components/Table/index.tsx
@@ -6,6 +6,7 @@ export {
RegExpIsFloat,
timezoneOptions,
TimezoneSelect,
+ makeDateColumn,
makeGroupColumn,
makeColumn,
makeColumnsPlanFact,
diff --git a/src/components/PeriodPicker.tsx b/src/components/selectors/PeriodPicker.tsx
similarity index 100%
rename from src/components/PeriodPicker.tsx
rename to src/components/selectors/PeriodPicker.tsx
diff --git a/src/components/Poprompt.tsx b/src/components/selectors/Poprompt.tsx
similarity index 100%
rename from src/components/Poprompt.tsx
rename to src/components/selectors/Poprompt.tsx
diff --git a/src/components/selectors/TelemetrySelect.tsx b/src/components/selectors/TelemetrySelect.tsx
new file mode 100644
index 0000000..0e8dd4e
--- /dev/null
+++ b/src/components/selectors/TelemetrySelect.tsx
@@ -0,0 +1,34 @@
+import { Select, SelectProps } from 'antd'
+import { memo } from 'react'
+
+import { getTelemetryLabel } from '@components/views'
+import { TelemetryDto } from '@api'
+
+import '@styles/components/telemetry_select.less'
+
+export type TelemetrySelectProps = SelectProps & {
+ telemetry?: TelemetryDto[],
+ value?: TelemetryDto ,
+ onChange?: (value?: TelemetryDto) => void,
+}
+
+export const TelemetrySelect = memo(({ telemetry, value, onChange, ...other }) => (
+
+))
+
+export default TelemetrySelect
diff --git a/src/components/WellSelector.jsx b/src/components/selectors/WellSelector.jsx
similarity index 100%
rename from src/components/WellSelector.jsx
rename to src/components/selectors/WellSelector.jsx
diff --git a/src/components/WellTreeSelector.tsx b/src/components/selectors/WellTreeSelector.tsx
similarity index 96%
rename from src/components/WellTreeSelector.tsx
rename to src/components/selectors/WellTreeSelector.tsx
index 15f96f2..f354d07 100644
--- a/src/components/WellTreeSelector.tsx
+++ b/src/components/selectors/WellTreeSelector.tsx
@@ -7,9 +7,9 @@ import { RawValueType } from 'rc-tree-select/lib/TreeSelect'
import { LabelInValueType } from 'rc-select/lib/Select'
import { isRawDate } from '@utils'
-import LoaderPortal from './LoaderPortal'
-import { WellIcon, WellIconState } from './icons'
-import { invokeWebApiWrapperAsync } from './factory'
+import LoaderPortal from '@components/LoaderPortal'
+import { WellIcon, WellIconState } from '@components/icons'
+import { invokeWebApiWrapperAsync } from '@components/factory'
import { DepositService, DepositDto } from '@api'
import { ReactComponent as DepositIcon } from '@images/DepositIcon.svg'
diff --git a/src/components/views/TelemetryView.tsx b/src/components/views/TelemetryView.tsx
index 30401ff..702ebd2 100644
--- a/src/components/views/TelemetryView.tsx
+++ b/src/components/views/TelemetryView.tsx
@@ -4,7 +4,7 @@ import { Tooltip } from 'antd'
import { TelemetryDto, TelemetryInfoDto } from '@api'
import { Grid, GridItem } from '@components/Grid'
-const lables: Record = {
+export const lables: Record = {
timeZoneId: 'Временная зона',
timeZoneOffsetTotalHours: 'Сдвиг временной зоны',
drillingStartDate: 'Начало бурения',
diff --git a/src/pages/AdminPanel/ClusterController.jsx b/src/pages/AdminPanel/ClusterController.jsx
index d513d9d..0da72f5 100644
--- a/src/pages/AdminPanel/ClusterController.jsx
+++ b/src/pages/AdminPanel/ClusterController.jsx
@@ -1,4 +1,5 @@
-import { memo, useCallback, useEffect, useState } from 'react'
+import { memo, useCallback, useEffect, useMemo, useState } from 'react'
+import { Input } from 'antd'
import {
EditableTable,
@@ -9,7 +10,6 @@ import {
defaultPagination,
makeTimezoneColumn
} from '@components/Table'
-import LoaderPortal from '@components/LoaderPortal'
import { invokeWebApiWrapperAsync } from '@components/factory'
import { AdminClusterService, AdminDepositService } from '@api'
import { arrayOrDefault } from '@utils'
@@ -22,8 +22,16 @@ export const ClusterController = memo(() => {
const [deposits, setDeposits] = useState([])
const [clusters, setClusters] = useState([])
const [showLoader, setShowLoader] = useState(false)
+ const [searchValue, setSearchValue] = useState('')
- const clusterColumns = [
+ const filteredClusters = useMemo(() => clusters.filter((cluster) => cluster && (!searchValue || [
+ cluster.caption ?? '',
+ cluster.latitude?.toString ?? '',
+ cluster.longitude?.toString() ?? '',
+ ].join(' ').toLowerCase().includes(searchValue.toLowerCase()))
+ ), [clusters, searchValue])
+
+ const clusterColumns = useMemo(() => [
makeSelectColumn('Месторождение', 'idDeposit', deposits, '--', {
width: 200,
editable: true,
@@ -38,7 +46,7 @@ export const ClusterController = memo(() => {
makeColumn('Широта', 'latitude', { width: 150, editable: true, render: coordsFixed }),
makeColumn('Долгота', 'longitude', { width: 150, editable: true, render: coordsFixed }),
makeTimezoneColumn('Зона', 'timezone', null, true, { width: 150 }),
- ]
+ ], [deposits])
const updateTable = useCallback(() => invokeWebApiWrapperAsync(
async () => {
@@ -63,27 +71,35 @@ export const ClusterController = memo(() => {
useEffect(updateTable, [updateTable])
- const handlerProps = {
+ const handlerProps = useMemo(() => ({
service: AdminClusterService,
setLoader: setShowLoader,
errorMsg: `Не удалось выполнить операцию`,
onComplete: updateTable,
- }
+ }), [updateTable])
return (
-
+ <>
+ setSearchValue(e.target.value)}
+ value={searchValue}
+ loading={showLoader}
+ />
-
+ >
)
})
diff --git a/src/pages/AdminPanel/CompanyController.jsx b/src/pages/AdminPanel/CompanyController.jsx
index 9973496..836ab11 100644
--- a/src/pages/AdminPanel/CompanyController.jsx
+++ b/src/pages/AdminPanel/CompanyController.jsx
@@ -1,4 +1,5 @@
-import { memo, useCallback, useEffect, useState } from 'react'
+import { memo, useCallback, useEffect, useMemo, useState } from 'react'
+import { Input } from 'antd'
import {
EditableTable,
@@ -8,7 +9,6 @@ import {
makeSelectColumn,
defaultPagination
} from '@components/Table'
-import LoaderPortal from '@components/LoaderPortal'
import { invokeWebApiWrapperAsync } from '@components/factory'
import { AdminCompanyService, AdminCompanyTypeService } from '@api'
import { arrayOrDefault } from '@utils'
@@ -20,6 +20,11 @@ export const CompanyController = memo(() => {
const [columns, setColumns] = useState([])
const [companies, setCompanies] = useState([])
const [showLoader, setShowLoader] = useState(false)
+ const [searchValue, setSearchValue] = useState('')
+
+ const filteredCompanies = useMemo(() => companies.filter((company) => company && (!searchValue ||
+ company.caption?.toLowerCase()?.includes(searchValue.toLowerCase())
+ )), [companies, searchValue])
const updateTable = useCallback(async () => {
const companies = await AdminCompanyService.getAll()
@@ -53,7 +58,7 @@ export const CompanyController = memo(() => {
'Получение списка типов команд'
), [updateTable])
- const handlerProps = {
+ const handlerProps = useMemo(() => ({
service: AdminCompanyService,
setLoader: setShowLoader,
errorMsg: `Не удалось выполнить операцию`,
@@ -63,22 +68,30 @@ export const CompanyController = memo(() => {
`Не удалось обновить список компаний`,
'Получение списка компаний'
),
- }
+ }), [updateTable])
return (
-
+ <>
+ setSearchValue(e.target.value)}
+ value={searchValue}
+ loading={showLoader}
+ />
-
+ >
)
})
diff --git a/src/pages/AdminPanel/CompanyTypeController.jsx b/src/pages/AdminPanel/CompanyTypeController.jsx
index af55a6a..0fa804d 100644
--- a/src/pages/AdminPanel/CompanyTypeController.jsx
+++ b/src/pages/AdminPanel/CompanyTypeController.jsx
@@ -1,4 +1,5 @@
-import { memo, useCallback, useEffect, useState } from 'react'
+import { memo, useCallback, useEffect, useMemo, useState } from 'react'
+import { Input } from 'antd'
import {
EditableTable,
@@ -7,7 +8,6 @@ import {
makeStringSorter,
defaultPagination
} from '@components/Table'
-import LoaderPortal from '@components/LoaderPortal'
import { invokeWebApiWrapperAsync } from '@components/factory'
import { AdminCompanyTypeService } from '@api'
import { arrayOrDefault } from '@utils'
@@ -26,6 +26,11 @@ const columns = [
export const CompanyTypeController = memo(() => {
const [companyTypes, setCompanyTypes] = useState([])
const [showLoader, setShowLoader] = useState(false)
+ const [searchValue, setSearchValue] = useState('')
+
+ const filteredCompanyTypes = useMemo(() => companyTypes.filter((companyType) => companyType && (!searchValue ||
+ companyType.caption?.toLowerCase()?.includes(searchValue.toLowerCase())
+ )), [companyTypes, searchValue])
const updateTable = useCallback(() => invokeWebApiWrapperAsync(
async() => {
@@ -39,27 +44,35 @@ export const CompanyTypeController = memo(() => {
useEffect(updateTable, [updateTable])
- const handlerProps = {
+ const handlerProps = useMemo(() => ({
service: AdminCompanyTypeService,
setLoader: setShowLoader,
errorMsg: `Не удалось выполнить операцию`,
onComplete: updateTable,
- }
+ }), [updateTable])
return (
-
+ <>
+ setSearchValue(e.target.value)}
+ value={searchValue}
+ loading={showLoader}
+ />
-
+ >
)
})
diff --git a/src/pages/AdminPanel/DepositController.jsx b/src/pages/AdminPanel/DepositController.jsx
index d033753..9a1b5e1 100644
--- a/src/pages/AdminPanel/DepositController.jsx
+++ b/src/pages/AdminPanel/DepositController.jsx
@@ -1,12 +1,12 @@
-import { memo, useCallback, useEffect, useState } from 'react'
+import { memo, useCallback, useEffect, useMemo, useState } from 'react'
+import { Input } from 'antd'
-import LoaderPortal from '@components/LoaderPortal'
import { invokeWebApiWrapperAsync } from '@components/factory'
import { EditableTable, makeColumn, makeActionHandler, defaultPagination, makeTimezoneColumn } from '@components/Table'
-import { AdminDepositService } from '@api'
-import { arrayOrDefault } from '@utils'
-import { min1 } from '@utils/validationRules'
import { hasPermission } from '@utils/permissions'
+import { min1 } from '@utils/validationRules'
+import { arrayOrDefault } from '@utils'
+import { AdminDepositService } from '@api'
export const coordsFixed = (coords) => coords && isFinite(coords) ? (+coords).toPrecision(10) : '-'
@@ -20,6 +20,14 @@ const depositColumns = [
export const DepositController = memo(() => {
const [deposits, setDeposits] = useState([])
const [showLoader, setShowLoader] = useState(false)
+ const [searchValue, setSearchValue] = useState('')
+
+ const filteredDeposits = useMemo(() => deposits.filter((deposit) => deposit && (!searchValue || [
+ deposit.caption ?? '',
+ deposit.latitude?.toString() ?? '',
+ deposit.longitude?.toString() ?? '',
+ ].join(' ').toLowerCase().includes(searchValue.toLowerCase()))
+ ), [deposits, searchValue])
const updateTable = useCallback(() => invokeWebApiWrapperAsync(
async() => {
@@ -33,27 +41,35 @@ export const DepositController = memo(() => {
useEffect(updateTable, [updateTable])
- const handlerProps = {
+ const handlerProps = useMemo(() => ({
service: AdminDepositService,
setLoader: setShowLoader,
errorMsg: `Не удалось выполнить операцию`,
onComplete: updateTable,
- }
+ }), [updateTable])
return (
-
+ <>
+ setSearchValue(e.target.value)}
+ value={searchValue}
+ loading={showLoader}
+ />
-
+ >
)
})
diff --git a/src/pages/AdminPanel/PermissionController.jsx b/src/pages/AdminPanel/PermissionController.jsx
index a094e60..8f1ecba 100644
--- a/src/pages/AdminPanel/PermissionController.jsx
+++ b/src/pages/AdminPanel/PermissionController.jsx
@@ -1,4 +1,5 @@
-import { memo, useCallback, useEffect, useState } from 'react'
+import { memo, useCallback, useEffect, useMemo, useState } from 'react'
+import { Input } from 'antd'
import {
EditableTable,
@@ -6,7 +7,6 @@ import {
makeColumn,
makeStringSorter
} from '@components/Table'
-import LoaderPortal from '@components/LoaderPortal'
import { invokeWebApiWrapperAsync } from '@components/factory'
import { AdminPermissionService } from '@api'
import { arrayOrDefault } from '@utils'
@@ -27,8 +27,15 @@ const columns = [
]
export const PermissionController = memo(() => {
- const [showLoader, setShowLoader] = useState(false)
const [permissions, setPermissions] = useState([])
+ const [showLoader, setShowLoader] = useState(false)
+ const [searchValue, setSearchValue] = useState('')
+
+ const filteredPermissions = useMemo(() => permissions.filter((permission) => permission && (!searchValue || [
+ permission.name ?? '',
+ permission.description ?? '',
+ ].join(' ').includes(searchValue.toLowerCase()))
+ ), [permissions, searchValue])
const updateTable = useCallback(async () => invokeWebApiWrapperAsync(
async () => {
@@ -42,27 +49,35 @@ export const PermissionController = memo(() => {
useEffect(() => updateTable(), [updateTable])
- const handlerProps = {
+ const handlerProps = useMemo(() => ({
service: AdminPermissionService,
setLoader: setShowLoader,
errorMsg: `Не удалось выполнить операцию`,
onComplete: updateTable
- }
+ }), [updateTable])
return (
-
+ <>
+ setSearchValue(e.target.value)}
+ value={searchValue}
+ loading={showLoader}
+ />
-
+ >
)
})
diff --git a/src/pages/AdminPanel/RoleController.jsx b/src/pages/AdminPanel/RoleController.jsx
index 63e2d5b..102cf65 100644
--- a/src/pages/AdminPanel/RoleController.jsx
+++ b/src/pages/AdminPanel/RoleController.jsx
@@ -1,9 +1,9 @@
-import { memo, useCallback, useEffect, useState } from 'react'
+import { memo, useCallback, useEffect, useMemo, useState } from 'react'
+import { Input } from 'antd'
-import LoaderPortal from '@components/LoaderPortal'
import { PermissionView, RoleView } from '@components/views'
import { invokeWebApiWrapperAsync } from '@components/factory'
-import { EditableTable, makeActionHandler, makeColumn, makeTagColumn } from '@components/Table'
+import { EditableTable, makeActionHandler, makeTagColumn, makeTextColumn } from '@components/Table'
import { AdminPermissionService, AdminUserRoleService } from '@api'
import { arrayOrDefault } from '@utils'
import { min1 } from '@utils/validationRules'
@@ -13,29 +13,31 @@ export const RoleController = memo(() => {
const [permissions, setPermissions] = useState([])
const [roles, setRoles] = useState([])
const [showLoader, setShowLoader] = useState(false)
- const [columns, setColumns] = useState([])
+ const [searchValue, setSearchValue] = useState('')
+
+ const filteredRoles = useMemo(() => roles.filter((role) => role && (!searchValue ||
+ role.caption?.toLowerCase()?.includes(searchValue.toLowerCase())
+ )), [roles, searchValue])
+
+ const columns = useMemo(() => [
+ makeTextColumn('Название', 'caption', null, null, null, { width: 100, editable: true, formItemRules: min1 }),
+ makeTagColumn('Включённые роли', 'roles', roles, 'id', 'caption', {
+ width: 400,
+ editable: true,
+ render: (role) =>
+ }, { allowClear: true }),
+ makeTagColumn('Разрешения', 'permissions', permissions, 'id', 'name', {
+ width: 600,
+ editable: true,
+ render: (permission) => ,
+ }),
+ ], [roles, permissions])
const loadRoles = useCallback(async () => {
const roles = await AdminUserRoleService.getAll()
setRoles(arrayOrDefault(roles))
}, [])
- useEffect(() => {
- setColumns([
- makeColumn('Название', 'caption', { width: 100, editable: true, formItemRules: min1 }),
- makeTagColumn('Включённые роли', 'roles', roles, 'id', 'caption', {
- width: 400,
- editable: true,
- render: (role) =>
- }, { allowClear: true }),
- makeTagColumn('Разрешения', 'permissions', permissions, 'id', 'name', {
- width: 600,
- editable: true,
- render: (permission) => ,
- }),
- ])
- }, [roles, permissions])
-
useEffect(() => invokeWebApiWrapperAsync(
async () => {
const permissions = await AdminPermissionService.getAll()
@@ -47,7 +49,7 @@ export const RoleController = memo(() => {
'Получение списка ролей'
), [loadRoles])
- const handlerProps = {
+ const handlerProps = useMemo(() => ({
service: AdminUserRoleService,
setLoader: setShowLoader,
errorMsg: `Не удалось выполнить операцию`,
@@ -55,23 +57,31 @@ export const RoleController = memo(() => {
loadRoles,
setShowLoader,
`Не удалось загрузить список ролей`,
- 'Получение списка ролей'
+ 'Получение списка ролей',
)
- }
+ }), [loadRoles])
return (
-
+ <>
+ setSearchValue(e.target.value)}
+ value={searchValue}
+ loading={showLoader}
+ />
-
+ >
)
})
diff --git a/src/pages/AdminPanel/Telemetry/TelemetryMerger.jsx b/src/pages/AdminPanel/Telemetry/TelemetryMerger.jsx
new file mode 100644
index 0000000..31991d9
--- /dev/null
+++ b/src/pages/AdminPanel/Telemetry/TelemetryMerger.jsx
@@ -0,0 +1,136 @@
+import { memo, useCallback, useEffect, useMemo, useState } from 'react'
+import { useLocation } from 'react-router-dom'
+import { PullRequestOutlined } from '@ant-design/icons'
+import { Button, Descriptions, Popconfirm } from 'antd'
+
+import { Grid, GridItem } from '@components/Grid'
+import LoaderPortal from '@components/LoaderPortal'
+import { lables } from '@components/views/TelemetryView'
+import { invokeWebApiWrapperAsync } from '@components/factory'
+import TelemetrySelect from '@components/selectors/TelemetrySelect'
+import { AdminTelemetryService } from '@api'
+import { arrayOrDefault } from '@utils'
+
+const { Item } = Descriptions
+
+export const TelemetryInfo = memo(({ info, danger, ...other }) => (
+
+ {Object.keys({ ...lables, ...info }).map(key => (
+ - {info?.[key] ?? '-'}
+ ))}
+
+))
+
+export const TelemetryMerger = memo(() => {
+ const [primary, setPrimary] = useState(null)
+ const [secondary, setSecondary] = useState(null)
+ const [telemetry, setTelemetry] = useState([])
+ const [isLoading, setIsLoading] = useState(false)
+ const [isMerging, setIsMerging] = useState(false)
+
+ const location = useLocation()
+
+ const danger = useMemo(() => [
+ primary?.info?.well !== secondary?.info?.well && 'well',
+ primary?.info?.cluster !== secondary?.info?.cluster && 'cluster',
+ primary?.info?.deposit !== secondary?.info?.deposit && 'deposit',
+ ], [primary, secondary])
+
+ const updateTelemetry = useCallback(async () => await invokeWebApiWrapperAsync(
+ async () => {
+ const telemetry = arrayOrDefault(await AdminTelemetryService.getAll())
+ setTelemetry(telemetry)
+ },
+ setIsLoading,
+ 'Не удалось загрузить список телеметрий',
+ 'Получение списка телеметрий',
+ ), [])
+
+ const mergeTelemetry = useCallback(() => invokeWebApiWrapperAsync(
+ async () => {
+ await new Promise(res => setTimeout(res, 1000))
+ /// await AdminTelemetryService.mergeTelemetries(secondary.id, primary.id)
+ await updateTelemetry()
+ },
+ setIsMerging,
+ 'Не удалось объединить телеметрии',
+ 'Объединение телеметрий',
+ ), [updateTelemetry])
+
+ useEffect(() => updateTelemetry(), [updateTelemetry])
+
+ useEffect(() => {
+ const query = new URLSearchParams(location.search)
+ const primaryId = parseInt(query.get('primary') ?? null)
+ const secondaryId = parseInt(query.get('secondary') ?? null)
+ const primary = isNaN(primaryId) ? null : telemetry.find((t) => t.id === primaryId)
+ const secondary = isNaN(secondaryId) ? null : telemetry.find((t) => t.id === secondaryId)
+ console.log([primary, secondary])
+ setPrimary(primary)
+ setSecondary(secondary)
+ }, [location, telemetry])
+
+ return (
+
+ {
+ ///TODO: Добавить описание
+ }
+
+ Результирующая телеметрия
+ Исходная телеметрия
+
+
+
+
+
+
+
+
+ }
+ disabled={!primary || !secondary}
+ loading={isMerging}
+ >Объединить
+
+
+
+
+
+
+
+
+
+
+ )
+})
+
+export default TelemetryMerger
diff --git a/src/pages/AdminPanel/Telemetry/TelemetryViewer.jsx b/src/pages/AdminPanel/Telemetry/TelemetryViewer.jsx
new file mode 100644
index 0000000..b02c122
--- /dev/null
+++ b/src/pages/AdminPanel/Telemetry/TelemetryViewer.jsx
@@ -0,0 +1,121 @@
+import { memo, useCallback, useEffect, useMemo, useState } from 'react'
+import { PullRequestOutlined } from '@ant-design/icons'
+import { Button, Input } from 'antd'
+
+import {
+ defaultPagination,
+ makeColumn,
+ makeDateSorter,
+ makeNumericColumn,
+ makeNumericRender,
+ makeTextColumn,
+ Table
+} from '@components/Table'
+import Poprompt from '@components/selectors/Poprompt'
+import { invokeWebApiWrapperAsync } from '@components/factory'
+import { AdminTelemetryService } from '@api'
+import { arrayOrDefault } from '@utils'
+import { useHistory } from 'react-router-dom'
+
+export const TelemetryController = memo(() => {
+ const [telemetryData, setTelemetryData] = useState([])
+ const [showLoader, setShowLoader] = useState(false)
+ const [searchValue, setSearchValue] = useState('')
+
+ const history = useHistory()
+
+ const toMerger = useCallback((type, id) => () => history.push(`/admin/telemetry/merger/?${type}=${id}`), [history])
+
+ const mergeRender = useCallback((value, record) => (
+ ,
+ size: 'small',
+ danger: !!value,
+ }}
+ footer={(
+
+
+
+
+ )}
+ >
+ Вы собираетесь использовать данную телеметрию для слияния
+ {record.realWell && (
+ Внимание! Телеметрии назначена скважина!
+ )}
+
+ ), [toMerger])
+
+ const columns = useMemo(() => [
+ makeColumn('', 'hasParent', { render: mergeRender }),
+ makeNumericColumn('ID', 'id', null, null, makeNumericRender(0)),
+ makeTextColumn('UID', 'remoteUid'),
+ makeTextColumn('Назначена на скважину', 'realWell'),
+ makeTextColumn('Дата начала бурения', 'drillingStartDate', null, makeDateSorter('drillingStartDate')),
+ makeTextColumn('Часовой пояс', 'timeZoneId'),
+ makeTextColumn('Скважина', 'well'),
+ makeTextColumn('Куст', 'cluster'),
+ makeTextColumn('Месторождение', 'deposit'),
+ makeTextColumn('Заказчик', 'customer'),
+ makeTextColumn('Комментарий', 'comment'),
+ makeTextColumn('Версия HMI', 'hmiVersion'),
+ makeTextColumn('Версия САУБ', 'saubPlcVersion'),
+ makeTextColumn('Версия Спин Мастер', 'spinPlcVersion'),
+ ], [mergeRender])
+
+ const filteredTelemetryData = useMemo(() => telemetryData.filter((telemetry) => telemetry && (!searchValue || [
+ telemetry.id?.toString() ?? '',
+ telemetry.remoteUid ?? '',
+ telemetry.realWell ?? '',
+ telemetry.drillingStartDate ?? '',
+ telemetry.well ?? '',
+ telemetry.cluster ?? '',
+ telemetry.deposit ?? '',
+ telemetry.customer ?? '',
+ telemetry.comment ?? '',
+ telemetry.hmiVersion ?? '',
+ telemetry.saubPlcVersion ?? '',
+ telemetry.spinPlcVersion ?? '',
+ ].join(' ').toLowerCase().includes(searchValue.toLowerCase()))
+ ), [telemetryData, searchValue])
+
+ useEffect(() => invokeWebApiWrapperAsync(
+ async () => {
+ const telemetryData = arrayOrDefault(await AdminTelemetryService.getAll())
+ setTelemetryData(telemetryData.map((telemetry) => ({
+ ...(telemetry?.info ?? []),
+ id: telemetry?.id,
+ remoteUid: telemetry?.remoteUid,
+ realWell: telemetry?.well?.caption,
+ })))
+ },
+ setShowLoader,
+ `Не удалось загрузить список телеметрии скважин`,
+ 'Полученик списка телеметрии скважин'
+ ), [])
+
+ return (
+ <>
+ setSearchValue(e.target.value)}
+ value={searchValue}
+ loading={showLoader}
+ />
+
+ >
+ )
+})
+
+export default TelemetryController
diff --git a/src/pages/AdminPanel/Telemetry/index.jsx b/src/pages/AdminPanel/Telemetry/index.jsx
new file mode 100644
index 0000000..0db46d6
--- /dev/null
+++ b/src/pages/AdminPanel/Telemetry/index.jsx
@@ -0,0 +1,42 @@
+import { Layout, Menu } from 'antd'
+import { lazy, memo, Suspense } from 'react'
+import { Switch, useParams } from 'react-router-dom'
+
+import { PrivateMenuItem, PrivateRoute, PrivateDefaultRoute } from '@components/Private'
+
+import { SuspenseFallback } from '@pages/SuspenseFallback'
+
+const TelemetryViewer = lazy(() => import('./TelemetryViewer'))
+const TelemetryMerger = lazy(() => import('./TelemetryMerger'))
+
+const rootPath = '/admin/telemetry'
+
+export const Telemetry = memo(() => {
+ const { tab } = useParams()
+
+ return (
+
+
+
+
+
+ }>
+
+
+
+
+
+
+
+
+
+ )
+})
+
+export default Telemetry
diff --git a/src/pages/AdminPanel/TelemetryController.jsx b/src/pages/AdminPanel/TelemetryController.jsx
deleted file mode 100644
index 7621ce9..0000000
--- a/src/pages/AdminPanel/TelemetryController.jsx
+++ /dev/null
@@ -1,65 +0,0 @@
-import { memo, useEffect, useState } from 'react'
-
-import {
- defaultPagination,
- makeDateSorter,
- makeNumericColumn,
- makeNumericRender,
- makeTextColumn,
- Table
-} from '@components/Table'
-import LoaderPortal from '@components/LoaderPortal'
-import { invokeWebApiWrapperAsync } from '@components/factory'
-import { AdminTelemetryService } from '@api'
-import { arrayOrDefault } from '@utils'
-
-const columns = [
- makeNumericColumn('ID', 'id', null, null, makeNumericRender(0)),
- makeTextColumn('UID', 'remoteUid'),
- makeTextColumn('Назначена на скважину', 'realWell'),
- makeTextColumn('Дата начала бурения', 'drillingStartDate', null, makeDateSorter('drillingStartDate')),
- makeTextColumn('Часовой пояс', 'timeZoneId'),
- makeTextColumn('Скважина', 'well'),
- makeTextColumn('Куст', 'cluster'),
- makeTextColumn('Месторождение', 'deposit'),
- makeTextColumn('Заказчик', 'customer'),
- makeTextColumn('Комментарий', 'comment'),
- makeTextColumn('Версия HMI', 'hmiVersion'),
- makeTextColumn('Версия САУБ', 'saubPlcVersion'),
- makeTextColumn('Версия Спин Мастер', 'spinPlcVersion'),
-]
-
-export const TelemetryController = memo(() => {
- const [telemetryData, setTelemetryData] = useState([])
- const [isLoading, setIsLoading] = useState(false)
-
- useEffect(() => invokeWebApiWrapperAsync(
- async () => {
- const telemetryData = arrayOrDefault(await AdminTelemetryService.getAll())
- setTelemetryData(telemetryData.map((telemetry) => ({
- ...(telemetry?.info ?? []),
- id: telemetry?.id,
- remoteUid: telemetry?.remoteUid,
- realWell: telemetry?.well?.caption,
- })))
- },
- setIsLoading,
- `Не удалось загрузить список телеметрии скважин`,
- 'Полученик списка телеметрии скважин'
- ), [])
-
- return (
-
-
-
- )
-})
-
-export default TelemetryController
diff --git a/src/pages/AdminPanel/UserController/RoleTag.jsx b/src/pages/AdminPanel/UserController/RoleTag.jsx
index c67aa26..a88c7ce 100644
--- a/src/pages/AdminPanel/UserController/RoleTag.jsx
+++ b/src/pages/AdminPanel/UserController/RoleTag.jsx
@@ -1,16 +1,12 @@
import { Select } from 'antd'
-import { memo, useEffect, useState } from 'react'
+import { memo, useMemo } from 'react'
export const RoleTag = memo(({ roles, value, onChange }) => {
- const [options, setOptions] = useState([])
-
- useEffect(() => {
- setOptions(roles.map((elm) => ({
- key: Date.now(),
- value: `${elm.caption}`,
- label: elm.caption
- })))
- }, [roles])
+ const options = useMemo(() => roles.map((elm) => ({
+ key: Date.now(),
+ value: `${elm.caption}`,
+ label: elm.caption
+ })), [roles])
return (