Compare commits

..
Author SHA1 Message Date
ajnart 84f7ed97fc style: auto-fix lint and format 2026-06-17 14:11:52 +00:00
Thomas Camlong dc1e1891fb fix: persist Beszel server selection and improve picker visibility
The server picker was invisible (opacity: 0, hover-only) and selections
were lost on refresh because setOptions only updated the React Query cache.
Add a generic saveItemOptions mutation that persists widget option changes
directly to the database, and replace the hidden icon with a visible button.
2026-06-17 16:09:32 +02:00
40 changed files with 732 additions and 957 deletions

No files matched your search

-1
View File
@@ -33,7 +33,6 @@ body:
options: options:
# The below comment is used to insert a new version with on-release.yml # The below comment is used to insert a new version with on-release.yml
#NEXT_VERSION# #NEXT_VERSION#
- 1.66.0
- 1.65.0 - 1.65.0
- 1.64.0 - 1.64.0
- 1.62.0 - 1.62.0
+14 -10
View File
@@ -647,13 +647,9 @@ const seedDemoUserAsync = async (db: Database) => {
const seedDefaultCustomWidgetsAsync = async (db: Database) => { const seedDefaultCustomWidgetsAsync = async (db: Database) => {
const seedIds = CUSTOM_WIDGET_SEEDS.map((s) => s.id); const seedIds = CUSTOM_WIDGET_SEEDS.map((s) => s.id);
const existing = await db.query.customWidgetDefinitions.findMany({ const beforeCount = await db.$count(customWidgetDefinitions, inArray(customWidgetDefinitions.id, seedIds));
columns: { id: true },
where: inArray(customWidgetDefinitions.id, seedIds),
});
const existingIds = new Set(existing.map((row) => row.id));
const seedValues = CUSTOM_WIDGET_SEEDS.filter((seed) => !existingIds.has(seed.id)).map((seed) => { const seedValues = CUSTOM_WIDGET_SEEDS.map((seed) => {
const parsed = customWidgetImportSchema.parse(seed.data); const parsed = customWidgetImportSchema.parse(seed.data);
return { return {
id: seed.id, id: seed.id,
@@ -672,14 +668,22 @@ const seedDefaultCustomWidgetsAsync = async (db: Database) => {
}; };
}); });
if (seedValues.length === 0) { if (seedValues.length === 0) return;
await db
.insert(customWidgetDefinitions)
.values(seedValues)
.onConflictDoNothing({ target: customWidgetDefinitions.id });
const afterCount = await db.$count(customWidgetDefinitions, inArray(customWidgetDefinitions.id, seedIds));
const createdCount = afterCount - beforeCount;
if (createdCount === 0) {
console.log("Skipping seeding of default custom widgets as they already exist"); console.log("Skipping seeding of default custom widgets as they already exist");
return; return;
} }
await db.insert(customWidgetDefinitions).values(seedValues); console.log(`Created ${createdCount} default custom widgets through seeding process`);
console.log(`Created ${seedValues.length} default custom widgets through seeding process`);
}; };
const seedBoardWidgetsAsync = async (db: Database) => { const seedBoardWidgetsAsync = async (db: Database) => {
@@ -38,7 +38,7 @@ const itemSchema = z.object({
ServerId: z.string(), ServerId: z.string(),
Name: z.string(), Name: z.string(),
Taglines: z.array(z.string()), Taglines: z.array(z.string()),
Studios: z.array(z.object({ Name: z.string() })).optional(), Studios: z.array(z.object({ Name: z.string() })),
Overview: z.string().optional(), Overview: z.string().optional(),
PremiereDate: z PremiereDate: z
.string() .string()
@@ -172,7 +172,7 @@ export class EmbyIntegration extends Integration implements IMediaServerIntegrat
poster: super.externalUrl(`/Items/${item.Id}/Images/Primary?maxHeight=492&maxWidth=328&quality=90`).toString(), poster: super.externalUrl(`/Items/${item.Id}/Images/Primary?maxHeight=492&maxWidth=328&quality=90`).toString(),
backdrop: super.externalUrl(`/Items/${item.Id}/Images/Backdrop/0?maxWidth=960&quality=70`).toString(), backdrop: super.externalUrl(`/Items/${item.Id}/Images/Backdrop/0?maxWidth=960&quality=70`).toString(),
}, },
producer: item.Studios?.at(0)?.Name, producer: item.Studios.at(0)?.Name,
rating: item.CommunityRating?.toFixed(1), rating: item.CommunityRating?.toFixed(1),
tags: item.Genres, tags: item.Genres,
href: super.externalUrl(`/web/index.html#!/item?id=${item.Id}&serverId=${item.ServerId}`).toString(), href: super.externalUrl(`/web/index.html#!/item?id=${item.Id}&serverId=${item.ServerId}`).toString(),
-9
View File
@@ -1739,15 +1739,6 @@
} }
} }
}, },
"archiveTeamWarrior": {
"name": "",
"description": "",
"option": {
"showBroadcastMessage": {
"label": ""
}
}
},
"dnsHoleSummary": { "dnsHoleSummary": {
"name": "", "name": "",
"description": "", "description": "",
-9
View File
@@ -1739,15 +1739,6 @@
} }
} }
}, },
"archiveTeamWarrior": {
"name": "",
"description": "",
"option": {
"showBroadcastMessage": {
"label": ""
}
}
},
"dnsHoleSummary": { "dnsHoleSummary": {
"name": "DNS Hole 摘要", "name": "DNS Hole 摘要",
"description": "显示 DNS Hole 的摘要", "description": "显示 DNS Hole 的摘要",
-9
View File
@@ -1739,15 +1739,6 @@
} }
} }
}, },
"archiveTeamWarrior": {
"name": "crwdns5635:0crwdne5635:0",
"description": "crwdns5637:0crwdne5637:0",
"option": {
"showBroadcastMessage": {
"label": "crwdns5639:0crwdne5639:0"
}
}
},
"dnsHoleSummary": { "dnsHoleSummary": {
"name": "crwdns768:0crwdne768:0", "name": "crwdns768:0crwdne768:0",
"description": "crwdns770:0crwdne770:0", "description": "crwdns770:0crwdne770:0",
-9
View File
@@ -1739,15 +1739,6 @@
} }
} }
}, },
"archiveTeamWarrior": {
"name": "",
"description": "",
"option": {
"showBroadcastMessage": {
"label": ""
}
}
},
"dnsHoleSummary": { "dnsHoleSummary": {
"name": "", "name": "",
"description": "Zobrazí shrnutí vaší DNS Hole", "description": "Zobrazí shrnutí vaší DNS Hole",
-9
View File
@@ -1739,15 +1739,6 @@
} }
} }
}, },
"archiveTeamWarrior": {
"name": "",
"description": "",
"option": {
"showBroadcastMessage": {
"label": ""
}
}
},
"dnsHoleSummary": { "dnsHoleSummary": {
"name": "DNS Hole Oversigt", "name": "DNS Hole Oversigt",
"description": "Viser oversigten over dit DNS-hul", "description": "Viser oversigten over dit DNS-hul",
-9
View File
@@ -1739,15 +1739,6 @@
} }
} }
}, },
"archiveTeamWarrior": {
"name": "",
"description": "",
"option": {
"showBroadcastMessage": {
"label": ""
}
}
},
"dnsHoleSummary": { "dnsHoleSummary": {
"name": "DNS Hole Zusammenfassung", "name": "DNS Hole Zusammenfassung",
"description": "Zeigt die Zusammenfassung deines DNS Holes an", "description": "Zeigt die Zusammenfassung deines DNS Holes an",
-9
View File
@@ -1739,15 +1739,6 @@
} }
} }
}, },
"archiveTeamWarrior": {
"name": "",
"description": "",
"option": {
"showBroadcastMessage": {
"label": ""
}
}
},
"dnsHoleSummary": { "dnsHoleSummary": {
"name": "DNS Hole Zusammenfassung", "name": "DNS Hole Zusammenfassung",
"description": "Zeigt die Zusammenfassung deines DNS Holes an", "description": "Zeigt die Zusammenfassung deines DNS Holes an",
-9
View File
@@ -1739,15 +1739,6 @@
} }
} }
}, },
"archiveTeamWarrior": {
"name": "",
"description": "",
"option": {
"showBroadcastMessage": {
"label": ""
}
}
},
"dnsHoleSummary": { "dnsHoleSummary": {
"name": "", "name": "",
"description": "", "description": "",
+39 -48
View File
@@ -8,9 +8,9 @@
"action": { "action": {
"scratch": "Start from scratch", "scratch": "Start from scratch",
"importOldmarr": "Import from a Homarr version before v1.0", "importOldmarr": "Import from a Homarr version before v1.0",
"restoreSqlite": "Restore from SQLite backup", "restoreSqlite": "",
"restoreSqliteDescription": "Upload a full SQLite database backup from a previous Homarr instance. This will restore all boards, users, apps, integrations, and settings.", "restoreSqliteDescription": "",
"backToOptions": "← Back to setup options" "backToOptions": ""
} }
}, },
"import": { "import": {
@@ -115,24 +115,24 @@
} }
}, },
"urlTemplate": { "urlTemplate": {
"label": "Base URL", "label": "",
"placeholder": "homelab.local or 192.168.1.1", "placeholder": "",
"hint": "Enter your base domain or IP to auto-fill integration URLs", "hint": "",
"warning": "Setting your base URL now will auto-fill all integration URLs, saving you time during setup", "warning": "",
"preview": "e.g. {example}", "preview": "",
"mode": { "mode": {
"subdomain": "Subdomain", "subdomain": "",
"hostPort": "Host:Port" "hostPort": ""
} }
}, },
"docker": { "docker": {
"detected": "Docker detected {count} services", "detected": "",
"detectedBreakdown": "{integrations} integrations · {apps} apps", "detectedBreakdown": "",
"summary": "Homarr detected {apps} apps, {integrations} of which have integrations built-in", "summary": "",
"appBadge": "App", "appBadge": "",
"appSectionLabel": "Apps to add to dashboard ({count} selected)", "appSectionLabel": "",
"scanning": "Scanning Docker...", "scanning": "",
"scanningDescription": "Looking for running containers on your system" "scanningDescription": ""
} }
}, },
"finish": { "finish": {
@@ -1739,15 +1739,6 @@
} }
} }
}, },
"archiveTeamWarrior": {
"name": "",
"description": "",
"option": {
"showBroadcastMessage": {
"label": ""
}
}
},
"dnsHoleSummary": { "dnsHoleSummary": {
"name": "DNS Hole Summary", "name": "DNS Hole Summary",
"description": "Displays the summary of your DNS Hole", "description": "Displays the summary of your DNS Hole",
@@ -5713,10 +5704,10 @@
"option": { "option": {
"google": { "google": {
"name": "", "name": "",
"description": "Search the web with Google" "description": ""
}, },
"bing": { "bing": {
"name": "Bing", "name": "",
"description": "Search the web with Bing" "description": "Search the web with Bing"
}, },
"duckduckgo": { "duckduckgo": {
@@ -6098,46 +6089,46 @@
"description": "These are all the apps you've added — links to your self-hosted services. Each app has an icon, optional health check, and a status badge on the dashboard." "description": "These are all the apps you've added — links to your self-hosted services. Each app has an icon, optional health check, and a status badge on the dashboard."
}, },
"appsCreate": { "appsCreate": {
"title": "Add an App", "title": "",
"description": "Register a new service here. Give it a name, URL, and icon — it will appear as a tile on your boards with live status monitoring." "description": ""
}, },
"integrationsList": { "integrationsList": {
"title": "Your Integrations", "title": "",
"description": "These are the services connected to Homarr — Sonarr, Radarr, Plex, Jellyfin, and 50+ more. All credentials are encrypted at rest." "description": ""
}, },
"integrationsCreate": { "integrationsCreate": {
"title": "Add an Integration", "title": "",
"description": "Connect a new service here. Pick the type, enter the URL and API key — Homarr validates the connection before saving." "description": ""
}, },
"usersList": { "usersList": {
"title": "Your Users", "title": "",
"description": "See everyone who has access. Organise users into groups and control who can view or edit each board." "description": ""
}, },
"usersCreate": { "usersCreate": {
"title": "Create a User", "title": "",
"description": "Add a new user account here. You can also use invite links for easy onboarding. That's the tour — you're all set!" "description": ""
} }
}, },
"board": { "board": {
"welcome": { "welcome": {
"title": "This is your board", "title": "",
"description": "A drag-and-drop dashboard where you arrange apps and widgets. Press Ctrl+K anytime to search for apps, boards, and actions." "description": ""
}, },
"editMode": { "editMode": {
"title": "Edit Mode", "title": "",
"description": "Click here to enter edit mode. You can then add widgets, apps, and sections — drag to reposition, resize with the corner handle. Click again to save your changes." "description": ""
}, },
"settings": { "settings": {
"title": "Board Settings", "title": "",
"description": "Change this board's name, columns, background, colours, and who can access it. Each board can be public or private." "description": ""
}, },
"switcher": { "switcher": {
"title": "Switch Boards", "title": "",
"description": "Jump between boards. Create separate dashboards for different purposes — media, networking, per-user, or anything you like." "description": ""
}, },
"userMenu": { "userMenu": {
"title": "Your Profile", "title": "",
"description": "Change your colour scheme, language, home board, and preferences. You can also jump to the management area from here." "description": ""
} }
} }
} }
-9
View File
@@ -1739,15 +1739,6 @@
} }
} }
}, },
"archiveTeamWarrior": {
"name": "",
"description": "",
"option": {
"showBroadcastMessage": {
"label": ""
}
}
},
"dnsHoleSummary": { "dnsHoleSummary": {
"name": "Resumen del agujero DNS", "name": "Resumen del agujero DNS",
"description": "Muestra el resumen de tu agujero DNS", "description": "Muestra el resumen de tu agujero DNS",
-9
View File
@@ -1739,15 +1739,6 @@
} }
} }
}, },
"archiveTeamWarrior": {
"name": "",
"description": "",
"option": {
"showBroadcastMessage": {
"label": ""
}
}
},
"dnsHoleSummary": { "dnsHoleSummary": {
"name": "", "name": "",
"description": "", "description": "",
-9
View File
@@ -1739,15 +1739,6 @@
} }
} }
}, },
"archiveTeamWarrior": {
"name": "",
"description": "",
"option": {
"showBroadcastMessage": {
"label": ""
}
}
},
"dnsHoleSummary": { "dnsHoleSummary": {
"name": "", "name": "",
"description": "", "description": "",
-9
View File
@@ -1739,15 +1739,6 @@
} }
} }
}, },
"archiveTeamWarrior": {
"name": "",
"description": "",
"option": {
"showBroadcastMessage": {
"label": ""
}
}
},
"dnsHoleSummary": { "dnsHoleSummary": {
"name": "Résumé du puit DNS", "name": "Résumé du puit DNS",
"description": "Affiche le résumé de votre puit DNS", "description": "Affiche le résumé de votre puit DNS",
-9
View File
@@ -1739,15 +1739,6 @@
} }
} }
}, },
"archiveTeamWarrior": {
"name": "",
"description": "",
"option": {
"showBroadcastMessage": {
"label": ""
}
}
},
"dnsHoleSummary": { "dnsHoleSummary": {
"name": "סיכום חור אבטחה DNS", "name": "סיכום חור אבטחה DNS",
"description": "מציג את הסיכום חור אבטחת DNS שלך", "description": "מציג את הסיכום חור אבטחת DNS שלך",
-9
View File
@@ -1739,15 +1739,6 @@
} }
} }
}, },
"archiveTeamWarrior": {
"name": "",
"description": "",
"option": {
"showBroadcastMessage": {
"label": ""
}
}
},
"dnsHoleSummary": { "dnsHoleSummary": {
"name": "", "name": "",
"description": "", "description": "",
-9
View File
@@ -1739,15 +1739,6 @@
} }
} }
}, },
"archiveTeamWarrior": {
"name": "",
"description": "",
"option": {
"showBroadcastMessage": {
"label": ""
}
}
},
"dnsHoleSummary": { "dnsHoleSummary": {
"name": "DNS Blokkoló Összefoglaló", "name": "DNS Blokkoló Összefoglaló",
"description": "Megjeleníti a DNS Blokkoló összefoglalóját", "description": "Megjeleníti a DNS Blokkoló összefoglalóját",
-9
View File
@@ -1739,15 +1739,6 @@
} }
} }
}, },
"archiveTeamWarrior": {
"name": "",
"description": "",
"option": {
"showBroadcastMessage": {
"label": ""
}
}
},
"dnsHoleSummary": { "dnsHoleSummary": {
"name": "Riepilogo del filtraggio DNS", "name": "Riepilogo del filtraggio DNS",
"description": "Mostra il riepilogo del tuo filtro DNS", "description": "Mostra il riepilogo del tuo filtro DNS",
-9
View File
@@ -1739,15 +1739,6 @@
} }
} }
}, },
"archiveTeamWarrior": {
"name": "",
"description": "",
"option": {
"showBroadcastMessage": {
"label": ""
}
}
},
"dnsHoleSummary": { "dnsHoleSummary": {
"name": "DNS Hole 概要", "name": "DNS Hole 概要",
"description": "DNS Hole の概要を表示します", "description": "DNS Hole の概要を表示します",
-9
View File
@@ -1739,15 +1739,6 @@
} }
} }
}, },
"archiveTeamWarrior": {
"name": "",
"description": "",
"option": {
"showBroadcastMessage": {
"label": ""
}
}
},
"dnsHoleSummary": { "dnsHoleSummary": {
"name": "", "name": "",
"description": "", "description": "",
-9
View File
@@ -1739,15 +1739,6 @@
} }
} }
}, },
"archiveTeamWarrior": {
"name": "",
"description": "",
"option": {
"showBroadcastMessage": {
"label": ""
}
}
},
"dnsHoleSummary": { "dnsHoleSummary": {
"name": "", "name": "",
"description": "", "description": "",
-9
View File
@@ -1739,15 +1739,6 @@
} }
} }
}, },
"archiveTeamWarrior": {
"name": "",
"description": "",
"option": {
"showBroadcastMessage": {
"label": ""
}
}
},
"dnsHoleSummary": { "dnsHoleSummary": {
"name": "", "name": "",
"description": "", "description": "",
-9
View File
@@ -1739,15 +1739,6 @@
} }
} }
}, },
"archiveTeamWarrior": {
"name": "",
"description": "",
"option": {
"showBroadcastMessage": {
"label": ""
}
}
},
"dnsHoleSummary": { "dnsHoleSummary": {
"name": "DNS-hole overzicht", "name": "DNS-hole overzicht",
"description": "Toont het overzicht van je DNS-hole", "description": "Toont het overzicht van je DNS-hole",
-9
View File
@@ -1739,15 +1739,6 @@
} }
} }
}, },
"archiveTeamWarrior": {
"name": "",
"description": "",
"option": {
"showBroadcastMessage": {
"label": ""
}
}
},
"dnsHoleSummary": { "dnsHoleSummary": {
"name": "DNS Hole Sammendrag", "name": "DNS Hole Sammendrag",
"description": "Viser sammendrag av DNS Hole", "description": "Viser sammendrag av DNS Hole",
-9
View File
@@ -1739,15 +1739,6 @@
} }
} }
}, },
"archiveTeamWarrior": {
"name": "",
"description": "",
"option": {
"showBroadcastMessage": {
"label": ""
}
}
},
"dnsHoleSummary": { "dnsHoleSummary": {
"name": "Podsumowanie Hole DNS", "name": "Podsumowanie Hole DNS",
"description": "Wyświetla podsumowanie Twojego hosta DNS", "description": "Wyświetla podsumowanie Twojego hosta DNS",
+192 -201
View File
@@ -8,9 +8,9 @@
"action": { "action": {
"scratch": "Começar do zero", "scratch": "Começar do zero",
"importOldmarr": "Importe de uma instância do Homarr anterior a 1.0", "importOldmarr": "Importe de uma instância do Homarr anterior a 1.0",
"restoreSqlite": "Restaurar do backup SQLite", "restoreSqlite": "",
"restoreSqliteDescription": "Fazer o upload de um backup completo do banco de dados SQLite de uma instância anterior da Homarr. Isso restaurará todos os painéis, usuários, apps, integrações e configurações.", "restoreSqliteDescription": "",
"backToOptions": "← Retorna às opções de instalação" "backToOptions": ""
} }
}, },
"import": { "import": {
@@ -94,45 +94,45 @@
"subtitle": "Definir as configurações do servidor." "subtitle": "Definir as configurações do servidor."
}, },
"integrations": { "integrations": {
"title": "Integrações", "title": "",
"subtitle": "Selecione os serviços que você usa.", "subtitle": "",
"description": "Escolha as integrações que deseja conectar. Vamos configurar seu painel com os widgets correspondentes automaticamente.", "description": "",
"action": { "action": {
"continue": "Continuar", "continue": "",
"skip": "Pular por enquanto" "skip": ""
}, },
"configure": { "configure": {
"progress": "{current} de {total}", "progress": "",
"skip": "Pular esta integração", "skip": "",
"finishing": "Configurando seu painel...", "finishing": "",
"error": { "error": {
"title": "Falha na configuração", "title": "",
"message": "Algo deu errado ao configurar seu painel. Por favor, tente novamente." "message": ""
}, },
"helpers": { "helpers": {
"tooltip": "Auxiliares de URL", "tooltip": "",
"description": "Esses auxiliares tentam adivinhar a URL dos seus serviços. Se não funcionar, digite o endereço manualmente." "description": ""
} }
}, },
"urlTemplate": { "urlTemplate": {
"label": "URL base", "label": "",
"placeholder": "homelab.local ou 192.168.1.1", "placeholder": "",
"hint": "Digite seu domínio base ou IP para preencher automaticamente as URLs das integrações", "hint": "",
"warning": "Definir sua URL base agora preencherá automaticamente todas as URLs das integrações, economizando tempo durante a configuração", "warning": "",
"preview": "ex.: {example}", "preview": "",
"mode": { "mode": {
"subdomain": "Subdomínio", "subdomain": "",
"hostPort": "Host:Porta" "hostPort": ""
} }
}, },
"docker": { "docker": {
"detected": "Docker detectou {count} serviços", "detected": "",
"detectedBreakdown": "{integrations} integrações · {apps} apps", "detectedBreakdown": "",
"summary": "O Homarr detectou {apps} apps, dos quais {integrations} possuem integrações nativas", "summary": "",
"appBadge": "App", "appBadge": "",
"appSectionLabel": "Apps para adicionar ao painel ({count} selecionados)", "appSectionLabel": "",
"scanning": "Verificando Docker...", "scanning": "",
"scanningDescription": "Procurando contêineres em execução no seu sistema" "scanningDescription": ""
} }
}, },
"finish": { "finish": {
@@ -177,7 +177,7 @@
}, },
"password": { "password": {
"label": "Senha", "label": "Senha",
"suggestionsTitle": "Sugestões de senha", "suggestionsTitle": "",
"suggestion": { "suggestion": {
"length": "Inclua pelo menos 8 caracteres", "length": "Inclua pelo menos 8 caracteres",
"lowercase": "Inclui letras minúsculas", "lowercase": "Inclui letras minúsculas",
@@ -687,94 +687,94 @@
"customWidget": { "customWidget": {
"page": { "page": {
"list": { "list": {
"title": "Widgets Personalizados", "title": "",
"noResults": "Nenhum widget personalizado ainda. Crie o seu primeiro!", "noResults": "",
"loading": "Carregando..." "loading": ""
}, },
"create": { "create": {
"title": "Criar widget personalizado", "title": "",
"subtitle": "Defina uma URL de API, autenticação e como exibir os dados de resposta." "subtitle": ""
}, },
"edit": { "edit": {
"title": "Editar widget personalizado" "title": ""
} }
}, },
"action": { "action": {
"create": "Criar", "create": "",
"import": "Importar", "import": "",
"save": "Salvar", "save": "",
"delete": "Excluir widget personalizado", "delete": "",
"deleteConfirm": "Tem certeza de que deseja excluir \"{name}\"? Esta ação não pode ser desfeita.", "deleteConfirm": "",
"export": "Exportar", "export": "",
"addMapping": "Adicionar Mapeamento", "addMapping": "",
"addColumn": "Adicionar Coluna", "addColumn": "",
"edit": "Editar", "edit": "",
"removeMapping": "Remover Mapeamento", "removeMapping": "",
"removeColumn": "Remover coluna", "removeColumn": "",
"addItem": "Adicionar Item", "addItem": "",
"removeItem": "Remover item", "removeItem": "",
"addBar": "Adicionar barra", "addBar": "",
"duplicate": "Duplicar", "duplicate": "",
"copyAiPrompt": "", "copyAiPrompt": "",
"enable": "Habilitado", "enable": "",
"disable": "Desabilitado", "disable": "",
"menu": "Ações" "menu": ""
}, },
"field": { "field": {
"name": "Nome", "name": "",
"description": "Descrição", "description": "",
"iconUrl": "URL do ícone", "iconUrl": "",
"url": "URL", "url": "",
"authType": "Tipo de Autenticação", "authType": "",
"headerName": "", "headerName": "",
"method": "Método", "method": "",
"requestBody": "Corpo da requisição", "requestBody": "",
"displayType": "", "displayType": "",
"jsonPath": "Caminho JSON", "jsonPath": "",
"jsonPathHint": "Usar sintaxe JSONPath para extrair valores, por exemplo, $.data.temperature ou $.items[0].name", "jsonPathHint": "",
"label": "", "label": "",
"unit": "", "unit": "",
"mappings": "Mapeamentos", "mappings": "",
"tablePath": "Caminho Array JSON", "tablePath": "",
"tablePathHint": "Caminho para o array na resposta, por exemplo, $.data.items", "tablePathHint": "",
"columns": "Colunas", "columns": "",
"header": "Header (cabeçalho)", "header": "",
"items": "Itens", "items": "",
"gridColumns": "Colunas da grade", "gridColumns": "",
"cardStyle": "Estilo de cartão", "cardStyle": "",
"bars": "Barras", "bars": "",
"valuePath": "Caminho do valor JSON", "valuePath": "",
"maxPath": "Caminho do Max Valor JSON", "maxPath": "",
"showPercentage": "Mostrar porcentagem", "showPercentage": "",
"barSize": "Tamanho da barra", "barSize": "",
"goodValues": "Valores bons (separados por vírgula)", "goodValues": "",
"dotSize": "", "dotSize": "",
"valueSize": "Tamanho do valor", "valueSize": "",
"labelPosition": "", "labelPosition": "",
"kvLayout": "Layout", "kvLayout": "",
"striped": "Linhas Listradas", "striped": "",
"compact": "Modo Compacto", "compact": "",
"maxHeight": "Altura máxima (px)", "maxHeight": "",
"color": "Cor", "color": "",
"buttonLabel": "", "buttonLabel": "",
"buttonColor": "Cor do botão", "buttonColor": "",
"confirmText": "Texto de confirmação", "confirmText": "",
"confirmTextHint": "Se definido, um diálogo de confirmação irá aparecer antes de executar a solicitação", "confirmTextHint": "",
"successMessage": "Mensagem de Sucesso", "successMessage": "",
"successMessageHint": "Mensagem mostrada após execução com sucesso", "successMessageHint": "",
"enabled": "Habilitado", "enabled": "",
"template": { "template": {
"label": "Template JSX", "label": "",
"description": "" "description": ""
} }
}, },
"placeholder": { "placeholder": {
"exampleLabel": "Temperatura da CPU", "exampleLabel": "",
"exampleLabelShort": "", "exampleLabelShort": "",
"exampleHeader": "Nome", "exampleHeader": "",
"exampleUnit": "", "exampleUnit": "",
"iconUrl": "https://...", "iconUrl": "",
"url": "https://api.exemplo.com/br/api/v1/status", "url": "",
"headerName": "", "headerName": "",
"jsonPath": "", "jsonPath": "",
"tablePath": "", "tablePath": "",
@@ -790,35 +790,35 @@
"subtle": "" "subtle": ""
}, },
"layoutOption": { "layoutOption": {
"list": "Lista", "list": "",
"grid": "Grade" "grid": ""
}, },
"sizeOption": { "sizeOption": {
"sm": "Pequeno", "sm": "",
"md": "Médio", "md": "",
"lg": "Grande", "lg": "",
"xl": "Extra grande" "xl": ""
}, },
"labelPositionOption": { "labelPositionOption": {
"above": "Acima", "above": "",
"below": "Abaixo" "below": ""
}, },
"fieldset": { "fieldset": {
"general": "Geral", "general": "",
"connection": "Conexão com API", "connection": "",
"display": "Configurações de tela" "display": ""
}, },
"displayTypeDescription": { "displayTypeDescription": {
"singleValue": "", "singleValue": "",
"keyValue": "", "keyValue": "",
"table": "", "table": "",
"statGrid": "Estatísticas coloridas em uma grade — como Pi-Hole ou Widgets Rápidos", "statGrid": "",
"progressBars": "Barras de progresso mostrando uso ou conclusão — para disco, memória, quotas", "progressBars": "",
"statusIndicator": "Pontos de status coloridos mostrando estados online/offline ou de saúde", "statusIndicator": "",
"countGrid": "", "countGrid": "",
"raw": "Saída JSON impressa para depuração", "raw": "",
"actionButton": "Um botão que aciona uma solicitação quando clicado", "actionButton": "",
"customJsx": "Layout JSX personalizado usando componentes Mantine na lista branca com ligação completa de dados de API" "customJsx": ""
}, },
"method": { "method": {
"GET": "", "GET": "",
@@ -848,42 +848,42 @@
}, },
"secret": { "secret": {
"apiKey": "", "apiKey": "",
"username": "Usuário", "username": "",
"password": "Senha", "password": "",
"savedPlaceholder": "" "savedPlaceholder": ""
}, },
"preview": { "preview": {
"title": "Pré-visualizar", "title": "",
"test": "", "test": "",
"hint": "Clique em Testar para visualizar a resposta da API com sua configuração atual.", "hint": "",
"rawResponse": "Resposta JSON Bruta" "rawResponse": ""
}, },
"notification": { "notification": {
"created": "Widget \"{name}\" criado com sucesso.", "created": "",
"updated": "Widget \"{name}atualizado com sucesso.", "updated": "",
"deleted": "Widget \"{name}excluído.", "deleted": "",
"imported": "Widget importado com sucesso.", "imported": "",
"aiPromptCopied": "", "aiPromptCopied": "",
"aiPromptDescription": "Copie um prompt pré-construído para colar qualquer chatbot de AI (ChatGPT, Claude, Gemini...). Ele inclui o esquema completo de widget e a sua resposta de API para que a AI possa gerar uma configuração JSON pronta para importar para você.", "aiPromptDescription": "",
"aiPromptCopy": "Copiar para área de transferência", "aiPromptCopy": "",
"aiPromptNoResponse": "Dica: Execute um teste primeiro para incluir a sua API de resposta no prompt para melhores resultados.", "aiPromptNoResponse": "",
"aiPromptCopyError": "Falha ao copiar prompt para área de transferência. O seu navegador pode não suportar este recurso.", "aiPromptCopyError": "",
"createError": "Falha ao criar widget. Verifique se o endpoint API está acessível.", "createError": "",
"updateError": "Falha ao atualizar o widget. Suas alterações não foram salvas.", "updateError": "",
"importError": "Falha ao importar o widget. Certifique-se de que o arquivo seja um widget personalizado válido exportado em JSON.", "importError": "",
"exportError": "Falha ao exportar o widget.", "exportError": "",
"duplicated": "Widget \"{name}duplicado.", "duplicated": "",
"duplicateError": "Falha ao duplicar o widget.", "duplicateError": "",
"toggleError": "Falha ao alternar o status do widget.", "toggleError": "",
"deleteError": "Falha ao excluir o widget.", "deleteError": "",
"previewError": "Falha ao buscar a pré-visualização. Verifique a URL e tente novamente.", "previewError": "",
"executed": "Ação executada com sucesso.", "executed": "",
"executeError": "A ação falhou: {error}" "executeError": ""
}, },
"table": { "table": {
"name": "Nome", "name": "",
"url": "URL", "url": "",
"display": "Exibição" "display": ""
}, },
"widget": { "widget": {
"disabled": "" "disabled": ""
@@ -983,46 +983,46 @@
"placeholder": "URL de aplicativo personalizada" "placeholder": "URL de aplicativo personalizada"
}, },
"apiKeySettings": { "apiKeySettings": {
"label": "Obter chave de API" "label": ""
} }
}, },
"action": { "action": {
"create": "Nova integração" "create": "Nova integração"
}, },
"grid": { "grid": {
"widgetCount": "{count} widgets", "widgetCount": "",
"noWidgets": "Sem widgets", "noWidgets": "",
"detected": "Detectado via Docker" "detected": ""
}, },
"category": { "category": {
"dnsHole": "DNS", "dnsHole": "",
"mediaService": "Mídia", "mediaService": "",
"calendar": "Calendário", "calendar": "",
"mediaSearch": "Busca", "mediaSearch": "",
"mediaRelease": "Lançamentos", "mediaRelease": "",
"mediaRequest": "Solicitações", "mediaRequest": "",
"downloadClient": "Downloads", "downloadClient": "",
"usenet": "Usenet", "usenet": "",
"torrent": "Torrent", "torrent": "",
"miscellaneous": "Diversos", "miscellaneous": "",
"smartHomeServer": "Casa Inteligente", "smartHomeServer": "",
"indexerManager": "Indexador", "indexerManager": "",
"healthMonitoring": "", "healthMonitoring": "",
"search": "Busca", "search": "",
"mediaTranscoding": "Transcodificação", "mediaTranscoding": "",
"networkController": "Rede", "networkController": "",
"releasesProvider": "Lançamentos", "releasesProvider": "",
"notifications": "Notificações", "notifications": "",
"firewall": "Firewall", "firewall": "Firewall",
"timetable": "", "timetable": "",
"photoService": "Fotos", "photoService": "",
"documents": "Documentos", "documents": "",
"notes": "Anotações", "notes": "",
"mediaMonitoring": "Monitoramento", "mediaMonitoring": "",
"speedtest": "Teste de Velocidade", "speedtest": "",
"analytics": "Análises", "analytics": "",
"mediaLibrary": "Biblioteca de mídia", "mediaLibrary": "",
"uptimeMonitoring": "Monitoramento do Uptime" "uptimeMonitoring": ""
}, },
"testConnection": { "testConnection": {
"action": { "action": {
@@ -1297,7 +1297,7 @@
"newLabel": "Nova chave privada" "newLabel": "Nova chave privada"
}, },
"slug": { "slug": {
"label": "Slug página de status", "label": "",
"newLabel": "" "newLabel": ""
} }
} }
@@ -1329,7 +1329,7 @@
}, },
"paperlessNgx": { "paperlessNgx": {
"name": "", "name": "",
"description": "Sistema de gerenciamento de documentos para arquivamento e organização de documentos digitalizados" "description": ""
} }
}, },
"media": { "media": {
@@ -1384,7 +1384,7 @@
"add": "Adicionar", "add": "Adicionar",
"apply": "Aplicar", "apply": "Aplicar",
"backToOverview": "Voltar à visão geral", "backToOverview": "Voltar à visão geral",
"skip": "Pular", "skip": "",
"change": "Alterar", "change": "Alterar",
"create": "Criar", "create": "Criar",
"createAnother": "Criar e recomeçar", "createAnother": "Criar e recomeçar",
@@ -1621,11 +1621,11 @@
"edit": { "edit": {
"title": "Editar item", "title": "Editar item",
"tab": { "tab": {
"widget": "Editar widget", "widget": "",
"app": "Editar aplicativo" "app": ""
}, },
"app": { "app": {
"propagationNotice": "As alterações deste aplicativo serão aplicadas em todos os lugares em que for usado em todos os painéis." "propagationNotice": ""
}, },
"advancedOptions": { "advancedOptions": {
"label": "Opções avançadas", "label": "Opções avançadas",
@@ -1731,7 +1731,7 @@
"label": "Abrir em nova guia" "label": "Abrir em nova guia"
}, },
"withBorder": { "withBorder": {
"label": "Mostrar bordas" "label": ""
}, },
"items": { "items": {
"label": "Marcadores", "label": "Marcadores",
@@ -1739,15 +1739,6 @@
} }
} }
}, },
"archiveTeamWarrior": {
"name": "",
"description": "Monitore o status do ArchiveTeam Warrior, projetos e trabalhos de arquivamento ativos.",
"option": {
"showBroadcastMessage": {
"label": "Mostrar mensagens de transmissão"
}
}
},
"dnsHoleSummary": { "dnsHoleSummary": {
"name": "Resumo do DNS Hole", "name": "Resumo do DNS Hole",
"description": "Exibe o resumo do seu DNS Hole", "description": "Exibe o resumo do seu DNS Hole",
@@ -2399,31 +2390,31 @@
} }
}, },
"ups": { "ups": {
"name": "UPS", "name": "",
"description": "Monitore o status de seus dispositivos UPS através de um servidor NUT", "description": "",
"option": { "option": {
"showBattery": { "showBattery": {
"label": "Exibir bateria" "label": ""
}, },
"showLoad": { "showLoad": {
"label": "Mostrar carga" "label": ""
}, },
"showVoltage": { "showVoltage": {
"label": "Mostrar tensão" "label": ""
} }
}, },
"status": { "status": {
"online": "Online", "online": "",
"onBattery": "Na bateria", "onBattery": "",
"lowBattery": "Bateria fraca", "lowBattery": "",
"charging": "Carregando", "charging": "",
"unknown": "Desconhecido" "unknown": ""
}, },
"field": { "field": {
"runtime": "Tempo de execução", "runtime": "",
"load": "Carga", "load": "",
"input": "Entrada", "input": "",
"output": "Saída" "output": ""
}, },
"error": { "error": {
"internalServerError": "" "internalServerError": ""
@@ -2678,8 +2669,8 @@
} }
}, },
"paperlessNgx": { "paperlessNgx": {
"name": "Paperless-ngx", "name": "",
"description": "Visão geral do seu arquivo de documentos Paperless-ngx", "description": "",
"documentsTotal": "", "documentsTotal": "",
"documentsInbox": "", "documentsInbox": "",
"correspondents": "", "correspondents": "",
@@ -4142,7 +4133,7 @@
"items": { "items": {
"documentation": "Documentação", "documentation": "Documentação",
"submitIssue": "Enviar um problema", "submitIssue": "Enviar um problema",
"discord": "Discord da comunidade", "discord": "Discórdia da comunidade",
"sourceCode": "Código-fonte" "sourceCode": "Código-fonte"
} }
}, },
@@ -5750,7 +5741,7 @@
"label": "Reportar um problema" "label": "Reportar um problema"
}, },
"discord": { "discord": {
"label": "Discord da comunidade" "label": "Discórdia da comunidade"
} }
} }
} }
-9
View File
@@ -1739,15 +1739,6 @@
} }
} }
}, },
"archiveTeamWarrior": {
"name": "",
"description": "",
"option": {
"showBroadcastMessage": {
"label": ""
}
}
},
"dnsHoleSummary": { "dnsHoleSummary": {
"name": "", "name": "",
"description": "", "description": "",
-9
View File
@@ -1739,15 +1739,6 @@
} }
} }
}, },
"archiveTeamWarrior": {
"name": "",
"description": "",
"option": {
"showBroadcastMessage": {
"label": ""
}
}
},
"dnsHoleSummary": { "dnsHoleSummary": {
"name": "", "name": "",
"description": "", "description": "",
-9
View File
@@ -1739,15 +1739,6 @@
} }
} }
}, },
"archiveTeamWarrior": {
"name": "",
"description": "",
"option": {
"showBroadcastMessage": {
"label": ""
}
}
},
"dnsHoleSummary": { "dnsHoleSummary": {
"name": "Сводка DNS-фильтра", "name": "Сводка DNS-фильтра",
"description": "Отображает сводную информацию о вашем DNS-фильтре", "description": "Отображает сводную информацию о вашем DNS-фильтре",
-9
View File
@@ -1739,15 +1739,6 @@
} }
} }
}, },
"archiveTeamWarrior": {
"name": "",
"description": "",
"option": {
"showBroadcastMessage": {
"label": ""
}
}
},
"dnsHoleSummary": { "dnsHoleSummary": {
"name": "Zhrnutie dier DNS", "name": "Zhrnutie dier DNS",
"description": "Zobrazí súhrn vašej diery DNS", "description": "Zobrazí súhrn vašej diery DNS",
-9
View File
@@ -1739,15 +1739,6 @@
} }
} }
}, },
"archiveTeamWarrior": {
"name": "",
"description": "",
"option": {
"showBroadcastMessage": {
"label": ""
}
}
},
"dnsHoleSummary": { "dnsHoleSummary": {
"name": "", "name": "",
"description": "", "description": "",
-9
View File
@@ -1739,15 +1739,6 @@
} }
} }
}, },
"archiveTeamWarrior": {
"name": "",
"description": "",
"option": {
"showBroadcastMessage": {
"label": ""
}
}
},
"dnsHoleSummary": { "dnsHoleSummary": {
"name": "", "name": "",
"description": "", "description": "",
-9
View File
@@ -1739,15 +1739,6 @@
} }
} }
}, },
"archiveTeamWarrior": {
"name": "",
"description": "",
"option": {
"showBroadcastMessage": {
"label": ""
}
}
},
"dnsHoleSummary": { "dnsHoleSummary": {
"name": "DNS Çözümleyici Özeti", "name": "DNS Çözümleyici Özeti",
"description": "DNS Çözümleyici özetini görüntüler", "description": "DNS Çözümleyici özetini görüntüler",
-9
View File
@@ -1739,15 +1739,6 @@
} }
} }
}, },
"archiveTeamWarrior": {
"name": "",
"description": "",
"option": {
"showBroadcastMessage": {
"label": ""
}
}
},
"dnsHoleSummary": { "dnsHoleSummary": {
"name": "", "name": "",
"description": "", "description": "",
-9
View File
@@ -1739,15 +1739,6 @@
} }
} }
}, },
"archiveTeamWarrior": {
"name": "",
"description": "",
"option": {
"showBroadcastMessage": {
"label": ""
}
}
},
"dnsHoleSummary": { "dnsHoleSummary": {
"name": "", "name": "",
"description": "", "description": "",
-9
View File
@@ -1739,15 +1739,6 @@
} }
} }
}, },
"archiveTeamWarrior": {
"name": "",
"description": "",
"option": {
"showBroadcastMessage": {
"label": ""
}
}
},
"dnsHoleSummary": { "dnsHoleSummary": {
"name": "DNS Hole 概況", "name": "DNS Hole 概況",
"description": "顯示 DNS Hole 的概況", "description": "顯示 DNS Hole 的概況",
+463 -376
View File
File diff suppressed because it is too large. Load diff
+22 -22
View File
@@ -49,25 +49,25 @@ catalog:
"@tanstack/react-query": ^5.101.0 "@tanstack/react-query": ^5.101.0
"@tanstack/react-query-devtools": ^5.101.0 "@tanstack/react-query-devtools": ^5.101.0
"@tanstack/react-query-next-experimental": ^5.101.0 "@tanstack/react-query-next-experimental": ^5.101.0
"@testcontainers/mysql": ^12.0.2 "@testcontainers/mysql": ^12.0.1
"@testcontainers/postgresql": ^12.0.2 "@testcontainers/postgresql": ^12.0.1
"@testcontainers/redis": ^12.0.2 "@testcontainers/redis": ^12.0.1
"@tiptap/extension-color": 3.26.1 "@tiptap/extension-color": 3.26.0
"@tiptap/extension-highlight": 3.26.1 "@tiptap/extension-highlight": 3.26.0
"@tiptap/extension-image": 3.26.1 "@tiptap/extension-image": 3.26.0
"@tiptap/extension-link": ^3.26.1 "@tiptap/extension-link": ^3.26.0
"@tiptap/extension-placeholder": ^3.26.1 "@tiptap/extension-placeholder": ^3.26.0
"@tiptap/extension-table": 3.26.1 "@tiptap/extension-table": 3.26.0
"@tiptap/extension-table-cell": 3.26.1 "@tiptap/extension-table-cell": 3.26.0
"@tiptap/extension-table-header": 3.26.1 "@tiptap/extension-table-header": 3.26.0
"@tiptap/extension-table-row": 3.26.1 "@tiptap/extension-table-row": 3.26.0
"@tiptap/extension-task-item": 3.26.1 "@tiptap/extension-task-item": 3.26.0
"@tiptap/extension-task-list": 3.26.1 "@tiptap/extension-task-list": 3.26.0
"@tiptap/extension-text-align": 3.26.1 "@tiptap/extension-text-align": 3.26.0
"@tiptap/extension-text-style": 3.26.1 "@tiptap/extension-text-style": 3.26.0
"@tiptap/extension-underline": 3.26.1 "@tiptap/extension-underline": 3.26.0
"@tiptap/react": ^3.26.1 "@tiptap/react": ^3.26.0
"@tiptap/starter-kit": ^3.26.1 "@tiptap/starter-kit": ^3.26.0
"@trpc/client": ^11.17.0 "@trpc/client": ^11.17.0
"@trpc/next": ^11.17.0 "@trpc/next": ^11.17.0
"@trpc/react-query": ^11.17.0 "@trpc/react-query": ^11.17.0
@@ -88,7 +88,7 @@ catalog:
"@types/prismjs": ^1.26.6 "@types/prismjs": ^1.26.6
"@types/react": 19.2.17 "@types/react": 19.2.17
"@types/react-dom": 19.2.3 "@types/react-dom": 19.2.3
"@scalar/api-reference-react": ^0.9.46 "@scalar/api-reference-react": ^0.9.45
"@types/video.js": ^7.3.58 "@types/video.js": ^7.3.58
"@types/ws": ^8.18.1 "@types/ws": ^8.18.1
"@types/xml2js": ^0.4.14 "@types/xml2js": ^0.4.14
@@ -131,7 +131,7 @@ catalog:
ical.js: ^2.2.1 ical.js: ^2.2.1
ioredis: 5.11.1 ioredis: 5.11.1
isomorphic-dompurify: ^3.16.0 isomorphic-dompurify: ^3.16.0
jotai: ^2.20.1 jotai: ^2.20.0
jsdom: ^29.1.1 jsdom: ^29.1.1
json5: ^2.2.3 json5: ^2.2.3
jsonpath-plus: ^10.4.0 jsonpath-plus: ^10.4.0
@@ -168,7 +168,7 @@ catalog:
semver-parser: ^4.2.1 semver-parser: ^4.2.1
superjson: 2.2.6 superjson: 2.2.6
svgson: ^5.3.1 svgson: ^5.3.1
testcontainers: ^12.0.2 testcontainers: ^12.0.1
timezones-ical-library: ^2.2.0 timezones-ical-library: ^2.2.0
trpc-to-mcp: ^1.3.2 trpc-to-mcp: ^1.3.2
trpc-to-openapi: ^3.3.0 trpc-to-openapi: ^3.3.0