From cdfbc2d25a4b48371b1eeb284997fa1e95db52ff Mon Sep 17 00:00:00 2001 From: goodmice Date: Thu, 2 Jun 2022 14:40:06 +0500 Subject: [PATCH] =?UTF-8?q?=D1=80=D0=B0=D1=81=D0=BF=D0=B8=D1=81=D0=B0?= =?UTF-8?q?=D0=BD=D0=B8=D0=B5=20=D0=B8=20=D1=81=D0=BF=D0=B8=D1=81=D0=BE?= =?UTF-8?q?=D0=BA=20=D1=80=D0=B0=D0=B7=D0=B4=D0=B5=D0=BB=D0=B5=D0=BD=D1=8B?= =?UTF-8?q?=20=D0=BD=D0=B0=20=D1=80=D0=B0=D0=B7=D0=BD=D1=8B=D0=B5=20=D0=BA?= =?UTF-8?q?=D0=BE=D0=BC=D0=BF=D0=BE=D0=BD=D0=B5=D0=BD=D1=82=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Telemetry/Operations/DrillerList.jsx | 78 ++++++++ .../Telemetry/Operations/DrillerSchedule.jsx | 185 ++++++------------ src/pages/Telemetry/Operations/index.jsx | 34 +++- src/styles/detected_operations.less | 25 +-- src/utils/permissions.ts | 26 +-- 5 files changed, 177 insertions(+), 171 deletions(-) create mode 100644 src/pages/Telemetry/Operations/DrillerList.jsx diff --git a/src/pages/Telemetry/Operations/DrillerList.jsx b/src/pages/Telemetry/Operations/DrillerList.jsx new file mode 100644 index 0000000..5d4efa3 --- /dev/null +++ b/src/pages/Telemetry/Operations/DrillerList.jsx @@ -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 ( + <> + + + + + + ) +}) + +export default DrillerList diff --git a/src/pages/Telemetry/Operations/DrillerSchedule.jsx b/src/pages/Telemetry/Operations/DrillerSchedule.jsx index c2d1e7a..b4f3cfc 100644 --- a/src/pages/Telemetry/Operations/DrillerSchedule.jsx +++ b/src/pages/Telemetry/Operations/DrillerSchedule.jsx @@ -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={'Настройка бурильщиков и расписаний'} > -
-
- Список бурильщиков - -
-
- Смены бурильщика - = 0 && actionHandlers.schedule.add} - onRowEdit={actionHandlers.schedule.edit} - onRowDelete={actionHandlers.schedule.delete} - /> -
-
+ - + ) }) diff --git a/src/pages/Telemetry/Operations/index.jsx b/src/pages/Telemetry/Operations/index.jsx index 62699c8..cc5f06c 100644 --- a/src/pages/Telemetry/Operations/index.jsx +++ b/src/pages/Telemetry/Operations/index.jsx @@ -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' }} /> - + {permissions.driller.get && ( + <> + + + + )}
diff --git a/src/styles/detected_operations.less b/src/styles/detected_operations.less index bcadd38..5084ee1 100644 --- a/src/styles/detected_operations.less +++ b/src/styles/detected_operations.less @@ -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; } } diff --git a/src/utils/permissions.ts b/src/utils/permissions.ts index ca1ae2d..43444b6 100755 --- a/src/utils/permissions.ts +++ b/src/utils/permissions.ts @@ -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>> = {} - 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>> = {} + 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 => {