forked from VinokurovVE/tests
mantine
This commit is contained in:
@ -1,156 +0,0 @@
|
||||
import * as React from 'react';
|
||||
import Box from '@mui/material/Box';
|
||||
import Avatar from '@mui/material/Avatar';
|
||||
import Menu from '@mui/material/Menu';
|
||||
import MenuItem from '@mui/material/MenuItem';
|
||||
import ListItemIcon from '@mui/material/ListItemIcon';
|
||||
import IconButton from '@mui/material/IconButton';
|
||||
import Tooltip from '@mui/material/Tooltip';
|
||||
import Settings from '@mui/icons-material/Settings';
|
||||
import Logout from '@mui/icons-material/Logout';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { logout } from '../store/auth';
|
||||
import { ListItemText, Switch, styled } from '@mui/material';
|
||||
import { setDarkMode, usePrefStore } from '../store/preferences';
|
||||
|
||||
const Android12Switch = styled(Switch)(({ theme }) => ({
|
||||
padding: 8,
|
||||
'& .MuiSwitch-track': {
|
||||
borderRadius: 22 / 2,
|
||||
'&::before, &::after': {
|
||||
content: '""',
|
||||
position: 'absolute',
|
||||
top: '50%',
|
||||
transform: 'translateY(-50%)',
|
||||
width: 16,
|
||||
height: 16,
|
||||
},
|
||||
'&::before': {
|
||||
backgroundImage: `url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" height="16" width="16" viewBox="0 0 24 24"><path fill="${encodeURIComponent(
|
||||
theme.palette.getContrastText(theme.palette.primary.main),
|
||||
)}" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"/></svg>')`,
|
||||
left: 12,
|
||||
},
|
||||
'&::after': {
|
||||
backgroundImage: `url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" height="16" width="16" viewBox="0 0 24 24"><path fill="${encodeURIComponent(
|
||||
theme.palette.getContrastText(theme.palette.primary.main),
|
||||
)}" d="M19,13H5V11H19V13Z" /></svg>')`,
|
||||
right: 12,
|
||||
},
|
||||
},
|
||||
'& .MuiSwitch-thumb': {
|
||||
boxShadow: 'none',
|
||||
width: 16,
|
||||
height: 16,
|
||||
margin: 2,
|
||||
},
|
||||
}));
|
||||
|
||||
export default function AccountMenu() {
|
||||
const navigate = useNavigate()
|
||||
|
||||
const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null);
|
||||
|
||||
const open = Boolean(anchorEl);
|
||||
|
||||
const handleClick = (event: React.MouseEvent<HTMLElement>) => {
|
||||
setAnchorEl(event.currentTarget);
|
||||
};
|
||||
const handleClose = () => {
|
||||
setAnchorEl(null);
|
||||
};
|
||||
|
||||
const prefStore = usePrefStore()
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
<Box sx={{ display: 'flex', alignItems: 'center', textAlign: 'center' }}>
|
||||
<Tooltip title="Account settings">
|
||||
<IconButton
|
||||
onClick={handleClick}
|
||||
size="small"
|
||||
sx={{ ml: 2 }}
|
||||
aria-controls={open ? 'account-menu' : undefined}
|
||||
aria-haspopup="true"
|
||||
aria-expanded={open ? 'true' : undefined}
|
||||
>
|
||||
<Avatar sx={{ width: 32, height: 32 }}></Avatar>
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
</Box>
|
||||
|
||||
<Menu
|
||||
anchorEl={anchorEl}
|
||||
id="account-menu"
|
||||
open={open}
|
||||
onClose={handleClose}
|
||||
slotProps={{
|
||||
paper: {
|
||||
elevation: 0,
|
||||
sx: {
|
||||
overflow: 'visible',
|
||||
filter: 'drop-shadow(0px 2px 8px rgba(0,0,0,0.32))',
|
||||
mt: 1.5,
|
||||
'& .MuiAvatar-root': {
|
||||
width: 32,
|
||||
height: 32,
|
||||
ml: -0.5,
|
||||
mr: 1,
|
||||
},
|
||||
'&::before': {
|
||||
content: '""',
|
||||
display: 'block',
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
right: 14,
|
||||
width: 10,
|
||||
height: 10,
|
||||
bgcolor: 'background.paper',
|
||||
transform: 'translateY(-50%) rotate(45deg)',
|
||||
zIndex: 0,
|
||||
},
|
||||
},
|
||||
}
|
||||
}}
|
||||
transformOrigin={{ horizontal: 'right', vertical: 'top' }}
|
||||
anchorOrigin={{ horizontal: 'right', vertical: 'bottom' }}
|
||||
>
|
||||
<MenuItem onClick={() => {
|
||||
}}>
|
||||
<ListItemIcon>
|
||||
<Android12Switch
|
||||
checked={prefStore.darkMode}
|
||||
onChange={(e) => {
|
||||
setDarkMode(e.target.checked)
|
||||
}} />
|
||||
</ListItemIcon>
|
||||
<ListItemText>
|
||||
Тема: {prefStore.darkMode ? "темная" : "светлая"}
|
||||
</ListItemText>
|
||||
</MenuItem>
|
||||
|
||||
|
||||
<MenuItem onClick={() => {
|
||||
navigate('/settings')
|
||||
}}>
|
||||
<ListItemIcon>
|
||||
<Settings fontSize="small" />
|
||||
</ListItemIcon>
|
||||
Настройки
|
||||
</MenuItem>
|
||||
|
||||
<MenuItem
|
||||
onClick={() => {
|
||||
logout()
|
||||
navigate("/auth/signin")
|
||||
}}
|
||||
>
|
||||
<ListItemIcon>
|
||||
<Logout fontSize="small" />
|
||||
</ListItemIcon>
|
||||
Выход
|
||||
</MenuItem>
|
||||
</Menu>
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
@ -1,11 +1,13 @@
|
||||
import { useDocuments, useDownload, useFolders } from '../hooks/swrHooks'
|
||||
import { IDocument, IDocumentFolder } from '../interfaces/documents'
|
||||
import { Box, Breadcrumbs, Button, CircularProgress, Divider, IconButton, Link, List, ListItemButton, SxProps } from '@mui/material'
|
||||
import { Cancel, Close, Download, Folder, InsertDriveFile, Upload, UploadFile } from '@mui/icons-material'
|
||||
import React, { useEffect, useRef, useState } from 'react'
|
||||
import { Box, CircularProgress, Divider, SxProps } from '@mui/material'
|
||||
import { Folder, InsertDriveFile } from '@mui/icons-material'
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import DocumentService from '../services/DocumentService'
|
||||
import { mutate } from 'swr'
|
||||
import FileViewer from './modals/FileViewer'
|
||||
import { ActionIcon, Anchor, Breadcrumbs, Button, FileButton, Flex, Loader, RingProgress, Table, Text } from '@mantine/core'
|
||||
import { IconCancel, IconDownload, IconFile, IconFilePlus, IconFileUpload, IconX } from '@tabler/icons-react'
|
||||
|
||||
interface FolderProps {
|
||||
folder: IDocumentFolder;
|
||||
@ -31,7 +33,7 @@ const FileItemStyle: SxProps = {
|
||||
|
||||
function ItemFolder({ folder, handleFolderClick, ...props }: FolderProps) {
|
||||
return (
|
||||
<ListItemButton
|
||||
<Flex
|
||||
onClick={() => handleFolderClick(folder)}
|
||||
>
|
||||
<Box
|
||||
@ -41,7 +43,7 @@ function ItemFolder({ folder, handleFolderClick, ...props }: FolderProps) {
|
||||
<Folder />
|
||||
{folder.name}
|
||||
</Box>
|
||||
</ListItemButton>
|
||||
</Flex>
|
||||
)
|
||||
}
|
||||
|
||||
@ -69,7 +71,7 @@ function ItemDocument({ doc, index, handleDocumentClick, ...props }: DocumentPro
|
||||
}, [shouldFetch, file])
|
||||
|
||||
return (
|
||||
<ListItemButton>
|
||||
<Flex align='center'>
|
||||
<Box
|
||||
sx={FileItemStyle}
|
||||
onClick={() => handleDocumentClick(index)}
|
||||
@ -79,22 +81,21 @@ function ItemDocument({ doc, index, handleDocumentClick, ...props }: DocumentPro
|
||||
{doc.name}
|
||||
</Box>
|
||||
<Box>
|
||||
<IconButton
|
||||
<ActionIcon
|
||||
onClick={() => {
|
||||
if (!isLoading) {
|
||||
setShouldFetch(true)
|
||||
}
|
||||
}}
|
||||
sx={{ ml: 'auto' }}
|
||||
>
|
||||
variant='subtle'>
|
||||
{isLoading ?
|
||||
<CircularProgress size={24} variant='indeterminate' />
|
||||
<Loader size='sm' />
|
||||
:
|
||||
<Download />
|
||||
<IconDownload />
|
||||
}
|
||||
</IconButton>
|
||||
</ActionIcon>
|
||||
</Box>
|
||||
</ListItemButton>
|
||||
</Flex>
|
||||
)
|
||||
}
|
||||
|
||||
@ -105,7 +106,6 @@ export default function FolderViewer() {
|
||||
const { documents, isLoading: documentsLoading } = useDocuments(currentFolder?.id)
|
||||
const [uploadProgress, setUploadProgress] = useState(0)
|
||||
const [isUploading, setIsUploading] = useState(false)
|
||||
const fileInputRef = useRef<HTMLInputElement>(null)
|
||||
const [fileViewerModal, setFileViewerModal] = useState(false)
|
||||
const [currentFileNo, setCurrentFileNo] = useState<number>(-1)
|
||||
|
||||
@ -128,12 +128,6 @@ export default function FolderViewer() {
|
||||
setCurrentFolder(newBreadcrumbs[newBreadcrumbs.length - 1])
|
||||
}
|
||||
|
||||
const handleUploadClick = () => {
|
||||
if (fileInputRef.current) {
|
||||
fileInputRef.current.click()
|
||||
}
|
||||
}
|
||||
|
||||
const handleDragOver = (e: React.DragEvent) => {
|
||||
e.preventDefault()
|
||||
setDragOver(true)
|
||||
@ -150,9 +144,10 @@ export default function FolderViewer() {
|
||||
setFilesToUpload((prevFiles) => [...prevFiles, ...files])
|
||||
}
|
||||
|
||||
const handleFileInput = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const files = Array.from(e.target.files || [])
|
||||
setFilesToUpload((prevFiles) => [...prevFiles, ...files])
|
||||
const handleFileInput = (files: File[] | null) => {
|
||||
if (files !== null) {
|
||||
setFilesToUpload((prevFiles) => [...prevFiles, ...files])
|
||||
}
|
||||
}
|
||||
|
||||
const uploadFiles = async () => {
|
||||
@ -196,28 +191,21 @@ export default function FolderViewer() {
|
||||
/>
|
||||
|
||||
<Breadcrumbs>
|
||||
<Link
|
||||
underline='hover'
|
||||
color='inherit'
|
||||
<Anchor
|
||||
onClick={() => {
|
||||
setCurrentFolder(null)
|
||||
setBreadcrumbs([])
|
||||
}}
|
||||
sx={{ cursor: 'pointer' }}
|
||||
>
|
||||
Главная
|
||||
</Link>
|
||||
|
||||
</Anchor>
|
||||
{breadcrumbs.map((breadcrumb, index) => (
|
||||
<Link
|
||||
<Anchor
|
||||
key={breadcrumb.id}
|
||||
underline="hover"
|
||||
color="inherit"
|
||||
onClick={() => handleBreadcrumbClick(index)}
|
||||
sx={{ cursor: 'pointer' }}
|
||||
>
|
||||
{breadcrumb.name}
|
||||
</Link>
|
||||
</Anchor>
|
||||
))}
|
||||
</Breadcrumbs>
|
||||
|
||||
@ -232,44 +220,23 @@ export default function FolderViewer() {
|
||||
p: '16px'
|
||||
}}>
|
||||
<Box sx={{ display: 'flex', gap: '16px' }}>
|
||||
<Button
|
||||
LinkComponent="label"
|
||||
role={undefined}
|
||||
variant="outlined"
|
||||
tabIndex={-1}
|
||||
startIcon={
|
||||
isUploading ? <CircularProgress sx={{ maxHeight: "20px", maxWidth: "20px" }} variant="determinate" value={uploadProgress} /> : <UploadFile />
|
||||
}
|
||||
onClick={handleUploadClick}
|
||||
>
|
||||
<input
|
||||
type='file'
|
||||
ref={fileInputRef}
|
||||
style={{ display: 'none' }}
|
||||
onChange={handleFileInput}
|
||||
onClick={(e) => {
|
||||
if (e.currentTarget) {
|
||||
e.currentTarget.value = ''
|
||||
}
|
||||
}}
|
||||
/>
|
||||
Добавить
|
||||
</Button>
|
||||
<FileButton multiple onChange={handleFileInput}>
|
||||
{(props) => <Button variant='filled' leftSection={isUploading ? <Loader /> : <IconFilePlus />} {...props}>Добавить</Button>}
|
||||
</FileButton>
|
||||
|
||||
{filesToUpload.length > 0 &&
|
||||
<>
|
||||
<Button
|
||||
variant="contained"
|
||||
color="primary"
|
||||
startIcon={<Upload />}
|
||||
variant='filled'
|
||||
leftSection={isUploading ? <RingProgress sections={[{ value: uploadProgress, color: 'blue' }]} /> : <IconFileUpload />}
|
||||
onClick={uploadFiles}
|
||||
>
|
||||
Загрузить все
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
variant='outlined'
|
||||
startIcon={<Cancel />}
|
||||
variant='outline'
|
||||
leftSection={<IconCancel />}
|
||||
onClick={() => {
|
||||
setFilesToUpload([])
|
||||
}}
|
||||
@ -283,62 +250,69 @@ export default function FolderViewer() {
|
||||
<Divider />
|
||||
|
||||
{filesToUpload.length > 0 &&
|
||||
<Box>
|
||||
<Flex direction='column'>
|
||||
{filesToUpload.map((file, index) => (
|
||||
<Box key={index} sx={{ display: 'flex', alignItems: 'center', gap: '8px', marginTop: '8px' }}>
|
||||
<Box>
|
||||
<InsertDriveFile />
|
||||
<span>{file.name}</span>
|
||||
</Box>
|
||||
<Flex key={index} p='8px'>
|
||||
<Flex gap='sm' direction='row' align='center'>
|
||||
<IconFile />
|
||||
<Text>{file.name}</Text>
|
||||
</Flex>
|
||||
|
||||
<IconButton sx={{ ml: 'auto' }} onClick={() => {
|
||||
<ActionIcon onClick={() => {
|
||||
setFilesToUpload(prev => {
|
||||
return prev.filter((_, i) => i != index)
|
||||
})
|
||||
}}>
|
||||
<Close />
|
||||
</IconButton>
|
||||
</Box>
|
||||
}} ml='auto' variant='subtle'>
|
||||
<IconX />
|
||||
</ActionIcon>
|
||||
</Flex>
|
||||
))}
|
||||
</Box>
|
||||
</Flex>
|
||||
}
|
||||
</Box>
|
||||
</Box>
|
||||
}
|
||||
|
||||
<List
|
||||
dense
|
||||
<Table
|
||||
onDragOver={handleDragOver}
|
||||
onDragLeave={handleDragLeave}
|
||||
onDrop={handleDrop}
|
||||
sx={{
|
||||
backgroundColor: dragOver ? 'rgba(0, 0, 0, 0.1)' : 'inherit'
|
||||
}}
|
||||
>
|
||||
{currentFolder ? (
|
||||
documents?.map((doc: IDocument, index: number) => (
|
||||
<div key={`${doc.id}-${doc.name}`}>
|
||||
<ItemDocument
|
||||
doc={doc}
|
||||
index={index}
|
||||
handleDocumentClick={handleDocumentClick}
|
||||
/>
|
||||
{index < documents.length - 1 && <Divider />}
|
||||
</div>
|
||||
))
|
||||
) : (
|
||||
folders?.map((folder: IDocumentFolder, index: number) => (
|
||||
<div key={`${folder.id}-${folder.name}`}>
|
||||
<ItemFolder
|
||||
folder={folder}
|
||||
index={index}
|
||||
handleFolderClick={handleFolderClick}
|
||||
/>
|
||||
{index < folders.length - 1 && <Divider />}
|
||||
</div>
|
||||
))
|
||||
)}
|
||||
</List>
|
||||
bg={dragOver ? 'rgba(0, 0, 0, 0.1)' : 'inherit'}
|
||||
highlightOnHover>
|
||||
<Table.Thead>
|
||||
<Table.Tr>
|
||||
|
||||
</Table.Tr>
|
||||
</Table.Thead>
|
||||
|
||||
<Table.Tbody>
|
||||
{currentFolder ? (
|
||||
documents?.map((doc: IDocument, index: number) => (
|
||||
<Table.Tr key={doc.id}>
|
||||
<Table.Td>
|
||||
<ItemDocument
|
||||
doc={doc}
|
||||
index={index}
|
||||
handleDocumentClick={handleDocumentClick}
|
||||
/>
|
||||
</Table.Td>
|
||||
</Table.Tr>
|
||||
))
|
||||
) : (
|
||||
folders?.map((folder: IDocumentFolder, index: number) => (
|
||||
<Table.Tr key={folder.id}>
|
||||
<Table.Td>
|
||||
<ItemFolder
|
||||
folder={folder}
|
||||
index={index}
|
||||
handleFolderClick={handleFolderClick}
|
||||
/>
|
||||
</Table.Td>
|
||||
</Table.Tr>
|
||||
))
|
||||
)}
|
||||
</Table.Tbody>
|
||||
</Table>
|
||||
</Box>
|
||||
)
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
import { SubmitHandler, useForm } from 'react-hook-form'
|
||||
import { CreateField } from '../interfaces/create'
|
||||
import { Box, Button, CircularProgress, Stack, SxProps, TextField, Typography } from '@mui/material';
|
||||
import { AxiosResponse } from 'axios';
|
||||
import { Button, Loader, Stack, Text, TextInput } from '@mantine/core';
|
||||
|
||||
interface Props {
|
||||
title?: string;
|
||||
@ -11,7 +11,6 @@ interface Props {
|
||||
mutateHandler?: any;
|
||||
defaultValues?: {};
|
||||
watchValues?: string[];
|
||||
sx?: SxProps | null;
|
||||
}
|
||||
|
||||
function FormFields({
|
||||
@ -20,8 +19,7 @@ function FormFields({
|
||||
fields,
|
||||
submitButtonText = 'Сохранить',
|
||||
mutateHandler,
|
||||
defaultValues,
|
||||
sx
|
||||
defaultValues
|
||||
}: Props) {
|
||||
const getDefaultValues = (fields: CreateField[]) => {
|
||||
let result: { [key: string]: string | boolean } = {}
|
||||
@ -53,20 +51,20 @@ function FormFields({
|
||||
|
||||
return (
|
||||
<form onSubmit={handleSubmit(onSubmit)}>
|
||||
<Stack sx={sx} spacing={2} width='100%'>
|
||||
<Typography variant="h6" component="h6" gutterBottom>
|
||||
{title}
|
||||
</Typography>
|
||||
<Stack gap='sm' w='100%'>
|
||||
{title.length > 0 &&
|
||||
<Text size="xl" fw={500}>
|
||||
{title}
|
||||
</Text>
|
||||
}
|
||||
|
||||
{fields.map((field: CreateField) => {
|
||||
return (
|
||||
<TextField
|
||||
fullWidth
|
||||
margin='normal'
|
||||
<TextInput
|
||||
key={field.key}
|
||||
type={field.inputType ? field.inputType : 'text'}
|
||||
label={field.headerName || field.key.charAt(0).toUpperCase() + field.key.slice(1)}
|
||||
required={field.required || false}
|
||||
//placeholder="Your name"
|
||||
type={field.inputType ? field.inputType : 'text'}
|
||||
{...register(field.key, {
|
||||
required: field.required ? `${field.headerName} обязателен` : false,
|
||||
validate: (val: string | boolean) => {
|
||||
@ -77,21 +75,17 @@ function FormFields({
|
||||
}
|
||||
},
|
||||
})}
|
||||
error={!!errors[field.key]}
|
||||
helperText={errors[field.key]?.message}
|
||||
radius="md"
|
||||
required={field.required || false}
|
||||
error={errors[field.key]?.message}
|
||||
errorProps={errors[field.key]}
|
||||
/>
|
||||
)
|
||||
})}
|
||||
|
||||
<Box sx={{
|
||||
display: "flex",
|
||||
justifyContent: "space-between",
|
||||
gap: "8px"
|
||||
}}>
|
||||
<Button disabled={isSubmitting || Object.keys(dirtyFields).length === 0 || !isValid} type="submit" variant="contained" color="primary">
|
||||
{isSubmitting ? <CircularProgress size={16} /> : submitButtonText}
|
||||
</Button>
|
||||
</Box>
|
||||
<Button disabled={isSubmitting || Object.keys(dirtyFields).length === 0 || !isValid} type='submit'>
|
||||
{isSubmitting ? <Loader size={16} /> : submitButtonText}
|
||||
</Button>
|
||||
</Stack>
|
||||
</form>
|
||||
)
|
||||
|
@ -1,8 +1,8 @@
|
||||
import { Box } from '@mui/material'
|
||||
import { IServer } from '../interfaces/servers'
|
||||
import { useServerIps } from '../hooks/swrHooks'
|
||||
import FullFeaturedCrudGrid from './TableEditable'
|
||||
import { GridColDef } from '@mui/x-data-grid'
|
||||
import { Table } from '@mantine/core'
|
||||
|
||||
function ServerData({ id }: IServer) {
|
||||
const { serverIps } = useServerIps(id, 0, 10)
|
||||
@ -19,18 +19,34 @@ function ServerData({ id }: IServer) {
|
||||
return (
|
||||
<Box sx={{ display: 'flex', flexDirection: 'column', p: '16px' }}>
|
||||
{serverIps &&
|
||||
<FullFeaturedCrudGrid
|
||||
initialRows={serverIps}
|
||||
columns={serverIpsColumns}
|
||||
actions
|
||||
onRowClick={() => {
|
||||
//setCurrentServerData(params.row)
|
||||
//setServerDataOpen(true)
|
||||
}}
|
||||
onSave={undefined}
|
||||
onDelete={undefined}
|
||||
loading={false}
|
||||
/>
|
||||
// <FullFeaturedCrudGrid
|
||||
// initialRows={serverIps}
|
||||
// columns={serverIpsColumns}
|
||||
// actions
|
||||
// onRowClick={() => {
|
||||
// //setCurrentServerData(params.row)
|
||||
// //setServerDataOpen(true)
|
||||
// }}
|
||||
// onSave={undefined}
|
||||
// onDelete={undefined}
|
||||
// loading={false}
|
||||
// />
|
||||
<Table highlightOnHover>
|
||||
<Table.Thead>
|
||||
<Table.Tr>
|
||||
{serverIpsColumns.map(column => (
|
||||
<Table.Th key={column.field}>{column.headerName}</Table.Th>
|
||||
))}
|
||||
</Table.Tr>
|
||||
</Table.Thead>
|
||||
<Table.Tbody>
|
||||
<Table.Tr>
|
||||
{serverIpsColumns.map(column => (
|
||||
<Table.Td key={column.field}>{serverIps ? serverIps[column.field] : ''}</Table.Td>
|
||||
))}
|
||||
</Table.Tr>
|
||||
</Table.Tbody>
|
||||
</Table>
|
||||
}
|
||||
</Box>
|
||||
)
|
||||
|
@ -1,16 +1,17 @@
|
||||
import { AppBar, Autocomplete, CircularProgress, Dialog, IconButton, TextField, Toolbar } from '@mui/material'
|
||||
import { AppBar, CircularProgress, Dialog, IconButton, Toolbar } from '@mui/material'
|
||||
import { Fragment, useState } from 'react'
|
||||
import { IRegion } from '../interfaces/fuel'
|
||||
import { useHardwares, useServers } from '../hooks/swrHooks'
|
||||
import FullFeaturedCrudGrid from './TableEditable'
|
||||
import ServerService from '../services/ServersService'
|
||||
import { GridColDef } from '@mui/x-data-grid'
|
||||
import { Close } from '@mui/icons-material'
|
||||
import ServerData from './ServerData'
|
||||
import { Autocomplete, CloseButton, Table } from '@mantine/core'
|
||||
import { IServer } from '../interfaces/servers'
|
||||
|
||||
export default function ServerHardware() {
|
||||
const [open, setOpen] = useState(false)
|
||||
const [selectedOption, setSelectedOption] = useState<IRegion | null>(null)
|
||||
const [selectedOption, setSelectedOption] = useState<number | null>(null)
|
||||
const { servers, isLoading } = useServers()
|
||||
|
||||
const [serverDataOpen, setServerDataOpen] = useState(false)
|
||||
@ -71,54 +72,96 @@ export default function ServerHardware() {
|
||||
}
|
||||
</Dialog>
|
||||
|
||||
<form>
|
||||
<Autocomplete
|
||||
placeholder="Сервер"
|
||||
flex={'1'}
|
||||
data={servers ? servers.map((item: IServer) => ({ label: item.name, value: item.id.toString() })) : []}
|
||||
onSelect={(e) => console.log(e.currentTarget.value)}
|
||||
//onChange={(value) => setSearch(value)}
|
||||
onOptionSubmit={(value) => setSelectedOption(Number(value))}
|
||||
rightSection={
|
||||
//search !== '' &&
|
||||
(
|
||||
<CloseButton
|
||||
size="sm"
|
||||
onMouseDown={(event) => event.preventDefault()}
|
||||
onClick={() => {
|
||||
//setSearch('')
|
||||
setSelectedOption(null)
|
||||
}}
|
||||
aria-label="Clear value"
|
||||
/>
|
||||
)
|
||||
}
|
||||
//value={search}
|
||||
/>
|
||||
</form>
|
||||
|
||||
{serversLoading ?
|
||||
<CircularProgress />
|
||||
:
|
||||
<FullFeaturedCrudGrid
|
||||
autoComplete={
|
||||
<Autocomplete
|
||||
open={open}
|
||||
onOpen={() => {
|
||||
setOpen(true)
|
||||
}}
|
||||
onClose={() => {
|
||||
setOpen(false)
|
||||
}}
|
||||
onInputChange={(_, value) => handleInputChange(value)}
|
||||
onChange={(_, value) => handleOptionChange(value)}
|
||||
filterOptions={(x) => x}
|
||||
isOptionEqualToValue={(option: IRegion, value: IRegion) => option.name === value.name}
|
||||
getOptionLabel={(option: IRegion) => option.name ? option.name : ""}
|
||||
options={servers || []}
|
||||
loading={isLoading}
|
||||
value={selectedOption}
|
||||
renderInput={(params) => (
|
||||
<TextField
|
||||
{...params}
|
||||
label="Сервер"
|
||||
size='small'
|
||||
InputProps={{
|
||||
...params.InputProps,
|
||||
endAdornment: (
|
||||
<Fragment>
|
||||
{isLoading ? <CircularProgress color="inherit" size={20} /> : null}
|
||||
{params.InputProps.endAdornment}
|
||||
</Fragment>
|
||||
)
|
||||
}} />
|
||||
)} />}
|
||||
onSave={() => {
|
||||
}}
|
||||
onDelete={ServerService.removeServer}
|
||||
initialRows={hardwares || []}
|
||||
columns={hardwareColumns}
|
||||
actions
|
||||
onRowClick={(params) => {
|
||||
setCurrentServerData(params.row)
|
||||
setServerDataOpen(true)
|
||||
}}
|
||||
loading={false}
|
||||
/>
|
||||
// <FullFeaturedCrudGrid
|
||||
// autoComplete={
|
||||
// <Autocomplete
|
||||
// open={open}
|
||||
// onOpen={() => {
|
||||
// setOpen(true)
|
||||
// }}
|
||||
// onClose={() => {
|
||||
// setOpen(false)
|
||||
// }}
|
||||
// onInputChange={(_, value) => handleInputChange(value)}
|
||||
// onChange={(_, value) => handleOptionChange(value)}
|
||||
// filterOptions={(x) => x}
|
||||
// isOptionEqualToValue={(option: IRegion, value: IRegion) => option.name === value.name}
|
||||
// getOptionLabel={(option: IRegion) => option.name ? option.name : ""}
|
||||
// options={servers || []}
|
||||
// loading={isLoading}
|
||||
// value={selectedOption}
|
||||
// renderInput={(params) => (
|
||||
// <TextField
|
||||
// {...params}
|
||||
// label="Сервер"
|
||||
// size='small'
|
||||
// InputProps={{
|
||||
// ...params.InputProps,
|
||||
// endAdornment: (
|
||||
// <Fragment>
|
||||
// {isLoading ? <CircularProgress color="inherit" size={20} /> : null}
|
||||
// {params.InputProps.endAdornment}
|
||||
// </Fragment>
|
||||
// )
|
||||
// }} />
|
||||
// )} />}
|
||||
// onSave={() => {
|
||||
// }}
|
||||
// onDelete={ServerService.removeServer}
|
||||
// initialRows={hardwares || []}
|
||||
// columns={hardwareColumns}
|
||||
// actions
|
||||
// onRowClick={(params) => {
|
||||
// setCurrentServerData(params.row)
|
||||
// setServerDataOpen(true)
|
||||
// }}
|
||||
// loading={false}
|
||||
// />
|
||||
<Table highlightOnHover>
|
||||
<Table.Thead>
|
||||
<Table.Tr>
|
||||
{hardwareColumns.map(column => (
|
||||
<Table.Th key={column.field}>{column.headerName}</Table.Th>
|
||||
))}
|
||||
</Table.Tr>
|
||||
</Table.Thead>
|
||||
<Table.Tbody>
|
||||
<Table.Tr>
|
||||
{hardwareColumns.map(column => (
|
||||
<Table.Td key={column.field}>{hardwares ? hardwares[column.field] : ''}</Table.Td>
|
||||
))}
|
||||
</Table.Tr>
|
||||
</Table.Tbody>
|
||||
</Table>
|
||||
}
|
||||
</>
|
||||
)
|
||||
|
@ -1,16 +1,17 @@
|
||||
import { AppBar, Autocomplete, CircularProgress, Dialog, IconButton, TextField, Toolbar } from '@mui/material'
|
||||
import { AppBar, CircularProgress, Dialog, IconButton, TextField, Toolbar } from '@mui/material'
|
||||
import { Fragment, useState } from 'react'
|
||||
import { IRegion } from '../interfaces/fuel'
|
||||
import { useServerIps, useServers } from '../hooks/swrHooks'
|
||||
import FullFeaturedCrudGrid from './TableEditable'
|
||||
import ServerService from '../services/ServersService'
|
||||
import { GridColDef } from '@mui/x-data-grid'
|
||||
import { Close } from '@mui/icons-material'
|
||||
import ServerData from './ServerData'
|
||||
import { Autocomplete, CloseButton, Table } from '@mantine/core'
|
||||
import { IServer } from '../interfaces/servers'
|
||||
|
||||
export default function ServerIpsView() {
|
||||
const [open, setOpen] = useState(false)
|
||||
const [selectedOption, setSelectedOption] = useState<IRegion | null>(null)
|
||||
const [selectedOption, setSelectedOption] = useState<number | null>(null)
|
||||
const { servers, isLoading } = useServers()
|
||||
|
||||
const [serverDataOpen, setServerDataOpen] = useState(false)
|
||||
@ -69,52 +70,97 @@ export default function ServerIpsView() {
|
||||
}
|
||||
</Dialog>
|
||||
|
||||
<form>
|
||||
<Autocomplete
|
||||
placeholder="Сервер"
|
||||
flex={'1'}
|
||||
data={servers ? servers.map((item: IServer) => ({ label: item.name, value: item.id.toString() })) : []}
|
||||
onSelect={(e) => console.log(e.currentTarget.value)}
|
||||
//onChange={(value) => setSearch(value)}
|
||||
onOptionSubmit={(value) => setSelectedOption(Number(value))}
|
||||
rightSection={
|
||||
//search !== '' &&
|
||||
(
|
||||
<CloseButton
|
||||
size="sm"
|
||||
onMouseDown={(event) => event.preventDefault()}
|
||||
onClick={() => {
|
||||
//setSearch('')
|
||||
setSelectedOption(null)
|
||||
}}
|
||||
aria-label="Clear value"
|
||||
/>
|
||||
)
|
||||
}
|
||||
//value={search}
|
||||
/>
|
||||
</form>
|
||||
|
||||
{serversLoading ?
|
||||
<CircularProgress />
|
||||
:
|
||||
<FullFeaturedCrudGrid
|
||||
autoComplete={
|
||||
<Autocomplete
|
||||
open={open}
|
||||
onOpen={() => {
|
||||
setOpen(true)
|
||||
}}
|
||||
onClose={() => {
|
||||
setOpen(false)
|
||||
}}
|
||||
onInputChange={(_, value) => handleInputChange(value)}
|
||||
onChange={(_, value) => handleOptionChange(value)}
|
||||
filterOptions={(x) => x}
|
||||
isOptionEqualToValue={(option: IRegion, value: IRegion) => option.name === value.name}
|
||||
getOptionLabel={(option: IRegion) => option.name ? option.name : ""}
|
||||
options={servers || []}
|
||||
loading={isLoading}
|
||||
value={selectedOption}
|
||||
renderInput={(params) => (
|
||||
<TextField
|
||||
{...params}
|
||||
size='small'
|
||||
label="Сервер"
|
||||
InputProps={{
|
||||
...params.InputProps,
|
||||
endAdornment: (
|
||||
<Fragment>
|
||||
{isLoading ? <CircularProgress color="inherit" size={20} /> : null}
|
||||
{params.InputProps.endAdornment}
|
||||
</Fragment>
|
||||
)
|
||||
}} />
|
||||
)} />}
|
||||
onSave={() => {
|
||||
}}
|
||||
onDelete={ServerService.removeServer}
|
||||
initialRows={serverIps || []}
|
||||
columns={serverIpsColumns}
|
||||
actions
|
||||
onRowClick={(params) => {
|
||||
setCurrentServerData(params.row)
|
||||
setServerDataOpen(true)
|
||||
}} loading={false} />
|
||||
// <FullFeaturedCrudGrid
|
||||
// autoComplete={
|
||||
// <Autocomplete
|
||||
// open={open}
|
||||
// onOpen={() => {
|
||||
// setOpen(true)
|
||||
// }}
|
||||
// onClose={() => {
|
||||
// setOpen(false)
|
||||
// }}
|
||||
// onInputChange={(_, value) => handleInputChange(value)}
|
||||
// onChange={(_, value) => handleOptionChange(value)}
|
||||
// filterOptions={(x) => x}
|
||||
// isOptionEqualToValue={(option: IRegion, value: IRegion) => option.name === value.name}
|
||||
// getOptionLabel={(option: IRegion) => option.name ? option.name : ""}
|
||||
// options={servers || []}
|
||||
// loading={isLoading}
|
||||
// value={selectedOption}
|
||||
// renderInput={(params) => (
|
||||
// <TextField
|
||||
// {...params}
|
||||
// size='small'
|
||||
// label="Сервер"
|
||||
// InputProps={{
|
||||
// ...params.InputProps,
|
||||
// endAdornment: (
|
||||
// <Fragment>
|
||||
// {isLoading ? <CircularProgress color="inherit" size={20} /> : null}
|
||||
// {params.InputProps.endAdornment}
|
||||
// </Fragment>
|
||||
// )
|
||||
// }} />
|
||||
// )} />}
|
||||
// onSave={() => {
|
||||
// }}
|
||||
// onDelete={ServerService.removeServer}
|
||||
// initialRows={serverIps || []}
|
||||
// columns={serverIpsColumns}
|
||||
// actions
|
||||
// onRowClick={(params) => {
|
||||
// setCurrentServerData(params.row)
|
||||
// setServerDataOpen(true)
|
||||
// }} loading={false}
|
||||
// />
|
||||
<Table highlightOnHover>
|
||||
<Table.Thead>
|
||||
<Table.Tr>
|
||||
{serverIpsColumns.map(column => (
|
||||
<Table.Th key={column.field}>{column.headerName}</Table.Th>
|
||||
))}
|
||||
</Table.Tr>
|
||||
</Table.Thead>
|
||||
<Table.Tbody>
|
||||
<Table.Tr
|
||||
//bg={selectedRows.includes(element.position) ? 'var(--mantine-color-blue-light)' : undefined}
|
||||
>
|
||||
{serverIpsColumns.map(column => (
|
||||
<Table.Td key={column.field}>{servers ? servers[column.field] : ''}</Table.Td>
|
||||
))}
|
||||
</Table.Tr>
|
||||
</Table.Tbody>
|
||||
</Table>
|
||||
}
|
||||
</>
|
||||
)
|
||||
|
@ -1,8 +1,7 @@
|
||||
import { AppBar, Autocomplete, Box, CircularProgress, Dialog, Grid, IconButton, TextField, Toolbar } from '@mui/material'
|
||||
import { AppBar, Box, CircularProgress, Dialog, Grid, IconButton, TextField, Toolbar } from '@mui/material'
|
||||
import { Fragment, useState } from 'react'
|
||||
import { IRegion } from '../interfaces/fuel'
|
||||
import { useRegions, useServers, useServersInfo } from '../hooks/swrHooks'
|
||||
import FullFeaturedCrudGrid from './TableEditable'
|
||||
import ServerService from '../services/ServersService'
|
||||
import { GridColDef, GridRenderCellParams } from '@mui/x-data-grid'
|
||||
import { Close, Cloud, CloudOff } from '@mui/icons-material'
|
||||
@ -12,22 +11,23 @@ import CardInfo from './CardInfo/CardInfo'
|
||||
import CardInfoLabel from './CardInfo/CardInfoLabel'
|
||||
import CardInfoChip from './CardInfo/CardInfoChip'
|
||||
import { useDebounce } from '@uidotdev/usehooks'
|
||||
import { Autocomplete, CloseButton, Table } from '@mantine/core'
|
||||
|
||||
export default function ServersView() {
|
||||
const [search, setSearch] = useState<string | null>("")
|
||||
const [search, setSearch] = useState<string | undefined>("")
|
||||
|
||||
const debouncedSearch = useDebounce(search, 500)
|
||||
|
||||
const [selectedOption, setSelectedOption] = useState<IRegion | null>(null)
|
||||
const [selectedOption, setSelectedOption] = useState<number | null>(null)
|
||||
|
||||
const { regions, isLoading } = useRegions(10, 1, debouncedSearch)
|
||||
|
||||
const { serversInfo } = useServersInfo(selectedOption?.id)
|
||||
const { serversInfo } = useServersInfo(selectedOption)
|
||||
|
||||
const [serverDataOpen, setServerDataOpen] = useState(false)
|
||||
const [currentServerData, setCurrentServerData] = useState<any | null>(null)
|
||||
|
||||
const { servers, isLoading: serversLoading } = useServers(selectedOption?.id, 0, 10)
|
||||
const { servers, isLoading: serversLoading } = useServers(selectedOption, 0, 10)
|
||||
|
||||
const serversColumns: GridColDef[] = [
|
||||
//{ field: 'id', headerName: 'ID', type: "number" },
|
||||
@ -37,42 +37,43 @@ export default function ServersView() {
|
||||
{
|
||||
field: 'region_id',
|
||||
editable: true,
|
||||
headerName: 'region_id',
|
||||
renderCell: (params) => (
|
||||
<div>
|
||||
{params.value}
|
||||
</div>
|
||||
),
|
||||
renderEditCell: (params: GridRenderCellParams) => (
|
||||
<Autocomplete
|
||||
sx={{ display: 'flex', flexGrow: '1' }}
|
||||
onInputChange={(_, value) => setSearch(value)}
|
||||
onChange={(_, value) => {
|
||||
params.value = value
|
||||
}}
|
||||
isOptionEqualToValue={(option: IRegion, value: IRegion) => option.name === value.name}
|
||||
getOptionLabel={(option: IRegion) => option.name ? option.name : ""}
|
||||
options={regions || []}
|
||||
loading={isLoading}
|
||||
value={params.value}
|
||||
renderInput={(params) => (
|
||||
<TextField
|
||||
{...params}
|
||||
size='small'
|
||||
variant='standard'
|
||||
label="Район"
|
||||
InputProps={{
|
||||
...params.InputProps,
|
||||
endAdornment: (
|
||||
<Fragment>
|
||||
{isLoading ? <CircularProgress color="inherit" size={20} /> : null}
|
||||
{params.InputProps.endAdornment}
|
||||
</Fragment>
|
||||
)
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
),
|
||||
// renderEditCell: (params: GridRenderCellParams) => (
|
||||
// <Autocomplete
|
||||
// sx={{ display: 'flex', flexGrow: '1' }}
|
||||
// onInputChange={(_, value) => setSearch(value)}
|
||||
// onChange={(_, value) => {
|
||||
// params.value = value
|
||||
// }}
|
||||
// isOptionEqualToValue={(option: IRegion, value: IRegion) => option.name === value.name}
|
||||
// getOptionLabel={(option: IRegion) => option.name ? option.name : ""}
|
||||
// options={regions || []}
|
||||
// loading={isLoading}
|
||||
// value={params.value}
|
||||
// renderInput={(params) => (
|
||||
// <TextField
|
||||
// {...params}
|
||||
// size='small'
|
||||
// variant='standard'
|
||||
// label="Район"
|
||||
// InputProps={{
|
||||
// ...params.InputProps,
|
||||
// endAdornment: (
|
||||
// <Fragment>
|
||||
// {isLoading ? <CircularProgress color="inherit" size={20} /> : null}
|
||||
// {params.InputProps.endAdornment}
|
||||
// </Fragment>
|
||||
// )
|
||||
// }}
|
||||
// />
|
||||
// )}
|
||||
// />
|
||||
// ),
|
||||
flex: 1
|
||||
}
|
||||
]
|
||||
@ -132,7 +133,50 @@ export default function ServersView() {
|
||||
</Box>
|
||||
}
|
||||
|
||||
<FullFeaturedCrudGrid
|
||||
<form>
|
||||
<Autocomplete
|
||||
placeholder="Район"
|
||||
flex={'1'}
|
||||
data={regions ? regions.map((item: IRegion) => ({ label: item.name, value: item.id.toString() })) : []}
|
||||
onSelect={(e) => console.log(e.currentTarget.value)}
|
||||
onChange={(value) => setSearch(value)}
|
||||
onOptionSubmit={(value) => setSelectedOption(Number(value))}
|
||||
rightSection={
|
||||
search !== '' && (
|
||||
<CloseButton
|
||||
size="sm"
|
||||
onMouseDown={(event) => event.preventDefault()}
|
||||
onClick={() => {
|
||||
setSearch('')
|
||||
setSelectedOption(null)
|
||||
}}
|
||||
aria-label="Clear value"
|
||||
/>
|
||||
)
|
||||
}
|
||||
value={search}
|
||||
/>
|
||||
</form>
|
||||
|
||||
|
||||
<Table highlightOnHover>
|
||||
<Table.Thead>
|
||||
<Table.Tr>
|
||||
{serversColumns.map(column => (
|
||||
<Table.Th key={column.field}>{column.headerName}</Table.Th>
|
||||
))}
|
||||
</Table.Tr>
|
||||
</Table.Thead>
|
||||
<Table.Tbody>
|
||||
<Table.Tr>
|
||||
{serversColumns.map(column => (
|
||||
<Table.Td key={column.field}>{servers ? servers[column.field] : ''}</Table.Td>
|
||||
))}
|
||||
</Table.Tr>
|
||||
</Table.Tbody>
|
||||
</Table>
|
||||
|
||||
{/* <FullFeaturedCrudGrid
|
||||
loading={serversLoading}
|
||||
autoComplete={
|
||||
<Autocomplete
|
||||
@ -171,7 +215,7 @@ export default function ServersView() {
|
||||
setCurrentServerData(params.row)
|
||||
setServerDataOpen(true)
|
||||
}}
|
||||
/>
|
||||
/> */}
|
||||
</>
|
||||
)
|
||||
}
|
@ -6,8 +6,7 @@ import View from 'ol/View'
|
||||
import { Draw, Modify, Select, Snap, Translate } from 'ol/interaction'
|
||||
import { ImageStatic, OSM, Vector as VectorSource, XYZ } from 'ol/source'
|
||||
import { Tile as TileLayer, Vector as VectorLayer } from 'ol/layer'
|
||||
import { Divider, IconButton, Slider, Stack, Select as MUISelect, MenuItem, Box, Typography, Accordion, AccordionSummary, AccordionDetails, SxProps, Theme } from '@mui/material'
|
||||
import { Add, Adjust, Api, CircleOutlined, ExpandMore, OpenWith, RectangleOutlined, Straighten, Timeline, Undo, Upload, Warning } from '@mui/icons-material'
|
||||
import { Stack, Typography } from '@mui/material'
|
||||
import { Type } from 'ol/geom/Geometry'
|
||||
import { click, never, noModifierKeys, platformModifierKeyOnly, primaryAction, shiftKeyOnly } from 'ol/events/condition'
|
||||
import Feature from 'ol/Feature'
|
||||
@ -30,6 +29,8 @@ import { useCities } from '../../hooks/swrHooks'
|
||||
import useSWR from 'swr'
|
||||
import { fetcher } from '../../http/axiosInstance'
|
||||
import { BASE_URL } from '../../constants'
|
||||
import { Accordion, ActionIcon, Box, Flex, Select as MantineSelect, MantineStyleProp, rem, Slider, useMantineColorScheme } from '@mantine/core'
|
||||
import { IconApi, IconArrowBackUp, IconArrowsMove, IconCircle, IconExclamationCircle, IconLine, IconPlus, IconPoint, IconPolygon, IconRuler, IconTable, IconUpload } from '@tabler/icons-react'
|
||||
|
||||
const MapComponent = () => {
|
||||
const { cities } = useCities(100, 1)
|
||||
@ -775,14 +776,17 @@ const MapComponent = () => {
|
||||
}
|
||||
}
|
||||
|
||||
const mapControlsStyle: SxProps<Theme> = {
|
||||
const { colorScheme } = useMantineColorScheme();
|
||||
|
||||
const mapControlsStyle: MantineStyleProp = {
|
||||
borderRadius: '4px',
|
||||
position: 'absolute',
|
||||
zIndex: '1',
|
||||
backgroundColor: (theme) =>
|
||||
theme.palette.mode === 'light'
|
||||
? '#FFFFFFAA'
|
||||
: '#000000AA',
|
||||
// backgroundColor: (theme) =>
|
||||
// theme.palette.mode === 'light'
|
||||
// ? '#FFFFFFAA'
|
||||
// : '#000000AA',
|
||||
backgroundColor: colorScheme === 'light' ? '#FFFFFFAA' : '#000000AA',
|
||||
backdropFilter: 'blur(8px)'
|
||||
}
|
||||
|
||||
@ -808,134 +812,118 @@ const MapComponent = () => {
|
||||
}, [nodes])
|
||||
|
||||
return (
|
||||
<Box height={'calc(100% - 64px)'} maxHeight={'100%'} flex={'1'} flexGrow={'1'} position={'relative'}>
|
||||
<Stack
|
||||
direction={'column'}
|
||||
sx={{
|
||||
...mapControlsStyle,
|
||||
top: '8px',
|
||||
right: '8px',
|
||||
}}
|
||||
divider={<Divider orientation='horizontal' flexItem />}>
|
||||
<IconButton onClick={() => {
|
||||
<Box w={'100%'} h={'calc(100% - 64px)'} mah={'100%'} flex={'1'} pos={'relative'}>
|
||||
<ActionIcon.Group orientation='vertical' pos='absolute' top='8px' right='8px' style={{ zIndex: 1, backdropFilter: 'blur(8px)', backgroundColor: colorScheme === 'light' ? '#FFFFFFAA' : '#000000AA', borderRadius: '4px' }}>
|
||||
<ActionIcon size='lg' variant='transparent' onClick={() => {
|
||||
fetch(`${import.meta.env.VITE_API_EMS_URL}/hello`, { method: 'GET' }).then(res => console.log(res))
|
||||
}}>
|
||||
<Api />
|
||||
</IconButton>
|
||||
<IconApi />
|
||||
</ActionIcon>
|
||||
|
||||
<IconButton onClick={() => {
|
||||
<ActionIcon size='lg' variant='transparent' onClick={() => {
|
||||
saveFeatures()
|
||||
}}>
|
||||
<Warning />
|
||||
</IconButton>
|
||||
<IconExclamationCircle />
|
||||
</ActionIcon>
|
||||
|
||||
<IconButton
|
||||
<ActionIcon size='lg' variant='transparent' onClick={() => {
|
||||
draw.current?.removeLastPoint()
|
||||
}}>
|
||||
<IconArrowBackUp />
|
||||
</ActionIcon>
|
||||
|
||||
<ActionIcon
|
||||
size='lg'
|
||||
variant={currentTool === 'Point' ? 'filled' : 'transparent'}
|
||||
onClick={() => {
|
||||
draw.current?.removeLastPoint()
|
||||
handleToolSelect('Point')
|
||||
}}>
|
||||
<Undo />
|
||||
</IconButton>
|
||||
<IconPoint />
|
||||
</ActionIcon>
|
||||
|
||||
<IconButton
|
||||
sx={{ backgroundColor: currentTool === 'Point' ? 'Highlight' : 'transparent' }}
|
||||
onClick={() => handleToolSelect('Point')}>
|
||||
<Adjust />
|
||||
</IconButton>
|
||||
<ActionIcon
|
||||
size='lg'
|
||||
variant={currentTool === 'LineString' ? 'filled' : 'transparent'}
|
||||
onClick={() => {
|
||||
handleToolSelect('LineString')
|
||||
}}>
|
||||
<IconLine />
|
||||
</ActionIcon>
|
||||
|
||||
<IconButton
|
||||
sx={{ backgroundColor: currentTool === 'LineString' ? 'Highlight' : 'transparent' }}
|
||||
onClick={() => handleToolSelect('LineString')}>
|
||||
<Timeline />
|
||||
</IconButton>
|
||||
<ActionIcon
|
||||
size='lg'
|
||||
variant={currentTool === 'Polygon' ? 'filled' : 'transparent'}
|
||||
onClick={() => {
|
||||
handleToolSelect('Polygon')
|
||||
}}>
|
||||
<IconPolygon />
|
||||
</ActionIcon>
|
||||
|
||||
<IconButton
|
||||
sx={{ backgroundColor: currentTool === 'Polygon' ? 'Highlight' : 'transparent' }}
|
||||
onClick={() => handleToolSelect('Polygon')}>
|
||||
<RectangleOutlined />
|
||||
</IconButton>
|
||||
<ActionIcon
|
||||
size='lg'
|
||||
variant={currentTool === 'Circle' ? 'filled' : 'transparent'}
|
||||
onClick={() => {
|
||||
handleToolSelect('Circle')
|
||||
}}>
|
||||
<IconCircle />
|
||||
</ActionIcon>
|
||||
|
||||
<IconButton
|
||||
sx={{ backgroundColor: currentTool === 'Circle' ? 'Highlight' : 'transparent' }}
|
||||
onClick={() => handleToolSelect('Circle')}>
|
||||
<CircleOutlined />
|
||||
</IconButton>
|
||||
|
||||
<IconButton
|
||||
<ActionIcon
|
||||
size='lg'
|
||||
variant='transparent'
|
||||
onClick={() => map?.current?.addInteraction(new Translate())}
|
||||
>
|
||||
<OpenWith />
|
||||
</IconButton>
|
||||
<IconArrowsMove />
|
||||
</ActionIcon>
|
||||
|
||||
<IconButton>
|
||||
<Straighten />
|
||||
</IconButton>
|
||||
</Stack>
|
||||
<ActionIcon
|
||||
size='lg'
|
||||
variant='transparent'
|
||||
>
|
||||
<IconRuler />
|
||||
</ActionIcon>
|
||||
</ActionIcon.Group>
|
||||
|
||||
<Stack
|
||||
direction={'column'}
|
||||
sx={{
|
||||
...mapControlsStyle,
|
||||
maxWidth: '300px',
|
||||
width: '100%',
|
||||
top: '8px',
|
||||
left: '8px',
|
||||
}} divider={<Divider orientation='horizontal' flexItem />}
|
||||
>
|
||||
<Stack direction={'row'}>
|
||||
<IconButton onClick={() => submitOverlay()}>
|
||||
<Upload />
|
||||
</IconButton>
|
||||
|
||||
<IconButton title='Добавить подложку'>
|
||||
<Add />
|
||||
</IconButton>
|
||||
</Stack>
|
||||
|
||||
|
||||
<Stack direction={'row'} padding={'8px'} spacing={4}>
|
||||
<Slider size='small' aria-label="Opacity" min={0} max={1} step={0.001} defaultValue={satelliteOpacity} value={satelliteOpacity} onChange={(_, value) => setSatelliteOpacity(Array.isArray(value) ? value[0] : value)} />
|
||||
|
||||
<MUISelect
|
||||
variant='standard'
|
||||
labelId="demo-simple-select-label"
|
||||
id="demo-simple-select"
|
||||
value={satMapsProvider}
|
||||
label="Satellite Provider"
|
||||
onChange={(e) => setSatMapsProvider(e.target.value as SatelliteMapsProvider)}
|
||||
<Flex direction='column' style={{
|
||||
...mapControlsStyle,
|
||||
maxWidth: '300px',
|
||||
width: '100%',
|
||||
top: '8px',
|
||||
left: '8px'
|
||||
}}>
|
||||
<Flex direction='row'>
|
||||
<ActionIcon
|
||||
size='lg'
|
||||
variant='transparent'
|
||||
onClick={() => submitOverlay()}
|
||||
>
|
||||
<MenuItem value={'google'}>Google</MenuItem>
|
||||
<MenuItem value={'yandex'}>Яндекс</MenuItem>
|
||||
<MenuItem value={'custom'}>Custom</MenuItem>
|
||||
</MUISelect>
|
||||
</Stack>
|
||||
<IconUpload style={{ width: rem(20), height: rem(20) }} />
|
||||
</ActionIcon>
|
||||
|
||||
<Accordion disableGutters sx={{ backgroundColor: 'transparent' }} defaultExpanded>
|
||||
<AccordionSummary
|
||||
expandIcon={<ExpandMore />}
|
||||
aria-controls="panel1-content"
|
||||
id="panel1-header"
|
||||
<ActionIcon
|
||||
size='lg'
|
||||
variant='transparent'
|
||||
title='Добавить подложку'
|
||||
>
|
||||
<Typography>Объекты</Typography>
|
||||
</AccordionSummary>
|
||||
<AccordionDetails>
|
||||
<Typography>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse
|
||||
malesuada lacus ex, sit amet blandit leo lobortis eget.
|
||||
</Typography>
|
||||
</AccordionDetails>
|
||||
<IconPlus style={{ width: rem(20), height: rem(20) }} />
|
||||
</ActionIcon>
|
||||
</Flex>
|
||||
|
||||
<Flex align='center' direction='row' p='sm' gap='sm'>
|
||||
<Slider w='100%' min={0} max={1} step={0.001} value={satelliteOpacity} defaultValue={satelliteOpacity} onChange={(value) => setSatelliteOpacity(Array.isArray(value) ? value[0] : value)} />
|
||||
|
||||
<MantineSelect variant='filled' value={satMapsProvider} data={[{ label: 'Google', value: 'google' }, { label: 'Yandex', value: 'yandex' }, { label: 'Custom', value: 'custom' }]} onChange={(value) => setSatMapsProvider(value as SatelliteMapsProvider)} />
|
||||
</Flex>
|
||||
|
||||
<Accordion variant='filled' style={{ backgroundColor: 'transparent' }} defaultValue='Объекты'>
|
||||
<Accordion.Item key={'s'} value={'Объекты'}>
|
||||
<Accordion.Control icon={<IconTable />}>{'Объекты'}</Accordion.Control>
|
||||
<Accordion.Panel>{'ASd'}</Accordion.Panel>
|
||||
</Accordion.Item>
|
||||
</Accordion>
|
||||
</Flex>
|
||||
|
||||
</Stack>
|
||||
|
||||
<Stack direction={'row'}
|
||||
sx={{
|
||||
...mapControlsStyle,
|
||||
bottom: '8px',
|
||||
left: '8px',
|
||||
}}
|
||||
|
||||
divider={<Divider orientation='vertical' flexItem />}
|
||||
>
|
||||
<Flex direction='row' pos='absolute' bottom='8px' left='8px' style={{ ...mapControlsStyle }}>
|
||||
<Stack>
|
||||
<Typography>
|
||||
x: {currentCoordinate?.[0]}
|
||||
@ -950,20 +938,11 @@ const MapComponent = () => {
|
||||
X={currentX}
|
||||
Y={currentY}
|
||||
</Typography>
|
||||
</Stack>
|
||||
</Flex>
|
||||
|
||||
<Stack direction={'row'}
|
||||
sx={{
|
||||
...mapControlsStyle,
|
||||
bottom: '8px',
|
||||
right: '8px',
|
||||
}}
|
||||
|
||||
divider={<Divider orientation='vertical' flexItem />}>
|
||||
<Stack>
|
||||
{statusText}
|
||||
</Stack>
|
||||
</Stack>
|
||||
<Flex direction='row' style={{ ...mapControlsStyle, bottom: '8px', right: '8px' }}>
|
||||
{statusText}
|
||||
</Flex>
|
||||
|
||||
<div
|
||||
id="map-container"
|
||||
|
@ -1,171 +0,0 @@
|
||||
import * as React from 'react';
|
||||
import AppBar from '@mui/material/AppBar';
|
||||
import Box from '@mui/material/Box';
|
||||
import CssBaseline from '@mui/material/CssBaseline';
|
||||
import Divider from '@mui/material/Divider';
|
||||
import Drawer from '@mui/material/Drawer';
|
||||
import IconButton from '@mui/material/IconButton';
|
||||
import InboxIcon from '@mui/icons-material/MoveToInbox';
|
||||
import List from '@mui/material/List';
|
||||
import ListItem from '@mui/material/ListItem';
|
||||
import ListItemButton from '@mui/material/ListItemButton';
|
||||
import ListItemIcon from '@mui/material/ListItemIcon';
|
||||
import ListItemText from '@mui/material/ListItemText';
|
||||
import MailIcon from '@mui/icons-material/Mail';
|
||||
import MenuIcon from '@mui/icons-material/Menu';
|
||||
import Toolbar from '@mui/material/Toolbar';
|
||||
import Typography from '@mui/material/Typography';
|
||||
|
||||
const drawerWidth = 240;
|
||||
|
||||
export default function ResponsiveDrawer() {
|
||||
//const { window } = props;
|
||||
const [mobileOpen, setMobileOpen] = React.useState(false);
|
||||
const [isClosing, setIsClosing] = React.useState(false);
|
||||
|
||||
const handleDrawerClose = () => {
|
||||
setIsClosing(true);
|
||||
setMobileOpen(false);
|
||||
};
|
||||
|
||||
const handleDrawerTransitionEnd = () => {
|
||||
setIsClosing(false);
|
||||
};
|
||||
|
||||
const handleDrawerToggle = () => {
|
||||
if (!isClosing) {
|
||||
setMobileOpen(!mobileOpen);
|
||||
}
|
||||
};
|
||||
|
||||
const drawer = (
|
||||
<div>
|
||||
<Toolbar />
|
||||
|
||||
<Divider />
|
||||
|
||||
<List>
|
||||
{['Inbox', 'Starred', 'Send email', 'Drafts'].map((text, index) => (
|
||||
<ListItem key={text} disablePadding>
|
||||
<ListItemButton>
|
||||
<ListItemIcon>
|
||||
{index % 2 === 0 ? <InboxIcon /> : <MailIcon />}
|
||||
</ListItemIcon>
|
||||
<ListItemText primary={text} />
|
||||
</ListItemButton>
|
||||
</ListItem>
|
||||
))}
|
||||
</List>
|
||||
|
||||
<Divider />
|
||||
|
||||
<List>
|
||||
{['All mail', 'Trash', 'Spam'].map((text, index) => (
|
||||
<ListItem key={text} disablePadding>
|
||||
<ListItemButton>
|
||||
<ListItemIcon>
|
||||
{index % 2 === 0 ? <InboxIcon /> : <MailIcon />}
|
||||
</ListItemIcon>
|
||||
<ListItemText primary={text} />
|
||||
</ListItemButton>
|
||||
</ListItem>
|
||||
))}
|
||||
</List>
|
||||
</div>
|
||||
);
|
||||
|
||||
return (
|
||||
<Box sx={{ display: 'flex' }}>
|
||||
<CssBaseline />
|
||||
<AppBar
|
||||
position="fixed"
|
||||
sx={{
|
||||
width: { sm: `calc(100% - ${drawerWidth}px)` },
|
||||
ml: { sm: `${drawerWidth}px` },
|
||||
}}
|
||||
>
|
||||
<Toolbar>
|
||||
<IconButton
|
||||
color="inherit"
|
||||
aria-label="open drawer"
|
||||
edge="start"
|
||||
onClick={handleDrawerToggle}
|
||||
sx={{ mr: 2, display: { sm: 'none' } }}
|
||||
>
|
||||
<MenuIcon />
|
||||
</IconButton>
|
||||
<Typography variant="h6" noWrap component="div">
|
||||
Dashboard
|
||||
</Typography>
|
||||
</Toolbar>
|
||||
</AppBar>
|
||||
|
||||
<Box
|
||||
component="nav"
|
||||
sx={{ width: { sm: drawerWidth }, flexShrink: { sm: 0 } }}
|
||||
aria-label="mailbox folders"
|
||||
>
|
||||
{/* The implementation can be swapped with js to avoid SEO duplication of links. */}
|
||||
<Drawer
|
||||
variant="temporary"
|
||||
open={mobileOpen}
|
||||
onTransitionEnd={handleDrawerTransitionEnd}
|
||||
onClose={handleDrawerClose}
|
||||
ModalProps={{
|
||||
keepMounted: true, // Better open performance on mobile.
|
||||
}}
|
||||
sx={{
|
||||
display: { xs: 'block', sm: 'none' },
|
||||
'& .MuiDrawer-paper': { boxSizing: 'border-box', width: drawerWidth },
|
||||
}}
|
||||
>
|
||||
{drawer}
|
||||
</Drawer>
|
||||
<Drawer
|
||||
variant="permanent"
|
||||
sx={{
|
||||
display: { xs: 'none', sm: 'block' },
|
||||
'& .MuiDrawer-paper': { boxSizing: 'border-box', width: drawerWidth },
|
||||
}}
|
||||
open
|
||||
>
|
||||
{drawer}
|
||||
</Drawer>
|
||||
</Box>
|
||||
|
||||
<Box
|
||||
component="main"
|
||||
sx={{ flexGrow: 1, p: 3, width: { sm: `calc(100% - ${drawerWidth}px)` } }}
|
||||
>
|
||||
<Toolbar />
|
||||
<Typography paragraph>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
|
||||
tempor incididunt ut labore et dolore magna aliqua. Rhoncus dolor purus non
|
||||
enim praesent elementum facilisis leo vel. Risus at ultrices mi tempus
|
||||
imperdiet. Semper risus in hendrerit gravida rutrum quisque non tellus.
|
||||
Convallis convallis tellus id interdum velit laoreet id donec ultrices.
|
||||
Odio morbi quis commodo odio aenean sed adipiscing. Amet nisl suscipit
|
||||
adipiscing bibendum est ultricies integer quis. Cursus euismod quis viverra
|
||||
nibh cras. Metus vulputate eu scelerisque felis imperdiet proin fermentum
|
||||
leo. Mauris commodo quis imperdiet massa tincidunt. Cras tincidunt lobortis
|
||||
feugiat vivamus at augue. At augue eget arcu dictum varius duis at
|
||||
consectetur lorem. Velit sed ullamcorper morbi tincidunt. Lorem donec massa
|
||||
sapien faucibus et molestie ac.
|
||||
</Typography>
|
||||
<Typography paragraph>
|
||||
Consequat mauris nunc congue nisi vitae suscipit. Fringilla est ullamcorper
|
||||
eget nulla facilisi etiam dignissim diam. Pulvinar elementum integer enim
|
||||
neque volutpat ac tincidunt. Ornare suspendisse sed nisi lacus sed viverra
|
||||
tellus. Purus sit amet volutpat consequat mauris. Elementum eu facilisis
|
||||
sed odio morbi. Euismod lacinia at quis risus sed vulputate odio. Morbi
|
||||
tincidunt ornare massa eget egestas purus viverra accumsan in. In hendrerit
|
||||
gravida rutrum quisque non tellus orci ac. Pellentesque nec nam aliquam sem
|
||||
et tortor. Habitant morbi tristique senectus et. Adipiscing elit duis
|
||||
tristique sollicitudin nibh sit. Ornare aenean euismod elementum nisi quis
|
||||
eleifend. Commodo viverra maecenas accumsan lacus vel facilisis. Nulla
|
||||
posuere sollicitudin aliquam ultrices sagittis orci a.
|
||||
</Typography>
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
||||
}
|
@ -1,30 +0,0 @@
|
||||
import { Tab, Tabs } from "@mui/material"
|
||||
import { Link, matchPath, useLocation } from "react-router-dom"
|
||||
|
||||
function useRouteMatch(patterns: readonly string[]) {
|
||||
const { pathname } = useLocation()
|
||||
|
||||
for (let i = 0; i < patterns.length; i += 1) {
|
||||
const pattern = patterns[i]
|
||||
const possibleMatch = matchPath(pattern, pathname)
|
||||
if (possibleMatch !== null) {
|
||||
return possibleMatch
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
export default function NavTabs() {
|
||||
const routeMatch = useRouteMatch(['/', '/user', '/role']);
|
||||
const currentTab = routeMatch?.pattern?.path;
|
||||
|
||||
return (
|
||||
<Tabs value={currentTab}>
|
||||
<Tab label="Главная" value="/" to="/" component={Link} />
|
||||
<Tab label="Пользователи" value="/user" to="/user" component={Link} />
|
||||
<Tab label="Роли" value="/role" to="/role" component={Link} />
|
||||
</Tabs>
|
||||
);
|
||||
|
||||
}
|
Reference in New Issue
Block a user