Фильтр по дате
@@ -158,6 +158,7 @@ export const DocumentsTemplate = ({ idCategory, well: givenWell, mimeTypes, head
onRowDelete={handleFileDelete}
rowKey={(record) => record.id}
tableName={tableName ?? `file_${idCategory}`}
+ scroll={{ x: true }}
/>
)
diff --git a/src/pages/Documents/index.jsx b/src/pages/Well/Documents/index.jsx
old mode 100755
new mode 100644
similarity index 59%
rename from src/pages/Documents/index.jsx
rename to src/pages/Well/Documents/index.jsx
index d3882fb..1b4c293
--- a/src/pages/Documents/index.jsx
+++ b/src/pages/Well/Documents/index.jsx
@@ -1,16 +1,11 @@
import { Navigate, Route, Routes } from 'react-router-dom'
import { memo, useMemo } from 'react'
-import { FolderOutlined } from '@ant-design/icons'
-import { Layout } from 'antd'
import { RootPathContext, useRootPath } from '@asb/context'
-import { PrivateMenu } from '@components/Private'
-import { getTabname, wrapPrivateComponent, NoAccessComponent, hasPermission } from '@utils'
+import { wrapPrivateComponent, NoAccessComponent, hasPermission } from '@utils'
import DocumentsTemplate from './DocumentsTemplate'
-const { Content } = Layout
-
const makeDocCat = (id, key, title, permissions = ['File.get']) => ({ id, key, title, permissions })
export const documentCategories = [
@@ -27,7 +22,6 @@ export const documentCategories = [
]
const MenuDocuments = memo(() => {
- const category = getTabname()
const root = useRootPath()
const rootPath = useMemo(() => `${root}/document`, [root])
@@ -35,34 +29,21 @@ const MenuDocuments = memo(() => {
return (
-
- {categories.map(category => (
- }
- title={category.title}
- />
- ))}
-
-
-
-
- {categories.length > 0 && (
- } />
- )}
- } />
+
+ {categories.length > 0 && (
+ } />
+ )}
+ } />
- {categories.map(category => (
-
- )} />
- ))}
-
-
-
+ {categories.map(category => (
+
+ )} />
+ ))}
+
)
})
diff --git a/src/pages/DrillingProgram/CategoryAdder.jsx b/src/pages/Well/DrillingProgram/CategoryAdder.jsx
old mode 100755
new mode 100644
similarity index 100%
rename from src/pages/DrillingProgram/CategoryAdder.jsx
rename to src/pages/Well/DrillingProgram/CategoryAdder.jsx
diff --git a/src/pages/DrillingProgram/CategoryEditor.jsx b/src/pages/Well/DrillingProgram/CategoryEditor.jsx
old mode 100755
new mode 100644
similarity index 99%
rename from src/pages/DrillingProgram/CategoryEditor.jsx
rename to src/pages/Well/DrillingProgram/CategoryEditor.jsx
index b1066e1..cab4df1
--- a/src/pages/DrillingProgram/CategoryEditor.jsx
+++ b/src/pages/Well/DrillingProgram/CategoryEditor.jsx
@@ -159,7 +159,7 @@ export const CategoryEditor = memo(({ visible, category, onClosed }) => {
{
title={'История категории'}
width={1200}
centered
- visible={!!visible}
+ open={!!visible}
onCancel={onClose}
footer={(
diff --git a/src/pages/DrillingProgram/CategoryRender.jsx b/src/pages/Well/DrillingProgram/CategoryRender.jsx
old mode 100755
new mode 100644
similarity index 100%
rename from src/pages/DrillingProgram/CategoryRender.jsx
rename to src/pages/Well/DrillingProgram/CategoryRender.jsx
diff --git a/src/pages/DrillingProgram/MarksCard.jsx b/src/pages/Well/DrillingProgram/MarksCard.jsx
old mode 100755
new mode 100644
similarity index 100%
rename from src/pages/DrillingProgram/MarksCard.jsx
rename to src/pages/Well/DrillingProgram/MarksCard.jsx
diff --git a/src/pages/DrillingProgram/index.jsx b/src/pages/Well/DrillingProgram/index.jsx
old mode 100755
new mode 100644
similarity index 100%
rename from src/pages/DrillingProgram/index.jsx
rename to src/pages/Well/DrillingProgram/index.jsx
diff --git a/src/pages/Measure/InclinometryTable.jsx b/src/pages/Well/Measure/InclinometryTable.jsx
old mode 100755
new mode 100644
similarity index 97%
rename from src/pages/Measure/InclinometryTable.jsx
rename to src/pages/Well/Measure/InclinometryTable.jsx
index 18d1660..2725743
--- a/src/pages/Measure/InclinometryTable.jsx
+++ b/src/pages/Well/Measure/InclinometryTable.jsx
@@ -35,7 +35,7 @@ export const InclinometryTable = memo(({ group, visible, onClose }) => {
, [
+ makeItem('Мониторинг', 'telemetry', [], ),
+ makeItem('Сообщения', 'messages', [], ),
+ makeItem('Архив', 'archive', [], ),
+ makeItem('ННБ', 'dashboard_nnb', [], ),
+ makeItem('Операции', 'operations', [], ),
+ makeItem('Наработка', 'operation_time', [], ),
+ ]),
+ makeItem('Рапорта', 'reports', [], , [
+ makeItem('Диаграмма', 'diagram_report', [], ),
+ makeItem('Суточный рапорт', 'daily_report', [], ),
+ ]),
+ makeItem('Аналитика', 'analytics', [], , [
+ makeItem('Композитная скважина', 'composite', [], , [
+ makeItem('Статистика по скважинам', 'wells', [], ),
+ makeItem('Статистика по секциям', 'sections', [], ),
+ ]),
+ makeItem('Оценка по ЦБ', 'statistics', [], ),
+ ]),
+ makeItem('Операции по скважине', 'operations', [], , [
+ makeItem('TVD', 'tvd', [], ),
+ makeItem('Секции', 'sections', [], ),
+ makeItem('План', 'plan', [], ),
+ makeItem('Факт', 'fact', [], ),
+ makeItem('РТК', 'drillProcessFlow', [], ),
+ makeItem('Режимы', 'params', [], ),
+ ]),
+ makeItem('Документы', 'document', [], , [
+ makeItem('Растворный сервис', 'fluidService', [], ),
+ makeItem('Цементирование', 'cementing', [], ),
+ makeItem('ННБ', 'nnb', [], ),
+ makeItem('ГТИ', 'gti', [], ),
+ makeItem('Документы по скважине', 'documentsForWell', [], ),
+ makeItem('Супервайзер', 'supervisor', [], ),
+ makeItem('Мастер', 'master', [], ),
+ makeItem('Долотный сервис', 'toolService', [], ),
+ makeItem('Буровой подрядчик', 'drillService', [], ),
+ makeItem('Сервис по заканчиванию скважины', 'closingService', [], ),
+ ]),
+ makeItem('Измерения', 'measure', [], ),
+ makeItem('Программа бурения', 'drillingProgram', [], ),
+ makeItem('Дело скважины', 'well_case', [], ),
+]
+
+export const NavigationMenu = memo((props) => (
+
+))
+
+export default NavigationMenu
diff --git a/src/pages/Reports/DailyReport/ReportEditor.jsx b/src/pages/Well/Reports/DailyReport/ReportEditor.jsx
similarity index 99%
rename from src/pages/Reports/DailyReport/ReportEditor.jsx
rename to src/pages/Well/Reports/DailyReport/ReportEditor.jsx
index c39ef39..e77fc61 100644
--- a/src/pages/Reports/DailyReport/ReportEditor.jsx
+++ b/src/pages/Well/Reports/DailyReport/ReportEditor.jsx
@@ -374,7 +374,7 @@ export const ReportEditor = memo(({ visible, data, onDone, onCancel, checkIsDate
(
))
diff --git a/src/pages/Telemetry/Operations/TargetEditor.jsx b/src/pages/Well/Telemetry/Operations/TargetEditor.jsx
similarity index 99%
rename from src/pages/Telemetry/Operations/TargetEditor.jsx
rename to src/pages/Well/Telemetry/Operations/TargetEditor.jsx
index 1df0c9a..69f49cf 100644
--- a/src/pages/Telemetry/Operations/TargetEditor.jsx
+++ b/src/pages/Well/Telemetry/Operations/TargetEditor.jsx
@@ -96,7 +96,7 @@ export const TargetEditor = memo(({ loading, onChange }) => {
centered
width={1000}
footer={null}
- visible={showModal}
+ open={showModal}
onCancel={onModalCancel}
title={'Цели бурения'}
>
diff --git a/src/pages/Telemetry/Operations/index.jsx b/src/pages/Well/Telemetry/Operations/index.jsx
similarity index 95%
rename from src/pages/Telemetry/Operations/index.jsx
rename to src/pages/Well/Telemetry/Operations/index.jsx
index af06d26..fd34730 100644
--- a/src/pages/Telemetry/Operations/index.jsx
+++ b/src/pages/Well/Telemetry/Operations/index.jsx
@@ -1,11 +1,12 @@
import { memo, useCallback, useEffect, useMemo, useState } from 'react'
-import { Empty, InputNumber, Select } from 'antd'
+import { InputNumber, Select } from 'antd'
import moment from 'moment'
import { useWell } from '@asb/context'
import LoaderPortal from '@components/LoaderPortal'
import { DateRangeWrapper } from '@components/Table'
import { invokeWebApiWrapperAsync } from '@components/factory'
+import { unique } from '@utils/filters'
import { getPermissions, arrayOrDefault, range, wrapPrivateComponent, pretify } from '@utils'
import { DetectedOperationService, DrillerService, TelemetryDataSaubService } from '@api'
@@ -16,7 +17,6 @@ import OperationsChart from './OperationsChart'
import OperationsTable from './OperationsTable'
import '@styles/detected_operations.less'
-import { unique } from '@asb/utils/filters'
const Operations = memo(() => {
const [isLoading, setIsLoading] = useState(false)
@@ -161,11 +161,4 @@ const Operations = memo(() => {
)
})
-export default wrapPrivateComponent(Operations, {
- requirements: [
- 'DetectedOperation.get',
- 'TelemetryDataSaub.get',
- ],
- title: 'Операции',
- route: 'operations',
-})
+export default wrapPrivateComponent(Operations, { requirements: ['DetectedOperation.get', 'TelemetryDataSaub.get'] })
diff --git a/src/pages/Telemetry/TelemetryView/ActiveMessagesOnline.jsx b/src/pages/Well/Telemetry/TelemetryView/ActiveMessagesOnline.jsx
old mode 100755
new mode 100644
similarity index 100%
rename from src/pages/Telemetry/TelemetryView/ActiveMessagesOnline.jsx
rename to src/pages/Well/Telemetry/TelemetryView/ActiveMessagesOnline.jsx
diff --git a/src/pages/Telemetry/TelemetryView/CustomColumn.jsx b/src/pages/Well/Telemetry/TelemetryView/CustomColumn.jsx
old mode 100755
new mode 100644
similarity index 100%
rename from src/pages/Telemetry/TelemetryView/CustomColumn.jsx
rename to src/pages/Well/Telemetry/TelemetryView/CustomColumn.jsx
diff --git a/src/pages/Telemetry/TelemetryView/ModeDisplay.jsx b/src/pages/Well/Telemetry/TelemetryView/ModeDisplay.jsx
old mode 100755
new mode 100644
similarity index 100%
rename from src/pages/Telemetry/TelemetryView/ModeDisplay.jsx
rename to src/pages/Well/Telemetry/TelemetryView/ModeDisplay.jsx
diff --git a/src/pages/Telemetry/TelemetryView/RigMnemo.jsx b/src/pages/Well/Telemetry/TelemetryView/RigMnemo.jsx
old mode 100755
new mode 100644
similarity index 100%
rename from src/pages/Telemetry/TelemetryView/RigMnemo.jsx
rename to src/pages/Well/Telemetry/TelemetryView/RigMnemo.jsx
diff --git a/src/pages/Telemetry/TelemetryView/Setpoints/SetpointSender.jsx b/src/pages/Well/Telemetry/TelemetryView/Setpoints/SetpointSender.jsx
old mode 100755
new mode 100644
similarity index 99%
rename from src/pages/Telemetry/TelemetryView/Setpoints/SetpointSender.jsx
rename to src/pages/Well/Telemetry/TelemetryView/Setpoints/SetpointSender.jsx
index 0d7bcf4..537ed29
--- a/src/pages/Telemetry/TelemetryView/Setpoints/SetpointSender.jsx
+++ b/src/pages/Well/Telemetry/TelemetryView/Setpoints/SetpointSender.jsx
@@ -80,7 +80,7 @@ export const SetpointSender = memo(({ onClose, visible, setpointNames }) => {
diff --git a/src/pages/Telemetry/TelemetryView/Setpoints/index.jsx b/src/pages/Well/Telemetry/TelemetryView/Setpoints/index.jsx
old mode 100755
new mode 100644
similarity index 99%
rename from src/pages/Telemetry/TelemetryView/Setpoints/index.jsx
rename to src/pages/Well/Telemetry/TelemetryView/Setpoints/index.jsx
index 828f61c..a5822de
--- a/src/pages/Telemetry/TelemetryView/Setpoints/index.jsx
+++ b/src/pages/Well/Telemetry/TelemetryView/Setpoints/index.jsx
@@ -89,7 +89,7 @@ export const Setpoints = memo(({ ...other }) => {
>
)}
- visible={isModalVisible}
+ open={isModalVisible}
onCancel={() => setIsModalVisible(false)}
footer={null}
>
diff --git a/src/pages/Telemetry/TelemetryView/UserOfWells.jsx b/src/pages/Well/Telemetry/TelemetryView/UserOfWells.jsx
old mode 100755
new mode 100644
similarity index 100%
rename from src/pages/Telemetry/TelemetryView/UserOfWells.jsx
rename to src/pages/Well/Telemetry/TelemetryView/UserOfWells.jsx
diff --git a/src/pages/Telemetry/TelemetryView/WirelineRunOut.jsx b/src/pages/Well/Telemetry/TelemetryView/WirelineRunOut.jsx
similarity index 95%
rename from src/pages/Telemetry/TelemetryView/WirelineRunOut.jsx
rename to src/pages/Well/Telemetry/TelemetryView/WirelineRunOut.jsx
index d3ef138..fd98f71 100644
--- a/src/pages/Telemetry/TelemetryView/WirelineRunOut.jsx
+++ b/src/pages/Well/Telemetry/TelemetryView/WirelineRunOut.jsx
@@ -33,7 +33,7 @@ export const WirelineRunOut = memo(() => {
return (
)
diff --git a/src/pages/Telemetry/TelemetryView/cursorRender.jsx b/src/pages/Well/Telemetry/TelemetryView/cursorRender.jsx
similarity index 100%
rename from src/pages/Telemetry/TelemetryView/cursorRender.jsx
rename to src/pages/Well/Telemetry/TelemetryView/cursorRender.jsx
diff --git a/src/pages/Telemetry/TelemetryView/index.jsx b/src/pages/Well/Telemetry/TelemetryView/index.jsx
old mode 100755
new mode 100644
similarity index 100%
rename from src/pages/Telemetry/TelemetryView/index.jsx
rename to src/pages/Well/Telemetry/TelemetryView/index.jsx
diff --git a/src/pages/Well/Telemetry/index.jsx b/src/pages/Well/Telemetry/index.jsx
new file mode 100644
index 0000000..e893433
--- /dev/null
+++ b/src/pages/Well/Telemetry/index.jsx
@@ -0,0 +1,27 @@
+import { FundViewOutlined } from '@ant-design/icons'
+import { Outlet } from 'react-router-dom'
+import { memo, useMemo } from 'react'
+
+import { RootPathContext, useRootPath } from '@asb/context'
+import { wrapPrivateComponent } from '@utils'
+
+import '@styles/index.css'
+
+const Telemetry = memo(() => {
+ const root = useRootPath()
+ const rootPath = useMemo(() => `${root}/telemetry`, [root])
+
+ return (
+
+
+
+ )
+})
+
+export default wrapPrivateComponent(Telemetry, {
+ requirements: [],
+ icon: ,
+ title: 'Телеметрия',
+ route: 'telemetry/*',
+ key: 'telemetry',
+})
diff --git a/src/pages/WellCase/HistoryTable.jsx b/src/pages/Well/WellCase/HistoryTable.jsx
similarity index 100%
rename from src/pages/WellCase/HistoryTable.jsx
rename to src/pages/Well/WellCase/HistoryTable.jsx
diff --git a/src/pages/WellCase/WellCaseEditor.jsx b/src/pages/Well/WellCase/WellCaseEditor.jsx
similarity index 99%
rename from src/pages/WellCase/WellCaseEditor.jsx
rename to src/pages/Well/WellCase/WellCaseEditor.jsx
index e8ef061..dcc287c 100644
--- a/src/pages/WellCase/WellCaseEditor.jsx
+++ b/src/pages/Well/WellCase/WellCaseEditor.jsx
@@ -117,7 +117,7 @@ export const WellCaseEditor = memo(({ categories: currentCategories, show, onClo
{
}, [well])
const columns = useMemo(() => [
- makeTextColumn('Категория', 'nameCategory'),
+ makeTextColumn('Категория', 'nameCategory', undefined, undefined, undefined, { width: 300 }),
makeColumn('Файл', 'file', {
render: (file, category) => (
@@ -59,10 +59,12 @@ const WellCase = memo(() => {
)}
),
+ width: 300,
}),
- makeDateColumn('Дата загрузки', 'uploadDate'),
+ makeDateColumn('Дата загрузки', 'uploadDate', undefined, undefined, { width: 150 }),
makeColumn('Ответственные', 'publishers', {
- render: (publishers) => publishers?.map((user) => ),
+ render: (publishers) => publishers?.map((user, i) => ),
+ width: 200,
}),
], [well, updateTable])
@@ -92,6 +94,7 @@ const WellCase = memo(() => {
pagination={false}
dataSource={categories}
expandable={expandable}
+ scroll={{ x: true }}
/>
diff --git a/src/pages/WellOperations/DrillProcessFlow.jsx b/src/pages/Well/WellOperations/DrillProcessFlow.jsx
old mode 100755
new mode 100644
similarity index 100%
rename from src/pages/WellOperations/DrillProcessFlow.jsx
rename to src/pages/Well/WellOperations/DrillProcessFlow.jsx
diff --git a/src/pages/Well/WellOperations/OperationEditor/Fact.jsx b/src/pages/Well/WellOperations/OperationEditor/Fact.jsx
new file mode 100644
index 0000000..3671de2
--- /dev/null
+++ b/src/pages/Well/WellOperations/OperationEditor/Fact.jsx
@@ -0,0 +1,14 @@
+import { wrapPrivateComponent } from '@utils'
+
+import WellOperationsEditor from './WellOperationsEditor'
+
+export const WellOperationsEditorFact = wrapPrivateComponent(
+ () => ,
+ {
+ requirements: [ 'WellOperation.get' ],
+ title: 'Факт',
+ route: 'fact',
+ }
+)
+
+export default WellOperationsEditorFact
diff --git a/src/pages/WellOperations/ImportExportBar.jsx b/src/pages/Well/WellOperations/OperationEditor/ImportExportBar.jsx
old mode 100755
new mode 100644
similarity index 98%
rename from src/pages/WellOperations/ImportExportBar.jsx
rename to src/pages/Well/WellOperations/OperationEditor/ImportExportBar.jsx
index 3776ffd..3cc574a
--- a/src/pages/WellOperations/ImportExportBar.jsx
+++ b/src/pages/Well/WellOperations/OperationEditor/ImportExportBar.jsx
@@ -48,7 +48,7 @@ export const ImportExportBar = memo(({ well: givenWell, onImported, disabled })
setIsImportModalVisible(false)}
footer={null}
>
diff --git a/src/pages/WellOperations/ImportOperations.jsx b/src/pages/Well/WellOperations/OperationEditor/ImportOperations.jsx
old mode 100755
new mode 100644
similarity index 100%
rename from src/pages/WellOperations/ImportOperations.jsx
rename to src/pages/Well/WellOperations/OperationEditor/ImportOperations.jsx
diff --git a/src/pages/Well/WellOperations/OperationEditor/Plan.jsx b/src/pages/Well/WellOperations/OperationEditor/Plan.jsx
new file mode 100644
index 0000000..240a189
--- /dev/null
+++ b/src/pages/Well/WellOperations/OperationEditor/Plan.jsx
@@ -0,0 +1,14 @@
+import { wrapPrivateComponent } from '@utils'
+
+import WellOperationsEditor from './WellOperationsEditor'
+
+export const WellOperationsEditorPlan = wrapPrivateComponent(
+ () => ,
+ {
+ requirements: [ 'WellOperation.get' ],
+ title: 'План',
+ route: 'plan',
+ }
+)
+
+export default WellOperationsEditorPlan
diff --git a/src/pages/WellOperations/WellOperationsEditor.jsx b/src/pages/Well/WellOperations/OperationEditor/WellOperationsEditor.jsx
old mode 100755
new mode 100644
similarity index 90%
rename from src/pages/WellOperations/WellOperationsEditor.jsx
rename to src/pages/Well/WellOperations/OperationEditor/WellOperationsEditor.jsx
index 5ac3cfc..653ec16
--- a/src/pages/WellOperations/WellOperationsEditor.jsx
+++ b/src/pages/Well/WellOperations/OperationEditor/WellOperationsEditor.jsx
@@ -3,7 +3,7 @@ import { Input } from 'antd'
import { useLocation } from 'react-router-dom'
import { useState, useEffect, memo, useMemo, useCallback } from 'react'
-import { useWell } from '@asb/context'
+import { useTopRightBlock, useWell } from '@asb/context'
import {
EditableTable,
makeColumn,
@@ -17,9 +17,11 @@ import {
} from '@components/Table'
import LoaderPortal from '@components/LoaderPortal'
import { invokeWebApiWrapperAsync } from '@components/factory'
-import { arrayOrDefault, wrapPrivateComponent } from '@utils'
+import { arrayOrDefault } from '@utils'
import { WellOperationService } from '@api'
+import ImportExportBar from './ImportExportBar'
+
const { TextArea } = Input
const basePageSize = 160
@@ -51,13 +53,14 @@ const generateColumns = (showNpt = false, categories = [], sectionTypes = []) =>
makeTextColumn('Комментарий', 'comment', null, null, null, { editable: true, input: }),
].filter(Boolean)
-const WellOperationsEditor = memo(({ idType, showNpt, ...other }) => {
+export const WellOperationsEditor = memo(({ idType, showNpt, ...other }) => {
const [pageNumAndPageSize, setPageNumAndPageSize] = useState({ current: 1, pageSize: basePageSize })
const [paginationTotal, setPaginationTotal] = useState(0)
const [operations, setOperations] = useState([])
const [showLoader, setShowLoader] = useState(false)
const [well] = useWell()
+ const setTopRightBlock = useTopRightBlock()
const [categories, setCategories] = useState([])
const [sectionTypes, setSectionTypes] = useState([])
@@ -70,21 +73,6 @@ const WellOperationsEditor = memo(({ idType, showNpt, ...other }) => {
return arrayOrDefault(query.get('selectedId')?.split(',')?.map(parseInt))
}, [location])
- useEffect(() => {
- invokeWebApiWrapperAsync(
- async () => {
- const categories = arrayOrDefault(await WellOperationService.getCategories(well.id))
- setCategories(categories.map((item) => ({ value: item.id, label: item.name })))
-
- const sectionTypes = Object.entries(await WellOperationService.getSectionTypes(well.id) ?? {})
- setSectionTypes(sectionTypes.map(([id, label]) => ({ value: parseInt(id), label })))
- },
- setShowLoader,
- `Не удалось загрузить список операций`,
- { actionName: 'Получение списка операций по скважине', well }
- )
- }, [well])
-
const updateOperations = useCallback(() => invokeWebApiWrapperAsync(
async () => {
const skip = ((pageNumAndPageSize.current - 1) * pageNumAndPageSize.pageSize) || 0
@@ -102,10 +90,6 @@ const WellOperationsEditor = memo(({ idType, showNpt, ...other }) => {
{ actionName: 'Получение списка операций', well }
), [well, idType, pageNumAndPageSize])
- useEffect(() => {
- updateOperations()
- }, [updateOperations])
-
const onRow = useCallback((record) => {
if (selectedIds?.includes(record.id))
return { style: { background: '#BF0000A0' } }
@@ -135,6 +119,31 @@ const WellOperationsEditor = memo(({ idType, showNpt, ...other }) => {
}
}, [updateOperations, well.id, recordParser])
+ useEffect(() => {
+ updateOperations()
+ }, [updateOperations])
+
+ useEffect(() => {
+ invokeWebApiWrapperAsync(
+ async () => {
+ const categories = arrayOrDefault(await WellOperationService.getCategories(well.id))
+ setCategories(categories.map((item) => ({ value: item.id, label: item.name })))
+
+ const sectionTypes = Object.entries(await WellOperationService.getSectionTypes(well.id) ?? {})
+ setSectionTypes(sectionTypes.map(([id, label]) => ({ value: parseInt(id), label })))
+ },
+ setShowLoader,
+ `Не удалось загрузить список операций`,
+ { actionName: 'Получение списка операций по скважине', well }
+ )
+ }, [well])
+
+ useEffect(() => {
+ setTopRightBlock(
+
+ )
+ }, [well, setTopRightBlock, updateOperations])
+
return (
{
)
})
-export const WellOperationsEditorPlan = wrapPrivateComponent(
- () => ,
- {
- requirements: [ 'WellOperation.get' ],
- title: 'План',
- route: 'plan',
- }
-)
-
-export const WellOperationsEditorFact = wrapPrivateComponent(
- () => ,
- {
- requirements: [ 'WellOperation.get' ],
- title: 'Факт',
- route: 'fact',
- }
-)
+export default WellOperationsEditor
diff --git a/src/pages/WellOperations/Tvd/AdditionalTables.jsx b/src/pages/Well/WellOperations/Tvd/AdditionalTables.jsx
old mode 100755
new mode 100644
similarity index 100%
rename from src/pages/WellOperations/Tvd/AdditionalTables.jsx
rename to src/pages/Well/WellOperations/Tvd/AdditionalTables.jsx
diff --git a/src/pages/WellOperations/Tvd/NetGraphExport.jsx b/src/pages/Well/WellOperations/Tvd/NetGraphExport.jsx
old mode 100755
new mode 100644
similarity index 100%
rename from src/pages/WellOperations/Tvd/NetGraphExport.jsx
rename to src/pages/Well/WellOperations/Tvd/NetGraphExport.jsx
diff --git a/src/pages/WellOperations/Tvd/NptTable.jsx b/src/pages/Well/WellOperations/Tvd/NptTable.jsx
old mode 100755
new mode 100644
similarity index 100%
rename from src/pages/WellOperations/Tvd/NptTable.jsx
rename to src/pages/Well/WellOperations/Tvd/NptTable.jsx
diff --git a/src/pages/WellOperations/Tvd/StatExport.jsx b/src/pages/Well/WellOperations/Tvd/StatExport.jsx
similarity index 100%
rename from src/pages/WellOperations/Tvd/StatExport.jsx
rename to src/pages/Well/WellOperations/Tvd/StatExport.jsx
diff --git a/src/pages/WellOperations/Tvd/TLChart.jsx b/src/pages/Well/WellOperations/Tvd/TLChart.jsx
similarity index 98%
rename from src/pages/WellOperations/Tvd/TLChart.jsx
rename to src/pages/Well/WellOperations/Tvd/TLChart.jsx
index b173992..e34ba61 100644
--- a/src/pages/WellOperations/Tvd/TLChart.jsx
+++ b/src/pages/Well/WellOperations/Tvd/TLChart.jsx
@@ -10,7 +10,7 @@ import { DetectedOperationService } from '@api'
import { unique } from '@utils/filters'
import { formatDate } from '@utils'
-import { makeTooltipRender } from '@pages/Telemetry/Operations/OperationsChart'
+import { makeTooltipRender } from '../../Telemetry/Operations/OperationsChart'
import { makeGetColor } from '.'
import '@styles/d3.less'
diff --git a/src/pages/WellOperations/Tvd/TLPie.jsx b/src/pages/Well/WellOperations/Tvd/TLPie.jsx
similarity index 100%
rename from src/pages/WellOperations/Tvd/TLPie.jsx
rename to src/pages/Well/WellOperations/Tvd/TLPie.jsx
diff --git a/src/pages/WellOperations/Tvd/index.jsx b/src/pages/Well/WellOperations/Tvd/index.jsx
similarity index 96%
rename from src/pages/WellOperations/Tvd/index.jsx
rename to src/pages/Well/WellOperations/Tvd/index.jsx
index f295d49..e41ba75 100644
--- a/src/pages/WellOperations/Tvd/index.jsx
+++ b/src/pages/Well/WellOperations/Tvd/index.jsx
@@ -4,7 +4,7 @@ import { Switch, Segmented } from 'antd'
import { Link } from 'react-router-dom'
import * as d3 from 'd3'
-import { useWell } from '@asb/context'
+import { useTopRightBlock, useWell } from '@asb/context'
import { D3Chart } from '@components/d3'
import LoaderPortal from '@components/LoaderPortal'
import { invokeWebApiWrapperAsync } from '@components/factory'
@@ -170,6 +170,8 @@ const Tvd = memo(({ well: givenWell, title, ...other }) => {
const [pointsEnabled, setPointsEnabled] = useState(true)
const [selectedTab, setSelectedTab] = useState('Скрыть')
+ const setTopRightBlock = useTopRightBlock()
+
const [wellContext] = useWell()
const well = useMemo(() => givenWell ?? wellContext, [givenWell, wellContext])
@@ -227,11 +229,22 @@ const Tvd = memo(({ well: givenWell, title, ...other }) => {
)
}, [well])
+ useEffect(() => {
+ setTopRightBlock(
+
+
+
+
+ )
+ }, [well, setTopRightBlock])
+
return (
{title || 'График Глубина-день'}
+
+
-
{
title={'Нажмите для переключения видимости засечек на графиках'}
/>
-
-
-
-
{
+ const root = useRootPath()
+ const rootPath = useMemo(() => `${root}/${properties.key}`, [root])
+
+ return(
+
+
+
+ )
+})
+
+export default wrapPrivateComponent(WellOperations, properties)
diff --git a/src/pages/Well/index.jsx b/src/pages/Well/index.jsx
new file mode 100644
index 0000000..4725aa9
--- /dev/null
+++ b/src/pages/Well/index.jsx
@@ -0,0 +1,146 @@
+import { lazy, memo, useCallback, useEffect, useMemo, useState } from 'react'
+import { Navigate, Route, Routes, useLocation, useParams } from 'react-router-dom'
+
+import { WellContext, RootPathContext, useRootPath, useLayoutProps, TopRightBlockContext } from '@asb/context'
+import { invokeWebApiWrapperAsync } from '@components/factory'
+import { MenuBreadcrumbItems } from '@components/MenuBreadcrumb'
+import { NoAccessComponent, wrapPrivateComponent } from '@utils'
+import { WellService } from '@api'
+
+import { NavigationMenu, menuItems } from './NavigationMenu'
+
+import '@styles/index.css'
+
+const Measure = lazy(() => import('./Measure'))
+const Reports = lazy(() => import('./Reports'))
+const WellCase = lazy(() => import('./WellCase'))
+const Analytics = lazy(() => import('./Analytics'))
+const Documents = lazy(() => import('./Documents'))
+const Telemetry = lazy(() => import('./Telemetry'))
+const WellOperations = lazy(() => import('./WellOperations'))
+const DrillingProgram = lazy(() => import('./DrillingProgram'))
+
+const Tvd = lazy(() => import('./WellOperations/Tvd'))
+const WellDrillParams = lazy(() => import('./WellOperations/WellDrillParams'))
+const DrillProcessFlow = lazy(() => import('./WellOperations/DrillProcessFlow'))
+const WellSectionsStat = lazy(() => import('./WellOperations/WellSectionsStat'))
+const WellOperationsEditorFact = lazy(() => import('./WellOperations/OperationEditor/Fact'))
+const WellOperationsEditorPlan = lazy(() => import('./WellOperations/OperationEditor/Plan'))
+
+const Archive = lazy(() => import('./Telemetry/Archive'))
+const Messages = lazy(() => import('./Telemetry/Messages'))
+const Operations = lazy(() => import('./Telemetry/Operations'))
+const DashboardNNB = lazy(() => import('./Telemetry/DashboardNNB'))
+const TelemetryView = lazy(() => import('./Telemetry/TelemetryView'))
+const OperationTime = lazy(() => import('./Telemetry/OperationTime'))
+
+const DailyReport = lazy(() => import('./Reports/DailyReport'))
+const DiagramReport = lazy(() => import('./Reports/DiagramReport'))
+
+const Statistics = lazy(() => import('./Analytics/Statistics'))
+const WellCompositeEditor = lazy(() => import('./Analytics/WellCompositeEditor'))
+
+const Well = memo(() => {
+ const { idWell } = useParams()
+
+ const location = useLocation()
+
+ const [well, setWell] = useState({ id: idWell })
+ const [topRightBlock, setTopRightBlock] = useState()
+
+ const root = useRootPath()
+ const rootPath = useMemo(() => `${root}/well/${idWell}`, [root, idWell])
+
+ const setLayoutProps = useLayoutProps()
+
+ const updateWell = useCallback((data) => invokeWebApiWrapperAsync(
+ async () => {
+ const newWell = { ...well, ...data }
+ await WellService.updateWell(newWell)
+ setWell(newWell)
+ },
+ undefined,
+ `Не удалось изменить данные скважины`,
+ { actionName: 'Изменение данных скважины', well }
+ ), [well])
+
+ useEffect(() => {
+ invokeWebApiWrapperAsync(
+ async () => {
+ const well = await WellService.get(idWell)
+ setWell(well ?? { id: idWell })
+ },
+ undefined,
+ 'Не удалось получить данные по скважине'
+ )
+ }, [idWell])
+
+ useEffect(() => setLayoutProps({
+ sider: ,
+ breadcrumb: ,
+ topRightBlock: topRightBlock,
+ }), [well, setLayoutProps, topRightBlock])
+
+ useEffect(() => setTopRightBlock(undefined), [location])
+
+ return (
+
+
+
+
+ } />
+ } />
+
+ }>
+ } />
+ } />
+
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+
+ }>
+ } />
+ } />
+
+ } />
+ } />
+
+ }>
+ } />
+ } />
+
+ } />
+ } />
+
+ }>
+ } />
+ } />
+
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+
+ } />
+ } />
+ } />
+ } />
+
+
+
+
+ )
+})
+
+export default wrapPrivateComponent(Well, {
+ requirements: [],
+ title: 'Скважина',
+ route: 'well/:idWell/*',
+ key: 'well',
+})
diff --git a/src/pages/WellOperations/index.jsx b/src/pages/WellOperations/index.jsx
deleted file mode 100755
index 2f59865..0000000
--- a/src/pages/WellOperations/index.jsx
+++ /dev/null
@@ -1,78 +0,0 @@
-import { useNavigate, useLocation, Route, Routes, Navigate } from 'react-router-dom'
-import { memo, useCallback, useMemo } from 'react'
-import { Layout } from 'antd'
-import {
- BarChartOutlined,
- BuildOutlined,
- ControlOutlined,
- LineChartOutlined,
- TableOutlined,
-} from '@ant-design/icons'
-
-import { RootPathContext, useRootPath } from '@asb/context'
-import { Flex } from '@components/Grid'
-import { PrivateMenu } from '@components/Private'
-import { getTabname, NoAccessComponent, wrapPrivateComponent } from '@utils'
-
-import Tvd from './Tvd'
-import { ImportExportBar } from './ImportExportBar'
-import { WellDrillParams } from './WellDrillParams'
-import { DrillProcessFlow } from './DrillProcessFlow'
-import { WellSectionsStat } from './WellSectionsStat'
-import { WellOperationsEditorPlan, WellOperationsEditorFact } from './WellOperationsEditor'
-
-const { Content } = Layout
-
-const properties = {
- requirements: [],
- title: 'Операции по скважине',
- route: 'operations/*',
- key: 'operations',
-}
-
-const WellOperations = memo(() => {
- const tab = getTabname()
- const navigate = useNavigate()
- const location = useLocation()
- const root = useRootPath()
- const rootPath = useMemo(() => `${root}/${properties.key}`, [root])
-
- const onImported = useCallback(() =>
- navigate(`${rootPath}`, { state: { from: location.pathname }})
- , [navigate, location, rootPath])
-
- const isIEBarDisabled = useMemo(() => !['plan', 'fact'].includes(tab), [tab])
-
- return(
-
-
-
- } />
- } key={'sections'} title={'Секции'} />
- } />
- } />
- } key={'drillProcessFlow'} title={'РТК'} />
- } key={'params'} title={'Режимы'} />
-
-
-
-
-
-
- } />
- } />
-
- } />
- } />
- } />
- } />
- } />
- } />
-
-
-
-
- )
-})
-
-export default wrapPrivateComponent(WellOperations, properties)
diff --git a/src/pages/AccessDenied.jsx b/src/pages/public/AccessDenied.jsx
old mode 100755
new mode 100644
similarity index 100%
rename from src/pages/AccessDenied.jsx
rename to src/pages/public/AccessDenied.jsx
diff --git a/src/pages/Login.jsx b/src/pages/public/Login.jsx
old mode 100755
new mode 100644
similarity index 100%
rename from src/pages/Login.jsx
rename to src/pages/public/Login.jsx
diff --git a/src/pages/Register.jsx b/src/pages/public/Register.jsx
old mode 100755
new mode 100644
similarity index 100%
rename from src/pages/Register.jsx
rename to src/pages/public/Register.jsx
diff --git a/src/services/signalr/index.ts b/src/services/signalr/index.ts
index 5a8ed93..8c2d684 100755
--- a/src/services/signalr/index.ts
+++ b/src/services/signalr/index.ts
@@ -1,6 +1,6 @@
import { HubConnection, HubConnectionBuilder, HubConnectionState } from '@microsoft/signalr'
-import { getUserToken, isDev } from '@utils'
+import { getUser, isDev } from '@utils'
import { makeTaskQueue } from '@utils/queue'
const queue = makeTaskQueue()
@@ -8,8 +8,8 @@ const queue = makeTaskQueue()
// SignalR js api:
//https://docs.microsoft.com/ru-ru/javascript/api/@aspnet/signalr/?view=signalr-js-latest
-const ConnectionOptions = {
- accessTokenFactory: () => getUserToken() ?? '',
+const ConnectionOptions = {
+ accessTokenFactory: () => getUser().token ?? '',
transport: 1,
}
diff --git a/src/styles/App.less b/src/styles/App.less
index c4399b5..90db107 100755
--- a/src/styles/App.less
+++ b/src/styles/App.less
@@ -1,142 +1,119 @@
@import './loader.css';
-@header-height: 64px;
-@layout-min-height: calc(100vh - @header-height);
-
#root, .app{
- min-height:100%;
+ min-height:100%;
}
.ant-layout{
- flex: 1;
+ flex: 1;
- > .ant-menu {
- flex: 0;
- }
+ > .ant-menu {
+ flex: 0;
+ }
}
html {
- display: flex;
- height: 100%;
+ display: flex;
+ height: 100%;
}
.mt-30px {
- margin-top: 30px;
+ margin-top: 30px;
}
.ml-30px {
- margin-left: 30px;
+ margin-left: 30px;
}
.login_page {
- position: absolute;
- height: 100%;
- width: 100%;
- display: flex;
- justify-content: center;
- align-items: center;
- padding: 24px;
- background-color: #9d9d9d;
+ position: absolute;
+ height: 100%;
+ width: 100%;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ padding: 24px;
+ background-color: #9d9d9d;
}
.shadow{
- box-shadow: 1px 1px 4px #00000033;
-}
-
-.header {
- display: flex;
- align-items: center;
- justify-content: space-around;
- gap: 50px;
- height: @header-height;
-}
-
-.header .logo {
- padding: 8px 24px;
- margin: 0 10px;
- margin-bottom: 2px;
-}
-
-.header .title{
- flex-grow: 1;
- color: #fff;
- padding-left: calc(100vw / 2 - 400px);
-}
-
-.header button{
- color: rgb(255, 255, 255);
- background-color: rgba(0, 0, 0, 0.1);
- border: 1px solid rgba(0, 0, 0, 0.2);
+ box-shadow: 1px 1px 4px #00000033;
}
.small-font {
- font-size: 12px;
+ font-size: 12px;
}
.yellow-background {
- background-color: #FFFF99 !important;
+ background-color: #FFFF99 !important;
}
.lightgray-background {
- background-color: #AFABAB !important;
+ background-color: #AFABAB !important;
}
.lightpurple-background {
- background-color: #CCCCFF !important;
+ background-color: #CCCCFF !important;
}
.lightorange-background {
- background-color: #FFCC99 !important;
+ background-color: #FFCC99 !important;
}
.ph-2 {
- padding: 2px 10px;
+ padding: 2px 10px;
}
.mh-2 {
- margin-left: 2px;
- margin-right: 2px;
+ margin-left: 2px;
+ margin-right: 2px;
}
.ant-layout-content {
- display: flex;
- flex-direction: column;
- align-items: stretch;
-}
-
-.sheet{
- padding: 5px 24px;
- min-height: calc(@layout-min-height - 15px); // 280px;
- margin: 0 15px 15px 15px;
-}
-
-.site-layout-background {
- background: #fff;
+ display: flex;
+ flex-direction: column;
+ align-items: stretch;
}
.border_small{
- border: 1px solid rgba(0, 0, 0, 0.05);
+ border: 1px solid rgba(0, 0, 0, 0.05);
}
.menu-title,
.chart-footer {
- display: flex;
+ display: flex;
}
.submit-button {
- border-radius: 5px;
- font-weight: bold;
- text-align: center;
- margin: 0 5px 5px 0;
+ border-radius: 5px;
+ font-weight: bold;
+ text-align: center;
+ margin: 0 5px 5px 0;
}
.well_menu {
- margin-top: 0;
- padding-top: 0;
- height: 100%;
- border-right: 0;
+ margin-top: 0;
+ padding-top: 0;
+ border-right: 0;
}
tr.table_row_size {
- height: 10px;
+ height: 10px;
+}
+
+.hide-slider {
+ scrollbar-width: none;
+ -ms-overflow-style: none;
+
+ &::-webkit-scrollbar {
+ display: none;
+ }
+}
+
+.centered {
+ display: flex;
+ width: 100%;
+ height: 100%;
+ justify-content: center;
+ align-items: center;
}
diff --git a/src/styles/components/color_picker.less b/src/styles/components/color_picker.less
index aba100d..fd146dd 100644
--- a/src/styles/components/color_picker.less
+++ b/src/styles/components/color_picker.less
@@ -18,4 +18,4 @@
border: 1px solid black;
width: 20px;
height: 20px;
-}
\ No newline at end of file
+}
diff --git a/src/styles/d3.less b/src/styles/d3.less
index 90db40d..58b64d9 100644
--- a/src/styles/d3.less
+++ b/src/styles/d3.less
@@ -150,4 +150,4 @@
.asb-d3-chart .adaptive-tooltip {
font-size: 6px;
}
-}
\ No newline at end of file
+}
diff --git a/src/styles/dashboard_nnb.less b/src/styles/dashboard_nnb.less
index 6291a9b..7b47d6e 100644
--- a/src/styles/dashboard_nnb.less
+++ b/src/styles/dashboard_nnb.less
@@ -26,4 +26,4 @@
height: 13vh;
}
}
-}
\ No newline at end of file
+}
diff --git a/src/styles/detected_operations.less b/src/styles/detected_operations.less
index 1f624d5..8d906d0 100644
--- a/src/styles/detected_operations.less
+++ b/src/styles/detected_operations.less
@@ -37,4 +37,4 @@
& > .tooltip-label {
text-align: center;
}
-}
\ No newline at end of file
+}
diff --git a/src/styles/equipment_details.css b/src/styles/equipment_details.css
index 8ad648f..52e8db4 100755
--- a/src/styles/equipment_details.css
+++ b/src/styles/equipment_details.css
@@ -1,3 +1,3 @@
span.right-text {
float: right;
-}
\ No newline at end of file
+}
diff --git a/src/styles/index.css b/src/styles/index.css
index bde3eb8..53d4e5d 100755
--- a/src/styles/index.css
+++ b/src/styles/index.css
@@ -1,156 +1,156 @@
body {
- margin: 0;
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
- 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
- sans-serif;
- -webkit-font-smoothing: antialiased;
- -moz-osx-font-smoothing: grayscale;
+ margin: 0;
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
+ 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
+ sans-serif;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
}
.d-flex {
- display: flex;
+ display: flex;
}
.flex-direction-column {
- flex-direction: column;
+ flex-direction: column;
}
.d-inline {
- display: inline;
+ display: inline;
}
.d-none {
- display: none;
+ display: none;
}
.flex-1 {
- flex: 1;
+ flex: 1;
}
.w-15 {
- width: 15%
+ width: 15%
}
.w-33 {
- width: 33%
+ width: 33%
}
.w-50 {
- width: 50%
+ width: 50%
}
.w-100 {
- width: 100%
+ width: 100%
}
.m-0 {
- margin: 0;
+ margin: 0;
}
.mt-8px {
- margin-top: 8px;
+ margin-top: 8px;
}
.mt-20px {
- margin-top: 20px;
+ margin-top: 20px;
}
.mb-20px {
- margin-bottom: 20px;
+ margin-bottom: 20px;
}
.ml-5px {
- margin-left: 5px;
+ margin-left: 5px;
}
.ml-10px {
- margin-left: 10px;
+ margin-left: 10px;
}
.ml-30px {
- margin-left: 30px;
+ margin-left: 30px;
}
.h-100vh {
- height: calc(100vh - 64px);
+ height: 100vh;
}
.p-10 {
- padding: 10px;
+ padding: 10px;
}
.vertical-align-center {
- vertical-align: center;
+ vertical-align: center;
}
.text-align-center {
- text-align: center;
+ text-align: center;
}
.text-align-r-container {
- width: 100%;
- text-align: right;
+ width: 100%;
+ text-align: right;
}
code {
- font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
- monospace;
+ font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
+ monospace;
}
.linkDocuments {
- color: #000;
+ color: #000;
}
.linkDocuments:hover {
- color: #c32828;
+ color: #c32828;
}
.container{
- width: 100%;
+ width: 100%;
}
.login-button {
- width: 20%;
- margin: auto;
+ width: 20%;
+ margin: auto;
}
.register-button {
- width: 50%;
- margin: auto;
+ width: 50%;
+ margin: auto;
}
.first-column-title {
- display: flex;
- flex-direction: column;
- align-items: stretch;
- justify-content: space-between;
- position: relative;
- padding: 16px 0;
+ display: flex;
+ flex-direction: column;
+ align-items: stretch;
+ justify-content: space-between;
+ position: relative;
+ padding: 16px 0;
}
.noselect {
- -webkit-touch-callout: none; /* iOS Safari */
- -webkit-user-select: none; /* Safari */
- -khtml-user-select: none; /* Konqueror HTML */
- -moz-user-select: none; /* Old versions of Firefox */
- -ms-user-select: none; /* Internet Explorer/Edge */
- user-select: none; /* Non-prefixed version, currently
- supported by Chrome, Edge, Opera and Firefox */
+ -webkit-touch-callout: none; /* iOS Safari */
+ -webkit-user-select: none; /* Safari */
+ -khtml-user-select: none; /* Konqueror HTML */
+ -moz-user-select: none; /* Old versions of Firefox */
+ -ms-user-select: none; /* Internet Explorer/Edge */
+ user-select: none; /* Non-prefixed version, currently
+ supported by Chrome, Edge, Opera and Firefox */
}
.download-link {
- height: 32px;
- padding: 4px 15px;
+ height: 32px;
+ padding: 4px 15px;
}
.ant-table-cell:has(.color-pale-green) {
- background-color: #98fb98;
+ background-color: #98fb98;
}
.ant-table-tbody > tr > td.ant-table-cell-row-hover:has( > div.color-pale-green) {
- background: #98fb98;
+ background: #98fb98;
}
.color-pale-green {
- background-color: #98fb98;
+ background-color: #98fb98;
}
\ No newline at end of file
diff --git a/src/styles/layout.less b/src/styles/layout.less
new file mode 100644
index 0000000..4d5861f
--- /dev/null
+++ b/src/styles/layout.less
@@ -0,0 +1,128 @@
+@link-color: #FFFC;
+@active-bg: #c32828;
+@admin-bg: #900;
+@admin-active-bg: #413f3d;
+
+.no-select {
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+}
+
+.ant-menu-submenu-popup .ant-menu-sub {
+ color: @link-color;
+
+ & .ant-menu-item > span > a, & a {
+ color: @link-color;
+ }
+}
+
+.page-layout {
+ height: 100vh;
+
+ & .menu-sider {
+ overflow-x: hidden;
+ overflow-y: auto;
+ height: 100%;
+
+ & .ant-menu-submenu-selected {
+ &.ant-menu-submenu-vertical {
+ background-color: @active-bg;
+ }
+
+ &.ant-menu-submenu-inline {
+ background-color: inherit;
+ & .ant-menu-submenu-title {
+ color: @active-bg;
+ }
+ }
+ }
+
+ & .ant-menu-submenu-title > .ant-menu-title-content > a,
+ & .ant-menu .ant-menu-item,
+ & .ant-menu .ant-menu-item > span > a {
+ color: @link-color;
+ .no-select;
+ }
+
+ & .sider-content {
+ display: flex;
+ flex-direction: column;
+ align-items: stretch;
+ justify-content: start;
+ height: 100%;
+
+ & .sider-toogle {
+ display: flex;
+ padding: 0;
+ margin: 10px;
+ border: none;
+ outline: none;
+ background-color: transparent;
+ cursor: pointer;
+ overflow: hidden;
+
+ &:hover {
+ color: white;
+ }
+ }
+
+ & .scrollable {
+ flex: 1;
+ overflow-y: scroll;
+ }
+ }
+
+ & .ant-menu-dark .ant-menu-inline.ant-menu-sub, & .ant-menu {
+ background: transparent;
+ color: @link-color;
+ }
+ }
+
+ & .page-content {
+ overflow-y: auto;
+ background: white;
+
+ & .breadcrumb-block {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ gap: 15px;
+ padding: 0 15px 15px 15px;
+
+ & .ant-breadcrumb-link, .ant-breadcrumb-separator {
+ .no-select;
+ }
+ }
+
+ }
+
+ & .sheet{
+ padding: 15px;
+ // min-height: calc(@layout-min-height - 30px); // 280px;
+ overflow: visible;
+ // margin: 15px;
+ }
+
+ &-admin {
+ .header {
+ background-color: @admin-bg;
+ }
+
+ .menu-sider {
+ background-color: @admin-bg;
+ }
+
+ & .menu-sider .ant-menu-submenu-selected.ant-menu-submenu-inline .ant-menu-submenu-title {
+ color: white;
+ & .ant-menu-title-content > a {
+ color: white;
+ }
+ }
+ }
+}
+
+.site-layout-background {
+ background: #fff;
+}
diff --git a/src/styles/loader.css b/src/styles/loader.css
index e8b0844..23ab350 100755
--- a/src/styles/loader.css
+++ b/src/styles/loader.css
@@ -1,69 +1,69 @@
/* original from https://loading.io/css/ */
.lds-ripple {
- display: inline-block;
- position: absolute;
- width: 80px;
- height: 80px;
+ display: inline-block;
+ position: absolute;
+ width: 80px;
+ height: 80px;
}
.lds-ripple div {
- position: absolute;
- border: 4px solid rgb(226, 29, 29);
- opacity: 1;
- border-radius: 50%;
- animation: lds-ripple 1s cubic-bezier(0, 0.2, 0.8, 1) infinite;
+ position: absolute;
+ border: 4px solid rgb(226, 29, 29);
+ opacity: 1;
+ border-radius: 50%;
+ animation: lds-ripple 1s cubic-bezier(0, 0.2, 0.8, 1) infinite;
}
.lds-ripple div:nth-child(2) {
- animation-delay: -0.5s;
+ animation-delay: -0.5s;
}
@keyframes lds-ripple {
- 0% {
- top: 36px;
- left: 36px;
- width: 0;
- height: 0;
- opacity: 1;
- }
- 100% {
- top: 0px;
- left: 0px;
- width: 72px;
- height: 72px;
- opacity: 0;
- }
+ 0% {
+ top: 36px;
+ left: 36px;
+ width: 0;
+ height: 0;
+ opacity: 1;
+ }
+ 100% {
+ top: 0px;
+ left: 0px;
+ width: 72px;
+ height: 72px;
+ opacity: 0;
+ }
}
.loader-container{
- display: grid;
- grid-template-columns: 1fr 1fr 1fr;
+ display: grid;
+ grid-template-columns: 1fr 1fr 1fr;
}
.loader-content{
- grid-column-start: 1;
- grid-column-end: span 3;
- grid-row-start: 1;
+ grid-column-start: 1;
+ grid-column-end: span 3;
+ grid-row-start: 1;
}
.loader-overlay{
- grid-column-start: 1;
- grid-column-end: span 3;
- grid-row-start: 1;
- place-self: center;
- align-self: center;
- justify-self: center;
- z-index: 1;
- height: 80px;
- width: 80px;
- border-radius: 40px;
+ grid-column-start: 1;
+ grid-column-end: span 3;
+ grid-row-start: 1;
+ place-self: center;
+ align-self: center;
+ justify-self: center;
+ z-index: 1;
+ height: 80px;
+ width: 80px;
+ border-radius: 40px;
}
.loader-fade{
- grid-column-start: 1;
- grid-column-end: span 3;
- grid-row-start: 1;
- background-color: rgba(255, 255, 255, 0.4);
- align-self: stretch;
- justify-self: stretch;
- z-index: 1;
- box-shadow: 0px 0px 6px 5px rgba(255, 254, 254, 0.4);
+ grid-column-start: 1;
+ grid-column-end: span 3;
+ grid-row-start: 1;
+ background-color: rgba(255, 255, 255, 0.4);
+ align-self: stretch;
+ justify-self: stretch;
+ z-index: 1;
+ box-shadow: 0px 0px 6px 5px rgba(255, 254, 254, 0.4);
}
diff --git a/src/styles/message.less b/src/styles/message.less
index be78867..8785dbf 100644
--- a/src/styles/message.less
+++ b/src/styles/message.less
@@ -1,49 +1,49 @@
.event_message > td {
- font-size: 14px;
- padding: 1px 4px !important;
- border-bottom: 1px !important;
+ font-size: 14px;
+ padding: 1px 4px !important;
+ border-bottom: 1px !important;
}
.event_message .anticon{
- display: none;
+ display: none;
}
.event_message:hover a{
- text-decoration: underline;
+ text-decoration: underline;
}
.event_message:hover .anticon{
- display: inherit;
+ display: inherit;
}
.event_message_off {
- color: #505050;
- background: #b5b5b5;
+ color: #505050;
+ background: #b5b5b5;
}
.event_message_disabled {
- color: #656565;
- background: #b5b5b5;
+ color: #656565;
+ background: #b5b5b5;
}
.event_message_1 {
- color: white;
- background: #ff3737;
+ color: white;
+ background: #ff3737;
}
.event_message_2 {
- color: black;
- background: gold;
+ color: black;
+ background: gold;
}
.event_message_3 {
- color: #c0c0c0;
- background: #505060;
+ color: #c0c0c0;
+ background: #505060;
}
td.ant-table-column-sort {
- color: black;
- background-color: #fafafa;
+ color: black;
+ background-color: #fafafa;
}
.ant-table-tbody > tr > td.ant-table-cell-row-hover {
- color: black;
+ color: black;
}
diff --git a/src/styles/message_telemetry.css b/src/styles/message_telemetry.css
index 5eed9e1..d627755 100755
--- a/src/styles/message_telemetry.css
+++ b/src/styles/message_telemetry.css
@@ -1,30 +1,30 @@
.event_message {
- font-size: 14px;
+ font-size: 14px;
}
.event_message_off {
- color: #505050;
- background: #b5b5b5;
+ color: #505050;
+ background: #b5b5b5;
}
.event_message_disabled {
- color: #656565;
- background: #b5b5b5;
+ color: #656565;
+ background: #b5b5b5;
}
.event_message_1 {
- color: white;
- background: #ff3737;
+ color: white;
+ background: #ff3737;
}
.event_message_2 {
- color: black;
- background: gold;
+ color: black;
+ background: gold;
}
.event_message_3,
.event_message_3:hover {
- color: #c0c0c0;
- background: #505060;
- height: 1px;
-}
\ No newline at end of file
+ color: #c0c0c0;
+ background: #505060;
+ height: 1px;
+}
diff --git a/src/styles/smbo.css b/src/styles/smbo.css
index 5f6e5aa..9a86f6b 100755
--- a/src/styles/smbo.css
+++ b/src/styles/smbo.css
@@ -120,4 +120,4 @@
font-size: 75px;
margin-top: 5px;
align-items: center;
-}
\ No newline at end of file
+}
diff --git a/src/styles/tvd.less b/src/styles/tvd.less
index 6a672a5..9adbda4 100755
--- a/src/styles/tvd.less
+++ b/src/styles/tvd.less
@@ -6,19 +6,19 @@
min-height: 80vh;
.tvd-top {
+ margin: 0 15px;
display: flex;
align-items: center;
justify-content: space-between;
- margin-top: 20px;
.tvd-inputs {
display: flex;
align-items: center;
+ gap: 15px;
.tvd-input-group {
display: flex;
align-items: center;
- margin: 0 15px;
& > span {
margin-right: 5px;
diff --git a/src/styles/user_menu.less b/src/styles/user_menu.less
new file mode 100644
index 0000000..6089225
--- /dev/null
+++ b/src/styles/user_menu.less
@@ -0,0 +1,10 @@
+.user-menu {
+
+ & .profile-links {
+ display: flex;
+ flex-direction: column;
+ align-items: stretch;
+ gap: 10px;
+ margin-bottom: 10px;
+ }
+}
diff --git a/src/styles/wellTreeSelect.css b/src/styles/wellTreeSelect.css
index c889fd8..f5435d3 100755
--- a/src/styles/wellTreeSelect.css
+++ b/src/styles/wellTreeSelect.css
@@ -1,19 +1,19 @@
.header-tree-select {
- width: 300px
+ width: 300px
}
.header-tree-select *{
- color: #fff;
- font-size: 1rem;
+ color: #fff;
+ font-size: 1rem;
}
.header-tree-select{
- width: 300px;
- border: 1px solid rgba(255, 255, 255, 0.2);
- background-color: rgba(0, 0, 0, 0.3);
+ width: 300px;
+ border: 1px solid rgba(255, 255, 255, 0.2);
+ background-color: rgba(0, 0, 0, 0.3);
}
.header-tree-select:hover{
- border: 1px solid rgba(255, 255, 255, 0.8);
- background-color: rgba(0, 0, 0, 0.5);
-}
\ No newline at end of file
+ border: 1px solid rgba(255, 255, 255, 0.8);
+ background-color: rgba(0, 0, 0, 0.5);
+}
diff --git a/src/styles/well_composite.less b/src/styles/well_composite.less
new file mode 100644
index 0000000..ea64fc8
--- /dev/null
+++ b/src/styles/well_composite.less
@@ -0,0 +1,13 @@
+.avg-column {
+ & .avg-fill {
+ position: absolute;
+ right: 0;
+ top: 0;
+ height: 100%;
+ background-color: red;
+ }
+
+ & .avg-value {
+ position: relative;
+ }
+}
diff --git a/src/styles/widgets/base.less b/src/styles/widgets/base.less
index ee611c9..5a1988d 100644
--- a/src/styles/widgets/base.less
+++ b/src/styles/widgets/base.less
@@ -1,5 +1,5 @@
-
@size: 9.9vh;
+
.number_widget {
display: flex;
flex-direction: column;
diff --git a/src/utils/functions/numbers.tsx b/src/utils/functions/numbers.tsx
index 4de2a13..0a686f1 100644
--- a/src/utils/functions/numbers.tsx
+++ b/src/utils/functions/numbers.tsx
@@ -59,3 +59,5 @@ export const makeDisplayValue = ({
if (Number.isFinite(f)) return f.toFixed(fixed)
return typeof inf === 'function' ? inf(f) : inf
}
+
+export const coordsFormat = (coords?: string) => (typeof coords === 'string') && isFinite(Number(coords)) ? Number(coords).toPrecision(10) : '-'
diff --git a/src/utils/functions/permissions.tsx b/src/utils/functions/permissions.tsx
index a8067b0..6375502 100644
--- a/src/utils/functions/permissions.tsx
+++ b/src/utils/functions/permissions.tsx
@@ -1,10 +1,9 @@
import { memo, NamedExoticComponent, ReactElement, ReactNode, useMemo } from 'react'
import { Navigate, useParams } from 'react-router-dom'
-import { getUserLogin, getUserPermissions, getUserRoles } from '@utils'
-import { isDev } from '@utils'
+import { isDev, getUser, getUserPermissions } from '@utils'
-import AccessDenied from '@pages/AccessDenied'
+import AccessDenied from '@pages/public/AccessDenied'
export type Role = string
export type Permission = string
@@ -23,7 +22,7 @@ export const getPermissions = (...values: PermissionRequest[]) => {
const [service, type] = (key[0].toLowerCase() + key.slice(1)).split('.') // toCamelCase
if (!isRequestType(type)) return
permissions[service] = permissions[service] ?? {}
- permissions[service][type] = hasPermission(key) || (isDev() && getUserLogin() === 'dev')
+ permissions[service][type] = hasPermission(key) || (isDev() && getUser().login === 'dev')
})
return permissions
}
@@ -31,22 +30,13 @@ export const getPermissions = (...values: PermissionRequest[]) => {
export const hasPermission = (permission?: Permission | Permission[], userPermissions?: Permission[]): boolean => {
if (!Array.isArray(permission) && typeof permission !== 'string')
return true
- const userPerms = userPermissions ?? getUserPermissions()
+ const userPerms = userPermissions ?? getUserPermissions() ?? []
if (typeof permission === 'string')
permission = [permission]
return permission.every((perm) => userPerms.includes(perm))
}
-export const isInRole = (roles?: Role[] | Role): boolean => {
- if (typeof roles === 'string' && !Array.isArray(roles))
- roles = [roles]
- if (!roles?.length) return true
-
- const user_roles = getUserRoles()
- return roles.some((role) => user_roles.includes(role))
-}
-
-const sectionAvailable = (section: PermissionRecord, userPermission: Permission[] = getUserPermissions()) => {
+const sectionAvailable = (section: PermissionRecord, userPermission: Permission[]) => {
for (const child of Object.values(section)) {
if (!child) continue
if (Array.isArray(child)) {
@@ -81,7 +71,7 @@ export const isURLAvailable = (path: string, userPermissions?: Permission[]) =>
}
if (!perms) return false
- const userPerms: string[] = userPermissions ?? getUserPermissions()
+ const userPerms: string[] = userPermissions ?? getUserPermissions() ?? []
if (Array.isArray(perms)) {
return perms.every((perm) => userPerms.includes(perm))
}
@@ -109,7 +99,7 @@ export type PrivateComponent = NamedExoticComponent
& Priva
getKey: () => string
}
-export const NoAccessComponent = memo(() => getUserLogin() ? (
+export const NoAccessComponent = memo(() => getUser().login ? (
//
) : (
diff --git a/src/utils/functions/storage.ts b/src/utils/functions/storage.ts
index c4392f7..85772b7 100644
--- a/src/utils/functions/storage.ts
+++ b/src/utils/functions/storage.ts
@@ -1,7 +1,8 @@
import { OpenAPI, UserTokenDto } from '@api'
+import { isDev } from '..'
import { wrapValues } from './objects'
-import { Role, Permission } from './permissions'
+import { Permission } from './permissions'
import { normalizeTableColumn, optimizeTableColumn, TableSettings, TableSettingsStore } from './table_settings'
export enum StorageNames {
@@ -9,7 +10,7 @@ export enum StorageNames {
token = 'token',
login = 'login',
permissions = 'permissions',
- roles = 'roles',
+ user = 'user',
tableSettings = 'tableSettings',
dashboardNNB = 'dashboardNNB',
witsInfo = 'witsInfo'
@@ -22,11 +23,12 @@ export const getArrayFromLocalStorage = (name: string
}
export const getJSON = (name: StorageNames): T | null => {
- const raw = localStorage.getItem(name)
- if (!raw) return null
try {
- return JSON.parse(raw)
- } catch {}
+ const raw = localStorage.getItem(name)
+ if (raw) return JSON.parse(raw)
+ } catch {
+ if (isDev()) console.warn(`Storage "${name}" parsing exception!`)
+ }
return null
}
@@ -34,25 +36,24 @@ export const setJSON = (name: StorageNames, data: T | null): boolean => {
try {
localStorage.setItem(name, JSON.stringify(data))
return true
- } catch {}
+ } catch {
+ if (isDev()) console.warn(`Storage "${name}" saving exception!`)
+ }
return false
}
-export const getUserRoles = (): Role[] => getArrayFromLocalStorage(StorageNames.roles) ?? []
-export const getUserPermissions = (): Permission[] => getArrayFromLocalStorage(StorageNames.permissions) ?? []
-export const getUserId = () => Number(localStorage.getItem(StorageNames.userId)) || null
-export const getUserLogin = () => localStorage.getItem(StorageNames.login)
-export const getUserToken = () => localStorage.getItem(StorageNames.token)
+export const getUser = (): UserTokenDto => getJSON(StorageNames.user) || {}
+
+export const getUserPermissions = (): Permission[] | null => {
+ let permissions = getUser()?.permissions?.map((perm) => perm.name as string)
+ if (!permissions) // TODO: Удалить в следующем релизе, вставлено для совместимости
+ permissions = localStorage.getItem(StorageNames.permissions)?.split(',')
+ return permissions || null
+}
export const setUser = (user: UserTokenDto) => {
OpenAPI.TOKEN = user.token ?? undefined
- localStorage.setItem(StorageNames.userId, String(user.id))
- localStorage.setItem(StorageNames.token, String(user.token))
- localStorage.setItem(StorageNames.login, String(user.login))
- if (user.permissions)
- localStorage.setItem(StorageNames.permissions, user.permissions.map((permission) => permission.name).join(','))
- if (user.roleNames)
- localStorage.setItem(StorageNames.roles, user.roleNames.join(','))
+ localStorage.setItem(StorageNames.user, JSON.stringify(user))
}
export const removeUser = () => {
@@ -60,7 +61,8 @@ export const removeUser = () => {
localStorage.removeItem(StorageNames.login)
localStorage.removeItem(StorageNames.token)
localStorage.removeItem(StorageNames.permissions)
- localStorage.removeItem(StorageNames.roles)
+
+ localStorage.removeItem(StorageNames.user)
}
export const getTableSettings = (tableName: string): TableSettings => {