finish config edit page

This commit is contained in:
NlightN22 2024-03-13 00:54:43 +07:00
parent 529885498d
commit 04962ba56a
5 changed files with 195 additions and 62 deletions

View File

@ -1,6 +1,6 @@
# syntax=docker/dockerfile:1
# Build commands:
# - $VERSION=0.9
# - $VERSION=1.0
# - rm build -r -Force ; rm ./node_modules/.cache/babel-loader -r -Force ; yarn build
# - docker build --pull --rm -t oncharterliz/multi-frigate:latest -t oncharterliz/multi-frigate:$VERSION "."
# - docker image push --all-tags oncharterliz/multi-frigate

View File

@ -1,28 +1,61 @@
import React, { useCallback, useContext, useEffect, useRef, useState } from 'react';
import { Button, Flex, Text, useMantineTheme } from '@mantine/core';
import { useClipboard } from '@mantine/hooks';
import Editor, { Monaco } from '@monaco-editor/react';
import { useMutation, useQuery } from '@tanstack/react-query';
import { observer } from 'mobx-react-lite';
import * as monaco from "monaco-editor";
import { SchemasSettings, configureMonacoYaml } from 'monaco-yaml';
import { useCallback, useContext, useEffect, useRef, useState } from 'react';
import { useParams } from 'react-router-dom';
import { Context } from '..';
import { useMutation, useQuery } from '@tanstack/react-query';
import { frigateApi, frigateQueryKeys, mapHostToHostname, proxyApi } from '../services/frigate.proxy/frigate.api';
import { Button, Flex, useMantineTheme, Text } from '@mantine/core';
import { useClipboard } from '@mantine/hooks';
import Editor, { Monaco } from '@monaco-editor/react'
import * as monaco from "monaco-editor";
import CenterLoader from '../shared/components/loaders/CenterLoader';
import RetryErrorPage from './RetryErrorPage';
import { useAdminRole } from '../hooks/useAdminRole';
import Forbidden from './403';
import { observer } from 'mobx-react-lite';
import { frigateApi, frigateQueryKeys, mapHostToHostname, proxyApi } from '../services/frigate.proxy/frigate.api';
import { GetFrigateHost } from '../services/frigate.proxy/frigate.schema';
import CenterLoader from '../shared/components/loaders/CenterLoader';
import { isProduction } from '../shared/env.const';
import { SaveOption } from '../types/saveConfig';
import { GetFrigateHost } from '../services/frigate.proxy/frigate.schema';
import { error } from 'console';
import Forbidden from './403';
import RetryErrorPage from './RetryErrorPage';
import { notifications } from '@mantine/notifications';
import { IconAlertCircle, IconCircleCheck } from '@tabler/icons-react';
window.MonacoEnvironment = {
getWorker(moduleId, label) {
switch (label) {
case 'editorWorkerService':
return new Worker(new URL('monaco-editor/esm/vs/editor/editor.worker', import.meta.url))
case 'css':
case 'less':
case 'scss':
return new Worker(new URL('monaco-editor/esm/vs/language/css/css.worker', import.meta.url))
case 'handlebars':
case 'html':
case 'razor':
return new Worker(
new URL('monaco-editor/esm/vs/language/html/html.worker', import.meta.url)
)
case 'json':
return new Worker(
new URL('monaco-editor/esm/vs/language/json/json.worker', import.meta.url)
)
case 'javascript':
case 'typescript':
return new Worker(
new URL('monaco-editor/esm/vs/language/typescript/ts.worker', import.meta.url)
)
case 'yaml':
return new Worker(new URL('monaco-yaml/yaml.worker', import.meta.url))
default:
throw new Error(`Unknown label ${label}`)
}
}
}
const HostConfigPage = () => {
const executed = useRef(false)
const host = useRef<GetFrigateHost | undefined>()
const { sideBarsStore } = useContext(Context)
const [saveMessage, setSaveMessage] = useState<string>()
let { id } = useParams<'id'>()
const { isAdmin, isLoading: adminLoading } = useAdminRole()
@ -51,10 +84,26 @@ const HostConfigPage = () => {
})
},
onSuccess: (data) => {
setSaveMessage(data?.message)
notifications.show({
id: data?.message,
withCloseButton: true,
autoClose: 5000,
title: `Sucess: ${data?.success}`,
message: data?.message,
color: 'green',
icon: <IconCircleCheck />
})
},
onError: (error) => {
setSaveMessage(error.message)
onError: (e) => {
notifications.show({
id: e.message,
withCloseButton: true,
autoClose: false,
title: "Error",
message: e.message,
color: 'red',
icon: <IconAlertCircle />,
})
}
})
@ -72,28 +121,24 @@ const HostConfigPage = () => {
const editorRef = useRef<monaco.editor.IStandaloneCodeEditor | null>(null)
function handleEditorWillMount(monaco: Monaco) {
monaco.languages.typescript.javascriptDefaults.setEagerModelSync(true);
// TODO add yaml schema
// const modelUri = monaco.Uri.parse("http://localhost:4000/proxy/api/config/schema.json?hostName=localhost:5001")
// configureMonacoYaml(monaco, {
// enableSchemaRequest: true,
// hover: true,
// completion: true,
// validate: true,
// format: true,
// schemas: [
// {
// uri: `http://localhost:4000/proxy/api/config/schema.json?hostName=localhost:5001`,
// fileMatch: ['**/.schema.*'],
// },
// ],
// })
const hostName = mapHostToHostname(host.current)
if (!hostName) return
const schemaURL = proxyApi.configSchemaURL(hostName)
const defaultSchema: SchemasSettings = {
uri: schemaURL,
fileMatch: ['monaco-yaml.yaml']
}
configureMonacoYaml(monaco, {
enableSchemaRequest: true,
schemas: [defaultSchema]
})
}
function handleEditorDidMount(editor: monaco.editor.IStandaloneCodeEditor, monaco: Monaco) {
// here is another way to get monaco instance
// you can also store it in `useRef` for further usage
const model = monaco.editor.createModel(config, 'yaml', monaco.Uri.parse('monaco-yaml.yaml'))
editor.setModel(model)
editorRef.current = editor;
}
@ -115,7 +160,7 @@ const HostConfigPage = () => {
saveConfig({ saveOption: saveOption, config: editorRef.current.getValue() })
}, [editorRef])
if (configPending || adminLoading) return <CenterLoader />
if (configPending || adminLoading ) return <CenterLoader />
if (configError) return <RetryErrorPage onRetry={refetch} />
if (!isAdmin) return <Forbidden />
@ -133,11 +178,6 @@ const HostConfigPage = () => {
Save Only
</Button>
</Flex>
{!saveMessage ? null :
<Flex w='100%' justify='center' wrap='nowrap' mt='1rem'>
<Text>{saveMessage}</Text>
</Flex>
}
<Flex h='100%' mt='1rem'>
<Editor
defaultLanguage='yaml'

View File

@ -1,12 +1,16 @@
import { Flex, Grid, Group } from '@mantine/core';
import { Flex, Group, useMantineTheme } from '@mantine/core';
import { Editor, Monaco } from '@monaco-editor/react';
import { observer } from 'mobx-react-lite';
import * as monaco from 'monaco-editor';
import { SchemasSettings, configureMonacoYaml } from 'monaco-yaml';
import { useContext, useEffect, useRef } from 'react';
import { Context } from '..';
import HeadSearch from '../shared/components/inputs/HeadSearch';
import TestItem from './TestItem';
const Test = () => {
const executed = useRef(false)
const editorRef = useRef<monaco.editor.IStandaloneCodeEditor | null>(null)
const theme = useMantineTheme();
const { sideBarsStore } = useContext(Context)
sideBarsStore.rightVisible = true
@ -18,23 +22,101 @@ const Test = () => {
sideBarsStore.setRightChildren(null)
executed.current = true
}
}, [sideBarsStore])
}, [sideBarsStore])
// const handleClick = () => {
// const startOfDay = new Date();
// startOfDay.setHours(0, 0, 0, 0);
// setValue([startOfDay, startOfDay])
// }
const cards = (qty: number) => {
let items = []
for (let i = 0; i < qty; i++) {
items.push(<TestItem key={i} />)
const value = `
# Property descriptions are displayed when hovering over properties using your cursor
property: This property has a JSON schema description
# Titles work too!
titledProperty: Titles work too!
# Even markdown descriptions work
markdown: hover me to get a markdown based description 😮
# Enums can be autocompleted by placing the cursor after the colon and pressing Ctrl+Space
enum:
# Unused anchors will be reported
unused anchor: &unused anchor
# Of course numbers are supported!
number: 12
# As well as booleans!
boolean: true
# And strings
string: I am a string
# This property is using the JSON schema recursively
reference:
boolean: Not a boolean
# Also works in arrays
array:
- string: 12
enum: Mewtwo
reference:
reference:
boolean: true
# JSON referenses can be clicked for navigation
pointer:
$ref: '#/array'
# This anchor can be referenced
anchorRef: &anchor can be clicked as well
# Press control while hovering over the anchor
anchorPointer: *anchor
formatting: Formatting is supported too! Under the hood this is powered by Prettier. Just press Ctrl+Shift+I or right click and press Format to format this document.
`.replace(/:$/m, ': ')
function handleEditorWillMount(monaco: Monaco) {
const defaultSchema: SchemasSettings = {
uri: 'https://github.com/remcohaszing/monaco-yaml/blob/HEAD/examples/demo/src/schema.json',
fileMatch: ['monaco-yaml.yaml']
}
return items
configureMonacoYaml(monaco, {
enableSchemaRequest: true,
schemas: [defaultSchema]
})
}
function handleEditorDidMount(editor: monaco.editor.IStandaloneCodeEditor, monaco: Monaco) {
// here is another way to get monaco instance
// you can also store it in `useRef` for further usage
const model = monaco.editor.createModel(value, 'yaml', monaco.Uri.parse('monaco-yaml.yaml'))
editor.setModel(model)
editorRef.current = editor;
}
return (
<Flex direction='column' h='100%' >
<Flex justify='space-between' align='center' w='100%'>
@ -54,9 +136,14 @@ const Test = () => {
</Group>
</Flex>
<Flex justify='center' h='100%' direction='column' >
<Grid mt='sm' justify="center" mb='sm' align='stretch'>
{cards(60)}
</Grid>
<Editor
defaultLanguage='yaml'
value={value}
defaultValue="// Data empty"
theme={theme.colorScheme === "dark" ? "vs-dark" : "vs-light"}
beforeMount={handleEditorWillMount}
onMount={handleEditorDidMount}
/>
</Flex>
</Flex>
);

View File

@ -143,6 +143,7 @@ export const proxyApi = {
getEventsSummary: (hostName: string, cameraName: string) =>
instanceApi.get(`proxy/${hostName}/api/${cameraName}/events/summary`).then(res => res.data),
configSchemaURL: (hostName: string) => `${proxyPrefix}${hostName}/api/config/schema.json`,
cameraWsURL: (hostName: string, cameraName: string) => {
const protocol = proxyURL.protocol === 'https:' ? 'wss' : 'ws';
return `${protocol}://${proxyURL.host}/proxy-ws/${hostName}/live/jsmpeg/${cameraName}`

View File

@ -10857,7 +10857,12 @@ yaml@^1.10.0, yaml@^1.10.2, yaml@^1.7.2:
resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b"
integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==
yaml@^2.0.0, yaml@^2.3.4:
yaml@^2.0.0:
version "2.4.1"
resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.4.1.tgz#2e57e0b5e995292c25c75d2658f0664765210eed"
integrity sha512-pIXzoImaqmfOrL7teGUBt/T7ZDnyeGBWyXQBvOVhLkWLN37GXv8NMLK406UY6dS51JfcQHsmcW5cJ441bHg6Lg==
yaml@^2.3.4:
version "2.4.0"
resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.4.0.tgz#2376db1083d157f4b3a452995803dbcf43b08140"
integrity sha512-j9iR8g+/t0lArF4V6NE/QCfT+CO7iLqrXAHZbJdo+LfjqP1vR8Fg5bSiaq6Q2lOD1AUEVrEVIgABvBFYojJVYQ==