forked from ddrilling/asb_cloud_front
расписание и список разделены на разные компоненты
This commit is contained in:
parent
294bc16a83
commit
cdfbc2d25a
78
src/pages/Telemetry/Operations/DrillerList.jsx
Normal file
78
src/pages/Telemetry/Operations/DrillerList.jsx
Normal file
@ -0,0 +1,78 @@
|
||||
import { memo, useCallback, useMemo, useState } from 'react'
|
||||
import { Button, Modal } from 'antd'
|
||||
|
||||
import { EditableTable, makeActionHandler, makeTextColumn } from '@components/Table'
|
||||
import { getPermissions } from '@utils/permissions'
|
||||
import { DrillerService } from '@api'
|
||||
|
||||
const reqRule = [{ message: 'Обязательное поле!', required: true }]
|
||||
|
||||
const rowClassName = (record) => record.has ? 'driller_list_active' : ''
|
||||
|
||||
const columns = [
|
||||
makeTextColumn('Фамилия', 'surname', undefined, undefined, undefined, { editable: true, formItemRules: reqRule }),
|
||||
makeTextColumn('Имя', 'name', undefined, undefined, undefined, { editable: true, formItemRules: reqRule }),
|
||||
makeTextColumn('Отчество', 'patronymic', undefined, undefined, undefined, { editable: true }),
|
||||
]
|
||||
|
||||
export const DrillerList = memo(({ loading, drillers, onChange }) => {
|
||||
const [showLoader, setShowLoader] = useState(false)
|
||||
const [showModal, setShowModal] = useState(false)
|
||||
|
||||
const permissions = useMemo(() => getPermissions('Driller.edit', 'Driller.delete'), [])
|
||||
|
||||
const onModalOpen = useCallback(() => {
|
||||
setShowModal(true)
|
||||
}, [])
|
||||
|
||||
const onModalCancel = useCallback(() => {
|
||||
setShowModal(false)
|
||||
}, [])
|
||||
|
||||
const handlerProps = useMemo(() => ({
|
||||
service: DrillerService,
|
||||
setLoader: setShowLoader,
|
||||
errorMsg: `Не удалось выполнить операцию`,
|
||||
onComplete: onChange,
|
||||
}), [onChange])
|
||||
|
||||
const actionHandlers = useMemo(() => ({
|
||||
add: permissions.driller.edit && makeActionHandler('insert', handlerProps),
|
||||
edit: permissions.driller.edit && makeActionHandler('update', handlerProps),
|
||||
delete: permissions.driller.delete && makeActionHandler('delete', handlerProps),
|
||||
}), [permissions, handlerProps])
|
||||
|
||||
return (
|
||||
<>
|
||||
<Modal
|
||||
centered
|
||||
width={500}
|
||||
footer={null}
|
||||
visible={showModal}
|
||||
onCancel={onModalCancel}
|
||||
title={'Список бурильщиков'}
|
||||
>
|
||||
<EditableTable
|
||||
bordered
|
||||
size={'small'}
|
||||
pagination={false}
|
||||
loading={loading || showLoader}
|
||||
dataSource={drillers}
|
||||
columns={columns}
|
||||
scroll={{ y: '75vh', scrollToFirstRowOnChange: true }}
|
||||
onRowAdd={actionHandlers.add}
|
||||
onRowEdit={actionHandlers.edit}
|
||||
onRowDelete={actionHandlers.delete}
|
||||
rowClassName={rowClassName}
|
||||
/>
|
||||
</Modal>
|
||||
<Button
|
||||
onClick={onModalOpen}
|
||||
loading={loading || showLoader}
|
||||
style={{ marginRight: '10px' }}
|
||||
>Список бурильщиков</Button>
|
||||
</>
|
||||
)
|
||||
})
|
||||
|
||||
export default DrillerList
|
@ -1,64 +1,29 @@
|
||||
import { memo, useCallback, useEffect, useMemo, useState } from 'react'
|
||||
import { Button, Modal, Typography } from 'antd'
|
||||
import { Button, Modal } from 'antd'
|
||||
|
||||
import { useIdWell } from '@asb/context'
|
||||
import {
|
||||
makeTimeColumn,
|
||||
makeGroupColumn,
|
||||
makeDateColumn,
|
||||
makeTextColumn,
|
||||
EditableTable,
|
||||
makeActionHandler,
|
||||
makeSelectColumn,
|
||||
} from '@components/Table'
|
||||
import { invokeWebApiWrapperAsync } from '@components/factory'
|
||||
import { DrillerService, ScheduleService } from '@api'
|
||||
import { usePermissions } from '@utils/permissions'
|
||||
import { getPermissions } from '@utils/permissions'
|
||||
import { ScheduleService } from '@api'
|
||||
|
||||
const reqRule = [{ message: 'Обязательное поле!', required: true }]
|
||||
|
||||
const drillerColumns = [
|
||||
makeTextColumn('Фамилия', 'surname', undefined, undefined, undefined, { editable: true, formItemRules: reqRule }),
|
||||
makeTextColumn('Имя', 'name', undefined, undefined, undefined, { editable: true, formItemRules: reqRule }),
|
||||
makeTextColumn('Отчество', 'patronymic', undefined, undefined, undefined, { editable: true }),
|
||||
]
|
||||
|
||||
const scheduleColumns = [
|
||||
makeGroupColumn('Рабочий период', [
|
||||
makeDateColumn('Начало', 'drillStart', undefined, undefined, { editable: true, formItemRules: reqRule }),
|
||||
makeDateColumn('Конец', 'drillEnd', undefined, undefined, { editable: true, formItemRules: reqRule }),
|
||||
]),
|
||||
makeGroupColumn('Смена', [
|
||||
makeTimeColumn('Начало', 'shiftStart', undefined, undefined, { editable: true, formItemRules: reqRule }),
|
||||
makeTimeColumn('Конец', 'shiftEnd', undefined, undefined, { editable: true, formItemRules: reqRule }),
|
||||
]),
|
||||
]
|
||||
|
||||
const drillerRowClassName = (record) => record.has ? 'driller_list_active' : ''
|
||||
|
||||
export const DrillerSchedule = memo(() => {
|
||||
const [modalVisible, setModalVisible] = useState(false)
|
||||
export const DrillerSchedule = memo(({ drillers, loading, onChange }) => {
|
||||
const [modalVisible, setScheduleModalVisible] = useState(false)
|
||||
const [showLoader, setShowLoader] = useState(false)
|
||||
const [schedule, setSchedule] = useState([])
|
||||
const [drillers, setDrillers] = useState([])
|
||||
const [selectedDrillerId, setSelectedDrillerId] = useState(-1)
|
||||
|
||||
const idWell = useIdWell()
|
||||
|
||||
// const permissions = usePermissions(
|
||||
// 'Driller.edit',
|
||||
// 'Driller.delete',
|
||||
// 'Schedule.edit',
|
||||
// 'Schedule.delete'
|
||||
// )
|
||||
|
||||
const permissions = {
|
||||
driller: { edit: true, delete: true },
|
||||
schedule: { edit: true, delete: true },
|
||||
}
|
||||
|
||||
const drillerSchedule = useMemo(() =>
|
||||
schedule.filter((v) => v.idDriller === selectedDrillerId)
|
||||
, [schedule, selectedDrillerId])
|
||||
const permissions = useMemo(() => getPermissions('Schedule.edit', 'Schedule.delete'), [])
|
||||
|
||||
const updateSchedule = useCallback(async () => invokeWebApiWrapperAsync(
|
||||
async () => {
|
||||
@ -67,48 +32,18 @@ export const DrillerSchedule = memo(() => {
|
||||
}
|
||||
), [idWell])
|
||||
|
||||
const updateList = useCallback(async () => invokeWebApiWrapperAsync(
|
||||
async () => {
|
||||
let drillers = await DrillerService.getAll()
|
||||
drillers = drillers.map((val) => ({
|
||||
...val,
|
||||
has: schedule.findIndex((elm) => elm.idDriller === val.id) >= 0,
|
||||
}))
|
||||
drillers.sort((a, b) => +b.has - a.has)
|
||||
setDrillers(drillers)
|
||||
},
|
||||
setShowLoader,
|
||||
'Не удалось загрузить список бурильщиков',
|
||||
'Получение списка бурильщиков'
|
||||
), [schedule])
|
||||
|
||||
const onModalOpen = useCallback(() => {
|
||||
setModalVisible(true)
|
||||
setScheduleModalVisible(true)
|
||||
}, [])
|
||||
|
||||
const onModalCancel = useCallback(() => {
|
||||
setModalVisible(false)
|
||||
}, [])
|
||||
|
||||
const onDrillerSelected = useCallback((selected) => {
|
||||
setSelectedDrillerId(selected?.[0] ?? -1)
|
||||
setScheduleModalVisible(false)
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
updateSchedule()
|
||||
}, [updateSchedule])
|
||||
|
||||
useEffect(() => {
|
||||
updateList()
|
||||
}, [updateList])
|
||||
|
||||
const drillerHandlerProps = useMemo(() => ({
|
||||
service: DrillerService,
|
||||
setLoader: setShowLoader,
|
||||
errorMsg: `Не удалось выполнить операцию`,
|
||||
onComplete: updateSchedule,
|
||||
}), [updateSchedule])
|
||||
|
||||
const scheduleHandlerProps = useMemo(() => ({
|
||||
service: ScheduleService,
|
||||
setLoader: setShowLoader,
|
||||
@ -116,24 +51,39 @@ export const DrillerSchedule = memo(() => {
|
||||
onComplete: updateSchedule,
|
||||
}), [updateSchedule])
|
||||
|
||||
const newScheduleParser = useCallback((record) => ({
|
||||
...record,
|
||||
idWell,
|
||||
idDriller: selectedDrillerId
|
||||
}), [idWell, selectedDrillerId])
|
||||
const newScheduleParser = useCallback((record) => ({ ...record, idWell }), [idWell])
|
||||
|
||||
const actionHandlers = useMemo(() => ({
|
||||
driller: {
|
||||
add: permissions.driller.edit && makeActionHandler('insert', drillerHandlerProps),
|
||||
edit: permissions.driller.edit && makeActionHandler('update', drillerHandlerProps),
|
||||
delete: permissions.driller.delete && makeActionHandler('delete', drillerHandlerProps),
|
||||
},
|
||||
schedule: {
|
||||
add: permissions.schedule.edit && makeActionHandler('insert', scheduleHandlerProps, newScheduleParser),
|
||||
edit: permissions.schedule.edit && makeActionHandler('update', scheduleHandlerProps),
|
||||
delete: permissions.schedule.delete && makeActionHandler('delete', scheduleHandlerProps),
|
||||
},
|
||||
}), [permissions, drillerHandlerProps, scheduleHandlerProps, newScheduleParser])
|
||||
add: permissions.schedule.edit && makeActionHandler('insert', scheduleHandlerProps, newScheduleParser),
|
||||
edit: permissions.schedule.edit && makeActionHandler('update', scheduleHandlerProps),
|
||||
delete: permissions.schedule.delete && makeActionHandler('delete', scheduleHandlerProps),
|
||||
}), [permissions, scheduleHandlerProps, newScheduleParser])
|
||||
|
||||
const scheduleColumns = useMemo(() => {
|
||||
const options = drillers.map(({ id, name, surname, patronymic }) => ({
|
||||
value: id,
|
||||
label: `${surname} ${name} ${patronymic}`,
|
||||
}))
|
||||
|
||||
return [
|
||||
makeSelectColumn('Бурильщик', 'idDriller', options, undefined, {
|
||||
editable: true,
|
||||
formItemRules: reqRule,
|
||||
}, {
|
||||
showSearch: true,
|
||||
filterOption: (input, option) =>
|
||||
String(option?.label ?? '').toLowerCase().indexOf(input.toLowerCase()) >= 0
|
||||
}),
|
||||
makeGroupColumn('Рабочий период', [
|
||||
makeDateColumn('Начало', 'drillStart', undefined, undefined, { editable: true, formItemRules: reqRule }),
|
||||
makeDateColumn('Конец', 'drillEnd', undefined, undefined, { editable: true, formItemRules: reqRule }),
|
||||
]),
|
||||
makeGroupColumn('Смена', [
|
||||
makeTimeColumn('Начало', 'shiftStart', undefined, undefined, { editable: true, formItemRules: reqRule }),
|
||||
makeTimeColumn('Конец', 'shiftEnd', undefined, undefined, { editable: true, formItemRules: reqRule }),
|
||||
]),
|
||||
]
|
||||
}, [drillers])
|
||||
|
||||
return (
|
||||
<>
|
||||
@ -145,44 +95,25 @@ export const DrillerSchedule = memo(() => {
|
||||
onCancel={onModalCancel}
|
||||
title={'Настройка бурильщиков и расписаний'}
|
||||
>
|
||||
<div className={'drill_schedule'}>
|
||||
<div className={'driller_list list'}>
|
||||
<Typography.Title level={4}>Список бурильщиков</Typography.Title>
|
||||
<EditableTable
|
||||
bordered
|
||||
size={'small'}
|
||||
pagination={false}
|
||||
loading={showLoader}
|
||||
dataSource={drillers}
|
||||
columns={drillerColumns}
|
||||
scroll={{ y: '75vh', scrollToFirstRowOnChange: true }}
|
||||
onRowAdd={actionHandlers.driller.add}
|
||||
onRowEdit={actionHandlers.driller.edit}
|
||||
onRowDelete={actionHandlers.driller.delete}
|
||||
rowClassName={drillerRowClassName}
|
||||
rowSelection={{ type: 'radio', onChange: onDrillerSelected }}
|
||||
rowKey={'id'}
|
||||
/>
|
||||
</div>
|
||||
<div className={'schedule_list list'}>
|
||||
<Typography.Title level={4}>Смены бурильщика</Typography.Title>
|
||||
<EditableTable
|
||||
sticky
|
||||
bordered
|
||||
size={'small'}
|
||||
pagination={false}
|
||||
loading={showLoader}
|
||||
columns={scheduleColumns}
|
||||
dataSource={drillerSchedule}
|
||||
scroll={{ y: '75vh', scrollToFirstRowOnChange: true }}
|
||||
onRowAdd={selectedDrillerId >= 0 && actionHandlers.schedule.add}
|
||||
onRowEdit={actionHandlers.schedule.edit}
|
||||
onRowDelete={actionHandlers.schedule.delete}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<EditableTable
|
||||
sticky
|
||||
bordered
|
||||
size={'small'}
|
||||
pagination={false}
|
||||
loading={loading || showLoader}
|
||||
dataSource={schedule}
|
||||
columns={scheduleColumns}
|
||||
scroll={{ y: '75vh', scrollToFirstRowOnChange: true }}
|
||||
onRowAdd={actionHandlers.add}
|
||||
onRowEdit={actionHandlers.edit}
|
||||
onRowDelete={actionHandlers.delete}
|
||||
/>
|
||||
</Modal>
|
||||
<Button onClick={onModalOpen} loading={showLoader}>Расписание бурильщиков</Button>
|
||||
<Button
|
||||
onClick={onModalOpen}
|
||||
loading={loading || showLoader}
|
||||
style={{ marginRight: '10px' }}
|
||||
>Расписание бурильщиков</Button>
|
||||
</>
|
||||
)
|
||||
})
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { memo, useCallback, useEffect, useState } from 'react'
|
||||
import { memo, useCallback, useEffect, useMemo, useState } from 'react'
|
||||
import { InputNumber } from 'antd'
|
||||
import moment from 'moment'
|
||||
|
||||
@ -6,9 +6,11 @@ import { useIdWell } from '@asb/context'
|
||||
import LoaderPortal from '@components/LoaderPortal'
|
||||
import { DateRangeWrapper } from '@components/Table'
|
||||
import { invokeWebApiWrapperAsync } from '@components/factory'
|
||||
import { DetectedOperationService, TelemetryDataSaubService } from '@api'
|
||||
import { range } from '@utils'
|
||||
import { DetectedOperationService, DrillerService, TelemetryDataSaubService } from '@api'
|
||||
import { getPermissions } from '@utils/permissions'
|
||||
import { arrayOrDefault, range } from '@utils'
|
||||
|
||||
import DrillerList from './DrillerList'
|
||||
import DrillerSchedule from './DrillerSchedule'
|
||||
import OperationsChart from './OperationsChart'
|
||||
import OperationsTable from './OperationsTable'
|
||||
@ -21,9 +23,13 @@ export const Operations = memo(() => {
|
||||
const [yDomain, setYDomain] = useState(20)
|
||||
const [dates, setDates] = useState()
|
||||
const [data, setData] = useState([])
|
||||
const [drillers, setDrillers] = useState([])
|
||||
const [drillersLoader, setDrillersLoader] = useState(false)
|
||||
|
||||
const idWell = useIdWell()
|
||||
|
||||
const permissions = useMemo(() => getPermissions('Driller.get'), [])
|
||||
|
||||
const disabledDates = useCallback((current) => current && !moment(current).isBetween(...dateRange, 'day', '[]'), [dateRange])
|
||||
|
||||
const disabledTimes = useCallback((date) => ({
|
||||
@ -32,6 +38,21 @@ export const Operations = memo(() => {
|
||||
disabledSeconds: () => range(60).filter(s => date && !moment(date).seconds(s).isBetween(...dateRange, 'second', '[]'))
|
||||
}), [dateRange])
|
||||
|
||||
const updateDrillers = useCallback(async () => invokeWebApiWrapperAsync(
|
||||
async () => {
|
||||
const drillers = arrayOrDefault(await DrillerService.getAll())
|
||||
setDrillers(drillers)
|
||||
},
|
||||
setDrillersLoader,
|
||||
'Не удалось загрузить список бурильщиков',
|
||||
'Получение списка бурильщиков'
|
||||
), [])
|
||||
|
||||
useEffect(() => {
|
||||
if (permissions.driller.get)
|
||||
updateDrillers()
|
||||
}, [updateDrillers, permissions])
|
||||
|
||||
useEffect(() => invokeWebApiWrapperAsync(
|
||||
async () => {
|
||||
const dates = await TelemetryDataSaubService.getDataDatesRange(idWell)
|
||||
@ -78,7 +99,12 @@ export const Operations = memo(() => {
|
||||
addonBefore={'Верхняя граница'}
|
||||
style={{ marginRight: '10px' }}
|
||||
/>
|
||||
<DrillerSchedule />
|
||||
{permissions.driller.get && (
|
||||
<>
|
||||
<DrillerSchedule drillers={drillers} loading={drillersLoader} onChange={updateDrillers} />
|
||||
<DrillerList drillers={drillers} loading={drillersLoader} onChange={updateDrillers} />
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
<LoaderPortal show={isLoading}>
|
||||
<div className={'page-main'}>
|
||||
|
@ -8,6 +8,7 @@
|
||||
|
||||
.drill_schedule {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
height: 75vh;
|
||||
align-items: stretch;
|
||||
@ -21,29 +22,5 @@
|
||||
& > .ant-list, .ant-table {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
& > .buttons {
|
||||
display: flex;
|
||||
|
||||
& > * {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
& > .driller_list {
|
||||
flex: 2;
|
||||
width: 10vw;
|
||||
margin-right: 15px;
|
||||
|
||||
.driller_list_active {
|
||||
background-color: rgba(0, 255, 0, .25);
|
||||
}
|
||||
}
|
||||
|
||||
& > .schedule_list {
|
||||
width: 10vw;
|
||||
flex: 3;
|
||||
margin-left: 15px;
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,4 @@
|
||||
import { useMemo } from 'react'
|
||||
|
||||
import { getUserPermissions, getUserRoles } from './storage'
|
||||
import { getUserLogin, getUserPermissions, getUserRoles } from './storage'
|
||||
|
||||
export type Role = string
|
||||
export type Permission = string
|
||||
@ -13,19 +11,15 @@ export function isRequestType(value: string): value is ServiceRequestType {
|
||||
return ['get', 'edit', 'delete'].includes(value)
|
||||
}
|
||||
|
||||
export const usePermissions = (...values: PermissionRequest[]) => {
|
||||
const result = useMemo(() => {
|
||||
const permissions: Record<string, Partial<Record<ServiceRequestType, boolean>>> = {}
|
||||
values.forEach((key) => {
|
||||
const [service, type] = key.toLowerCase().split('.')
|
||||
if (!isRequestType(type)) return
|
||||
permissions[service] = permissions[service] ?? {}
|
||||
permissions[service][type] = hasPermission(key)
|
||||
})
|
||||
return permissions
|
||||
}, [values])
|
||||
|
||||
return result
|
||||
export const getPermissions = (...values: PermissionRequest[]) => {
|
||||
const permissions: Record<string, Partial<Record<ServiceRequestType, boolean>>> = {}
|
||||
values.forEach((key) => {
|
||||
const [service, type] = key.toLowerCase().split('.')
|
||||
if (!isRequestType(type)) return
|
||||
permissions[service] = permissions[service] ?? {}
|
||||
permissions[service][type] = getUserLogin() === 'dev' || hasPermission(key)
|
||||
})
|
||||
return permissions
|
||||
}
|
||||
|
||||
export const hasPermission = (permission?: Permission | Permission[], userPermissions?: Permission[]): boolean => {
|
||||
|
Loading…
Reference in New Issue
Block a user