+
+
+
-
-
-
- );
-};
-
-const ApiKeysSummary = () => {
- const keys_count = useRead("ListApiKeys", {}).data?.length;
-
- return (
-
-
-
-
-
- Api Keys
- {keys_count} Total
-
-
+
+
-
+
+
+
+
);
diff --git a/frontend/src/pages/home/dashboard2.tsx b/frontend/src/pages/home/dashboard2.tsx
deleted file mode 100644
index e86d4df6f..000000000
--- a/frontend/src/pages/home/dashboard2.tsx
+++ /dev/null
@@ -1,58 +0,0 @@
-import { OpenAlerts } from "@components/alert";
-import { Page } from "@components/layouts";
-import { ResourceComponents } from "@components/resources";
-import { RecentCard } from "@components/resources/common";
-import { AllUpdates } from "@components/updates/resource";
-import { useRead, useUser } from "@lib/hooks";
-import { UsableResource } from "@types";
-import { Separator } from "@ui/separator";
-import { History } from "lucide-react";
-
-export const Dashboard = () => {
- return (
-
-
-
-
-
-
-
-
-
-
- );
-};
-
-const ResourceRow = ({ type }: { type: UsableResource }) => {
- const recents = useUser().data?.[`recent_${type.toLowerCase()}s`]?.slice(
- 0,
- 6
- ) as string[] | undefined;
- const resources = useRead(`List${type}s`, {})
- .data?.filter((r) => !recents?.includes(r.id))
- .map((r) => r.id);
- const ids = [
- ...(recents ?? []),
- ...(resources?.slice(0, 6 - (recents?.length || 0)) ?? []),
- ];
- const Components = ResourceComponents[type];
- return (
-
-
-
-
-
-
-
-
-
Recent {type}s
-
-
- {ids.map((id: string) => (
-
- ))}
-
-
-
- );
-};
diff --git a/frontend/src/pages/home/index.tsx b/frontend/src/pages/home/index.tsx
index 1a4f56cb4..f36de2eda 100644
--- a/frontend/src/pages/home/index.tsx
+++ b/frontend/src/pages/home/index.tsx
@@ -1,6 +1,6 @@
import { homeViewAtom } from "@main";
import { useAtom } from "jotai";
-import { Dashboard } from "./dashboard2";
+import { Dashboard } from "./dashboard";
import { AllResources } from "./all_resources";
import { Tree } from "./tree";
import { useSetTitle } from "@lib/hooks";
diff --git a/frontend/src/pages/updates.tsx b/frontend/src/pages/updates.tsx
index 56df36bc6..ec3148b27 100644
--- a/frontend/src/pages/updates.tsx
+++ b/frontend/src/pages/updates.tsx
@@ -1,9 +1,21 @@
import { Page } from "@components/layouts";
import { ResourceComponents } from "@components/resources";
-import { AddTags, ResourceTags } from "@components/tags";
import { UpdatesTable } from "@components/updates/table";
import { useRead, useResourceParamType, useSetTitle } from "@lib/hooks";
+import { Types } from "@monitor/client";
+import { CaretSortIcon } from "@radix-ui/react-icons";
import { UsableResource } from "@types";
+import {
+ Command,
+ CommandEmpty,
+ CommandGroup,
+ CommandInput,
+ CommandItem,
+ CommandList,
+} from "@ui/command";
+import { Popover, PopoverContent, PopoverTrigger } from "@ui/popover";
+import { SearchX } from "lucide-react";
+import { useState } from "react";
import { useParams } from "react-router-dom";
export const Updates = () => {
@@ -18,10 +30,16 @@ export const Updates = () => {
const AllUpdates = () => {
useSetTitle("Updates");
- const updates = useRead("ListUpdates", {}).data;
+ const [operation, setOperation] = useState
();
+ const updates = useRead("ListUpdates", { query: { operation } }).data;
return (
-
-
+
+ }
+ >
+
);
};
@@ -35,24 +53,141 @@ const ResourceUpdates = ({
}) => {
const name = useRead(`List${type}s`, {}).data?.find((r) => r.id === id)?.name;
useSetTitle(name && `${name} | Updates`);
+ const [operation, setOperation] = useState();
const updates = useRead("ListUpdates", {
query: {
"target.type": type,
"target.id": id,
+ operation,
},
}).data;
const Components = ResourceComponents[type];
return (
}
- titleRight={
-
+ titleRight={Updates
}
+ icon={}
+ actions={
+
}
>
);
};
+
+const OPERATIONS_BY_RESOURCE: { [key: string]: Types.Operation[] } = {
+ Server: [
+ Types.Operation.CreateServer,
+ Types.Operation.UpdateServer,
+ Types.Operation.RenameServer,
+ Types.Operation.PruneImagesServer,
+ Types.Operation.PruneContainersServer,
+ Types.Operation.PruneNetworksServer,
+ Types.Operation.CreateNetwork,
+ Types.Operation.DeleteNetwork,
+ Types.Operation.StopAllContainers,
+ ],
+ Deployment: [
+ Types.Operation.CreateDeployment,
+ Types.Operation.UpdateDeployment,
+ Types.Operation.RenameDeployment,
+ Types.Operation.DeployContainer,
+ Types.Operation.StopContainer,
+ Types.Operation.StartContainer,
+ Types.Operation.RemoveContainer,
+ ],
+ Build: [
+ Types.Operation.CreateBuild,
+ Types.Operation.UpdateBuild,
+ Types.Operation.RunBuild,
+ Types.Operation.CancelBuild,
+ ],
+ Repo: [
+ Types.Operation.CreateRepo,
+ Types.Operation.UpdateRepo,
+ Types.Operation.CloneRepo,
+ Types.Operation.PullRepo,
+ ],
+ Procedure: [
+ Types.Operation.CreateProcedure,
+ Types.Operation.UpdateProcedure,
+ Types.Operation.RunProcedure,
+ ],
+ Builder: [Types.Operation.CreateBuilder, Types.Operation.UpdateBuilder],
+ Alerter: [Types.Operation.CreateAlerter, Types.Operation.UpdateAlerter],
+ ServerTemplate: [
+ Types.Operation.CreateServerTemplate,
+ Types.Operation.UpdateServerTemplate,
+ Types.Operation.LaunchServer,
+ ],
+};
+
+const OperationSelector = ({
+ selected,
+ onSelect,
+ options = Object.values(Types.Operation).filter(
+ (o) => o !== Types.Operation.None
+ ),
+}: {
+ selected: Types.Operation | undefined;
+ onSelect: (operation: Types.Operation | undefined) => void;
+ options?: Types.Operation[];
+}) => {
+ const [open, setOpen] = useState(false);
+ const [input, setInput] = useState("");
+ return (
+
+
+
+ {selected ?? "Select Operation"}
+
+
+
+
+
+
+
+
+ No Operations Found
+
+
+
+
+ {
+ onSelect(undefined);
+ setOpen(false);
+ }}
+ >
+ All
+
+
+ {options.map((operation) => (
+ {
+ onSelect(operation);
+ setOpen(false);
+ }}
+ >
+ {operation}
+
+ ))}
+
+
+
+
+
+ );
+};