diff options
Diffstat (limited to 'ui/src/components')
| -rw-r--r-- | ui/src/components/Drawer.tsx | 2 | ||||
| -rw-r--r-- | ui/src/components/HistoryList.tsx | 131 | ||||
| -rw-r--r-- | ui/src/components/dotfiles/Aliases.tsx | 37 | ||||
| -rw-r--r-- | ui/src/components/history/Stats.tsx | 56 |
4 files changed, 91 insertions, 135 deletions
diff --git a/ui/src/components/Drawer.tsx b/ui/src/components/Drawer.tsx index 65bb5ab4..91753624 100644 --- a/ui/src/components/Drawer.tsx +++ b/ui/src/components/Drawer.tsx @@ -1,5 +1,3 @@ -import * as React from "react"; - import { Drawer as VDrawer } from "vaul"; export default function Drawer({ diff --git a/ui/src/components/HistoryList.tsx b/ui/src/components/HistoryList.tsx index b31a4be4..9616ecf0 100644 --- a/ui/src/components/HistoryList.tsx +++ b/ui/src/components/HistoryList.tsx @@ -1,75 +1,88 @@ -import { DateTime } from 'luxon'; -import { ChevronRightIcon } from '@heroicons/react/20/solid' +import { ChevronRightIcon } from "@heroicons/react/20/solid"; -function msToTime(ms) { - let milliseconds = (ms).toFixed(1); - let seconds = (ms / 1000).toFixed(1); - let minutes = (ms / (1000 * 60)).toFixed(1); - let hours = (ms / (1000 * 60 * 60)).toFixed(1); - let days = (ms / (1000 * 60 * 60 * 24)).toFixed(1); +// @ts-ignore +import { DateTime } from "luxon"; + +function msToTime(ms: number) { + let milliseconds = parseInt(ms.toFixed(1)); + let seconds = parseInt((ms / 1000).toFixed(1)); + let minutes = parseInt((ms / (1000 * 60)).toFixed(1)); + let hours = parseInt((ms / (1000 * 60 * 60)).toFixed(1)); + let days = parseInt((ms / (1000 * 60 * 60 * 24)).toFixed(1)); if (milliseconds < 1000) return milliseconds + "ms"; else if (seconds < 60) return seconds + "s"; else if (minutes < 60) return minutes + "m"; else if (hours < 24) return hours + "hr"; - else return days + " Days" + else return days + " Days"; } -export default function HistoryList(props){ +export default function HistoryList(props: any) { return ( + <ul + role="list" + className="divide-y divide-gray-100 overflow-hidden bg-white shadow-sm ring-1 ring-gray-900/5" + > + {props.history.map((h: any) => ( + <li + key={h.id} + className="relative flex justify-between gap-x-6 px-4 py-5 hover:bg-gray-50 sm:px-6" + > + <div className="flex min-w-0 gap-x-4"> + <div className="flex flex-col justify-center"> + <p className="flex text-xs text-gray-500 justify-center"> + {DateTime.fromMillis(h.timestamp / 1000000).toLocaleString( + DateTime.TIME_WITH_SECONDS, + )} + </p> + <p className="flex text-xs mt-1 text-gray-400 justify-center"> + {DateTime.fromMillis(h.timestamp / 1000000).toLocaleString( + DateTime.DATE_SHORT, + )} + </p> + </div> + <div className="min-w-0 flex-col justify-center"> + <pre className="whitespace-pre-wrap"> + <code className="text-sm">{h.command}</code> + </pre> + <p className="mt-1 flex text-xs leading-5 text-gray-500"> + <span className="relative truncate ">{h.user}</span> - <ul - role="list" - className="divide-y divide-gray-100 overflow-hidden bg-white shadow-sm ring-1 ring-gray-900/5" - > - {props.history.map((h) => ( - <li key={h.id} className="relative flex justify-between gap-x-6 px-4 py-5 hover:bg-gray-50 sm:px-6"> - <div className="flex min-w-0 gap-x-4"> - <div className="flex flex-col justify-center"> - <p className="flex text-xs text-gray-500 justify-center">{ DateTime.fromMillis(h.timestamp / 1000000).toLocaleString(DateTime.TIME_WITH_SECONDS)}</p> - <p className="flex text-xs mt-1 text-gray-400 justify-center">{ DateTime.fromMillis(h.timestamp / 1000000).toLocaleString(DateTime.DATE_SHORT)}</p> - </div> - <div className="min-w-0 flex-col justify-center"> - <pre className="whitespace-pre-wrap"><code className="text-sm">{h.command}</code></pre> - <p className="mt-1 flex text-xs leading-5 text-gray-500"> - <span className="relative truncate "> - {h.user} - </span> - - <span> on </span> + <span> on </span> - <span className="relative truncate "> - {h.host} - </span> + <span className="relative truncate ">{h.host}</span> - <span> in </span> + <span> in </span> - <span className="relative truncate "> - {h.cwd} - </span> - </p> - </div> - </div> - <div className="flex shrink-0 items-center gap-x-4"> - <div className="hidden sm:flex sm:flex-col sm:items-end"> - <p className="text-sm leading-6 text-gray-900">{h.exit}</p> - {h.duration ? ( - <p className="mt-1 text-xs leading-5 text-gray-500"> - <time dateTime={h.duration}>{msToTime(h.duration / 1000000)}</time> - </p> - ) : ( - <div className="mt-1 flex items-center gap-x-1.5"> - <div className="flex-none rounded-full bg-emerald-500/20 p-1"> - <div className="h-1.5 w-1.5 rounded-full bg-emerald-500" /> - </div> - <p className="text-xs leading-5 text-gray-500">Online</p> - </div> - )} - </div> - <ChevronRightIcon className="h-5 w-5 flex-none text-gray-400" aria-hidden="true" /> + <span className="relative truncate ">{h.cwd}</span> + </p> + </div> + </div> + <div className="flex shrink-0 items-center gap-x-4"> + <div className="hidden sm:flex sm:flex-col sm:items-end"> + <p className="text-sm leading-6 text-gray-900">{h.exit}</p> + {h.duration ? ( + <p className="mt-1 text-xs leading-5 text-gray-500"> + <time dateTime={h.duration}> + {msToTime(h.duration / 1000000)} + </time> + </p> + ) : ( + <div className="mt-1 flex items-center gap-x-1.5"> + <div className="flex-none rounded-full bg-emerald-500/20 p-1"> + <div className="h-1.5 w-1.5 rounded-full bg-emerald-500" /> </div> - </li> - ))} - </ul> + <p className="text-xs leading-5 text-gray-500">Online</p> + </div> + )} + </div> + <ChevronRightIcon + className="h-5 w-5 flex-none text-gray-400" + aria-hidden="true" + /> + </div> + </li> + ))} + </ul> ); } diff --git a/ui/src/components/dotfiles/Aliases.tsx b/ui/src/components/dotfiles/Aliases.tsx index 4854e6b5..61fd001c 100644 --- a/ui/src/components/dotfiles/Aliases.tsx +++ b/ui/src/components/dotfiles/Aliases.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useState } from "react"; +import { useEffect, useState } from "react"; import DataTable from "@/components/ui/data-table"; import { Button } from "@/components/ui/button"; @@ -8,34 +8,21 @@ import { DropdownMenuContent, DropdownMenuItem, DropdownMenuLabel, - DropdownMenuSeparator, DropdownMenuTrigger, } from "@/components/ui/dropdown-menu"; +import { ColumnDef } from "@tanstack/react-table"; + import { invoke } from "@tauri-apps/api/core"; import Drawer from "@/components/Drawer"; -function loadAliases( - setAliases: React.Dispatch<React.SetStateAction<never[]>>, -) { - invoke("aliases").then((aliases: any) => { - setAliases(aliases); - }); -} - -type Alias = { - name: string; - value: string; -}; +import { Alias } from "@/state/models"; +import { useStore } from "@/state/store"; -function deleteAlias( - name: string, - setAliases: React.Dispatch<React.SetStateAction<never[]>>, -) { +function deleteAlias(name: string, refreshAliases: () => void) { invoke("delete_alias", { name: name }) .then(() => { - console.log("Deleted alias"); - loadAliases(setAliases); + refreshAliases(); }) .catch(() => { console.error("Failed to delete alias"); @@ -101,7 +88,9 @@ function AddAlias({ onAdd: onAdd }: { onAdd?: () => void }) { } export default function Aliases() { - let [aliases, setAliases] = useState([]); + const aliases = useStore((state) => state.aliases); + const refreshAliases = useStore((state) => state.refreshAliases); + let [aliasDrawerOpen, setAliasDrawerOpen] = useState(false); const columns: ColumnDef<Alias>[] = [ @@ -129,7 +118,7 @@ export default function Aliases() { <DropdownMenuContent align="end"> <DropdownMenuLabel>Actions</DropdownMenuLabel> <DropdownMenuItem - onClick={() => deleteAlias(alias.name, setAliases)} + onClick={() => deleteAlias(alias.name, refreshAliases)} > Delete </DropdownMenuItem> @@ -141,7 +130,7 @@ export default function Aliases() { ]; useEffect(() => { - loadAliases(setAliases); + refreshAliases(); }, []); return ( @@ -172,7 +161,7 @@ export default function Aliases() { > <AddAlias onAdd={() => { - loadAliases(setAliases); + refreshAliases(); setAliasDrawerOpen(false); }} /> diff --git a/ui/src/components/history/Stats.tsx b/ui/src/components/history/Stats.tsx index afd9ed89..ce92ac04 100644 --- a/ui/src/components/history/Stats.tsx +++ b/ui/src/components/history/Stats.tsx @@ -5,29 +5,18 @@ import PacmanLoader from "react-spinners/PacmanLoader"; import { BarChart, Bar, - Rectangle, XAxis, YAxis, - CartesianGrid, Tooltip, - Legend, ResponsiveContainer, } from "recharts"; -const tabs = [ - { name: "Daily", href: "#", current: true }, - { name: "Weekly", href: "#", current: false }, - { name: "Monthly", href: "#", current: false }, -]; - -function classNames(...classes) { - return classes.filter(Boolean).join(" "); -} - function renderLoading() { - <div className="flex items-center justify-center h-full"> - <PacmanLoader color="#26bd65" /> - </div>; + return ( + <div className="flex items-center justify-center h-full"> + <PacmanLoader color="#26bd65" /> + </div> + ); } export default function Stats() { @@ -77,7 +66,7 @@ export default function Stats() { <div className="flex flex-col"> <div className="flexfull"> <dl className="grid grid-cols-1 sm:grid-cols-4 w-full"> - {stats.map((item) => ( + {stats.map((item: any) => ( <div key={item.name} className="overflow-hidden bg-white px-4 py-5 shadow sm:p-6" @@ -94,39 +83,6 @@ export default function Stats() { </div> <div className="flex flex-col h-54 py-4 pl-5"> - <div className="sm:hidden"> - {/* Use an "onChange" listener to redirect the user to the selected tab URL. */} - <select - id="tabs" - name="tabs" - className="block w-full rounded-md border-gray-300 focus:border-green-500 focus:ring-green-500" - defaultValue={tabs.find((tab) => tab.current).name} - > - {tabs.map((tab) => ( - <option key={tab.name}>{tab.name}</option> - ))} - </select> - </div> - <div className="hidden sm:block"> - <nav className="flex space-x-4" aria-label="Tabs"> - {tabs.map((tab) => ( - <a - key={tab.name} - href={tab.href} - className={classNames( - tab.current - ? "bg-gray-100 text-gray-700" - : "text-gray-500 hover:text-gray-700", - "rounded-md px-3 py-2 text-sm font-medium", - )} - aria-current={tab.current ? "page" : undefined} - > - {tab.name} - </a> - ))} - </nav> - </div> - <div className="flex flex-col h-48 pt-5 pr-5"> <ResponsiveContainer width="100%" height="100%"> <BarChart width={500} height={300} data={chart}> |
