From 078ba59002b829d2a18830df0565b5af75af65f2 Mon Sep 17 00:00:00 2001 From: mbecker20 Date: Fri, 7 Jun 2024 21:02:28 -0700 Subject: [PATCH] ensure sync directory exist --- bin/core/src/helpers/sync/remote.rs | 5 ++ frontend/src/components/config/util.tsx | 2 +- frontend/src/components/resources/common.tsx | 24 ++++++-- frontend/src/components/resources/index.tsx | 2 +- .../resources/resource-sync/actions.tsx | 57 +++++++++++++++++++ .../{sync => resource-sync}/config.tsx | 0 .../{sync => resource-sync}/index.tsx | 9 +-- .../{sync => resource-sync}/table.tsx | 0 .../src/components/resources/sync/actions.tsx | 0 frontend/src/components/sidebar.tsx | 7 ++- frontend/src/components/topbar.tsx | 6 +- frontend/src/lib/hooks.ts | 1 + frontend/src/lib/socket.tsx | 9 +++ frontend/src/lib/utils.ts | 20 +++++++ frontend/src/pages/resources.tsx | 7 ++- 15 files changed, 135 insertions(+), 14 deletions(-) create mode 100644 frontend/src/components/resources/resource-sync/actions.tsx rename frontend/src/components/resources/{sync => resource-sync}/config.tsx (100%) rename frontend/src/components/resources/{sync => resource-sync}/index.tsx (89%) rename frontend/src/components/resources/{sync => resource-sync}/table.tsx (100%) delete mode 100644 frontend/src/components/resources/sync/actions.tsx diff --git a/bin/core/src/helpers/sync/remote.rs b/bin/core/src/helpers/sync/remote.rs index a0090ab09..8b2d4e651 100644 --- a/bin/core/src/helpers/sync/remote.rs +++ b/bin/core/src/helpers/sync/remote.rs @@ -1,3 +1,5 @@ +use std::fs; + use anyhow::{anyhow, Context}; use monitor_client::entities::{ sync::ResourceSync, to_monitor_name, toml::ResourcesToml, @@ -32,6 +34,9 @@ pub async fn get_remote_resources( .transpose()? .cloned(); + fs::create_dir_all(&config.sync_directory) + .context("failed to create sync directory")?; + let mut logs = git::clone(clone_args, &config.sync_directory, github_token) .await diff --git a/frontend/src/components/config/util.tsx b/frontend/src/components/config/util.tsx index ed299d2a0..af79e1cc8 100644 --- a/frontend/src/components/config/util.tsx +++ b/frontend/src/components/config/util.tsx @@ -217,7 +217,7 @@ export const AccountSelector = ({ > diff --git a/frontend/src/components/resources/common.tsx b/frontend/src/components/resources/common.tsx index 770453580..7034028a3 100644 --- a/frontend/src/components/resources/common.tsx +++ b/frontend/src/components/resources/common.tsx @@ -49,7 +49,11 @@ export const ResourceDescription = ({ const inv = useInvalidate(); const key = - type === "ServerTemplate" ? "server_template" : type.toLowerCase(); + type === "ServerTemplate" + ? "server_template" + : type === "ResourceSync" + ? "sync" + : type.toLowerCase(); const resource = useRead(`Get${type}`, { [key]: id, @@ -244,10 +248,12 @@ export const CopyResource = ({ export const NewResource = ({ type, + readable_type, server_id, build_id, }: { type: UsableResource; + readable_type?: string; server_id?: string; build_id?: string; }) => { @@ -255,7 +261,11 @@ export const NewResource = ({ const { mutateAsync } = useWrite(`Create${type}`); const [name, setName] = useState(""); const type_display = - type === "ServerTemplate" ? "server-template" : type.toLowerCase(); + type === "ServerTemplate" + ? "server-template" + : type === "ResourceSync" + ? "resource-sync" + : type.toLowerCase(); const config = type === "Deployment" ? { @@ -267,7 +277,7 @@ export const NewResource = ({ : {}; return ( { const id = (await mutateAsync({ name, config }))._id?.$oid!; nav(`/${usableResourcePath(type)}/${id}`); @@ -276,7 +286,7 @@ export const NewResource = ({ onOpenChange={() => setName("")} >
- {type} Name + {readable_type ?? type} Name { const nav = useNavigate(); const key = - type === "ServerTemplate" ? "server_template" : type.toLowerCase(); + type === "ServerTemplate" + ? "server_template" + : type === "ResourceSync" + ? "sync" + : type.toLowerCase(); const resource = useRead(`Get${type}`, { [key]: id, } as any).data; diff --git a/frontend/src/components/resources/index.tsx b/frontend/src/components/resources/index.tsx index bffdba18e..77e187418 100644 --- a/frontend/src/components/resources/index.tsx +++ b/frontend/src/components/resources/index.tsx @@ -7,7 +7,7 @@ import { RepoComponents } from "./repo"; import { ServerComponents } from "./server"; import { ProcedureComponents } from "./procedure/index"; import { ServerTemplateComponents } from "./server-template"; -import { ResourceSyncComponents } from "./sync"; +import { ResourceSyncComponents } from "./resource-sync"; export const ResourceComponents: { [key in UsableResource]: RequiredResourceComponents; diff --git a/frontend/src/components/resources/resource-sync/actions.tsx b/frontend/src/components/resources/resource-sync/actions.tsx new file mode 100644 index 000000000..7d33434f7 --- /dev/null +++ b/frontend/src/components/resources/resource-sync/actions.tsx @@ -0,0 +1,57 @@ +import { ConfirmButton } from "@components/util"; +import { useExecute, useInvalidate, useRead, useWrite } from "@lib/hooks"; +import { sync_no_changes } from "@lib/utils"; +import { Loader2, RefreshCcw, SquarePlay } from "lucide-react"; + +export const RefreshSync = ({ id }: { id: string }) => { + const inv = useInvalidate(); + const { mutate, isPending } = useWrite("RefreshResourceSyncPending", { + onSuccess: () => inv(["GetResourceSync", { sync: id }]), + }); + const pending = isPending; + return ( + + ) : ( + + ) + } + onClick={() => mutate({ sync: id })} + disabled={pending} + loading={pending} + /> + ); +}; + +export const ExecuteSync = ({ id }: { id: string }) => { + const { mutate, isPending } = useExecute("RunSync"); + const syncing = useRead( + "GetResourceSyncActionState", + { sync: id }, + { refetchInterval: 5000 } + ).data?.syncing; + const sync = useRead("GetResourceSync", { sync: id }).data; + + if (!sync || sync_no_changes(sync)) return null; + + const pending = isPending || syncing; + + return ( + + ) : ( + + ) + } + onClick={() => mutate({ sync: id })} + disabled={pending} + loading={pending} + /> + ); +}; diff --git a/frontend/src/components/resources/sync/config.tsx b/frontend/src/components/resources/resource-sync/config.tsx similarity index 100% rename from frontend/src/components/resources/sync/config.tsx rename to frontend/src/components/resources/resource-sync/config.tsx diff --git a/frontend/src/components/resources/sync/index.tsx b/frontend/src/components/resources/resource-sync/index.tsx similarity index 89% rename from frontend/src/components/resources/sync/index.tsx rename to frontend/src/components/resources/resource-sync/index.tsx index 77814c443..0fd45792a 100644 --- a/frontend/src/components/resources/sync/index.tsx +++ b/frontend/src/components/resources/resource-sync/index.tsx @@ -9,6 +9,7 @@ import { Types } from "@monitor/client"; import { ResourceSyncConfig } from "./config"; import { useState } from "react"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "@ui/tabs"; +import { ExecuteSync, RefreshSync } from "./actions"; const useResourceSync = (id?: string) => useRead("ListResourceSyncs", {}).data?.find((d) => d.id === id); @@ -44,12 +45,12 @@ export const ResourceSyncComponents: RequiredResourceComponents = { Dashboard: () => { const syncs_count = useRead("ListResourceSyncs", {}).data?.length; return ( - +
- Syncs + Resource Syncs {syncs_count} Total
@@ -60,7 +61,7 @@ export const ResourceSyncComponents: RequiredResourceComponents = { ); }, - New: () => , + New: () => , Table: ({ resources }) => ( @@ -73,7 +74,7 @@ export const ResourceSyncComponents: RequiredResourceComponents = { Info: {}, - Actions: {}, + Actions: { RefreshSync, ExecuteSync }, Page: {}, diff --git a/frontend/src/components/resources/sync/table.tsx b/frontend/src/components/resources/resource-sync/table.tsx similarity index 100% rename from frontend/src/components/resources/sync/table.tsx rename to frontend/src/components/resources/resource-sync/table.tsx diff --git a/frontend/src/components/resources/sync/actions.tsx b/frontend/src/components/resources/sync/actions.tsx deleted file mode 100644 index e69de29bb..000000000 diff --git a/frontend/src/components/sidebar.tsx b/frontend/src/components/sidebar.tsx index b58200d24..e28d5690f 100644 --- a/frontend/src/components/sidebar.tsx +++ b/frontend/src/components/sidebar.tsx @@ -52,7 +52,12 @@ export const Sidebar = () => { {RESOURCE_TARGETS.map((type) => { const RTIcon = ResourceComponents[type].Icon; - const name = type === "ServerTemplate" ? "Template" : type; + const name = + type === "ServerTemplate" + ? "Template" + : type === "ResourceSync" + ? "Sync" + : type; return ( { const [icon, title] = Components ? [ , - (type === "ServerTemplate" ? "Template" : type) + "s", + (type === "ServerTemplate" + ? "Template" + : type === "ResourceSync" + ? "Sync" + : type) + "s", ] : location.pathname === "/" ? [, "Home"] diff --git a/frontend/src/lib/hooks.ts b/frontend/src/lib/hooks.ts index 58e5e6f00..1a7a42ab5 100644 --- a/frontend/src/lib/hooks.ts +++ b/frontend/src/lib/hooks.ts @@ -192,6 +192,7 @@ export const useResourceParamType = () => { const type = useParams().type; if (!type) return undefined; if (type === "server-templates") return "ServerTemplate"; + if (type === "resource-syncs") return "ResourceSync"; return (type[0].toUpperCase() + type.slice(1, -1)) as UsableResource; }; diff --git a/frontend/src/lib/socket.tsx b/frontend/src/lib/socket.tsx index d976a85d6..7ed8bbd35 100644 --- a/frontend/src/lib/socket.tsx +++ b/frontend/src/lib/socket.tsx @@ -137,6 +137,15 @@ const on_message = ( ); } + if (update.target.type === "ResourceSync") { + invalidate( + ["ListResourceSyncs"], + ["GetResourceSync"], + ["GetResourceSyncActionState"], + ["GetResourceSyncsSummary"] + ); + } + if ( update.target.type === "System" && update.operation.includes("Variable") diff --git a/frontend/src/lib/utils.ts b/frontend/src/lib/utils.ts index 03eb76582..727bffe1d 100644 --- a/frontend/src/lib/utils.ts +++ b/frontend/src/lib/utils.ts @@ -22,6 +22,7 @@ export const RESOURCE_TARGETS: UsableResource[] = [ "Builder", "Alerter", "ServerTemplate", + "ResourceSync", ]; export function env_to_text(envVars: Types.EnvironmentVar[] | undefined) { @@ -97,6 +98,7 @@ export const convertTsMsToLocalUnixTsInSecs = (ts: number) => export const usableResourcePath = (resource: UsableResource) => { if (resource === "ServerTemplate") return "server-templates"; + if (resource === "ResourceSync") return "resource-syncs"; return `${resource.toLowerCase()}s`; }; @@ -173,3 +175,21 @@ export const filterBySplit = ( : items) ?? [] ); }; + +export const sync_no_changes = (sync: Types.ResourceSync) => { + const pending = sync.info?.pending; + if (!pending) return false; + return ( + !pending.server_updates?.length && + !pending.deployment_updates?.length && + !pending.build_updates?.length && + !pending.repo_updates?.length && + !pending.procedure_updates?.length && + !pending.alerter_updates?.length && + !pending.builder_updates?.length && + !pending.server_template_updates?.length && + !pending.resource_sync_updates?.length && + !pending.variable_updates?.length && + !pending.user_group_updates?.length + ); +}; diff --git a/frontend/src/pages/resources.tsx b/frontend/src/pages/resources.tsx index 08eb90e76..31ee31737 100644 --- a/frontend/src/pages/resources.tsx +++ b/frontend/src/pages/resources.tsx @@ -14,7 +14,12 @@ import { useState } from "react"; export const Resources = () => { const type = useResourceParamType()!; - const name = type === "ServerTemplate" ? "Server Template" : type; + const name = + type === "ServerTemplate" + ? "Server Template" + : type === "ResourceSync" + ? "Resource Sync" + : type; useSetTitle(name + "s"); const Components = ResourceComponents[type]; const [search, set] = useState("");