formatter.nix: Add prettier
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
name: deploy
|
name: deploy
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- main
|
- main
|
||||||
jobs:
|
jobs:
|
||||||
@@ -10,4 +10,4 @@ jobs:
|
|||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- run: nix run .#deploy-docs
|
- run: nix run .#deploy-docs
|
||||||
env:
|
env:
|
||||||
SSH_HOMEPAGE_KEY: ${{ secrets.SSH_HOMEPAGE_KEY }}
|
SSH_HOMEPAGE_KEY: ${{ secrets.SSH_HOMEPAGE_KEY }}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
{
|
{
|
||||||
"publickey": "age15x8u838dwqflr3t6csf4tlghxm4tx77y379ncqxav7y2n8qp7yzqgrwt00",
|
"publickey": "age15x8u838dwqflr3t6csf4tlghxm4tx77y379ncqxav7y2n8qp7yzqgrwt00",
|
||||||
"type": "age"
|
"type": "age"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
{
|
{
|
||||||
"publickey": "age15x8u838dwqflr3t6csf4tlghxm4tx77y379ncqxav7y2n8qp7yzqgrwt00",
|
"publickey": "age15x8u838dwqflr3t6csf4tlghxm4tx77y379ncqxav7y2n8qp7yzqgrwt00",
|
||||||
"type": "age"
|
"type": "age"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,19 @@
|
|||||||
{% extends "base.html" %}
|
{% extends "base.html" %} {% block extrahead %}
|
||||||
|
<meta
|
||||||
{% block extrahead %}
|
property="og:title"
|
||||||
<meta property="og:title" content="Clan - Documentation, Blog & Getting Started Guide" />
|
content="Clan - Documentation, Blog & Getting Started Guide"
|
||||||
<meta property="og:description" content="Documentation for Clan. The peer-to-peer machine deployment framework." />
|
/>
|
||||||
<meta property="og:image" content="https://clan.lol/static/dark-favicon/128x128.png" />
|
<meta
|
||||||
|
property="og:description"
|
||||||
|
content="Documentation for Clan. The peer-to-peer machine deployment framework."
|
||||||
|
/>
|
||||||
|
<meta
|
||||||
|
property="og:image"
|
||||||
|
content="https://clan.lol/static/dark-favicon/128x128.png"
|
||||||
|
/>
|
||||||
<meta property="og:url" content="https://docs.clan.lol" />
|
<meta property="og:url" content="https://docs.clan.lol" />
|
||||||
<meta property="og:type" content="website" />
|
<meta property="og:type" content="website" />
|
||||||
<meta property="og:site_name" content="Clan" />
|
<meta property="og:site_name" content="Clan" />
|
||||||
<meta property="og:locale" content="en_US" />
|
<meta property="og:locale" content="en_US" />
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
@font-face {
|
@font-face {
|
||||||
font-family: "Roboto";
|
font-family: "Roboto";
|
||||||
src: url(./Roboto-Regular.ttf) format('truetype');
|
src: url(./Roboto-Regular.ttf) format("truetype");
|
||||||
}
|
}
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: "Fira Code";
|
font-family: "Fira Code";
|
||||||
src: url(./FiraCode-VF.ttf) format('truetype');
|
src: url(./FiraCode-VF.ttf) format("truetype");
|
||||||
}
|
}
|
||||||
|
|
||||||
:root {
|
:root {
|
||||||
--md-text-font: "Roboto";
|
--md-text-font: "Roboto";
|
||||||
--md-code-font: "Fira Code";
|
--md-code-font: "Fira Code";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,39 @@
|
|||||||
treefmt.programs.nixfmt.enable = true;
|
treefmt.programs.nixfmt.enable = true;
|
||||||
treefmt.programs.nixfmt.package = pkgs.nixfmt-rfc-style;
|
treefmt.programs.nixfmt.package = pkgs.nixfmt-rfc-style;
|
||||||
treefmt.programs.deadnix.enable = true;
|
treefmt.programs.deadnix.enable = true;
|
||||||
|
treefmt.settings.global.excludes = [
|
||||||
|
"*.png"
|
||||||
|
"*.jpeg"
|
||||||
|
"*.gitignore"
|
||||||
|
".vscode/*"
|
||||||
|
"*.toml"
|
||||||
|
"*.clan-flake"
|
||||||
|
"*.code-workspace"
|
||||||
|
"*.pub"
|
||||||
|
"*.typed"
|
||||||
|
"*.age"
|
||||||
|
"*.list"
|
||||||
|
"*.desktop"
|
||||||
|
];
|
||||||
|
treefmt.programs.prettier = {
|
||||||
|
enable = true;
|
||||||
|
includes = [
|
||||||
|
"*.cjs"
|
||||||
|
"*.css"
|
||||||
|
"*.html"
|
||||||
|
"*.js"
|
||||||
|
"*.json5"
|
||||||
|
"*.jsx"
|
||||||
|
"*.mdx"
|
||||||
|
"*.mjs"
|
||||||
|
"*.scss"
|
||||||
|
"*.ts"
|
||||||
|
"*.tsx"
|
||||||
|
"*.vue"
|
||||||
|
"*.yaml"
|
||||||
|
"*.yml"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
treefmt.programs.mypy.directories =
|
treefmt.programs.mypy.directories =
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,66 +1,63 @@
|
|||||||
/* Insert custom styles here */
|
/* Insert custom styles here */
|
||||||
|
|
||||||
navigation-view {
|
navigation-view {
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
/* padding-left: 5px;
|
/* padding-left: 5px;
|
||||||
padding-right: 5px;
|
padding-right: 5px;
|
||||||
padding-bottom: 5px; */
|
padding-bottom: 5px; */
|
||||||
}
|
}
|
||||||
|
|
||||||
avatar {
|
avatar {
|
||||||
margin: 2px;
|
margin: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.trust {
|
.trust {
|
||||||
padding-top: 25px;
|
padding-top: 25px;
|
||||||
padding-bottom: 25px;
|
padding-bottom: 25px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.join-list {
|
.join-list {
|
||||||
margin-top: 1px;
|
margin-top: 1px;
|
||||||
margin-left: 2px;
|
margin-left: 2px;
|
||||||
margin-right: 2px;
|
margin-right: 2px;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.progress-bar {
|
.progress-bar {
|
||||||
margin-right: 25px;
|
margin-right: 25px;
|
||||||
min-width: 200px;
|
min-width: 200px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.group-list {
|
.group-list {
|
||||||
background-color: inherit;
|
background-color: inherit;
|
||||||
}
|
}
|
||||||
.group-list > .activatable:hover {
|
.group-list > .activatable:hover {
|
||||||
background-color: unset;
|
background-color: unset;
|
||||||
}
|
}
|
||||||
|
|
||||||
.group-list > row {
|
.group-list > row {
|
||||||
margin-top: 12px;
|
margin-top: 12px;
|
||||||
border-bottom: unset;
|
border-bottom: unset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.vm-list {
|
.vm-list {
|
||||||
margin-top: 25px;
|
margin-top: 25px;
|
||||||
margin-bottom: 25px;
|
margin-bottom: 25px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.no-shadow {
|
.no-shadow {
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.search-entry {
|
.search-entry {
|
||||||
margin-bottom: 12px;
|
margin-bottom: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
searchbar {
|
searchbar {
|
||||||
margin-bottom: 25px;
|
margin-bottom: 25px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.log-view {
|
.log-view {
|
||||||
margin-top: 12px;
|
margin-top: 12px;
|
||||||
font-family: monospace;
|
font-family: monospace;
|
||||||
padding: 8px;
|
padding: 8px;
|
||||||
}
|
}
|
||||||
|
|||||||
48
pkgs/clan-cli/.vscode/launch.json
vendored
48
pkgs/clan-cli/.vscode/launch.json
vendored
@@ -1,26 +1,24 @@
|
|||||||
{
|
{
|
||||||
// Use IntelliSense to learn about possible attributes.
|
// Use IntelliSense to learn about possible attributes.
|
||||||
// Hover to view descriptions of existing attributes.
|
// Hover to view descriptions of existing attributes.
|
||||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||||
"version": "0.2.0",
|
"version": "0.2.0",
|
||||||
"configurations": [
|
"configurations": [
|
||||||
{
|
{
|
||||||
"name": "Clan Webui",
|
"name": "Clan Webui",
|
||||||
"type": "python",
|
"type": "python",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"module": "clan_cli.webui",
|
"module": "clan_cli.webui",
|
||||||
"justMyCode": false,
|
"justMyCode": false,
|
||||||
"args": [ "--reload", "--no-open", "--log-level", "debug" ],
|
"args": ["--reload", "--no-open", "--log-level", "debug"]
|
||||||
|
},
|
||||||
},
|
{
|
||||||
{
|
"name": "Clan Cli VMs",
|
||||||
"name": "Clan Cli VMs",
|
"type": "python",
|
||||||
"type": "python",
|
"request": "launch",
|
||||||
"request": "launch",
|
"module": "clan_cli",
|
||||||
"module": "clan_cli",
|
"justMyCode": false,
|
||||||
"justMyCode": false,
|
"args": ["vms"]
|
||||||
"args": [ "vms" ],
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|||||||
42
pkgs/clan-cli/.vscode/settings.json
vendored
42
pkgs/clan-cli/.vscode/settings.json
vendored
@@ -1,22 +1,22 @@
|
|||||||
{
|
{
|
||||||
"python.testing.pytestArgs": [
|
"python.testing.pytestArgs": [
|
||||||
// Coverage is not supported by vscode:
|
// Coverage is not supported by vscode:
|
||||||
// https://github.com/Microsoft/vscode-python/issues/693
|
// https://github.com/Microsoft/vscode-python/issues/693
|
||||||
// Note that this will make pytest fail if pytest-cov is not installed,
|
// Note that this will make pytest fail if pytest-cov is not installed,
|
||||||
// if that's the case, then this option needs to be be removed (overrides
|
// if that's the case, then this option needs to be be removed (overrides
|
||||||
// can be set at a workspace level, it's up to you to decide what's the
|
// can be set at a workspace level, it's up to you to decide what's the
|
||||||
// best approach). You might also prefer to only set this option
|
// best approach). You might also prefer to only set this option
|
||||||
// per-workspace (wherever coverage is used).
|
// per-workspace (wherever coverage is used).
|
||||||
"--no-cov",
|
"--no-cov",
|
||||||
"tests"
|
"tests"
|
||||||
],
|
],
|
||||||
"python.testing.unittestEnabled": false,
|
"python.testing.unittestEnabled": false,
|
||||||
"python.testing.pytestEnabled": true,
|
"python.testing.pytestEnabled": true,
|
||||||
"search.exclude": {
|
"search.exclude": {
|
||||||
"**/.direnv": true
|
"**/.direnv": true
|
||||||
},
|
},
|
||||||
"python.linting.mypyPath": "mypy",
|
"python.linting.mypyPath": "mypy",
|
||||||
"python.linting.mypyEnabled": true,
|
"python.linting.mypyEnabled": true,
|
||||||
"python.linting.enabled": true,
|
"python.linting.enabled": true,
|
||||||
"python.defaultInterpreterPath": "python"
|
"python.defaultInterpreterPath": "python"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,23 +1,23 @@
|
|||||||
secret-key: ENC[AES256_GCM,data:gjX4OmCUdd3TlA4p,iv:3yZVpyd6FqkITQY0nU2M1iubmzvkR6PfkK2m/s6nQh8=,tag:Abgp9xkiFFylZIyAlap6Ew==,type:str]
|
secret-key: ENC[AES256_GCM,data:gjX4OmCUdd3TlA4p,iv:3yZVpyd6FqkITQY0nU2M1iubmzvkR6PfkK2m/s6nQh8=,tag:Abgp9xkiFFylZIyAlap6Ew==,type:str]
|
||||||
nested:
|
nested:
|
||||||
secret-key: ENC[AES256_GCM,data:iUMgDhhIjwvd7wL4,iv:jiJIrh12dSu/sXX+z9ITVoEMNDMjwIlFBnyv40oN4LE=,tag:G9VmAa66Km1sc7JEhW5AvA==,type:str]
|
secret-key: ENC[AES256_GCM,data:iUMgDhhIjwvd7wL4,iv:jiJIrh12dSu/sXX+z9ITVoEMNDMjwIlFBnyv40oN4LE=,tag:G9VmAa66Km1sc7JEhW5AvA==,type:str]
|
||||||
sops:
|
sops:
|
||||||
kms: []
|
kms: []
|
||||||
gcp_kms: []
|
gcp_kms: []
|
||||||
azure_kv: []
|
azure_kv: []
|
||||||
hc_vault: []
|
hc_vault: []
|
||||||
age:
|
age:
|
||||||
- recipient: age14tva0txcrl0zes05x7gkx56qd6wd9q3nwecjac74xxzz4l47r44sv3fz62
|
- recipient: age14tva0txcrl0zes05x7gkx56qd6wd9q3nwecjac74xxzz4l47r44sv3fz62
|
||||||
enc: |
|
enc: |
|
||||||
-----BEGIN AGE ENCRYPTED FILE-----
|
-----BEGIN AGE ENCRYPTED FILE-----
|
||||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA0eWdRVjlydXlXOVZFQ3lO
|
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA0eWdRVjlydXlXOVZFQ3lO
|
||||||
bzU1eG9Iam5Ka29Sdlo0cHJ4b1R6bjdNSzBjCkgwRndCbWZQWHlDU0x1cWRmaGVt
|
bzU1eG9Iam5Ka29Sdlo0cHJ4b1R6bjdNSzBjCkgwRndCbWZQWHlDU0x1cWRmaGVt
|
||||||
N29lbjR6UjN0L2RhaXEzSG9zQmRsZGsKLS0tIEdsdWgxSmZwU3BWUDVxVWRSSC9M
|
N29lbjR6UjN0L2RhaXEzSG9zQmRsZGsKLS0tIEdsdWgxSmZwU3BWUDVxVWRSSC9M
|
||||||
eVZ6bjgwZnR2TTM5MkRYZWNFSFplQWsKmSzv12/dftL9jx2y35UZUGVK6xWdatE8
|
eVZ6bjgwZnR2TTM5MkRYZWNFSFplQWsKmSzv12/dftL9jx2y35UZUGVK6xWdatE8
|
||||||
BGJiCvMlp0BQNrh2s/+YaEaBa48w8LL79U/XJnEZ+ZUwxmlbSTn6Hg==
|
BGJiCvMlp0BQNrh2s/+YaEaBa48w8LL79U/XJnEZ+ZUwxmlbSTn6Hg==
|
||||||
-----END AGE ENCRYPTED FILE-----
|
-----END AGE ENCRYPTED FILE-----
|
||||||
lastmodified: "2023-08-08T14:27:20Z"
|
lastmodified: "2023-08-08T14:27:20Z"
|
||||||
mac: ENC[AES256_GCM,data:iRWWX+L5Q5nKn3fBCLaWoz/mvqGnNnRd93gJmYXDZbRjFoHa9IFJZst5QDIDa1ZRYUe6G0/+lV5SBi+vwRm1pHysJ3c0ZWYjBP+e1jw3jLXxLV5gACsDC8by+6rFUCho0Xgu+Nqu2ehhNenjQQnCvDH5ivWbW70KFT5ynNgR9Tw=,iv:RYnnbLMC/hNfMwWPreMq9uvY0khajwQTZENO/P34ckY=,tag:Xi1PS5vM1c+sRkroHkPn1Q==,type:str]
|
mac: ENC[AES256_GCM,data:iRWWX+L5Q5nKn3fBCLaWoz/mvqGnNnRd93gJmYXDZbRjFoHa9IFJZst5QDIDa1ZRYUe6G0/+lV5SBi+vwRm1pHysJ3c0ZWYjBP+e1jw3jLXxLV5gACsDC8by+6rFUCho0Xgu+Nqu2ehhNenjQQnCvDH5ivWbW70KFT5ynNgR9Tw=,iv:RYnnbLMC/hNfMwWPreMq9uvY0khajwQTZENO/P34ckY=,tag:Xi1PS5vM1c+sRkroHkPn1Q==,type:str]
|
||||||
pgp: []
|
pgp: []
|
||||||
unencrypted_suffix: _unencrypted
|
unencrypted_suffix: _unencrypted
|
||||||
version: 3.7.3
|
version: 3.7.3
|
||||||
|
|||||||
@@ -1,66 +1,63 @@
|
|||||||
/* Insert custom styles here */
|
/* Insert custom styles here */
|
||||||
|
|
||||||
navigation-view {
|
navigation-view {
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
/* padding-left: 5px;
|
/* padding-left: 5px;
|
||||||
padding-right: 5px;
|
padding-right: 5px;
|
||||||
padding-bottom: 5px; */
|
padding-bottom: 5px; */
|
||||||
}
|
}
|
||||||
|
|
||||||
avatar {
|
avatar {
|
||||||
margin: 2px;
|
margin: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.trust {
|
.trust {
|
||||||
padding-top: 25px;
|
padding-top: 25px;
|
||||||
padding-bottom: 25px;
|
padding-bottom: 25px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.join-list {
|
.join-list {
|
||||||
margin-top: 1px;
|
margin-top: 1px;
|
||||||
margin-left: 2px;
|
margin-left: 2px;
|
||||||
margin-right: 2px;
|
margin-right: 2px;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.progress-bar {
|
.progress-bar {
|
||||||
margin-right: 25px;
|
margin-right: 25px;
|
||||||
min-width: 200px;
|
min-width: 200px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.group-list {
|
.group-list {
|
||||||
background-color: inherit;
|
background-color: inherit;
|
||||||
}
|
}
|
||||||
.group-list > .activatable:hover {
|
.group-list > .activatable:hover {
|
||||||
background-color: unset;
|
background-color: unset;
|
||||||
}
|
}
|
||||||
|
|
||||||
.group-list > row {
|
.group-list > row {
|
||||||
margin-top: 12px;
|
margin-top: 12px;
|
||||||
border-bottom: unset;
|
border-bottom: unset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.vm-list {
|
.vm-list {
|
||||||
margin-top: 25px;
|
margin-top: 25px;
|
||||||
margin-bottom: 25px;
|
margin-bottom: 25px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.no-shadow {
|
.no-shadow {
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.search-entry {
|
.search-entry {
|
||||||
margin-bottom: 12px;
|
margin-bottom: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
searchbar {
|
searchbar {
|
||||||
margin-bottom: 25px;
|
margin-bottom: 25px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.log-view {
|
.log-view {
|
||||||
margin-top: 12px;
|
margin-top: 12px;
|
||||||
font-family: monospace;
|
font-family: monospace;
|
||||||
padding: 8px;
|
padding: 8px;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,5 +28,5 @@ export default tseslint.config(
|
|||||||
"no-unused-vars": "off",
|
"no-unused-vars": "off",
|
||||||
"@typescript-eslint/no-unused-vars": "off",
|
"@typescript-eslint/no-unused-vars": "off",
|
||||||
},
|
},
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<!DOCTYPE html>
|
<!doctype html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>Solid App</title>
|
<title>Solid App</title>
|
||||||
|
|||||||
@@ -134,19 +134,21 @@ export const callApi = <K extends OperationNames>(
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const deserialize = <T>(fn: (response: T) => void) => (str: string) => {
|
const deserialize =
|
||||||
try {
|
<T>(fn: (response: T) => void) =>
|
||||||
const r = JSON.parse(str) as T;
|
(str: string) => {
|
||||||
console.log("Received: ", r);
|
try {
|
||||||
fn(r);
|
const r = JSON.parse(str) as T;
|
||||||
} catch (e) {
|
console.log("Received: ", r);
|
||||||
console.log("Error parsing JSON: ", e);
|
fn(r);
|
||||||
window.localStorage.setItem("error", str);
|
} catch (e) {
|
||||||
console.error(str);
|
console.log("Error parsing JSON: ", e);
|
||||||
console.error("See localStorage 'error'");
|
window.localStorage.setItem("error", str);
|
||||||
alert(`Error parsing JSON: ${e}`);
|
console.error(str);
|
||||||
}
|
console.error("See localStorage 'error'");
|
||||||
};
|
alert(`Error parsing JSON: ${e}`);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Create the API object
|
// Create the API object
|
||||||
|
|
||||||
|
|||||||
@@ -94,18 +94,21 @@ export const MachineListItem = (props: MachineListItemProps) => {
|
|||||||
<div class="flex flex-row flex-wrap gap-4 py-2">
|
<div class="flex flex-row flex-wrap gap-4 py-2">
|
||||||
<div class="badge badge-primary flex flex-row gap-1 py-4 align-middle">
|
<div class="badge badge-primary flex flex-row gap-1 py-4 align-middle">
|
||||||
<span>System:</span>
|
<span>System:</span>
|
||||||
{hwInfo()[name]?.system
|
{hwInfo()[name]?.system ? (
|
||||||
? <span class="text-primary">{hwInfo()[name]?.system}</span>
|
<span class="text-primary">{hwInfo()[name]?.system}</span>
|
||||||
: <span class="text-warning">Not set</span>}
|
) : (
|
||||||
|
<span class="text-warning">Not set</span>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="badge badge-ghost flex flex-row gap-1 py-4 align-middle">
|
<div class="badge badge-ghost flex flex-row gap-1 py-4 align-middle">
|
||||||
<span>Target Host:</span>
|
<span>Target Host:</span>
|
||||||
{deploymentInfo()[name]
|
{deploymentInfo()[name] ? (
|
||||||
? <span class="text-primary">{deploymentInfo()[name]}</span>
|
<span class="text-primary">{deploymentInfo()[name]}</span>
|
||||||
: <span class="text-warning">Not set</span>}
|
) : (
|
||||||
{
|
<span class="text-warning">Not set</span>
|
||||||
/* <Show
|
)}
|
||||||
|
{/* <Show
|
||||||
when={deploymentInfo()[name]}
|
when={deploymentInfo()[name]}
|
||||||
fallback={
|
fallback={
|
||||||
<Switch fallback={<div class="skeleton h-8 w-full"></div>}>
|
<Switch fallback={<div class="skeleton h-8 w-full"></div>}>
|
||||||
@@ -116,8 +119,7 @@ export const MachineListItem = (props: MachineListItemProps) => {
|
|||||||
}
|
}
|
||||||
>
|
>
|
||||||
{(i) => + i()}
|
{(i) => + i()}
|
||||||
</Show> */
|
</Show> */}
|
||||||
}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{/* Show only the first error at the bottom */}
|
{/* Show only the first error at the bottom */}
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
@import 'material-icons/iconfont/filled.css';
|
@import "material-icons/iconfont/filled.css";
|
||||||
/* List of icons: https://marella.me/material-icons/demo/ */
|
/* List of icons: https://marella.me/material-icons/demo/ */
|
||||||
@tailwind base;
|
@tailwind base;
|
||||||
@tailwind components;
|
@tailwind components;
|
||||||
@tailwind utilities;
|
@tailwind utilities;
|
||||||
|
|
||||||
html {
|
html {
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
overflow-y: scroll;
|
overflow-y: scroll;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,8 +32,7 @@ export const Layout: Component<LayoutProps> = (props) => {
|
|||||||
for="toplevel-drawer"
|
for="toplevel-drawer"
|
||||||
aria-label="close sidebar"
|
aria-label="close sidebar"
|
||||||
class="drawer-overlay"
|
class="drawer-overlay"
|
||||||
>
|
></label>
|
||||||
</label>
|
|
||||||
<Sidebar route={route} setRoute={setRoute} />
|
<Sidebar route={route} setRoute={setRoute} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -27,35 +27,35 @@ export const BlockDevicesView: Component = () => {
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex max-w-screen-lg flex-col gap-4">
|
<div class="flex max-w-screen-lg flex-col gap-4">
|
||||||
{isFetching
|
{isFetching ? (
|
||||||
? <span class="loading loading-bars"></span>
|
<span class="loading loading-bars"></span>
|
||||||
: (
|
) : (
|
||||||
<Show when={devices}>
|
<Show when={devices}>
|
||||||
{(devices) => (
|
{(devices) => (
|
||||||
<For each={devices().blockdevices}>
|
<For each={devices().blockdevices}>
|
||||||
{(device) => (
|
{(device) => (
|
||||||
<div class="stats shadow">
|
<div class="stats shadow">
|
||||||
<div class="stat w-28 py-8">
|
<div class="stat w-28 py-8">
|
||||||
<div class="stat-title">Name</div>
|
<div class="stat-title">Name</div>
|
||||||
<div class="stat-value">
|
<div class="stat-value">
|
||||||
{" "}
|
{" "}
|
||||||
<span class="material-icons">storage</span>{" "}
|
<span class="material-icons">storage</span>{" "}
|
||||||
{device.name}
|
{device.name}
|
||||||
</div>
|
|
||||||
<div class="stat-desc"></div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="stat w-28">
|
|
||||||
<div class="stat-title">Size</div>
|
|
||||||
<div class="stat-value">{device.size}</div>
|
|
||||||
<div class="stat-desc"></div>
|
|
||||||
</div>
|
</div>
|
||||||
|
<div class="stat-desc"></div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
|
||||||
</For>
|
<div class="stat w-28">
|
||||||
)}
|
<div class="stat-title">Size</div>
|
||||||
</Show>
|
<div class="stat-value">{device.size}</div>
|
||||||
)}
|
<div class="stat-desc"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</For>
|
||||||
|
)}
|
||||||
|
</Show>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,16 +1,14 @@
|
|||||||
import { route } from "@/src/App";
|
import { callApi, OperationResponse } from "@/src/api";
|
||||||
import { callApi, OperationArgs, OperationResponse, pyApi } from "@/src/api";
|
|
||||||
import {
|
import {
|
||||||
createForm,
|
createForm,
|
||||||
required,
|
required,
|
||||||
|
FieldValues,
|
||||||
setValue,
|
setValue,
|
||||||
SubmitHandler,
|
|
||||||
} from "@modular-forms/solid";
|
} from "@modular-forms/solid";
|
||||||
import { createQuery } from "@tanstack/solid-query";
|
import { createQuery } from "@tanstack/solid-query";
|
||||||
import { createEffect, createSignal, For } from "solid-js";
|
import { createEffect, createSignal, For } from "solid-js";
|
||||||
import { effect } from "solid-js/web";
|
|
||||||
|
|
||||||
type FlashFormValues = {
|
interface FlashFormValues extends FieldValues {
|
||||||
machine: {
|
machine: {
|
||||||
devicePath: string;
|
devicePath: string;
|
||||||
flake: string;
|
flake: string;
|
||||||
@@ -19,7 +17,7 @@ type FlashFormValues = {
|
|||||||
language: string;
|
language: string;
|
||||||
keymap: string;
|
keymap: string;
|
||||||
sshKeys: string[];
|
sshKeys: string[];
|
||||||
};
|
}
|
||||||
|
|
||||||
type BlockDevices = Extract<
|
type BlockDevices = Extract<
|
||||||
OperationResponse<"show_block_devices">,
|
OperationResponse<"show_block_devices">,
|
||||||
@@ -59,10 +57,7 @@ export const Flash = () => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const {
|
const { data: devices, isFetching } = createQuery(() => ({
|
||||||
data: devices,
|
|
||||||
isFetching,
|
|
||||||
} = createQuery(() => ({
|
|
||||||
queryKey: ["block_devices"],
|
queryKey: ["block_devices"],
|
||||||
queryFn: async () => {
|
queryFn: async () => {
|
||||||
const result = await callApi("show_block_devices", {});
|
const result = await callApi("show_block_devices", {});
|
||||||
@@ -72,10 +67,7 @@ export const Flash = () => {
|
|||||||
staleTime: 1000 * 60 * 2, // 1 minutes
|
staleTime: 1000 * 60 * 2, // 1 minutes
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const {
|
const { data: keymaps, isFetching: isFetchingKeymaps } = createQuery(() => ({
|
||||||
data: keymaps,
|
|
||||||
isFetching: isFetchingKeymaps,
|
|
||||||
} = createQuery(() => ({
|
|
||||||
queryKey: ["list_keymaps"],
|
queryKey: ["list_keymaps"],
|
||||||
queryFn: async () => {
|
queryFn: async () => {
|
||||||
const result = await callApi("list_possible_keymaps", {});
|
const result = await callApi("list_possible_keymaps", {});
|
||||||
@@ -85,18 +77,17 @@ export const Flash = () => {
|
|||||||
staleTime: 1000 * 60 * 15, // 15 minutes
|
staleTime: 1000 * 60 * 15, // 15 minutes
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const {
|
const { data: languages, isFetching: isFetchingLanguages } = createQuery(
|
||||||
data: languages,
|
() => ({
|
||||||
isFetching: isFetchingLanguages,
|
queryKey: ["list_languages"],
|
||||||
} = createQuery(() => ({
|
queryFn: async () => {
|
||||||
queryKey: ["list_languages"],
|
const result = await callApi("list_possible_languages", {});
|
||||||
queryFn: async () => {
|
if (result.status === "error") throw new Error("Failed to fetch data");
|
||||||
const result = await callApi("list_possible_languages", {});
|
return result.data;
|
||||||
if (result.status === "error") throw new Error("Failed to fetch data");
|
},
|
||||||
return result.data;
|
staleTime: 1000 * 60 * 15, // 15 minutes
|
||||||
},
|
}),
|
||||||
staleTime: 1000 * 60 * 15, // 15 minutes
|
);
|
||||||
}));
|
|
||||||
|
|
||||||
const handleSubmit = async (values: FlashFormValues) => {
|
const handleSubmit = async (values: FlashFormValues) => {
|
||||||
setIsFlashing(true);
|
setIsFlashing(true);
|
||||||
@@ -109,7 +100,7 @@ export const Flash = () => {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
mode: "format",
|
mode: "format",
|
||||||
disks: { "main": values.disk },
|
disks: { main: values.disk },
|
||||||
system_config: {
|
system_config: {
|
||||||
language: values.language,
|
language: values.language,
|
||||||
keymap: values.keymap,
|
keymap: values.keymap,
|
||||||
@@ -191,7 +182,9 @@ export const Flash = () => {
|
|||||||
class="select select-bordered w-full"
|
class="select select-bordered w-full"
|
||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
<option value="" disabled>Select a disk</option>
|
<option value="" disabled>
|
||||||
|
Select a disk
|
||||||
|
</option>
|
||||||
<For each={devices?.blockdevices}>
|
<For each={devices?.blockdevices}>
|
||||||
{(device) => (
|
{(device) => (
|
||||||
<option value={device.path}>
|
<option value={device.path}>
|
||||||
@@ -227,11 +220,7 @@ export const Flash = () => {
|
|||||||
>
|
>
|
||||||
<option>en_US.UTF-8</option>
|
<option>en_US.UTF-8</option>
|
||||||
<For each={languages}>
|
<For each={languages}>
|
||||||
{(language) => (
|
{(language) => <option value={language}>{language}</option>}
|
||||||
<option value={language}>
|
|
||||||
{language}
|
|
||||||
</option>
|
|
||||||
)}
|
|
||||||
</For>
|
</For>
|
||||||
</select>
|
</select>
|
||||||
<div class="label">
|
<div class="label">
|
||||||
@@ -261,17 +250,12 @@ export const Flash = () => {
|
|||||||
>
|
>
|
||||||
<option>en</option>
|
<option>en</option>
|
||||||
<For each={keymaps}>
|
<For each={keymaps}>
|
||||||
{(keymap) => (
|
{(keymap) => <option value={keymap}>{keymap}</option>}
|
||||||
<option value={keymap}>
|
|
||||||
{keymap}
|
|
||||||
</option>
|
|
||||||
)}
|
|
||||||
</For>
|
</For>
|
||||||
</select>
|
</select>
|
||||||
<div class="label">
|
<div class="label">
|
||||||
{isFetchingKeymaps && (
|
{isFetchingKeymaps && (
|
||||||
<span class="label-text
|
<span class="label-text-alt">
|
||||||
-alt">
|
|
||||||
<span class="loading loading-bars"></span>
|
<span class="loading loading-bars"></span>
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
@@ -312,9 +296,11 @@ export const Flash = () => {
|
|||||||
)}
|
)}
|
||||||
</Field>
|
</Field>
|
||||||
<button class="btn btn-error" type="submit" disabled={isFlashing()}>
|
<button class="btn btn-error" type="submit" disabled={isFlashing()}>
|
||||||
{isFlashing()
|
{isFlashing() ? (
|
||||||
? <span class="loading loading-spinner"></span>
|
<span class="loading loading-spinner"></span>
|
||||||
: <span class="material-icons">bolt</span>}
|
) : (
|
||||||
|
<span class="material-icons">bolt</span>
|
||||||
|
)}
|
||||||
{isFlashing() ? "Flashing..." : "Flash Installer"}
|
{isFlashing() ? "Flashing..." : "Flash Installer"}
|
||||||
</button>
|
</button>
|
||||||
</Form>
|
</Form>
|
||||||
|
|||||||
@@ -91,8 +91,7 @@ export const MachineListView: Component = () => {
|
|||||||
<span class="material-icons ">add</span>
|
<span class="material-icons ">add</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
{
|
{/* <Show when={services()}>
|
||||||
/* <Show when={services()}>
|
|
||||||
{(services) => (
|
{(services) => (
|
||||||
<For each={Object.values(services())}>
|
<For each={Object.values(services())}>
|
||||||
{(service) => (
|
{(service) => (
|
||||||
@@ -138,8 +137,7 @@ export const MachineListView: Component = () => {
|
|||||||
)}
|
)}
|
||||||
</For>
|
</For>
|
||||||
)}
|
)}
|
||||||
</Show> */
|
</Show> */}
|
||||||
}
|
|
||||||
<Switch>
|
<Switch>
|
||||||
<Match when={loading()}>
|
<Match when={loading()}>
|
||||||
{/* Loading skeleton */}
|
{/* Loading skeleton */}
|
||||||
|
|||||||
@@ -33,17 +33,17 @@ export const registerClan = async () => {
|
|||||||
});
|
});
|
||||||
console.log({ loc }, loc.status);
|
console.log({ loc }, loc.status);
|
||||||
if (loc.status === "success" && loc.data) {
|
if (loc.status === "success" && loc.data) {
|
||||||
// @ts-expect-error: data is a string
|
const data = loc.data[0];
|
||||||
setClanList((s) => {
|
setClanList((s) => {
|
||||||
const res = new Set([...s, loc.data]);
|
const res = new Set([...s, data]);
|
||||||
return Array.from(res);
|
return Array.from(res);
|
||||||
});
|
});
|
||||||
setActiveURI(loc.data);
|
setActiveURI(data);
|
||||||
setRoute((r) => {
|
setRoute((r) => {
|
||||||
if (r === "welcome") return "machines";
|
if (r === "welcome") return "machines";
|
||||||
return r;
|
return r;
|
||||||
});
|
});
|
||||||
return loc.data;
|
return data;
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
//
|
//
|
||||||
@@ -145,7 +145,7 @@ const ClanDetails = (props: ClanDetailsProps) => {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
})
|
}),
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -44,13 +44,13 @@ describe.concurrent("API types work properly", () => {
|
|||||||
.parameter(0)
|
.parameter(0)
|
||||||
.toMatchTypeOf<
|
.toMatchTypeOf<
|
||||||
| {
|
| {
|
||||||
status: "success";
|
status: "success";
|
||||||
data: {
|
data: {
|
||||||
machine_name: string;
|
machine_name: string;
|
||||||
machine_icon?: string | null;
|
machine_icon?: string | null;
|
||||||
machine_description?: string | null;
|
machine_description?: string | null;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
| { status: "error"; errors: any }
|
| { status: "error"; errors: any }
|
||||||
>();
|
>();
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -20,7 +20,8 @@ export function isValidHostname(value: string | null | undefined) {
|
|||||||
const isValid = labels.every(function (label) {
|
const isValid = labels.every(function (label) {
|
||||||
const validLabelChars = /^([a-zA-Z0-9-]+)$/g;
|
const validLabelChars = /^([a-zA-Z0-9-]+)$/g;
|
||||||
|
|
||||||
const validLabel = validLabelChars.test(label) &&
|
const validLabel =
|
||||||
|
validLabelChars.test(label) &&
|
||||||
label.length < 64 &&
|
label.length < 64 &&
|
||||||
!label.startsWith("-") &&
|
!label.startsWith("-") &&
|
||||||
!label.endsWith("-");
|
!label.endsWith("-");
|
||||||
|
|||||||
Reference in New Issue
Block a user