diff --git a/apps/nextjs/src/components/board/items/item-content.tsx b/apps/nextjs/src/components/board/items/item-content.tsx
index 969195d60..a572cdbad 100644
--- a/apps/nextjs/src/components/board/items/item-content.tsx
+++ b/apps/nextjs/src/components/board/items/item-content.tsx
@@ -157,8 +157,9 @@ export const BoardItemContent = ({ item }: BoardItemContentProps) => {
height: advancedRect.height,
"--focus-translate-x": `${activeFocus.sourceRect.left - advancedRect.left}px`,
"--focus-translate-y": `${activeFocus.sourceRect.top - advancedRect.top}px`,
- "--focus-scale-x": activeFocus.sourceRect.width / advancedRect.width,
- "--focus-scale-y": activeFocus.sourceRect.height / advancedRect.height,
+ "--focus-scale-x": advancedRect.width > 0 ? activeFocus.sourceRect.width / advancedRect.width : 1,
+ "--focus-scale-y":
+ advancedRect.height > 0 ? activeFocus.sourceRect.height / advancedRect.height : 1,
} as CSSProperties)
: undefined
}
diff --git a/e2e/custom-widgets-custom-jsx.spec.ts b/e2e/custom-widgets-custom-jsx.spec.ts
index cba6c0d75..c1f7743ba 100644
--- a/e2e/custom-widgets-custom-jsx.spec.ts
+++ b/e2e/custom-widgets-custom-jsx.spec.ts
@@ -40,16 +40,17 @@ describe("Custom JSX custom widgets", () => {
const browser = await chromium.launch();
const context = await browser.newContext();
const page = await context.newPage();
+ const destination = "/manage/custom-widgets/new";
try {
- await page.goto(`${baseUrl}/auth/login`);
+ await page.goto(`${baseUrl}/auth/login?callbackUrl=${encodeURIComponent(destination)}`);
await page.getByLabel("Username").fill(adminCredentials.username);
await page.locator("#password").fill(adminCredentials.password);
- await page.locator("css=button[type='submit']").click();
- await page.waitForURL(baseUrl, { timeout: 15_000 });
-
- await page.goto(`${baseUrl}/manage/custom-widgets/new`);
- await page.waitForURL("**/manage/custom-widgets/new", { timeout: 15_000 });
+ await Promise.all([
+ page.waitForURL(`**${destination}`, { timeout: 30_000 }),
+ page.locator("css=button[type='submit']").click(),
+ ]);
+ await expect(page.getByRole("textbox", { name: "Name" })).toBeVisible({ timeout: 30_000 });
await page.getByRole("textbox", { name: "Name" }).fill("E2E Custom JSX");
await page.getByRole("textbox", { name: "URL", exact: true }).fill(`${mockApi.url}/status`);
await page.getByRole("combobox", { name: "Display Type" }).click();
diff --git a/packages/translation/src/lang/en.json b/packages/translation/src/lang/en.json
index 16f33874c..9151de77c 100644
--- a/packages/translation/src/lang/en.json
+++ b/packages/translation/src/lang/en.json
@@ -2567,6 +2567,12 @@
"label": "Show services"
}
},
+ "action": {
+ "openResource": "Open {name}",
+ "openLogs": "Open {name} logs",
+ "showIp": "Show IP address",
+ "hideIp": "Hide IP address"
+ },
"empty": {
"servers": "No servers found",
"applications": "No applications found",
@@ -2590,6 +2596,12 @@
"name": "VPN",
"description": "Overview of your VPN connections",
"serviceUnavailable": "VPN unavailable",
+ "status": {
+ "running": "Running",
+ "notRunning": "Not running",
+ "unavailable": "Unavailable",
+ "vpn": "VPN: {status}"
+ },
"option": {}
},
"ups": {
diff --git a/packages/widgets/src/coolify/resource-row.tsx b/packages/widgets/src/coolify/resource-row.tsx
index fba5279ca..44ca137a1 100644
--- a/packages/widgets/src/coolify/resource-row.tsx
+++ b/packages/widgets/src/coolify/resource-row.tsx
@@ -3,6 +3,8 @@
import { ActionIcon, Anchor, Group, Indicator, Stack, Text } from "@mantine/core";
import { IconFileText, IconLink } from "@tabler/icons-react";
+import { useScopedI18n } from "@homarr/translation/client";
+
import actionTargetClasses from "../common/action-target.module.css";
import { cleanFqdn, getResourceTimestamp, getStatusColor, parseStatus } from "./coolify-utils";
@@ -25,6 +27,7 @@ interface ResourceRowProps {
}
export function ResourceRow({ item, baseUrl, isTiny, resourceType }: ResourceRowProps) {
+ const t = useScopedI18n("widget.coolify");
const status = parseStatus(item.status ?? "");
const statusColor = getStatusColor(status);
@@ -64,7 +67,7 @@ export function ResourceRow({ item, baseUrl, isTiny, resourceType }: ResourceRow
href={cleanFqdn(item.fqdn)}
target="_blank"
rel="noopener noreferrer"
- aria-label={`Open ${item.name}`}
+ aria-label={t("action.openResource", { name: item.name })}
size="xs"
variant="subtle"
c="dimmed"
@@ -79,7 +82,7 @@ export function ResourceRow({ item, baseUrl, isTiny, resourceType }: ResourceRow
href={logsUrl}
target="_blank"
rel="noopener noreferrer"
- aria-label={`Open ${item.name} logs`}
+ aria-label={t("action.openLogs", { name: item.name })}
size="xs"
variant="subtle"
c="dimmed"
diff --git a/packages/widgets/src/coolify/servers-section.tsx b/packages/widgets/src/coolify/servers-section.tsx
index 6a5da6ef4..24f82852a 100644
--- a/packages/widgets/src/coolify/servers-section.tsx
+++ b/packages/widgets/src/coolify/servers-section.tsx
@@ -42,7 +42,7 @@ export function ServersSection({