Добавлены фильтры на страницу админки

This commit is contained in:
Александр Сироткин 2022-03-18 17:37:05 +05:00
parent ba88454500
commit d98e223468
12 changed files with 269 additions and 124 deletions

View File

@ -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'
@ -21,9 +21,11 @@ import { coordsFixed } from './DepositController'
export const ClusterController = memo(() => {
const [deposits, setDeposits] = useState([])
const [clusters, setClusters] = useState([])
const [filteredClusters, setFilteredClusters] = useState([])
const [showLoader, setShowLoader] = useState(false)
const [searchValue, setSearchValue] = useState('')
const clusterColumns = [
const clusterColumns = useMemo(() => [
makeSelectColumn('Месторождение', 'idDeposit', deposits, '--', {
width: 200,
editable: true,
@ -38,7 +40,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 +65,43 @@ export const ClusterController = memo(() => {
useEffect(updateTable, [updateTable])
const handlerProps = {
useEffect(() => {
setFilteredClusters(clusters.filter((cluster) => cluster && (!searchValue || [
cluster.caption ?? '',
cluster.latitude?.toString ?? '',
cluster.longitude?.toString() ?? '',
].join(' ').toLowerCase().includes(searchValue.toLowerCase()))))
}, [clusters, searchValue])
const handlerProps = useMemo(() => ({
service: AdminClusterService,
setLoader: setShowLoader,
errorMsg: `Не удалось выполнить операцию`,
onComplete: updateTable,
}
}), [updateTable])
return (
<LoaderPortal show={showLoader}>
<>
<Input.Search
style={{ margin: '15px 0' }}
placeholder={'Введите текст для поиска...'}
onChange={(e) => setSearchValue(e.target.value)}
value={searchValue}
loading={showLoader}
/>
<EditableTable
size={'small'}
bordered
dataSource={clusters}
size={'small'}
loading={showLoader}
columns={clusterColumns}
dataSource={filteredClusters}
pagination={defaultPagination}
onRowAdd={hasPermission('AdminCluster.edit') && makeActionHandler('insert', handlerProps, null, 'Добавление куста')}
onRowEdit={hasPermission('AdminCluster.edit') && makeActionHandler('update', handlerProps, null, 'Редактирование куста')}
onRowDelete={hasPermission('AdminCluster.delete') && makeActionHandler('delete', handlerProps, null, 'Удаление куста')}
tableName={'admin_cluster_controller'}
/>
</LoaderPortal>
</>
)
})

View File

@ -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'
@ -19,7 +19,9 @@ import { hasPermission } from '@utils/permissions'
export const CompanyController = memo(() => {
const [columns, setColumns] = useState([])
const [companies, setCompanies] = useState([])
const [filteredCompanies, setFilteredCompanies] = useState([])
const [showLoader, setShowLoader] = useState(false)
const [searchValue, setSearchValue] = useState('')
const updateTable = useCallback(async () => {
const companies = await AdminCompanyService.getAll()
@ -53,7 +55,13 @@ export const CompanyController = memo(() => {
'Получение списка типов команд'
), [updateTable])
const handlerProps = {
useEffect(() => {
setFilteredCompanies(companies.filter((company) => company && (!searchValue ||
company.caption?.toLowerCase()?.includes(searchValue.toLowerCase())
)))
}, [companies, searchValue])
const handlerProps = useMemo(() => ({
service: AdminCompanyService,
setLoader: setShowLoader,
errorMsg: `Не удалось выполнить операцию`,
@ -63,22 +71,30 @@ export const CompanyController = memo(() => {
`Не удалось обновить список компаний`,
'Получение списка компаний'
),
}
}), [updateTable])
return (
<LoaderPortal show={showLoader}>
<>
<Input.Search
style={{ margin: '15px 0' }}
placeholder={'Введите текст для поиска...'}
onChange={(e) => setSearchValue(e.target.value)}
value={searchValue}
loading={showLoader}
/>
<EditableTable
size={'small'}
bordered
size={'small'}
columns={columns}
dataSource={companies}
loading={showLoader}
dataSource={filteredCompanies}
pagination={defaultPagination}
onRowAdd={hasPermission('AdminCompany.edit') && makeActionHandler('insert', handlerProps, null, 'Добавлениее компаний')}
onRowEdit={hasPermission('AdminCompany.edit') && makeActionHandler('update', handlerProps, null, 'Редактирование команий')}
onRowDelete={hasPermission('AdminCompany.delete') && makeActionHandler('delete', handlerProps, null, 'Удаление компаний')}
tableName={'admin_company_controller'}
/>
</LoaderPortal>
</>
)
})

View File

@ -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'
@ -25,7 +25,9 @@ const columns = [
export const CompanyTypeController = memo(() => {
const [companyTypes, setCompanyTypes] = useState([])
const [filteredCompanyTypes, setFilteredCompanyTypes] = useState([])
const [showLoader, setShowLoader] = useState(false)
const [searchValue, setSearchValue] = useState('')
const updateTable = useCallback(() => invokeWebApiWrapperAsync(
async() => {
@ -39,27 +41,41 @@ export const CompanyTypeController = memo(() => {
useEffect(updateTable, [updateTable])
const handlerProps = {
useEffect(() => {
setFilteredCompanyTypes(companyTypes.filter((companyType) => companyType && (!searchValue ||
companyType.caption?.toLowerCase()?.includes(searchValue.toLowerCase())
)))
}, [companyTypes, searchValue])
const handlerProps = useMemo(() => ({
service: AdminCompanyTypeService,
setLoader: setShowLoader,
errorMsg: `Не удалось выполнить операцию`,
onComplete: updateTable,
}
}), [updateTable])
return (
<LoaderPortal show={showLoader}>
<>
<Input.Search
style={{ margin: '15px 0' }}
placeholder={'Введите текст для поиска...'}
onChange={(e) => setSearchValue(e.target.value)}
value={searchValue}
loading={showLoader}
/>
<EditableTable
bordered
size={'small'}
columns={columns}
dataSource={companyTypes}
loading={showLoader}
pagination={defaultPagination}
dataSource={filteredCompanyTypes}
onRowAdd={hasPermission('AdminCompanyType.edit') && makeActionHandler('insert', handlerProps, null, 'Добавление типа компаний')}
onRowEdit={hasPermission('AdminCompanyType.edit') && makeActionHandler('update', handlerProps, null, 'Редактирование типа компаний')}
onRowDelete={hasPermission('AdminCompanyType.delete') && makeActionHandler('delete', handlerProps, null, 'Удаление типа компаний')}
tableName={'admin_company_type_controller'}
/>
</LoaderPortal>
</>
)
})

View File

@ -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) : '-'
@ -19,7 +19,9 @@ const depositColumns = [
export const DepositController = memo(() => {
const [deposits, setDeposits] = useState([])
const [filteredDeposits, setFilteredDeposits] = useState([])
const [showLoader, setShowLoader] = useState(false)
const [searchValue, setSearchValue] = useState('')
const updateTable = useCallback(() => invokeWebApiWrapperAsync(
async() => {
@ -33,27 +35,43 @@ export const DepositController = memo(() => {
useEffect(updateTable, [updateTable])
const handlerProps = {
useEffect(() => {
setFilteredDeposits(deposits.filter((deposit) => deposit && (!searchValue || [
deposit.caption ?? '',
deposit.latitude?.toString() ?? '',
deposit.longitude?.toString() ?? '',
].join(' ').toLowerCase().includes(searchValue.toLowerCase()))))
}, [deposits, searchValue])
const handlerProps = useMemo(() => ({
service: AdminDepositService,
setLoader: setShowLoader,
errorMsg: `Не удалось выполнить операцию`,
onComplete: updateTable,
}
}), [updateTable])
return (
<LoaderPortal show={showLoader}>
<>
<Input.Search
style={{ margin: '15px 0' }}
placeholder={'Введите текст для поиска...'}
onChange={(e) => setSearchValue(e.target.value)}
value={searchValue}
loading={showLoader}
/>
<EditableTable
size={'small'}
bordered
dataSource={deposits}
size={'small'}
loading={showLoader}
columns={depositColumns}
dataSource={filteredDeposits}
pagination={defaultPagination}
onRowAdd={hasPermission('AdminDeposit.edit') && makeActionHandler('insert', handlerProps, null, 'Добавление месторождения')}
onRowEdit={hasPermission('AdminDeposit.edit') && makeActionHandler('update', handlerProps, null, 'Редактирование месторождения')}
onRowDelete={hasPermission('AdminDeposit.delete') && makeActionHandler('delete', handlerProps, null, 'Удаление месторождения')}
tableName={'admin_deposit_controller'}
/>
</LoaderPortal>
</>
)
})

View File

@ -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,10 @@ const columns = [
]
export const PermissionController = memo(() => {
const [showLoader, setShowLoader] = useState(false)
const [permissions, setPermissions] = useState([])
const [filteredPermissions, setFilteredPermissions] = useState([])
const [showLoader, setShowLoader] = useState(false)
const [searchValue, setSearchValue] = useState('')
const updateTable = useCallback(async () => invokeWebApiWrapperAsync(
async () => {
@ -42,27 +44,42 @@ export const PermissionController = memo(() => {
useEffect(() => updateTable(), [updateTable])
const handlerProps = {
useEffect(() => {
setFilteredPermissions(permissions.filter((permission) => permission && (!searchValue || [
permission.name ?? '',
permission.description ?? '',
].join(' ').includes(searchValue.toLowerCase()))))
}, [permissions, searchValue])
const handlerProps = useMemo(() => ({
service: AdminPermissionService,
setLoader: setShowLoader,
errorMsg: `Не удалось выполнить операцию`,
onComplete: updateTable
}
}), [updateTable])
return (
<LoaderPortal show={showLoader}>
<>
<Input.Search
style={{ margin: '15px 0' }}
placeholder={'Введите текст для поиска...'}
onChange={(e) => setSearchValue(e.target.value)}
value={searchValue}
loading={showLoader}
/>
<EditableTable
bordered
size={'small'}
columns={columns}
dataSource={permissions}
loading={showLoader}
dataSource={filteredPermissions}
pagination={{ showSizeChanger: true }}
onRowAdd={hasPermission('AdminPermission.edit') && makeActionHandler('insert', handlerProps, null, 'Добавление права')}
onRowEdit={hasPermission('AdminPermission.edit') && makeActionHandler('update', handlerProps, null, 'Редактирование права')}
onRowDelete={hasPermission('AdminPermission.delete') && makeActionHandler('delete', handlerProps, null, 'Удаление права')}
tableName={'admin_permission_controller'}
/>
</LoaderPortal>
</>
)
})

View File

@ -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'
@ -12,7 +12,9 @@ import { hasPermission } from '@utils/permissions'
export const RoleController = memo(() => {
const [permissions, setPermissions] = useState([])
const [roles, setRoles] = useState([])
const [filteredRoles, setFilteredRoles] = useState([])
const [showLoader, setShowLoader] = useState(false)
const [searchValue, setSearchValue] = useState('')
const [columns, setColumns] = useState([])
const loadRoles = useCallback(async () => {
@ -22,7 +24,7 @@ export const RoleController = memo(() => {
useEffect(() => {
setColumns([
makeColumn('Название', 'caption', { width: 100, editable: true, formItemRules: min1 }),
makeTextColumn('Название', 'caption', null, null, null, { width: 100, editable: true, formItemRules: min1 }),
makeTagColumn('Включённые роли', 'roles', roles, 'id', 'caption', {
width: 400,
editable: true,
@ -47,7 +49,13 @@ export const RoleController = memo(() => {
'Получение списка ролей'
), [loadRoles])
const handlerProps = {
useEffect(() => {
setFilteredRoles(roles.filter((role) => role && (!searchValue ||
role.caption?.toLowerCase()?.includes(searchValue.toLowerCase())
)))
}, [roles, searchValue])
const handlerProps = useMemo(() => ({
service: AdminUserRoleService,
setLoader: setShowLoader,
errorMsg: `Не удалось выполнить операцию`,
@ -57,21 +65,29 @@ export const RoleController = memo(() => {
`Не удалось загрузить список ролей`,
'Получение списка ролей'
)
}
}), [loadRoles])
return (
<LoaderPortal show={showLoader}>
<>
<Input.Search
style={{ margin: '15px 0' }}
placeholder={'Введите текст для поиска...'}
onChange={(e) => setSearchValue(e.target.value)}
value={searchValue}
loading={showLoader}
/>
<EditableTable
bordered
size={'small'}
columns={columns}
dataSource={roles}
loading={showLoader}
dataSource={filteredRoles}
onRowAdd={hasPermission('AdminUserRole.edit') && makeActionHandler('insert', handlerProps, null, 'Добавление роли')}
onRowEdit={hasPermission('AdminUserRole.edit') && makeActionHandler('update', handlerProps, null, 'Редактирование роли')}
onRowDelete={hasPermission('AdminUserRole.delete') && makeActionHandler('delete', handlerProps, null, 'Удаление роли')}
tableName={'admin_role_controller'}
/>
</LoaderPortal>
</>
)
})

View File

@ -1,4 +1,5 @@
import { memo, useEffect, useState } from 'react'
import { Input } from 'antd'
import {
defaultPagination,
@ -8,7 +9,6 @@ import {
makeTextColumn,
Table
} from '@components/Table'
import LoaderPortal from '@components/LoaderPortal'
import { invokeWebApiWrapperAsync } from '@components/factory'
import { AdminTelemetryService } from '@api'
import { arrayOrDefault } from '@utils'
@ -31,7 +31,10 @@ const columns = [
export const TelemetryController = memo(() => {
const [telemetryData, setTelemetryData] = useState([])
const [isLoading, setIsLoading] = useState(false)
const [filteredTelemetryData, setFilteredTelemetryData] = useState([])
const [showLoader, setShowLoader] = useState(false)
const [searchValue, setSearchValue] = useState('')
useEffect(() => invokeWebApiWrapperAsync(
async () => {
@ -43,22 +46,46 @@ export const TelemetryController = memo(() => {
realWell: telemetry?.well?.caption,
})))
},
setIsLoading,
setShowLoader,
`Не удалось загрузить список телеметрии скважин`,
'Полученик списка телеметрии скважин'
), [])
useEffect(() => {
setFilteredTelemetryData(telemetryData.filter((telemetry) => telemetry && (!searchValue || [
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])
return (
<LoaderPortal show={isLoading}>
<>
<Input.Search
style={{ margin: '15px 0' }}
placeholder={'Введите текст для поиска...'}
onChange={(e) => setSearchValue(e.target.value)}
value={searchValue}
loading={showLoader}
/>
<Table
size={'small'}
bordered
size={'small'}
columns={columns}
dataSource={telemetryData}
loading={showLoader}
pagination={defaultPagination}
dataSource={filteredTelemetryData}
tableName={'admin_telemetry_controller'}
/>
</LoaderPortal>
</>
)
})

View File

@ -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 (
<Select

View File

@ -5,12 +5,11 @@ import { BehaviorSubject, debounceTime, distinctUntilChanged, filter, map } from
import {
EditableTable,
makeColumn,
makeSelectColumn,
makeActionHandler,
makeStringSorter,
makeNumericSorter,
defaultPagination
defaultPagination,
makeTextColumn
} from '@components/Table'
import { RoleView } from '@components/views'
import LoaderPortal from '@components/LoaderPortal'
@ -38,7 +37,7 @@ export const UserController = memo(() => {
useEffect(() => invokeWebApiWrapperAsync(
async () => {
const filteredUsers = users.filter((user) => user && [
const filteredUsers = users.filter((user) => user && (!searchValue || [
user.login ?? '',
user.name ?? '',
user.surname ?? '',
@ -47,7 +46,7 @@ export const UserController = memo(() => {
user.phone ?? '',
user.position ?? '',
user.company?.caption ?? '',
].join(' ').toLowerCase().includes(searchValue))
].join(' ').toLowerCase().includes(searchValue.toLowerCase())))
setFilteredUsers(filteredUsers)
},
setIsSearching,
@ -106,8 +105,14 @@ export const UserController = memo(() => {
const filters = makeTextFilters(users, ['surname', 'name', 'patronymic', 'email'])
const roleFilters = [{ text: 'Без роли', value: null }, ...roles.map((role) => ({ text: role.caption, value: role.caption }))]
const rolesRender = (item) => item?.map((elm) => (
<Tag key={elm} color={'blue'}>
<RoleView role={roles.find((role) => role.caption === elm)} />
</Tag>
)) ?? '-'
setColumns([
makeColumn('Логин', 'login', {
makeTextColumn('Логин', 'login', null, null, null, {
editable: true,
formItemRules: [
{ required: true },
@ -121,59 +126,40 @@ export const UserController = memo(() => {
// })
// TODO: Для проверки уникальности логина необходимо исключить из выборки логин выбранного пользователя
],
sorter: makeStringSorter('login'),
}),
makeColumn('Фамилия', 'surname', {
makeTextColumn('Фамилия', 'surname', filters.surname, null, null, {
editable: true,
formItemRules: [{ required: true }, ...nameRules],
sorter: makeStringSorter('surname'),
filters: filters.surname,
filterSearch: true,
onFilter: makeTextOnFilter('surname'),
}),
makeColumn('Имя', 'name', {
makeTextColumn('Имя', 'name', filters.name, null, null, {
editable: true,
formItemRules: nameRules,
sorter: makeStringSorter('name'),
filters: filters.name,
filterSearch: true,
onFilter: makeTextOnFilter('name'),
}),
makeColumn('Отчество', 'patronymic', {
makeTextColumn('Отчество', 'patronymic', filters.partonymic, null, null, {
editable: true,
formItemRules: nameRules,
sorter: makeStringSorter('patronymic'),
filters: filters.patronymic,
filterSearch: true,
onFilter: makeTextOnFilter('patronymic'),
}),
makeColumn('E-mail', 'email', {
makeTextColumn('E-mail', 'email', filters.email, null, null, {
editable: true,
formItemRules: [{ required: true }, ...emailRules],
sorter: makeStringSorter('email'),
filters: filters.email,
filterSearch: true,
onFilter: makeTextOnFilter('email'),
}),
makeColumn('Номер телефона', 'phone', {
makeTextColumn('Номер телефона', 'phone', null, null, null, {
editable: true,
formItemRules: phoneRules,
sorter: makeStringSorter('phone'),
}),
makeColumn('Должность', 'position', {
editable: true,
sorter: makeStringSorter('position'),
}),
makeColumn('Роли', 'roleNames', {
makeTextColumn('Должность', 'position', null, null, null, { editable: true }),
makeTextColumn('Роли', 'roleNames', roleFilters, null, rolesRender, {
editable: true,
input: <RoleTag roles={roles} />,
filters: roleFilters,
onFilter: makeArrayOnFilter('roleNames'),
render: (item) => item?.map((elm) => (
<Tag key={elm} color={'blue'}>
<RoleView role={roles.find((role) => role.caption === elm)} />
</Tag>
)) ?? '-'
}),
makeSelectColumn('Компания', 'idCompany', companies, '--', {
editable: true,

View File

@ -1,6 +1,6 @@
import { memo, useEffect, useState } from 'react'
import { Input } from 'antd'
import LoaderPortal from '@components/LoaderPortal'
import { invokeWebApiWrapperAsync } from '@components/factory'
import { defaultPagination, makeColumn, makeDateSorter, makeStringSorter, Table } from '@components/Table'
import { RequestTrackerService } from '@api'
@ -19,7 +19,9 @@ const columns = [
export const VisitLog = memo(() => {
const [logData, setLogData] = useState([])
const [isLoading, setIsLoading] = useState(false)
const [filteredLogData, setFilteredLogData] = useState([])
const [showLoader, setShowLoader] = useState(false)
const [searchValue, setSearchValue] = useState('')
useEffect(() => invokeWebApiWrapperAsync(
async () => {
@ -27,23 +29,38 @@ export const VisitLog = memo(() => {
logData.forEach((log) => log.key = `${log.login}${log.ip}`)
setLogData(logData)
},
setIsLoading,
setShowLoader,
`Не удалось загрузить список последних посещений пользователей`,
'Получение списка последних посещений'
), [])
useEffect(() => {
setFilteredLogData(logData.filter((data) => data && (!searchValue || [
data.login ?? '',
data.ip ?? '',
data.lastDate ?? '',
].join(' ').toLowerCase().includes(searchValue.toLowerCase()))))
}, [logData, searchValue])
return (
<LoaderPortal show={isLoading}>
<>
<Input.Search
style={{ margin: '15px 0' }}
placeholder={'Введите текст для поиска...'}
onChange={(e) => setSearchValue(e.target.value)}
value={searchValue}
loading={showLoader}
/>
<Table
size={'small'}
bordered
size={'small'}
columns={columns}
dataSource={logData}
loading={showLoader}
dataSource={filteredLogData}
pagination={defaultPagination}
tableName={'visit_log'}
/>
</LoaderPortal>
</>
)
})

View File

@ -1,6 +1,6 @@
import { Button } from 'antd'
import { Button, Input } from 'antd'
import { CopyOutlined } from '@ant-design/icons'
import { memo, useEffect, useState } from 'react'
import { memo, useCallback, useEffect, useMemo, useState } from 'react'
import {
AdminClusterService,
@ -19,7 +19,6 @@ import {
defaultPagination,
makeTimezoneColumn,
} from '@components/Table'
import LoaderPortal from '@components/LoaderPortal'
import { invokeWebApiWrapperAsync } from '@components/factory'
import { TelemetryView, CompanyView } from '@components/views'
import { hasPermission } from '@utils/permissions'
@ -43,9 +42,12 @@ const recordParser = (record) => ({
export const WellController = memo(() => {
const [columns, setColumns] = useState([])
const [wells, setWells] = useState([])
const [filteredWells, setFilteredWells] = useState([])
const [showLoader, setShowLoader] = useState(false)
const [searchValue, setSearchValue] = useState('')
const updateTable = async () => invokeWebApiWrapperAsync(
const updateTable = useCallback(async () => invokeWebApiWrapperAsync(
async () => {
const wells = await AdminWellService.getAll()
setWells(arrayOrDefault(wells))
@ -53,11 +55,11 @@ export const WellController = memo(() => {
setShowLoader,
`Не удалось загрузить список скважин`,
'Получение списка скважин'
)
), [])
const duplicateWell = (well) => {
const duplicateWell = useCallback((well) => {
// TODO: Метод дубликации скважины
}
}, [])
const addititonalButtons = memo((record, editingKey) => (
<Button
@ -112,22 +114,38 @@ export const WellController = memo(() => {
setShowLoader,
`Не удалось загрузить список кустов`,
'Получение списка кустов'
), [])
), [updateTable])
const handlerProps = {
useEffect(() => {
setFilteredWells(wells.filter((well) => well && (!searchValue || [
well.caption ?? '',
well.latitude?.toString() ?? '',
well.longitude?.toString() ?? '',
].join(' ').toLowerCase().includes(searchValue.toLowerCase()))))
}, [wells, searchValue])
const handlerProps = useMemo(() => ({
service: AdminWellService,
setLoader: setShowLoader,
errorMsg: `Не удалось выполнить операцию`,
onComplete: updateTable
}
}), [updateTable])
return (
<LoaderPortal show={showLoader}>
<>
<Input.Search
style={{ margin: '15px 0' }}
placeholder={'Введите текст для поиска...'}
onChange={(e) => setSearchValue(e.target.value)}
value={searchValue}
loading={showLoader}
/>
<EditableTable
size={'small'}
bordered
columns={columns}
dataSource={wells}
loading={showLoader}
dataSource={filteredWells}
pagination={defaultPagination}
onRowAdd={hasPermission('AdminWell.edit') && makeActionHandler('insert', handlerProps, recordParser, 'Добавление скважины')}
onRowEdit={hasPermission('AdminWell.edit') && makeActionHandler('update', handlerProps, recordParser, 'Редактирование скважины')}
@ -136,7 +154,7 @@ export const WellController = memo(() => {
buttonsWidth={95}
tableName={'admin_well_controller'}
/>
</LoaderPortal>
</>
)
})

View File

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