From a8ff6c7b3f83c6c41a72462b065500f9116fedcf Mon Sep 17 00:00:00 2001 From: Nicholas Penree Date: Sat, 21 Dec 2024 11:03:41 -0500 Subject: [PATCH 1/3] feat(updates): new update UI --- .../settings/web-server/update-server.tsx | 201 +++++++++++++----- .../settings/web-server/update-webserver.tsx | 4 +- apps/dokploy/components/layouts/navbar.tsx | 4 +- apps/dokploy/server/api/routers/settings.ts | 4 +- 4 files changed, 158 insertions(+), 55 deletions(-) diff --git a/apps/dokploy/components/dashboard/settings/web-server/update-server.tsx b/apps/dokploy/components/dashboard/settings/web-server/update-server.tsx index 1b8798e4..1bb240bb 100644 --- a/apps/dokploy/components/dashboard/settings/web-server/update-server.tsx +++ b/apps/dokploy/components/dashboard/settings/web-server/update-server.tsx @@ -3,38 +3,49 @@ import { Button } from "@/components/ui/button"; import { Dialog, DialogContent, - DialogDescription, - DialogHeader, DialogTitle, DialogTrigger, } from "@/components/ui/dialog"; import { api } from "@/utils/api"; -import { RefreshCcw } from "lucide-react"; +import { + Bug, + Download, + Info, + RefreshCcw, + Server, + Sparkles, + Stars, +} from "lucide-react"; import Link from "next/link"; import { useState } from "react"; import { toast } from "sonner"; -import { UpdateWebServer } from "./update-webserver"; import { ToggleAutoCheckUpdates } from "./toggle-auto-check-updates"; +import { UpdateWebServer } from "./update-webserver"; export const UpdateServer = () => { - const [isUpdateAvailable, setIsUpdateAvailable] = useState( - null, - ); + const [hasCheckedUpdate, setHasCheckedUpdate] = useState(false); + const [isUpdateAvailable, setIsUpdateAvailable] = useState(false); const { mutateAsync: getUpdateData, isLoading } = api.settings.getUpdateData.useMutation(); + const { data: dokployVersion } = api.settings.getDokployVersion.useQuery(); const [isOpen, setIsOpen] = useState(false); + const [latestVersion, setLatestVersion] = useState(""); const handleCheckUpdates = async () => { try { - const { updateAvailable, latestVersion } = await getUpdateData(); - setIsUpdateAvailable(updateAvailable); - if (updateAvailable) { - toast.success(`${latestVersion} update is available!`); + const updateData = await getUpdateData(); + setHasCheckedUpdate(true); + setIsUpdateAvailable(updateData.updateAvailable); + setLatestVersion(updateData.latestVersion || ""); + + if (updateData.updateAvailable) { + toast.success(`${updateData.latestVersion || ""} update is available!`); } else { toast.info("No updates available"); } } catch (error) { console.error("Error checking for updates:", error); + setHasCheckedUpdate(true); setIsUpdateAvailable(false); toast.error( "An error occurred while checking for updates, please try again.", @@ -45,59 +56,147 @@ export const UpdateServer = () => { return ( - - - - Web Server Update - - Check new releases and update your dokploy - - + +
+ + Web Server Update + + {dokployVersion && ( +
+ + {dokployVersion} +
+ )} +
-
- - We suggest to update your dokploy to the latest version only if you: - -
    -
  • Want to try the latest features
  • -
  • Some bug that is blocking to use some features
  • -
- - We recommend checking the latest version for any breaking changes - before updating. Go to{" "} - - Dokploy Releases - {" "} - to check the latest version. - + {/* Initial state */} + {!hasCheckedUpdate && ( +
+

+ Check for new releases and update Dokploy. +
+
+ We recommend checking for updates regularly to ensure you have the + latest features and security improvements. +

+
+ )} -
- - {isUpdateAvailable === false && ( -
- - - You are using the latest version + {/* Update available state */} + {isUpdateAvailable && latestVersion && ( +
+
+
+ + + + + + + New version available:
- )} + + {latestVersion} + +
+ +
+

+ A new version of the server software is available. Consider + updating if you: +

+
    +
  • + + + Want to access the latest features and improvements + +
  • +
  • + + + Are experiencing issues that may be resolved in the new + version + +
  • +
+
+
+ )} + + {/* Up to date state */} + {hasCheckedUpdate && !isUpdateAvailable && !isLoading && ( +
+
+
+ +
+
+

+ You are using the latest version +

+

+ Your server is up to date with all the latest features and + security improvements. +

+
+
+
+ )} + + {isUpdateAvailable && ( +
+
+ +
+ We recommend reviewing the{" "} + + release notes + {" "} + for any breaking changes before updating. +
+
+
+ )} + +
+ +
+ +
+
+ {isUpdateAvailable ? ( ) : ( )}
@@ -106,3 +205,5 @@ export const UpdateServer = () => {
); }; + +export default UpdateServer; diff --git a/apps/dokploy/components/dashboard/settings/web-server/update-webserver.tsx b/apps/dokploy/components/dashboard/settings/web-server/update-webserver.tsx index 9b3c89f6..c1e5de70 100644 --- a/apps/dokploy/components/dashboard/settings/web-server/update-webserver.tsx +++ b/apps/dokploy/components/dashboard/settings/web-server/update-webserver.tsx @@ -11,6 +11,7 @@ import { } from "@/components/ui/alert-dialog"; import { Button } from "@/components/ui/button"; import { api } from "@/utils/api"; +import { HardDriveDownload } from "lucide-react"; import { toast } from "sonner"; interface Props { @@ -21,7 +22,7 @@ export const UpdateWebServer = ({ isNavbar }: Props) => { const { mutateAsync: updateServer, isLoading } = api.settings.updateServer.useMutation(); - const buttonLabel = isNavbar ? "Update available" : "Update server"; + const buttonLabel = isNavbar ? "Update available" : "Update Server"; const handleConfirm = async () => { try { @@ -49,6 +50,7 @@ export const UpdateWebServer = ({ isNavbar }: Props) => { variant={isNavbar ? "outline" : "secondary"} isLoading={isLoading} > + {!isLoading && } {!isLoading && ( diff --git a/apps/dokploy/components/layouts/navbar.tsx b/apps/dokploy/components/layouts/navbar.tsx index 3d17b3e9..1a7da0ea 100644 --- a/apps/dokploy/components/layouts/navbar.tsx +++ b/apps/dokploy/components/layouts/navbar.tsx @@ -12,11 +12,11 @@ import { api } from "@/utils/api"; import { HeartIcon } from "lucide-react"; import Link from "next/link"; import { useRouter } from "next/router"; +import { useEffect, useRef, useState } from "react"; +import { UpdateWebServer } from "../dashboard/settings/web-server/update-webserver"; import { Logo } from "../shared/logo"; import { Avatar, AvatarFallback, AvatarImage } from "../ui/avatar"; import { buttonVariants } from "../ui/button"; -import { useEffect, useRef, useState } from "react"; -import { UpdateWebServer } from "../dashboard/settings/web-server/update-webserver"; const AUTO_CHECK_UPDATES_INTERVAL_MINUTES = 15; diff --git a/apps/dokploy/server/api/routers/settings.ts b/apps/dokploy/server/api/routers/settings.ts index 937c93d3..e30cee4a 100644 --- a/apps/dokploy/server/api/routers/settings.ts +++ b/apps/dokploy/server/api/routers/settings.ts @@ -12,6 +12,7 @@ import { } from "@/server/db/schema"; import { removeJob, schedule } from "@/server/utils/backup"; import { + DEFAULT_UPDATE_DATA, IS_CLOUD, canAccessToTraefikFiles, cleanStoppedContainers, @@ -25,6 +26,7 @@ import { findAdminById, findServerById, getDokployImage, + getUpdateData, initializeTraefik, logRotationManager, parseRawConfig, @@ -45,14 +47,12 @@ import { stopService, stopServiceRemote, updateAdmin, - getUpdateData, updateLetsEncryptEmail, updateServerById, updateServerTraefik, writeConfig, writeMainConfig, writeTraefikConfigInPath, - DEFAULT_UPDATE_DATA, } from "@dokploy/server"; import { checkGPUStatus, setupGPUSupport } from "@dokploy/server"; import { generateOpenApiDocument } from "@dokploy/trpc-openapi"; From d08530d4516945a0bc77602fe9d213f8fcda08da Mon Sep 17 00:00:00 2001 From: Nicholas Penree Date: Sat, 21 Dec 2024 12:22:01 -0500 Subject: [PATCH 2/3] feat(updates): clean up light mode --- .../web-server/toggle-auto-check-updates.tsx | 3 +- .../settings/web-server/update-server.tsx | 59 +++++++++++++------ 2 files changed, 43 insertions(+), 19 deletions(-) diff --git a/apps/dokploy/components/dashboard/settings/web-server/toggle-auto-check-updates.tsx b/apps/dokploy/components/dashboard/settings/web-server/toggle-auto-check-updates.tsx index 5c07d5df..fb3776b1 100644 --- a/apps/dokploy/components/dashboard/settings/web-server/toggle-auto-check-updates.tsx +++ b/apps/dokploy/components/dashboard/settings/web-server/toggle-auto-check-updates.tsx @@ -2,7 +2,7 @@ import { Label } from "@/components/ui/label"; import { Switch } from "@/components/ui/switch"; import { useState } from "react"; -export const ToggleAutoCheckUpdates = () => { +export const ToggleAutoCheckUpdates = ({ disabled }: { disabled: boolean }) => { const [enabled, setEnabled] = useState( localStorage.getItem("enableAutoCheckUpdates") === "true", ); @@ -18,6 +18,7 @@ export const ToggleAutoCheckUpdates = () => { checked={enabled} onCheckedChange={handleToggle} id="autoCheckUpdatesToggle" + disabled={disabled} />