feat(ui): integrate list_tags api call into machine detail
This commit is contained in:
@@ -11,7 +11,7 @@ import { Label } from "@/src/components/Form/Label";
|
||||
import { Orienter } from "@/src/components/Form/Orienter";
|
||||
import { CollectionNode } from "@kobalte/core";
|
||||
|
||||
interface MachineTag {
|
||||
export interface MachineTag {
|
||||
value: string;
|
||||
disabled?: boolean;
|
||||
new?: boolean;
|
||||
@@ -24,11 +24,10 @@ export type MachineTagsProps = FieldProps & {
|
||||
disabled?: boolean;
|
||||
required?: boolean;
|
||||
defaultValue?: string[];
|
||||
defaultOptions?: string[];
|
||||
readonlyOptions?: string[];
|
||||
};
|
||||
|
||||
// tags which are applied to all machines and cannot be removed
|
||||
const staticOptions = [{ value: "all", disabled: true }];
|
||||
|
||||
const uniqueOptions = (options: MachineTag[]) => {
|
||||
const record: Record<string, MachineTag> = {};
|
||||
options.forEach((option) => {
|
||||
@@ -39,13 +38,8 @@ const uniqueOptions = (options: MachineTag[]) => {
|
||||
return Object.values(record);
|
||||
};
|
||||
|
||||
const sortedOptions = (options: MachineTag[]) => {
|
||||
return options.sort((a, b) => {
|
||||
if (a.new && !b.new) return -1;
|
||||
if (a.disabled && !b.disabled) return -1;
|
||||
return a.value.localeCompare(b.value);
|
||||
});
|
||||
};
|
||||
const sortedOptions = (options: MachineTag[]) =>
|
||||
options.sort((a, b) => a.value.localeCompare(b.value));
|
||||
|
||||
const sortedAndUniqueOptions = (options: MachineTag[]) =>
|
||||
sortedOptions(uniqueOptions(options));
|
||||
@@ -72,9 +66,15 @@ export const MachineTags = (props: MachineTagsProps) => {
|
||||
(props.defaultValue || []).map((value) => ({ value })),
|
||||
);
|
||||
|
||||
// todo this should be the superset of tags used across the entire clan and be passed in via a prop
|
||||
// convert default options string[] into MachineTag[]
|
||||
const [availableOptions, setAvailableOptions] = createSignal<MachineTag[]>(
|
||||
sortedAndUniqueOptions([...staticOptions, ...defaultValue]),
|
||||
sortedAndUniqueOptions([
|
||||
...(props.readonlyOptions || []).map((value) => ({
|
||||
value,
|
||||
disabled: true,
|
||||
})),
|
||||
...(props.defaultOptions || []).map((value) => ({ value })),
|
||||
]),
|
||||
);
|
||||
|
||||
const onKeyDown = (event: KeyboardEvent) => {
|
||||
|
||||
@@ -13,11 +13,13 @@ export type FieldSchema<T> = {
|
||||
};
|
||||
};
|
||||
|
||||
export type Tags = SuccessData<"list_tags">;
|
||||
export type Machine = SuccessData<"get_machine">;
|
||||
export type ListMachines = SuccessData<"list_machines">;
|
||||
export type MachineDetails = SuccessData<"get_machine_details">;
|
||||
|
||||
export interface MachineDetail {
|
||||
tags: Tags;
|
||||
machine: Machine;
|
||||
fieldsSchema: FieldSchema<Machine>;
|
||||
}
|
||||
@@ -50,7 +52,12 @@ export const useMachineQuery = (clanURI: string, machineName: string) => {
|
||||
return useQuery<MachineDetail>(() => ({
|
||||
queryKey: ["clans", encodeBase64(clanURI), "machine", machineName],
|
||||
queryFn: async () => {
|
||||
const [machineCall, schemaCall] = await Promise.all([
|
||||
const [tagsCall, machineCall, schemaCall] = await Promise.all([
|
||||
client.fetch("list_tags", {
|
||||
flake: {
|
||||
identifier: clanURI,
|
||||
},
|
||||
}),
|
||||
client.fetch("get_machine", {
|
||||
name: machineName,
|
||||
flake: {
|
||||
@@ -67,6 +74,11 @@ export const useMachineQuery = (clanURI: string, machineName: string) => {
|
||||
}),
|
||||
]);
|
||||
|
||||
const tags = await tagsCall.result;
|
||||
if (tags.status === "error") {
|
||||
throw new Error("Error fetching tags: " + tags.errors[0].message);
|
||||
}
|
||||
|
||||
const machine = await machineCall.result;
|
||||
if (machine.status === "error") {
|
||||
throw new Error("Error fetching machine: " + machine.errors[0].message);
|
||||
@@ -81,6 +93,7 @@ export const useMachineQuery = (clanURI: string, machineName: string) => {
|
||||
}
|
||||
|
||||
return {
|
||||
tags: tags.data,
|
||||
machine: machine.data,
|
||||
fieldsSchema: writeSchema.data,
|
||||
};
|
||||
|
||||
@@ -4,7 +4,8 @@ import { MachineDetail } from "@/src/hooks/queries";
|
||||
import { SidebarSectionForm } from "@/src/components/Sidebar/SidebarSectionForm";
|
||||
import { pick } from "@/src/util";
|
||||
import { UseQueryResult } from "@tanstack/solid-query";
|
||||
import { MachineTags } from "@/src/components/Form/MachineTags";
|
||||
import { MachineTag, MachineTags } from "@/src/components/Form/MachineTags";
|
||||
import { machineNameParam } from "@/src/hooks/clan";
|
||||
|
||||
const schema = v.object({
|
||||
tags: v.pipe(v.optional(v.array(v.string()))),
|
||||
@@ -30,6 +31,28 @@ export const SectionTags = (props: SectionTags) => {
|
||||
return pick(machineQuery.data.machine, ["tags"]) satisfies FormValues;
|
||||
};
|
||||
|
||||
const readonlyOptions = () => {
|
||||
if (!machineQuery.isSuccess) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const result: string[] = ["all"];
|
||||
|
||||
if (machineQuery.data.machine.machineClass) {
|
||||
result.push(machineQuery.data.machine.machineClass);
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
const defaultOptions = () => {
|
||||
if (!machineQuery.isSuccess) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return machineQuery.data.tags?.options ?? [];
|
||||
};
|
||||
|
||||
return (
|
||||
<Show when={machineQuery.isSuccess}>
|
||||
<SidebarSectionForm
|
||||
@@ -50,6 +73,8 @@ export const SectionTags = (props: SectionTags) => {
|
||||
readOnly={!editing}
|
||||
orientation="horizontal"
|
||||
defaultValue={field.value}
|
||||
defaultOptions={defaultOptions()}
|
||||
readonlyOptions={readonlyOptions()}
|
||||
input={input}
|
||||
/>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user