mirror of
https://github.com/MetaCubeX/metacubexd.git
synced 2024-12-27 19:44:12 +08:00
refactor: supports new solid-router
This commit is contained in:
parent
4ec3d9a019
commit
6a48bbdd19
28
package.json
28
package.json
@ -14,7 +14,7 @@
|
|||||||
"serve": "vite preview"
|
"serve": "vite preview"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@commitlint/config-conventional": "^19.0.3",
|
"@commitlint/config-conventional": "^19.1.0",
|
||||||
"@felte/solid": "^1.2.13",
|
"@felte/solid": "^1.2.13",
|
||||||
"@felte/validator-zod": "^1.0.17",
|
"@felte/validator-zod": "^1.0.17",
|
||||||
"@fontsource/fira-sans": "^5.0.19",
|
"@fontsource/fira-sans": "^5.0.19",
|
||||||
@ -28,24 +28,24 @@
|
|||||||
"@solid-primitives/storage": "^2.1.4",
|
"@solid-primitives/storage": "^2.1.4",
|
||||||
"@solid-primitives/timer": "^1.3.9",
|
"@solid-primitives/timer": "^1.3.9",
|
||||||
"@solid-primitives/websocket": "^1.2.2",
|
"@solid-primitives/websocket": "^1.2.2",
|
||||||
"@solidjs/router": "^0.9.1",
|
"@solidjs/router": "^0.13.1",
|
||||||
"@tabler/icons-solidjs": "^2.47.0",
|
"@tabler/icons-solidjs": "^2.47.0",
|
||||||
"@tanstack/match-sorter-utils": "^8.11.8",
|
"@tanstack/match-sorter-utils": "^8.11.8",
|
||||||
"@tanstack/solid-table": "^8.13.2",
|
"@tanstack/solid-table": "^8.14.0",
|
||||||
"@tanstack/solid-virtual": "3.0.2",
|
"@tanstack/solid-virtual": "3.0.2",
|
||||||
"@tanstack/virtual-core": "3.0.2",
|
"@tanstack/virtual-core": "3.0.2",
|
||||||
"@thisbeyond/solid-dnd": "^0.7.5",
|
"@thisbeyond/solid-dnd": "^0.7.5",
|
||||||
"@types/byte-size": "^8.1.2",
|
"@types/byte-size": "^8.1.2",
|
||||||
"@types/lodash": "^4.14.202",
|
"@types/lodash": "^4.17.0",
|
||||||
"@types/node": "^20.11.25",
|
"@types/node": "^20.11.30",
|
||||||
"@types/uuid": "^9.0.8",
|
"@types/uuid": "^9.0.8",
|
||||||
"@typescript-eslint/eslint-plugin": "^7.1.1",
|
"@typescript-eslint/eslint-plugin": "^7.3.1",
|
||||||
"@typescript-eslint/parser": "^7.1.1",
|
"@typescript-eslint/parser": "^7.3.1",
|
||||||
"@vite-pwa/assets-generator": "^0.2.4",
|
"@vite-pwa/assets-generator": "^0.2.4",
|
||||||
"apexcharts": "^3.47.0",
|
"apexcharts": "^3.48.0",
|
||||||
"autoprefixer": "^10.4.18",
|
"autoprefixer": "^10.4.18",
|
||||||
"byte-size": "^8.1.1",
|
"byte-size": "^8.1.1",
|
||||||
"commitlint": "^19.0.3",
|
"commitlint": "^19.2.1",
|
||||||
"daisyui": "^4.7.3",
|
"daisyui": "^4.7.3",
|
||||||
"dayjs": "^1.11.10",
|
"dayjs": "^1.11.10",
|
||||||
"eslint": "^8.57.0",
|
"eslint": "^8.57.0",
|
||||||
@ -61,16 +61,16 @@
|
|||||||
"prettier-plugin-organize-imports": "^3.2.4",
|
"prettier-plugin-organize-imports": "^3.2.4",
|
||||||
"prettier-plugin-tailwindcss": "^0.5.12",
|
"prettier-plugin-tailwindcss": "^0.5.12",
|
||||||
"solid-apexcharts": "^0.3.4",
|
"solid-apexcharts": "^0.3.4",
|
||||||
"solid-js": "^1.8.15",
|
"solid-js": "^1.8.16",
|
||||||
"solid-toast": "^0.5.0",
|
"solid-toast": "^0.5.0",
|
||||||
"sort-package-json": "^2.8.0",
|
"sort-package-json": "^2.8.0",
|
||||||
"tailwind-merge": "^2.2.1",
|
"tailwind-merge": "^2.2.2",
|
||||||
"tailwindcss": "^3.4.1",
|
"tailwindcss": "^3.4.1",
|
||||||
"typescript": "^5.4.2",
|
"typescript": "^5.4.2",
|
||||||
"uuid": "^9.0.1",
|
"uuid": "^9.0.1",
|
||||||
"vite": "^5.1.5",
|
"vite": "^5.1.6",
|
||||||
"vite-plugin-pwa": "^0.19.2",
|
"vite-plugin-pwa": "^0.19.5",
|
||||||
"vite-plugin-solid": "^2.10.1",
|
"vite-plugin-solid": "^2.10.2",
|
||||||
"zod": "^3.22.4"
|
"zod": "^3.22.4"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
64
src/App.tsx
64
src/App.tsx
@ -1,11 +1,7 @@
|
|||||||
import { usePrefersDark } from '@solid-primitives/media'
|
import { usePrefersDark } from '@solid-primitives/media'
|
||||||
import { Navigate, Route, Routes } from '@solidjs/router'
|
import { ParentComponent, Show, createEffect } from 'solid-js'
|
||||||
import { Show, createEffect, lazy } from 'solid-js'
|
|
||||||
import { Toaster } from 'solid-toast'
|
|
||||||
import { twMerge } from 'tailwind-merge'
|
import { twMerge } from 'tailwind-merge'
|
||||||
import { Header } from '~/components'
|
import { Header } from '~/components'
|
||||||
import { ROUTES } from '~/constants'
|
|
||||||
import { I18nProvider, locale } from '~/i18n'
|
|
||||||
import {
|
import {
|
||||||
WsMsg,
|
WsMsg,
|
||||||
autoSwitchTheme,
|
autoSwitchTheme,
|
||||||
@ -19,14 +15,6 @@ import {
|
|||||||
useWsRequest,
|
useWsRequest,
|
||||||
} from '~/signals'
|
} from '~/signals'
|
||||||
|
|
||||||
const Setup = lazy(() => import('~/pages/Setup'))
|
|
||||||
const Overview = lazy(() => import('~/pages/Overview'))
|
|
||||||
const Connections = lazy(() => import('~/pages/Connections'))
|
|
||||||
const Logs = lazy(() => import('~/pages/Logs'))
|
|
||||||
const Proxies = lazy(() => import('~/pages/Proxies'))
|
|
||||||
const Rules = lazy(() => import('~/pages/Rules'))
|
|
||||||
const Config = lazy(() => import('~/pages/Config'))
|
|
||||||
|
|
||||||
const ProtectedResources = () => {
|
const ProtectedResources = () => {
|
||||||
const latestConnectionMsg = useWsRequest<WsMsg>('connections')
|
const latestConnectionMsg = useWsRequest<WsMsg>('connections')
|
||||||
|
|
||||||
@ -35,7 +23,7 @@ const ProtectedResources = () => {
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
export const App = () => {
|
export const App: ParentComponent = ({ children }) => {
|
||||||
const prefersDark = usePrefersDark()
|
const prefersDark = usePrefersDark()
|
||||||
|
|
||||||
createEffect(() => {
|
createEffect(() => {
|
||||||
@ -44,40 +32,22 @@ export const App = () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<I18nProvider locale={locale()}>
|
<div
|
||||||
<div
|
class={twMerge(
|
||||||
class={twMerge(
|
'relative flex h-screen flex-col overscroll-y-none subpixel-antialiased',
|
||||||
'relative flex h-screen flex-col overscroll-y-none subpixel-antialiased',
|
useTwemoji() ? 'font-twemoji' : 'font-no-twemoji',
|
||||||
useTwemoji() ? 'font-twemoji' : 'font-no-twemoji',
|
)}
|
||||||
)}
|
data-theme={curTheme()}
|
||||||
data-theme={curTheme()}
|
>
|
||||||
>
|
<Header />
|
||||||
<Header />
|
|
||||||
|
|
||||||
<div class="flex-1 overflow-y-auto p-2 sm:p-4">
|
<div class="flex-1 overflow-y-auto p-2 sm:p-4">
|
||||||
<div class="pb-8">
|
<div class="pb-8">{children}</div>
|
||||||
<Routes>
|
|
||||||
<Show when={endpoint()}>
|
|
||||||
<Route path={ROUTES.Overview} component={Overview} />
|
|
||||||
<Route path={ROUTES.Proxies} component={Proxies} />
|
|
||||||
<Route path={ROUTES.Rules} component={Rules} />
|
|
||||||
<Route path={ROUTES.Conns} component={Connections} />
|
|
||||||
<Route path={ROUTES.Log} component={Logs} />
|
|
||||||
<Route path={ROUTES.Config} component={Config} />
|
|
||||||
<Route path="*" element={<Navigate href={ROUTES.Overview} />} />
|
|
||||||
</Show>
|
|
||||||
|
|
||||||
<Route path={endpoint() ? ROUTES.Setup : '*'} component={Setup} />
|
|
||||||
</Routes>
|
|
||||||
|
|
||||||
<Show when={endpoint()}>
|
|
||||||
<ProtectedResources />
|
|
||||||
</Show>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<Toaster position="bottom-center" />
|
|
||||||
</div>
|
</div>
|
||||||
</I18nProvider>
|
|
||||||
|
<Show when={endpoint()}>
|
||||||
|
<ProtectedResources />
|
||||||
|
</Show>
|
||||||
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -69,7 +69,7 @@ const TagClientSourceIPWithNameForm: Component = () => {
|
|||||||
return (
|
return (
|
||||||
<form use:form={form}>
|
<form use:form={form}>
|
||||||
<div class="join flex">
|
<div class="join flex">
|
||||||
<select name="sourceIP" class="select join-item select-bordered">
|
<select name="sourceIP" class="join-item select select-bordered">
|
||||||
<option />
|
<option />
|
||||||
|
|
||||||
<Index
|
<Index
|
||||||
|
@ -19,14 +19,14 @@ export const ProxyNodeCard = (props: {
|
|||||||
? proxyNode()?.xudp
|
? proxyNode()?.xudp
|
||||||
? 'xudp'
|
? 'xudp'
|
||||||
: proxyNode()?.udp
|
: proxyNode()?.udp
|
||||||
? 'udp'
|
? 'udp'
|
||||||
: null
|
: null
|
||||||
: null
|
: null
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
class={twMerge(
|
class={twMerge(
|
||||||
'card card-bordered tooltip-bottom flex flex-col justify-between gap-1 border-neutral-focus bg-neutral p-2 text-neutral-content',
|
'border-neutral-focus card card-bordered tooltip-bottom flex flex-col justify-between gap-1 bg-neutral p-2 text-neutral-content',
|
||||||
isSelected && 'border-primary bg-primary-content text-primary',
|
isSelected && 'border-primary bg-primary-content text-primary',
|
||||||
onClick && 'cursor-pointer',
|
onClick && 'cursor-pointer',
|
||||||
)}
|
)}
|
||||||
|
33
src/main.tsx
33
src/main.tsx
@ -1,20 +1,43 @@
|
|||||||
/* @refresh reload */
|
/* @refresh reload */
|
||||||
import '~/index.css'
|
import '~/index.css'
|
||||||
|
|
||||||
import { Router, hashIntegration } from '@solidjs/router'
|
import { HashRouter, Route } from '@solidjs/router'
|
||||||
import dayjs from 'dayjs'
|
import dayjs from 'dayjs'
|
||||||
import 'dayjs/locale/zh-cn'
|
import 'dayjs/locale/zh-cn'
|
||||||
import relativeTime from 'dayjs/plugin/relativeTime'
|
import relativeTime from 'dayjs/plugin/relativeTime'
|
||||||
|
import { lazy } from 'solid-js'
|
||||||
import { render } from 'solid-js/web'
|
import { render } from 'solid-js/web'
|
||||||
|
import { Toaster } from 'solid-toast'
|
||||||
import { App } from '~/App'
|
import { App } from '~/App'
|
||||||
|
import { ROUTES } from '~/constants'
|
||||||
|
import { I18nProvider, locale } from '~/i18n'
|
||||||
|
|
||||||
|
const Setup = lazy(() => import('~/pages/Setup'))
|
||||||
|
const Overview = lazy(() => import('~/pages/Overview'))
|
||||||
|
const Connections = lazy(() => import('~/pages/Connections'))
|
||||||
|
const Logs = lazy(() => import('~/pages/Logs'))
|
||||||
|
const Proxies = lazy(() => import('~/pages/Proxies'))
|
||||||
|
const Rules = lazy(() => import('~/pages/Rules'))
|
||||||
|
const Config = lazy(() => import('~/pages/Config'))
|
||||||
|
|
||||||
dayjs.extend(relativeTime)
|
dayjs.extend(relativeTime)
|
||||||
|
|
||||||
render(
|
render(
|
||||||
() => (
|
() => (
|
||||||
<Router source={hashIntegration()}>
|
<I18nProvider locale={locale()}>
|
||||||
<App />
|
<HashRouter root={App}>
|
||||||
</Router>
|
<Route path={ROUTES.Setup} component={Setup} />
|
||||||
|
<Route path="/" component={Overview} />
|
||||||
|
<Route path={ROUTES.Overview} component={Overview} />
|
||||||
|
<Route path={ROUTES.Proxies} component={Proxies} />
|
||||||
|
<Route path={ROUTES.Rules} component={Rules} />
|
||||||
|
<Route path={ROUTES.Conns} component={Connections} />
|
||||||
|
<Route path={ROUTES.Log} component={Logs} />
|
||||||
|
<Route path={ROUTES.Config} component={Config} />
|
||||||
|
</HashRouter>
|
||||||
|
|
||||||
|
<Toaster position="bottom-center" />
|
||||||
|
</I18nProvider>
|
||||||
),
|
),
|
||||||
document.getElementById('root')!,
|
document.querySelector('#root')!,
|
||||||
)
|
)
|
||||||
|
@ -341,7 +341,7 @@ export default () => {
|
|||||||
<button
|
<button
|
||||||
class={twMerge(
|
class={twMerge(
|
||||||
activeTab() === tab().type && 'tab-active',
|
activeTab() === tab().type && 'tab-active',
|
||||||
'tab tab-sm gap-2 sm:tab-md',
|
'tab-sm sm:tab-md tab gap-2',
|
||||||
)}
|
)}
|
||||||
onClick={() => setActiveTab(tab().type)}
|
onClick={() => setActiveTab(tab().type)}
|
||||||
>
|
>
|
||||||
@ -377,7 +377,7 @@ export default () => {
|
|||||||
<div class="join flex flex-1 items-center md:flex-1">
|
<div class="join flex flex-1 items-center md:flex-1">
|
||||||
<input
|
<input
|
||||||
type="search"
|
type="search"
|
||||||
class="input join-item input-primary input-sm min-w-0 flex-1 sm:input-md"
|
class="input input-sm join-item input-primary min-w-0 flex-1 sm:input-md"
|
||||||
placeholder={t('search')}
|
placeholder={t('search')}
|
||||||
onInput={(e) => setGlobalFilter(e.target.value)}
|
onInput={(e) => setGlobalFilter(e.target.value)}
|
||||||
/>
|
/>
|
||||||
|
@ -135,7 +135,7 @@ export default () => {
|
|||||||
<div class="join w-full">
|
<div class="join w-full">
|
||||||
<input
|
<input
|
||||||
type="search"
|
type="search"
|
||||||
class="input join-item input-primary input-sm flex-1 flex-shrink-0 sm:input-md"
|
class="input input-sm join-item input-primary flex-1 flex-shrink-0 sm:input-md"
|
||||||
placeholder={t('search')}
|
placeholder={t('search')}
|
||||||
onInput={(e) => setGlobalFilter(e.target.value)}
|
onInput={(e) => setGlobalFilter(e.target.value)}
|
||||||
/>
|
/>
|
||||||
|
@ -114,7 +114,7 @@ export default () => {
|
|||||||
</TrafficWidget>
|
</TrafficWidget>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="rounded-box flex flex-col gap-2 bg-base-300 py-4 lg:flex-row">
|
<div class="flex flex-col gap-2 rounded-box bg-base-300 py-4 lg:flex-row">
|
||||||
<div class="flex-1">
|
<div class="flex-1">
|
||||||
<SolidApexCharts
|
<SolidApexCharts
|
||||||
type="area"
|
type="area"
|
||||||
@ -131,7 +131,7 @@ export default () => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<footer class="footer rounded-box mx-auto mt-4 block bg-neutral p-4 text-center text-lg font-bold text-neutral-content">
|
<footer class="footer mx-auto mt-4 block rounded-box bg-neutral p-4 text-center text-lg font-bold text-neutral-content">
|
||||||
{endpoint()?.url}
|
{endpoint()?.url}
|
||||||
</footer>
|
</footer>
|
||||||
</div>
|
</div>
|
||||||
|
@ -107,7 +107,7 @@ export default () => {
|
|||||||
<button
|
<button
|
||||||
class={twMerge(
|
class={twMerge(
|
||||||
activeTab() === tab.type && 'tab-active',
|
activeTab() === tab.type && 'tab-active',
|
||||||
'tab tab-sm gap-2 px-2 sm:tab-md',
|
'tab-sm sm:tab-md tab gap-2 px-2',
|
||||||
)}
|
)}
|
||||||
onClick={() => setActiveTab(tab.type)}
|
onClick={() => setActiveTab(tab.type)}
|
||||||
>
|
>
|
||||||
|
@ -123,7 +123,7 @@ export default () => {
|
|||||||
<button
|
<button
|
||||||
class={twMerge(
|
class={twMerge(
|
||||||
activeTab() === tab.type && 'tab-active',
|
activeTab() === tab.type && 'tab-active',
|
||||||
'tab tab-sm gap-2 px-2 md:tab-md',
|
'tab-sm md:tab-md tab gap-2 px-2',
|
||||||
)}
|
)}
|
||||||
onClick={() => setActiveTab(tab.type)}
|
onClick={() => setActiveTab(tab.type)}
|
||||||
>
|
>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user