Separate pages for controls and workers
This commit is contained in:
@@ -18,12 +18,15 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@heroicons/react": "^2.2.0",
|
"@heroicons/react": "^2.2.0",
|
||||||
"@hookform/resolvers": "^5.1.1",
|
"@hookform/resolvers": "^5.1.1",
|
||||||
|
"@radix-ui/react-checkbox": "^1.3.3",
|
||||||
"@radix-ui/react-collapsible": "^1.1.11",
|
"@radix-ui/react-collapsible": "^1.1.11",
|
||||||
"@radix-ui/react-dialog": "^1.1.14",
|
"@radix-ui/react-dialog": "^1.1.14",
|
||||||
"@radix-ui/react-label": "^2.1.7",
|
"@radix-ui/react-label": "^2.1.7",
|
||||||
"@radix-ui/react-select": "^2.2.6",
|
"@radix-ui/react-select": "^2.2.6",
|
||||||
"@radix-ui/react-separator": "^1.1.7",
|
"@radix-ui/react-separator": "^1.1.7",
|
||||||
"@radix-ui/react-slot": "^1.2.3",
|
"@radix-ui/react-slot": "^1.2.3",
|
||||||
|
"@radix-ui/react-switch": "^1.2.6",
|
||||||
|
"@radix-ui/react-tabs": "^1.1.13",
|
||||||
"@radix-ui/react-tooltip": "^1.2.7",
|
"@radix-ui/react-tooltip": "^1.2.7",
|
||||||
"@tailwindcss/vite": "^4.1.10",
|
"@tailwindcss/vite": "^4.1.10",
|
||||||
"@tanstack/react-query": "^5.62.10",
|
"@tanstack/react-query": "^5.62.10",
|
||||||
@@ -36,6 +39,7 @@
|
|||||||
"react-markdown": "^10.1.0",
|
"react-markdown": "^10.1.0",
|
||||||
"react-router": "^7.9.4",
|
"react-router": "^7.9.4",
|
||||||
"react-router-dom": "^7.9.4",
|
"react-router-dom": "^7.9.4",
|
||||||
|
"sonner": "^2.0.7",
|
||||||
"tailwind-merge": "^3.3.1",
|
"tailwind-merge": "^3.3.1",
|
||||||
"tailwindcss": "^4.1.10",
|
"tailwindcss": "^4.1.10",
|
||||||
"zod": "^3.25.67"
|
"zod": "^3.25.67"
|
||||||
|
|||||||
162
pnpm-lock.yaml
generated
162
pnpm-lock.yaml
generated
@@ -14,6 +14,9 @@ importers:
|
|||||||
'@hookform/resolvers':
|
'@hookform/resolvers':
|
||||||
specifier: ^5.1.1
|
specifier: ^5.1.1
|
||||||
version: 5.1.1(react-hook-form@7.58.1(react@19.1.0))
|
version: 5.1.1(react-hook-form@7.58.1(react@19.1.0))
|
||||||
|
'@radix-ui/react-checkbox':
|
||||||
|
specifier: ^1.3.3
|
||||||
|
version: 1.3.3(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||||
'@radix-ui/react-collapsible':
|
'@radix-ui/react-collapsible':
|
||||||
specifier: ^1.1.11
|
specifier: ^1.1.11
|
||||||
version: 1.1.11(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
version: 1.1.11(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||||
@@ -32,6 +35,12 @@ importers:
|
|||||||
'@radix-ui/react-slot':
|
'@radix-ui/react-slot':
|
||||||
specifier: ^1.2.3
|
specifier: ^1.2.3
|
||||||
version: 1.2.3(@types/react@19.1.8)(react@19.1.0)
|
version: 1.2.3(@types/react@19.1.8)(react@19.1.0)
|
||||||
|
'@radix-ui/react-switch':
|
||||||
|
specifier: ^1.2.6
|
||||||
|
version: 1.2.6(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||||
|
'@radix-ui/react-tabs':
|
||||||
|
specifier: ^1.1.13
|
||||||
|
version: 1.1.13(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||||
'@radix-ui/react-tooltip':
|
'@radix-ui/react-tooltip':
|
||||||
specifier: ^1.2.7
|
specifier: ^1.2.7
|
||||||
version: 1.2.7(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
version: 1.2.7(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||||
@@ -68,6 +77,9 @@ importers:
|
|||||||
react-router-dom:
|
react-router-dom:
|
||||||
specifier: ^7.9.4
|
specifier: ^7.9.4
|
||||||
version: 7.9.4(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
version: 7.9.4(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||||
|
sonner:
|
||||||
|
specifier: ^2.0.7
|
||||||
|
version: 2.0.7(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||||
tailwind-merge:
|
tailwind-merge:
|
||||||
specifier: ^3.3.1
|
specifier: ^3.3.1
|
||||||
version: 3.3.1
|
version: 3.3.1
|
||||||
@@ -564,6 +576,19 @@ packages:
|
|||||||
'@types/react-dom':
|
'@types/react-dom':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
'@radix-ui/react-checkbox@1.3.3':
|
||||||
|
resolution: {integrity: sha512-wBbpv+NQftHDdG86Qc0pIyXk5IR3tM8Vd0nWLKDcX8nNn4nXFOFwsKuqw2okA/1D/mpaAkmuyndrPJTYDNZtFw==}
|
||||||
|
peerDependencies:
|
||||||
|
'@types/react': '*'
|
||||||
|
'@types/react-dom': '*'
|
||||||
|
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||||
|
react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||||
|
peerDependenciesMeta:
|
||||||
|
'@types/react':
|
||||||
|
optional: true
|
||||||
|
'@types/react-dom':
|
||||||
|
optional: true
|
||||||
|
|
||||||
'@radix-ui/react-collapsible@1.1.11':
|
'@radix-ui/react-collapsible@1.1.11':
|
||||||
resolution: {integrity: sha512-2qrRsVGSCYasSz1RFOorXwl0H7g7J1frQtgpQgYrt+MOidtPAINHn9CPovQXb83r8ahapdx3Tu0fa/pdFFSdPg==}
|
resolution: {integrity: sha512-2qrRsVGSCYasSz1RFOorXwl0H7g7J1frQtgpQgYrt+MOidtPAINHn9CPovQXb83r8ahapdx3Tu0fa/pdFFSdPg==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@@ -761,6 +786,19 @@ packages:
|
|||||||
'@types/react-dom':
|
'@types/react-dom':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
'@radix-ui/react-presence@1.1.5':
|
||||||
|
resolution: {integrity: sha512-/jfEwNDdQVBCNvjkGit4h6pMOzq8bHkopq458dPt2lMjx+eBQUohZNG9A7DtO/O5ukSbxuaNGXMjHicgwy6rQQ==}
|
||||||
|
peerDependencies:
|
||||||
|
'@types/react': '*'
|
||||||
|
'@types/react-dom': '*'
|
||||||
|
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||||
|
react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||||
|
peerDependenciesMeta:
|
||||||
|
'@types/react':
|
||||||
|
optional: true
|
||||||
|
'@types/react-dom':
|
||||||
|
optional: true
|
||||||
|
|
||||||
'@radix-ui/react-primitive@2.1.3':
|
'@radix-ui/react-primitive@2.1.3':
|
||||||
resolution: {integrity: sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==}
|
resolution: {integrity: sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@@ -774,6 +812,19 @@ packages:
|
|||||||
'@types/react-dom':
|
'@types/react-dom':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
'@radix-ui/react-roving-focus@1.1.11':
|
||||||
|
resolution: {integrity: sha512-7A6S9jSgm/S+7MdtNDSb+IU859vQqJ/QAtcYQcfFC6W8RS4IxIZDldLR0xqCFZ6DCyrQLjLPsxtTNch5jVA4lA==}
|
||||||
|
peerDependencies:
|
||||||
|
'@types/react': '*'
|
||||||
|
'@types/react-dom': '*'
|
||||||
|
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||||
|
react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||||
|
peerDependenciesMeta:
|
||||||
|
'@types/react':
|
||||||
|
optional: true
|
||||||
|
'@types/react-dom':
|
||||||
|
optional: true
|
||||||
|
|
||||||
'@radix-ui/react-select@2.2.6':
|
'@radix-ui/react-select@2.2.6':
|
||||||
resolution: {integrity: sha512-I30RydO+bnn2PQztvo25tswPH+wFBjehVGtmagkU78yMdwTwVf12wnAOF+AeP8S2N8xD+5UPbGhkUfPyvT+mwQ==}
|
resolution: {integrity: sha512-I30RydO+bnn2PQztvo25tswPH+wFBjehVGtmagkU78yMdwTwVf12wnAOF+AeP8S2N8xD+5UPbGhkUfPyvT+mwQ==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@@ -809,6 +860,32 @@ packages:
|
|||||||
'@types/react':
|
'@types/react':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
'@radix-ui/react-switch@1.2.6':
|
||||||
|
resolution: {integrity: sha512-bByzr1+ep1zk4VubeEVViV592vu2lHE2BZY5OnzehZqOOgogN80+mNtCqPkhn2gklJqOpxWgPoYTSnhBCqpOXQ==}
|
||||||
|
peerDependencies:
|
||||||
|
'@types/react': '*'
|
||||||
|
'@types/react-dom': '*'
|
||||||
|
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||||
|
react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||||
|
peerDependenciesMeta:
|
||||||
|
'@types/react':
|
||||||
|
optional: true
|
||||||
|
'@types/react-dom':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@radix-ui/react-tabs@1.1.13':
|
||||||
|
resolution: {integrity: sha512-7xdcatg7/U+7+Udyoj2zodtI9H/IIopqo+YOIcZOq1nJwXWBZ9p8xiu5llXlekDbZkca79a/fozEYQXIA4sW6A==}
|
||||||
|
peerDependencies:
|
||||||
|
'@types/react': '*'
|
||||||
|
'@types/react-dom': '*'
|
||||||
|
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||||
|
react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||||
|
peerDependenciesMeta:
|
||||||
|
'@types/react':
|
||||||
|
optional: true
|
||||||
|
'@types/react-dom':
|
||||||
|
optional: true
|
||||||
|
|
||||||
'@radix-ui/react-tooltip@1.2.7':
|
'@radix-ui/react-tooltip@1.2.7':
|
||||||
resolution: {integrity: sha512-Ap+fNYwKTYJ9pzqW+Xe2HtMRbQ/EeWkj2qykZ6SuEV4iS/o1bZI5ssJbk4D2r8XuDuOBVz/tIx2JObtuqU+5Zw==}
|
resolution: {integrity: sha512-Ap+fNYwKTYJ9pzqW+Xe2HtMRbQ/EeWkj2qykZ6SuEV4iS/o1bZI5ssJbk4D2r8XuDuOBVz/tIx2JObtuqU+5Zw==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@@ -2273,6 +2350,12 @@ packages:
|
|||||||
siginfo@2.0.0:
|
siginfo@2.0.0:
|
||||||
resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==}
|
resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==}
|
||||||
|
|
||||||
|
sonner@2.0.7:
|
||||||
|
resolution: {integrity: sha512-W6ZN4p58k8aDKA4XPcx2hpIQXBRAgyiWVkYhT7CvK6D3iAu7xjvVyhQHg2/iaKJZ1XVJ4r7XuwGL+WGEK37i9w==}
|
||||||
|
peerDependencies:
|
||||||
|
react: ^18.0.0 || ^19.0.0 || ^19.0.0-rc
|
||||||
|
react-dom: ^18.0.0 || ^19.0.0 || ^19.0.0-rc
|
||||||
|
|
||||||
source-map-js@1.2.1:
|
source-map-js@1.2.1:
|
||||||
resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
|
resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
@@ -2977,6 +3060,22 @@ snapshots:
|
|||||||
'@types/react': 19.1.8
|
'@types/react': 19.1.8
|
||||||
'@types/react-dom': 19.1.6(@types/react@19.1.8)
|
'@types/react-dom': 19.1.6(@types/react@19.1.8)
|
||||||
|
|
||||||
|
'@radix-ui/react-checkbox@1.3.3(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
|
||||||
|
dependencies:
|
||||||
|
'@radix-ui/primitive': 1.1.3
|
||||||
|
'@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.8)(react@19.1.0)
|
||||||
|
'@radix-ui/react-context': 1.1.2(@types/react@19.1.8)(react@19.1.0)
|
||||||
|
'@radix-ui/react-presence': 1.1.5(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||||
|
'@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||||
|
'@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.1.8)(react@19.1.0)
|
||||||
|
'@radix-ui/react-use-previous': 1.1.1(@types/react@19.1.8)(react@19.1.0)
|
||||||
|
'@radix-ui/react-use-size': 1.1.1(@types/react@19.1.8)(react@19.1.0)
|
||||||
|
react: 19.1.0
|
||||||
|
react-dom: 19.1.0(react@19.1.0)
|
||||||
|
optionalDependencies:
|
||||||
|
'@types/react': 19.1.8
|
||||||
|
'@types/react-dom': 19.1.6(@types/react@19.1.8)
|
||||||
|
|
||||||
'@radix-ui/react-collapsible@1.1.11(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
|
'@radix-ui/react-collapsible@1.1.11(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@radix-ui/primitive': 1.1.2
|
'@radix-ui/primitive': 1.1.2
|
||||||
@@ -3166,6 +3265,16 @@ snapshots:
|
|||||||
'@types/react': 19.1.8
|
'@types/react': 19.1.8
|
||||||
'@types/react-dom': 19.1.6(@types/react@19.1.8)
|
'@types/react-dom': 19.1.6(@types/react@19.1.8)
|
||||||
|
|
||||||
|
'@radix-ui/react-presence@1.1.5(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
|
||||||
|
dependencies:
|
||||||
|
'@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.8)(react@19.1.0)
|
||||||
|
'@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.1.8)(react@19.1.0)
|
||||||
|
react: 19.1.0
|
||||||
|
react-dom: 19.1.0(react@19.1.0)
|
||||||
|
optionalDependencies:
|
||||||
|
'@types/react': 19.1.8
|
||||||
|
'@types/react-dom': 19.1.6(@types/react@19.1.8)
|
||||||
|
|
||||||
'@radix-ui/react-primitive@2.1.3(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
|
'@radix-ui/react-primitive@2.1.3(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@radix-ui/react-slot': 1.2.3(@types/react@19.1.8)(react@19.1.0)
|
'@radix-ui/react-slot': 1.2.3(@types/react@19.1.8)(react@19.1.0)
|
||||||
@@ -3175,6 +3284,23 @@ snapshots:
|
|||||||
'@types/react': 19.1.8
|
'@types/react': 19.1.8
|
||||||
'@types/react-dom': 19.1.6(@types/react@19.1.8)
|
'@types/react-dom': 19.1.6(@types/react@19.1.8)
|
||||||
|
|
||||||
|
'@radix-ui/react-roving-focus@1.1.11(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
|
||||||
|
dependencies:
|
||||||
|
'@radix-ui/primitive': 1.1.3
|
||||||
|
'@radix-ui/react-collection': 1.1.7(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||||
|
'@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.8)(react@19.1.0)
|
||||||
|
'@radix-ui/react-context': 1.1.2(@types/react@19.1.8)(react@19.1.0)
|
||||||
|
'@radix-ui/react-direction': 1.1.1(@types/react@19.1.8)(react@19.1.0)
|
||||||
|
'@radix-ui/react-id': 1.1.1(@types/react@19.1.8)(react@19.1.0)
|
||||||
|
'@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||||
|
'@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.1.8)(react@19.1.0)
|
||||||
|
'@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.1.8)(react@19.1.0)
|
||||||
|
react: 19.1.0
|
||||||
|
react-dom: 19.1.0(react@19.1.0)
|
||||||
|
optionalDependencies:
|
||||||
|
'@types/react': 19.1.8
|
||||||
|
'@types/react-dom': 19.1.6(@types/react@19.1.8)
|
||||||
|
|
||||||
'@radix-ui/react-select@2.2.6(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
|
'@radix-ui/react-select@2.2.6(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@radix-ui/number': 1.1.1
|
'@radix-ui/number': 1.1.1
|
||||||
@@ -3220,6 +3346,37 @@ snapshots:
|
|||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
'@types/react': 19.1.8
|
'@types/react': 19.1.8
|
||||||
|
|
||||||
|
'@radix-ui/react-switch@1.2.6(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
|
||||||
|
dependencies:
|
||||||
|
'@radix-ui/primitive': 1.1.3
|
||||||
|
'@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.8)(react@19.1.0)
|
||||||
|
'@radix-ui/react-context': 1.1.2(@types/react@19.1.8)(react@19.1.0)
|
||||||
|
'@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||||
|
'@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.1.8)(react@19.1.0)
|
||||||
|
'@radix-ui/react-use-previous': 1.1.1(@types/react@19.1.8)(react@19.1.0)
|
||||||
|
'@radix-ui/react-use-size': 1.1.1(@types/react@19.1.8)(react@19.1.0)
|
||||||
|
react: 19.1.0
|
||||||
|
react-dom: 19.1.0(react@19.1.0)
|
||||||
|
optionalDependencies:
|
||||||
|
'@types/react': 19.1.8
|
||||||
|
'@types/react-dom': 19.1.6(@types/react@19.1.8)
|
||||||
|
|
||||||
|
'@radix-ui/react-tabs@1.1.13(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
|
||||||
|
dependencies:
|
||||||
|
'@radix-ui/primitive': 1.1.3
|
||||||
|
'@radix-ui/react-context': 1.1.2(@types/react@19.1.8)(react@19.1.0)
|
||||||
|
'@radix-ui/react-direction': 1.1.1(@types/react@19.1.8)(react@19.1.0)
|
||||||
|
'@radix-ui/react-id': 1.1.1(@types/react@19.1.8)(react@19.1.0)
|
||||||
|
'@radix-ui/react-presence': 1.1.5(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||||
|
'@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||||
|
'@radix-ui/react-roving-focus': 1.1.11(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||||
|
'@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.1.8)(react@19.1.0)
|
||||||
|
react: 19.1.0
|
||||||
|
react-dom: 19.1.0(react@19.1.0)
|
||||||
|
optionalDependencies:
|
||||||
|
'@types/react': 19.1.8
|
||||||
|
'@types/react-dom': 19.1.6(@types/react@19.1.8)
|
||||||
|
|
||||||
'@radix-ui/react-tooltip@1.2.7(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
|
'@radix-ui/react-tooltip@1.2.7(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@radix-ui/primitive': 1.1.2
|
'@radix-ui/primitive': 1.1.2
|
||||||
@@ -4781,6 +4938,11 @@ snapshots:
|
|||||||
|
|
||||||
siginfo@2.0.0: {}
|
siginfo@2.0.0: {}
|
||||||
|
|
||||||
|
sonner@2.0.7(react-dom@19.1.0(react@19.1.0))(react@19.1.0):
|
||||||
|
dependencies:
|
||||||
|
react: 19.1.0
|
||||||
|
react-dom: 19.1.0(react@19.1.0)
|
||||||
|
|
||||||
source-map-js@1.2.1: {}
|
source-map-js@1.2.1: {}
|
||||||
|
|
||||||
space-separated-tokens@2.0.2: {}
|
space-separated-tokens@2.0.2: {}
|
||||||
|
|||||||
@@ -188,11 +188,22 @@ export function AppSidebar() {
|
|||||||
<SidebarMenuSub>
|
<SidebarMenuSub>
|
||||||
<SidebarMenuSubItem>
|
<SidebarMenuSubItem>
|
||||||
<SidebarMenuSubButton asChild>
|
<SidebarMenuSubButton asChild>
|
||||||
<NavLink to={`/instances/${instanceId}/infrastructure`}>
|
<NavLink to={`/instances/${instanceId}/control`}>
|
||||||
<div className="p-1 rounded-md">
|
<div className="p-1 rounded-md">
|
||||||
<Play className="h-4 w-4" />
|
<Cpu className="h-4 w-4" />
|
||||||
</div>
|
</div>
|
||||||
<span className="truncate">Cluster Nodes</span>
|
<span className="truncate">Control Nodes</span>
|
||||||
|
</NavLink>
|
||||||
|
</SidebarMenuSubButton>
|
||||||
|
</SidebarMenuSubItem>
|
||||||
|
|
||||||
|
<SidebarMenuSubItem>
|
||||||
|
<SidebarMenuSubButton asChild>
|
||||||
|
<NavLink to={`/instances/${instanceId}/worker`}>
|
||||||
|
<div className="p-1 rounded-md">
|
||||||
|
<HardDrive className="h-4 w-4" />
|
||||||
|
</div>
|
||||||
|
<span className="truncate">Worker Nodes</span>
|
||||||
</NavLink>
|
</NavLink>
|
||||||
</SidebarMenuSubButton>
|
</SidebarMenuSubButton>
|
||||||
</SidebarMenuSubItem>
|
</SidebarMenuSubItem>
|
||||||
|
|||||||
@@ -15,7 +15,17 @@ import { NodeFormDrawer } from './nodes/NodeFormDrawer';
|
|||||||
import type { NodeFormData } from './nodes/NodeForm';
|
import type { NodeFormData } from './nodes/NodeForm';
|
||||||
import type { Node, HardwareInfo, DiscoveredNode } from '../services/api/types';
|
import type { Node, HardwareInfo, DiscoveredNode } from '../services/api/types';
|
||||||
|
|
||||||
export function ClusterNodesComponent() {
|
interface ClusterNodesComponentProps {
|
||||||
|
filterRole?: 'controlplane' | 'worker';
|
||||||
|
hideDiscoveryWhenNodesGte?: number;
|
||||||
|
showBootstrap?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function ClusterNodesComponent({
|
||||||
|
filterRole,
|
||||||
|
hideDiscoveryWhenNodesGte,
|
||||||
|
showBootstrap = true
|
||||||
|
}: ClusterNodesComponentProps = {}) {
|
||||||
const { currentInstance } = useInstanceContext();
|
const { currentInstance } = useInstanceContext();
|
||||||
const {
|
const {
|
||||||
nodes,
|
nodes,
|
||||||
@@ -64,6 +74,7 @@ export function ClusterNodesComponent() {
|
|||||||
open: false,
|
open: false,
|
||||||
mode: 'add',
|
mode: 'add',
|
||||||
});
|
});
|
||||||
|
const [drawerEverOpened, setDrawerEverOpened] = useState(false);
|
||||||
const [deletingNodeHostname, setDeletingNodeHostname] = useState<string | null>(null);
|
const [deletingNodeHostname, setDeletingNodeHostname] = useState<string | null>(null);
|
||||||
|
|
||||||
const closeDrawer = () => setDrawerState({ ...drawerState, open: false });
|
const closeDrawer = () => setDrawerState({ ...drawerState, open: false });
|
||||||
@@ -121,6 +132,7 @@ export function ClusterNodesComponent() {
|
|||||||
// Fetch full hardware details for the discovered node
|
// Fetch full hardware details for the discovered node
|
||||||
try {
|
try {
|
||||||
const hardware = await getHardware(discovered.ip);
|
const hardware = await getHardware(discovered.ip);
|
||||||
|
setDrawerEverOpened(true);
|
||||||
setDrawerState({
|
setDrawerState({
|
||||||
open: true,
|
open: true,
|
||||||
mode: 'add',
|
mode: 'add',
|
||||||
@@ -137,6 +149,7 @@ export function ClusterNodesComponent() {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const hardware = await getHardware(addNodeIp);
|
const hardware = await getHardware(addNodeIp);
|
||||||
|
setDrawerEverOpened(true);
|
||||||
setDrawerState({
|
setDrawerState({
|
||||||
open: true,
|
open: true,
|
||||||
mode: 'add',
|
mode: 'add',
|
||||||
@@ -153,6 +166,7 @@ export function ClusterNodesComponent() {
|
|||||||
if (node.target_ip) {
|
if (node.target_ip) {
|
||||||
try {
|
try {
|
||||||
const hardware = await getHardware(node.target_ip);
|
const hardware = await getHardware(node.target_ip);
|
||||||
|
setDrawerEverOpened(true);
|
||||||
setDrawerState({
|
setDrawerState({
|
||||||
open: true,
|
open: true,
|
||||||
mode: 'configure',
|
mode: 'configure',
|
||||||
@@ -167,6 +181,7 @@ export function ClusterNodesComponent() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Open drawer without detection data (either no target_ip or detection failed)
|
// Open drawer without detection data (either no target_ip or detection failed)
|
||||||
|
setDrawerEverOpened(true);
|
||||||
setDrawerState({
|
setDrawerState({
|
||||||
open: true,
|
open: true,
|
||||||
mode: 'configure',
|
mode: 'configure',
|
||||||
@@ -177,7 +192,7 @@ export function ClusterNodesComponent() {
|
|||||||
const handleAddSubmit = async (data: NodeFormData) => {
|
const handleAddSubmit = async (data: NodeFormData) => {
|
||||||
const nodeData = {
|
const nodeData = {
|
||||||
hostname: data.hostname,
|
hostname: data.hostname,
|
||||||
role: data.role,
|
role: filterRole || data.role,
|
||||||
disk: data.disk,
|
disk: data.disk,
|
||||||
target_ip: data.targetIp,
|
target_ip: data.targetIp,
|
||||||
interface: data.interface,
|
interface: data.interface,
|
||||||
@@ -244,7 +259,8 @@ export function ClusterNodesComponent() {
|
|||||||
|
|
||||||
|
|
||||||
// Derive status from backend state flags for each node
|
// Derive status from backend state flags for each node
|
||||||
const assignedNodes = nodes.map(node => {
|
const assignedNodes = useMemo(() => {
|
||||||
|
const allNodes = nodes.map(node => {
|
||||||
// Get runtime status from cluster status
|
// Get runtime status from cluster status
|
||||||
const runtimeStatus = clusterStatusData?.node_statuses?.[node.hostname];
|
const runtimeStatus = clusterStatusData?.node_statuses?.[node.hostname];
|
||||||
|
|
||||||
@@ -266,6 +282,13 @@ export function ClusterNodesComponent() {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Filter by role if specified
|
||||||
|
if (filterRole) {
|
||||||
|
return allNodes.filter(node => node.role === filterRole);
|
||||||
|
}
|
||||||
|
return allNodes;
|
||||||
|
}, [nodes, clusterStatusData, filterRole]);
|
||||||
|
|
||||||
// Check if cluster needs bootstrap
|
// Check if cluster needs bootstrap
|
||||||
const needsBootstrap = useMemo(() => {
|
const needsBootstrap = useMemo(() => {
|
||||||
// Find first ready control plane node
|
// Find first ready control plane node
|
||||||
@@ -345,7 +368,7 @@ export function ClusterNodesComponent() {
|
|||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
{/* Bootstrap Alert */}
|
{/* Bootstrap Alert */}
|
||||||
{needsBootstrap && firstReadyControl && (
|
{showBootstrap && needsBootstrap && firstReadyControl && (
|
||||||
<Alert variant="info" className="mb-6">
|
<Alert variant="info" className="mb-6">
|
||||||
<CheckCircle className="h-5 w-5" />
|
<CheckCircle className="h-5 w-5" />
|
||||||
<div className="flex-1">
|
<div className="flex-1">
|
||||||
@@ -443,6 +466,7 @@ export function ClusterNodesComponent() {
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
{/* ADD NODES SECTION - Discovery and manual add combined */}
|
{/* ADD NODES SECTION - Discovery and manual add combined */}
|
||||||
|
{(!hideDiscoveryWhenNodesGte || assignedNodes.length < hideDiscoveryWhenNodesGte) && (
|
||||||
<div className="bg-white dark:bg-gray-800 rounded-lg shadow p-6 mb-6">
|
<div className="bg-white dark:bg-gray-800 rounded-lg shadow p-6 mb-6">
|
||||||
<h3 className="text-lg font-medium text-gray-900 dark:text-gray-100 mb-4">
|
<h3 className="text-lg font-medium text-gray-900 dark:text-gray-100 mb-4">
|
||||||
Add Nodes to Cluster
|
Add Nodes to Cluster
|
||||||
@@ -535,6 +559,7 @@ export function ClusterNodesComponent() {
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
@@ -664,7 +689,8 @@ export function ClusterNodesComponent() {
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Node Form Drawer */}
|
{/* Node Form Drawer - only render after first open to prevent infinite loop on initial mount */}
|
||||||
|
{drawerEverOpened && (
|
||||||
<NodeFormDrawer
|
<NodeFormDrawer
|
||||||
open={drawerState.open}
|
open={drawerState.open}
|
||||||
onClose={closeDrawer}
|
onClose={closeDrawer}
|
||||||
@@ -675,6 +701,7 @@ export function ClusterNodesComponent() {
|
|||||||
onApply={drawerState.mode === 'configure' ? handleApply : undefined}
|
onApply={drawerState.mode === 'configure' ? handleApply : undefined}
|
||||||
instanceName={currentInstance || ''}
|
instanceName={currentInstance || ''}
|
||||||
/>
|
/>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
5
src/components/ControlNodesComponent.tsx
Normal file
5
src/components/ControlNodesComponent.tsx
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
import { ClusterNodesComponent } from './ClusterNodesComponent';
|
||||||
|
|
||||||
|
export function ControlNodesComponent() {
|
||||||
|
return <ClusterNodesComponent filterRole="controlplane" hideDiscoveryWhenNodesGte={3} showBootstrap={true} />;
|
||||||
|
}
|
||||||
5
src/components/WorkerNodesComponent.tsx
Normal file
5
src/components/WorkerNodesComponent.tsx
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
import { ClusterNodesComponent } from './ClusterNodesComponent';
|
||||||
|
|
||||||
|
export function WorkerNodesComponent() {
|
||||||
|
return <ClusterNodesComponent filterRole="worker" hideDiscoveryWhenNodesGte={undefined} showBootstrap={false} />;
|
||||||
|
}
|
||||||
@@ -14,7 +14,6 @@ export { CentralComponent } from './CentralComponent';
|
|||||||
export { DnsComponent } from './DnsComponent';
|
export { DnsComponent } from './DnsComponent';
|
||||||
export { DhcpComponent } from './DhcpComponent';
|
export { DhcpComponent } from './DhcpComponent';
|
||||||
export { PxeComponent } from './PxeComponent';
|
export { PxeComponent } from './PxeComponent';
|
||||||
export { ClusterNodesComponent } from './ClusterNodesComponent';
|
|
||||||
export { ClusterServicesComponent } from './ClusterServicesComponent';
|
export { ClusterServicesComponent } from './ClusterServicesComponent';
|
||||||
export { AppsComponent } from './AppsComponent';
|
export { AppsComponent } from './AppsComponent';
|
||||||
export { SecretInput } from './SecretInput';
|
export { SecretInput } from './SecretInput';
|
||||||
|
|||||||
30
src/components/ui/checkbox.tsx
Normal file
30
src/components/ui/checkbox.tsx
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
import * as React from "react"
|
||||||
|
import * as CheckboxPrimitive from "@radix-ui/react-checkbox"
|
||||||
|
import { CheckIcon } from "lucide-react"
|
||||||
|
|
||||||
|
import { cn } from "@/lib/utils"
|
||||||
|
|
||||||
|
function Checkbox({
|
||||||
|
className,
|
||||||
|
...props
|
||||||
|
}: React.ComponentProps<typeof CheckboxPrimitive.Root>) {
|
||||||
|
return (
|
||||||
|
<CheckboxPrimitive.Root
|
||||||
|
data-slot="checkbox"
|
||||||
|
className={cn(
|
||||||
|
"peer border-input dark:bg-input/30 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground dark:data-[state=checked]:bg-primary data-[state=checked]:border-primary focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive size-4 shrink-0 rounded-[4px] border shadow-xs transition-shadow outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
<CheckboxPrimitive.Indicator
|
||||||
|
data-slot="checkbox-indicator"
|
||||||
|
className="grid place-content-center text-current transition-none"
|
||||||
|
>
|
||||||
|
<CheckIcon className="size-3.5" />
|
||||||
|
</CheckboxPrimitive.Indicator>
|
||||||
|
</CheckboxPrimitive.Root>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export { Checkbox }
|
||||||
29
src/components/ui/switch.tsx
Normal file
29
src/components/ui/switch.tsx
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
import * as React from "react"
|
||||||
|
import * as SwitchPrimitive from "@radix-ui/react-switch"
|
||||||
|
|
||||||
|
import { cn } from "@/lib/utils"
|
||||||
|
|
||||||
|
function Switch({
|
||||||
|
className,
|
||||||
|
...props
|
||||||
|
}: React.ComponentProps<typeof SwitchPrimitive.Root>) {
|
||||||
|
return (
|
||||||
|
<SwitchPrimitive.Root
|
||||||
|
data-slot="switch"
|
||||||
|
className={cn(
|
||||||
|
"peer data-[state=checked]:bg-primary data-[state=unchecked]:bg-input focus-visible:border-ring focus-visible:ring-ring/50 dark:data-[state=unchecked]:bg-input/80 inline-flex h-[1.15rem] w-8 shrink-0 items-center rounded-full border border-transparent shadow-xs transition-all outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
<SwitchPrimitive.Thumb
|
||||||
|
data-slot="switch-thumb"
|
||||||
|
className={cn(
|
||||||
|
"bg-background dark:data-[state=unchecked]:bg-foreground dark:data-[state=checked]:bg-primary-foreground pointer-events-none block size-4 rounded-full ring-0 transition-transform data-[state=checked]:translate-x-[calc(100%-2px)] data-[state=unchecked]:translate-x-0"
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</SwitchPrimitive.Root>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export { Switch }
|
||||||
64
src/components/ui/tabs.tsx
Normal file
64
src/components/ui/tabs.tsx
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
import * as React from "react"
|
||||||
|
import * as TabsPrimitive from "@radix-ui/react-tabs"
|
||||||
|
|
||||||
|
import { cn } from "@/lib/utils"
|
||||||
|
|
||||||
|
function Tabs({
|
||||||
|
className,
|
||||||
|
...props
|
||||||
|
}: React.ComponentProps<typeof TabsPrimitive.Root>) {
|
||||||
|
return (
|
||||||
|
<TabsPrimitive.Root
|
||||||
|
data-slot="tabs"
|
||||||
|
className={cn("flex flex-col gap-2", className)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function TabsList({
|
||||||
|
className,
|
||||||
|
...props
|
||||||
|
}: React.ComponentProps<typeof TabsPrimitive.List>) {
|
||||||
|
return (
|
||||||
|
<TabsPrimitive.List
|
||||||
|
data-slot="tabs-list"
|
||||||
|
className={cn(
|
||||||
|
"bg-muted text-muted-foreground inline-flex h-9 w-fit items-center justify-center rounded-lg p-[3px]",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function TabsTrigger({
|
||||||
|
className,
|
||||||
|
...props
|
||||||
|
}: React.ComponentProps<typeof TabsPrimitive.Trigger>) {
|
||||||
|
return (
|
||||||
|
<TabsPrimitive.Trigger
|
||||||
|
data-slot="tabs-trigger"
|
||||||
|
className={cn(
|
||||||
|
"data-[state=active]:bg-background dark:data-[state=active]:text-foreground focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:outline-ring dark:data-[state=active]:border-input dark:data-[state=active]:bg-input/30 text-foreground dark:text-muted-foreground inline-flex h-[calc(100%-1px)] flex-1 items-center justify-center gap-1.5 rounded-md border border-transparent px-2 py-1 text-sm font-medium whitespace-nowrap transition-[color,box-shadow] focus-visible:ring-[3px] focus-visible:outline-1 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:shadow-sm [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function TabsContent({
|
||||||
|
className,
|
||||||
|
...props
|
||||||
|
}: React.ComponentProps<typeof TabsPrimitive.Content>) {
|
||||||
|
return (
|
||||||
|
<TabsPrimitive.Content
|
||||||
|
data-slot="tabs-content"
|
||||||
|
className={cn("flex-1 outline-none", className)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export { Tabs, TabsList, TabsTrigger, TabsContent }
|
||||||
10
src/router/pages/ControlNodesPage.tsx
Normal file
10
src/router/pages/ControlNodesPage.tsx
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
import { ErrorBoundary } from '../../components';
|
||||||
|
import { ControlNodesComponent } from '../../components/ControlNodesComponent';
|
||||||
|
|
||||||
|
export function ControlNodesPage() {
|
||||||
|
return (
|
||||||
|
<ErrorBoundary>
|
||||||
|
<ControlNodesComponent />
|
||||||
|
</ErrorBoundary>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
import { ErrorBoundary } from '../../components';
|
|
||||||
import { ClusterNodesComponent } from '../../components/ClusterNodesComponent';
|
|
||||||
|
|
||||||
export function InfrastructurePage() {
|
|
||||||
// Note: onComplete callback removed as phase management will be handled differently with routing
|
|
||||||
return (
|
|
||||||
<ErrorBoundary>
|
|
||||||
<ClusterNodesComponent />
|
|
||||||
</ErrorBoundary>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
10
src/router/pages/WorkerNodesPage.tsx
Normal file
10
src/router/pages/WorkerNodesPage.tsx
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
import { ErrorBoundary } from '../../components';
|
||||||
|
import { WorkerNodesComponent } from '../../components/WorkerNodesComponent';
|
||||||
|
|
||||||
|
export function WorkerNodesPage() {
|
||||||
|
return (
|
||||||
|
<ErrorBoundary>
|
||||||
|
<WorkerNodesComponent />
|
||||||
|
</ErrorBoundary>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -15,9 +15,11 @@ import { DnsPage } from './pages/DnsPage';
|
|||||||
import { DhcpPage } from './pages/DhcpPage';
|
import { DhcpPage } from './pages/DhcpPage';
|
||||||
import { PxePage } from './pages/PxePage';
|
import { PxePage } from './pages/PxePage';
|
||||||
import { IsoPage } from './pages/IsoPage';
|
import { IsoPage } from './pages/IsoPage';
|
||||||
import { InfrastructurePage } from './pages/InfrastructurePage';
|
import { ControlNodesPage } from './pages/ControlNodesPage';
|
||||||
|
import { WorkerNodesPage } from './pages/WorkerNodesPage';
|
||||||
import { ClusterPage } from './pages/ClusterPage';
|
import { ClusterPage } from './pages/ClusterPage';
|
||||||
import { AppsPage } from './pages/AppsPage';
|
import { AppsPage } from './pages/AppsPage';
|
||||||
|
import { BackupsPage } from './pages/BackupsPage';
|
||||||
import { AdvancedPage } from './pages/AdvancedPage';
|
import { AdvancedPage } from './pages/AdvancedPage';
|
||||||
import { AssetsIsoPage } from './pages/AssetsIsoPage';
|
import { AssetsIsoPage } from './pages/AssetsIsoPage';
|
||||||
import { AssetsPxePage } from './pages/AssetsPxePage';
|
import { AssetsPxePage } from './pages/AssetsPxePage';
|
||||||
@@ -92,8 +94,12 @@ export const routes: RouteObject[] = [
|
|||||||
element: <IsoPage />,
|
element: <IsoPage />,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'infrastructure',
|
path: 'control',
|
||||||
element: <InfrastructurePage />,
|
element: <ControlNodesPage />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'worker',
|
||||||
|
element: <WorkerNodesPage />,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'cluster',
|
path: 'cluster',
|
||||||
@@ -116,6 +122,10 @@ export const routes: RouteObject[] = [
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: 'backups',
|
||||||
|
element: <BackupsPage />,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: 'advanced',
|
path: 'advanced',
|
||||||
element: <AdvancedPage />,
|
element: <AdvancedPage />,
|
||||||
|
|||||||
Reference in New Issue
Block a user