Merge pull request 'UI: init draggable dialog' (#2660) from hsjobeki/clan-core:hsjobeki-main into main

This commit is contained in:
clan-bot
2024-12-29 11:30:51 +00:00
8 changed files with 492 additions and 50 deletions

View File

@@ -105,7 +105,7 @@ def dataclass_to_dict(obj: Any, *, use_alias: bool = True) -> Any:
and getattr(obj, field.name) is not None # type: ignore and getattr(obj, field.name) is not None # type: ignore
} }
if isinstance(obj, list | tuple | set): if isinstance(obj, list | tuple | set):
return sorted([_to_dict(item) for item in obj]) return [_to_dict(item) for item in obj]
if isinstance(obj, dict): if isinstance(obj, dict):
return {sanitize_string(k): _to_dict(v) for k, v in obj.items()} return {sanitize_string(k): _to_dict(v) for k, v in obj.items()}
if isinstance(obj, Path): if isinstance(obj, Path):

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" fill="currentColor"><path fill-rule="evenodd" d="M25.6 4h-4.1v8.2h4.1zm-8.2 12.3h12.3v4.1h4.1v8.2h-4.1v8.2H17.4v-8.2h-4.1v-8.2h4.1zm0 24.6h12.3V45H17.4zm28.7-18.45v4.1h-8.2v-4.1zm-36.9 4.1v-4.1H1v4.1zM33.8 12.2h4.1v4.1h-4.1zm4.1 0H42V8.1h-4.1zm-28.7 0h4.1v4.1H9.2zm0 0V8.1H5.1v4.1z" clip-rule="evenodd"/></svg>

After

Width:  |  Height:  |  Size: 373 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" fill="currentColor"><path fill-rule="evenodd" d="M42 6H5v37h37zm-20.555 8.222h4.111v12.334h-4.111zm0 16.445h4.111v4.11h-4.111z" clip-rule="evenodd"/></svg>

After

Width:  |  Height:  |  Size: 218 B

View File

@@ -16,6 +16,7 @@
"@tanstack/eslint-plugin-query": "^5.51.12", "@tanstack/eslint-plugin-query": "^5.51.12",
"@tanstack/solid-query": "^5.51.2", "@tanstack/solid-query": "^5.51.2",
"@types/json-schema": "^7.0.15", "@types/json-schema": "^7.0.15",
"corvu": "^0.7.1",
"material-icons": "^1.13.12", "material-icons": "^1.13.12",
"nanoid": "^5.0.7", "nanoid": "^5.0.7",
"solid-js": "^1.8.11", "solid-js": "^1.8.11",
@@ -406,6 +407,165 @@
"node": ">=6.9.0" "node": ">=6.9.0"
} }
}, },
"node_modules/@corvu/accordion": {
"version": "0.2.3",
"resolved": "https://registry.npmjs.org/@corvu/accordion/-/accordion-0.2.3.tgz",
"integrity": "sha512-M+qDysE1bKXeCmVsaHVs4FbrIWzQfffOrQ2H2yYYuGQfZINi5783rBcLTn7eNhUknOfdwVcjs2rnODeIomVC3A==",
"license": "MIT",
"dependencies": {
"@corvu/disclosure": "~0.2.0",
"@corvu/utils": "~0.4.0",
"solid-list": "~0.3.0"
},
"peerDependencies": {
"solid-js": "^1.8"
}
},
"node_modules/@corvu/dialog": {
"version": "0.2.3",
"resolved": "https://registry.npmjs.org/@corvu/dialog/-/dialog-0.2.3.tgz",
"integrity": "sha512-1p1lG2Pdu7CtDYw0FP+gdU0Db4zsB2ljOP7UxszZIQpvVvnrAYhNPfu/8IpscB38c0hZCodEnv5hR0NaEEA/Ag==",
"license": "MIT",
"dependencies": {
"@corvu/utils": "~0.4.0",
"solid-dismissible": "~0.1.0",
"solid-focus-trap": "~0.1.7",
"solid-presence": "~0.1.8",
"solid-prevent-scroll": "~0.1.9"
},
"peerDependencies": {
"solid-js": "^1.8"
}
},
"node_modules/@corvu/disclosure": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/@corvu/disclosure/-/disclosure-0.2.0.tgz",
"integrity": "sha512-+SkGXXcah8CiXQeM1qrYgikEEX6CFGZ8AOAEDHHkxFkQHC8ll0wAdGAkqT11quPvE9O6/f1ulfWNWdrX4Lqmnw==",
"license": "MIT",
"dependencies": {
"@corvu/utils": "~0.3.0",
"solid-presence": "~0.1.6"
},
"peerDependencies": {
"solid-js": "^1.8"
}
},
"node_modules/@corvu/disclosure/node_modules/@corvu/utils": {
"version": "0.3.2",
"resolved": "https://registry.npmjs.org/@corvu/utils/-/utils-0.3.2.tgz",
"integrity": "sha512-ZWlyWEE8qV9+CB9OAyo2bTrZGXQN9ZeM+JfYv89zoR+lRACKTDuoOZEdiyL8Uc7U5dUSH1uTqKhTTnaHWb+wZA==",
"license": "MIT",
"dependencies": {
"@floating-ui/dom": "^1.6.7"
},
"peerDependencies": {
"solid-js": "^1.8"
}
},
"node_modules/@corvu/drawer": {
"version": "0.2.2",
"resolved": "https://registry.npmjs.org/@corvu/drawer/-/drawer-0.2.2.tgz",
"integrity": "sha512-gj0dGnAc5fxoOe1E55uo8LPrHFxR+MaStn3UB8I1ZbtlJeeLDTK40uCc/Ee9xVxYpYNpUDX6ICGr3i23bsZyOA==",
"license": "MIT",
"dependencies": {
"@corvu/dialog": "~0.2.1",
"@corvu/utils": "~0.3.2",
"@solid-primitives/memo": "^1.3.8",
"solid-transition-size": "~0.1.4"
},
"peerDependencies": {
"solid-js": "^1.8"
}
},
"node_modules/@corvu/drawer/node_modules/@corvu/utils": {
"version": "0.3.2",
"resolved": "https://registry.npmjs.org/@corvu/utils/-/utils-0.3.2.tgz",
"integrity": "sha512-ZWlyWEE8qV9+CB9OAyo2bTrZGXQN9ZeM+JfYv89zoR+lRACKTDuoOZEdiyL8Uc7U5dUSH1uTqKhTTnaHWb+wZA==",
"license": "MIT",
"dependencies": {
"@floating-ui/dom": "^1.6.7"
},
"peerDependencies": {
"solid-js": "^1.8"
}
},
"node_modules/@corvu/otp-field": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/@corvu/otp-field/-/otp-field-0.1.4.tgz",
"integrity": "sha512-3eG7OoUt6CfVqGujIYfqImdrhGR/s4DpKr5ZQT10zzw3nawIlcwVpqoHTam0v4cgv+NXXvl6I8DoA3J+WgW2YA==",
"license": "MIT",
"dependencies": {
"@corvu/utils": "~0.4.2"
},
"peerDependencies": {
"solid-js": "^1.8"
}
},
"node_modules/@corvu/popover": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/@corvu/popover/-/popover-0.2.0.tgz",
"integrity": "sha512-zynRWyRV7mk2uX7t/COQL4OEa6H6FBgOxxlXLQJ1BV8hTiBJwmfAN/yB/9jy+zlp0G9vp64E8VdsNn6gxUEUEQ==",
"license": "MIT",
"dependencies": {
"@corvu/dialog": "~0.2.0",
"@corvu/utils": "~0.3.0",
"@floating-ui/dom": "^1.6.5"
},
"peerDependencies": {
"solid-js": "^1.8"
}
},
"node_modules/@corvu/popover/node_modules/@corvu/utils": {
"version": "0.3.2",
"resolved": "https://registry.npmjs.org/@corvu/utils/-/utils-0.3.2.tgz",
"integrity": "sha512-ZWlyWEE8qV9+CB9OAyo2bTrZGXQN9ZeM+JfYv89zoR+lRACKTDuoOZEdiyL8Uc7U5dUSH1uTqKhTTnaHWb+wZA==",
"license": "MIT",
"dependencies": {
"@floating-ui/dom": "^1.6.7"
},
"peerDependencies": {
"solid-js": "^1.8"
}
},
"node_modules/@corvu/resizable": {
"version": "0.2.3",
"resolved": "https://registry.npmjs.org/@corvu/resizable/-/resizable-0.2.3.tgz",
"integrity": "sha512-UwpObxqKlx1mc3G496Daz9NjK25Gx1V5fB8zIGazbq5tJs7aU8RjPW4png5OoNpMyxV7GQWjQtVc59zaAEVAJg==",
"license": "MIT",
"dependencies": {
"@corvu/utils": "~0.4.0"
},
"peerDependencies": {
"solid-js": "^1.8"
}
},
"node_modules/@corvu/tooltip": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/@corvu/tooltip/-/tooltip-0.2.1.tgz",
"integrity": "sha512-y2CQ2/6DH/gJJZPo1fV3O7l4Jfgu5ZW58bpqPmKS+l8Pa6gIKV6zkrMoyBg8Hsn6z9RmdZFqkGFs/9C5fvwKpg==",
"license": "MIT",
"dependencies": {
"@corvu/utils": "~0.4.0",
"@floating-ui/dom": "^1.6.8",
"solid-dismissible": "~0.1.0",
"solid-presence": "~0.1.8"
},
"peerDependencies": {
"solid-js": "^1.8"
}
},
"node_modules/@corvu/utils": {
"version": "0.4.2",
"resolved": "https://registry.npmjs.org/@corvu/utils/-/utils-0.4.2.tgz",
"integrity": "sha512-Ox2kYyxy7NoXdKWdHeDEjZxClwzO4SKM8plAaVwmAJPxHMqA0rLOoAsa+hBDwRLpctf+ZRnAd/ykguuJidnaTA==",
"license": "MIT",
"dependencies": {
"@floating-ui/dom": "^1.6.11"
},
"peerDependencies": {
"solid-js": "^1.8"
}
},
"node_modules/@esbuild/aix-ppc64": { "node_modules/@esbuild/aix-ppc64": {
"version": "0.20.2", "version": "0.20.2",
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.20.2.tgz", "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.20.2.tgz",
@@ -847,18 +1007,20 @@
} }
}, },
"node_modules/@floating-ui/dom": { "node_modules/@floating-ui/dom": {
"version": "1.6.8", "version": "1.6.12",
"resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.8.tgz", "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.12.tgz",
"integrity": "sha512-kx62rP19VZ767Q653wsP1XZCGIirkE09E0QUGNYTM/ttbbQHqcGPdSfWFxUyyNLc/W6aoJRBajOSXhP6GXjC0Q==", "integrity": "sha512-NP83c0HjokcGVEMeoStg317VD9W7eDlGK7457dMBANbKA6GJZdc7rjujdgqzTaz93jkGgc5P/jeWbaCHnMNc+w==",
"license": "MIT",
"dependencies": { "dependencies": {
"@floating-ui/core": "^1.6.0", "@floating-ui/core": "^1.6.0",
"@floating-ui/utils": "^0.2.5" "@floating-ui/utils": "^0.2.8"
} }
}, },
"node_modules/@floating-ui/utils": { "node_modules/@floating-ui/utils": {
"version": "0.2.5", "version": "0.2.8",
"resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.5.tgz", "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.8.tgz",
"integrity": "sha512-sTcG+QZ6fdEUObICavU+aB3Mp8HY4n14wYHdxK4fXjPmv3PXZZeY5RaguJmGyeH/CJQhX3fqKUtS4qc1LoHwhQ==" "integrity": "sha512-kym7SodPp8/wloecOpcmSnWJsK7M0E5Wg8UcFA+uO4B9s5d0ywXOEro/8HM9x0rW+TljRzul/14UYz3TleT3ig==",
"license": "MIT"
}, },
"node_modules/@humanwhocodes/config-array": { "node_modules/@humanwhocodes/config-array": {
"version": "0.11.14", "version": "0.11.14",
@@ -1379,6 +1541,19 @@
"solid-js": "^1.6.12" "solid-js": "^1.6.12"
} }
}, },
"node_modules/@solid-primitives/memo": {
"version": "1.3.10",
"resolved": "https://registry.npmjs.org/@solid-primitives/memo/-/memo-1.3.10.tgz",
"integrity": "sha512-S4cNjjKINVC4KiY3ovP1oagbTVQI77VvSRMNsInFIi7T4hM/N5InJk5k+W0zD4lt+SUYrWF04BMbZyMy17vfUw==",
"license": "MIT",
"dependencies": {
"@solid-primitives/scheduled": "^1.4.4",
"@solid-primitives/utils": "^6.2.3"
},
"peerDependencies": {
"solid-js": "^1.6.12"
}
},
"node_modules/@solid-primitives/platform": { "node_modules/@solid-primitives/platform": {
"version": "0.1.2", "version": "0.1.2",
"resolved": "https://registry.npmjs.org/@solid-primitives/platform/-/platform-0.1.2.tgz", "resolved": "https://registry.npmjs.org/@solid-primitives/platform/-/platform-0.1.2.tgz",
@@ -1440,10 +1615,10 @@
} }
}, },
"node_modules/@solid-primitives/scheduled": { "node_modules/@solid-primitives/scheduled": {
"version": "1.4.3", "version": "1.4.4",
"resolved": "https://registry.npmjs.org/@solid-primitives/scheduled/-/scheduled-1.4.3.tgz", "resolved": "https://registry.npmjs.org/@solid-primitives/scheduled/-/scheduled-1.4.4.tgz",
"integrity": "sha512-HfWN5w7b7FEc6VPLBKnnE302h90jsLMuR28Fcf7neRGGf8jBj6wm6/UFQ00VlKexHFMR6KQ2u4VBh5a1ZcqM8g==", "integrity": "sha512-BTGdFP7t+s7RSak+s1u0eTix4lHP23MrbGkgQTFlt1E+4fmnD/bEx3ZfNW7Grylz3GXgKyXrgDKA7jQ/wuWKgA==",
"dev": true, "license": "MIT",
"peerDependencies": { "peerDependencies": {
"solid-js": "^1.6.12" "solid-js": "^1.6.12"
} }
@@ -2614,6 +2789,25 @@
"optional": true, "optional": true,
"peer": true "peer": true
}, },
"node_modules/corvu": {
"version": "0.7.1",
"resolved": "https://registry.npmjs.org/corvu/-/corvu-0.7.1.tgz",
"integrity": "sha512-MmiSyTM75+Co6KtvkocZ+qy2HJrDwkjJPL0zt06klvkHkKkGZBKYhmzzpEeni/7b7woR6/3XSDGsn3ljGP/O4w==",
"license": "MIT",
"dependencies": {
"@corvu/accordion": "~0.2.0",
"@corvu/dialog": "~0.2.0",
"@corvu/disclosure": "~0.2.0",
"@corvu/drawer": "~0.2.1",
"@corvu/otp-field": "~0.1.0",
"@corvu/popover": "~0.2.0",
"@corvu/resizable": "~0.2.1",
"@corvu/tooltip": "~0.2.0"
},
"peerDependencies": {
"solid-js": "^1.8"
}
},
"node_modules/cross-spawn": { "node_modules/cross-spawn": {
"version": "7.0.3", "version": "7.0.3",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
@@ -6312,6 +6506,42 @@
} }
} }
}, },
"node_modules/solid-dismissible": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/solid-dismissible/-/solid-dismissible-0.1.1.tgz",
"integrity": "sha512-9kcKBJIMdS+586cA1g63HYWxKh3h89leeNHbPZ1csYjuni+NvPBtNr11l0iEX2AKKEt6FHk6qNhc/gjoYAW1pA==",
"license": "MIT",
"dependencies": {
"@corvu/utils": "~0.4.1"
},
"peerDependencies": {
"solid-js": "^1.8"
}
},
"node_modules/solid-focus-trap": {
"version": "0.1.7",
"resolved": "https://registry.npmjs.org/solid-focus-trap/-/solid-focus-trap-0.1.7.tgz",
"integrity": "sha512-NSJiIkL+WTWGgca+OKQA9rV3bD51lT23iLn1Z+Ap1Qk3rJBxQ8SoEAQ0FvXoQThtyXFKAK1ibcVBBMMEcu6YMw==",
"license": "MIT",
"dependencies": {
"@corvu/utils": "~0.3.1"
},
"peerDependencies": {
"solid-js": "^1.8"
}
},
"node_modules/solid-focus-trap/node_modules/@corvu/utils": {
"version": "0.3.2",
"resolved": "https://registry.npmjs.org/@corvu/utils/-/utils-0.3.2.tgz",
"integrity": "sha512-ZWlyWEE8qV9+CB9OAyo2bTrZGXQN9ZeM+JfYv89zoR+lRACKTDuoOZEdiyL8Uc7U5dUSH1uTqKhTTnaHWb+wZA==",
"license": "MIT",
"dependencies": {
"@floating-ui/dom": "^1.6.7"
},
"peerDependencies": {
"solid-js": "^1.8"
}
},
"node_modules/solid-js": { "node_modules/solid-js": {
"version": "1.8.17", "version": "1.8.17",
"resolved": "https://registry.npmjs.org/solid-js/-/solid-js-1.8.17.tgz", "resolved": "https://registry.npmjs.org/solid-js/-/solid-js-1.8.17.tgz",
@@ -6322,6 +6552,18 @@
"seroval-plugins": "^1.0.3" "seroval-plugins": "^1.0.3"
} }
}, },
"node_modules/solid-list": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/solid-list/-/solid-list-0.3.0.tgz",
"integrity": "sha512-t4hx/F/l8Vmq+ib9HtZYl7Z9F1eKxq3eKJTXlvcm7P7yI4Z8O7QSOOEVHb/K6DD7M0RxzVRobK/BS5aSfLRwKg==",
"license": "MIT",
"dependencies": {
"@corvu/utils": "~0.4.0"
},
"peerDependencies": {
"solid-js": "^1.8"
}
},
"node_modules/solid-markdown": { "node_modules/solid-markdown": {
"version": "2.0.13", "version": "2.0.13",
"resolved": "https://registry.npmjs.org/solid-markdown/-/solid-markdown-2.0.13.tgz", "resolved": "https://registry.npmjs.org/solid-markdown/-/solid-markdown-2.0.13.tgz",
@@ -6347,6 +6589,30 @@
"solid-js": "^1.6.0" "solid-js": "^1.6.0"
} }
}, },
"node_modules/solid-presence": {
"version": "0.1.8",
"resolved": "https://registry.npmjs.org/solid-presence/-/solid-presence-0.1.8.tgz",
"integrity": "sha512-pWGtXUFWYYUZNbg5YpG5vkQJyOtzn2KXhxYaMx/4I+lylTLYkITOLevaCwMRN+liCVk0pqB6EayLWojNqBFECA==",
"license": "MIT",
"dependencies": {
"@corvu/utils": "~0.4.0"
},
"peerDependencies": {
"solid-js": "^1.8"
}
},
"node_modules/solid-prevent-scroll": {
"version": "0.1.10",
"resolved": "https://registry.npmjs.org/solid-prevent-scroll/-/solid-prevent-scroll-0.1.10.tgz",
"integrity": "sha512-KplGPX2GHiWJLZ6AXYRql4M127PdYzfwvLJJXMkO+CMb8Np4VxqDAg5S8jLdwlEuBis/ia9DKw2M8dFx5u8Mhw==",
"license": "MIT",
"dependencies": {
"@corvu/utils": "~0.4.1"
},
"peerDependencies": {
"solid-js": "^1.8"
}
},
"node_modules/solid-refresh": { "node_modules/solid-refresh": {
"version": "0.6.3", "version": "0.6.3",
"resolved": "https://registry.npmjs.org/solid-refresh/-/solid-refresh-0.6.3.tgz", "resolved": "https://registry.npmjs.org/solid-refresh/-/solid-refresh-0.6.3.tgz",
@@ -6369,6 +6635,30 @@
"solid-js": "^1.5.4" "solid-js": "^1.5.4"
} }
}, },
"node_modules/solid-transition-size": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/solid-transition-size/-/solid-transition-size-0.1.4.tgz",
"integrity": "sha512-ocHVnbfy23CgfaH4cEUR/AFg0Y3CEL8Oh3n9Qv8OHFJgPh+zkmERKZQfi/xH5XvxDCizg8VjPrVUhiHB1Gza8g==",
"license": "MIT",
"dependencies": {
"@corvu/utils": "~0.3.2"
},
"peerDependencies": {
"solid-js": "^1.8"
}
},
"node_modules/solid-transition-size/node_modules/@corvu/utils": {
"version": "0.3.2",
"resolved": "https://registry.npmjs.org/@corvu/utils/-/utils-0.3.2.tgz",
"integrity": "sha512-ZWlyWEE8qV9+CB9OAyo2bTrZGXQN9ZeM+JfYv89zoR+lRACKTDuoOZEdiyL8Uc7U5dUSH1uTqKhTTnaHWb+wZA==",
"license": "MIT",
"dependencies": {
"@floating-ui/dom": "^1.6.7"
},
"peerDependencies": {
"solid-js": "^1.8"
}
},
"node_modules/source-map": { "node_modules/source-map": {
"version": "0.6.1", "version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",

View File

@@ -43,6 +43,7 @@
"@tanstack/eslint-plugin-query": "^5.51.12", "@tanstack/eslint-plugin-query": "^5.51.12",
"@tanstack/solid-query": "^5.51.2", "@tanstack/solid-query": "^5.51.2",
"@types/json-schema": "^7.0.15", "@types/json-schema": "^7.0.15",
"corvu": "^0.7.1",
"material-icons": "^1.13.12", "material-icons": "^1.13.12",
"nanoid": "^5.0.7", "nanoid": "^5.0.7",
"solid-js": "^1.8.11", "solid-js": "^1.8.11",

View File

@@ -10,6 +10,7 @@ import CaretRight from "@/icons/caret-right.svg";
import Checkmark from "@/icons/checkmark.svg"; import Checkmark from "@/icons/checkmark.svg";
import ClanIcon from "@/icons/clan-icon.svg"; import ClanIcon from "@/icons/clan-icon.svg";
import ClanLogo from "@/icons/clan-logo.svg"; import ClanLogo from "@/icons/clan-logo.svg";
import Close from "@/icons/close.svg";
import Download from "@/icons/download.svg"; import Download from "@/icons/download.svg";
import Edit from "@/icons/edit.svg"; import Edit from "@/icons/edit.svg";
import Expand from "@/icons/expand.svg"; import Expand from "@/icons/expand.svg";
@@ -44,6 +45,7 @@ const icons = {
Checkmark, Checkmark,
ClanIcon, ClanIcon,
ClanLogo, ClanLogo,
Close,
Download, Download,
Edit, Edit,
Expand, Expand,

View File

@@ -0,0 +1,119 @@
import Dialog from "corvu/dialog";
import { createEffect, createSignal, JSX } from "solid-js";
import { Button } from "../button";
import Icon from "../icon";
import cx from "classnames";
interface ModalProps {
open: boolean | undefined;
handleClose: () => void;
title: string;
children: JSX.Element;
}
export const Modal = (props: ModalProps) => {
const [dragging, setDragging] = createSignal(false);
const [startOffset, setStartOffset] = createSignal({ x: 0, y: 0 });
// const [dialogStyle, setDialogStyle] = createSignal({ top: 100, left: 100 });
let dialogRef: HTMLDivElement;
const handleMouseDown = (e: MouseEvent) => {
setDragging(true);
const rect = dialogRef.getBoundingClientRect();
setStartOffset({
x: e.clientX - rect.left,
y: e.clientY - rect.top,
});
};
const handleMouseMove = (e: MouseEvent) => {
if (dragging()) {
const newTop = e.clientY - startOffset().y;
const newLeft = e.clientX - startOffset().x;
dialogRef.style.top = `${newTop}px`;
dialogRef.style.left = `${newLeft}px`;
}
};
const handleMouseUp = () => setDragging(false);
createEffect(() => {
console.log("dialog open", props.open);
});
return (
<Dialog open={props.open} trapFocus={true}>
<Dialog.Portal>
<Dialog.Overlay
class="fixed inset-0 z-50 bg-black/50"
onMouseMove={handleMouseMove}
/>
<Dialog.Content
class="absolute left-1/3 top-1/3 z-50 min-w-[320px] rounded-md border border-def-4 focus-visible:outline-none"
classList={{
"!cursor-grabbing": dragging(),
[cx("scale-105 transition-transform")]: dragging(),
}}
ref={(el) => {
dialogRef = el;
}}
onMouseMove={handleMouseMove}
onMouseUp={handleMouseUp}
onMouseDown={(e: MouseEvent) => {
e.stopPropagation(); // Prevent backdrop drag conflict
}}
onClick={(e: MouseEvent) => e.stopPropagation()} // Prevent backdrop click closing
>
<Dialog.Label
as="div"
class="flex w-full justify-center rounded-t-md border-b-2 px-4 py-2 align-middle bg-def-3 border-def-5"
onMouseDown={handleMouseDown}
>
<div
class="flex w-full cursor-move flex-col gap-px py-1 "
classList={{
"!cursor-grabbing": dragging(),
}}
>
<hr class="h-px w-full border-none bg-secondary-300" />
<hr class="h-px w-full border-none bg-secondary-300" />
<hr class="h-px w-full border-none bg-secondary-300" />
<hr class="h-px w-full border-none bg-secondary-300" />
<hr class="h-px w-full border-none bg-secondary-300" />
<hr class="h-px w-full border-none bg-secondary-300" />
</div>
<span class="mx-2"> {props.title}</span>
<div
class="flex w-full cursor-move flex-col gap-px py-1 "
classList={{
"!cursor-grabbing": dragging(),
}}
>
<hr class="h-px w-full border-none bg-secondary-300" />
<hr class="h-px w-full border-none bg-secondary-300" />
<hr class="h-px w-full border-none bg-secondary-300" />
<hr class="h-px w-full border-none bg-secondary-300" />
<hr class="h-px w-full border-none bg-secondary-300" />
<hr class="h-px w-full border-none bg-secondary-300" />
</div>
<div class="absolute right-1 top-2 pl-1 bg-def-3">
<Button
onMouseDown={(e) => e.stopPropagation()}
tabIndex={-1}
class="size-4"
variant="ghost"
onClick={() => props.handleClose()}
size="s"
startIcon={<Icon icon={"Close"} />}
/>
</div>
</Dialog.Label>
<Dialog.Description class="flex flex-col bg-def-1" as="div">
{props.children}
</Dialog.Description>
</Dialog.Content>
</Dialog.Portal>
</Dialog>
);
};

View File

@@ -20,6 +20,7 @@ import { createEffect, createSignal, For, Show } from "solid-js";
import toast from "solid-toast"; import toast from "solid-toast";
import { FieldLayout } from "@/src/Form/fields/layout"; import { FieldLayout } from "@/src/Form/fields/layout";
import { InputLabel } from "@/src/components/inputBase"; import { InputLabel } from "@/src/components/inputBase";
import { Modal } from "@/src/components/modal";
interface Wifi extends FieldValues { interface Wifi extends FieldValues {
ssid: string; ssid: string;
@@ -144,11 +145,15 @@ export const Flash = () => {
} }
return dataTransfer.files; return dataTransfer.files;
}; };
const [confirmOpen, setConfirmOpen] = createSignal(false);
const handleSubmit = async (values: FlashFormValues) => { const handleConfirm = async (values: FlashFormValues) => {
setConfirmOpen(true);
console.log("Submit:", values); console.log("Submit:", values);
toast.error("Not fully implemented yet"); toast.error("Not fully implemented yet");
// Disabled for now. To prevent accidental flashing of local disks // Disabled for now. To prevent accidental flashing of local disks
// User should confirm the disk to flash to
// try { // try {
// await callApi("flash_machine", { // await callApi("flash_machine", {
// machine: { // machine: {
@@ -177,6 +182,30 @@ export const Flash = () => {
return ( return (
<> <>
<Header title="Flash installer" /> <Header title="Flash installer" />
<Modal
open={confirmOpen()}
handleClose={() => setConfirmOpen(false)}
title="Confirm"
>
<div class="flex flex-col gap-4 p-4">
<div class="flex justify-between rounded-sm border p-4 align-middle text-red-900 border-def-2">
<Typography
hierarchy="label"
weight="medium"
size="default"
class="flex-wrap break-words pr-4"
>
Warning: All data on will be lost.
<br />
Selected disk: '{getValue(formStore, "disk")}'
</Typography>
</div>
<div class="flex w-full justify-between">
<Button variant="light">Cancel</Button>
<Button>Confirm</Button>
</div>
</div>
</Modal>
<div class="p-4"> <div class="p-4">
<Typography tag="p" hierarchy="body" size="default" color="primary"> <Typography tag="p" hierarchy="body" size="default" color="primary">
USB Utility image. USB Utility image.
@@ -185,7 +214,7 @@ export const Flash = () => {
Will make bootstrapping new machines easier by providing secure remote Will make bootstrapping new machines easier by providing secure remote
connection to any machine when plugged in. connection to any machine when plugged in.
</Typography> </Typography>
<Form onSubmit={handleSubmit}> <Form onSubmit={handleConfirm}>
<div class="my-4"> <div class="my-4">
<Field name="sshKeys" type="File[]"> <Field name="sshKeys" type="File[]">
{(field, props) => ( {(field, props) => (
@@ -242,7 +271,7 @@ export const Flash = () => {
value={field.value || ""} value={field.value || ""}
error={field.error} error={field.error}
required required
placeholder="Select a thing where the installer will be flashed to" placeholder="Select a drive where the clan-installer will be flashed to"
options={ options={
deviceQuery.data?.blockdevices.map((d) => ({ deviceQuery.data?.blockdevices.map((d) => ({
value: d.path, value: d.path,
@@ -285,7 +314,7 @@ export const Flash = () => {
label="SSID" label="SSID"
value={field.value ?? ""} value={field.value ?? ""}
error={field.error} error={field.error}
class="col-span-3" class="col-span-full "
required required
/> />
)} )}
@@ -295,40 +324,39 @@ export const Flash = () => {
validate={[required("Password is required")]} validate={[required("Password is required")]}
> >
{(field, props) => ( {(field, props) => (
<div class="relative col-span-3 w-full"> <TextInput
<TextInput class="col-span-full"
inputProps={{ inputProps={{
...props, ...props,
type: passwordVisibility()[index()] type: passwordVisibility()[index()]
? "text" ? "text"
: "password", : "password",
}} }}
label="Password" label="Password"
value={field.value ?? ""} value={field.value ?? ""}
error={field.error} error={field.error}
// adornment={{ // adornment={{
// position: "end", // position: "end",
// content: ( // content: (
// <Button // <Button
// variant="light" // variant="light"
// type="button" // type="button"
// class="flex justify-center opacity-70" // class="flex justify-center opacity-70"
// onClick={() => // onClick={() =>
// togglePasswordVisibility(index()) // togglePasswordVisibility(index())
// } // }
// startIcon={ // startIcon={
// passwordVisibility()[index()] ? ( // passwordVisibility()[index()] ? (
// <Icon icon="EyeClose" /> // <Icon icon="EyeClose" />
// ) : ( // ) : (
// <Icon icon="EyeOpen" /> // <Icon icon="EyeOpen" />
// ) // )
// } // }
// ></Button> // ></Button>
// ), // ),
// }} // }}
required required
/> />
</div>
)} )}
</Field> </Field>
</div> </div>