Remove @mui, move states into zustand store

This commit is contained in:
cracklesparkle
2024-12-10 10:51:29 +09:00
parent e9595f9703
commit eeae97288a
27 changed files with 537 additions and 2079 deletions

724
client/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -12,8 +12,6 @@
}, },
"dependencies": { "dependencies": {
"-": "^0.0.1", "-": "^0.0.1",
"@emotion/react": "^11.11.4",
"@emotion/styled": "^11.11.5",
"@fontsource/inter": "^5.0.19", "@fontsource/inter": "^5.0.19",
"@fontsource/open-sans": "^5.0.28", "@fontsource/open-sans": "^5.0.28",
"@js-preview/docx": "^1.6.2", "@js-preview/docx": "^1.6.2",
@ -32,10 +30,6 @@
"@mantine/nprogress": "^7.13.0", "@mantine/nprogress": "^7.13.0",
"@mantine/spotlight": "^7.13.0", "@mantine/spotlight": "^7.13.0",
"@mantine/tiptap": "^7.13.0", "@mantine/tiptap": "^7.13.0",
"@mui/icons-material": "^5.15.20",
"@mui/material": "^5.15.20",
"@mui/x-charts": "^7.8.0",
"@mui/x-data-grid": "^7.7.1",
"@tabler/icons-react": "^3.17.0", "@tabler/icons-react": "^3.17.0",
"@tanstack/react-table": "^8.20.5", "@tanstack/react-table": "^8.20.5",
"@tiptap/extension-link": "^2.7.3", "@tiptap/extension-link": "^2.7.3",

View File

@ -5,7 +5,6 @@ import Roles from "./pages/Roles"
import NotFound from "./pages/NotFound" import NotFound from "./pages/NotFound"
import MainLayout from "./layouts/MainLayout" import MainLayout from "./layouts/MainLayout"
import SignIn from "./pages/auth/SignIn" import SignIn from "./pages/auth/SignIn"
import ApiTest from "./pages/ApiTest"
import SignUp from "./pages/auth/SignUp" import SignUp from "./pages/auth/SignUp"
import { initAuth, useAuthStore } from "./store/auth" import { initAuth, useAuthStore } from "./store/auth"
import { useEffect, useState } from "react" import { useEffect, useState } from "react"
@ -18,7 +17,7 @@ import PasswordReset from "./pages/auth/PasswordReset"
import MapTest from "./pages/MapTest" import MapTest from "./pages/MapTest"
import MonitorPage from "./pages/MonitorPage" import MonitorPage from "./pages/MonitorPage"
import DashboardLayout from "./layouts/DashboardLayout" import DashboardLayout from "./layouts/DashboardLayout"
import { IconApi, IconBuildingFactory2, IconComponents, IconDeviceDesktopAnalytics, IconFiles, IconHome, IconLogin, IconLogin2, IconMap, IconPassword, IconReport, IconServer, IconSettings, IconShield, IconTable, IconUsers } from "@tabler/icons-react" import { IconBuildingFactory2, IconComponents, IconDeviceDesktopAnalytics, IconFiles, IconHome, IconLogin, IconLogin2, IconMap, IconPassword, IconReport, IconServer, IconSettings, IconShield, IconTable, IconUsers } from "@tabler/icons-react"
import { Box, Loader } from "@mantine/core" import { Box, Loader } from "@mantine/core"
import TableTest from "./pages/TableTest" import TableTest from "./pages/TableTest"
import ComponentTest from "./pages/ComponentTest" import ComponentTest from "./pages/ComponentTest"
@ -124,15 +123,6 @@ export const pages = [
dashboard: true, dashboard: true,
enabled: true, enabled: true,
}, },
{
label: "API Test",
path: "/api-test",
icon: <IconApi />,
component: <ApiTest />,
drawer: true,
dashboard: true,
enabled: false,
},
{ {
label: "ИКС", label: "ИКС",
path: "/map-test", path: "/map-test",

View File

@ -4,29 +4,34 @@ import { useMemo, useState } from 'react';
import styles from './CustomTable.module.scss' import styles from './CustomTable.module.scss'
// Sample data // Sample data
const initialData = [
{ id: 1, name: 'John Doe', age: 25 }, type DataType = {
{ id: 2, name: 'Jane Smith', age: 30 }, id: number,
{ id: 3, name: 'Sam Green', age: 22 }, name: string,
]; age: number
}
// Define columns // Define columns
const columns: ColumnDef<typeof initialData[0]>[] = [ const columns: ColumnDef<DataType>[] = [
{ {
accessorKey: 'name', accessorKey: 'name',
header: 'Name', header: 'Name',
cell: (info: any) => info.getValue(), cell: (info) => info.getValue(),
maxSize: Number.MAX_SAFE_INTEGER, maxSize: Number.MAX_SAFE_INTEGER,
}, },
{ {
accessorKey: 'age', accessorKey: 'age',
header: 'Age', header: 'Age',
cell: (info: any) => info.getValue(), cell: (info) => info.getValue(),
}, },
]; ];
const CustomTable = () => { const CustomTable = () => {
const [data, setData] = useState(initialData); const [data, setData] = useState<DataType[]>([
{ id: 1, name: 'John Doe', age: 25 },
{ id: 2, name: 'Jane Smith', age: 30 },
{ id: 3, name: 'Sam Green', age: 22 },
]);
const [editingCell, setEditingCell] = useState({ rowIndex: null, columnId: null }); const [editingCell, setEditingCell] = useState({ rowIndex: null, columnId: null });
const tableColumns = useMemo<ColumnDef<typeof data[0]>[]>(() => columns, []); const tableColumns = useMemo<ColumnDef<typeof data[0]>[]>(() => columns, []);
@ -39,7 +44,11 @@ const CustomTable = () => {
}); });
// Function to handle cell edit // Function to handle cell edit
const handleEditCell = (rowIndex: any, columnId: any, value: any) => { const handleEditCell = (
rowIndex: number,
columnId: keyof DataType,
value: DataType[keyof DataType]
) => {
const updatedData = [...data]; const updatedData = [...data];
updatedData[rowIndex][columnId] = value; updatedData[rowIndex][columnId] = value;
setData(updatedData); setData(updatedData);

View File

@ -1,12 +1,11 @@
import { useDocuments, useDownload, useFolders } from '../hooks/swrHooks' import { useDocuments, useDownload, useFolders } from '../hooks/swrHooks'
import { IDocument, IDocumentFolder } from '../interfaces/documents' import { IDocument, IDocumentFolder } from '../interfaces/documents'
import { Folder, InsertDriveFile } from '@mui/icons-material'
import React, { useEffect, useState } from 'react' import React, { useEffect, useState } from 'react'
import DocumentService from '../services/DocumentService' import DocumentService from '../services/DocumentService'
import { mutate } from 'swr' import { mutate } from 'swr'
import FileViewer from './modals/FileViewer' import FileViewer from './modals/FileViewer'
import { ActionIcon, Anchor, Breadcrumbs, Button, Divider, FileButton, Flex, Loader, MantineStyleProp, RingProgress, ScrollAreaAutosize, Table, Text } from '@mantine/core' import { ActionIcon, Anchor, Breadcrumbs, Button, Divider, FileButton, Flex, Loader, MantineStyleProp, RingProgress, ScrollAreaAutosize, Table, Text } from '@mantine/core'
import { IconCancel, IconDownload, IconFile, IconFilePlus, IconFileUpload, IconX } from '@tabler/icons-react' import { IconCancel, IconDownload, IconFile, IconFileFilled, IconFilePlus, IconFileUpload, IconFolderFilled, IconX } from '@tabler/icons-react'
interface FolderProps { interface FolderProps {
folder: IDocumentFolder; folder: IDocumentFolder;
@ -39,7 +38,7 @@ function ItemFolder({ folder, handleFolderClick, ...props }: FolderProps) {
style={FileItemStyle} style={FileItemStyle}
{...props} {...props}
> >
<Folder /> <IconFolderFilled />
{folder.name} {folder.name}
</Flex> </Flex>
</Flex> </Flex>
@ -76,7 +75,7 @@ function ItemDocument({ doc, index, handleDocumentClick, ...props }: DocumentPro
onClick={() => handleDocumentClick(index)} onClick={() => handleDocumentClick(index)}
{...props} {...props}
> >
<InsertDriveFile /> <IconFileFilled />
{doc.name} {doc.name}
</Flex> </Flex>
<Flex> <Flex>

View File

@ -1,12 +1,11 @@
import { IServer } from '../interfaces/servers' import { IServer } from '../interfaces/servers'
import { useServerIps } from '../hooks/swrHooks' import { useServerIps } from '../hooks/swrHooks'
import { GridColDef } from '@mui/x-data-grid'
import { Flex, Table } from '@mantine/core' import { Flex, Table } from '@mantine/core'
function ServerData({ id }: IServer) { function ServerData({ id }: IServer) {
const { serverIps } = useServerIps(id, 0, 10) const { serverIps } = useServerIps(id, 0, 10)
const serverIpsColumns: GridColDef[] = [ const serverIpsColumns = [
{ field: 'id', headerName: 'ID', type: 'number' }, { field: 'id', headerName: 'ID', type: 'number' },
{ field: 'server_id', headerName: 'Server ID', type: 'number' }, { field: 'server_id', headerName: 'Server ID', type: 'number' },
{ field: 'name', headerName: 'Название', type: 'string' }, { field: 'name', headerName: 'Название', type: 'string' },
@ -18,18 +17,6 @@ function ServerData({ id }: IServer) {
return ( return (
<Flex direction='column' p='sm'> <Flex direction='column' p='sm'>
{serverIps && {serverIps &&
// <FullFeaturedCrudGrid
// initialRows={serverIps}
// columns={serverIpsColumns}
// actions
// onRowClick={() => {
// //setCurrentServerData(params.row)
// //setServerDataOpen(true)
// }}
// onSave={undefined}
// onDelete={undefined}
// loading={false}
// />
<Table highlightOnHover> <Table highlightOnHover>
<Table.Thead> <Table.Thead>
<Table.Tr> <Table.Tr>

View File

@ -1,32 +1,15 @@
import { AppBar, CircularProgress, Dialog, IconButton, Toolbar } from '@mui/material'
import { useState } from 'react' import { useState } from 'react'
import { IRegion } from '../interfaces/fuel'
import { useHardwares, useServers } from '../hooks/swrHooks' import { useHardwares, useServers } from '../hooks/swrHooks'
import { GridColDef } from '@mui/x-data-grid' import { Autocomplete, CloseButton, Loader, Table } from '@mantine/core'
import { Close } from '@mui/icons-material'
import ServerData from './ServerData'
import { Autocomplete, CloseButton, Table } from '@mantine/core'
import { IServer } from '../interfaces/servers' import { IServer } from '../interfaces/servers'
export default function ServerHardware() { export default function ServerHardware() {
const [open, setOpen] = useState(false) const [selectedOption, setSelectedOption] = useState<number | undefined>(undefined)
const [selectedOption, setSelectedOption] = useState<number | null>(null) const { servers } = useServers()
const { servers, isLoading } = useServers()
const [serverDataOpen, setServerDataOpen] = useState(false) const { hardwares, isLoading: serversLoading } = useHardwares(selectedOption, 0, 10)
const [currentServerData, setCurrentServerData] = useState<any | null>(null)
const handleInputChange = (value: string) => { const hardwareColumns = [
return value
}
const handleOptionChange = (value: IRegion | null) => {
setSelectedOption(value)
}
const { hardwares, isLoading: serversLoading } = useHardwares(selectedOption?.id, 0, 10)
const hardwareColumns: GridColDef[] = [
{ field: 'id', headerName: 'ID', type: 'number' }, { field: 'id', headerName: 'ID', type: 'number' },
{ field: 'name', headerName: 'Название', type: 'string' }, { field: 'name', headerName: 'Название', type: 'string' },
{ field: 'server_id', headerName: 'Server ID', type: 'number' }, { field: 'server_id', headerName: 'Server ID', type: 'number' },
@ -39,38 +22,6 @@ export default function ServerHardware() {
return ( return (
<> <>
<Dialog
fullScreen
open={serverDataOpen}
onClose={() => {
setServerDataOpen(false)
}}
aria-labelledby="modal-modal-title"
aria-describedby="modal-modal-description">
<AppBar sx={{ position: 'sticky' }}>
<Toolbar>
<IconButton
edge="start"
color="inherit"
onClick={() => {
setServerDataOpen(false)
}}
aria-label="close"
>
<Close />
</IconButton>
</Toolbar>
</AppBar>
{currentServerData &&
<ServerData
id={currentServerData?.id}
region_id={currentServerData?.region_id}
name={currentServerData?.name}
/>
}
</Dialog>
<form> <form>
<Autocomplete <Autocomplete
placeholder="Сервер" placeholder="Сервер"
@ -87,7 +38,7 @@ export default function ServerHardware() {
onMouseDown={(event) => event.preventDefault()} onMouseDown={(event) => event.preventDefault()}
onClick={() => { onClick={() => {
//setSearch('') //setSearch('')
setSelectedOption(null) setSelectedOption(undefined)
}} }}
aria-label="Clear value" aria-label="Clear value"
/> />
@ -98,53 +49,8 @@ export default function ServerHardware() {
</form> </form>
{serversLoading ? {serversLoading ?
<CircularProgress /> <Loader />
: :
// <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 highlightOnHover>
<Table.Thead> <Table.Thead>
<Table.Tr> <Table.Tr>

View File

@ -1,33 +1,15 @@
import { AppBar, CircularProgress, Dialog, IconButton, Toolbar } from '@mui/material' import { useEffect, useState } from 'react'
import { useState } from 'react'
import { IRegion } from '../interfaces/fuel'
import { useServerIps, useServers } from '../hooks/swrHooks' import { useServerIps, useServers } from '../hooks/swrHooks'
import ServerService from '../services/ServersService' import { Autocomplete, CloseButton, Loader, Table } from '@mantine/core'
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' import { IServer } from '../interfaces/servers'
export default function ServerIpsView() { export default function ServerIpsView() {
const [open, setOpen] = useState(false)
const [selectedOption, setSelectedOption] = useState<number | null>(null) const [selectedOption, setSelectedOption] = useState<number | null>(null)
const { servers, isLoading } = useServers() const { servers } = useServers()
const [serverDataOpen, setServerDataOpen] = useState(false) const { serverIps, isLoading: serversLoading } = useServerIps(selectedOption, 0, 10)
const [currentServerData, setCurrentServerData] = useState<any | null>(null)
const handleInputChange = (value: string) => { const serverIpsColumns = [
return value
}
const handleOptionChange = (value: IRegion | null) => {
setSelectedOption(value)
}
const { serverIps, isLoading: serversLoading } = useServerIps(selectedOption?.id, 0, 10)
const serverIpsColumns: GridColDef[] = [
{ field: 'id', headerName: 'ID', type: 'number' }, { field: 'id', headerName: 'ID', type: 'number' },
{ field: 'server_id', headerName: 'Server ID', type: 'number' }, { field: 'server_id', headerName: 'Server ID', type: 'number' },
{ field: 'name', headerName: 'Название', type: 'string' }, { field: 'name', headerName: 'Название', type: 'string' },
@ -36,40 +18,12 @@ export default function ServerIpsView() {
{ field: 'servername', headerName: 'Название сервера', type: 'string' }, { field: 'servername', headerName: 'Название сервера', type: 'string' },
] ]
useEffect(() => {
console.log(serverIps)
}, [serverIps])
return ( return (
<> <>
<Dialog
fullScreen
open={serverDataOpen}
onClose={() => {
setServerDataOpen(false)
}}
aria-labelledby="modal-modal-title"
aria-describedby="modal-modal-description">
<AppBar sx={{ position: 'sticky' }}>
<Toolbar>
<IconButton
edge="start"
color="inherit"
onClick={() => {
setServerDataOpen(false)
}}
aria-label="close"
>
<Close />
</IconButton>
</Toolbar>
</AppBar>
{currentServerData &&
<ServerData
id={currentServerData?.id}
region_id={currentServerData?.region_id}
name={currentServerData?.name}
/>
}
</Dialog>
<form> <form>
<Autocomplete <Autocomplete
placeholder="Сервер" placeholder="Сервер"
@ -97,52 +51,8 @@ export default function ServerIpsView() {
</form> </form>
{serversLoading ? {serversLoading ?
<CircularProgress /> <Loader />
: :
// <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 highlightOnHover>
<Table.Thead> <Table.Thead>
<Table.Tr> <Table.Tr>

View File

@ -1,32 +1,14 @@
import { AppBar, Autocomplete, CircularProgress, Dialog, IconButton, TextField, Toolbar } from '@mui/material' import { useState } from 'react'
import { Fragment, useState } from 'react'
import { IRegion } from '../interfaces/fuel' import { IRegion } from '../interfaces/fuel'
import { useHardwares, useStorages } from '../hooks/swrHooks' import { useStorages } from '../hooks/swrHooks'
import FullFeaturedCrudGrid from './TableEditable' import { Loader, Table } from '@mantine/core'
import ServerService from '../services/ServersService'
import { GridColDef } from '@mui/x-data-grid'
import { Close } from '@mui/icons-material'
import ServerData from './ServerData'
export default function ServerStorage() { export default function ServerStorage() {
const [open, setOpen] = useState(false)
const [selectedOption, setSelectedOption] = useState<IRegion | null>(null) const [selectedOption, setSelectedOption] = useState<IRegion | null>(null)
const { hardwares, isLoading } = useHardwares()
const [serverDataOpen, setServerDataOpen] = useState(false)
const [currentServerData, setCurrentServerData] = useState<any | null>(null)
const handleInputChange = (value: string) => {
return value
}
const handleOptionChange = (value: IRegion | null) => {
setSelectedOption(value)
}
const { storages, isLoading: serversLoading } = useStorages(selectedOption?.id, 0, 10) const { storages, isLoading: serversLoading } = useStorages(selectedOption?.id, 0, 10)
const storageColumns: GridColDef[] = [ const storageColumns = [
{ field: 'id', headerName: 'ID', type: 'number' }, { field: 'id', headerName: 'ID', type: 'number' },
{ field: 'hardware_id', headerName: 'Hardware ID', type: 'number' }, { field: 'hardware_id', headerName: 'Hardware ID', type: 'number' },
{ field: 'name', headerName: 'Название', type: 'string' }, { field: 'name', headerName: 'Название', type: 'string' },
@ -36,86 +18,25 @@ export default function ServerStorage() {
return ( return (
<> <>
<Dialog
fullScreen
open={serverDataOpen}
onClose={() => {
setServerDataOpen(false)
}}
aria-labelledby="modal-modal-title"
aria-describedby="modal-modal-description">
<AppBar sx={{ position: 'sticky' }}>
<Toolbar>
<IconButton
edge="start"
color="inherit"
onClick={() => {
setServerDataOpen(false)
}}
aria-label="close"
>
<Close />
</IconButton>
</Toolbar>
</AppBar>
{currentServerData &&
<ServerData
id={currentServerData?.id}
region_id={currentServerData?.region_id}
name={currentServerData?.name}
/>
}
</Dialog>
{serversLoading ? {serversLoading ?
<CircularProgress /> <Loader />
: :
<FullFeaturedCrudGrid <Table highlightOnHover>
autoComplete={ <Table.Thead>
<Autocomplete <Table.Tr>
open={open} {storageColumns.map(column => (
onOpen={() => { <Table.Th key={column.field}>{column.headerName}</Table.Th>
setOpen(true) ))}
}} </Table.Tr>
onClose={() => { </Table.Thead>
setOpen(false) <Table.Tbody>
}} <Table.Tr>
onInputChange={(_, value) => handleInputChange(value)} {storageColumns.map(column => (
onChange={(_, value) => handleOptionChange(value)} <Table.Td key={column.field}>{storages ? storages[column.field] : ''}</Table.Td>
filterOptions={(x) => x} ))}
isOptionEqualToValue={(option: IRegion, value: IRegion) => option.name === value.name} </Table.Tr>
getOptionLabel={(option: IRegion) => option.name ? option.name : ""} </Table.Tbody>
options={hardwares || []} </Table>
loading={isLoading}
value={selectedOption}
renderInput={(params) => (
<TextField
{...params}
size='small'
label="Hardware"
InputProps={{
...params.InputProps,
endAdornment: (
<Fragment>
{isLoading ? <CircularProgress color="inherit" size={20} /> : null}
{params.InputProps.endAdornment}
</Fragment>
)
}} />
)} />}
onSave={() => {
}}
onDelete={ServerService.removeServer}
initialRows={storages || []}
columns={storageColumns}
actions
onRowClick={(params) => {
setCurrentServerData(params.row)
setServerDataOpen(true)
}}
loading={false}
/>
} }
</> </>
) )

View File

@ -1,14 +1,6 @@
import { AppBar, Box, Dialog, Grid, IconButton, Toolbar } from '@mui/material'
import { useState } from 'react' import { useState } from 'react'
import { IRegion } from '../interfaces/fuel' import { IRegion } from '../interfaces/fuel'
import { useRegions, useServers, useServersInfo } from '../hooks/swrHooks' import { useRegions, useServers } from '../hooks/swrHooks'
import { GridColDef } from '@mui/x-data-grid'
import { Close, Cloud, CloudOff } from '@mui/icons-material'
import ServerData from './ServerData'
import { IServersInfo } from '../interfaces/servers'
import CardInfo from './CardInfo/CardInfo'
import CardInfoLabel from './CardInfo/CardInfoLabel'
import CardInfoChip from './CardInfo/CardInfoChip'
import { useDebounce } from '@uidotdev/usehooks' import { useDebounce } from '@uidotdev/usehooks'
import { Autocomplete, CloseButton, Table } from '@mantine/core' import { Autocomplete, CloseButton, Table } from '@mantine/core'
@ -21,14 +13,9 @@ export default function ServersView() {
const { regions } = useRegions(10, 1, debouncedSearch) const { regions } = useRegions(10, 1, debouncedSearch)
const { serversInfo } = useServersInfo(selectedOption)
const [serverDataOpen, setServerDataOpen] = useState(false)
const [currentServerData, setCurrentServerData] = useState<any | null>(null)
const { servers } = useServers(selectedOption, 0, 10) const { servers } = useServers(selectedOption, 0, 10)
const serversColumns: GridColDef[] = [ const serversColumns = [
//{ field: 'id', headerName: 'ID', type: "number" }, //{ field: 'id', headerName: 'ID', type: "number" },
{ {
field: 'name', headerName: 'Название', type: "string", editable: true, field: 'name', headerName: 'Название', type: "string", editable: true,
@ -37,101 +24,12 @@ export default function ServersView() {
field: 'region_id', field: 'region_id',
editable: true, editable: true,
headerName: 'region_id', 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>
// )
// }}
// />
// )}
// />
// ),
flex: 1 flex: 1
} }
] ]
return ( return (
<> <>
<Dialog
fullScreen
open={serverDataOpen}
onClose={() => {
setServerDataOpen(false)
}}
aria-labelledby="modal-modal-title"
aria-describedby="modal-modal-description">
<AppBar sx={{ position: 'sticky' }}>
<Toolbar>
<IconButton
edge="start"
color="inherit"
onClick={() => {
setServerDataOpen(false)
}}
aria-label="close"
>
<Close />
</IconButton>
</Toolbar>
</AppBar>
{currentServerData &&
<ServerData
id={currentServerData?.id}
region_id={currentServerData?.region_id}
name={currentServerData?.name}
/>
}
</Dialog>
{serversInfo &&
<Box sx={{ display: 'flex', flexDirection: 'column', gap: '16px', height: '100%' }}>
<Grid container spacing={{ xs: 2, md: 3 }} columns={{ xs: 1, sm: 1, md: 2, lg: 3, xl: 4 }}>
{serversInfo.map((serverInfo: IServersInfo) => (
<Grid key={`si-${serverInfo.id}`} item xs={1} sm={1} md={1}>
<CardInfo label={serverInfo.name}>
<CardInfoLabel label='Количество IP' value={serverInfo.IPs_count} />
<CardInfoLabel label='Количество серверов' value={serverInfo.servers_count} />
<CardInfoChip
status={serverInfo.status === "Online"}
label={serverInfo.status}
iconOn={<Cloud />}
iconOff={<CloudOff />}
/>
</CardInfo>
</Grid>
))}
</Grid>
</Box>
}
<form> <form>
<Autocomplete <Autocomplete
placeholder="Район" placeholder="Район"
@ -174,47 +72,6 @@ export default function ServersView() {
</Table.Tr> </Table.Tr>
</Table.Tbody> </Table.Tbody>
</Table> </Table>
{/* <FullFeaturedCrudGrid
loading={serversLoading}
autoComplete={
<Autocomplete
onInputChange={(_, value) => setSearch(value)}
onChange={(_, value) => setSelectedOption(value)}
isOptionEqualToValue={(option: IRegion, value: IRegion) => option.id === value.id}
getOptionLabel={(option: IRegion) => option.name ? option.name : ""}
options={regions || []}
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={servers}
columns={serversColumns}
actions
onRowClick={(params) => {
setCurrentServerData(params.row)
setServerDataOpen(true)
}}
/> */}
</> </>
) )
} }

View File

@ -1,233 +0,0 @@
import { useEffect, useState } from 'react';
import Box from '@mui/material/Box';
import Button from '@mui/material/Button';
import AddIcon from '@mui/icons-material/Add';
import EditIcon from '@mui/icons-material/Edit';
import DeleteIcon from '@mui/icons-material/DeleteOutlined';
import SaveIcon from '@mui/icons-material/Save';
import CancelIcon from '@mui/icons-material/Close';
import {
GridRowsProp,
GridRowModesModel,
GridRowModes,
DataGrid,
GridColDef,
GridToolbarContainer,
GridActionsCellItem,
GridEventListener,
GridRowId,
GridRowModel,
GridRowEditStopReasons,
GridSlots,
} from '@mui/x-data-grid';
interface EditToolbarProps {
setRows: (newRows: (oldRows: GridRowsProp) => GridRowsProp) => void
setRowModesModel: (
newModel: (oldModel: GridRowModesModel) => GridRowModesModel,
) => void
columns: GridColDef[]
autoComplete?: React.ReactElement | null
}
function EditToolbar(props: EditToolbarProps) {
const { setRows, setRowModesModel, columns, autoComplete } = props
const handleClick = () => {
const id = Date.now().toString(36)
const newValues: any = {}
columns.forEach(column => {
if (column.type === 'number') {
newValues[column.field] = 0
} else if (column.type === 'string') {
newValues[column.field] = ''
} else if (column.type === 'boolean') {
newValues[column.field] = false
} else {
newValues[column.field] = undefined
}
if (column.field === 'region_id') {
// column.valueGetter = (value: any) => {
// console.log(value)
// }
}
})
setRows((oldRows) => [...oldRows, { id, ...newValues, isNew: true }]);
setRowModesModel((oldModel) => ({
...oldModel,
[id]: { mode: GridRowModes.Edit, fieldToFocus: columns[0].field },
}))
};
return (
<GridToolbarContainer sx={{ px: '16px', py: '16px' }}>
{autoComplete &&
<Box sx={{ flexGrow: '1' }}>
{autoComplete}
</Box>
}
<Button color="primary" startIcon={<AddIcon />} onClick={handleClick}>
Добавить
</Button>
</GridToolbarContainer>
);
}
interface DataGridProps {
initialRows: GridRowsProp;
columns: GridColDef[];
actions: boolean;
onRowClick: GridEventListener<"rowClick">;
onSave: any;
onDelete: any;
autoComplete?: React.ReactElement | null;
loading: boolean;
}
export default function FullFeaturedCrudGrid({
initialRows,
columns,
actions = false,
//onRowClick,
onSave,
onDelete,
autoComplete,
loading
}: DataGridProps) {
const [rows, setRows] = useState(initialRows);
const [rowModesModel, setRowModesModel] = useState<GridRowModesModel>({});
const handleRowEditStop: GridEventListener<'rowEditStop'> = (params, event) => {
if (params.reason === GridRowEditStopReasons.rowFocusOut) {
event.defaultMuiPrevented = true;
}
};
const handleEditClick = (id: GridRowId) => () => {
setRowModesModel({ ...rowModesModel, [id]: { mode: GridRowModes.Edit } });
};
const handleSaveClick = (id: GridRowId) => () => {
setRowModesModel({ ...rowModesModel, [id]: { mode: GridRowModes.View } });
onSave?.(id)
};
const handleDeleteClick = (id: GridRowId) => () => {
setRows(rows.filter((row) => row.id !== id));
onDelete?.(id)
};
const handleCancelClick = (id: GridRowId) => () => {
setRowModesModel({
...rowModesModel,
[id]: { mode: GridRowModes.View, ignoreModifications: true },
});
const editedRow = rows.find((row) => row.id === id);
if (editedRow!.isNew) {
setRows(rows.filter((row) => row.id !== id));
}
};
const processRowUpdate = (newRow: GridRowModel) => {
const updatedRow = { ...newRow, isNew: false };
setRows(rows.map((row) => (row.id === newRow.id ? updatedRow : row)));
return updatedRow;
};
const handleRowModesModelChange = (newRowModesModel: GridRowModesModel) => {
setRowModesModel(newRowModesModel);
};
useEffect(() => {
if (initialRows) {
setRows(initialRows)
}
}, [initialRows])
const actionColumns: GridColDef[] = [
{
field: 'actions',
type: 'actions',
headerName: 'Действия',
width: 100,
cellClassName: 'actions',
getActions: ({ id }) => {
const isInEditMode = rowModesModel[id]?.mode === GridRowModes.Edit;
if (isInEditMode) {
return [
<GridActionsCellItem
icon={<SaveIcon />}
label="Save"
sx={{
color: 'primary.main',
}}
onClick={handleSaveClick(id)}
/>,
<GridActionsCellItem
icon={<CancelIcon />}
label="Cancel"
className="textPrimary"
onClick={handleCancelClick(id)}
color="inherit"
/>,
];
}
return [
<GridActionsCellItem
icon={<EditIcon />}
label="Edit"
className="textPrimary"
onClick={handleEditClick(id)}
color="inherit"
/>,
<GridActionsCellItem
icon={<DeleteIcon />}
label="Delete"
onClick={handleDeleteClick(id)}
color="inherit"
/>,
];
},
}
]
return (
<Box
sx={{
height: 500,
width: '100%',
'& .actions': {
color: 'text.secondary',
},
'& .textPrimary': {
color: 'text.primary',
},
}}
>
<DataGrid
loading={loading}
rows={rows || []}
columns={actions ? [...columns, ...actionColumns] : columns}
editMode="row"
rowModesModel={rowModesModel}
//onRowClick={onRowClick}
onRowModesModelChange={handleRowModesModelChange}
onRowEditStop={handleRowEditStop}
processRowUpdate={processRowUpdate}
slots={{
toolbar: EditToolbar as GridSlots['toolbar'],
}}
slotProps={{
toolbar: { setRows, setRowModesModel, columns, autoComplete },
}}
/>
</Box>
);
}

View File

@ -101,7 +101,7 @@ const ObjectList = ({
return ( return (
<NavLink p={0} label={`${label} ${count ? `(${count})` : ''}`}> <NavLink p={0} label={`${label} ${count ? `(${count})` : ''}`}>
{Array.isArray(data) && data.map((type) => ( {Array.isArray(data) && data.map((type) => (
<NavLink key={type.object_id} label={type.object_id} p={0} onClick={() => setCurrentObjectId(type.object_id)} /> <NavLink key={type.object_id} label={type.name} p={0} onClick={() => setCurrentObjectId(type.object_id)} />
))} ))}
</NavLink> </NavLink>
) )

View File

@ -2,13 +2,13 @@ import { useCallback, useEffect, useRef, useState } from 'react'
import 'ol/ol.css' import 'ol/ol.css'
import Map from 'ol/Map' import Map from 'ol/Map'
import View from 'ol/View' import View from 'ol/View'
import { Draw, Modify, Select, Snap, Translate } from 'ol/interaction' import { DragBox, Draw, Modify, Select, Snap, Translate } from 'ol/interaction'
import { ImageStatic, OSM, Vector as VectorSource, XYZ } from 'ol/source' import { ImageStatic, OSM, Vector as VectorSource, XYZ } from 'ol/source'
import { Tile as TileLayer, VectorImage, Vector as VectorLayer } from 'ol/layer' import { Tile as TileLayer, VectorImage, Vector as VectorLayer } from 'ol/layer'
import { click, never, platformModifierKeyOnly, primaryAction, shiftKeyOnly } from 'ol/events/condition' import { click, never, platformModifierKeyOnly, primaryAction, shiftKeyOnly } from 'ol/events/condition'
import Feature from 'ol/Feature' import Feature from 'ol/Feature'
import { IRectCoords, SatelliteMapsProvider } from '../../interfaces/map' import { IRectCoords, SatelliteMapsProvider } from '../../interfaces/map'
import { Extent } from 'ol/extent' import { Extent, getWidth } from 'ol/extent'
import { drawingLayerStyle, highlightStyleRed, highlightStyleYellow, overlayStyle, regionsLayerStyle } from './MapStyles' import { drawingLayerStyle, highlightStyleRed, highlightStyleYellow, overlayStyle, regionsLayerStyle } from './MapStyles'
import { googleMapsSatelliteSource, regionsLayerSource, yandexMapsSatelliteSource } from './MapSources' import { googleMapsSatelliteSource, regionsLayerSource, yandexMapsSatelliteSource } from './MapSources'
import ImageLayer from 'ol/layer/Image' import ImageLayer from 'ol/layer/Image'
@ -22,7 +22,7 @@ import { get, transform } from 'ol/proj'
import useSWR from 'swr' import useSWR from 'swr'
import { fetcher } from '../../http/axiosInstance' import { fetcher } from '../../http/axiosInstance'
import { BASE_URL } from '../../constants' import { BASE_URL } from '../../constants'
import { Accordion, ActionIcon, Autocomplete, Box, CloseButton, Flex, Select as MantineSelect, MantineStyleProp, rem, ScrollAreaAutosize, Slider, useMantineColorScheme, Portal, Timeline, Text, Stack, NavLink, Grid, Checkbox } from '@mantine/core' import { Accordion, ActionIcon, Autocomplete, Box, CloseButton, Flex, Select as MantineSelect, MantineStyleProp, rem, ScrollAreaAutosize, Slider, useMantineColorScheme, Portal, Timeline, Text, Stack, NavLink, Checkbox } from '@mantine/core'
import { IconPlus, IconSearch, IconSettings, IconTable, IconUpload } from '@tabler/icons-react' import { IconPlus, IconSearch, IconSettings, IconTable, IconUpload } from '@tabler/icons-react'
import { getGridCellPosition } from './mapUtils' import { getGridCellPosition } from './mapUtils'
import { IFigure, ILine } from '../../interfaces/gis' import { IFigure, ILine } from '../../interfaces/gis'
@ -32,7 +32,7 @@ import { IObjectParam } from '../../interfaces/objects'
import MapToolbar from './MapToolbar/MapToolbar' import MapToolbar from './MapToolbar/MapToolbar'
import MapStatusbar from './MapStatusbar/MapStatusbar' import MapStatusbar from './MapStatusbar/MapStatusbar'
import { measureStyleFunction, modifyStyle } from './Measure/MeasureStyles' import { measureStyleFunction, modifyStyle } from './Measure/MeasureStyles'
import { useMapStore } from '../../store/map' import { setCurrentCoordinate, setCurrentX, setCurrentY, setCurrentZ, setSatMapsProvider, useMapStore } from '../../store/map'
import { v4 as uuidv4 } from 'uuid' import { v4 as uuidv4 } from 'uuid'
import { useThrottle } from '@uidotdev/usehooks' import { useThrottle } from '@uidotdev/usehooks'
import ObjectTree from '../Tree/ObjectTree' import ObjectTree from '../Tree/ObjectTree'
@ -42,6 +42,8 @@ import { setCurrentObjectId, setSelectedCity, setSelectedYear, useObjectsStore }
const citySettings = [ const citySettings = [
{ {
city_id: 145, city_id: 145,
image_width: 8500,
image_height: 12544,
// scale: 10000, // scale: 10000,
scale: 9000, scale: 9000,
offset_x: 14442665.697619518, offset_x: 14442665.697619518,
@ -51,14 +53,11 @@ const citySettings = [
] ]
const MapComponent = () => { const MapComponent = () => {
// States
const { selectedCity, selectedYear, currentObjectId } = useObjectsStore() const { selectedCity, selectedYear, currentObjectId } = useObjectsStore()
const { currentTool, satMapsProvider } = useMapStore()
const mapState = useMapStore() ///
const [currentCoordinate, setCurrentCoordinate] = useState<Coordinate | null>(null)
const [currentZ, setCurrentZ] = useState<number | undefined>(undefined)
const [currentX, setCurrentX] = useState<number | undefined>(undefined)
const [currentY, setCurrentY] = useState<number | undefined>(undefined)
const [file, setFile] = useState<File | null>(null) const [file, setFile] = useState<File | null>(null)
const [polygonExtent, setPolygonExtent] = useState<Extent | undefined>(undefined) const [polygonExtent, setPolygonExtent] = useState<Extent | undefined>(undefined)
@ -85,12 +84,85 @@ const MapComponent = () => {
///// /////
// Box selection
const dragBox = useRef(new DragBox({
condition: platformModifierKeyOnly
}))
useEffect(() => {
if (dragBox.current) {
dragBox.current.on('boxend', function () {
const boxExtent = dragBox.current.getGeometry().getExtent();
// if the extent crosses the antimeridian process each world separately
const worldExtent = map.current?.getView().getProjection().getExtent();
if (worldExtent) {
const worldWidth = getWidth(worldExtent);
const startWorld = Math.floor((boxExtent[0] - worldExtent[0]) / worldWidth);
const endWorld = Math.floor((boxExtent[2] - worldExtent[0]) / worldWidth);
for (let world = startWorld; world <= endWorld; ++world) {
const left = Math.max(boxExtent[0] - world * worldWidth, worldExtent[0]);
const right = Math.min(boxExtent[2] - world * worldWidth, worldExtent[2]);
const extent = [left, boxExtent[1], right, boxExtent[3]];
const boxFeatures = vectorSource
.getFeaturesInExtent(extent)
.filter(
(feature) =>
!selectedFeatures.getArray().includes(feature) &&
feature.getGeometry().intersectsExtent(extent),
);
// features that intersect the box geometry are added to the
// collection of selected features
// if the view is not obliquely rotated the box geometry and
// its extent are equalivalent so intersecting features can
// be added directly to the collection
const rotation = map.getView().getRotation();
const oblique = rotation % (Math.PI / 2) !== 0;
// when the view is obliquely rotated the box extent will
// exceed its geometry so both the box and the candidate
// feature geometries are rotated around a common anchor
// to confirm that, with the box geometry aligned with its
// extent, the geometries intersect
if (oblique) {
const anchor = [0, 0];
const geometry = dragBox.getGeometry().clone();
geometry.translate(-world * worldWidth, 0);
geometry.rotate(-rotation, anchor);
const extent = geometry.getExtent();
boxFeatures.forEach(function (feature) {
const geometry = feature.getGeometry().clone();
geometry.rotate(-rotation, anchor);
if (geometry.intersectsExtent(extent)) {
selectedFeatures.push(feature);
}
});
} else {
selectedFeatures.extend(boxFeatures);
}
}
}
})
// clear selection when drawing a new box and when clicking on the map
dragBox.current.on('boxstart', function () {
selectedFeatures.clear();
})
}
}, [])
/////
const mapElement = useRef<HTMLDivElement | null>(null) const mapElement = useRef<HTMLDivElement | null>(null)
const map = useRef<Map | null>(null) const map = useRef<Map | null>(null)
const [satMapsProvider, setSatMapsProvider] = useState<SatelliteMapsProvider>('custom')
const gMapsSatSource = useRef<XYZ>(googleMapsSatelliteSource) const gMapsSatSource = useRef<XYZ>(googleMapsSatelliteSource)
const customMapSource = useRef<XYZ>(new XYZ({ const customMapSource = useRef<XYZ>(new XYZ({
@ -134,7 +206,7 @@ const MapComponent = () => {
} }
})) }))
const figuresLayer = useRef<VectorImage>(new VectorImage({ const figuresLayer = useRef<VectorLayer>(new VectorLayer({
source: new VectorSource(), source: new VectorSource(),
declutter: true, declutter: true,
properties: { properties: {
@ -143,7 +215,7 @@ const MapComponent = () => {
} }
})) }))
const linesLayer = useRef<VectorImage>(new VectorImage({ const linesLayer = useRef<VectorLayer>(new VectorLayer({
source: new VectorSource(), source: new VectorSource(),
declutter: true, declutter: true,
properties: { properties: {
@ -179,6 +251,14 @@ const MapComponent = () => {
} }
})) }))
const staticMapLayer = useRef<ImageLayer<ImageStatic>>(new ImageLayer({
properties: {
id: uuidv4(),
name: 'Static image'
}
}))
// tile processing // tile processing
const handleImageDrop = useCallback((event: DragEvent) => { const handleImageDrop = useCallback((event: DragEvent) => {
event.preventDefault(); event.preventDefault();
@ -360,6 +440,7 @@ const MapComponent = () => {
layers: [ layers: [
baseLayer.current, baseLayer.current,
satLayer.current, satLayer.current,
staticMapLayer.current,
regionsLayer.current, regionsLayer.current,
citiesLayer.current, citiesLayer.current,
linesLayer.current, linesLayer.current,
@ -373,7 +454,8 @@ const MapComponent = () => {
target: mapElement.current as HTMLDivElement, target: mapElement.current as HTMLDivElement,
view: new View({ view: new View({
center: transform([129.7466541, 62.083504], 'EPSG:4326', 'EPSG:3857'),//center: fromLonLat([130.401113, 67.797368]), center: transform([129.7466541, 62.083504], 'EPSG:4326', 'EPSG:3857'),//center: fromLonLat([130.401113, 67.797368]),
zoom: 16, //zoom: 16,
zoom: 15,
maxZoom: 21, maxZoom: 21,
//extent: mapExtent, //extent: mapExtent,
}), }),
@ -415,7 +497,7 @@ const MapComponent = () => {
loadFeatures(drawingLayerSource) loadFeatures(drawingLayerSource)
regionsInit(map, selectedRegion, regionsLayer, setStatusText) regionsInit(map, selectedRegion, regionsLayer)
if (mapElement.current) { if (mapElement.current) {
mapElement.current.addEventListener('dragover', (e) => { mapElement.current.addEventListener('dragover', (e) => {
@ -435,7 +517,7 @@ const MapComponent = () => {
}, []) }, [])
useEffect(() => { useEffect(() => {
if (mapState.currentTool) { if (currentTool) {
if (draw.current) map?.current?.removeInteraction(draw.current) if (draw.current) map?.current?.removeInteraction(draw.current)
//if (snap.current) map?.current?.removeInteraction(snap.current) //if (snap.current) map?.current?.removeInteraction(snap.current)
addInteractions(drawingLayerSource, draw, map, snap, measureDraw, measureSource, measureModify) addInteractions(drawingLayerSource, draw, map, snap, measureDraw, measureSource, measureModify)
@ -444,12 +526,10 @@ const MapComponent = () => {
if (snap.current) map?.current?.removeInteraction(snap.current) if (snap.current) map?.current?.removeInteraction(snap.current)
if (measureDraw.current) map?.current?.removeInteraction(measureDraw.current) if (measureDraw.current) map?.current?.removeInteraction(measureDraw.current)
} }
}, [mapState.currentTool]) }, [currentTool])
const [satelliteOpacity, setSatelliteOpacity] = useState<number>(0) const [satelliteOpacity, setSatelliteOpacity] = useState<number>(0)
const [statusText, setStatusText] = useState('')
// Visibility setting // Visibility setting
useEffect(() => { useEffect(() => {
satLayer.current?.setOpacity(satelliteOpacity) satLayer.current?.setOpacity(satelliteOpacity)
@ -468,7 +548,11 @@ const MapComponent = () => {
// Satellite tiles setting // Satellite tiles setting
useEffect(() => { useEffect(() => {
satLayer.current?.setSource(satMapsProvider == 'google' ? gMapsSatSource.current : satMapsProvider == 'yandex' ? yMapsSatSource.current : satMapsProvider == 'custom' ? customMapSource.current : gMapsSatSource.current) satLayer.current?.setSource(
satMapsProvider == 'google' ? gMapsSatSource.current :
satMapsProvider == 'yandex' ? yMapsSatSource.current :
satMapsProvider == 'custom' ? customMapSource.current :
gMapsSatSource.current)
satLayer.current?.getSource()?.refresh() satLayer.current?.getSource()?.refresh()
}, [satMapsProvider]) }, [satMapsProvider])
@ -517,7 +601,7 @@ const MapComponent = () => {
if (node.shape_type === 'LINE') { if (node.shape_type === 'LINE') {
const coordinates: Coordinate[] = [] const coordinates: Coordinate[] = []
if (Array.isArray(node.shape)) { if (Array.isArray(node.shape)) {
node.shape.map((point: any) => { node.shape.map((point: { x: number, y: number }) => {
const coordinate = [point.x as number, point.y as number] as Coordinate const coordinate = [point.x as number, point.y as number] as Coordinate
coordinates.push(coordinate) coordinates.push(coordinate)
}) })
@ -658,24 +742,26 @@ const MapComponent = () => {
w: 100000, w: 100000,
h: 100000 h: 100000
} }
let rotation = 0 //let rotation = 0
if (citySettings.find(el => el.city_id === selectedCity)) { const settings = citySettings.find(el => el.city_id === selectedCity)
if (settings) {
console.log("City settings found") console.log("City settings found")
if (citySettings.find(el => el.city_id === selectedCity)?.scale) { if (settings.scale) {
scale = { scale = {
w: citySettings.find(el => el.city_id === selectedCity).scale, w: settings.scale,
h: citySettings.find(el => el.city_id === selectedCity).scale h: settings.scale
} }
} }
if (citySettings.find(el => el.city_id === selectedCity)?.offset_x && citySettings.find(el => el.city_id === selectedCity)?.offset_y) { if (settings.offset_x && settings.offset_y) {
offset_x = citySettings.find(el => el.city_id === selectedCity).offset_x offset_x = settings.offset_x
offset_y = citySettings.find(el => el.city_id === selectedCity).offset_y offset_y = settings.offset_y
} }
if (citySettings.find(el => el.city_id === selectedCity)?.rotation) { if (settings.rotation) {
rotation = citySettings.find(el => el.city_id === selectedCity)?.rotation //rotation = settings.rotation
} }
} else { } else {
console.log("City settings NOT found") console.log("City settings NOT found")
@ -710,6 +796,78 @@ const MapComponent = () => {
} }
}, [figuresData, linesData, selectedCity, selectedYear]) }, [figuresData, linesData, selectedCity, selectedYear])
useEffect(() => {
if (selectedCity) {
let offset_x = 14442665.697619518
let offset_y = 8884520.63524492
//let scale = 9000
//let rotation = 0
//let image_width = 8500
//let image_height = 12544
const settings = citySettings.find(el => el.city_id === selectedCity)
if (settings) {
console.log("City settings found")
if (settings.scale) {
//scale = settings.scale
}
if (settings.offset_x && settings.offset_y) {
offset_x = settings.offset_x
offset_y = settings.offset_y
}
if (settings.image_width && settings.image_height) {
//image_width = settings.image_width
//image_height = settings.image_height
}
if (settings.rotation) {
//rotation = settings.rotation
}
} else {
console.log("City settings NOT found")
}
const imageUrl = `${import.meta.env.VITE_API_EMS_URL}/static/${selectedCity}`;
const img = new Image();
img.src = imageUrl;
img.onload = () => {
if (map.current) {
const width = img.naturalWidth;
const height = img.naturalHeight;
console.log(width, height)
//const k = (width < height ? width / height : height / width)
const k = 0.40340
console.log(k)
const wk = width * k
const hk = height * k
const center = [offset_x + (wk), offset_y - (hk)];
const extent = [
center[0] - (wk),
center[1] - (hk),
center[0] + (wk),
center[1] + (hk),
];
// Set up the initial image layer with the extent
const imageSource = new ImageStatic({
url: imageUrl,
imageExtent: extent,
});
staticMapLayer.current.setSource(imageSource);
//map.current.addLayer(imageLayer.current);
}
};
}
}, [selectedCity])
useEffect(() => { useEffect(() => {
// if (map.current) { // if (map.current) {
@ -754,7 +912,7 @@ const MapComponent = () => {
<Flex align='center' direction='row' gap='sm'> <Flex align='center' direction='row' 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)} /> <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)} /> <MantineSelect variant='filled' value={satMapsProvider} data={[{ label: 'Google', value: 'google' }, { label: 'Yandex', value: 'yandex' }, { label: 'Custom', value: 'custom' }, { label: 'Static', value: 'static' }]} onChange={(value) => setSatMapsProvider(value as SatelliteMapsProvider)} />
</Flex> </Flex>
<form> <form>
@ -949,11 +1107,6 @@ const MapComponent = () => {
<MapStatusbar <MapStatusbar
mapControlsStyle={mapControlsStyle} mapControlsStyle={mapControlsStyle}
currentCoordinate={currentCoordinate}
currentX={currentX}
currentY={currentY}
currentZ={currentZ}
statusText={statusText}
/> />
</Flex> </Flex>

View File

@ -1,50 +1,42 @@
import { Divider, Flex, rem, Text } from '@mantine/core' import { Divider, Flex, rem, Text } from '@mantine/core'
import { Coordinate } from 'ol/coordinate'; import { CSSProperties } from 'react'
import React, { CSSProperties } from 'react' import { useMapStore } from '../../../store/map';
interface IMapStatusbarProps { interface IMapStatusbarProps {
mapControlsStyle: CSSProperties; mapControlsStyle: CSSProperties;
currentCoordinate: Coordinate | null;
currentX: number | undefined;
currentY: number | undefined;
currentZ: number | undefined;
statusText: string;
} }
const MapStatusbar = ({ const MapStatusbar = ({
mapControlsStyle, mapControlsStyle,
currentCoordinate,
currentX,
currentY,
currentZ,
statusText
}: IMapStatusbarProps) => { }: IMapStatusbarProps) => {
const mapState = useMapStore()
return ( return (
<Flex gap='sm' p={'4px'} miw={'100%'} fz={'xs'} pos='absolute' bottom='0px' left='0px' style={{ ...mapControlsStyle, borderRadius: 0 }}> <Flex gap='sm' p={'4px'} miw={'100%'} fz={'xs'} pos='absolute' bottom='0px' left='0px' style={{ ...mapControlsStyle, borderRadius: 0 }}>
<Text fz='xs' w={rem(130)}> <Text fz='xs' w={rem(130)}>
x: {currentCoordinate?.[0]} x: {mapState.currentCoordinate?.[0]}
</Text> </Text>
<Text fz='xs' w={rem(130)}> <Text fz='xs' w={rem(130)}>
y: {currentCoordinate?.[1]} y: {mapState.currentCoordinate?.[1]}
</Text> </Text>
<Divider orientation='vertical' /> <Divider orientation='vertical' />
<Text fz='xs'> <Text fz='xs'>
Z={currentZ} Z={mapState.currentZ}
</Text> </Text>
<Text fz='xs'> <Text fz='xs'>
X={currentX} X={mapState.currentX}
</Text> </Text>
<Text fz='xs'> <Text fz='xs'>
Y={currentY} Y={mapState.currentY}
</Text> </Text>
<Text fz='xs' ml='auto'> <Text fz='xs' ml='auto'>
{statusText} {mapState.statusText}
</Text> </Text>
</Flex> </Flex>
) )

View File

@ -20,15 +20,14 @@ import ImageLayer from "ol/layer/Image";
import { IFigure, ILine } from "../../interfaces/gis"; import { IFigure, ILine } from "../../interfaces/gis";
import { fromCircle } from "ol/geom/Polygon"; import { fromCircle } from "ol/geom/Polygon";
import { measureStyleFunction, modifyStyle } from "./Measure/MeasureStyles"; import { measureStyleFunction, modifyStyle } from "./Measure/MeasureStyles";
import { getCurrentTool, getMeasureClearPrevious, getMeasureType, getTipPoint } from "../../store/map"; import { getCurrentTool, getMeasureClearPrevious, getMeasureType, getTipPoint, setStatusText } from "../../store/map";
import { VectorImage } from "ol/layer";
import { MutableRefObject } from "react"; import { MutableRefObject } from "react";
export function processLine( export function processLine(
line: ILine, line: ILine,
scaling: { w: number, h: number }, scaling: { w: number, h: number },
mapCenter: Coordinate, mapCenter: Coordinate,
linesLayer: React.MutableRefObject<VectorImage<Feature<Geometry>, VectorSource<Feature<Geometry>>>> linesLayer: MutableRefObject<VectorLayer<VectorSource>>
) { ) {
const x1 = line.x1 * scaling.w const x1 = line.x1 * scaling.w
const y1 = line.y1 * scaling.h const y1 = line.y1 * scaling.h
@ -55,7 +54,7 @@ export function processFigure(
figure: IFigure, figure: IFigure,
scaling: { w: number, h: number }, scaling: { w: number, h: number },
mapCenter: Coordinate, mapCenter: Coordinate,
figuresLayer: React.MutableRefObject<VectorImage<Feature<Geometry>, VectorSource<Feature<Geometry>>>> figuresLayer: MutableRefObject<VectorLayer<VectorSource>>
) { ) {
if (figure.figure_type_id == 1) { if (figure.figure_type_id == 1) {
const width = figure.width * scaling.w const width = figure.width * scaling.w
@ -262,8 +261,6 @@ export function regionsInit(
map: React.MutableRefObject<Map | null>, map: React.MutableRefObject<Map | null>,
selectedRegion: React.MutableRefObject<Feature<Geometry> | null>, selectedRegion: React.MutableRefObject<Feature<Geometry> | null>,
regionsLayer: React.MutableRefObject<VectorImageLayer<Feature<Geometry>, VectorSource<Feature<Geometry>>>>, regionsLayer: React.MutableRefObject<VectorImageLayer<Feature<Geometry>, VectorSource<Feature<Geometry>>>>,
setStatusText: (value: React.SetStateAction<string>) => void,
) { ) {
map.current?.on('click', function (e) { map.current?.on('click', function (e) {
if (selectedRegion.current !== null) { if (selectedRegion.current !== null) {

View File

@ -1,6 +1,4 @@
import { useEffect, useRef } from 'react' import { useEffect, useRef } from 'react'
import { AppBar, Box, Button, CircularProgress, Dialog, IconButton, Toolbar, Typography } from '@mui/material';
import { ChevronLeft, ChevronRight, Close, Warning } from '@mui/icons-material';
import { useDownload, useFileType } from '../../hooks/swrHooks'; import { useDownload, useFileType } from '../../hooks/swrHooks';
import jsPreviewExcel from "@js-preview/excel" import jsPreviewExcel from "@js-preview/excel"
@ -11,6 +9,8 @@ import '@js-preview/docx/lib/index.css'
import jsPreviewPdf from '@js-preview/pdf' import jsPreviewPdf from '@js-preview/pdf'
import { IDocument } from '../../interfaces/documents'; import { IDocument } from '../../interfaces/documents';
import { IconAlertTriangle, IconChevronLeft, IconChevronRight } from '@tabler/icons-react';
import { Button, Flex, Grid, Loader, Modal, ScrollAreaAutosize, Text } from '@mantine/core';
interface Props { interface Props {
open: boolean; open: boolean;
@ -45,9 +45,9 @@ function PdfViewer({
}, [previewContainerRef]) }, [previewContainerRef])
return ( return (
<Box ref={previewContainerRef} sx={{ <div ref={previewContainerRef} style={{
width: '100%', width: '100%',
height: '100%' height: '100%',
}} /> }} />
) )
} }
@ -75,9 +75,9 @@ function DocxViewer({
}, []) }, [])
return ( return (
<Box ref={previewContainerRef} sx={{ <div ref={previewContainerRef} style={{
width: '100%', width: '100%',
height: '100%' height: '100%',
}} /> }} />
) )
} }
@ -101,9 +101,9 @@ function ExcelViewer({
}, []) }, [])
return ( return (
<Box ref={previewContainerRef} sx={{ <div ref={previewContainerRef} style={{
width: '100%', width: '100%',
height: '100%' height: '100%',
}} /> }} />
) )
} }
@ -112,7 +112,7 @@ function ImageViewer({
url url
}: ViewerProps) { }: ViewerProps) {
return ( return (
<Box sx={{ <Flex style={{
display: 'flex', display: 'flex',
alignItems: 'center', alignItems: 'center',
justifyContent: 'center', justifyContent: 'center',
@ -125,7 +125,7 @@ function ImageViewer({
maxWidth: '100%', maxWidth: '100%',
maxHeight: '100%' maxHeight: '100%'
}} /> }} />
</Box> </Flex>
) )
} }
@ -151,118 +151,106 @@ export default function FileViewer({
} }
return ( return (
<Dialog <Modal.Root fullScreen opened={open} onClose={() => setOpen(false)} scrollAreaComponent={ScrollAreaAutosize.Autosize}>
fullScreen <Modal.Overlay />
open={open} <Modal.Content style={{
onClose={() => { display: 'grid',
setOpen(false) gridTemplateRows: 'min-content auto',
setCurrentFileNo(-1) width: '100vw',
}} height: '100vh'
aria-labelledby="modal-modal-title"
aria-describedby="modal-modal-description"
>
<AppBar sx={{ position: 'sticky' }}>
<Toolbar>
<IconButton
edge="start"
color="inherit"
onClick={() => {
setOpen(false)
setCurrentFileNo(-1)
}}
aria-label="close"
>
<Close />
</IconButton>
<Typography sx={{ ml: 2, flex: 1 }} variant="h6" component="div">
{currentFileNo != -1 && docs[currentFileNo].name}
</Typography>
<div>
<IconButton
color='inherit'
onClick={() => {
if (currentFileNo >= 0 && currentFileNo > 0) {
setCurrentFileNo(currentFileNo - 1)
}
}}
disabled={currentFileNo >= 0 && currentFileNo === 0}
>
<ChevronLeft />
</IconButton>
<IconButton
color='inherit'
onClick={() => {
if (currentFileNo >= 0 && currentFileNo < docs.length) {
setCurrentFileNo(currentFileNo + 1)
}
}}
disabled={currentFileNo >= 0 && currentFileNo >= docs.length - 1}
>
<ChevronRight />
</IconButton>
</div>
<Button
autoFocus
color="inherit"
onClick={handleSave}
>
Сохранить
</Button>
</Toolbar>
</AppBar>
<Box sx={{
flexGrow: '1',
overflowY: 'hidden'
}}> }}>
{fileIsLoading || fileTypeIsLoading ? <Modal.Header>
<Box sx={{ <Modal.Title component='div' w='100%'>
display: 'flex', <Flex align='center'>
width: '100%', <Text mr='auto'>{currentFileNo != -1 && docs[currentFileNo].name}</Text>
height: '100%',
alignItems: 'center',
justifyContent: 'center'
}}>
<CircularProgress />
</Box>
:
fileType === 'application/pdf' ?
<PdfViewer url={window.URL.createObjectURL(file)} />
:
fileType === 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' ?
<ExcelViewer url={window.URL.createObjectURL(file)} />
:
fileType === 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' ?
<DocxViewer url={window.URL.createObjectURL(file)} />
:
fileType?.startsWith('image/') ?
<ImageViewer url={window.URL.createObjectURL(file)} />
:
fileType && file ?
<Box sx={{ display: 'flex', gap: '16px', flexDirection: 'column', p: '16px' }}>
<Box sx={{ display: 'flex', gap: '16px', alignItems: 'center' }}>
<Warning />
<Typography>
Предпросмотр данного файла невозможен.
</Typography>
</Box>
<Box> <Grid>
<Button variant='contained' onClick={() => { <Grid.Col span='auto'>
handleSave() <Button
}}> variant='transparent'
Сохранить onClick={() => {
</Button> if (currentFileNo >= 0 && currentFileNo > 0) {
</Box> setCurrentFileNo(currentFileNo - 1)
</Box> }
}}
disabled={currentFileNo >= 0 && currentFileNo === 0}
>
<IconChevronLeft />
</Button>
</Grid.Col>
<Grid.Col span='auto'>
<Button
variant='transparent'
onClick={() => {
if (currentFileNo >= 0 && currentFileNo < docs.length) {
setCurrentFileNo(currentFileNo + 1)
}
}}
disabled={currentFileNo >= 0 && currentFileNo >= docs.length - 1}
>
<IconChevronRight />
</Button>
</Grid.Col>
</Grid>
<Button
autoFocus
variant='subtle'
onClick={handleSave}
>
Сохранить
</Button>
</Flex>
</Modal.Title>
<Modal.CloseButton ml='xl' />
</Modal.Header>
<Modal.Body style={{ display: 'flex', flexGrow: 1, height: '100%', width: '100vw' }}>
{fileIsLoading || fileTypeIsLoading ?
<Flex style={{
display: 'flex',
width: '100%',
height: '100%',
alignItems: 'center',
justifyContent: 'center'
}}>
<Loader />
</Flex>
:
fileType === 'application/pdf' ?
<PdfViewer url={window.URL.createObjectURL(file)} />
:
fileType === 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' ?
<ExcelViewer url={window.URL.createObjectURL(file)} />
:
fileType === 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' ?
<DocxViewer url={window.URL.createObjectURL(file)} />
:
fileType?.startsWith('image/') ?
<ImageViewer url={window.URL.createObjectURL(file)} />
: :
null fileType && file ?
} <Flex style={{ display: 'flex', gap: '16px', flexDirection: 'column', p: '16px' }}>
</Box> <Flex style={{ display: 'flex', gap: '16px', alignItems: 'center' }}>
</Dialog> <IconAlertTriangle />
<Text>
Предпросмотр данного файла невозможен.
</Text>
</Flex>
<Flex>
<Button variant='contained' onClick={() => {
handleSave()
}}>
Сохранить
</Button>
</Flex>
</Flex>
:
null
}
</Modal.Body>
</Modal.Content>
</Modal.Root>
) )
} }

View File

@ -1,18 +1,8 @@
import { Coordinate } from "ol/coordinate"; import { Coordinate } from "ol/coordinate";
export interface SatelliteMapsProviders { export type SatelliteMapsProvider = 'google' | 'yandex' | 'custom' | 'static'
google: 'google';
yandex: 'yandex';
custom: 'custom';
}
export type SatelliteMapsProvider = SatelliteMapsProviders[keyof SatelliteMapsProviders]
export interface IGeometryTypes { export type IGeometryType = 'LINE' | 'POLYGON'
LINE: 'LINE'
POLYGON: 'POLYGON'
}
export type IGeometryType = IGeometryTypes[keyof IGeometryTypes]
export interface IRectCoords { export interface IRectCoords {
bl: Coordinate | undefined, bl: Coordinate | undefined,

View File

@ -1,51 +0,0 @@
import { useCities } from "../hooks/swrHooks"
import { useEffect, useState } from "react"
import { DataGrid, GridColDef } from "@mui/x-data-grid"
import axiosInstance from "../http/axiosInstance"
import { BASE_URL } from "../constants"
import { Flex } from "@mantine/core"
export default function ApiTest() {
const limit = 10
const [paginationModel, setPaginationModel] = useState({
page: 1,
pageSize: limit
})
const [rowCount, setRowCount] = useState(0)
const fetchCount = async () => {
await axiosInstance.get(`/general/cities_count`, {
baseURL: BASE_URL.fuel
}).then(response => {
setRowCount(response.data)
})
}
const { cities, isLoading } = useCities(paginationModel.pageSize, paginationModel.page)
useEffect(() => {
fetchCount()
}, [])
const citiesColumns: GridColDef[] = [
{ field: 'id' },
{ field: 'name' },
]
return (
<Flex direction='column' gap='sm' h='100%'>
<DataGrid
rows={cities || []}
columns={citiesColumns}
paginationMode='server'
rowCount={rowCount}
loading={isLoading}
paginationModel={paginationModel}
onPaginationModelChange={setPaginationModel}
/>
</Flex>
)
}

View File

@ -1,4 +1,3 @@
import { GridColDef } from '@mui/x-data-grid'
import { useEffect, useState } from 'react' import { useEffect, useState } from 'react'
import { useBoilers } from '../hooks/swrHooks' import { useBoilers } from '../hooks/swrHooks'
import { Badge, ScrollAreaAutosize, Table, Text } from '@mantine/core' import { Badge, ScrollAreaAutosize, Table, Text } from '@mantine/core'
@ -24,7 +23,7 @@ function Boilers() {
setBoilerSearch("") setBoilerSearch("")
}, []) }, [])
const boilersColumns: GridColDef[] = [ const boilersColumns = [
{ field: 'id_object', headerName: 'ID', type: "number" }, { field: 'id_object', headerName: 'ID', type: "number" },
{ field: 'boiler_name', headerName: 'Название', type: "string", flex: 1 }, { field: 'boiler_name', headerName: 'Название', type: "string", flex: 1 },
{ field: 'boiler_code', headerName: 'Код', type: "string", flex: 1 }, { field: 'boiler_code', headerName: 'Код', type: "string", flex: 1 },
@ -48,7 +47,7 @@ function Boilers() {
</Table.Tr> </Table.Tr>
</Table.Thead> </Table.Thead>
<Table.Tbody> <Table.Tbody>
{boilers.map((boiler: any) => ( {boilers.map((boiler: {id_object: string, activity: boolean}) => (
<Table.Tr key={boiler.id_object}> <Table.Tr key={boiler.id_object}>
{boilersColumns.map(column => { {boilersColumns.map(column => {
if (column.field === 'activity') { if (column.field === 'activity') {

View File

@ -1,4 +1,3 @@
import { GridColDef } from '@mui/x-data-grid'
import { useRoles } from '../hooks/swrHooks' import { useRoles } from '../hooks/swrHooks'
import { CreateField } from '../interfaces/create' import { CreateField } from '../interfaces/create'
import RoleService from '../services/RoleService' import RoleService from '../services/RoleService'
@ -16,7 +15,7 @@ export default function Roles() {
{ key: 'description', headerName: 'Описание', type: 'string', required: false, defaultValue: '' }, { key: 'description', headerName: 'Описание', type: 'string', required: false, defaultValue: '' },
] ]
const columns: GridColDef[] = [ const columns = [
{ field: 'id', headerName: 'ID', type: "number" }, { field: 'id', headerName: 'ID', type: "number" },
{ field: 'name', headerName: 'Название', flex: 1, editable: true }, { field: 'name', headerName: 'Название', flex: 1, editable: true },
{ field: 'description', headerName: 'Описание', flex: 1, editable: true }, { field: 'description', headerName: 'Описание', flex: 1, editable: true },

View File

@ -1,4 +1,3 @@
import { GridColDef } from "@mui/x-data-grid"
import { useRoles, useUsers } from "../hooks/swrHooks" import { useRoles, useUsers } from "../hooks/swrHooks"
import { IRole } from "../interfaces/role" import { IRole } from "../interfaces/role"
import { useEffect, useState } from "react" import { useEffect, useState } from "react"
@ -32,7 +31,7 @@ export default function Users() {
{ key: 'password', headerName: 'Пароль', type: 'string', required: true, defaultValue: '' }, { key: 'password', headerName: 'Пароль', type: 'string', required: true, defaultValue: '' },
] ]
const columns: GridColDef[] = [ const columns = [
{ field: 'id', headerName: 'ID', type: "number", flex: 1 }, { field: 'id', headerName: 'ID', type: "number", flex: 1 },
{ field: 'email', headerName: 'Email', flex: 1, editable: true }, { field: 'email', headerName: 'Email', flex: 1, editable: true },
{ field: 'login', headerName: 'Логин', flex: 1, editable: true }, { field: 'login', headerName: 'Логин', flex: 1, editable: true },

View File

@ -1,8 +1,8 @@
import { useState } from 'react' import { useState } from 'react'
import { SubmitHandler, useForm } from 'react-hook-form'; import { SubmitHandler, useForm } from 'react-hook-form';
import AuthService from '../../services/AuthService'; import AuthService from '../../services/AuthService';
import { CheckCircle } from '@mui/icons-material';
import { Button, Flex, Loader, Paper, Text, TextInput, Transition } from '@mantine/core'; import { Button, Flex, Loader, Paper, Text, TextInput, Transition } from '@mantine/core';
import { IconCheck } from '@tabler/icons-react';
interface PasswordResetProps { interface PasswordResetProps {
email: string; email: string;
@ -73,7 +73,7 @@ function PasswordReset() {
{(styles) => {(styles) =>
<Flex style={styles} direction='column' gap='sm'> <Flex style={styles} direction='column' gap='sm'>
<Flex align='center' gap='sm'> <Flex align='center' gap='sm'>
<CheckCircle color='success' /> <IconCheck />
<Text> <Text>
На указанный адрес было отправлено письмо с новыми данными для авторизации. На указанный адрес было отправлено письмо с новыми данными для авторизации.
</Text> </Text>

View File

@ -2,14 +2,22 @@ import { create } from 'zustand';
import { ToolType } from '../types/tools'; import { ToolType } from '../types/tools';
import { Point } from 'ol/geom'; import { Point } from 'ol/geom';
import Map from 'ol/Map'; import Map from 'ol/Map';
import { Coordinate } from 'ol/coordinate';
import { SatelliteMapsProvider } from '../interfaces/map';
interface MapState { interface MapState {
currentTool: ToolType, currentTool: ToolType;
measureType: "LineString" | "Polygon", measureType: "LineString" | "Polygon";
measureShowSegments: boolean, measureShowSegments: boolean;
measureClearPrevious: boolean, measureClearPrevious: boolean;
tipPoint: Point | null, tipPoint: Point | null;
map: Map | null map: Map | null;
currentZ: number | undefined;
currentX: number | undefined;
currentY: number | undefined;
currentCoordinate: Coordinate | null;
statusText: string;
satMapsProvider: SatelliteMapsProvider;
} }
export const useMapStore = create<MapState>(() => ({ export const useMapStore = create<MapState>(() => ({
@ -18,16 +26,21 @@ export const useMapStore = create<MapState>(() => ({
measureShowSegments: true, measureShowSegments: true,
measureClearPrevious: true, measureClearPrevious: true,
tipPoint: null, tipPoint: null,
map: null map: null,
currentZ: undefined,
currentX: undefined,
currentY: undefined,
currentCoordinate: null,
statusText: '',
satMapsProvider: 'custom'
})); }));
const getMap = () => { const setCurrentZ = (z: number | undefined) => useMapStore.setState(() => ({ currentZ: z }))
return useMapStore.getState().map const setCurrentX = (x: number | undefined) => useMapStore.setState(() => ({ currentX: x }))
} const setCurrentY = (y: number | undefined) => useMapStore.setState(() => ({ currentY: y }))
const setCurrentCoordinate = (c: Coordinate | null) => useMapStore.setState(() => ({ currentCoordinate: c }))
const setMap = (map: Map | null) => { const setStatusText = (t: string) => useMapStore.setState(() => ({ statusText: t }))
useMapStore.setState(() => ({ map: map })) const setSatMapsProvider = (p: SatelliteMapsProvider) => useMapStore.setState(() => ({ satMapsProvider: p }))
}
const setTipPoint = (tipPoint: Point | null) => { const setTipPoint = (tipPoint: Point | null) => {
useMapStore.setState(() => ({ tipPoint: tipPoint })) useMapStore.setState(() => ({ tipPoint: tipPoint }))
@ -81,5 +94,11 @@ export {
setMeasureType, setMeasureType,
getMeasureType, getMeasureType,
getTipPoint, getTipPoint,
setTipPoint setTipPoint,
setCurrentZ,
setCurrentX,
setCurrentY,
setCurrentCoordinate,
setStatusText,
setSatMapsProvider
} }

View File

@ -29,7 +29,7 @@
jsonpointer "^5.0.0" jsonpointer "^5.0.0"
leven "^3.1.0" leven "^3.1.0"
"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.24.7": "@babel/code-frame@^7.24.7":
version "7.24.7" version "7.24.7"
resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.7.tgz" resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.7.tgz"
integrity sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA== integrity sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==
@ -164,7 +164,7 @@
"@babel/traverse" "^7.24.7" "@babel/traverse" "^7.24.7"
"@babel/types" "^7.24.7" "@babel/types" "^7.24.7"
"@babel/helper-module-imports@^7.10.4", "@babel/helper-module-imports@^7.16.7", "@babel/helper-module-imports@^7.24.7": "@babel/helper-module-imports@^7.10.4", "@babel/helper-module-imports@^7.24.7":
version "7.24.7" version "7.24.7"
resolved "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.7.tgz" resolved "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.7.tgz"
integrity sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA== integrity sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA==
@ -936,7 +936,7 @@
resolved "https://registry.npmjs.org/@babel/regjsgen/-/regjsgen-0.8.0.tgz" resolved "https://registry.npmjs.org/@babel/regjsgen/-/regjsgen-0.8.0.tgz"
integrity sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA== integrity sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==
"@babel/runtime@^7.11.2", "@babel/runtime@^7.12.5", "@babel/runtime@^7.14.0", "@babel/runtime@^7.18.3", "@babel/runtime@^7.20.13", "@babel/runtime@^7.23.9", "@babel/runtime@^7.24.7", "@babel/runtime@^7.5.5", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7": "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.5", "@babel/runtime@^7.14.0", "@babel/runtime@^7.20.13", "@babel/runtime@^7.5.5", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7":
version "7.24.7" version "7.24.7"
resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.7.tgz" resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.7.tgz"
integrity sha512-UwgBRMjJP+xv857DCngvqXI3Iq6J4v0wXmwc6sapg+zyhbwmQX67LUEFrkK5tbyJ30jGuG3ZvWpBiB9LCy1kWw== integrity sha512-UwgBRMjJP+xv857DCngvqXI3Iq6J4v0wXmwc6sapg+zyhbwmQX67LUEFrkK5tbyJ30jGuG3ZvWpBiB9LCy1kWw==
@ -982,113 +982,6 @@
resolved "https://registry.npmjs.org/@bufbuild/protobuf/-/protobuf-2.2.0.tgz" resolved "https://registry.npmjs.org/@bufbuild/protobuf/-/protobuf-2.2.0.tgz"
integrity sha512-+imAQkHf7U/Rwvu0wk1XWgsP3WnpCWmK7B48f0XqSNzgk64+grljTKC7pnO/xBiEMUziF7vKRfbBnOQhg126qQ== integrity sha512-+imAQkHf7U/Rwvu0wk1XWgsP3WnpCWmK7B48f0XqSNzgk64+grljTKC7pnO/xBiEMUziF7vKRfbBnOQhg126qQ==
"@emotion/babel-plugin@^11.11.0":
version "11.11.0"
resolved "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.11.0.tgz"
integrity sha512-m4HEDZleaaCH+XgDDsPF15Ht6wTLsgDTeR3WYj9Q/k76JtWhrJjcP4+/XlG8LGT/Rol9qUfOIztXeA84ATpqPQ==
dependencies:
"@babel/helper-module-imports" "^7.16.7"
"@babel/runtime" "^7.18.3"
"@emotion/hash" "^0.9.1"
"@emotion/memoize" "^0.8.1"
"@emotion/serialize" "^1.1.2"
babel-plugin-macros "^3.1.0"
convert-source-map "^1.5.0"
escape-string-regexp "^4.0.0"
find-root "^1.1.0"
source-map "^0.5.7"
stylis "4.2.0"
"@emotion/cache@^11.11.0":
version "11.11.0"
resolved "https://registry.npmjs.org/@emotion/cache/-/cache-11.11.0.tgz"
integrity sha512-P34z9ssTCBi3e9EI1ZsWpNHcfY1r09ZO0rZbRO2ob3ZQMnFI35jB536qoXbkdesr5EUhYi22anuEJuyxifaqAQ==
dependencies:
"@emotion/memoize" "^0.8.1"
"@emotion/sheet" "^1.2.2"
"@emotion/utils" "^1.2.1"
"@emotion/weak-memoize" "^0.3.1"
stylis "4.2.0"
"@emotion/hash@^0.9.1":
version "0.9.1"
resolved "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.1.tgz"
integrity sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ==
"@emotion/is-prop-valid@^1.2.2":
version "1.2.2"
resolved "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.2.2.tgz"
integrity sha512-uNsoYd37AFmaCdXlg6EYD1KaPOaRWRByMCYzbKUX4+hhMfrxdVSelShywL4JVaAeM/eHUOSprYBQls+/neX3pw==
dependencies:
"@emotion/memoize" "^0.8.1"
"@emotion/memoize@^0.8.1":
version "0.8.1"
resolved "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.1.tgz"
integrity sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==
"@emotion/react@^11.0.0-rc.0", "@emotion/react@^11.11.4", "@emotion/react@^11.4.1", "@emotion/react@^11.5.0", "@emotion/react@^11.9.0":
version "11.11.4"
resolved "https://registry.npmjs.org/@emotion/react/-/react-11.11.4.tgz"
integrity sha512-t8AjMlF0gHpvvxk5mAtCqR4vmxiGHCeJBaQO6gncUSdklELOgtwjerNY2yuJNfwnc6vi16U/+uMF+afIawJ9iw==
dependencies:
"@babel/runtime" "^7.18.3"
"@emotion/babel-plugin" "^11.11.0"
"@emotion/cache" "^11.11.0"
"@emotion/serialize" "^1.1.3"
"@emotion/use-insertion-effect-with-fallbacks" "^1.0.1"
"@emotion/utils" "^1.2.1"
"@emotion/weak-memoize" "^0.3.1"
hoist-non-react-statics "^3.3.1"
"@emotion/serialize@^1.1.2", "@emotion/serialize@^1.1.3", "@emotion/serialize@^1.1.4":
version "1.1.4"
resolved "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.1.4.tgz"
integrity sha512-RIN04MBT8g+FnDwgvIUi8czvr1LU1alUMI05LekWB5DGyTm8cCBMCRpq3GqaiyEDRptEXOyXnvZ58GZYu4kBxQ==
dependencies:
"@emotion/hash" "^0.9.1"
"@emotion/memoize" "^0.8.1"
"@emotion/unitless" "^0.8.1"
"@emotion/utils" "^1.2.1"
csstype "^3.0.2"
"@emotion/sheet@^1.2.2":
version "1.2.2"
resolved "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.2.2.tgz"
integrity sha512-0QBtGvaqtWi+nx6doRwDdBIzhNdZrXUppvTM4dtZZWEGTXL/XE/yJxLMGlDT1Gt+UHH5IX1n+jkXyytE/av7OA==
"@emotion/styled@^11.11.5", "@emotion/styled@^11.3.0", "@emotion/styled@^11.8.1":
version "11.11.5"
resolved "https://registry.npmjs.org/@emotion/styled/-/styled-11.11.5.tgz"
integrity sha512-/ZjjnaNKvuMPxcIiUkf/9SHoG4Q196DRl1w82hQ3WCsjo1IUR8uaGWrC6a87CrYAW0Kb/pK7hk8BnLgLRi9KoQ==
dependencies:
"@babel/runtime" "^7.18.3"
"@emotion/babel-plugin" "^11.11.0"
"@emotion/is-prop-valid" "^1.2.2"
"@emotion/serialize" "^1.1.4"
"@emotion/use-insertion-effect-with-fallbacks" "^1.0.1"
"@emotion/utils" "^1.2.1"
"@emotion/unitless@^0.8.1":
version "0.8.1"
resolved "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.1.tgz"
integrity sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ==
"@emotion/use-insertion-effect-with-fallbacks@^1.0.1":
version "1.0.1"
resolved "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.0.1.tgz"
integrity sha512-jT/qyKZ9rzLErtrjGgdkMBn2OP8wl0G3sQlBb3YPryvKHsjvINUhVaPFfP+fpBcOkmrVOVEEHQFJ7nbj2TH2gw==
"@emotion/utils@^1.2.1":
version "1.2.1"
resolved "https://registry.npmjs.org/@emotion/utils/-/utils-1.2.1.tgz"
integrity sha512-Y2tGf3I+XVnajdItskUCn6LX+VUDmP6lTL4fcqsXAv43dnlbZiuW4MWQW38rW/BVWSE7Q/7+XQocmpnRYILUmg==
"@emotion/weak-memoize@^0.3.1":
version "0.3.1"
resolved "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.3.1.tgz"
integrity sha512-EsBwpc7hBUJWAsNPBmJy4hxWx12v6bshQsldrVmjxJoc3isbxhOrF2IcCpaXxfvq03NwkI7sbsOLXbYuqF/8Ww==
"@esbuild/win32-x64@0.21.5": "@esbuild/win32-x64@0.21.5":
version "0.21.5" version "0.21.5"
resolved "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz" resolved "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz"
@ -1141,7 +1034,7 @@
"@floating-ui/core" "^1.0.0" "@floating-ui/core" "^1.0.0"
"@floating-ui/utils" "^0.2.0" "@floating-ui/utils" "^0.2.0"
"@floating-ui/react-dom@^2.0.8", "@floating-ui/react-dom@^2.1.2": "@floating-ui/react-dom@^2.1.2":
version "2.1.2" version "2.1.2"
resolved "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.2.tgz" resolved "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.2.tgz"
integrity sha512-06okr5cgPzMNBy+Ycse2A6udMi4bqwW/zgBF/rwjcNqWkyr82Mcg8b0vjX8OJpZFy/FKjJmw6wV7t44kK6kW7A== integrity sha512-06okr5cgPzMNBy+Ycse2A6udMi4bqwW/zgBF/rwjcNqWkyr82Mcg8b0vjX8OJpZFy/FKjJmw6wV7t44kK6kW7A==
@ -1352,128 +1245,6 @@
resolved "https://registry.npmjs.org/@mantine/tiptap/-/tiptap-7.13.0.tgz" resolved "https://registry.npmjs.org/@mantine/tiptap/-/tiptap-7.13.0.tgz"
integrity sha512-WoquUeyX6s6CVFkm4qwJWSt9e10JjX9p/LdGPpdKLn0lrJ4vGJy+L2zFDcoDxwXwgUKIw32rTmIoSsxUBziVIQ== integrity sha512-WoquUeyX6s6CVFkm4qwJWSt9e10JjX9p/LdGPpdKLn0lrJ4vGJy+L2zFDcoDxwXwgUKIw32rTmIoSsxUBziVIQ==
"@mui/base@^5.0.0-beta.40", "@mui/base@5.0.0-beta.40":
version "5.0.0-beta.40"
resolved "https://registry.npmjs.org/@mui/base/-/base-5.0.0-beta.40.tgz"
integrity sha512-I/lGHztkCzvwlXpjD2+SNmvNQvB4227xBXhISPjEaJUXGImOQ9f3D2Yj/T3KasSI/h0MLWy74X0J6clhPmsRbQ==
dependencies:
"@babel/runtime" "^7.23.9"
"@floating-ui/react-dom" "^2.0.8"
"@mui/types" "^7.2.14"
"@mui/utils" "^5.15.14"
"@popperjs/core" "^2.11.8"
clsx "^2.1.0"
prop-types "^15.8.1"
"@mui/core-downloads-tracker@^5.15.20":
version "5.15.20"
resolved "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.15.20.tgz"
integrity sha512-DoL2ppgldL16utL8nNyj/P12f8mCNdx/Hb/AJnX9rLY4b52hCMIx1kH83pbXQ6uMy6n54M3StmEbvSGoj2OFuA==
"@mui/icons-material@^5.15.20":
version "5.15.20"
resolved "https://registry.npmjs.org/@mui/icons-material/-/icons-material-5.15.20.tgz"
integrity sha512-oGcKmCuHaYbAAoLN67WKSXtHmEgyWcJToT1uRtmPyxMj9N5uqwc/mRtEnst4Wj/eGr+zYH2FiZQ79v9k7kSk1Q==
dependencies:
"@babel/runtime" "^7.23.9"
"@mui/material@^5.0.0", "@mui/material@^5.15.14", "@mui/material@^5.15.20":
version "5.15.20"
resolved "https://registry.npmjs.org/@mui/material/-/material-5.15.20.tgz"
integrity sha512-tVq3l4qoXx/NxUgIx/x3lZiPn/5xDbdTE8VrLczNpfblLYZzlrbxA7kb9mI8NoBF6+w9WE9IrxWnKK5KlPI2bg==
dependencies:
"@babel/runtime" "^7.23.9"
"@mui/base" "5.0.0-beta.40"
"@mui/core-downloads-tracker" "^5.15.20"
"@mui/system" "^5.15.20"
"@mui/types" "^7.2.14"
"@mui/utils" "^5.15.20"
"@types/react-transition-group" "^4.4.10"
clsx "^2.1.0"
csstype "^3.1.3"
prop-types "^15.8.1"
react-is "^18.2.0"
react-transition-group "^4.4.5"
"@mui/private-theming@^5.15.20":
version "5.15.20"
resolved "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.15.20.tgz"
integrity sha512-BK8F94AIqSrnaPYXf2KAOjGZJgWfvqAVQ2gVR3EryvQFtuBnG6RwodxrCvd3B48VuMy6Wsk897+lQMUxJyk+6g==
dependencies:
"@babel/runtime" "^7.23.9"
"@mui/utils" "^5.15.20"
prop-types "^15.8.1"
"@mui/styled-engine@^5.15.14":
version "5.15.14"
resolved "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-5.15.14.tgz"
integrity sha512-RILkuVD8gY6PvjZjqnWhz8fu68dVkqhM5+jYWfB5yhlSQKg+2rHkmEwm75XIeAqI3qwOndK6zELK5H6Zxn4NHw==
dependencies:
"@babel/runtime" "^7.23.9"
"@emotion/cache" "^11.11.0"
csstype "^3.1.3"
prop-types "^15.8.1"
"@mui/system@^5.15.20":
version "5.15.20"
resolved "https://registry.npmjs.org/@mui/system/-/system-5.15.20.tgz"
integrity sha512-LoMq4IlAAhxzL2VNUDBTQxAb4chnBe8JvRINVNDiMtHE2PiPOoHlhOPutSxEbaL5mkECPVWSv6p8JEV+uykwIA==
dependencies:
"@babel/runtime" "^7.23.9"
"@mui/private-theming" "^5.15.20"
"@mui/styled-engine" "^5.15.14"
"@mui/types" "^7.2.14"
"@mui/utils" "^5.15.20"
clsx "^2.1.0"
csstype "^3.1.3"
prop-types "^15.8.1"
"@mui/types@^7.2.14":
version "7.2.14"
resolved "https://registry.npmjs.org/@mui/types/-/types-7.2.14.tgz"
integrity sha512-MZsBZ4q4HfzBsywtXgM1Ksj6HDThtiwmOKUXH1pKYISI9gAVXCNHNpo7TlGoGrBaYWZTdNoirIN7JsQcQUjmQQ==
"@mui/utils@^5.15.14", "@mui/utils@^5.15.20":
version "5.15.20"
resolved "https://registry.npmjs.org/@mui/utils/-/utils-5.15.20.tgz"
integrity sha512-mAbYx0sovrnpAu1zHc3MDIhPqL8RPVC5W5xcO1b7PiSCJPtckIZmBkp8hefamAvUiAV8gpfMOM6Zb+eSisbI2A==
dependencies:
"@babel/runtime" "^7.23.9"
"@types/prop-types" "^15.7.11"
prop-types "^15.8.1"
react-is "^18.2.0"
"@mui/x-charts@^7.8.0":
version "7.8.0"
resolved "https://registry.npmjs.org/@mui/x-charts/-/x-charts-7.8.0.tgz"
integrity sha512-SosaVtx4Ig1nu/loH6Mq4peH5Pq5UvVEnsMfe4G2IEVrMxfwrktWJo+86t9LxiHTERt4wxPKnsqlhkgBIf9ePQ==
dependencies:
"@babel/runtime" "^7.24.7"
"@mui/base" "^5.0.0-beta.40"
"@mui/system" "^5.15.20"
"@mui/utils" "^5.15.20"
"@react-spring/rafz" "^9.7.3"
"@react-spring/web" "^9.7.3"
clsx "^2.1.1"
d3-color "^3.1.0"
d3-delaunay "^6.0.4"
d3-interpolate "^3.0.1"
d3-scale "^4.0.2"
d3-shape "^3.2.0"
prop-types "^15.8.1"
"@mui/x-data-grid@^7.7.1":
version "7.7.1"
resolved "https://registry.npmjs.org/@mui/x-data-grid/-/x-data-grid-7.7.1.tgz"
integrity sha512-5XsvuVpJfjV2ERtNiVRWL+0UUq5rh2Tq8aLZdJ8Ca5PnweEfNzOesQMlf0lpjXqnzuoq7uTwvICqoAMjsTTglg==
dependencies:
"@babel/runtime" "^7.24.7"
"@mui/system" "^5.15.20"
"@mui/utils" "^5.15.20"
clsx "^2.1.1"
prop-types "^15.8.1"
reselect "^4.1.8"
"@nodelib/fs.scandir@2.1.5": "@nodelib/fs.scandir@2.1.5":
version "2.1.5" version "2.1.5"
resolved "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz" resolved "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz"
@ -1505,55 +1276,11 @@
resolved "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz" resolved "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz"
integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg== integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==
"@popperjs/core@^2.11.8", "@popperjs/core@^2.9.0": "@popperjs/core@^2.9.0":
version "2.11.8" version "2.11.8"
resolved "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz" resolved "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz"
integrity sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A== integrity sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==
"@react-spring/animated@~9.7.3":
version "9.7.3"
resolved "https://registry.npmjs.org/@react-spring/animated/-/animated-9.7.3.tgz"
integrity sha512-5CWeNJt9pNgyvuSzQH+uy2pvTg8Y4/OisoscZIR8/ZNLIOI+CatFBhGZpDGTF/OzdNFsAoGk3wiUYTwoJ0YIvw==
dependencies:
"@react-spring/shared" "~9.7.3"
"@react-spring/types" "~9.7.3"
"@react-spring/core@~9.7.3":
version "9.7.3"
resolved "https://registry.npmjs.org/@react-spring/core/-/core-9.7.3.tgz"
integrity sha512-IqFdPVf3ZOC1Cx7+M0cXf4odNLxDC+n7IN3MDcVCTIOSBfqEcBebSv+vlY5AhM0zw05PDbjKrNmBpzv/AqpjnQ==
dependencies:
"@react-spring/animated" "~9.7.3"
"@react-spring/shared" "~9.7.3"
"@react-spring/types" "~9.7.3"
"@react-spring/rafz@^9.7.3":
version "9.7.3"
resolved "https://registry.npmjs.org/@react-spring/rafz/-/rafz-9.7.3.tgz"
integrity sha512-9vzW1zJPcC4nS3aCV+GgcsK/WLaB520Iyvm55ARHfM5AuyBqycjvh1wbmWmgCyJuX4VPoWigzemq1CaaeRSHhQ==
"@react-spring/shared@~9.7.3":
version "9.7.3"
resolved "https://registry.npmjs.org/@react-spring/shared/-/shared-9.7.3.tgz"
integrity sha512-NEopD+9S5xYyQ0pGtioacLhL2luflh6HACSSDUZOwLHoxA5eku1UPuqcJqjwSD6luKjjLfiLOspxo43FUHKKSA==
dependencies:
"@react-spring/types" "~9.7.3"
"@react-spring/types@~9.7.3":
version "9.7.3"
resolved "https://registry.npmjs.org/@react-spring/types/-/types-9.7.3.tgz"
integrity sha512-Kpx/fQ/ZFX31OtlqVEFfgaD1ACzul4NksrvIgYfIFq9JpDHFwQkMVZ10tbo0FU/grje4rcL4EIrjekl3kYwgWw==
"@react-spring/web@^9.7.3":
version "9.7.3"
resolved "https://registry.npmjs.org/@react-spring/web/-/web-9.7.3.tgz"
integrity sha512-BXt6BpS9aJL/QdVqEIX9YoUy8CE6TJrU0mNCqSoxdXlIeNcEBWOfIyE6B14ENNsyQKS3wOWkiJfco0tCr/9tUg==
dependencies:
"@react-spring/animated" "~9.7.3"
"@react-spring/core" "~9.7.3"
"@react-spring/shared" "~9.7.3"
"@react-spring/types" "~9.7.3"
"@remirror/core-constants@3.0.0": "@remirror/core-constants@3.0.0":
version "3.0.0" version "3.0.0"
resolved "https://registry.npmjs.org/@remirror/core-constants/-/core-constants-3.0.0.tgz" resolved "https://registry.npmjs.org/@remirror/core-constants/-/core-constants-3.0.0.tgz"
@ -1958,17 +1685,12 @@
resolved "https://registry.npmjs.org/@siedlerchr/types-ol-ext/-/types-ol-ext-3.5.0.tgz" resolved "https://registry.npmjs.org/@siedlerchr/types-ol-ext/-/types-ol-ext-3.5.0.tgz"
integrity sha512-qC6hvHtLBqHSEGxqCkHlc/e0ZhMZNy9MlcY80i6yH8cwSJydOsmVK0BaCZ4WY/s4goFwx5hoZ7CkRy/P4KHLCg== integrity sha512-qC6hvHtLBqHSEGxqCkHlc/e0ZhMZNy9MlcY80i6yH8cwSJydOsmVK0BaCZ4WY/s4goFwx5hoZ7CkRy/P4KHLCg==
"@types/parse-json@^4.0.0":
version "4.0.2"
resolved "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz"
integrity sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==
"@types/proj4@^2.5.5": "@types/proj4@^2.5.5":
version "2.5.5" version "2.5.5"
resolved "https://registry.npmjs.org/@types/proj4/-/proj4-2.5.5.tgz" resolved "https://registry.npmjs.org/@types/proj4/-/proj4-2.5.5.tgz"
integrity sha512-y4tHUVVoMEOm2nxRLQ2/ET8upj/pBmoutGxFw2LZJTQWPgWXI+cbxVEUFFmIzr/bpFR83hGDOTSXX6HBeObvZA== integrity sha512-y4tHUVVoMEOm2nxRLQ2/ET8upj/pBmoutGxFw2LZJTQWPgWXI+cbxVEUFFmIzr/bpFR83hGDOTSXX6HBeObvZA==
"@types/prop-types@*", "@types/prop-types@^15.7.11": "@types/prop-types@*":
version "15.7.12" version "15.7.12"
resolved "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz" resolved "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz"
integrity sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q== integrity sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==
@ -1985,14 +1707,7 @@
dependencies: dependencies:
"@types/react" "*" "@types/react" "*"
"@types/react-transition-group@^4.4.10": "@types/react@*", "@types/react@^16.8.0 || ^17.0.0 || ^18.0.0", "@types/react@^16.9.0 || ^17.0.0 || ^18.0.0", "@types/react@^18.2.66", "@types/react@>=16.8":
version "4.4.10"
resolved "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.10.tgz"
integrity sha512-hT/+s0VQs2ojCX823m60m5f0sL5idt9SO6Tj6Dg+rdphGPIeJbJ6CxvBYkgkGKrYeDjvIpKTR38UzmtHJOGW3Q==
dependencies:
"@types/react" "*"
"@types/react@*", "@types/react@^16.8.0 || ^17.0.0 || ^18.0.0", "@types/react@^16.9.0 || ^17.0.0 || ^18.0.0", "@types/react@^17.0.0 || ^18.0.0", "@types/react@^18.2.66", "@types/react@>=16.8":
version "18.3.3" version "18.3.3"
resolved "https://registry.npmjs.org/@types/react/-/react-18.3.3.tgz" resolved "https://registry.npmjs.org/@types/react/-/react-18.3.3.tgz"
integrity sha512-hti/R0pS0q1/xx+TsI73XIqk26eBsISZ2R0wUijXIngRK9R/e7Xw/cXVxQK7R5JjW+SV4zGcn5hXjudkN/pLIw== integrity sha512-hti/R0pS0q1/xx+TsI73XIqk26eBsISZ2R0wUijXIngRK9R/e7Xw/cXVxQK7R5JjW+SV4zGcn5hXjudkN/pLIw==
@ -2325,15 +2040,6 @@ axios@^1.7.2:
form-data "^4.0.0" form-data "^4.0.0"
proxy-from-env "^1.1.0" proxy-from-env "^1.1.0"
babel-plugin-macros@^3.1.0:
version "3.1.0"
resolved "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz"
integrity sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==
dependencies:
"@babel/runtime" "^7.12.5"
cosmiconfig "^7.0.0"
resolve "^1.19.0"
babel-plugin-polyfill-corejs2@^0.4.10: babel-plugin-polyfill-corejs2@^0.4.10:
version "0.4.11" version "0.4.11"
resolved "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.11.tgz" resolved "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.11.tgz"
@ -2690,7 +2396,7 @@ clipboardy@3.0.0:
execa "^5.1.1" execa "^5.1.1"
is-wsl "^2.2.0" is-wsl "^2.2.0"
clsx@^2.0.0, clsx@^2.1.0, clsx@^2.1.1: clsx@^2.0.0, clsx@^2.1.1:
version "2.1.1" version "2.1.1"
resolved "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz" resolved "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz"
integrity sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA== integrity sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==
@ -2811,11 +2517,6 @@ content-disposition@0.5.2:
resolved "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz" resolved "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz"
integrity sha512-kRGRZw3bLlFISDBgwTSA1TMBFN6J6GWDeubmDE3AF+3+yXL8hTWv8r5rkLbqYXY4RjPk/EzHnClI3zQf1cFmHA== integrity sha512-kRGRZw3bLlFISDBgwTSA1TMBFN6J6GWDeubmDE3AF+3+yXL8hTWv8r5rkLbqYXY4RjPk/EzHnClI3zQf1cFmHA==
convert-source-map@^1.5.0:
version "1.9.0"
resolved "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz"
integrity sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==
convert-source-map@^2.0.0: convert-source-map@^2.0.0:
version "2.0.0" version "2.0.0"
resolved "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz" resolved "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz"
@ -2838,17 +2539,6 @@ core-util-is@~1.0.0:
resolved "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz" resolved "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz"
integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==
cosmiconfig@^7.0.0:
version "7.1.0"
resolved "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz"
integrity sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==
dependencies:
"@types/parse-json" "^4.0.0"
import-fresh "^3.2.1"
parse-json "^5.0.0"
path-type "^4.0.0"
yaml "^1.10.0"
create-ecdh@^4.0.0: create-ecdh@^4.0.0:
version "4.0.4" version "4.0.4"
resolved "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz" resolved "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz"
@ -2933,7 +2623,7 @@ cssesc@^3.0.0:
resolved "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz" resolved "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz"
integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg== integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==
csstype@^3.0.2, csstype@^3.1.3: csstype@^3.0.2:
version "3.1.3" version "3.1.3"
resolved "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz" resolved "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz"
integrity sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw== integrity sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==
@ -2945,18 +2635,11 @@ d3-array@^3.1.6, "d3-array@2 - 3", "d3-array@2.10.0 - 3":
dependencies: dependencies:
internmap "1 - 2" internmap "1 - 2"
d3-color@^3.1.0, "d3-color@1 - 3": "d3-color@1 - 3":
version "3.1.0" version "3.1.0"
resolved "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz" resolved "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz"
integrity sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA== integrity sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==
d3-delaunay@^6.0.4:
version "6.0.4"
resolved "https://registry.npmjs.org/d3-delaunay/-/d3-delaunay-6.0.4.tgz"
integrity sha512-mdjtIZ1XLAM8bm/hx3WwjfHt6Sggek7qH043O8KEjDXN40xi3vx/6pYSVTwLjEgiXQTbvaouWKynLBiUZ6SK6A==
dependencies:
delaunator "5"
d3-ease@^3.0.1: d3-ease@^3.0.1:
version "3.0.1" version "3.0.1"
resolved "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz" resolved "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz"
@ -2990,7 +2673,7 @@ d3-scale@^4.0.2:
d3-time "2.1.1 - 3" d3-time "2.1.1 - 3"
d3-time-format "2 - 4" d3-time-format "2 - 4"
d3-shape@^3.1.0, d3-shape@^3.2.0: d3-shape@^3.1.0:
version "3.2.0" version "3.2.0"
resolved "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz" resolved "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz"
integrity sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA== integrity sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==
@ -3100,13 +2783,6 @@ define-properties@^1.1.3, define-properties@^1.2.0, define-properties@^1.2.1:
has-property-descriptors "^1.0.0" has-property-descriptors "^1.0.0"
object-keys "^1.1.1" object-keys "^1.1.1"
delaunator@5:
version "5.0.1"
resolved "https://registry.npmjs.org/delaunator/-/delaunator-5.0.1.tgz"
integrity sha512-8nvh+XBe96aCESrGOqMp/84b13H9cdKbG5P2ejQCh4d4sK9RL4371qou9drQjMhvnPmhWl5hnmqbEE0fXr9Xnw==
dependencies:
robust-predicates "^3.0.2"
delayed-stream@~1.0.0: delayed-stream@~1.0.0:
version "1.0.0" version "1.0.0"
resolved "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz" resolved "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz"
@ -3244,13 +2920,6 @@ entities@^4.4.0:
resolved "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz" resolved "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz"
integrity sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw== integrity sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==
error-ex@^1.3.1:
version "1.3.2"
resolved "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz"
integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==
dependencies:
is-arrayish "^0.2.1"
es-abstract@^1.22.1, es-abstract@^1.22.3, es-abstract@^1.23.0, es-abstract@^1.23.2: es-abstract@^1.22.1, es-abstract@^1.22.3, es-abstract@^1.23.0, es-abstract@^1.23.2:
version "1.23.3" version "1.23.3"
resolved "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz" resolved "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz"
@ -3607,11 +3276,6 @@ fill-range@^7.1.1:
dependencies: dependencies:
to-regex-range "^5.0.1" to-regex-range "^5.0.1"
find-root@^1.1.0:
version "1.1.0"
resolved "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz"
integrity sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==
find-up@^5.0.0: find-up@^5.0.0:
version "5.0.0" version "5.0.0"
resolved "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz" resolved "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz"
@ -3926,13 +3590,6 @@ hmac-drbg@^1.0.1:
minimalistic-assert "^1.0.0" minimalistic-assert "^1.0.0"
minimalistic-crypto-utils "^1.0.1" minimalistic-crypto-utils "^1.0.1"
hoist-non-react-statics@^3.3.1:
version "3.3.2"
resolved "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz"
integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==
dependencies:
react-is "^16.7.0"
html2canvas@^1.0.0-rc.5: html2canvas@^1.0.0-rc.5:
version "1.4.1" version "1.4.1"
resolved "https://registry.npmjs.org/html2canvas/-/html2canvas-1.4.1.tgz" resolved "https://registry.npmjs.org/html2canvas/-/html2canvas-1.4.1.tgz"
@ -4039,11 +3696,6 @@ is-array-buffer@^3.0.4:
call-bind "^1.0.2" call-bind "^1.0.2"
get-intrinsic "^1.2.1" get-intrinsic "^1.2.1"
is-arrayish@^0.2.1:
version "0.2.1"
resolved "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz"
integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==
is-bigint@^1.0.1: is-bigint@^1.0.1:
version "1.0.4" version "1.0.4"
resolved "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz" resolved "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz"
@ -4304,11 +3956,6 @@ json-buffer@3.0.1:
resolved "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz" resolved "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz"
integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==
json-parse-even-better-errors@^2.3.0:
version "2.3.1"
resolved "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz"
integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==
json-schema-traverse@^0.4.1: json-schema-traverse@^0.4.1:
version "0.4.1" version "0.4.1"
resolved "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz" resolved "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz"
@ -4861,16 +4508,6 @@ parse-headers@^2.0.2:
resolved "https://registry.npmjs.org/parse-headers/-/parse-headers-2.0.5.tgz" resolved "https://registry.npmjs.org/parse-headers/-/parse-headers-2.0.5.tgz"
integrity sha512-ft3iAoLOB/MlwbNXgzy43SWGP6sQki2jQvAyBg/zDFAgr9bfNWZIUj42Kw2eJIl8kEi4PbgE6U1Zau/HwI75HA== integrity sha512-ft3iAoLOB/MlwbNXgzy43SWGP6sQki2jQvAyBg/zDFAgr9bfNWZIUj42Kw2eJIl8kEi4PbgE6U1Zau/HwI75HA==
parse-json@^5.0.0:
version "5.2.0"
resolved "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz"
integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==
dependencies:
"@babel/code-frame" "^7.0.0"
error-ex "^1.3.1"
json-parse-even-better-errors "^2.3.0"
lines-and-columns "^1.1.6"
path-browserify@^1.0.1: path-browserify@^1.0.1:
version "1.0.1" version "1.0.1"
resolved "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz" resolved "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz"
@ -5393,16 +5030,6 @@ react-is@^16.13.1:
resolved "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz" resolved "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz"
integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
react-is@^16.7.0:
version "16.13.1"
resolved "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz"
integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
react-is@^18.2.0:
version "18.3.1"
resolved "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz"
integrity sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==
react-number-format@^5.3.1: react-number-format@^5.3.1:
version "5.4.2" version "5.4.2"
resolved "https://registry.npmjs.org/react-number-format/-/react-number-format-5.4.2.tgz" resolved "https://registry.npmjs.org/react-number-format/-/react-number-format-5.4.2.tgz"
@ -5628,11 +5255,6 @@ require-from-string@^2.0.2:
resolved "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz" resolved "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz"
integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==
reselect@^4.1.8:
version "4.1.8"
resolved "https://registry.npmjs.org/reselect/-/reselect-4.1.8.tgz"
integrity sha512-ab9EmR80F/zQTMNeneUr4cv+jSwPJgIlvEmVwLerwrWVbpLlBuls9XHzIeTFy4cegU2NHBp3va0LKOzU5qFEYQ==
resolve-from@^4.0.0: resolve-from@^4.0.0:
version "4.0.0" version "4.0.0"
resolved "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz" resolved "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz"
@ -5645,7 +5267,7 @@ resolve-protobuf-schema@^2.1.0:
dependencies: dependencies:
protocol-buffers-schema "^3.3.1" protocol-buffers-schema "^3.3.1"
resolve@^1.1.7, resolve@^1.14.2, resolve@^1.17.0, resolve@^1.19.0, resolve@^1.22.1, resolve@^1.22.2: resolve@^1.1.7, resolve@^1.14.2, resolve@^1.17.0, resolve@^1.22.1, resolve@^1.22.2:
version "1.22.8" version "1.22.8"
resolved "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz" resolved "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz"
integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw== integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==
@ -5679,11 +5301,6 @@ ripemd160@^2.0.0, ripemd160@^2.0.1:
hash-base "^3.0.0" hash-base "^3.0.0"
inherits "^2.0.1" inherits "^2.0.1"
robust-predicates@^3.0.2:
version "3.0.2"
resolved "https://registry.npmjs.org/robust-predicates/-/robust-predicates-3.0.2.tgz"
integrity sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg==
"rollup@^1.20.0 || ^2.0.0", rollup@^1.20.0||^2.0.0, rollup@^2.43.1: "rollup@^1.20.0 || ^2.0.0", rollup@^1.20.0||^2.0.0, rollup@^2.43.1:
version "2.79.1" version "2.79.1"
resolved "https://registry.npmjs.org/rollup/-/rollup-2.79.1.tgz" resolved "https://registry.npmjs.org/rollup/-/rollup-2.79.1.tgz"
@ -5958,11 +5575,6 @@ source-map-support@~0.5.20:
buffer-from "^1.0.0" buffer-from "^1.0.0"
source-map "^0.6.0" source-map "^0.6.0"
source-map@^0.5.7:
version "0.5.7"
resolved "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz"
integrity sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==
source-map@^0.6.0: source-map@^0.6.0:
version "0.6.1" version "0.6.1"
resolved "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz" resolved "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz"
@ -6148,11 +5760,6 @@ strtok3@^7.0.0:
"@tokenizer/token" "^0.3.0" "@tokenizer/token" "^0.3.0"
peek-readable "^5.0.0" peek-readable "^5.0.0"
stylis@4.2.0:
version "4.2.0"
resolved "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz"
integrity sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==
sucrase@^3.32.0: sucrase@^3.32.0:
version "3.35.0" version "3.35.0"
resolved "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz" resolved "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz"
@ -6928,11 +6535,6 @@ yallist@^3.0.2:
resolved "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz" resolved "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz"
integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==
yaml@^1.10.0:
version "1.10.2"
resolved "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz"
integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==
yaml@^2.3.4: yaml@^2.3.4:
version "2.4.5" version "2.4.5"
resolved "https://registry.npmjs.org/yaml/-/yaml-2.4.5.tgz" resolved "https://registry.npmjs.org/yaml/-/yaml-2.4.5.tgz"

View File

@ -61,11 +61,38 @@ router.get('/objects/list', async (req: Request, res: Response) => {
if (type) { if (type) {
const result = await tediousQuery( const result = await tediousQuery(
// `
// SELECT
// *
// FROM
// vObjects
// WHERE
// vObjects.id_city = ${city_id}
// AND vObjects.year = ${year}
// AND type = ${type}
// AND
// (
// CASE
// WHEN TRY_CAST(vObjects.planning AS BIT) IS NOT NULL THEN TRY_CAST(vObjects.planning AS BIT)
// WHEN vObjects.planning = 'TRUE' THEN 1
// WHEN vObjects.planning = 'FALSE' THEN 0
// ELSE NULL
// END
// ) = ${planning};
// `
` `
SELECT SELECT
* vObjects.*,
CASE
WHEN vObjects.boiler_id IS NOT NULL THEN vBoilers.name
ELSE CAST(tValues.value AS varchar(max))
END AS name
FROM FROM
vObjects vObjects
JOIN
vBoilers ON vBoilers.id = vObjects.boiler_id
JOIN
tValues ON tValues.id_param = 4 AND tValues.id_object = vObjects.object_id
WHERE WHERE
vObjects.id_city = ${city_id} vObjects.id_city = ${city_id}
AND vObjects.year = ${year} AND vObjects.year = ${year}

View File

@ -0,0 +1,24 @@
import express, { Request, Response } from 'express';
import path from 'path';
import fs from 'fs';
const router = express.Router()
const tileFolder = path.join(__dirname, '..', '..', '..', 'public', 'static')
router.get('/:city_id', async (req: Request, res: Response) => {
const { city_id } = req.params
const tilePath1 = path.join(tileFolder, `${city_id}.jpg`)
const tilePath2 = path.join(tileFolder, `${city_id}.png`)
if (fs.existsSync(tilePath1)) {
return res.sendFile(tilePath1)
} else if (fs.existsSync(tilePath2)) {
return res.sendFile(tilePath2)
} else {
res.status(404).send('Tile is not generated or not provided')
}
})
export default router

View File

@ -5,6 +5,7 @@ import generalRouter from './api/general'
import gisRouter from './api/gis' import gisRouter from './api/gis'
import nodesRouter from './api/nodes' import nodesRouter from './api/nodes'
import tilesRouter from './api/tiles' import tilesRouter from './api/tiles'
import staticRouter from './api/static'
const app = express() const app = express()
const PORT = process.env.EMS_PORT || 5000 const PORT = process.env.EMS_PORT || 5000
@ -19,5 +20,6 @@ app.use('/general', generalRouter)
app.use('/gis', gisRouter) app.use('/gis', gisRouter)
app.use('/nodes', nodesRouter) app.use('/nodes', nodesRouter)
app.use('/tiles', tilesRouter) app.use('/tiles', tilesRouter)
app.use('/static', staticRouter)
app.listen(PORT, () => console.log(`Server running on port ${PORT}`)); app.listen(PORT, () => console.log(`Server running on port ${PORT}`));