Merge pull request 'clan-app: Remove unused files and exports from ui-2d' (#4027) from Qubasa/clan-core:ui_minimize into main

Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4027
This commit is contained in:
Luis Hebendanz
2025-06-18 20:36:04 +00:00
28 changed files with 42 additions and 208 deletions

View File

@@ -4,6 +4,7 @@
"stylelint.config.js", "stylelint.config.js",
"util.ts", "util.ts",
"src/components/v2/**", "src/components/v2/**",
"api/**" "api/**",
"tailwind/**"
] ]
} }

View File

@@ -17,37 +17,30 @@
"storybook-dev": "storybook dev -p 6006", "storybook-dev": "storybook dev -p 6006",
"test-storybook": "vitest run --project storybook", "test-storybook": "vitest run --project storybook",
"test-storybook-update-snapshots": "vitest run --project storybook --update", "test-storybook-update-snapshots": "vitest run --project storybook --update",
"test-storybook-static": "npm run storybook-build && concurrently -k -s first -n 'SB,TEST' -c 'magenta,blue' 'http-server storybook-static --port 6006 --silent' 'wait-on tcp:127.0.0.1:6006 && npm run test-storybook'" "test-storybook-static": "npm run storybook-build && concurrently -k -s first -n 'SB,TEST' -c 'magenta,blue' 'npx http-server storybook-static --port 6006 --silent' 'npx wait-on tcp:127.0.0.1:6006 && npm run test-storybook'"
}, },
"license": "MIT", "license": "MIT",
"devDependencies": { "devDependencies": {
"@babel/plugin-syntax-import-attributes": "^7.27.1",
"@eslint/js": "^9.3.0", "@eslint/js": "^9.3.0",
"@kachurun/storybook-solid": "^9.0.11",
"@kachurun/storybook-solid-vite": "^9.0.11", "@kachurun/storybook-solid-vite": "^9.0.11",
"@storybook/addon-a11y": "^9.0.8", "@storybook/addon-a11y": "^9.0.8",
"@storybook/addon-docs": "^9.0.8", "@storybook/addon-docs": "^9.0.8",
"@storybook/addon-links": "^9.0.8", "@storybook/addon-links": "^9.0.8",
"@storybook/addon-onboarding": "^9.0.8", "@storybook/addon-onboarding": "^9.0.8",
"@storybook/addon-viewport": "^9.0.8",
"@storybook/addon-vitest": "^9.0.8", "@storybook/addon-vitest": "^9.0.8",
"@tailwindcss/typography": "^0.5.13", "@tailwindcss/typography": "^0.5.13",
"@types/json-schema": "^7.0.15", "@types/json-schema": "^7.0.15",
"@types/node": "^22.15.19", "@types/node": "^22.15.19",
"@types/three": "^0.177.0",
"@typescript-eslint/parser": "^8.32.1",
"@vitest/browser": "^3.2.3", "@vitest/browser": "^3.2.3",
"@vitest/coverage-v8": "^3.2.3",
"autoprefixer": "^10.4.19", "autoprefixer": "^10.4.19",
"classnames": "^2.5.1", "classnames": "^2.5.1",
"concurrently": "^9.1.2", "concurrently": "^9.1.2",
"eslint": "^9.27.0", "eslint": "^9.27.0",
"eslint-plugin-tailwindcss": "^3.17.0", "eslint-plugin-tailwindcss": "^3.17.0",
"http-server": "^14.1.1",
"jsdom": "^26.1.0", "jsdom": "^26.1.0",
"knip": "^5.61.2", "knip": "^5.61.2",
"playwright": "~1.53.0",
"postcss": "^8.4.38", "postcss": "^8.4.38",
"postcss-url": "^10.1.3",
"prettier": "^3.2.5", "prettier": "^3.2.5",
"solid-devtools": "^0.34.0", "solid-devtools": "^0.34.0",
"storybook": "^9.0.8", "storybook": "^9.0.8",
@@ -57,8 +50,7 @@
"vite": "^6.3.5", "vite": "^6.3.5",
"vite-plugin-solid": "^2.8.2", "vite-plugin-solid": "^2.8.2",
"vite-plugin-solid-svg": "^0.8.1", "vite-plugin-solid-svg": "^0.8.1",
"vitest": "^3.2.3", "vitest": "^3.2.3"
"wait-on": "^8.0.3"
}, },
"dependencies": { "dependencies": {
"@floating-ui/dom": "^1.6.8", "@floating-ui/dom": "^1.6.8",
@@ -70,12 +62,9 @@
"@tanstack/eslint-plugin-query": "^5.51.12", "@tanstack/eslint-plugin-query": "^5.51.12",
"@tanstack/solid-query": "^5.76.0", "@tanstack/solid-query": "^5.76.0",
"corvu": "^0.7.1", "corvu": "^0.7.1",
"material-icons": "^1.13.12",
"nanoid": "^5.0.7", "nanoid": "^5.0.7",
"solid-js": "^1.9.7", "solid-js": "^1.9.7",
"solid-markdown": "^2.0.13", "solid-toast": "^0.5.0"
"solid-toast": "^0.5.0",
"three": "^0.177.0"
}, },
"optionalDependencies": { "optionalDependencies": {
"@esbuild/darwin-arm64": "^0.25.4", "@esbuild/darwin-arm64": "^0.25.4",

View File

@@ -6,10 +6,8 @@ import type {
} from "@floating-ui/dom"; } from "@floating-ui/dom";
import { computePosition } from "@floating-ui/dom"; import { computePosition } from "@floating-ui/dom";
export interface UseFloatingOptions< interface UseFloatingOptions<R extends ReferenceElement, F extends HTMLElement>
R extends ReferenceElement, extends Partial<ComputePositionConfig> {
F extends HTMLElement,
> extends Partial<ComputePositionConfig> {
whileElementsMounted?: ( whileElementsMounted?: (
reference: R, reference: R,
floating: F, floating: F,
@@ -23,7 +21,7 @@ interface UseFloatingState extends Omit<ComputePositionReturn, "x" | "y"> {
y?: number | null; y?: number | null;
} }
export interface UseFloatingResult extends UseFloatingState { interface UseFloatingResult extends UseFloatingState {
update(): void; update(): void;
} }

View File

@@ -3,6 +3,6 @@ import { JSX } from "solid-js";
interface FormSectionProps { interface FormSectionProps {
children: JSX.Element; children: JSX.Element;
} }
export const FormSection = (props: FormSectionProps) => { const FormSection = (props: FormSectionProps) => {
return <div class="p-2">{props.children}</div>; return <div class="p-2">{props.children}</div>;
}; };

View File

@@ -21,7 +21,7 @@ import { FieldLayout } from "./layout";
import Icon from "@/src/components/icon"; import Icon from "@/src/components/icon";
import { useContext } from "corvu/dialog"; import { useContext } from "corvu/dialog";
export interface Option { interface Option {
value: string; value: string;
label: string; label: string;
disabled?: boolean; disabled?: boolean;

View File

@@ -139,7 +139,7 @@ interface SchemaFieldsProps<T extends FieldValues, R extends ResponseData> {
readonly: boolean; readonly: boolean;
parent: JSONSchema7; parent: JSONSchema7;
} }
export function SchemaFields<T extends FieldValues, R extends ResponseData>( function SchemaFields<T extends FieldValues, R extends ResponseData>(
props: SchemaFieldsProps<T, R>, props: SchemaFieldsProps<T, R>,
) { ) {
return ( return (
@@ -172,7 +172,7 @@ export function SchemaFields<T extends FieldValues, R extends ResponseData>(
); );
} }
export function StringField<T extends FieldValues, R extends ResponseData>( function StringField<T extends FieldValues, R extends ResponseData>(
props: SchemaFieldsProps<T, R>, props: SchemaFieldsProps<T, R>,
) { ) {
if ( if (
@@ -325,7 +325,7 @@ export function StringField<T extends FieldValues, R extends ResponseData>(
interface OptionSchemaProps { interface OptionSchemaProps {
itemSpec: JSONSchema7Type; itemSpec: JSONSchema7Type;
} }
export function OptionSchema(props: OptionSchemaProps) { function OptionSchema(props: OptionSchemaProps) {
return ( return (
<Switch <Switch
fallback={<option class="text-error-700">Item spec unhandled</option>} fallback={<option class="text-error-700">Item spec unhandled</option>}
@@ -344,7 +344,7 @@ interface ValueDisplayProps<T extends FieldValues, R extends ResponseData>
idx: number; idx: number;
of: number; of: number;
} }
export function ListValueDisplay<T extends FieldValues, R extends ResponseData>( function ListValueDisplay<T extends FieldValues, R extends ResponseData>(
props: ValueDisplayProps<T, R>, props: ValueDisplayProps<T, R>,
) { ) {
const removeItem = (e: Event) => { const removeItem = (e: Event) => {
@@ -446,7 +446,7 @@ const OnlyStringItems = (props: OnlyStringItems) => {
); );
}; };
export function ArrayFields<T extends FieldValues, R extends ResponseData>( function ArrayFields<T extends FieldValues, R extends ResponseData>(
props: SchemaFieldsProps<T, R>, props: SchemaFieldsProps<T, R>,
) { ) {
if (props.schema.type !== "array") { if (props.schema.type !== "array") {
@@ -711,7 +711,7 @@ interface ObjectFieldPropertyLabelProps {
schema: JSONSchema7; schema: JSONSchema7;
fallback: JSX.Element; fallback: JSX.Element;
} }
export function ObjectFieldPropertyLabel(props: ObjectFieldPropertyLabelProps) { function ObjectFieldPropertyLabel(props: ObjectFieldPropertyLabelProps) {
return ( return (
<Switch fallback={props.fallback}> <Switch fallback={props.fallback}>
{/* @ts-expect-error: $exportedModuleInfo should exist since we export it */} {/* @ts-expect-error: $exportedModuleInfo should exist since we export it */}
@@ -722,7 +722,7 @@ export function ObjectFieldPropertyLabel(props: ObjectFieldPropertyLabelProps) {
); );
} }
export function ObjectFields<T extends FieldValues, R extends ResponseData>( function ObjectFields<T extends FieldValues, R extends ResponseData>(
props: SchemaFieldsProps<T, R>, props: SchemaFieldsProps<T, R>,
) { ) {
if (props.schema.type !== "object") { if (props.schema.type !== "object") {

View File

@@ -7,21 +7,14 @@ import {
ErrorToastComponent, ErrorToastComponent,
CancelToastComponent, CancelToastComponent,
} from "@/src/components/toast"; } from "@/src/components/toast";
export type OperationNames = keyof API;
type OperationNames = keyof API;
type Services = NonNullable<Inventory["services"]>;
type ServiceNames = keyof Services;
export type OperationArgs<T extends OperationNames> = API[T]["arguments"]; export type OperationArgs<T extends OperationNames> = API[T]["arguments"];
export type OperationResponse<T extends OperationNames> = API[T]["return"]; export type OperationResponse<T extends OperationNames> = API[T]["return"];
export type ApiEnvelope<T> =
| {
status: "success";
data: T;
op_key: string;
}
| ApiError;
export type Services = NonNullable<Inventory["services"]>;
export type ServiceNames = keyof Services;
export type ClanService<T extends ServiceNames> = Services[T];
export type ClanServiceInstance<T extends ServiceNames> = NonNullable< export type ClanServiceInstance<T extends ServiceNames> = NonNullable<
Services[T] Services[T]
>[string]; >[string];
@@ -32,18 +25,6 @@ export type SuccessQuery<T extends OperationNames> = Extract<
>; >;
export type SuccessData<T extends OperationNames> = SuccessQuery<T>["data"]; export type SuccessData<T extends OperationNames> = SuccessQuery<T>["data"];
export type ErrorQuery<T extends OperationNames> = Extract<
OperationResponse<T>,
{ status: "error" }
>;
export type ErrorData<T extends OperationNames> = ErrorQuery<T>["errors"];
export type ClanOperations = Record<OperationNames, (str: string) => void>;
export interface GtkResponse<T> {
result: T;
op_key: string;
}
const _callApi = <K extends OperationNames>( const _callApi = <K extends OperationNames>(
method: K, method: K,
args: OperationArgs<K>, args: OperationArgs<K>,

View File

@@ -1,20 +0,0 @@
import { callApi } from ".";
import { Schema as Inventory } from "@/api/Inventory";
export const instance_name = (machine_name: string) =>
`${machine_name}_wifi_0` as const;
export async function get_iwd_service(base_path: string, machine_name: string) {
const r = await callApi("get_inventory", {
flake: { identifier: base_path },
}).promise;
if (r.status == "error") {
return null;
}
// @FIXME: Clean this up once we implement the feature
// @ts-expect-error: This doesn't check currently
const inventory: Inventory = r.data;
const instance_key = instance_name(machine_name);
return inventory.services?.iwd?.[instance_key] || null;
}

View File

@@ -42,8 +42,7 @@ const sizeFont: Record<Size, string> = {
s: cx("text-[0.75rem]"), s: cx("text-[0.75rem]"),
}; };
export interface ButtonProps interface ButtonProps extends JSX.ButtonHTMLAttributes<HTMLButtonElement> {
extends JSX.ButtonHTMLAttributes<HTMLButtonElement> {
variant?: Variants; variant?: Variants;
size?: Size; size?: Size;
children?: JSX.Element; children?: JSX.Element;

View File

@@ -1,54 +0,0 @@
import { FieldValues, FormStore, ResponseData } from "@modular-forms/solid";
import { Show } from "solid-js";
import { type JSX } from "solid-js";
import cx from "classnames";
interface SelectInputProps<T extends FieldValues, R extends ResponseData> {
formStore: FormStore<T, R>;
value: string;
options: JSX.Element;
selectProps: JSX.HTMLAttributes<HTMLSelectElement>;
label: JSX.Element;
error?: string;
required?: boolean;
topRightLabel?: JSX.Element;
class?: string;
}
export function SelectInput<T extends FieldValues, R extends ResponseData>(
props: SelectInputProps<T, R>,
) {
return (
<label
class={cx(" w-full", props.class)}
aria-disabled={props.formStore.submitting}
>
<div class="">
<span
class=" block"
classList={{
"after:ml-0.5 after:text-primary after:content-['*']":
props.required,
}}
>
{props.label}
</span>
<Show when={props.topRightLabel}>
<span class="">{props.topRightLabel}</span>
</Show>
</div>
<select
{...props.selectProps}
required={props.required}
class="w-full"
value={props.value}
>
{props.options}
</select>
{props.error && (
<span class=" font-bold text-error-700">{props.error}</span>
)}
</label>
);
}

View File

@@ -8,7 +8,7 @@ import "./css/sidebar.css";
import Icon, { IconVariant } from "../icon"; import Icon, { IconVariant } from "../icon";
import { clanMetaQuery } from "@/src/queries/clan-meta"; import { clanMetaQuery } from "@/src/queries/clan-meta";
export const SidebarSection = (props: { const SidebarSection = (props: {
title: string; title: string;
icon: IconVariant; icon: IconVariant;
children: JSX.Element; children: JSX.Element;

View File

@@ -2,7 +2,7 @@ import { Component, For } from "solid-js";
import { Typography } from "@/src/components/Typography"; import { Typography } from "@/src/components/Typography";
import "./TagList.css"; import "./TagList.css";
export interface TagListProps { interface TagListProps {
values: string[]; values: string[];
} }

View File

@@ -3,7 +3,7 @@ import { Dynamic } from "solid-js/web";
import cx from "classnames"; import cx from "classnames";
import "./css/typography.css"; import "./css/typography.css";
export type Hierarchy = "body" | "title" | "headline" | "label"; type Hierarchy = "body" | "title" | "headline" | "label";
type Color = "primary" | "secondary" | "tertiary"; type Color = "primary" | "secondary" | "tertiary";
type Weight = "normal" | "medium" | "bold"; type Weight = "normal" | "medium" | "bold";
type Tag = "span" | "p" | "h1" | "h2" | "h3" | "h4" | "div"; type Tag = "span" | "p" | "h1" | "h2" | "h3" | "h4" | "div";

View File

@@ -12,7 +12,7 @@ export const Group = (props: GroupProps) => (
</div> </div>
); );
export type SectionVariant = "attention" | "danger"; type SectionVariant = "attention" | "danger";
interface SectionHeaderProps { interface SectionHeaderProps {
variant: SectionVariant; variant: SectionVariant;

View File

@@ -108,7 +108,7 @@ export const RndThumbnail = (props: RndThumbnailProps) => {
return <img src={imageSrc()} alt={props.name} />; return <img src={imageSrc()} alt={props.name} />;
}; };
export const RndThumbnailShow = () => { const RndThumbnailShow = () => {
const names = ["hsjobeki", "mic92", "lassulus", "D", "A", "D", "B", "C"]; const names = ["hsjobeki", "mic92", "lassulus", "D", "A", "D", "B", "C"];
return ( return (

View File

@@ -68,7 +68,7 @@ const WarningIcon: Component = () => (
// --- Base Props and Styles --- // --- Base Props and Styles ---
export interface BaseToastProps { interface BaseToastProps {
t: Toast; t: Toast;
message: string; message: string;
onCancel?: () => void; // Optional custom function on X click onCancel?: () => void; // Optional custom function on X click
@@ -254,7 +254,7 @@ export const CancelToastComponent: Component<BaseToastProps> = (props) => {
}; };
// Warning Toast // Warning Toast
export const WarningToastComponent: Component<BaseToastProps> = (props) => { const WarningToastComponent: Component<BaseToastProps> = (props) => {
let timeoutId: number | undefined; let timeoutId: number | undefined;
const [clicked, setClicked] = createSignal(false); const [clicked, setClicked] = createSignal(false);
const [exiting, setExiting] = createSignal(false); const [exiting, setExiting] = createSignal(false);

View File

@@ -6,10 +6,8 @@ import type {
} from "@floating-ui/dom"; } from "@floating-ui/dom";
import { computePosition } from "@floating-ui/dom"; import { computePosition } from "@floating-ui/dom";
export interface UseFloatingOptions< interface UseFloatingOptions<R extends ReferenceElement, F extends HTMLElement>
R extends ReferenceElement, extends Partial<ComputePositionConfig> {
F extends HTMLElement,
> extends Partial<ComputePositionConfig> {
whileElementsMounted?: ( whileElementsMounted?: (
reference: R, reference: R,
floating: F, floating: F,
@@ -23,7 +21,7 @@ interface UseFloatingState extends Omit<ComputePositionReturn, "x" | "y"> {
y?: number | null; y?: number | null;
} }
export interface UseFloatingResult extends UseFloatingState { interface UseFloatingResult extends UseFloatingState {
update(): void; update(): void;
} }

View File

@@ -23,7 +23,7 @@ export const registerClan = async () => {
* Opens the custom file dialog * Opens the custom file dialog
* Returns a native FileList to allow interaction with the native input type="file" * Returns a native FileList to allow interaction with the native input type="file"
*/ */
export const selectSshKeys = async (): Promise<FileList> => { const selectSshKeys = async (): Promise<FileList> => {
const dataTransfer = new DataTransfer(); const dataTransfer = new DataTransfer();
const response = await callApi("open_file", { const response = await callApi("open_file", {

View File

@@ -2,7 +2,7 @@ import { useQuery } from "@tanstack/solid-query";
import { callApi } from "../api"; import { callApi } from "../api";
import toast from "solid-toast"; import toast from "solid-toast";
export interface ModulesFilter { interface ModulesFilter {
features: string[]; features: string[];
} }
export const createModulesQuery = ( export const createModulesQuery = (

View File

@@ -1,13 +0,0 @@
export const colors = () => {
return (
<div class="grid grid-cols-3 gap-2">
<div class="h-10 w-20 bg-red-500">red</div>
<div class="h-10 w-20 bg-green-500">green</div>
<div class="h-10 w-20 bg-blue-500">blue</div>
<div class="h-10 w-20 bg-yellow-500">yellow</div>
<div class="h-10 w-20 bg-purple-500">purple</div>
<div class="h-10 w-20 bg-cyan-500">cyan</div>
<div class="h-10 w-20 bg-pink-500">pink</div>
</div>
);
};

View File

@@ -1,6 +0,0 @@
import { callApi } from "@/src/api";
import { createQuery } from "@tanstack/solid-query";
export const Deploy = () => {
return <div>Deloy view</div>;
};

View File

@@ -1,31 +0,0 @@
import { callApi } from "@/src/api";
import { useQuery } from "@tanstack/solid-query";
import { useClanContext } from "@/src/contexts/clan";
export function DiskView() {
const { activeClanURI } = useClanContext();
const query = useQuery(() => ({
queryKey: ["disk", activeClanURI()],
queryFn: async () => {
const currUri = activeClanURI();
if (currUri) {
// Example of calling an API
const result = await callApi("get_inventory", {
flake: { identifier: currUri },
}).promise;
if (result.status === "error") throw new Error("Failed to fetch data");
return result.data;
}
},
}));
return (
<div>
<h1>Configure Disk</h1>
<p>
Select machine then configure the disk. Required before installing for
the first time.
</p>
</div>
);
}

View File

@@ -34,7 +34,7 @@ interface Wifi extends FieldValues {
password: string; password: string;
} }
export interface FlashFormValues extends FieldValues { interface FlashFormValues extends FieldValues {
machine: { machine: {
devicePath: string; devicePath: string;
flake: string; flake: string;

View File

@@ -1,9 +1,2 @@
export { MachineActionsBar } from "./MachineActionsBar";
export { MachineAvatar } from "./MachineAvatar";
export { MachineForm } from "./MachineForm";
export { MachineGeneralFields } from "./MachineGeneralFields";
export { MachineHardwareInfo } from "./MachineHardwareInfo";
export { InstallMachine } from "./InstallMachine"; export { InstallMachine } from "./InstallMachine";
export { InstallProgress } from "./InstallProgress"; export { MachineAvatar } from "./MachineAvatar";
export { InstallStepper } from "./InstallStepper";
export { InstallStepNavigation } from "./InstallStepNavigation";

View File

@@ -19,7 +19,7 @@ import { useClanContext } from "@/src/contexts/clan";
export type VarsValues = FieldValues & Record<string, Record<string, string>>; export type VarsValues = FieldValues & Record<string, Record<string, string>>;
export interface VarsFormProps { interface VarsFormProps {
machine_id: string; machine_id: string;
dir: string; dir: string;
handleSubmit: SubmitHandler<VarsValues>; handleSubmit: SubmitHandler<VarsValues>;
@@ -27,7 +27,7 @@ export interface VarsFormProps {
footer: JSX.Element; footer: JSX.Element;
} }
export const VarsForm = (props: VarsFormProps) => { const VarsForm = (props: VarsFormProps) => {
const [formStore, { Form, Field }] = createForm<VarsValues>({}); const [formStore, { Form, Field }] = createForm<VarsValues>({});
const handleSubmit: SubmitHandler<VarsValues> = async (values, event) => { const handleSubmit: SubmitHandler<VarsValues> = async (values, event) => {

View File

@@ -32,7 +32,7 @@ interface AddModuleProps {
id: string; id: string;
} }
export const AddModule = (props: AddModuleProps) => { const AddModule = (props: AddModuleProps) => {
const { activeClanURI } = useClanContext(); const { activeClanURI } = useClanContext();
const tags = tagsQuery(activeClanURI()); const tags = tagsQuery(activeClanURI());
const machines = machinesQuery(activeClanURI()); const machines = machinesQuery(activeClanURI());

View File

@@ -140,7 +140,7 @@ interface SchemaFormProps {
path: string[]; path: string[];
} }
export const ModuleForm = (props: { id: string }) => { const ModuleForm = (props: { id: string }) => {
// TODO: Fetch the synced schema for all the modules at runtime // TODO: Fetch the synced schema for all the modules at runtime
// We use static schema file at build time for now. (Different versions might have different schema at runtime) // We use static schema file at build time for now. (Different versions might have different schema at runtime)
const schemaQuery = createQuery(() => ({ const schemaQuery = createQuery(() => ({

View File

@@ -80,7 +80,6 @@ const removeClanURI = (uri: string) => {
export { export {
store, store,
setStore,
activeClanURI, activeClanURI,
setActiveClanURI, setActiveClanURI,
clanURIs, clanURIs,