mirror of
https://github.com/MetaCubeX/metacubexd.git
synced 2024-11-24 09:45:35 +08:00
feat: settings per-page
This commit is contained in:
parent
c607a31070
commit
d77626058a
14
src/components/ConfigTitle.tsx
Normal file
14
src/components/ConfigTitle.tsx
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import { children, ParentComponent } from 'solid-js'
|
||||||
|
|
||||||
|
export const ConfigTitle: ParentComponent<{ withDivider?: boolean }> = (
|
||||||
|
props,
|
||||||
|
) => (
|
||||||
|
<div
|
||||||
|
class="pb-4 text-lg font-semibold"
|
||||||
|
classList={{
|
||||||
|
divider: props.withDivider,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{children(() => props.children)()}
|
||||||
|
</div>
|
||||||
|
)
|
@ -14,17 +14,20 @@ import {
|
|||||||
useDragDropContext,
|
useDragDropContext,
|
||||||
} from '@thisbeyond/solid-dnd'
|
} from '@thisbeyond/solid-dnd'
|
||||||
import { Component, For, Show, createSignal } from 'solid-js'
|
import { Component, For, Show, createSignal } from 'solid-js'
|
||||||
import { Button } from '~/components'
|
import { Button, ConfigTitle } from '~/components'
|
||||||
import {
|
import {
|
||||||
CONNECTIONS_TABLE_ACCESSOR_KEY,
|
CONNECTIONS_TABLE_ACCESSOR_KEY,
|
||||||
CONNECTIONS_TABLE_INITIAL_COLUMN_ORDER,
|
CONNECTIONS_TABLE_INITIAL_COLUMN_ORDER,
|
||||||
CONNECTIONS_TABLE_INITIAL_COLUMN_VISIBILITY,
|
CONNECTIONS_TABLE_INITIAL_COLUMN_VISIBILITY,
|
||||||
|
MODAL,
|
||||||
|
TAILWINDCSS_SIZE,
|
||||||
} from '~/constants'
|
} from '~/constants'
|
||||||
|
import { connectionsTableSize, setConnectionsTableSize } from '~/signals'
|
||||||
|
|
||||||
type ColumnVisibility = Partial<Record<CONNECTIONS_TABLE_ACCESSOR_KEY, boolean>>
|
type ColumnVisibility = Partial<Record<CONNECTIONS_TABLE_ACCESSOR_KEY, boolean>>
|
||||||
type ColumnOrder = CONNECTIONS_TABLE_ACCESSOR_KEY[]
|
type ColumnOrder = CONNECTIONS_TABLE_ACCESSOR_KEY[]
|
||||||
|
|
||||||
export const ConnectionsTableOrderingModal = (props: {
|
export const ConnectionsSettingsModal = (props: {
|
||||||
order: ColumnOrder
|
order: ColumnOrder
|
||||||
visible: ColumnVisibility
|
visible: ColumnVisibility
|
||||||
onOrderChange: (value: ColumnOrder) => void
|
onOrderChange: (value: ColumnOrder) => void
|
||||||
@ -76,8 +79,9 @@ export const ConnectionsTableOrderingModal = (props: {
|
|||||||
'transition-transform': !!state.active.draggable,
|
'transition-transform': !!state.active.draggable,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div class="my-1 flex cursor-grab justify-between p-1">
|
<div class="flex cursor-grab justify-between py-2">
|
||||||
<span class="select-none">{t(key)}</span>
|
<span class="select-none">{t(key)}</span>
|
||||||
|
|
||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
class="toggle"
|
class="toggle"
|
||||||
@ -96,10 +100,32 @@ export const ConnectionsTableOrderingModal = (props: {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<dialog
|
<dialog
|
||||||
id="connections-table-ordering-modal"
|
id={MODAL.CONNECTIONS_SETTINGS}
|
||||||
class="modal modal-bottom sm:modal-middle"
|
class="modal modal-bottom sm:modal-middle"
|
||||||
>
|
>
|
||||||
<div class="modal-box" onContextMenu={(e) => e.preventDefault()}>
|
<div
|
||||||
|
class="modal-box flex flex-col gap-4"
|
||||||
|
onContextMenu={(e) => e.preventDefault()}
|
||||||
|
>
|
||||||
|
<div>
|
||||||
|
<ConfigTitle withDivider>{t('tableSize')}</ConfigTitle>
|
||||||
|
|
||||||
|
<select
|
||||||
|
class="select select-bordered w-full"
|
||||||
|
value={connectionsTableSize()}
|
||||||
|
onChange={(e) =>
|
||||||
|
setConnectionsTableSize(e.target.value as TAILWINDCSS_SIZE)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<For each={Object.values(TAILWINDCSS_SIZE)}>
|
||||||
|
{(value) => <option value={value}>{t(value)}</option>}
|
||||||
|
</For>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<ConfigTitle withDivider>{t('sort')}</ConfigTitle>
|
||||||
|
|
||||||
<DragDropProvider
|
<DragDropProvider
|
||||||
onDragStart={onDragStart}
|
onDragStart={onDragStart}
|
||||||
onDragEnd={onDragEnd as DragEventHandler}
|
onDragEnd={onDragEnd as DragEventHandler}
|
||||||
@ -117,6 +143,7 @@ export const ConnectionsTableOrderingModal = (props: {
|
|||||||
</Show>
|
</Show>
|
||||||
</DragOverlay>
|
</DragOverlay>
|
||||||
</DragDropProvider>
|
</DragDropProvider>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="modal-action">
|
<div class="modal-action">
|
||||||
<Button
|
<Button
|
@ -1,4 +1,5 @@
|
|||||||
import { Component, Show } from 'solid-js'
|
import { Component, Show } from 'solid-js'
|
||||||
|
import { MODAL } from '~/constants'
|
||||||
import { allConnections } from '~/signals'
|
import { allConnections } from '~/signals'
|
||||||
|
|
||||||
export const ConnectionsTableDetailsModal: Component<{
|
export const ConnectionsTableDetailsModal: Component<{
|
||||||
@ -6,7 +7,7 @@ export const ConnectionsTableDetailsModal: Component<{
|
|||||||
}> = (props) => {
|
}> = (props) => {
|
||||||
return (
|
return (
|
||||||
<dialog
|
<dialog
|
||||||
id="connections-table-details-modal"
|
id={MODAL.CONNECTIONS_TABLE_DETAILS}
|
||||||
class="modal modal-bottom sm:modal-middle"
|
class="modal modal-bottom sm:modal-middle"
|
||||||
>
|
>
|
||||||
<div class="modal-box">
|
<div class="modal-box">
|
||||||
|
81
src/components/LogsSettingsModal.tsx
Normal file
81
src/components/LogsSettingsModal.tsx
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
import { useI18n } from '@solid-primitives/i18n'
|
||||||
|
import { For } from 'solid-js'
|
||||||
|
import { ConfigTitle } from '~/components'
|
||||||
|
import {
|
||||||
|
LOG_LEVEL,
|
||||||
|
LOGS_TABLE_MAX_ROWS_LIST,
|
||||||
|
MODAL,
|
||||||
|
TAILWINDCSS_SIZE,
|
||||||
|
} from '~/constants'
|
||||||
|
import {
|
||||||
|
logMaxRows,
|
||||||
|
logsTableSize,
|
||||||
|
setLogLevel,
|
||||||
|
setLogMaxRows,
|
||||||
|
setLogsTableSize,
|
||||||
|
} from '~/signals'
|
||||||
|
|
||||||
|
export const LogsSettingsModal = () => {
|
||||||
|
const [t] = useI18n()
|
||||||
|
|
||||||
|
return (
|
||||||
|
<dialog id={MODAL.LOGS_SETTINGS} class="modal modal-bottom sm:modal-middle">
|
||||||
|
<div class="modal-box flex flex-col gap-4">
|
||||||
|
<div>
|
||||||
|
<ConfigTitle withDivider>{t('tableSize')}</ConfigTitle>
|
||||||
|
|
||||||
|
<select
|
||||||
|
class="select select-bordered w-full"
|
||||||
|
value={logsTableSize()}
|
||||||
|
onChange={(e) =>
|
||||||
|
setLogsTableSize(e.target.value as TAILWINDCSS_SIZE)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<For each={Object.values(TAILWINDCSS_SIZE)}>
|
||||||
|
{(value) => <option value={value}>{t(value)}</option>}
|
||||||
|
</For>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<ConfigTitle withDivider>{t('logLevel')}</ConfigTitle>
|
||||||
|
|
||||||
|
<select
|
||||||
|
class="select select-bordered w-full"
|
||||||
|
onChange={(e) => setLogLevel(e.target.value as LOG_LEVEL)}
|
||||||
|
>
|
||||||
|
<For
|
||||||
|
each={[
|
||||||
|
LOG_LEVEL.Info,
|
||||||
|
LOG_LEVEL.Error,
|
||||||
|
LOG_LEVEL.Warning,
|
||||||
|
LOG_LEVEL.Debug,
|
||||||
|
LOG_LEVEL.Silent,
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
{(level) => <option value={level}>{t(level)}</option>}
|
||||||
|
</For>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<ConfigTitle withDivider>{t('logMaxRows')}</ConfigTitle>
|
||||||
|
|
||||||
|
<select
|
||||||
|
class="select select-bordered w-full"
|
||||||
|
value={logMaxRows()}
|
||||||
|
onChange={(e) => setLogMaxRows(parseInt(e.target.value))}
|
||||||
|
>
|
||||||
|
<For each={LOGS_TABLE_MAX_ROWS_LIST}>
|
||||||
|
{(rows) => <option value={rows}>{rows}</option>}
|
||||||
|
</For>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<form method="dialog" class="modal-backdrop">
|
||||||
|
<button />
|
||||||
|
</form>
|
||||||
|
</dialog>
|
||||||
|
)
|
||||||
|
}
|
107
src/components/ProxiesSettingsModal.tsx
Normal file
107
src/components/ProxiesSettingsModal.tsx
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
import { useI18n } from '@solid-primitives/i18n'
|
||||||
|
import { For } from 'solid-js'
|
||||||
|
import { ConfigTitle } from '~/components'
|
||||||
|
import { MODAL, PROXIES_ORDERING_TYPE, PROXIES_PREVIEW_TYPE } from '~/constants'
|
||||||
|
import {
|
||||||
|
autoCloseConns,
|
||||||
|
latencyTestTimeoutDuration,
|
||||||
|
proxiesOrderingType,
|
||||||
|
proxiesPreviewType,
|
||||||
|
setAutoCloseConns,
|
||||||
|
setLatencyTestTimeoutDuration,
|
||||||
|
setProxiesOrderingType,
|
||||||
|
setProxiesPreviewType,
|
||||||
|
setUrlForLatencyTest,
|
||||||
|
urlForLatencyTest,
|
||||||
|
} from '~/signals'
|
||||||
|
|
||||||
|
export const ProxiesSettingsModal = () => {
|
||||||
|
const [t] = useI18n()
|
||||||
|
|
||||||
|
return (
|
||||||
|
<dialog
|
||||||
|
id={MODAL.PROXIES_SETTINGS}
|
||||||
|
class="modal modal-bottom sm:modal-middle"
|
||||||
|
>
|
||||||
|
<div class="modal-box flex flex-col gap-4">
|
||||||
|
<div>
|
||||||
|
<ConfigTitle withDivider>{t('autoCloseConns')}</ConfigTitle>
|
||||||
|
|
||||||
|
<div class="flex w-full justify-center">
|
||||||
|
<input
|
||||||
|
class="toggle"
|
||||||
|
type="checkbox"
|
||||||
|
checked={autoCloseConns()}
|
||||||
|
onChange={(e) => setAutoCloseConns(e.target.checked)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex flex-col">
|
||||||
|
<ConfigTitle withDivider>{t('urlForLatencyTest')}</ConfigTitle>
|
||||||
|
|
||||||
|
<input
|
||||||
|
class="input input-bordered w-full"
|
||||||
|
value={urlForLatencyTest()}
|
||||||
|
onChange={(e) => setUrlForLatencyTest(e.target.value)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<ConfigTitle withDivider>
|
||||||
|
{t('latencyTestTimeoutDuration')} ({t('ms')})
|
||||||
|
</ConfigTitle>
|
||||||
|
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
class="input input-bordered w-full"
|
||||||
|
value={latencyTestTimeoutDuration()}
|
||||||
|
onChange={(e) =>
|
||||||
|
setLatencyTestTimeoutDuration(Number(e.target.value))
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<ConfigTitle withDivider>{t('proxiesSorting')}</ConfigTitle>
|
||||||
|
|
||||||
|
<select
|
||||||
|
class="select select-bordered w-full"
|
||||||
|
value={proxiesOrderingType()}
|
||||||
|
onChange={(e) =>
|
||||||
|
setProxiesOrderingType(e.target.value as PROXIES_ORDERING_TYPE)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<For each={Object.values(PROXIES_ORDERING_TYPE)}>
|
||||||
|
{(value) => (
|
||||||
|
<option class="flex items-center gap-2" value={value}>
|
||||||
|
{t(value)}
|
||||||
|
</option>
|
||||||
|
)}
|
||||||
|
</For>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<ConfigTitle withDivider>{t('proxiesPreviewType')}</ConfigTitle>
|
||||||
|
|
||||||
|
<select
|
||||||
|
class="select select-bordered w-full"
|
||||||
|
value={proxiesPreviewType()}
|
||||||
|
onChange={(e) =>
|
||||||
|
setProxiesPreviewType(e.target.value as PROXIES_PREVIEW_TYPE)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<For each={Object.values(PROXIES_PREVIEW_TYPE)}>
|
||||||
|
{(value) => <option value={value}>{t(value)}</option>}
|
||||||
|
</For>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<form method="dialog" class="modal-backdrop">
|
||||||
|
<button />
|
||||||
|
</form>
|
||||||
|
</dialog>
|
||||||
|
)
|
||||||
|
}
|
@ -1,11 +1,14 @@
|
|||||||
export * from './Button'
|
export * from './Button'
|
||||||
export * from './Collapse'
|
export * from './Collapse'
|
||||||
|
export * from './ConfigTitle'
|
||||||
|
export * from './ConnectionsSettingsModal'
|
||||||
export * from './ConnectionsTableDetailsModal'
|
export * from './ConnectionsTableDetailsModal'
|
||||||
export * from './ConnectionsTableOrderingModal'
|
|
||||||
export * from './ForTwoColumns'
|
export * from './ForTwoColumns'
|
||||||
export * from './Header'
|
export * from './Header'
|
||||||
export * from './Latency'
|
export * from './Latency'
|
||||||
export * from './LogoText'
|
export * from './LogoText'
|
||||||
|
export * from './LogsSettingsModal'
|
||||||
|
export * from './ProxiesSettingsModal'
|
||||||
export * from './ProxyCardGroups'
|
export * from './ProxyCardGroups'
|
||||||
export * from './ProxyNodeCard'
|
export * from './ProxyNodeCard'
|
||||||
export * from './ProxyNodePreview'
|
export * from './ProxyNodePreview'
|
||||||
|
@ -163,3 +163,11 @@ export enum LOG_LEVEL {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const LOGS_TABLE_MAX_ROWS_LIST = [200, 300, 500, 800, 1000]
|
export const LOGS_TABLE_MAX_ROWS_LIST = [200, 300, 500, 800, 1000]
|
||||||
|
|
||||||
|
export enum MODAL {
|
||||||
|
PROXIES_SETTINGS = 'proxies-settings',
|
||||||
|
RULES_SETTINGS = 'rules-settings',
|
||||||
|
CONNECTIONS_SETTINGS = 'connections-settings',
|
||||||
|
CONNECTIONS_TABLE_DETAILS = 'connections-table-details',
|
||||||
|
LOGS_SETTINGS = 'logs-settings',
|
||||||
|
}
|
||||||
|
@ -59,7 +59,6 @@ export default {
|
|||||||
orderName_desc: 'By name alphabetically (Z-A)',
|
orderName_desc: 'By name alphabetically (Z-A)',
|
||||||
ms: 'ms',
|
ms: 'ms',
|
||||||
updated: 'Updated',
|
updated: 'Updated',
|
||||||
renderProxiesInSamePage: 'Render proxies and proxy provider in same page',
|
|
||||||
tableSize: 'Table size',
|
tableSize: 'Table size',
|
||||||
logLevel: 'Log Level',
|
logLevel: 'Log Level',
|
||||||
info: 'info',
|
info: 'info',
|
||||||
@ -67,7 +66,7 @@ export default {
|
|||||||
debug: 'debug',
|
debug: 'debug',
|
||||||
warning: 'warning',
|
warning: 'warning',
|
||||||
error: 'error',
|
error: 'error',
|
||||||
logMaxRows: 'Log Maxinum Reserved Rows',
|
logMaxRows: 'Log Maximum Reserved Rows',
|
||||||
xs: 'Extra small size',
|
xs: 'Extra small size',
|
||||||
sm: 'Small size',
|
sm: 'Small size',
|
||||||
md: 'Normal size',
|
md: 'Normal size',
|
||||||
@ -86,4 +85,5 @@ export default {
|
|||||||
direct: 'Direct',
|
direct: 'Direct',
|
||||||
active: 'Active',
|
active: 'Active',
|
||||||
closed: 'Closed',
|
closed: 'Closed',
|
||||||
|
sort: 'Sort',
|
||||||
}
|
}
|
||||||
|
@ -59,7 +59,6 @@ export default {
|
|||||||
orderName_desc: '按名称字母排序 (Z-A)',
|
orderName_desc: '按名称字母排序 (Z-A)',
|
||||||
ms: '毫秒',
|
ms: '毫秒',
|
||||||
updated: '更新于',
|
updated: '更新于',
|
||||||
renderProxiesInSamePage: '将代理和代理提供者显示在同一页',
|
|
||||||
tableSize: '表格大小',
|
tableSize: '表格大小',
|
||||||
logLevel: '日志等级',
|
logLevel: '日志等级',
|
||||||
info: '信息',
|
info: '信息',
|
||||||
@ -86,4 +85,5 @@ export default {
|
|||||||
direct: '直连',
|
direct: '直连',
|
||||||
active: '活动',
|
active: '活动',
|
||||||
closed: '已关闭',
|
closed: '已关闭',
|
||||||
|
sort: '排序',
|
||||||
}
|
}
|
||||||
|
@ -2,14 +2,7 @@ import { createForm } from '@felte/solid'
|
|||||||
import { validator } from '@felte/validator-zod'
|
import { validator } from '@felte/validator-zod'
|
||||||
import { useI18n } from '@solid-primitives/i18n'
|
import { useI18n } from '@solid-primitives/i18n'
|
||||||
import { useNavigate } from '@solidjs/router'
|
import { useNavigate } from '@solidjs/router'
|
||||||
import {
|
import { For, Show, createSignal, onMount } from 'solid-js'
|
||||||
For,
|
|
||||||
ParentComponent,
|
|
||||||
Show,
|
|
||||||
children,
|
|
||||||
createSignal,
|
|
||||||
onMount,
|
|
||||||
} from 'solid-js'
|
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
import {
|
import {
|
||||||
fetchBackendConfigAPI,
|
fetchBackendConfigAPI,
|
||||||
@ -22,47 +15,21 @@ import {
|
|||||||
upgradeBackendAPI,
|
upgradeBackendAPI,
|
||||||
upgradingBackend,
|
upgradingBackend,
|
||||||
} from '~/apis'
|
} from '~/apis'
|
||||||
import { Button } from '~/components'
|
import { Button, ConfigTitle } from '~/components'
|
||||||
|
import { LANG, MODE_OPTIONS, ROUTES, themes } from '~/constants'
|
||||||
import {
|
import {
|
||||||
LANG,
|
|
||||||
LOGS_TABLE_MAX_ROWS_LIST,
|
|
||||||
LOG_LEVEL,
|
|
||||||
MODE_OPTIONS,
|
|
||||||
PROXIES_ORDERING_TYPE,
|
|
||||||
PROXIES_PREVIEW_TYPE,
|
|
||||||
ROUTES,
|
|
||||||
TAILWINDCSS_SIZE,
|
|
||||||
themes,
|
|
||||||
} from '~/constants'
|
|
||||||
import {
|
|
||||||
autoCloseConns,
|
|
||||||
autoSwitchTheme,
|
autoSwitchTheme,
|
||||||
backendConfig,
|
backendConfig,
|
||||||
favDayTheme,
|
favDayTheme,
|
||||||
favNightTheme,
|
favNightTheme,
|
||||||
latencyTestTimeoutDuration,
|
|
||||||
logLevel,
|
|
||||||
logMaxRows,
|
|
||||||
proxiesOrderingType,
|
|
||||||
proxiesPreviewType,
|
|
||||||
renderInTwoColumns,
|
renderInTwoColumns,
|
||||||
setAutoCloseConns,
|
|
||||||
setAutoSwitchTheme,
|
setAutoSwitchTheme,
|
||||||
setBackendConfig,
|
setBackendConfig,
|
||||||
setFavDayTheme,
|
setFavDayTheme,
|
||||||
setFavNightTheme,
|
setFavNightTheme,
|
||||||
setLatencyTestTimeoutDuration,
|
|
||||||
setLogLevel,
|
|
||||||
setLogMaxRows,
|
|
||||||
setProxiesOrderingType,
|
|
||||||
setProxiesPreviewType,
|
|
||||||
setRenderInTwoColumns,
|
setRenderInTwoColumns,
|
||||||
setSelectedEndpoint,
|
setSelectedEndpoint,
|
||||||
setTableSize,
|
|
||||||
setTwemoji,
|
setTwemoji,
|
||||||
setUrlForLatencyTest,
|
|
||||||
tableSize,
|
|
||||||
urlForLatencyTest,
|
|
||||||
useRequest,
|
useRequest,
|
||||||
useTwemoji,
|
useTwemoji,
|
||||||
} from '~/signals'
|
} from '~/signals'
|
||||||
@ -73,12 +40,6 @@ const dnsQueryFormSchema = z.object({
|
|||||||
type: z.string(),
|
type: z.string(),
|
||||||
})
|
})
|
||||||
|
|
||||||
const ConfigTitle: ParentComponent = (props) => (
|
|
||||||
<div class="pb-4 text-lg font-semibold">
|
|
||||||
{children(() => props.children)()}
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
|
|
||||||
const DNSQueryForm = () => {
|
const DNSQueryForm = () => {
|
||||||
const [t] = useI18n()
|
const [t] = useI18n()
|
||||||
const request = useRequest()
|
const request = useRequest()
|
||||||
@ -147,7 +108,7 @@ const ConfigForm = () => {
|
|||||||
|
|
||||||
const portsList = [
|
const portsList = [
|
||||||
{
|
{
|
||||||
label: 'Http Port',
|
label: 'HTTP Port',
|
||||||
key: 'port',
|
key: 'port',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -159,7 +120,7 @@ const ConfigForm = () => {
|
|||||||
key: 'redir-port',
|
key: 'redir-port',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'Tproxy Port',
|
label: 'TProxy Port',
|
||||||
key: 'tproxy-port',
|
key: 'tproxy-port',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -226,42 +187,6 @@ const ConfigForm = () => {
|
|||||||
{t('restartCore')}
|
{t('restartCore')}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex flex-col">
|
|
||||||
<ConfigTitle>{t('urlForLatencyTest')}</ConfigTitle>
|
|
||||||
|
|
||||||
<input
|
|
||||||
class="input input-bordered max-w-md"
|
|
||||||
value={urlForLatencyTest()}
|
|
||||||
onChange={(e) => setUrlForLatencyTest(e.target.value)}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<ConfigTitle>
|
|
||||||
{t('latencyTestTimeoutDuration')} ({t('ms')})
|
|
||||||
</ConfigTitle>
|
|
||||||
|
|
||||||
<input
|
|
||||||
type="number"
|
|
||||||
class="input input-bordered w-full max-w-md"
|
|
||||||
value={latencyTestTimeoutDuration()}
|
|
||||||
onChange={(e) =>
|
|
||||||
setLatencyTestTimeoutDuration(Number(e.target.value))
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<ConfigTitle>{t('autoCloseConns')}</ConfigTitle>
|
|
||||||
|
|
||||||
<input
|
|
||||||
class="toggle"
|
|
||||||
type="checkbox"
|
|
||||||
checked={autoCloseConns()}
|
|
||||||
onChange={(e) => setAutoCloseConns(e.target.checked)}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -355,97 +280,6 @@ const ConfigForXd = () => {
|
|||||||
)}
|
)}
|
||||||
</For>
|
</For>
|
||||||
|
|
||||||
<div>
|
|
||||||
<ConfigTitle>{t('proxiesPreviewType')}</ConfigTitle>
|
|
||||||
|
|
||||||
<select
|
|
||||||
class="select select-bordered w-full max-w-xs"
|
|
||||||
value={proxiesPreviewType()}
|
|
||||||
onChange={(e) =>
|
|
||||||
setProxiesPreviewType(e.target.value as PROXIES_PREVIEW_TYPE)
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<For each={Object.values(PROXIES_PREVIEW_TYPE)}>
|
|
||||||
{(value) => <option value={value}>{t(value)}</option>}
|
|
||||||
</For>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<ConfigTitle>{t('proxiesSorting')}</ConfigTitle>
|
|
||||||
|
|
||||||
<select
|
|
||||||
class="select select-bordered w-full max-w-xs"
|
|
||||||
value={proxiesOrderingType()}
|
|
||||||
onChange={(e) =>
|
|
||||||
setProxiesOrderingType(e.target.value as PROXIES_ORDERING_TYPE)
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<For each={Object.values(PROXIES_ORDERING_TYPE)}>
|
|
||||||
{(value) => (
|
|
||||||
<option class="flex items-center gap-2" value={value}>
|
|
||||||
{t(value)}
|
|
||||||
</option>
|
|
||||||
)}
|
|
||||||
</For>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<ConfigTitle>{t('tableSize')}</ConfigTitle>
|
|
||||||
|
|
||||||
<select
|
|
||||||
class="select select-bordered w-full max-w-xs"
|
|
||||||
value={tableSize()}
|
|
||||||
onChange={(e) => setTableSize(e.target.value as TAILWINDCSS_SIZE)}
|
|
||||||
>
|
|
||||||
<For each={Object.values(TAILWINDCSS_SIZE)}>
|
|
||||||
{(value) => <option value={value}>{t(value)}</option>}
|
|
||||||
</For>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<ConfigTitle>{t('logLevel')}</ConfigTitle>
|
|
||||||
|
|
||||||
<select
|
|
||||||
class="select select-bordered w-full max-w-xs"
|
|
||||||
onChange={(e) => {
|
|
||||||
setLogLevel(e.target.value as LOG_LEVEL)
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<For
|
|
||||||
each={[
|
|
||||||
LOG_LEVEL.Info,
|
|
||||||
LOG_LEVEL.Error,
|
|
||||||
LOG_LEVEL.Warning,
|
|
||||||
LOG_LEVEL.Debug,
|
|
||||||
LOG_LEVEL.Silent,
|
|
||||||
]}
|
|
||||||
>
|
|
||||||
{(level) => (
|
|
||||||
<option selected={logLevel() === level} value={level}>
|
|
||||||
{t(level)}
|
|
||||||
</option>
|
|
||||||
)}
|
|
||||||
</For>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<ConfigTitle>{t('logMaxRows')}</ConfigTitle>
|
|
||||||
|
|
||||||
<select
|
|
||||||
class="select select-bordered w-full max-w-xs"
|
|
||||||
value={logMaxRows()}
|
|
||||||
onChange={(e) => setLogMaxRows(parseInt(e.target.value))}
|
|
||||||
>
|
|
||||||
<For each={LOGS_TABLE_MAX_ROWS_LIST}>
|
|
||||||
{(rows) => <option value={rows}>{rows}</option>}
|
|
||||||
</For>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<Button
|
<Button
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
@ -33,16 +33,21 @@ import { twMerge } from 'tailwind-merge'
|
|||||||
import { closeAllConnectionsAPI, closeSingleConnectionAPI } from '~/apis'
|
import { closeAllConnectionsAPI, closeSingleConnectionAPI } from '~/apis'
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
|
ConnectionsSettingsModal,
|
||||||
ConnectionsTableDetailsModal,
|
ConnectionsTableDetailsModal,
|
||||||
ConnectionsTableOrderingModal,
|
|
||||||
} from '~/components'
|
} from '~/components'
|
||||||
import {
|
import {
|
||||||
CONNECTIONS_TABLE_ACCESSOR_KEY,
|
CONNECTIONS_TABLE_ACCESSOR_KEY,
|
||||||
CONNECTIONS_TABLE_INITIAL_COLUMN_ORDER,
|
CONNECTIONS_TABLE_INITIAL_COLUMN_ORDER,
|
||||||
CONNECTIONS_TABLE_INITIAL_COLUMN_VISIBILITY,
|
CONNECTIONS_TABLE_INITIAL_COLUMN_VISIBILITY,
|
||||||
|
MODAL,
|
||||||
} from '~/constants'
|
} from '~/constants'
|
||||||
import { formatTimeFromNow } from '~/helpers'
|
import { formatTimeFromNow } from '~/helpers'
|
||||||
import { tableSize, tableSizeClassName, useConnections } from '~/signals'
|
import {
|
||||||
|
connectionsTableSize,
|
||||||
|
tableSizeClassName,
|
||||||
|
useConnections,
|
||||||
|
} from '~/signals'
|
||||||
import type { Connection } from '~/types'
|
import type { Connection } from '~/types'
|
||||||
|
|
||||||
type ColumnVisibility = Partial<Record<CONNECTIONS_TABLE_ACCESSOR_KEY, boolean>>
|
type ColumnVisibility = Partial<Record<CONNECTIONS_TABLE_ACCESSOR_KEY, boolean>>
|
||||||
@ -107,7 +112,7 @@ export default () => {
|
|||||||
setSelectedConnectionID(row.original.id)
|
setSelectedConnectionID(row.original.id)
|
||||||
|
|
||||||
const modal = document.querySelector(
|
const modal = document.querySelector(
|
||||||
'#connections-table-details-modal',
|
`#${MODAL.CONNECTIONS_TABLE_DETAILS}`,
|
||||||
) as HTMLDialogElement | null
|
) as HTMLDialogElement | null
|
||||||
|
|
||||||
modal?.showModal()
|
modal?.showModal()
|
||||||
@ -357,7 +362,7 @@ export default () => {
|
|||||||
class="btn join-item btn-sm sm:btn-md"
|
class="btn join-item btn-sm sm:btn-md"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
const modal = document.querySelector(
|
const modal = document.querySelector(
|
||||||
'#connections-table-ordering-modal',
|
`#${MODAL.CONNECTIONS_SETTINGS}`,
|
||||||
) as HTMLDialogElement | null
|
) as HTMLDialogElement | null
|
||||||
|
|
||||||
modal?.showModal()
|
modal?.showModal()
|
||||||
@ -371,7 +376,7 @@ export default () => {
|
|||||||
<div class="overflow-x-auto whitespace-nowrap rounded-md bg-base-300">
|
<div class="overflow-x-auto whitespace-nowrap rounded-md bg-base-300">
|
||||||
<table
|
<table
|
||||||
class={twMerge(
|
class={twMerge(
|
||||||
tableSizeClassName(tableSize()),
|
tableSizeClassName(connectionsTableSize()),
|
||||||
'table table-zebra relative rounded-none',
|
'table table-zebra relative rounded-none',
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
@ -488,7 +493,7 @@ export default () => {
|
|||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<ConnectionsTableOrderingModal
|
<ConnectionsSettingsModal
|
||||||
order={columnOrder()}
|
order={columnOrder()}
|
||||||
visible={columnVisibility()}
|
visible={columnVisibility()}
|
||||||
onOrderChange={(data: ColumnOrder) => setColumnOrder(data)}
|
onOrderChange={(data: ColumnOrder) => setColumnOrder(data)}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import { useI18n } from '@solid-primitives/i18n'
|
import { useI18n } from '@solid-primitives/i18n'
|
||||||
|
import { IconSettings } from '@tabler/icons-solidjs'
|
||||||
import {
|
import {
|
||||||
ColumnDef,
|
ColumnDef,
|
||||||
createSolidTable,
|
createSolidTable,
|
||||||
@ -7,8 +8,9 @@ import {
|
|||||||
} from '@tanstack/solid-table'
|
} from '@tanstack/solid-table'
|
||||||
import { For, Index, createEffect, createSignal } from 'solid-js'
|
import { For, Index, createEffect, createSignal } from 'solid-js'
|
||||||
import { twMerge } from 'tailwind-merge'
|
import { twMerge } from 'tailwind-merge'
|
||||||
import { LOG_LEVEL } from '~/constants'
|
import { Button, LogsSettingsModal } from '~/components'
|
||||||
import { tableSize, tableSizeClassName, useWsRequest } from '~/signals'
|
import { LOG_LEVEL, MODAL } from '~/constants'
|
||||||
|
import { logsTableSize, tableSizeClassName, useWsRequest } from '~/signals'
|
||||||
import { logLevel, logMaxRows } from '~/signals/config'
|
import { logLevel, logMaxRows } from '~/signals/config'
|
||||||
import { Log } from '~/types'
|
import { Log } from '~/types'
|
||||||
|
|
||||||
@ -85,17 +87,32 @@ export default () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div class="flex h-full flex-col gap-4 p-1">
|
<div class="flex h-full flex-col gap-4 p-1">
|
||||||
|
<div class="join w-full">
|
||||||
<input
|
<input
|
||||||
type="search"
|
type="search"
|
||||||
class="input input-primary input-sm flex-shrink-0 sm:input-md"
|
class="input join-item input-primary input-sm flex-1 flex-shrink-0 sm:input-md"
|
||||||
placeholder={t('search')}
|
placeholder={t('search')}
|
||||||
onInput={(e) => setSearch(e.target.value)}
|
onInput={(e) => setSearch(e.target.value)}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
class="join-item btn-sm sm:btn-md"
|
||||||
|
onClick={() => {
|
||||||
|
const modal = document.querySelector(
|
||||||
|
`#${MODAL.LOGS_SETTINGS}`,
|
||||||
|
) as HTMLDialogElement | null
|
||||||
|
|
||||||
|
modal?.showModal()
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<IconSettings />
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="overflow-x-auto whitespace-nowrap rounded-md bg-base-300">
|
<div class="overflow-x-auto whitespace-nowrap rounded-md bg-base-300">
|
||||||
<table
|
<table
|
||||||
class={twMerge(
|
class={twMerge(
|
||||||
tableSizeClassName(tableSize()),
|
tableSizeClassName(logsTableSize()),
|
||||||
'table relative rounded-none',
|
'table relative rounded-none',
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
@ -150,6 +167,8 @@ export default () => {
|
|||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<LogsSettingsModal />
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -1,15 +1,21 @@
|
|||||||
import { useI18n } from '@solid-primitives/i18n'
|
import { useI18n } from '@solid-primitives/i18n'
|
||||||
import { IconBrandSpeedtest, IconReload } from '@tabler/icons-solidjs'
|
import {
|
||||||
|
IconBrandSpeedtest,
|
||||||
|
IconReload,
|
||||||
|
IconSettings,
|
||||||
|
} from '@tabler/icons-solidjs'
|
||||||
import { For, Show, createSignal } from 'solid-js'
|
import { For, Show, createSignal } from 'solid-js'
|
||||||
import { twMerge } from 'tailwind-merge'
|
import { twMerge } from 'tailwind-merge'
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
Collapse,
|
Collapse,
|
||||||
ForTwoColumns,
|
ForTwoColumns,
|
||||||
|
ProxiesSettingsModal,
|
||||||
ProxyCardGroups,
|
ProxyCardGroups,
|
||||||
ProxyNodePreview,
|
ProxyNodePreview,
|
||||||
SubscriptionInfo,
|
SubscriptionInfo,
|
||||||
} from '~/components'
|
} from '~/components'
|
||||||
|
import { MODAL } from '~/constants'
|
||||||
import {
|
import {
|
||||||
formatTimeFromNow,
|
formatTimeFromNow,
|
||||||
sortProxiesByOrderingType,
|
sortProxiesByOrderingType,
|
||||||
@ -123,6 +129,21 @@ export default () => {
|
|||||||
/>
|
/>
|
||||||
</Button>
|
</Button>
|
||||||
</Show>
|
</Show>
|
||||||
|
|
||||||
|
<div class="ml-auto">
|
||||||
|
<Button
|
||||||
|
class="btn-circle btn-sm sm:btn-md"
|
||||||
|
onClick={() => {
|
||||||
|
const modal = document.querySelector(
|
||||||
|
`#${MODAL.PROXIES_SETTINGS}`,
|
||||||
|
) as HTMLDialogElement | null
|
||||||
|
|
||||||
|
modal?.showModal()
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<IconSettings />
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Show>
|
</Show>
|
||||||
|
|
||||||
@ -274,6 +295,8 @@ export default () => {
|
|||||||
/>
|
/>
|
||||||
</Show>
|
</Show>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<ProxiesSettingsModal />
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -48,9 +48,13 @@ export const [renderInTwoColumns, setRenderInTwoColumns] = makePersisted(
|
|||||||
createSignal(true),
|
createSignal(true),
|
||||||
{ name: 'renderInTwoColumn', storage: localStorage },
|
{ name: 'renderInTwoColumn', storage: localStorage },
|
||||||
)
|
)
|
||||||
export const [tableSize, setTableSize] = makePersisted(
|
export const [connectionsTableSize, setConnectionsTableSize] = makePersisted(
|
||||||
createSignal<TAILWINDCSS_SIZE>(TAILWINDCSS_SIZE.XS),
|
createSignal<TAILWINDCSS_SIZE>(TAILWINDCSS_SIZE.XS),
|
||||||
{ name: 'tableSize', storage: localStorage },
|
{ name: 'connectionsTableSize', storage: localStorage },
|
||||||
|
)
|
||||||
|
export const [logsTableSize, setLogsTableSize] = makePersisted(
|
||||||
|
createSignal<TAILWINDCSS_SIZE>(TAILWINDCSS_SIZE.XS),
|
||||||
|
{ name: 'logsTableSize', storage: localStorage },
|
||||||
)
|
)
|
||||||
|
|
||||||
export const [logLevel, setLogLevel] = makePersisted(
|
export const [logLevel, setLogLevel] = makePersisted(
|
||||||
|
Loading…
Reference in New Issue
Block a user