mirror of
https://github.com/moghtech/komodo.git
synced 2026-09-07 08:00:54 +00:00
export to toml work. log scroll button better
This commit is contained in:
@@ -0,0 +1,59 @@
|
||||
import { useRead } from "@lib/hooks";
|
||||
import { Types } from "@monitor/client";
|
||||
import { Button } from "@ui/button";
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
} from "@ui/dialog";
|
||||
import { FileDown, Loader2 } from "lucide-react";
|
||||
import { useState } from "react";
|
||||
import { CopyButton } from "./util";
|
||||
|
||||
export const ExportButton = ({}: {
|
||||
target?: Types.ResourceTarget;
|
||||
user_group?: string;
|
||||
}) => {
|
||||
const [open, setOpen] = useState(false);
|
||||
return (
|
||||
<Dialog open={open} onOpenChange={setOpen}>
|
||||
<DialogTrigger asChild>
|
||||
<Button variant="outline" className="flex gap-2 items-center">
|
||||
Export
|
||||
<FileDown className="w-4 h-4" />
|
||||
</Button>
|
||||
</DialogTrigger>
|
||||
<DialogContent className="min-w-[50vw]">
|
||||
<DialogHeader>
|
||||
<DialogTitle>Export to toml</DialogTitle>
|
||||
</DialogHeader>
|
||||
<ExportLoader />
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
);
|
||||
};
|
||||
|
||||
const ExportLoader = () => {
|
||||
const { data, isPending } = useRead("ExportAllResourcesToToml", {});
|
||||
return <ExportPre loading={isPending} content={data?.toml} />;
|
||||
};
|
||||
|
||||
const ExportPre = ({
|
||||
loading,
|
||||
content,
|
||||
}: {
|
||||
loading: boolean;
|
||||
content: string | undefined;
|
||||
}) => {
|
||||
return (
|
||||
<div className="relative flex justify-center">
|
||||
{loading && <Loader2 className="w-8 h-8 animate-spin" />}
|
||||
<div className="overflow-y-scroll max-h-[80vh]">
|
||||
<pre className="h-fit">{content}</pre>
|
||||
</div>
|
||||
<CopyButton content={content} className="absolute top-4 right-4" />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -12,7 +12,7 @@ import {
|
||||
DeleteDeployment,
|
||||
RenameDeployment,
|
||||
} from "./actions";
|
||||
import { DeploymentLogs } from "./logs";
|
||||
import { DeploymentLogs } from "./log";
|
||||
import { snake_case_to_upper_space_case } from "@lib/formatting";
|
||||
import {
|
||||
bg_color_class_by_intention,
|
||||
|
||||
+12
-13
@@ -10,7 +10,7 @@ import {
|
||||
ChevronDown,
|
||||
X,
|
||||
} from "lucide-react";
|
||||
import { useState } from "react";
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import { useDeployment } from ".";
|
||||
import {
|
||||
Select,
|
||||
@@ -102,10 +102,8 @@ const DeploymentLogsInner = ({ id }: { id: string }) => {
|
||||
</Button>
|
||||
</div>
|
||||
<TabsList>
|
||||
<TabsTrigger value="stdout" onClick={to_bottom("stdout")}>
|
||||
stdout
|
||||
</TabsTrigger>
|
||||
<TabsTrigger value="stderr" onClick={to_bottom("stderr")}>
|
||||
<TabsTrigger value="stdout">stdout</TabsTrigger>
|
||||
<TabsTrigger value="stderr">
|
||||
stderr
|
||||
{stderr && (
|
||||
<AlertOctagon className="w-4 h-4 ml-2 stroke-red-500" />
|
||||
@@ -175,18 +173,24 @@ const Log = ({
|
||||
stream: "stdout" | "stderr";
|
||||
}) => {
|
||||
const _log = log?.[stream as keyof typeof log] as string | undefined;
|
||||
const ref = useRef<HTMLDivElement>(null);
|
||||
const scroll = () =>
|
||||
ref.current?.scroll({
|
||||
top: ref.current.scrollHeight,
|
||||
behavior: "smooth",
|
||||
});
|
||||
useEffect(scroll, []);
|
||||
return (
|
||||
<>
|
||||
<div className="h-[70vh] overflow-y-auto">
|
||||
<div ref={ref} className="h-[70vh] overflow-y-auto">
|
||||
<pre
|
||||
id={stream}
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: _log ? logToHtml(_log) : `no ${stream} logs`,
|
||||
}}
|
||||
className="-scroll-mt-24"
|
||||
/>
|
||||
</div>
|
||||
<Button className="absolute bottom-4 right-4" onClick={to_bottom(stream)}>
|
||||
<Button className="absolute bottom-4 right-4" onClick={scroll}>
|
||||
<ChevronDown className="h-4 w-4" />
|
||||
</Button>
|
||||
</>
|
||||
@@ -218,11 +222,6 @@ const TailLengthSelector = ({
|
||||
</Select>
|
||||
);
|
||||
|
||||
const to_bottom = (id: string) => () =>
|
||||
document
|
||||
.getElementById(id)
|
||||
?.scrollIntoView({ behavior: "smooth", block: "end", inline: "nearest" });
|
||||
|
||||
const convert = new Convert();
|
||||
/**
|
||||
* Converts the ansi colors in log to html.
|
||||
@@ -260,13 +260,19 @@ export const UserSettings = () => (
|
||||
</Link>
|
||||
);
|
||||
|
||||
export const CopyButton = ({ content }: { content: string | undefined }) => {
|
||||
export const CopyButton = ({
|
||||
content,
|
||||
className,
|
||||
}: {
|
||||
content: string | undefined;
|
||||
className?: string;
|
||||
}) => {
|
||||
const { toast } = useToast();
|
||||
const [copied, set] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (copied) {
|
||||
toast({ title: `Copied "${content}"` });
|
||||
toast({ title: "Copied selection" });
|
||||
const timeout = setTimeout(() => set(false), 3000);
|
||||
return () => {
|
||||
clearTimeout(timeout);
|
||||
@@ -276,7 +282,7 @@ export const CopyButton = ({ content }: { content: string | undefined }) => {
|
||||
|
||||
return (
|
||||
<Button
|
||||
className="shrink-0"
|
||||
className={cn("shrink-0", className)}
|
||||
size="icon"
|
||||
variant="outline"
|
||||
onClick={() => {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { OpenAlerts } from "@components/alert";
|
||||
import { ExportButton } from "@components/export";
|
||||
import { Page, Section } from "@components/layouts";
|
||||
import { ResourceComponents } from "@components/resources";
|
||||
import { TagsFilter } from "@components/tags";
|
||||
@@ -14,7 +15,8 @@ export const AllResources = () => {
|
||||
title="Resources"
|
||||
actions={
|
||||
<div className="grid gap-4 justify-items-end">
|
||||
<div className="flex gap-4">
|
||||
<div className="flex gap-4 items-center">
|
||||
<ExportButton />
|
||||
<Input
|
||||
value={search}
|
||||
onChange={(e) => setSearch(e.target.value)}
|
||||
|
||||
Reference in New Issue
Block a user