standard update text menu

This commit is contained in:
mbecker20
2024-04-23 22:24:43 -07:00
parent 62b34ab9a5
commit db9c2d924c
4 changed files with 107 additions and 84 deletions

View File

@@ -92,7 +92,6 @@ export const Config = <T,>({
>
>;
}) => {
console.log(selector);
const [show, setShow] = useState(keys(components)[0]);
return (

View File

@@ -2,11 +2,11 @@ import {
ActionButton,
ActionWithDialog,
ConfirmButton,
TextUpdateMenu,
} from "@components/util";
import { useInvalidate, useRead, useWrite } from "@lib/hooks";
import { UsableResource } from "@types";
import { Button } from "@ui/button";
import { Card, CardHeader } from "@ui/card";
import {
Command,
CommandEmpty,
@@ -24,16 +24,8 @@ import {
DialogTrigger,
} from "@ui/dialog";
import { Popover, PopoverContent, PopoverTrigger } from "@ui/popover";
import { Textarea } from "@ui/textarea";
import {
Check,
CheckCircle,
ChevronsUpDown,
Copy,
SearchX,
Trash,
} from "lucide-react";
import { useEffect, useState } from "react";
import { Check, ChevronsUpDown, Copy, SearchX, Trash } from "lucide-react";
import { useState } from "react";
import { Link, useNavigate } from "react-router-dom";
import { ResourceComponents } from ".";
import { Input } from "@ui/input";
@@ -51,8 +43,6 @@ export const ResourceDescription = ({
}) => {
const { toast } = useToast();
const inv = useInvalidate();
const [open, setOpen] = useState(false);
const [description, setDescription] = useState<string>();
const resource = useRead(`Get${type}`, {
[type.toLowerCase()]: id,
@@ -65,44 +55,18 @@ export const ResourceDescription = ({
},
});
useEffect(
() => setDescription(resource?.description),
[resource?.description]
);
return (
<Dialog open={open} onOpenChange={setOpen}>
<DialogTrigger asChild>
<Card className="hover:bg-accent/50 transition-colors cursor-pointer">
<CardHeader className="text-muted-foreground px-4 py-2 overflow-ellipsis">
{resource?.description || "Set description"}
</CardHeader>
</Card>
</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>Update Description</DialogTitle>
</DialogHeader>
<Textarea
value={description}
onChange={(e) => setDescription(e.target.value)}
/>
<DialogFooter>
<ConfirmButton
title="Update"
icon={<CheckCircle className="w-4 h-4" />}
onClick={() => {
update_description({
target: { type, id },
description: description!,
});
setOpen(false);
}}
disabled={description === undefined}
/>
</DialogFooter>
</DialogContent>
</Dialog>
<TextUpdateMenu
title="Update Description"
value={resource?.description}
onUpdate={(description) =>
update_description({
target: { type, id },
description,
})
}
triggerClassName="text-muted-foreground w-[300px]"
/>
);
};

View File

@@ -1,11 +1,7 @@
import { useRead, useWrite } from "@lib/hooks";
import { Types } from "@monitor/client";
import { useState } from "react";
import {
AccountSelector,
ConfigInput,
ConfigItem,
} from "@components/config/util";
import { AccountSelector, ConfigItem } from "@components/config/util";
import { ImageConfig } from "./components/image";
import { RestartModeSelector } from "./components/restart";
import { NetworkModeSelector } from "./components/network";
@@ -20,6 +16,7 @@ import {
TerminationTimeout,
} from "./components/term-signal";
import { LabelsConfig, ResourceSelector } from "@components/resources/common";
import { TextUpdateMenu } from "@components/util";
export const ServerSelector = ({
selected,
@@ -94,12 +91,14 @@ export const DeploymentConfig = ({ id }: { id: string }) => {
/>
),
process_args: (value, set) => (
<ConfigInput
label="Process Args"
value={value}
onChange={(process_args) => set({ process_args })}
disabled={disabled}
/>
<ConfigItem label="Process Args">
<TextUpdateMenu
title="Update Process Args"
value={value}
onUpdate={(process_args) => set({ process_args })}
triggerClassName="max-w-[400px]"
/>
</ConfigItem>
),
network: (value, set) => (
<NetworkModeSelector

View File

@@ -7,7 +7,14 @@ import {
useState,
} from "react";
import { Button } from "../ui/button";
import { Check, Copy, Loader2, LogOut, Settings, User } from "lucide-react";
import {
Check,
CheckCircle,
Copy,
Loader2,
LogOut,
Settings,
} from "lucide-react";
import { Input } from "../ui/input";
import {
Dialog,
@@ -20,12 +27,9 @@ import {
import { toast, useToast } from "@ui/use-toast";
import { cn } from "@lib/utils";
import { Link } from "react-router-dom";
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuTrigger,
} from "@ui/dropdown-menu";
import { AUTH_TOKEN_STORAGE_KEY } from "@main";
import { Textarea } from "@ui/textarea";
import { Card } from "@ui/card";
export const WithLoading = ({
children,
@@ -256,22 +260,6 @@ export const UserSettings = () => (
</Link>
);
export const UserDropdown = () => {
// const user = useRead("GetUser", {}).data;
return (
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="ghost" size="icon">
<User className="w-4 h-4" />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent>
<Logout />
</DropdownMenuContent>
</DropdownMenu>
);
};
export const CopyButton = ({ content }: { content: string | undefined }) => {
const { toast } = useToast();
const [copied, set] = useState(false);
@@ -302,3 +290,76 @@ export const CopyButton = ({ content }: { content: string | undefined }) => {
</Button>
);
};
export const TextUpdateMenu = ({
title,
value = "",
triggerClassName,
onUpdate,
placeholder,
confirmButton,
}: {
title: string;
value: string | undefined;
onUpdate: (value: string) => void;
triggerClassName?: string;
placeholder?: string;
confirmButton?: boolean;
}) => {
const [open, setOpen] = useState(false);
const [_value, setValue] = useState(value);
useEffect(() => setValue(value), [value]);
const onClick = () => {
onUpdate(_value);
setOpen(false);
};
return (
<Dialog open={open} onOpenChange={setOpen}>
<DialogTrigger asChild>
<Card className="px-3 py-2 hover:bg-accent/50 transition-colors cursor-pointer">
<div
className={cn(
"text-sm text-nowrap overflow-hidden overflow-ellipsis",
triggerClassName
)}
>
{value}
</div>
</Card>
</DialogTrigger>
<DialogContent className="min-w-[60vw]">
<DialogHeader>
<DialogTitle>{title}</DialogTitle>
</DialogHeader>
<Textarea
value={_value}
onChange={(e) => setValue(e.target.value)}
placeholder={placeholder}
onKeyDown={(e) => {
if (e.key === "Enter") onClick();
}}
className="min-h-[200px]"
/>
<DialogFooter>
{confirmButton ? (
<ConfirmButton
title="Update"
icon={<CheckCircle className="w-4 h-4" />}
onClick={onClick}
/>
) : (
<Button
variant="secondary"
onClick={onClick}
className="flex items-center gap-2"
>
<CheckCircle className="w-4 h-4" />
Update
</Button>
)}
</DialogFooter>
</DialogContent>
</Dialog>
);
};