Revert "feat: expand v2 beta guidance"

This reverts commit 7ba04f8019.

Co-authored-by: ajnart <49837342+ajnart@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot]andajnart authored and GitHub committed 2026-09-10 08:17:12 +00:00
1 parent 1544e6ae1a
commit fe8414c4f2
9 files changed
+124 -264

No files matched your search

@@ -1,79 +0,0 @@
"use client";
import { useState } from "react";
import { Alert, Button, Group, Stack } from "@mantine/core";
import { IconAlertTriangle, IconDownload } from "@tabler/icons-react";
import { useScopedI18n } from "@homarr/translation/client";
import { DangerousActionConfirmation } from "./dangerous-action-confirmation";
export const BackupExportButton = () => {
const t = useScopedI18n("management.page.tool.backup.export");
const [loading, setLoading] = useState(false);
const [error, setError] = useState<string | null>(null);
const [showConfirm, setShowConfirm] = useState(false);
const handleExport = async () => {
setLoading(true);
setError(null);
try {
const response = await fetch("/api/backup/export");
if (!response.ok) {
const errorMessage = await response.json().then(
(data) => data.error,
() => `Server returned ${response.status}`,
);
throw new Error(errorMessage ?? t("error"));
}
const blob = await response.blob();
const url = URL.createObjectURL(blob);
const filename =
response.headers.get("Content-Disposition")?.match(/filename="(.+)"/)?.[1] ?? "homarr-backup.zip";
const anchor = document.createElement("a");
anchor.href = url;
anchor.download = filename;
anchor.click();
URL.revokeObjectURL(url);
setShowConfirm(false);
} catch (cause) {
setError(cause instanceof Error ? cause.message : t("error"));
} finally {
setLoading(false);
}
};
return (
<Stack gap="sm">
{error && (
<Alert color="red" icon={<IconAlertTriangle size={16} />}>
{error}
</Alert>
)}
{showConfirm ? (
<DangerousActionConfirmation
title={t("confirm.title")}
warningTitle={t("confirm.warningTitle")}
warningBody={t("confirm.warningBody")}
typePrompt={t("confirm.typePrompt", { phrase: "I understand" })}
submitLabel={t("confirm.submit")}
submitIcon={<IconDownload size={16} />}
cancelLabel={t("confirm.cancel")}
onConfirm={handleExport}
onCancel={() => setShowConfirm(false)}
disabled={loading}
color="orange"
/>
) : (
<Group>
<Button leftSection={<IconDownload size={16} />} loading={loading} onClick={() => setShowConfirm(true)}>
{t("button")}
</Button>
</Group>
)}
</Stack>
);
};
@@ -1,4 +1,3 @@
export { BackupExportButton } from "./backup-export-button";
export { DatabaseRestoreFlow } from "./database-restore-flow";
export { DangerousActionConfirmation } from "./dangerous-action-confirmation";
export type { BackupAnalysis, RestoreStep } from "./types";
@@ -50,6 +50,11 @@
transform: rotate(5deg);
}
.featureCard {
height: 100%;
background: light-dark(var(--mantine-color-white), var(--mantine-color-dark-7));
}
.diffViewer {
overflow: hidden;
}
@@ -1,10 +1,8 @@
"use client";
import type { ReactNode } from "react";
import { useState } from "react";
import {
ActionIcon,
Accordion,
Alert,
Box,
Button,
@@ -24,7 +22,6 @@ import {
IconBrandGithub,
IconCheck,
IconCopy,
IconDatabaseExport,
IconExternalLink,
IconHeartHandshake,
IconRobot,
@@ -37,7 +34,6 @@ import {
import { setClientCookie } from "@homarr/common";
import { createModal, useModalAction } from "@homarr/modals";
import { BackupExportButton } from "~/components/backup";
import { discordInviteUrl, v2BetaBlogUrl, v2BetaDiscussionUrl, v2BetaFeedbackUrl, v2BetaPreviewUrl } from "./constants";
import classes from "./v2-beta-announcement.module.css";
@@ -58,7 +54,7 @@ const composeDiffLines = [
{ kind: "context", value: " - homarr-v2:/appdata" },
{ kind: "context", value: " environment:" },
{ kind: "context", value: " SECRET_ENCRYPTION_KEY: <SECRET_KEY>" },
{ kind: "added", value: "+ WORKSHOP_API_URL: https://v2.preview.homarr.dev/ # Only during the beta" },
{ kind: "context", value: " WORKSHOP_API_URL: https://v2.preview.homarr.dev/ # Only during the beta" },
{ kind: "context", value: "" },
{ kind: "context", value: " volumes:" },
{ kind: "context", value: " homarr-v2:" },
@@ -80,12 +76,11 @@ volumes:
`;
interface V2BetaAnnouncementProps {
canExportBackup: boolean;
dismissalCookieName: string;
onDismiss: () => void;
}
export const V2BetaAnnouncement = ({ canExportBackup, dismissalCookieName, onDismiss }: V2BetaAnnouncementProps) => {
export const V2BetaAnnouncement = ({ dismissalCookieName, onDismiss }: V2BetaAnnouncementProps) => {
const { openModal } = useModalAction(V2BetaAnnouncementModal);
const dismiss = () => {
@@ -112,7 +107,7 @@ export const V2BetaAnnouncement = ({ canExportBackup, dismissalCookieName, onDis
</Box>
<Group gap={6} wrap="nowrap">
<Button variant="white" color="red" size="compact-sm" onClick={() => openModal({ canExportBackup })}>
<Button variant="white" color="red" size="compact-sm" onClick={() => openModal(undefined)}>
Explore v2
</Button>
<ActionIcon variant="subtle" color="white" onClick={dismiss} aria-label="Dismiss the v2 beta announcement">
@@ -124,12 +119,8 @@ export const V2BetaAnnouncement = ({ canExportBackup, dismissalCookieName, onDis
);
};
interface V2BetaAnnouncementModalProps {
canExportBackup: boolean;
}
const V2BetaAnnouncementModal = createModal<V2BetaAnnouncementModalProps>(({ innerProps }) => {
const [openedSection, setOpenedSection] = useState<string | null>("workshop");
const V2BetaAnnouncementModal = createModal<void>(() => {
const { openModal: openInstallModal } = useModalAction(V2BetaInstallModal);
return (
<Stack gap="lg">
@@ -143,51 +134,27 @@ const V2BetaAnnouncementModal = createModal<V2BetaAnnouncementModalProps>(({ inn
</Stack>
</Paper>
<Accordion variant="separated" radius="md" value={openedSection} onChange={setOpenedSection}>
<FeatureAccordionItem value="workshop" icon={<IconBrandCss3 size={20} />} title="Homarr Workshop">
<SimpleGrid cols={{ base: 1, sm: 2 }} spacing="md">
<FeatureCard icon={<IconBrandCss3 size={21} />} title="Homarr Workshop">
Share and discover Custom Widgets and CSS made by the Homarr community.
</FeatureAccordionItem>
<FeatureAccordionItem
value="drag-and-drop"
icon={<IconArrowsMove size={20} />}
title="Complete drag-and-drop rewrite"
>
</FeatureCard>
<FeatureCard icon={<IconArrowsMove size={21} />} title="Complete drag-and-drop rewrite">
Move, resize, multi-select, and arrange your dashboard with a board editor rebuilt from the ground up.
</FeatureAccordionItem>
<FeatureAccordionItem value="custom-widgets" icon={<IconWand size={20} />} title="Custom Widgets v2">
</FeatureCard>
<FeatureCard icon={<IconWand size={21} />} title="Custom Widgets v2">
We think you can make almost any widget with live previews, API requests, options, actions, and validation.
</FeatureAccordionItem>
<FeatureAccordionItem value="assistant" icon={<IconRobot size={20} />} title="Homarr Assistant">
</FeatureCard>
<FeatureCard icon={<IconRobot size={21} />} title="Homarr Assistant">
Ask questions, find what you need, and manage Homarr through permission-aware tools.
</FeatureAccordionItem>
<Accordion.Item value="installation">
<Accordion.Control
icon={
<ThemeIcon variant="light" color="red" radius="md" size="lg">
<IconTerminal2 size={20} />
</ThemeIcon>
}
aria-label="Test Homarr v2 on your server"
>
<Box>
<Text fw={750}>Test Homarr v2 on your server</Text>
<Text c="dimmed" size="xs">
Back up this instance, then update your Docker Compose file.
</Text>
</Box>
</Accordion.Control>
<Accordion.Panel>
<V2BetaInstallInstructions canExportBackup={innerProps.canExportBackup} />
</Accordion.Panel>
</Accordion.Item>
</Accordion>
</FeatureCard>
</SimpleGrid>
<Alert variant="light" color="red" icon={<IconHeartHandshake size={22} />} title="Your testing is essential">
Everyone uses Homarr in a different way. We’re counting on you to tell us anything that breaks or doesn’t feel
right with this new version. Every report matters.
</Alert>
<SimpleGrid cols={{ base: 1, sm: 3 }} spacing="sm">
<SimpleGrid cols={{ base: 1, sm: 2 }} spacing="sm">
<Button
component="a"
href={v2BetaPreviewUrl}
@@ -198,6 +165,14 @@ const V2BetaAnnouncementModal = createModal<V2BetaAnnouncementModalProps>(({ inn
>
Try the hosted preview
</Button>
<Button
variant="light"
size="md"
leftSection={<IconTerminal2 size={18} />}
onClick={() => openInstallModal(undefined)}
>
Test v2 on your server
</Button>
<Button
component="a"
href={v2BetaBlogUrl}
@@ -259,37 +234,13 @@ const V2BetaAnnouncementModal = createModal<V2BetaAnnouncementModalProps>(({ inn
centered: true,
});
interface V2BetaInstallInstructionsProps {
canExportBackup: boolean;
}
const V2BetaInstallInstructions = ({ canExportBackup }: V2BetaInstallInstructionsProps) => (
const V2BetaInstallModal = createModal<void>(() => (
<Stack gap="lg">
<Alert color="yellow" title="Keep your current Homarr data safe">
Run the beta with the separate <code>homarr-v2</code> volume shown below. Keep a backup, and do not point this
prerelease image at the only copy of your production data.
</Alert>
{canExportBackup ? (
<Paper withBorder p="md" radius="md">
<Stack gap="sm">
<Group gap="sm">
<IconDatabaseExport size={22} />
<Title order={4}>Back up this Homarr instance</Title>
</Group>
<Text c="dimmed" size="sm">
Download a full backup before testing v2. The archive contains sensitive data, so keep it somewhere safe.
</Text>
<BackupExportButton />
</Stack>
</Paper>
) : (
<Alert color="blue" title="Back up your database before continuing">
Direct backup downloads are available here to Homarr administrators using SQLite. If you use MySQL or
PostgreSQL, back up the database with its own tools before testing v2.
</Alert>
)}
<Stack gap="xs">
<Title order={3}>Update your Docker Compose file</Title>
<Text c="dimmed" size="sm">
@@ -334,33 +285,32 @@ const V2BetaInstallInstructions = ({ canExportBackup }: V2BetaInstallInstruction
the beta uses the preview Workshop.
</Text>
</Stack>
);
)).withOptions({
defaultTitle: "Test Homarr v2 on your server",
size: 900,
centered: true,
});
interface FeatureAccordionItemProps {
value: string;
interface FeatureCardProps {
icon: ReactNode;
title: string;
children: ReactNode;
}
const FeatureAccordionItem = ({ value, icon, title, children }: FeatureAccordionItemProps) => (
<Accordion.Item value={value}>
<Accordion.Control
icon={
<ThemeIcon variant="light" color="red" radius="md" size="lg">
{icon}
</ThemeIcon>
}
aria-label={title}
>
<Text fw={750}>{title}</Text>
</Accordion.Control>
<Accordion.Panel>
<Box pl={48}>
const FeatureCard = ({ icon, title, children }: FeatureCardProps) => (
<Paper className={classes.featureCard} withBorder p="md" radius="md">
<Group gap="sm" align="flex-start" wrap="nowrap">
<ThemeIcon variant="light" color="red" radius="md" size="lg">
{icon}
</ThemeIcon>
<Box>
<Text fw={750} size="sm">
{title}
</Text>
<Text c="dimmed" size="sm">
{children}
</Text>
</Box>
</Accordion.Panel>
</Accordion.Item>
</Group>
</Paper>
);
@@ -8,14 +8,12 @@ import { ClientShell } from "../shell";
import { V2BetaAnnouncement } from "./v2-beta-announcement";
interface V2BetaDashboardShellProps {
canExportBackup: boolean;
dismissalCookieName: string;
initiallyDismissed: boolean;
header: ReactNode;
}
export const V2BetaDashboardShell = ({
canExportBackup,
dismissalCookieName,
initiallyDismissed,
header,
@@ -29,7 +27,6 @@ export const V2BetaDashboardShell = ({
<AppShellHeader maw="100vw" zIndex={201} style={{ overflowX: "hidden" }}>
{isAnnouncementVisible && (
<V2BetaAnnouncement
canExportBackup={canExportBackup}
dismissalCookieName={dismissalCookieName}
onDismiss={() => setIsAnnouncementVisible(false)}
/>