diff --git a/pkgs/theme/index.html b/pkgs/theme/index.html index 35eadad0..d20d8d4e 100644 --- a/pkgs/theme/index.html +++ b/pkgs/theme/index.html @@ -26,7 +26,43 @@
+ neutral2 +
+
+ neutral5 +
+
+ neutral8 +
+
- neutral51 + neutral54
+ neutral92 +
+
+ neutral95 +
+
+
+ green0 +
+
+ green2 +
+
+ green10 +
+
+ green20 +
+
+ green30 +
+
+ green40 +
+
+ green50 +
+
+ green60 +
+
+ green70 +
+
+ green72 +
+
+ green80 +
+
+ green90 +
+
+ green98 +
+
+ green100 +
+
+
+
+ yellow0 +
+
+ yellow2 +
+
+ yellow10 +
+
+ yellow20 +
+
+ yellow30 +
+
+ yellow40 +
+
+ yellow50 +
+
+ yellow60 +
+
+ yellow70 +
+
+ yellow80 +
+
+ yellow87 +
+
+ yellow90 +
+
+ yellow98 +
+
+ yellow100 +
+
+
+
+ purple0 +
+
+ purple2 +
+
+ purple10 +
+
+ purple20 +
+
+ purple30 +
+
+ purple33 +
+
+ purple40 +
+
+ purple50 +
+
+ purple60 +
+
+ purple70 +
+
+ purple80 +
+
+ purple90 +
+
+ purple98 +
+
+ purple100 +
+
-
- green0 -
-
- green10 -
-
- green20 -
-
- green30 -
-
- green40 -
-
- green50 -
-
- green60 -
-
- green70 -
-
- green72 -
-
- green80 -
-
- green90 -
-
- green98 -
-
- green100 -
-
-
-
- yellow0 -
-
- yellow10 -
-
- yellow20 -
-
- yellow30 -
-
- yellow40 -
-
- yellow50 -
-
- yellow60 -
-
- yellow70 -
-
- yellow80 -
-
- yellow87 -
-
- yellow90 -
-
- yellow98 -
-
- yellow100 -
-
-
-
- purple0 -
-
- purple10 -
-
- purple20 -
-
- purple30 -
-
- purple33 -
-
- purple40 -
-
- purple50 -
-
- purple60 -
-
- purple70 -
-
- purple80 -
-
- purple90 -
-
- purple100 -
-
+ blue5 +
-
+
-
- - - {children} -
+
{children}
diff --git a/pkgs/ui/src/app/machines/layout.tsx b/pkgs/ui/src/app/machines/layout.tsx index 474a3f51..25ae7320 100644 --- a/pkgs/ui/src/app/machines/layout.tsx +++ b/pkgs/ui/src/app/machines/layout.tsx @@ -10,7 +10,7 @@ export default function Layout({ children }: { children: React.ReactNode }) { <> {!clanDir &&
No clan selected
} {clanDir && ( - + {children} )} diff --git a/pkgs/ui/src/app/theme/themes.ts b/pkgs/ui/src/app/theme/themes.ts index 13e7af16..1a9beaaf 100644 --- a/pkgs/ui/src/app/theme/themes.ts +++ b/pkgs/ui/src/app/theme/themes.ts @@ -21,19 +21,19 @@ const commonOptions: Partial = { const commonPalette: Partial = { primary: { - main: palette.green50.value, + main: palette.blue50.value, }, secondary: { - main: palette.green50.value, + main: palette.green60.value, }, info: { main: palette.blue50.value, }, success: { - main: palette.green50.value, + main: palette.green60.value, }, warning: { - main: palette.yellow50.value, + main: palette.yellow80.value, }, error: { main: palette.red50.value, diff --git a/pkgs/ui/src/components/card/index.tsx b/pkgs/ui/src/components/card/index.tsx index 6a16b3e1..ae5355ab 100644 --- a/pkgs/ui/src/components/card/index.tsx +++ b/pkgs/ui/src/components/card/index.tsx @@ -8,13 +8,9 @@ interface DashboardCardProps { const DashboardCard = (props: DashboardCardProps) => { const { children, title } = props; return ( -
+
- + {title} {children} diff --git a/pkgs/ui/src/components/dashboard/appOverview/index.tsx b/pkgs/ui/src/components/dashboard/appOverview/index.tsx index a6148b2e..c1fc5c1d 100644 --- a/pkgs/ui/src/components/dashboard/appOverview/index.tsx +++ b/pkgs/ui/src/components/dashboard/appOverview/index.tsx @@ -13,7 +13,7 @@ const AppCard = (props: AppCardProps) => {
diff --git a/pkgs/ui/src/components/dashboard/quickActions/index.tsx b/pkgs/ui/src/components/dashboard/quickActions/index.tsx index b303e9a4..1340007d 100644 --- a/pkgs/ui/src/components/dashboard/quickActions/index.tsx +++ b/pkgs/ui/src/components/dashboard/quickActions/index.tsx @@ -48,7 +48,7 @@ export const QuickActions = () => { {actions.map(({ id, icon, label, eventHandler }) => ( = { + [P in K]?: T; }; -type Filters = Filter[]; -type MachineContextType = - | { - rawData: AxiosResponse | undefined; - data: Machine[]; - isLoading: boolean; - flakeName: string; - error: AxiosError | undefined; - isValidating: boolean; +export type MachineFilter = PartialRecord< + keyof Machine, + Machine[keyof Machine] +>; - filters: Filters; - setFilters: Dispatch>; - mutate: KeyedMutator>; - swrKey: string | false | Record; - } - | { - isLoading: true; - data: readonly []; - }; +type MachineContextType = { + rawData: AxiosResponse | undefined; + data: Machine[]; + isLoading: boolean; + error: AxiosError | undefined; + isValidating: boolean; -const initialState = { - isLoading: true, - data: [], -} as const; + filters: MachineFilter; + setFilters: Dispatch>; + mutate: KeyedMutator>; + swrKey: string | false | Record; +}; export function CreateMachineContext() { - return createContext({ - ...initialState, - }); + return createContext({} as MachineContextType); } interface MachineContextProviderProps { children: ReactNode; - flakeName: string; + clanDir: string; } const MachineContext = CreateMachineContext(); export const MachineContextProvider = (props: MachineContextProviderProps) => { - const { children, flakeName } = props; + const { children, clanDir } = props; const { data: rawData, isLoading, @@ -65,18 +57,27 @@ export const MachineContextProvider = (props: MachineContextProviderProps) => { isValidating, mutate, swrKey, - } = useListMachines({ flake_dir: flakeName }); - const [filters, setFilters] = useState([]); + } = useListMachines({ flake_dir: clanDir }); + + const [filters, setFilters] = useState({}); + + useEffect(() => { + if (error) { + clanErrorToast(error); + } + }, [error]); const data = useMemo(() => { - if (!isLoading && !error && !isValidating && rawData) { + if (!isLoading && rawData) { const { machines } = rawData.data; - return machines.filter((m) => - filters.every((f) => m[f.name] === f.value), + return machines.filter( + (m) => + !filters.name || + m.name.toLowerCase().includes(filters.name.toLowerCase()), ); } return []; - }, [isLoading, error, isValidating, rawData, filters]); + }, [isLoading, filters, rawData]); return ( { data, isLoading, - flakeName, + error, isValidating, diff --git a/pkgs/ui/src/components/sidebar/index.tsx b/pkgs/ui/src/components/sidebar/index.tsx index 8e801f09..2bdea6ee 100644 --- a/pkgs/ui/src/components/sidebar/index.tsx +++ b/pkgs/ui/src/components/sidebar/index.tsx @@ -13,13 +13,10 @@ import { ReactNode } from "react"; import { tw } from "@/utils/tailwind"; import AppsIcon from "@mui/icons-material/Apps"; import BackupIcon from "@mui/icons-material/Backup"; -import DashboardIcon from "@mui/icons-material/Dashboard"; -import DesignServicesIcon from "@mui/icons-material/DesignServices"; -import DevicesIcon from "@mui/icons-material/Devices"; -import LanIcon from "@mui/icons-material/Lan"; -import Link from "next/link"; - import ChevronLeftIcon from "@mui/icons-material/ChevronLeft"; +import DashboardIcon from "@mui/icons-material/Dashboard"; +import DevicesIcon from "@mui/icons-material/Devices"; +import Link from "next/link"; type MenuEntry = { icon: ReactNode; @@ -49,24 +46,24 @@ const menuEntries: MenuEntry[] = [ to: "/applications", disabled: true, }, - { - icon: , - label: "Network", - to: "/network", - disabled: true, - }, - { - icon: , - label: "Templates", - to: "/templates", - disabled: false, - }, { icon: , label: "Backups", to: "/backups", disabled: true, }, + // { + // icon: , + // label: "Network", + // to: "/network", + // disabled: true, + // }, + // { + // icon: , + // label: "Templates", + // to: "/templates", + // disabled: false, + // }, ]; const hideSidebar = tw`-translate-x-14 lg:-translate-x-64`; @@ -75,38 +72,35 @@ const showSidebar = tw`lg:translate-x-0`; interface SidebarProps { show: boolean; onClose: () => void; - clanSelect: React.ReactNode; } export function Sidebar(props: SidebarProps) { - const { show, onClose, clanSelect } = props; + const { show, onClose } = props; return ( diff --git a/pkgs/ui/src/components/table/enhancedTableToolbar.tsx b/pkgs/ui/src/components/table/enhancedTableToolbar.tsx deleted file mode 100644 index 2210f8f7..00000000 --- a/pkgs/ui/src/components/table/enhancedTableToolbar.tsx +++ /dev/null @@ -1,82 +0,0 @@ -"use client"; - -import React, { useMemo } from "react"; -import Box from "@mui/material/Box"; -import Grid2 from "@mui/material/Unstable_Grid2"; -import useMediaQuery from "@mui/material/useMediaQuery"; -import { useTheme } from "@mui/material"; - -import { PieCards } from "./pieCards"; -import { PieData, NodePieChart } from "./nodePieChart"; -import { Machine } from "@/api/model/machine"; -import { Status } from "@/api/model"; - -interface EnhancedTableToolbarProps { - tableData: readonly Machine[]; -} - -export function EnhancedTableToolbar( - props: React.PropsWithChildren, -) { - const { tableData } = props; - const theme = useTheme(); - const is_lg = useMediaQuery(theme.breakpoints.down("lg")); - - const pieData: PieData[] = useMemo(() => { - const online = tableData.filter( - (row) => row.status === Status.online, - ).length; - const offline = tableData.filter( - (row) => row.status === Status.offline, - ).length; - const pending = tableData.filter( - (row) => row.status === Status.unknown, - ).length; - - return [ - { name: "Online", value: online, color: theme.palette.success.main }, - { name: "Offline", value: offline, color: theme.palette.error.main }, - { name: "Pending", value: pending, color: theme.palette.warning.main }, - ]; - }, [tableData, theme]); - - return ( - - {/* Pie Chart Grid */} - - - - - - - {/* Card Stack Grid */} - - - - - {/*Toolbar Grid */} - - {props.children} - - - ); -} diff --git a/pkgs/ui/src/components/table/nodeTable.tsx b/pkgs/ui/src/components/table/nodeTable.tsx index afc7802a..7e90b6ea 100644 --- a/pkgs/ui/src/components/table/nodeTable.tsx +++ b/pkgs/ui/src/components/table/nodeTable.tsx @@ -1,38 +1,21 @@ "use client"; -import { CircularProgress, Grid, useTheme } from "@mui/material"; +import { CircularProgress, Grid } from "@mui/material"; import Box from "@mui/material/Box"; import Paper from "@mui/material/Paper"; import TablePagination from "@mui/material/TablePagination"; -import useMediaQuery from "@mui/material/useMediaQuery"; -import { ChangeEvent, useMemo, useState } from "react"; +import { ChangeEvent, useState } from "react"; -import { Machine } from "@/api/model/machine"; -import Grid2 from "@mui/material/Unstable_Grid2/Grid2"; import { useMachines } from "../hooks/useMachines"; -import { EnhancedTableToolbar } from "./enhancedTableToolbar"; import { NodeTableContainer } from "./nodeTableContainer"; import { SearchBar } from "./searchBar"; -import { StickySpeedDial } from "./stickySpeedDial"; export function NodeTable() { - const { isLoading, data: machines } = useMachines(); - - const theme = useTheme(); - const is_xs = useMediaQuery(theme.breakpoints.only("xs")); + const { isLoading, data: machines, rawData, setFilters } = useMachines(); const [selected, setSelected] = useState(undefined); const [page, setPage] = useState(0); const [rowsPerPage, setRowsPerPage] = useState(5); - const [filteredList, setFilteredList] = useState([]); - - const tableData = useMemo(() => { - const tableData = machines.map((machine) => { - return { name: machine.name, status: machine.status }; - }); - setFilteredList(tableData); - return tableData; - }, [machines]); const handleChangePage = (event: unknown, newPage: number) => { setPage(newPage); @@ -60,19 +43,13 @@ export function NodeTable() { return ( - - - - - - - - + + - {/* TODO: This creates the error Warning: Prop `id` did not match. Server: ":RspmmcqH1:" Client: ":R3j6qpj9H1:" */} >; + allData: Machine[]; + setQuery: Dispatch>; } export function SearchBar(props: SearchBarProps) { - const { tableData, setFilteredList } = props; + const { allData, setQuery } = props; const [search, setSearch] = useState(""); const debouncedSearch = useDebounce(search, 250); const [open, setOpen] = useState(false); @@ -22,7 +23,6 @@ export function SearchBar(props: SearchBarProps) { function handleEsc(event: React.KeyboardEvent) { if (event.key === "Escape") { setSearch(""); - setFilteredList(tableData); } // check if the key is Enter @@ -32,32 +32,21 @@ export function SearchBar(props: SearchBarProps) { } useEffect(() => { - if (debouncedSearch) { - const filtered: Machine[] = tableData.filter((row) => { - return row.name.toLowerCase().includes(debouncedSearch.toLowerCase()); - }); - setFilteredList(filtered); - } - }, [debouncedSearch, tableData, setFilteredList]); + setQuery((filters) => ({ ...filters, name: debouncedSearch })); + }, [debouncedSearch, setQuery]); const handleInputChange = (event: any, value: string) => { - if (value === "") { - setFilteredList(tableData); - } - + console.log({ value }); setSearch(value); }; - const suggestions = useMemo( - () => tableData.map((row) => row.name), - [tableData], - ); + const options = useMemo(() => allData.map((row) => row.name), [allData]); return ( { return (
  • diff --git a/pkgs/ui/tailwind.config.js b/pkgs/ui/tailwind.config.js index 16f2026a..216951f7 100644 --- a/pkgs/ui/tailwind.config.js +++ b/pkgs/ui/tailwind.config.js @@ -36,6 +36,7 @@ module.exports = { white: common.white.value, black: common.black.value, neutral: getTailwindColors(palette)("neutral"), + blue: getTailwindColors(palette)("blue"), purple: { ...getTailwindColors(palette)("purple"), DEFAULT: palette.purple50.value,