Merge pull request 'add more example utils to dashboard' (#139) from feature/dashboard into main
All checks were successful
build / test (push) Successful in 20s
1
pkgs/ui/public/app-icons/app-placeholder.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Pro 6.4.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --><path d="M255.9 120.9l9.1-15.7c5.6-9.8 18.1-13.1 27.9-7.5 9.8 5.6 13.1 18.1 7.5 27.9l-87.5 151.5h63.3c20.5 0 32 24.1 23.1 40.8H113.8c-11.3 0-20.4-9.1-20.4-20.4 0-11.3 9.1-20.4 20.4-20.4h52l66.6-115.4-20.8-36.1c-5.6-9.8-2.3-22.2 7.5-27.9 9.8-5.6 22.2-2.3 27.9 7.5l8.9 15.7zm-78.7 218l-19.6 34c-5.6 9.8-18.1 13.1-27.9 7.5-9.8-5.6-13.1-18.1-7.5-27.9l14.6-25.2c16.4-5.1 29.8-1.2 40.4 11.6zm168.9-61.7h53.1c11.3 0 20.4 9.1 20.4 20.4 0 11.3-9.1 20.4-20.4 20.4h-29.5l19.9 34.5c5.6 9.8 2.3 22.2-7.5 27.9-9.8 5.6-22.2 2.3-27.9-7.5-33.5-58.1-58.7-101.6-75.4-130.6-17.1-29.5-4.9-59.1 7.2-69.1 13.4 23 33.4 57.7 60.1 104zM256 8C119 8 8 119 8 256s111 248 248 248 248-111 248-248S393 8 256 8zm216 248c0 118.7-96.1 216-216 216-118.7 0-216-96.1-216-216 0-118.7 96.1-216 216-216 118.7 0 216 96.1 216 216z"/></svg>
|
After Width: | Height: | Size: 1.0 KiB |
1
pkgs/ui/public/app-icons/chess.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Pro 6.4.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --><path d="M96 48L82.7 61.3C70.7 73.3 64 89.5 64 106.5V238.9c0 10.7 5.3 20.7 14.2 26.6l10.6 7c14.3 9.6 32.7 10.7 48.1 3l3.2-1.6c2.6-1.3 5-2.8 7.3-4.5l49.4-37c6.6-5 15.7-5 22.3 0c10.2 7.7 9.9 23.1-.7 30.3L90.4 350C73.9 361.3 64 380 64 400H384l28.9-159c2.1-11.3 3.1-22.8 3.1-34.3V192C416 86 330 0 224 0H83.8C72.9 0 64 8.9 64 19.8c0 7.5 4.2 14.3 10.9 17.7L96 48zm24 68a20 20 0 1 1 40 0 20 20 0 1 1 -40 0zM22.6 473.4c-4.2 4.2-6.6 10-6.6 16C16 501.9 26.1 512 38.6 512H409.4c12.5 0 22.6-10.1 22.6-22.6c0-6-2.4-11.8-6.6-16L384 432H64L22.6 473.4z"/></svg>
|
After Width: | Height: | Size: 775 B |
1
pkgs/ui/public/app-icons/discord.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512"><!--! Font Awesome Pro 6.4.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --><path d="M524.531,69.836a1.5,1.5,0,0,0-.764-.7A485.065,485.065,0,0,0,404.081,32.03a1.816,1.816,0,0,0-1.923.91,337.461,337.461,0,0,0-14.9,30.6,447.848,447.848,0,0,0-134.426,0,309.541,309.541,0,0,0-15.135-30.6,1.89,1.89,0,0,0-1.924-.91A483.689,483.689,0,0,0,116.085,69.137a1.712,1.712,0,0,0-.788.676C39.068,183.651,18.186,294.69,28.43,404.354a2.016,2.016,0,0,0,.765,1.375A487.666,487.666,0,0,0,176.02,479.918a1.9,1.9,0,0,0,2.063-.676A348.2,348.2,0,0,0,208.12,430.4a1.86,1.86,0,0,0-1.019-2.588,321.173,321.173,0,0,1-45.868-21.853,1.885,1.885,0,0,1-.185-3.126c3.082-2.309,6.166-4.711,9.109-7.137a1.819,1.819,0,0,1,1.9-.256c96.229,43.917,200.41,43.917,295.5,0a1.812,1.812,0,0,1,1.924.233c2.944,2.426,6.027,4.851,9.132,7.16a1.884,1.884,0,0,1-.162,3.126,301.407,301.407,0,0,1-45.89,21.83,1.875,1.875,0,0,0-1,2.611,391.055,391.055,0,0,0,30.014,48.815,1.864,1.864,0,0,0,2.063.7A486.048,486.048,0,0,0,610.7,405.729a1.882,1.882,0,0,0,.765-1.352C623.729,277.594,590.933,167.465,524.531,69.836ZM222.491,337.58c-28.972,0-52.844-26.587-52.844-59.239S193.056,219.1,222.491,219.1c29.665,0,53.306,26.82,52.843,59.239C275.334,310.993,251.924,337.58,222.491,337.58Zm195.38,0c-28.971,0-52.843-26.587-52.843-59.239S388.437,219.1,417.871,219.1c29.667,0,53.307,26.82,52.844,59.239C470.715,310.993,447.538,337.58,417.871,337.58Z"/></svg>
|
After Width: | Height: | Size: 1.5 KiB |
1
pkgs/ui/public/app-icons/dochub.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 416 512"><!--! Font Awesome Pro 6.4.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --><path d="M397.9 160H256V19.6L397.9 160zM304 192v130c0 66.8-36.5 100.1-113.3 100.1H96V84.8h94.7c12 0 23.1.8 33.1 2.5v-84C212.9 1.1 201.4 0 189.2 0H0v512h189.2C329.7 512 400 447.4 400 318.1V192h-96z"/></svg>
|
After Width: | Height: | Size: 435 B |
1
pkgs/ui/public/app-icons/firefox.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Pro 6.4.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --><path d="M503.52,241.48c-.12-1.56-.24-3.12-.24-4.68v-.12l-.36-4.68v-.12a245.86,245.86,0,0,0-7.32-41.15c0-.12,0-.12-.12-.24l-1.08-4c-.12-.24-.12-.48-.24-.6-.36-1.2-.72-2.52-1.08-3.72-.12-.24-.12-.6-.24-.84-.36-1.2-.72-2.4-1.08-3.48-.12-.36-.24-.6-.36-1-.36-1.2-.72-2.28-1.2-3.48l-.36-1.08c-.36-1.08-.84-2.28-1.2-3.36a8.27,8.27,0,0,0-.36-1c-.48-1.08-.84-2.28-1.32-3.36-.12-.24-.24-.6-.36-.84-.48-1.2-1-2.28-1.44-3.48,0-.12-.12-.24-.12-.36-1.56-3.84-3.24-7.68-5-11.4l-.36-.72c-.48-1-.84-1.8-1.32-2.64-.24-.48-.48-1.08-.72-1.56-.36-.84-.84-1.56-1.2-2.4-.36-.6-.6-1.2-1-1.8s-.84-1.44-1.2-2.28c-.36-.6-.72-1.32-1.08-1.92s-.84-1.44-1.2-2.16a18.07,18.07,0,0,0-1.2-2c-.36-.72-.84-1.32-1.2-2s-.84-1.32-1.2-2-.84-1.32-1.2-1.92-.84-1.44-1.32-2.16a15.63,15.63,0,0,0-1.2-1.8L463.2,119a15.63,15.63,0,0,0-1.2-1.8c-.48-.72-1.08-1.56-1.56-2.28-.36-.48-.72-1.08-1.08-1.56l-1.8-2.52c-.36-.48-.6-.84-1-1.32-1-1.32-1.8-2.52-2.76-3.72a248.76,248.76,0,0,0-23.51-26.64A186.82,186.82,0,0,0,412,62.46c-4-3.48-8.16-6.72-12.48-9.84a162.49,162.49,0,0,0-24.6-15.12c-2.4-1.32-4.8-2.52-7.2-3.72a254,254,0,0,0-55.43-19.56c-1.92-.36-3.84-.84-5.64-1.2h-.12c-1-.12-1.8-.36-2.76-.48a236.35,236.35,0,0,0-38-4H255.14a234.62,234.62,0,0,0-45.48,5c-33.59,7.08-63.23,21.24-82.91,39-1.08,1-1.92,1.68-2.4,2.16l-.48.48H124l-.12.12.12-.12a.12.12,0,0,0,.12-.12l-.12.12a.42.42,0,0,1,.24-.12c14.64-8.76,34.92-16,49.44-19.56l5.88-1.44c.36-.12.84-.12,1.2-.24,1.68-.36,3.36-.72,5.16-1.08.24,0,.6-.12.84-.12C250.94,20.94,319.34,40.14,367,85.61a171.49,171.49,0,0,1,26.88,32.76c30.36,49.2,27.48,111.11,3.84,147.59-34.44,53-111.35,71.27-159,24.84a84.19,84.19,0,0,1-25.56-59,74.05,74.05,0,0,1,6.24-31c1.68-3.84,13.08-25.67,18.24-24.59-13.08-2.76-37.55,2.64-54.71,28.19-15.36,22.92-14.52,58.2-5,83.28a132.85,132.85,0,0,1-12.12-39.24c-12.24-82.55,43.31-153,94.31-170.51-27.48-24-96.47-22.31-147.71,15.36-29.88,22-51.23,53.16-62.51,90.36,1.68-20.88,9.6-52.08,25.8-83.88-17.16,8.88-39,37-49.8,62.88-15.6,37.43-21,82.19-16.08,124.79.36,3.24.72,6.36,1.08,9.6,19.92,117.11,122,206.38,244.78,206.38C392.77,503.42,504,392.19,504,255,503.88,250.48,503.76,245.92,503.52,241.48Z"/></svg>
|
After Width: | Height: | Size: 2.3 KiB |
1
pkgs/ui/public/app-icons/games.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512"><!--! Font Awesome Pro 6.4.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --><path d="M274.9 34.3c-28.1-28.1-73.7-28.1-101.8 0L34.3 173.1c-28.1 28.1-28.1 73.7 0 101.8L173.1 413.7c28.1 28.1 73.7 28.1 101.8 0L413.7 274.9c28.1-28.1 28.1-73.7 0-101.8L274.9 34.3zM200 224a24 24 0 1 1 48 0 24 24 0 1 1 -48 0zM96 200a24 24 0 1 1 0 48 24 24 0 1 1 0-48zM224 376a24 24 0 1 1 0-48 24 24 0 1 1 0 48zM352 200a24 24 0 1 1 0 48 24 24 0 1 1 0-48zM224 120a24 24 0 1 1 0-48 24 24 0 1 1 0 48zm96 328c0 35.3 28.7 64 64 64H576c35.3 0 64-28.7 64-64V256c0-35.3-28.7-64-64-64H461.7c11.6 36 3.1 77-25.4 105.5L320 413.8V448zM480 328a24 24 0 1 1 0 48 24 24 0 1 1 0-48z"/></svg>
|
After Width: | Height: | Size: 803 B |
1
pkgs/ui/public/app-icons/mail.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Pro 6.4.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --><path d="M64 112c-8.8 0-16 7.2-16 16v22.1L220.5 291.7c20.7 17 50.4 17 71.1 0L464 150.1V128c0-8.8-7.2-16-16-16H64zM48 212.2V384c0 8.8 7.2 16 16 16H448c8.8 0 16-7.2 16-16V212.2L322 328.8c-38.4 31.5-93.7 31.5-132 0L48 212.2zM0 128C0 92.7 28.7 64 64 64H448c35.3 0 64 28.7 64 64V384c0 35.3-28.7 64-64 64H64c-35.3 0-64-28.7-64-64V128z"/></svg>
|
After Width: | Height: | Size: 567 B |
1
pkgs/ui/public/app-icons/public-transport.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Pro 6.4.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --><path d="M96 0C43 0 0 43 0 96V352c0 48 35.2 87.7 81.1 94.9l-46 46C28.1 499.9 33.1 512 43 512H82.7c8.5 0 16.6-3.4 22.6-9.4L160 448H288l54.6 54.6c6 6 14.1 9.4 22.6 9.4H405c10 0 15-12.1 7.9-19.1l-46-46c46-7.1 81.1-46.9 81.1-94.9V96c0-53-43-96-96-96H96zM64 96c0-17.7 14.3-32 32-32H352c17.7 0 32 14.3 32 32v96c0 17.7-14.3 32-32 32H96c-17.7 0-32-14.3-32-32V96zM224 288a48 48 0 1 1 0 96 48 48 0 1 1 0-96z"/></svg>
|
After Width: | Height: | Size: 636 B |
1
pkgs/ui/public/app-icons/youtube.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><!--! Font Awesome Pro 6.4.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --><path d="M549.655 124.083c-6.281-23.65-24.787-42.276-48.284-48.597C458.781 64 288 64 288 64S117.22 64 74.629 75.486c-23.497 6.322-42.003 24.947-48.284 48.597-11.412 42.867-11.412 132.305-11.412 132.305s0 89.438 11.412 132.305c6.281 23.65 24.787 41.5 48.284 47.821C117.22 448 288 448 288 448s170.78 0 213.371-11.486c23.497-6.321 42.003-24.171 48.284-47.821 11.412-42.867 11.412-132.305 11.412-132.305s0-89.438-11.412-132.305zm-317.51 213.508V175.185l142.739 81.205-142.739 81.201z"/></svg>
|
After Width: | Height: | Size: 718 B |
@ -96,7 +96,7 @@ export default function RootLayout({
|
||||
</div>
|
||||
|
||||
<div className="px-1">
|
||||
<div className="relative flex flex-1 flex-col overflow-x-hidden">
|
||||
<div className="relative flex h-full flex-1 flex-col">
|
||||
<main>{children}</main>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1,15 +1,20 @@
|
||||
import { RecentActivity } from "@/components/dashboard/activity";
|
||||
import { AppOverview } from "@/components/dashboard/appOverview";
|
||||
import { NetworkOverview } from "@/components/dashboard/NetworkOverview";
|
||||
import { Notifications } from "@/components/dashboard/notifications";
|
||||
import { QuickActions } from "@/components/quickActions";
|
||||
import { QuickActions } from "@/components/dashboard/quickActions";
|
||||
import { TaskQueue } from "@/components/dashboard/taskQueue";
|
||||
import { tw } from "@/utils/tailwind";
|
||||
|
||||
interface DashboardCardProps {
|
||||
children?: React.ReactNode;
|
||||
rowSpan?: number;
|
||||
sx?: string;
|
||||
}
|
||||
const DashboardCard = (props: DashboardCardProps) => {
|
||||
const { children } = props;
|
||||
const { children, rowSpan = 1, sx = "" } = props;
|
||||
return (
|
||||
<div className="col-span-full row-span-1 border border-dashed border-slate-400 lg:col-span-1">
|
||||
<div className={tw`col-span-full row-span-${rowSpan} xl:col-span-1 ${sx}`}>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
@ -21,9 +26,7 @@ interface DashboardPanelProps {
|
||||
const DashboardPanel = (props: DashboardPanelProps) => {
|
||||
const { children } = props;
|
||||
return (
|
||||
<div className="col-span-full row-span-1 shrink-0 border border-dashed border-slate-400 lg:col-span-2">
|
||||
{children}
|
||||
</div>
|
||||
<div className="col-span-full row-span-1 xl:col-span-2">{children}</div>
|
||||
);
|
||||
};
|
||||
|
||||
@ -36,10 +39,7 @@ const SplitDashboardCard = (props: SplitDashboardCardProps) => {
|
||||
<div className="col-span-full row-span-1 lg:col-span-1">
|
||||
<div className="grid h-full grid-cols-1 gap-4">
|
||||
{children?.map((row, idx) => (
|
||||
<div
|
||||
key={idx}
|
||||
className="col-span-full row-span-1 border border-dashed border-slate-400"
|
||||
>
|
||||
<div key={idx} className="col-span-full row-span-1 ">
|
||||
{row}
|
||||
</div>
|
||||
))}
|
||||
@ -51,19 +51,25 @@ const SplitDashboardCard = (props: SplitDashboardCardProps) => {
|
||||
export default function Dashboard() {
|
||||
return (
|
||||
<div className="flex h-screen w-full">
|
||||
<div className="grid w-full auto-rows-min grid-cols-3 gap-4">
|
||||
<DashboardCard>
|
||||
<div className="grid w-full auto-cols-min grid-flow-row auto-rows-min grid-cols-1 grid-rows-none gap-4 xl:grid-cols-2 2xl:grid-cols-3 ">
|
||||
<DashboardCard rowSpan={2}>
|
||||
<NetworkOverview />
|
||||
</DashboardCard>
|
||||
<DashboardCard>
|
||||
<DashboardCard rowSpan={2}>
|
||||
<RecentActivity />
|
||||
</DashboardCard>
|
||||
<SplitDashboardCard>
|
||||
<DashboardCard>
|
||||
<Notifications />
|
||||
</DashboardCard>
|
||||
<DashboardCard>
|
||||
<QuickActions />
|
||||
</SplitDashboardCard>
|
||||
<DashboardPanel>Panel</DashboardPanel>
|
||||
<DashboardCard>Side Bar (misc)</DashboardCard>
|
||||
</DashboardCard>
|
||||
<DashboardPanel>
|
||||
<AppOverview />
|
||||
</DashboardPanel>
|
||||
<DashboardCard sx={tw`xl:col-span-full 2xl:col-span-1`}>
|
||||
<TaskQueue />
|
||||
</DashboardCard>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
@ -8,7 +8,7 @@ interface DashboardCardProps {
|
||||
const DashboardCard = (props: DashboardCardProps) => {
|
||||
const { children, title } = props;
|
||||
return (
|
||||
<div className="h-full w-full bg-slate-50 shadow-sm shadow-slate-500">
|
||||
<div className="h-full w-full border border-solid border-slate-100 bg-slate-50 shadow-sm shadow-slate-400">
|
||||
<div className="h-full w-full px-3 py-2">
|
||||
<Typography variant="h6" color={"secondary"}>
|
||||
{title}
|
||||
|
96
pkgs/ui/src/components/dashboard/appOverview/index.tsx
Normal file
@ -0,0 +1,96 @@
|
||||
import { DashboardCard } from "@/components/card";
|
||||
import Image from "next/image";
|
||||
import { ReactNode } from "react";
|
||||
|
||||
interface AppCardProps {
|
||||
name: string;
|
||||
icon?: string;
|
||||
}
|
||||
const AppCard = (props: AppCardProps) => {
|
||||
const { name, icon } = props;
|
||||
const iconPath = icon
|
||||
? `/app-icons/${icon}`
|
||||
: "app-icons/app-placeholder.svg";
|
||||
return (
|
||||
<div
|
||||
role="button"
|
||||
className="flex h-40 w-40 cursor-pointer items-center justify-center rounded-3xl p-2
|
||||
align-middle shadow-md ring-2 ring-inset ring-violet-500 hover:bg-slate-200 focus:bg-slate-200 active:bg-slate-300"
|
||||
>
|
||||
<div className="flex w-full flex-col justify-center">
|
||||
<div className="h-22 w-22 my-1 flex items-center justify-center self-center overflow-visible p-1">
|
||||
<Image
|
||||
src={iconPath}
|
||||
alt={`${name}-app-icon`}
|
||||
width={18 * 3}
|
||||
height={18 * 3}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex w-full justify-center">{name}</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
type App = {
|
||||
name: string;
|
||||
icon?: string;
|
||||
};
|
||||
|
||||
const apps = [
|
||||
{
|
||||
name: "Firefox",
|
||||
icon: "firefox.svg",
|
||||
},
|
||||
{
|
||||
name: "Discord",
|
||||
icon: "discord.svg",
|
||||
},
|
||||
{
|
||||
name: "Docs",
|
||||
},
|
||||
{
|
||||
name: "Dochub",
|
||||
icon: "dochub.svg",
|
||||
},
|
||||
{
|
||||
name: "Chess",
|
||||
icon: "chess.svg",
|
||||
},
|
||||
{
|
||||
name: "Games",
|
||||
icon: "games.svg",
|
||||
},
|
||||
{
|
||||
name: "Mail",
|
||||
icon: "mail.svg",
|
||||
},
|
||||
{
|
||||
name: "Public transport",
|
||||
icon: "public-transport.svg",
|
||||
},
|
||||
{
|
||||
name: "Outlook",
|
||||
icon: "mail.svg",
|
||||
},
|
||||
{
|
||||
name: "Youtube",
|
||||
icon: "youtube.svg",
|
||||
},
|
||||
];
|
||||
|
||||
export const AppOverview = () => {
|
||||
return (
|
||||
<DashboardCard title="Applications">
|
||||
<div className="flex h-full w-full justify-center">
|
||||
<div className="flex h-full w-fit justify-center">
|
||||
<div className="grid w-full auto-cols-min auto-rows-min grid-cols-2 gap-8 py-8 sm:grid-cols-3 md:grid-cols-3 xl:grid-cols-4 2xl:grid-cols-5 ">
|
||||
{apps.map((app) => (
|
||||
<AppCard key={app.name} name={app.name} icon={app.icon} />
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</DashboardCard>
|
||||
);
|
||||
};
|
64
pkgs/ui/src/components/dashboard/quickActions/index.tsx
Normal file
@ -0,0 +1,64 @@
|
||||
"use client";
|
||||
import { DashboardCard } from "@/components/card";
|
||||
import { Button, Fab } from "@mui/material";
|
||||
import { MouseEventHandler, ReactNode } from "react";
|
||||
|
||||
import LanIcon from "@mui/icons-material/Lan";
|
||||
import AppsIcon from "@mui/icons-material/Apps";
|
||||
import DevicesIcon from "@mui/icons-material/Devices";
|
||||
|
||||
type Action = {
|
||||
id: string;
|
||||
icon: ReactNode;
|
||||
label: ReactNode;
|
||||
eventHandler: MouseEventHandler<HTMLButtonElement>;
|
||||
};
|
||||
|
||||
export const QuickActions = () => {
|
||||
const actions: Action[] = [
|
||||
{
|
||||
id: "network",
|
||||
icon: <LanIcon sx={{ mr: 1 }} />,
|
||||
label: "Network",
|
||||
eventHandler: (event) => {
|
||||
console.log({ event });
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "apps",
|
||||
icon: <AppsIcon sx={{ mr: 1 }} />,
|
||||
label: "Apps",
|
||||
eventHandler: (event) => {
|
||||
console.log({ event });
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "nodes",
|
||||
icon: <DevicesIcon sx={{ mr: 1 }} />,
|
||||
label: "Devices",
|
||||
eventHandler: (event) => {
|
||||
console.log({ event });
|
||||
},
|
||||
},
|
||||
];
|
||||
return (
|
||||
<DashboardCard title="Quick Actions">
|
||||
<div className="flex h-fit w-full items-center justify-start pt-5 align-bottom">
|
||||
<div className="flex w-full flex-col flex-wrap justify-evenly gap-2 sm:flex-row">
|
||||
{actions.map(({ id, icon, label, eventHandler }) => (
|
||||
<Fab
|
||||
className="w-fit self-center shadow-none"
|
||||
color="secondary"
|
||||
key={id}
|
||||
onClick={eventHandler}
|
||||
variant="extended"
|
||||
>
|
||||
{icon}
|
||||
{label}
|
||||
</Fab>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</DashboardCard>
|
||||
);
|
||||
};
|
56
pkgs/ui/src/components/dashboard/taskQueue/index.tsx
Normal file
@ -0,0 +1,56 @@
|
||||
import { DashboardCard } from "@/components/card";
|
||||
|
||||
import SyncIcon from "@mui/icons-material/Sync";
|
||||
import ScheduleIcon from "@mui/icons-material/Schedule";
|
||||
import DoneIcon from "@mui/icons-material/Done";
|
||||
import { ReactNode } from "react";
|
||||
import { Chip } from "@mui/material";
|
||||
|
||||
const statusMap = {
|
||||
running: <SyncIcon className="animate-bounce" />,
|
||||
done: <DoneIcon />,
|
||||
planned: <ScheduleIcon />,
|
||||
};
|
||||
|
||||
interface TaskEntryProps {
|
||||
status: ReactNode;
|
||||
result: "default" | "error" | "info" | "success" | "warning";
|
||||
task: string;
|
||||
details?: string;
|
||||
}
|
||||
const TaskEntry = (props: TaskEntryProps) => {
|
||||
const { result, task, details, status } = props;
|
||||
return (
|
||||
<>
|
||||
<div className="col-span-1">{status}</div>
|
||||
<div className="col-span-4">{task}</div>
|
||||
<div className="col-span-1">
|
||||
<Chip color={result} label={result} />
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export const TaskQueue = () => {
|
||||
return (
|
||||
<DashboardCard title="Task Queue">
|
||||
<div className="grid grid-cols-6 gap-2 p-4">
|
||||
<TaskEntry
|
||||
result="success"
|
||||
task="Update DevX"
|
||||
status={statusMap.done}
|
||||
/>
|
||||
<TaskEntry
|
||||
result="default"
|
||||
task="Update XYZ"
|
||||
status={statusMap.running}
|
||||
/>
|
||||
<TaskEntry
|
||||
result="default"
|
||||
task="Update ABC"
|
||||
status={statusMap.planned}
|
||||
/>
|
||||
</div>
|
||||
</DashboardCard>
|
||||
);
|
||||
};
|
@ -34,7 +34,7 @@ interface NoDataOverlayProps {
|
||||
export function NoDataOverlay(props: NoDataOverlayProps) {
|
||||
const { label } = props;
|
||||
return (
|
||||
<StyledGridOverlay>
|
||||
<StyledGridOverlay className="block p-2">
|
||||
<svg
|
||||
width="120"
|
||||
height="100"
|
||||
|
@ -1,11 +0,0 @@
|
||||
import { Button } from "@mui/material";
|
||||
|
||||
export const QuickActions = () => {
|
||||
return (
|
||||
<div className="grid-cols-auto gris">
|
||||
<Button>Action 1</Button>
|
||||
<Button>Action 2</Button>
|
||||
<Button>Action 3</Button>
|
||||
</div>
|
||||
);
|
||||
};
|