feat: add tags

This commit is contained in:
2024-11-18 01:28:31 +07:00
parent 95f9f76edd
commit b0932c39b1
17 changed files with 409 additions and 67 deletions
+19 -2
View File
@@ -8,12 +8,16 @@ import { ScrollView, XStack } from "tamagui";
import { FormSchema, formSchema, typeOptions } from "../schema/form";
import { InputField } from "@/components/ui/input";
import FormField from "@/components/ui/form";
import { useSaveHost } from "../hooks/query";
import { useSaveHost, useTags } from "../hooks/query";
import { ErrorAlert } from "@/components/ui/alert";
import Button from "@/components/ui/button";
import { PVEFormFields } from "./pve";
import { IncusFormFields } from "./incus";
import { SSHFormFields } from "./ssh";
import {
SelectMultipleField,
useSelectCreatableItems,
} from "@/components/ui/select-multiple";
export const hostFormModal = createDisclosure<FormSchema>();
@@ -22,6 +26,8 @@ const HostForm = () => {
const form = useZForm(formSchema, data);
const isEditing = data?.id != null;
const type = form.watch("type");
const hostTags = useTags();
const [tags, addTag] = useSelectCreatableItems(hostTags.data);
const saveMutation = useSaveHost();
@@ -53,6 +59,17 @@ const HostForm = () => {
{type !== "group" && (
<>
<FormField label="Tags">
<SelectMultipleField
form={form}
name="tags"
placeholder="Select Tags"
items={tags}
isCreatable
onCreate={addTag}
/>
</FormField>
<FormField label="Hostname">
<InputField
form={form}
@@ -98,4 +115,4 @@ const HostForm = () => {
);
};
export default HostForm;
export default React.memo(HostForm);
@@ -3,6 +3,7 @@ import React from "react";
import { MultiTapPressable } from "@/components/ui/pressable";
import Icons from "@/components/ui/icons";
import OSIcons from "@/components/ui/os-icons";
import Badge from "@/components/ui/badge";
type HostItemProps = {
host: any;
@@ -26,12 +27,14 @@ const HostItem = ({
numberOfTaps={2}
onMultiTap={onMultiTap}
onTap={onTap}
h="100%"
>
<Card
bordered
p="$4"
borderColor={selected ? "$blue8" : "$borderColor"}
bg={selected ? "$blue3" : undefined}
h="100%"
>
<XStack>
{host.type === "group" ? (
@@ -48,6 +51,15 @@ const HostItem = ({
<View flex={1}>
<Text>{host.label}</Text>
{host.tags?.length > 0 && (
<XStack mt="$1" gap="$1" flexWrap="wrap">
{host.tags.map((i: any) => (
<Badge key={i.name}>{i.name}</Badge>
))}
</XStack>
)}
<Text fontSize="$3" mt="$2">
{host.host}
</Text>
+10 -4
View File
@@ -14,6 +14,7 @@ type HostsListProps = {
onParentIdChange?: (id: string | null) => void;
selected?: string[];
onSelectedChange?: (ids: string[]) => void;
hideGroups?: boolean;
};
const HostList = ({
@@ -22,12 +23,15 @@ const HostList = ({
onParentIdChange,
selected = [],
onSelectedChange,
hideGroups = false,
}: HostsListProps) => {
const openSession = useTermSession((i) => i.push);
const navigation = useNavigation();
const [search, setSearch] = useState("");
const { data, isLoading } = useHosts({ parentId });
const { data, isLoading } = useHosts({
parentId: !search.length ? parentId : "none",
});
const hostsList = useMemo(() => {
let items = data || [];
@@ -37,7 +41,8 @@ const HostList = ({
const q = search.toLowerCase();
return (
item.label.toLowerCase().includes(q) ||
item.host.toLowerCase().includes(q)
item.host.toLowerCase().includes(q) ||
item.tags.find((i: any) => i.name.toLowerCase().includes(q)) != null
);
});
}
@@ -65,7 +70,8 @@ const HostList = ({
const onEdit = (host: any) => {
if (!allowEdit) return;
hostFormModal.onOpen(host);
const data = { ...host, tags: host.tags?.map((i: any) => i.name) };
hostFormModal.onOpen(data);
};
const onOpenTerminal = (host: any) => {
@@ -103,7 +109,7 @@ const HostList = ({
</View>
) : (
<ScrollView>
{groups.length > 0 && (
{groups.length > 0 && !hideGroups && (
<>
<Text mx="$4">Groups</Text>
<ItemList
+14
View File
@@ -66,3 +66,17 @@ export const useMoveHost = () => {
},
});
};
export const useTags = () => {
const teamId = useTeamId();
return useQuery({
queryKey: ["hosts/tags", teamId],
queryFn: () => api("/hosts/tags", { params: { teamId } }),
select: (data) => {
return data?.rows?.map((row: any) => ({
label: row.name,
value: row.name,
}));
},
});
};
+2
View File
@@ -14,6 +14,7 @@ const groupSchema = baseFormSchema.merge(
const hostSchema = baseFormSchema.merge(
z.object({
tags: z.string().array(),
host: hostnameShape(),
port: z.coerce
.number({ message: "Invalid port" })
@@ -65,6 +66,7 @@ export type FormSchema = z.infer<typeof formSchema>;
export const initialValues: FormSchema = {
type: "ssh",
host: "",
tags: [],
port: 22,
label: "",
keyId: "",