feat(desktop): add Tauri updater (GitHub Releases), updater UI button, hide PowerShell windows; fix Windows inventory arrays and activation; improve metrics parsing; branding rename to Raven across app; avoid localhost fallback in auth-server; inject APP_URL/AUTH_URL in stack
This commit is contained in:
parent
eb5f39100f
commit
418599ef62
18 changed files with 127 additions and 34 deletions
|
|
@ -103,6 +103,15 @@ export async function POST(request: Request) {
|
|||
} catch (error) {
|
||||
console.error("[machines.register] Falha no provisionamento", error)
|
||||
const details = error instanceof Error ? error.message : String(error)
|
||||
return jsonWithCors({ error: "Falha ao provisionar máquina", details }, 500, request.headers.get("origin"), CORS_METHODS)
|
||||
const msg = details.toLowerCase()
|
||||
// Mapear alguns erros "esperados" para códigos adequados
|
||||
// - empresa inválida → 404
|
||||
// - segredo inválido → 401
|
||||
// - demais ConvexError → 400
|
||||
const isCompanyNotFound = msg.includes("empresa não encontrada")
|
||||
const isInvalidSecret = msg.includes("código de provisionamento inválido")
|
||||
const isConvexError = msg.includes("convexerror")
|
||||
const status = isCompanyNotFound ? 404 : isInvalidSecret ? 401 : isConvexError ? 400 : 500
|
||||
return jsonWithCors({ error: "Falha ao provisionar máquina", details }, status, request.headers.get("origin"), CORS_METHODS)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ export default async function InvitePage({ params }: { params: Promise<{ token:
|
|||
<CardHeader className="space-y-2 text-center">
|
||||
<CardTitle className="text-2xl font-semibold text-neutral-900">Aceitar convite</CardTitle>
|
||||
<CardDescription className="text-sm text-neutral-600">
|
||||
Conclua seu cadastro para acessar a plataforma Sistema de chamados.
|
||||
Conclua seu cadastro para acessar a plataforma Raven.
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
|
|
|
|||
|
|
@ -18,8 +18,8 @@ const jetBrainsMono = JetBrains_Mono({
|
|||
})
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "Sistema de chamados",
|
||||
description: "Plataforma de chamados da Rever",
|
||||
title: "Raven",
|
||||
description: "Plataforma Raven da Rever",
|
||||
icons: {
|
||||
icon: "/rever-8.png",
|
||||
},
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ export function LoginPageClient() {
|
|||
<div className="bg-primary text-primary-foreground flex size-6 items-center justify-center rounded-md">
|
||||
<GalleryVerticalEnd className="size-4" />
|
||||
</div>
|
||||
Sistema de chamados
|
||||
Raven
|
||||
</Link>
|
||||
</div>
|
||||
<div className="flex flex-1 items-center justify-center">
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ const ERROR_TEMPLATE = `
|
|||
<h1>Não foi possível autenticar esta máquina</h1>
|
||||
<p>O token informado é inválido, expirou ou não está mais associado a uma máquina ativa.</p>
|
||||
<p>Volte ao agente desktop, gere um novo token ou realize o provisionamento novamente.</p>
|
||||
<a href="/">Voltar para o Sistema de Chamados</a>
|
||||
<a href="/">Voltar para o Raven</a>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -61,4 +61,3 @@ export async function GET(request: NextRequest) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1354,8 +1354,27 @@ function DetailLine({ label, value, classNameValue }: DetailLineProps) {
|
|||
|
||||
function MetricsGrid({ metrics }: { metrics: MachineMetrics }) {
|
||||
const data = (metrics ?? {}) as Record<string, unknown>
|
||||
const cpu = Number(data.cpuUsage ?? data.cpu ?? data.cpu_percent ?? NaN)
|
||||
const memory = Number(data.memoryBytes ?? data.memory ?? data.memory_used ?? NaN)
|
||||
// Compat: aceitar chaves do agente desktop (cpuUsagePercent, memoryUsedBytes, memoryTotalBytes)
|
||||
const cpu = (() => {
|
||||
const v = Number(
|
||||
data.cpuUsage ?? data.cpu ?? data.cpu_percent ?? data.cpuUsagePercent ?? NaN
|
||||
)
|
||||
return v
|
||||
})()
|
||||
const memory = (() => {
|
||||
// valor absoluto em bytes, se disponível
|
||||
const memBytes = Number(
|
||||
data.memoryBytes ?? data.memory ?? data.memory_used ?? data.memoryUsedBytes ?? NaN
|
||||
)
|
||||
if (Number.isFinite(memBytes)) return memBytes
|
||||
// tentar derivar a partir de percentuais do agente
|
||||
const usedPct = Number(data.memoryUsedPercent ?? NaN)
|
||||
const totalBytes = Number(data.memoryTotalBytes ?? NaN)
|
||||
if (Number.isFinite(usedPct) && Number.isFinite(totalBytes)) {
|
||||
return Math.max(0, Math.min(1, usedPct > 1 ? usedPct / 100 : usedPct)) * totalBytes
|
||||
}
|
||||
return NaN
|
||||
})()
|
||||
const disk = Number(data.diskUsage ?? data.disk ?? NaN)
|
||||
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -164,7 +164,7 @@ export function AppSidebar({ ...props }: React.ComponentProps<typeof Sidebar>) {
|
|||
<Sidebar {...props}>
|
||||
<SidebarHeader className="gap-3">
|
||||
<VersionSwitcher
|
||||
label="Sistema de chamados"
|
||||
label="Raven"
|
||||
versions={[...navigation.versions]}
|
||||
defaultVersion={navigation.versions[0]}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ export function PortalShell({ children }: PortalShellProps) {
|
|||
<span className="text-xs font-semibold uppercase tracking-[0.28em] text-neutral-500">
|
||||
Portal do cliente
|
||||
</span>
|
||||
<span className="text-lg font-semibold text-neutral-900">Sistema de chamados</span>
|
||||
<span className="text-lg font-semibold text-neutral-900">Raven</span>
|
||||
</div>
|
||||
<nav className="flex items-center gap-3 text-sm font-medium">
|
||||
{navItems.map((item) => {
|
||||
|
|
@ -112,7 +112,7 @@ export function PortalShell({ children }: PortalShellProps) {
|
|||
</main>
|
||||
<footer className="border-t border-slate-200 bg-white/70">
|
||||
<div className="mx-auto flex w-full max-w-6xl items-center justify-between px-6 py-4 text-xs text-neutral-500">
|
||||
<span>© {new Date().getFullYear()} Sistema de chamados</span>
|
||||
<span>© {new Date().getFullYear()} Raven</span>
|
||||
<span>Suporte: suporte@sistema.dev</span>
|
||||
</div>
|
||||
</footer>
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ export function BackgroundPaperShaders({ className }: { className?: string }) {
|
|||
<div className="relative h-[420px] w-[420px] overflow-hidden rounded-full">
|
||||
<ShaderVisual />
|
||||
<div className="pointer-events-none absolute inset-0 flex flex-col items-center justify-center px-10 text-center text-white">
|
||||
<div className="text-sm uppercase tracking-[0.32em] text-white/50">Sistema de Chamados</div>
|
||||
<div className="text-sm uppercase tracking-[0.32em] text-white/50">Raven</div>
|
||||
<h2 className="mt-4 text-xl font-semibold md:text-2xl">Atendimento moderno e colaborativo</h2>
|
||||
<p className="mt-3 text-sm text-white/70">
|
||||
Tenha visão unificada de todos os canais, monitore SLAs em tempo real e mantenha os clientes informados
|
||||
|
|
|
|||
|
|
@ -24,7 +24,14 @@ async function buildRequest() {
|
|||
headerList.get("x-client-ip") ||
|
||||
undefined
|
||||
|
||||
return new Request(env.BETTER_AUTH_URL ?? "http://localhost:3000", {
|
||||
// Evitar fallback para localhost em produção: tenta BETTER_AUTH_URL,
|
||||
// depois NEXT_PUBLIC_APP_URL e, por fim, o host do próprio request.
|
||||
const forwardedProto = headerList.get("x-forwarded-proto")
|
||||
const forwardedHost = headerList.get("x-forwarded-host") ?? headerList.get("host")
|
||||
const requestOrigin = forwardedProto && forwardedHost ? `${forwardedProto}://${forwardedHost}` : undefined
|
||||
const baseUrl = env.BETTER_AUTH_URL || env.NEXT_PUBLIC_APP_URL || requestOrigin || "http://localhost:3000"
|
||||
|
||||
return new Request(baseUrl, {
|
||||
headers: {
|
||||
cookie: cookieHeader,
|
||||
"user-agent": userAgent,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue