Добавлены новые типы документов, косметика

This commit is contained in:
Александр Сироткин 2021-12-20 12:44:07 +05:00
parent efc7ae5e17
commit df9eeae047
6 changed files with 322 additions and 338 deletions

View File

@ -1,15 +1,11 @@
import { useState, useEffect } from "react"
import { DatePicker, Button, Input } from "antd"
import moment from "moment"
import { FileService } from "../../services/api"
import {
invokeWebApiWrapperAsync,
downloadFile,
formatBytes,
} from "../../components/factory"
import { EditableTable, makePaginationObject } from "../../components/Table"
import {UploadForm} from "../../components/UploadForm"
import LoaderPortal from "../../components/LoaderPortal"
import moment from 'moment'
import { useState, useEffect } from 'react'
import { DatePicker, Button, Input } from 'antd'
import { FileService } from '../../services/api'
import { invokeWebApiWrapperAsync, downloadFile, formatBytes } from '../../components/factory'
import { EditableTable, makePaginationObject } from '../../components/Table'
import { UploadForm } from '../../components/UploadForm'
import LoaderPortal from '../../components/LoaderPortal'
import { UserView } from '../../components/UserView'
import { CompanyView } from '../../components/CompanyView'
@ -17,6 +13,38 @@ const pageSize = 12
const { RangePicker } = DatePicker
const { Search } = Input
const columns = [
{
title: 'Документ',
key: 'document',
dataIndex: 'name',
render: (name, row) => (
<Button type={'link'} onClick={() => downloadFile(row)} download={name}>
{name}
</Button>
),
}, {
title: 'Дата загрузки',
key: 'uploadDate',
dataIndex: 'uploadDate',
render: item => moment.utc(item).local().format('DD MMM YYYY, HH:mm:ss'),
}, {
title: 'Размер',
key: 'size',
dataIndex: 'size',
render: item => formatBytes(item)
}, {
title: 'Автор',
key: 'author',
dataIndex: 'author',
render: item => <UserView user={item}/>
}, {
title: 'Компания',
key: 'company',
render: (_, record) => <CompanyView company={record?.author?.company}/>
}
]
export default function DocumentsTemplate({ idCategory, idWell, accept, headerChild, customColumns, beforeTable, onChange}) {
const [page, setPage] = useState(1)
const [filterDataRange, setFilterDataRange] = useState([])
@ -28,59 +56,17 @@ export default function DocumentsTemplate({ idCategory, idWell, accept, headerCh
const uploadUrl = `/api/well/${idWell}/files/?idCategory=${idCategory}`
const handleUploadComplete = () => {
update()
}
const handleUploadComplete = () => update()
const handleFileDelete = async (file) => {
await FileService.delete(idWell, file.id)
update()
}
const hanleCompanySearch = (value, _) => {
setFilterCompanyName(value)
}
const hanleCompanySearch = (value, _) => setFilterCompanyName(value)
const hanleFileNameSearch = (value, _) => setFilterFileName(value)
const hanleFileNameSearch = (value, _) => {
setFilterFileName(value)
}
const columns = [
{
title: "Документ",
key: "document",
dataIndex: "name",
render: (name, row) => (
<Button type="link" onClick={() => downloadFile(row)} download={name}>
{name}
</Button>),
},
{
title: "Дата загрузки",
key: "uploadDate",
dataIndex: "uploadDate",
render: item =>
moment.utc(item).local().format("DD MMM YYYY, HH:mm:ss"),
},
{
title: "Размер",
key: "size",
dataIndex: "size",
render: item => formatBytes(item)
},
{
title: "Автор",
key: "author",
dataIndex: "author",
render: item => <UserView user={item}/>
},
{
title: "Компания",
key: "company",
render: (_, record) => <CompanyView company={record?.author?.company}/>
},
...(customColumns??[])
]
const mergedColumns = [...columns, ...(customColumns ?? [])]
const update = () => {
let begin = null
@ -103,8 +89,7 @@ export default function DocumentsTemplate({ idCategory, idWell, accept, headerCh
pageSize,
)
if (!paginatedFiles)
return
if (!paginatedFiles) return
const filesInfos = paginatedFiles.items ?? []
setFiles(filesInfos)
@ -117,24 +102,10 @@ export default function DocumentsTemplate({ idCategory, idWell, accept, headerCh
}
useEffect(update, [idWell, idCategory, page, filterDataRange, filterCompanyName, filterFileName])
useEffect(()=>{
if(onChange)
onChange(files)
}, [files, onChange])
useEffect(() => onChange?.(files), [files, onChange])
const companies = [...new Set(files.map(file=>file.company))]
.filter(company=>company)
const DataListCompanies = <datalist id="listCompanies">
{companies.map((company)=><option key={company} value={company}>{company}</option>)}
</datalist>
const filenames = [...new Set(files.map(file=>file.name))]
.filter(name=>name)
const DataListFileNames = <datalist id="listFileNames">
{filenames.map((name)=><option key={name} value={name}>{name}</option>)}
</datalist>
const companies = [...new Set(files.map(file => file.company))].filter(company => company)
const filenames = [...new Set(files.map(file => file.name))].filter(name => name)
return (
<LoaderPortal show={showLoader}>
@ -149,19 +120,29 @@ export default function DocumentsTemplate({ idCategory, idWell, accept, headerCh
<div>
<span>Фильтр по компании</span>
<Search
list='listCompanies'
placeholder="Фильтр по компании"
onSearch={hanleCompanySearch}/>
{DataListCompanies}
list={'listCompanies'}
placeholder={'Фильтр по компании'}
onSearch={hanleCompanySearch}
/>
<datalist id={'listCompanies'}>
{companies.map((company) => (
<option key={company} value={company}>{company}</option>
))}
</datalist>
</div>
&nbsp;
<div>
<span>Фильтр по имени файла</span>
<Search
list='listFileNames'
placeholder="Фильтр по имени файла"
onSearch={hanleFileNameSearch}/>
{DataListFileNames}
list={'listFileNames'}
placeholder={'Фильтр по имени файла'}
onSearch={hanleFileNameSearch}
/>
<datalist id={'listFileNames'}>
{filenames.map((name) => (
<option key={name} value={name}>{name}</option>
))}
</datalist>
</div>
&nbsp;&nbsp;
<div>
@ -170,16 +151,17 @@ export default function DocumentsTemplate({ idCategory, idWell, accept, headerCh
url={uploadUrl}
accept={accept}
onUploadStart={() => setShowLoader(true)}
onUploadComplete={handleUploadComplete}/>
onUploadComplete={handleUploadComplete}
/>
</div>
&nbsp;&nbsp;
{headerChild}
</div>
{beforeTable}
<EditableTable
columns={columns}
columns={mergedColumns}
dataSource={files}
size={"small"}
size={'small'}
pagination={{
...pagination,
showSizeChanger: false,

View File

@ -1,15 +1,15 @@
import {Popconfirm, Button, Tooltip, Typography} from 'antd'
import { useEffect, useState } from 'react'
import { FileExcelOutlined } from '@ant-design/icons'
import { useEffect, useState } from "react"
import {invokeWebApiWrapperAsync, download, formatBytes} from '../../components/factory'
import DocumentsTemplate from './DocumentsTemplate'
import LoaderPortal from '../../components/LoaderPortal'
import { Popconfirm, Button, Tooltip, Typography } from 'antd'
import { Flex } from '../../components/Grid'
import {DrillingProgramService, WellService} from '../../services/api'
import { Mark } from '../../components/Mark'
import { UserView } from '../../components/UserView'
import LoaderPortal from '../../components/LoaderPortal'
import { invokeWebApiWrapperAsync, download, formatBytes } from '../../components/factory'
import {DrillingProgramService, WellService} from '../../services/api'
import DocumentsTemplate from './DocumentsTemplate'
const idFileCategoryDrillingProgramItems = 13;
const idFileCategoryDrillingProgramItems = 13
const {Text} = Typography
export default function DrillingProgram({ idWell }) {
@ -17,8 +17,8 @@ export default function DrillingProgram({idWell}) {
const [showLoader, setShowLoader] = useState(false)
const [tooltip, setTooltip] = useState('нет файлов для формирования')
const [wellLabel, setWellLabel] = useState(`${idWell}`)
const [childKey, setChildKey] = useState();
const [lastUpdatedFile, setLastUpdatedFile] = useState();
const [childKey, setChildKey] = useState()
const [lastUpdatedFile, setLastUpdatedFile] = useState()
useEffect(() => invokeWebApiWrapperAsync(
async () => {
@ -26,26 +26,28 @@ export default function DrillingProgram({idWell}) {
setWellLabel(well.caption ?? `${idWell}`)
},
setShowLoader,
`Не удалось загрузить название скважины "${idWell}"`
`Не удалось загрузить название скважины '${idWell}'`
), [idWell])
const urlDownloadProgram = `/api/well/${idWell}/drillingProgram`
const downloadProgram = () => invokeWebApiWrapperAsync(async()=>{
await download(urlDownloadProgram)
},
const downloadProgram = () => invokeWebApiWrapperAsync(
async () => await download(urlDownloadProgram),
setShowLoader,
"Не удалось загрузить программу бурения")
'Не удалось загрузить программу бурения'
)
const openProgramPreview = () => invokeWebApiWrapperAsync(async()=>{
const openProgramPreview = () => invokeWebApiWrapperAsync(
async() => {
const filWebUrl = await DrillingProgramService.getOrCreateSharedUrl(idWell)
if(filWebUrl && filWebUrl.length > 0)
window.open(filWebUrl, '_blank');
window.open(filWebUrl, '_blank')
else
throw new Error("Сервер вернул плохую ссылку")
throw new Error('Сервер вернул плохую ссылку')
},
setShowLoader,
"Не удалось создать быстрый просмотр программы")
'Не удалось создать быстрый просмотр программы'
)
const filesUpdated = (files) => {
if (!files || files.length === 0) {
@ -60,18 +62,17 @@ export default function DrillingProgram({idWell}) {
if (isAllFilesAreExcel && isAnyFileMarked) {
setTooltip('Программа доступна для скачивания')
selDownloadButtonEnabled(true)
}
else{
} else {
setTooltip('Список файлов содержит недопустимые типы файлов')
}
const last = files.reduce((pre, cur) => pre.uploadDate > cur.uploadDate ? pre : cur)
setLastUpdatedFile(last);
setLastUpdatedFile(last)
}
const customColumns = [
{
title: "Метки",
key: "fileMarks",
title: 'Метки',
key: 'fileMarks',
render: (_, record) => renderMarksColumn(record?.id, record?.fileMarks)
},
]
@ -81,10 +82,11 @@ export default function DrillingProgram({idWell}) {
if(validMarks?.length)
return validMarks.map(mark => <Mark mark = {mark} onDelete={() => deleteMark(mark.id)}/>)
return true &&
<Popconfirm title="Согласовать файл?" onConfirm={() => addMarkToFile(idFile)}>
<Button type="link">Согласовать</Button>
return (
<Popconfirm title={'Согласовать файл?'} onConfirm={() => addMarkToFile(idFile)}>
<Button type={'link'}>Согласовать</Button>
</Popconfirm>
)
}
const addMarkToFile = async (idFile) => {
@ -92,7 +94,8 @@ export default function DrillingProgram({idWell}) {
idFile: idFile,
idMarkType: 1,
isDeleted: false,
comment: ''}
comment: '',
}
await DrillingProgramService.createFileMark(idWell, mark)
selDownloadButtonEnabled(true)
setChildKey(Date.now())
@ -103,25 +106,29 @@ export default function DrillingProgram({idWell}) {
setChildKey(Date.now())
}
const downloadButton = <div>
const downloadButton = (
<div>
<span>Программа бурения</span>
<Flex>
<Tooltip title={tooltip}>
<Button
type="primary"
type={'primary'}
onClick={downloadProgram}
disabled={!downloadButtonEnabled}>
disabled={!downloadButtonEnabled}
>
Сформировать и скачать
</Button>
</Tooltip>
<Tooltip title="Просмотреть через GoogleDrive">
<Tooltip title={'Просмотреть через GoogleDrive'}>
<Popconfirm
title="Загрузить файл на GoogleDrive для просмотра?"
title={'Загрузить файл на GoogleDrive для просмотра?'}
onConfirm={openProgramPreview}
disabled={!downloadButtonEnabled}>
disabled={!downloadButtonEnabled}
>
<Button
type="link"
disabled={!downloadButtonEnabled}>
type={'link'}
disabled={!downloadButtonEnabled}
>
<FileExcelOutlined />
Программа бурения {wellLabel}.xlsx
</Button>
@ -129,25 +136,29 @@ export default function DrillingProgram({idWell}) {
</Tooltip>
</Flex>
</div>
)
const lastUpdatedFileView = lastUpdatedFile &&
<Text>
<b>Последнее изменние:</b>
&nbsp;"{lastUpdatedFile.name}"
&nbsp;'{lastUpdatedFile.name}'
&nbsp;[{formatBytes(lastUpdatedFile.size)}]
&nbsp;загружен: {new Date(lastUpdatedFile.uploadDate).toLocaleString()}
&nbsp;автор: <UserView user={lastUpdatedFile.author}/>
</Text>
return(<LoaderPortal show={showLoader}>
return (
<LoaderPortal show={showLoader}>
<DocumentsTemplate
beforeTable={lastUpdatedFileView}
idWell={idWell}
idCategory={idFileCategoryDrillingProgramItems}
accept='.xlsx'
accept={'.xlsx'}
headerChild={downloadButton}
onChange={filesUpdated}
customColumns = {customColumns}
key = {childKey}/>
</LoaderPortal>)
key = {childKey}
/>
</LoaderPortal>
)
}

View File

@ -1,27 +1,68 @@
import {Layout, Menu} from "antd";
import {Switch, useParams} from "react-router-dom";
import {makeMenuItems, makeRouteItems} from './menuItems'
import path from 'path'
import { memo } from 'react'
import { Layout, Menu } from 'antd'
import { FolderOutlined } from '@ant-design/icons'
import { Switch, useParams, Link, Route } from 'react-router-dom'
import { PrivateMenuItem } from '../../components/Private'
import { isInRole } from '../../utils/PermissionService'
import DocumentsTemplate from './DocumentsTemplate'
const { Content } = Layout
export default function MenuDocuments({idWell}) {
let {category} = useParams()
export const documentCategories = [
{ id: 1, key: 'fluidService', title: 'Растворный сервис' },
{ id: 2, key: 'cementing', title: 'Цементирование' },
{ id: 3, key: 'nnb', title: 'ННБ' },
{ id: 4, key: 'gti', title: 'ГТИ' },
{ id: 5, key: 'documentsForWell', title: 'Документы по скважине' },
{ id: 6, key: 'supervisor', title: 'Супервайзер' },
{ id: 7, key: 'master', title: 'Мастер' },
{ id: 8, key: 'toolService', title: 'Долотный сервис' },
{ id: 9, key: 'drillService', title: 'Буровой подрядчик' },
{ id: 9, key: 'closingService', title: 'Сервис по заканчиванию скважины' },
]
const getUserCategories = () => documentCategories.filter(cat => isInRole(cat.roles))
export const makeMenuItems = (root, cats) => {
const categories = cats ?? getUserCategories()
return categories.map(category => (
<PrivateMenuItem className={'ant-menu-item'} key={`${category.key}`} icon={<FolderOutlined/>}>
<Link to={{ pathname: `${root}/${category.key}` }}>{category.title}</Link>
</PrivateMenuItem>
))
}
export const MenuDocuments = memo(({ idWell }) => {
const { category } = useParams()
const rootPath = `/well/${idWell}`
return(<>
const root = path.join(rootPath, '/document')
const categories = getUserCategories()
return (
<>
<Menu
mode="horizontal"
mode={'horizontal'}
selectable={true}
className="well_menu"
selectedKeys={[category]}>
{makeMenuItems(rootPath)}
className={'well_menu'}
selectedKeys={[category]}
>
{makeMenuItems(root, categories)}
</Menu>
<Layout>
<Content className="site-layout-background">
<Content className={'site-layout-background'}>
<Switch>
{makeRouteItems(rootPath, idWell)}
{categories.map(category => (
<Route path={`${root}/${category.key}`} key={`${category.key}`}>
<DocumentsTemplate idCategory={category.id} idWell={idWell}/>
</Route>
))}
</Switch>
</Content>
</Layout>
</>)
}
</>
)
})
export default MenuDocuments

View File

@ -1,50 +0,0 @@
import path from 'path'
import { FolderOutlined } from '@ant-design/icons'
import { Link, Route } from 'react-router-dom'
import { PrivateMenuItem } from '../../components/Private'
import { getUserRoles, isInRole } from "../../utils/PermissionService";
import DocumentsTemplate from './DocumentsTemplate'
export const documentCategories = [
{ id: 1, key: 'fluidService', title: 'Растворный сервис' },
{ id: 2, key: 'cementing', title: 'Цементирование' },
{ id: 3, key: 'nnb', title: 'ННБ' },
{ id: 4, key: 'gti', title: 'ГТИ' },
{ id: 5, key: 'documentsForWell', title: 'Документы по скважине' },
{ id: 6, key: 'supervisor', title: 'Супервайзер' },
{ id: 7, key: 'master', title: 'Мастер' },
]
const makeMenuItem = (keyValue, rootPath, title, other) => (
<PrivateMenuItem className={'ant-menu-item'} key={`${keyValue}`} {...other}>
<Link to={{pathname: `${rootPath}/${keyValue}`}}>{title}</Link>
</PrivateMenuItem>
)
const makeRouteItem = (keyValue, rootPath, other) => (
<Route
path={`${rootPath}/${keyValue}`}
key={`${keyValue}`}
>
<DocumentsTemplate {...other}/>
</Route>
)
const getCategoriesByUserRole = (role) => documentCategories.filter(cat => isInRole(cat.roles))
export const makeMenuItems = (rootPath) => {
const root = path.join(rootPath, '/document')
const categories = getCategoriesByUserRole(getUserRoles())
return categories.map(category =>
makeMenuItem(category.key, root, category.title, {icon:<FolderOutlined/>}))
}
export const makeRouteItems = (rootPath, idWell) => {
const root = path.join(rootPath, '/document')
const categories = getCategoriesByUserRole(getUserRoles())
const routes = categories.map(category => makeRouteItem(category.key, root, {
idCategory: category.id,
idWell: idWell
}))
return routes
}

View File

@ -3,7 +3,7 @@ import { Select, Modal, Input, InputNumber } from 'antd'
import { SetpointsService } from '../../services/api'
import LoaderPortal from '../../components/LoaderPortal'
import { invokeWebApiWrapperAsync } from '../../components/factory'
import { makeNumericRender, EditableTable, makeNumericInput } from '../../components/Table'
import { makeNumericRender, EditableTable } from '../../components/Table'
import { PeriodPicker, defaultPeriod } from '../../components/PeriodPicker'
import { Grid, GridItem } from '../../components/Grid'
@ -54,6 +54,7 @@ export const SetpointSender = ({ idWell, onClose, visible, setpointNames }) => {
const onModalOk = () => invokeWebApiWrapperAsync(
async () => {
// eslint-disable-next-line no-sequences
const setpointsObject = setpoints.reduce((obj, sp) => (obj[sp.name] = sp.value, obj), {})
const request = {
uploadDate: new Date(),

View File

@ -1,4 +1,4 @@
import { Layout, Menu } from "antd";
import { Layout, Menu } from 'antd'
import {
FolderOutlined,
FundViewOutlined,
@ -6,61 +6,59 @@ import {
FilePdfOutlined,
DatabaseOutlined,
ExperimentOutlined,
//FundProjectionScreenOutlined
} from "@ant-design/icons";
import { Link, Redirect, Route, Switch, useParams } from "react-router-dom";
import TelemetryView from "./TelemetryView";
import Messages from "./Messages";
import Report from "./Report";
import Archive from "./Archive";
import Documents from "./Documents";
import Measure from "./Measure";
import { makeMenuItems } from "./Documents/menuItems";
import WellOperations from "./WellOperations";
import DrillingProgram from "./Documents/DrillingProgram";
import TelemetryAnalysis from "./TelemetryAnalysis"
FundProjectionScreenOutlined,
} from '@ant-design/icons'
import { Link, Redirect, Route, Switch, useParams } from 'react-router-dom'
import { PrivateMenuItem } from '../components/Private'
import TelemetryView from './TelemetryView'
import Messages from './Messages'
import Report from './Report'
import Archive from './Archive'
import Documents from './Documents'
import Measure from './Measure'
import WellOperations from './WellOperations'
import TelemetryAnalysis from './TelemetryAnalysis'
import { makeMenuItems } from './Documents/'
import DrillingProgram from './Documents/DrillingProgram'
const { Content } = Layout;
const { Content } = Layout
export default function Well() {
let { idWell, tab } = useParams();
const rootPath = `/well/${idWell}`;
const { idWell, tab } = useParams()
const rootPath = `/well/${idWell}`
const { SubMenu } = Menu;
const { SubMenu } = Menu
return <Layout>
return (
<Layout>
<Menu
mode="horizontal"
mode={'horizontal'}
selectable={true}
selectedKeys={[tab]}
className="well_menu"
className={'well_menu'}
>
<PrivateMenuItem key="telemetry" icon={<FundViewOutlined />}>
<PrivateMenuItem key={'telemetry'} icon={<FundViewOutlined />}>
<Link to={`${rootPath}/telemetry`}>Мониторинг</Link>
</PrivateMenuItem>
<PrivateMenuItem key="message" icon={<AlertOutlined/>} roles={[]}>
<PrivateMenuItem key={'message'} icon={<AlertOutlined/>}>
<Link to={`${rootPath}/message`}>Сообщения</Link>
</PrivateMenuItem>
<PrivateMenuItem key="report" icon={<FilePdfOutlined />}>
<PrivateMenuItem key={'report'} icon={<FilePdfOutlined />}>
<Link to={`${rootPath}/report`}>Рапорт</Link>
</PrivateMenuItem>
<PrivateMenuItem key="operations" icon={<FolderOutlined />}>
<PrivateMenuItem key={'operations'} icon={<FolderOutlined />}>
<Link to={`${rootPath}/operations`}>Операции по скважине</Link>
</PrivateMenuItem>
<PrivateMenuItem key="archive" icon={<DatabaseOutlined />}>
<PrivateMenuItem key={'archive'} icon={<DatabaseOutlined />}>
<Link to={`${rootPath}/archive`}>Архив</Link>
</PrivateMenuItem>
{/* <PrivateMenuItem key="telemetryAnalysis" icon={<FundProjectionScreenOutlined />}>
<PrivateMenuItem key={'telemetryAnalysis'} icon={<FundProjectionScreenOutlined />} roles={'admin'}>
<Link to={`${rootPath}/telemetryAnalysis/depthToDay`}>Операции по телеметрии</Link>
</PrivateMenuItem> */}
</PrivateMenuItem>
<SubMenu
key="document"
key={'document'}
title={
<Link
to={`${rootPath}/document/fluidService`}
className="linkDocuments"
>
<Link to={`${rootPath}/document/fluidService`} className={'linkDocuments'}>
Документы
</Link>
}
@ -69,49 +67,50 @@ export default function Well() {
>
{makeMenuItems(rootPath)}
</SubMenu>
<PrivateMenuItem key="measure" icon={<ExperimentOutlined />}>
<PrivateMenuItem key={'measure'} icon={<ExperimentOutlined />}>
<Link to={`${rootPath}/measure`}>Измерения</Link>
</PrivateMenuItem>
<PrivateMenuItem key="drillingProgram" icon={<FolderOutlined />}>
<PrivateMenuItem key={'drillingProgram'} icon={<FolderOutlined />}>
<Link to={`${rootPath}/drillingProgram`}>Программа бурения</Link>
</PrivateMenuItem>
</Menu>
<Layout>
<Content className="site-layout-background">
<Content className={'site-layout-background'}>
<Switch>
<Route path="/well/:idWell/telemetry">
<Route path={'/well/:idWell/telemetry'}>
<TelemetryView idWell={idWell} />
</Route>
<Route path="/well/:idWell/message">
<Route path={'/well/:idWell/message'}>
<Messages idWell={idWell} />
</Route>
<Route path="/well/:idWell/report">
<Route path={'/well/:idWell/report'}>
<Report idWell={idWell} />
</Route>
<Route path="/well/:idWell/operations/:tab?">
<Route path={'/well/:idWell/operations/:tab?'}>
<WellOperations idWell={idWell} />
</Route>
<Route path="/well/:idWell/archive">
<Route path={'/well/:idWell/archive'}>
<Archive idWell={idWell} />
</Route>
<Route path="/well/:idWell/telemetryAnalysis/:tab">
<Route path={'/well/:idWell/telemetryAnalysis/:tab'}>
<TelemetryAnalysis idWell={idWell} />
</Route>
<Route path="/well/:idWell/document/:category">
<Route path={'/well/:idWell/document/:category'}>
<Documents idWell={idWell} />
</Route>
<Route path="/well/:id/measure">
<Route path={'/well/:id/measure'}>
<Measure idWell={idWell}/>
</Route>
<Route path="/well/:id/drillingProgram">
<Route path={'/well/:id/drillingProgram'}>
<DrillingProgram idWell={idWell}/>
</Route>
<Route path="/">
<Route path={'/'}>
<Redirect to={`${rootPath}/telemetry`} />
</Route>
</Switch>
</Content>
</Layout>
</Layout>
)
}