fix: lint

This commit is contained in:
Mauricio Siu
2024-12-07 13:50:38 -06:00
parent 64e6919211
commit 1c1e52f777
17 changed files with 1475 additions and 1475 deletions

View File

@@ -68,7 +68,7 @@ export const ComposeActions = ({ composeId }: Props) => {
Open Terminal Open Terminal
</Button> </Button>
</DockerTerminalModal> </DockerTerminalModal>
<div className="flex flex-row items-center gap-2 rounded-md px-4 py-2 border"> <div className="flex flex-row items-center gap-2 rounded-md px-4 py-2 border">
<span className="text-sm font-medium">Autodeploy</span> <span className="text-sm font-medium">Autodeploy</span>
<Switch <Switch
aria-label="Toggle italic" aria-label="Toggle italic"

View File

@@ -1,94 +1,96 @@
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { import {
Dialog, Dialog,
DialogContent, DialogContent,
DialogDescription, DialogDescription,
DialogFooter, DialogFooter,
DialogHeader, DialogHeader,
DialogTitle, DialogTitle,
DialogTrigger, DialogTrigger,
} from "@/components/ui/dialog"; } from "@/components/ui/dialog";
import { DropdownMenuItem } from "@/components/ui/dropdown-menu"; import { DropdownMenuItem } from "@/components/ui/dropdown-menu";
import dynamic from "next/dynamic"; import dynamic from "next/dynamic";
import { useState } from "react"; import { useState } from "react";
const Terminal = dynamic( const Terminal = dynamic(
() => import("./docker-terminal").then((e) => e.DockerTerminal), () => import("./docker-terminal").then((e) => e.DockerTerminal),
{ {
ssr: false, ssr: false,
} },
); );
interface Props { interface Props {
containerId: string; containerId: string;
serverId?: string; serverId?: string;
children?: React.ReactNode; children?: React.ReactNode;
} }
export const DockerTerminalModal = ({ export const DockerTerminalModal = ({
children, children,
containerId, containerId,
serverId, serverId,
}: Props) => { }: Props) => {
const [mainDialogOpen, setMainDialogOpen] = useState(false); const [mainDialogOpen, setMainDialogOpen] = useState(false);
const [confirmDialogOpen, setConfirmDialogOpen] = useState(false); const [confirmDialogOpen, setConfirmDialogOpen] = useState(false);
const handleMainDialogOpenChange = (open: boolean) => { const handleMainDialogOpenChange = (open: boolean) => {
if (!open) { if (!open) {
setConfirmDialogOpen(true); setConfirmDialogOpen(true);
} else { } else {
setMainDialogOpen(true); setMainDialogOpen(true);
} }
}; };
const handleConfirm = () => { const handleConfirm = () => {
setConfirmDialogOpen(false); setConfirmDialogOpen(false);
setMainDialogOpen(false); setMainDialogOpen(false);
}; };
const handleCancel = () => { const handleCancel = () => {
setConfirmDialogOpen(false); setConfirmDialogOpen(false);
}; };
return ( return (
<Dialog open={mainDialogOpen} onOpenChange={handleMainDialogOpenChange}> <Dialog open={mainDialogOpen} onOpenChange={handleMainDialogOpenChange}>
<DialogTrigger asChild> <DialogTrigger asChild>
<DropdownMenuItem <DropdownMenuItem
className="w-full cursor-pointer space-x-3" className="w-full cursor-pointer space-x-3"
onSelect={(e) => e.preventDefault()} onSelect={(e) => e.preventDefault()}
> >
{children} {children}
</DropdownMenuItem> </DropdownMenuItem>
</DialogTrigger> </DialogTrigger>
<DialogContent className="max-h-screen overflow-y-auto sm:max-w-7xl"> <DialogContent className="max-h-screen overflow-y-auto sm:max-w-7xl">
<DialogHeader> <DialogHeader>
<DialogTitle>Docker Terminal</DialogTitle> <DialogTitle>Docker Terminal</DialogTitle>
<DialogDescription> <DialogDescription>
Easy way to access to docker container Easy way to access to docker container
</DialogDescription> </DialogDescription>
</DialogHeader> </DialogHeader>
<Terminal <Terminal
id="terminal" id="terminal"
containerId={containerId} containerId={containerId}
serverId={serverId || ""} serverId={serverId || ""}
/> />
<Dialog open={confirmDialogOpen} onOpenChange={setConfirmDialogOpen}> <Dialog open={confirmDialogOpen} onOpenChange={setConfirmDialogOpen}>
<DialogContent> <DialogContent>
<DialogHeader> <DialogHeader>
<DialogTitle>Are you sure you want to close the terminal?</DialogTitle> <DialogTitle>
<DialogDescription> Are you sure you want to close the terminal?
By clicking the confirm button, the terminal will be closed. </DialogTitle>
</DialogDescription> <DialogDescription>
</DialogHeader> By clicking the confirm button, the terminal will be closed.
<DialogFooter> </DialogDescription>
<Button variant="outline" onClick={handleCancel}> </DialogHeader>
Cancel <DialogFooter>
</Button> <Button variant="outline" onClick={handleCancel}>
<Button onClick={handleConfirm}>Confirm</Button> Cancel
</DialogFooter> </Button>
</DialogContent> <Button onClick={handleConfirm}>Confirm</Button>
</Dialog> </DialogFooter>
</DialogContent> </DialogContent>
</Dialog> </Dialog>
); </DialogContent>
</Dialog>
);
}; };

View File

@@ -27,12 +27,12 @@ import {
SelectTrigger, SelectTrigger,
SelectValue, SelectValue,
} from "@/components/ui/select"; } from "@/components/ui/select";
import { Languages } from "@/lib/languages";
import useLocale from "@/utils/hooks/use-locale"; import useLocale from "@/utils/hooks/use-locale";
import { useTranslation } from "next-i18next"; import { useTranslation } from "next-i18next";
import { useTheme } from "next-themes"; import { useTheme } from "next-themes";
import { useEffect } from "react"; import { useEffect } from "react";
import { toast } from "sonner"; import { toast } from "sonner";
import { Languages } from "@/lib/languages";
const appearanceFormSchema = z.object({ const appearanceFormSchema = z.object({
theme: z.enum(["light", "dark", "system"], { theme: z.enum(["light", "dark", "system"], {

View File

@@ -1,22 +1,22 @@
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { import {
Dialog, Dialog,
DialogContent, DialogContent,
DialogDescription, DialogDescription,
DialogFooter, DialogFooter,
DialogHeader, DialogHeader,
DialogTitle, DialogTitle,
DialogTrigger, DialogTrigger,
} from "@/components/ui/dialog"; } from "@/components/ui/dialog";
import { Label } from "@/components/ui/label"; import { Label } from "@/components/ui/label";
import { import {
Select, Select,
SelectContent, SelectContent,
SelectGroup, SelectGroup,
SelectItem, SelectItem,
SelectLabel, SelectLabel,
SelectTrigger, SelectTrigger,
SelectValue, SelectValue,
} from "@/components/ui/select"; } from "@/components/ui/select";
import { api } from "@/utils/api"; import { api } from "@/utils/api";
import { Loader2 } from "lucide-react"; import { Loader2 } from "lucide-react";
@@ -25,118 +25,118 @@ import type React from "react";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
const Terminal = dynamic( const Terminal = dynamic(
() => () =>
import("@/components/dashboard/docker/terminal/docker-terminal").then( import("@/components/dashboard/docker/terminal/docker-terminal").then(
(e) => e.DockerTerminal (e) => e.DockerTerminal,
), ),
{ {
ssr: false, ssr: false,
} },
); );
interface Props { interface Props {
appName: string; appName: string;
children?: React.ReactNode; children?: React.ReactNode;
serverId?: string; serverId?: string;
} }
export const DockerTerminalModal = ({ children, appName, serverId }: Props) => { export const DockerTerminalModal = ({ children, appName, serverId }: Props) => {
const { data, isLoading } = api.docker.getContainersByAppNameMatch.useQuery( const { data, isLoading } = api.docker.getContainersByAppNameMatch.useQuery(
{ {
appName, appName,
serverId, serverId,
}, },
{ {
enabled: !!appName, enabled: !!appName,
} },
); );
const [containerId, setContainerId] = useState<string | undefined>(); const [containerId, setContainerId] = useState<string | undefined>();
const [mainDialogOpen, setMainDialogOpen] = useState(false); const [mainDialogOpen, setMainDialogOpen] = useState(false);
const [confirmDialogOpen, setConfirmDialogOpen] = useState(false); const [confirmDialogOpen, setConfirmDialogOpen] = useState(false);
const handleMainDialogOpenChange = (open: boolean) => { const handleMainDialogOpenChange = (open: boolean) => {
if (!open) { if (!open) {
setConfirmDialogOpen(true); setConfirmDialogOpen(true);
} else { } else {
setMainDialogOpen(true); setMainDialogOpen(true);
} }
}; };
const handleConfirm = () => { const handleConfirm = () => {
setConfirmDialogOpen(false); setConfirmDialogOpen(false);
setMainDialogOpen(false); setMainDialogOpen(false);
}; };
const handleCancel = () => { const handleCancel = () => {
setConfirmDialogOpen(false); setConfirmDialogOpen(false);
}; };
useEffect(() => { useEffect(() => {
if (data && data?.length > 0) { if (data && data?.length > 0) {
setContainerId(data[0]?.containerId); setContainerId(data[0]?.containerId);
} }
}, [data]); }, [data]);
return ( return (
<Dialog open={mainDialogOpen} onOpenChange={handleMainDialogOpenChange}> <Dialog open={mainDialogOpen} onOpenChange={handleMainDialogOpenChange}>
<DialogTrigger asChild>{children}</DialogTrigger> <DialogTrigger asChild>{children}</DialogTrigger>
<DialogContent className="max-h-[85vh] overflow-y-auto sm:max-w-7xl"> <DialogContent className="max-h-[85vh] overflow-y-auto sm:max-w-7xl">
<DialogHeader> <DialogHeader>
<DialogTitle>Docker Terminal</DialogTitle> <DialogTitle>Docker Terminal</DialogTitle>
<DialogDescription> <DialogDescription>
Easy way to access to docker container Easy way to access to docker container
</DialogDescription> </DialogDescription>
</DialogHeader> </DialogHeader>
<Label>Select a container to view logs</Label> <Label>Select a container to view logs</Label>
<Select onValueChange={setContainerId} value={containerId}> <Select onValueChange={setContainerId} value={containerId}>
<SelectTrigger> <SelectTrigger>
{isLoading ? ( {isLoading ? (
<div className="flex flex-row gap-2 items-center justify-center text-sm text-muted-foreground"> <div className="flex flex-row gap-2 items-center justify-center text-sm text-muted-foreground">
<span>Loading...</span> <span>Loading...</span>
<Loader2 className="animate-spin size-4" /> <Loader2 className="animate-spin size-4" />
</div> </div>
) : ( ) : (
<SelectValue placeholder="Select a container" /> <SelectValue placeholder="Select a container" />
)} )}
</SelectTrigger> </SelectTrigger>
<SelectContent> <SelectContent>
<SelectGroup> <SelectGroup>
{data?.map((container) => ( {data?.map((container) => (
<SelectItem <SelectItem
key={container.containerId} key={container.containerId}
value={container.containerId} value={container.containerId}
> >
{container.name} ({container.containerId}) {container.state} {container.name} ({container.containerId}) {container.state}
</SelectItem> </SelectItem>
))} ))}
<SelectLabel>Containers ({data?.length})</SelectLabel> <SelectLabel>Containers ({data?.length})</SelectLabel>
</SelectGroup> </SelectGroup>
</SelectContent> </SelectContent>
</Select> </Select>
<Terminal <Terminal
serverId={serverId || ""} serverId={serverId || ""}
id="terminal" id="terminal"
containerId={containerId || "select-a-container"} containerId={containerId || "select-a-container"}
/> />
<Dialog open={confirmDialogOpen} onOpenChange={setConfirmDialogOpen}> <Dialog open={confirmDialogOpen} onOpenChange={setConfirmDialogOpen}>
<DialogContent> <DialogContent>
<DialogHeader> <DialogHeader>
<DialogTitle> <DialogTitle>
Are you sure you want to close the terminal? Are you sure you want to close the terminal?
</DialogTitle> </DialogTitle>
<DialogDescription> <DialogDescription>
By clicking the confirm button, the terminal will be closed. By clicking the confirm button, the terminal will be closed.
</DialogDescription> </DialogDescription>
</DialogHeader> </DialogHeader>
<DialogFooter> <DialogFooter>
<Button variant="outline" onClick={handleCancel}> <Button variant="outline" onClick={handleCancel}>
Cancel Cancel
</Button> </Button>
<Button onClick={handleConfirm}>Confirm</Button> <Button onClick={handleConfirm}>Confirm</Button>
</DialogFooter> </DialogFooter>
</DialogContent> </DialogContent>
</Dialog> </Dialog>
</DialogContent> </DialogContent>
</Dialog> </Dialog>
); );
}; };

View File

@@ -1,25 +1,23 @@
/** @type {import('next-i18next').UserConfig} */ /** @type {import('next-i18next').UserConfig} */
module.exports = { module.exports = {
fallbackLng: "en", fallbackLng: "en",
keySeparator: false, keySeparator: false,
i18n: { i18n: {
defaultLocale: "en", defaultLocale: "en",
locales: [ locales: [
"en", "en",
"pl", "pl",
"ru", "ru",
"fr", "fr",
"de", "de",
"tr", "tr",
"kz", "kz",
"zh-Hant", "zh-Hant",
"zh-Hans", "zh-Hans",
"fa", "fa",
"ko", "ko",
"pt-br", "pt-br",
], ],
localeDetection: false, localeDetection: false,
}, },
}; };

View File

@@ -1,6 +1,7 @@
import "@/styles/globals.css"; import "@/styles/globals.css";
import { Toaster } from "@/components/ui/sonner"; import { Toaster } from "@/components/ui/sonner";
import { Languages } from "@/lib/languages";
import { api } from "@/utils/api"; import { api } from "@/utils/api";
import type { NextPage } from "next"; import type { NextPage } from "next";
import { appWithTranslation } from "next-i18next"; import { appWithTranslation } from "next-i18next";
@@ -10,7 +11,6 @@ import { Inter } from "next/font/google";
import Head from "next/head"; import Head from "next/head";
import Script from "next/script"; import Script from "next/script";
import type { ReactElement, ReactNode } from "react"; import type { ReactElement, ReactNode } from "react";
import { Languages } from "@/lib/languages";
const inter = Inter({ subsets: ["latin"] }); const inter = Inter({ subsets: ["latin"] });

View File

@@ -10,142 +10,141 @@ import type { NextApiRequest, NextApiResponse } from "next";
import { extractCommitMessage, extractHash } from "./[refreshToken]"; import { extractCommitMessage, extractHash } from "./[refreshToken]";
export default async function handler( export default async function handler(
req: NextApiRequest, req: NextApiRequest,
res: NextApiResponse res: NextApiResponse,
) { ) {
const signature = req.headers["x-hub-signature-256"]; const signature = req.headers["x-hub-signature-256"];
const githubBody = req.body; const githubBody = req.body;
if (!githubBody?.installation?.id) { if (!githubBody?.installation?.id) {
res.status(400).json({ message: "Github Installation not found" }); res.status(400).json({ message: "Github Installation not found" });
return; return;
} }
const githubResult = await db.query.github.findFirst({ const githubResult = await db.query.github.findFirst({
where: eq(github.githubInstallationId, githubBody.installation.id), where: eq(github.githubInstallationId, githubBody.installation.id),
}); });
if (!githubResult) { if (!githubResult) {
res.status(400).json({ message: "Github Installation not found" }); res.status(400).json({ message: "Github Installation not found" });
return; return;
} }
if (!githubResult.githubWebhookSecret) { if (!githubResult.githubWebhookSecret) {
res.status(400).json({ message: "Github Webhook Secret not set" }); res.status(400).json({ message: "Github Webhook Secret not set" });
return; return;
} }
const webhooks = new Webhooks({ const webhooks = new Webhooks({
secret: githubResult.githubWebhookSecret, secret: githubResult.githubWebhookSecret,
}); });
const verified = await webhooks.verify( const verified = await webhooks.verify(
JSON.stringify(githubBody), JSON.stringify(githubBody),
signature as string signature as string,
); );
if (!verified) { if (!verified) {
res.status(401).json({ message: "Unauthorized" }); res.status(401).json({ message: "Unauthorized" });
return; return;
} }
if (req.headers["x-github-event"] === "ping") { if (req.headers["x-github-event"] === "ping") {
res.status(200).json({ message: "Ping received, webhook is active" }); res.status(200).json({ message: "Ping received, webhook is active" });
return; return;
} }
if (req.headers["x-github-event"] !== "push") { if (req.headers["x-github-event"] !== "push") {
res.status(400).json({ message: "We only accept push events" }); res.status(400).json({ message: "We only accept push events" });
return; return;
} }
try { try {
const branchName = githubBody?.ref?.replace("refs/heads/", ""); const branchName = githubBody?.ref?.replace("refs/heads/", "");
const repository = githubBody?.repository?.name; const repository = githubBody?.repository?.name;
const deploymentTitle = extractCommitMessage(req.headers, req.body); const deploymentTitle = extractCommitMessage(req.headers, req.body);
const deploymentHash = extractHash(req.headers, req.body); const deploymentHash = extractHash(req.headers, req.body);
const owner = githubBody?.repository?.owner?.name; const owner = githubBody?.repository?.owner?.name;
const apps = await db.query.applications.findMany({
where: and(
eq(applications.sourceType, "github"),
eq(applications.autoDeploy, true),
eq(applications.branch, branchName),
eq(applications.repository, repository),
eq(applications.owner, owner),
),
});
const apps = await db.query.applications.findMany({ for (const app of apps) {
where: and( const jobData: DeploymentJob = {
eq(applications.sourceType, "github"), applicationId: app.applicationId as string,
eq(applications.autoDeploy, true), titleLog: deploymentTitle,
eq(applications.branch, branchName), descriptionLog: `Hash: ${deploymentHash}`,
eq(applications.repository, repository), type: "deploy",
eq(applications.owner, owner) applicationType: "application",
), server: !!app.serverId,
}); };
for (const app of apps) { if (IS_CLOUD && app.serverId) {
const jobData: DeploymentJob = { jobData.serverId = app.serverId;
applicationId: app.applicationId as string, await deploy(jobData);
titleLog: deploymentTitle, return true;
descriptionLog: `Hash: ${deploymentHash}`, }
type: "deploy", await myQueue.add(
applicationType: "application", "deployments",
server: !!app.serverId, { ...jobData },
}; {
removeOnComplete: true,
removeOnFail: true,
},
);
}
if (IS_CLOUD && app.serverId) { const composeApps = await db.query.compose.findMany({
jobData.serverId = app.serverId; where: and(
await deploy(jobData); eq(compose.sourceType, "github"),
return true; eq(compose.autoDeploy, true),
} eq(compose.branch, branchName),
await myQueue.add( eq(compose.repository, repository),
"deployments", eq(compose.owner, owner),
{ ...jobData }, ),
{ });
removeOnComplete: true,
removeOnFail: true,
}
);
}
const composeApps = await db.query.compose.findMany({ for (const composeApp of composeApps) {
where: and( const jobData: DeploymentJob = {
eq(compose.sourceType, "github"), composeId: composeApp.composeId as string,
eq(compose.autoDeploy, true), titleLog: deploymentTitle,
eq(compose.branch, branchName), type: "deploy",
eq(compose.repository, repository), applicationType: "compose",
eq(compose.owner, owner) descriptionLog: `Hash: ${deploymentHash}`,
), server: !!composeApp.serverId,
}); };
for (const composeApp of composeApps) { if (IS_CLOUD && composeApp.serverId) {
const jobData: DeploymentJob = { jobData.serverId = composeApp.serverId;
composeId: composeApp.composeId as string, await deploy(jobData);
titleLog: deploymentTitle, return true;
type: "deploy", }
applicationType: "compose",
descriptionLog: `Hash: ${deploymentHash}`,
server: !!composeApp.serverId,
};
if (IS_CLOUD && composeApp.serverId) { await myQueue.add(
jobData.serverId = composeApp.serverId; "deployments",
await deploy(jobData); { ...jobData },
return true; {
} removeOnComplete: true,
removeOnFail: true,
},
);
}
await myQueue.add( const totalApps = apps.length + composeApps.length;
"deployments", const emptyApps = totalApps === 0;
{ ...jobData },
{
removeOnComplete: true,
removeOnFail: true,
}
);
}
const totalApps = apps.length + composeApps.length; if (emptyApps) {
const emptyApps = totalApps === 0; res.status(200).json({ message: "No apps to deploy" });
return;
if (emptyApps) { }
res.status(200).json({ message: "No apps to deploy" }); res.status(200).json({ message: `Deployed ${totalApps} apps` });
return; } catch (error) {
} res.status(400).json({ message: "Error To Deploy Application", error });
res.status(200).json({ message: `Deployed ${totalApps} apps` }); }
} catch (error) {
res.status(400).json({ message: "Error To Deploy Application", error });
}
} }

View File

@@ -1,44 +1,44 @@
{ {
"settings.common.save": "저장", "settings.common.save": "저장",
"settings.server.domain.title": "서버 도메인", "settings.server.domain.title": "서버 도메인",
"settings.server.domain.description": "서버 애플리케이션에 도메인을 추가합니다.", "settings.server.domain.description": "서버 애플리케이션에 도메인을 추가합니다.",
"settings.server.domain.form.domain": "도메인", "settings.server.domain.form.domain": "도메인",
"settings.server.domain.form.letsEncryptEmail": "Let's Encrypt 이메일", "settings.server.domain.form.letsEncryptEmail": "Let's Encrypt 이메일",
"settings.server.domain.form.certificate.label": "인증서", "settings.server.domain.form.certificate.label": "인증서",
"settings.server.domain.form.certificate.placeholder": "인증서 선택", "settings.server.domain.form.certificate.placeholder": "인증서 선택",
"settings.server.domain.form.certificateOptions.none": "없음", "settings.server.domain.form.certificateOptions.none": "없음",
"settings.server.domain.form.certificateOptions.letsencrypt": "Let's Encrypt (기본)", "settings.server.domain.form.certificateOptions.letsencrypt": "Let's Encrypt (기본)",
"settings.server.webServer.title": "웹 서버", "settings.server.webServer.title": "웹 서버",
"settings.server.webServer.description": "웹 서버를 재시작하거나 정리합니다.", "settings.server.webServer.description": "웹 서버를 재시작하거나 정리합니다.",
"settings.server.webServer.actions": "작업", "settings.server.webServer.actions": "작업",
"settings.server.webServer.reload": "재시작", "settings.server.webServer.reload": "재시작",
"settings.server.webServer.watchLogs": "로그 보기", "settings.server.webServer.watchLogs": "로그 보기",
"settings.server.webServer.updateServerIp": "서버 IP 갱신", "settings.server.webServer.updateServerIp": "서버 IP 갱신",
"settings.server.webServer.server.label": "서버", "settings.server.webServer.server.label": "서버",
"settings.server.webServer.traefik.label": "Traefik", "settings.server.webServer.traefik.label": "Traefik",
"settings.server.webServer.traefik.modifyEnv": "환경 변수 수정", "settings.server.webServer.traefik.modifyEnv": "환경 변수 수정",
"settings.server.webServer.storage.label": "저장 공간", "settings.server.webServer.storage.label": "저장 공간",
"settings.server.webServer.storage.cleanUnusedImages": "사용하지 않는 이미지 정리", "settings.server.webServer.storage.cleanUnusedImages": "사용하지 않는 이미지 정리",
"settings.server.webServer.storage.cleanUnusedVolumes": "사용하지 않는 볼륨 정리", "settings.server.webServer.storage.cleanUnusedVolumes": "사용하지 않는 볼륨 정리",
"settings.server.webServer.storage.cleanStoppedContainers": "정지된 컨테이너 정리", "settings.server.webServer.storage.cleanStoppedContainers": "정지된 컨테이너 정리",
"settings.server.webServer.storage.cleanDockerBuilder": "도커 빌더 & 시스템 정리", "settings.server.webServer.storage.cleanDockerBuilder": "도커 빌더 & 시스템 정리",
"settings.server.webServer.storage.cleanMonitoring": "모니터링 데이터 정리", "settings.server.webServer.storage.cleanMonitoring": "모니터링 데이터 정리",
"settings.server.webServer.storage.cleanAll": "전체 정리", "settings.server.webServer.storage.cleanAll": "전체 정리",
"settings.profile.title": "계정", "settings.profile.title": "계정",
"settings.profile.description": "여기에서 프로필 세부 정보를 변경하세요.", "settings.profile.description": "여기에서 프로필 세부 정보를 변경하세요.",
"settings.profile.email": "이메일", "settings.profile.email": "이메일",
"settings.profile.password": "비밀번호", "settings.profile.password": "비밀번호",
"settings.profile.avatar": "아바타", "settings.profile.avatar": "아바타",
"settings.appearance.title": "외관", "settings.appearance.title": "외관",
"settings.appearance.description": "대시보드의 테마를 사용자 설정합니다.", "settings.appearance.description": "대시보드의 테마를 사용자 설정합니다.",
"settings.appearance.theme": "테마", "settings.appearance.theme": "테마",
"settings.appearance.themeDescription": "대시보드 테마 선택", "settings.appearance.themeDescription": "대시보드 테마 선택",
"settings.appearance.themes.light": "라이트", "settings.appearance.themes.light": "라이트",
"settings.appearance.themes.dark": "다크", "settings.appearance.themes.dark": "다크",
"settings.appearance.themes.system": "시스템", "settings.appearance.themes.system": "시스템",
"settings.appearance.language": "언어", "settings.appearance.language": "언어",
"settings.appearance.languageDescription": "대시보드에서 사용할 언어 선택" "settings.appearance.languageDescription": "대시보드에서 사용할 언어 선택"
} }

View File

@@ -1 +1 @@
{} {}

View File

@@ -1,41 +1,41 @@
{ {
"settings.common.save": "Сақтау", "settings.common.save": "Сақтау",
"settings.server.domain.title": "Сервер домені", "settings.server.domain.title": "Сервер домені",
"settings.server.domain.description": "Dokploy сервер қолданбасына домен енгізіңіз.", "settings.server.domain.description": "Dokploy сервер қолданбасына домен енгізіңіз.",
"settings.server.domain.form.domain": "Домен", "settings.server.domain.form.domain": "Домен",
"settings.server.domain.form.letsEncryptEmail": "Let's Encrypt Эл. поштасы", "settings.server.domain.form.letsEncryptEmail": "Let's Encrypt Эл. поштасы",
"settings.server.domain.form.certificate.label": "Сертификат", "settings.server.domain.form.certificate.label": "Сертификат",
"settings.server.domain.form.certificate.placeholder": "Сертификатты таңдаңыз", "settings.server.domain.form.certificate.placeholder": "Сертификатты таңдаңыз",
"settings.server.domain.form.certificateOptions.none": "Жоқ", "settings.server.domain.form.certificateOptions.none": "Жоқ",
"settings.server.domain.form.certificateOptions.letsencrypt": "Let's Encrypt (Стандартты)", "settings.server.domain.form.certificateOptions.letsencrypt": "Let's Encrypt (Стандартты)",
"settings.server.webServer.title": "Веб-Сервер", "settings.server.webServer.title": "Веб-Сервер",
"settings.server.webServer.description": "Веб-серверді қайта жүктеу немесе тазалау.", "settings.server.webServer.description": "Веб-серверді қайта жүктеу немесе тазалау.",
"settings.server.webServer.actions": "Әрекеттер", "settings.server.webServer.actions": "Әрекеттер",
"settings.server.webServer.reload": "Қайта жүктеу", "settings.server.webServer.reload": "Қайта жүктеу",
"settings.server.webServer.watchLogs": "Журналдарды қарау", "settings.server.webServer.watchLogs": "Журналдарды қарау",
"settings.server.webServer.updateServerIp": "Сервердің IP жаңарту", "settings.server.webServer.updateServerIp": "Сервердің IP жаңарту",
"settings.server.webServer.server.label": "Сервер", "settings.server.webServer.server.label": "Сервер",
"settings.server.webServer.traefik.label": "Traefik", "settings.server.webServer.traefik.label": "Traefik",
"settings.server.webServer.traefik.modifyEnv": "Env Өзгерту", "settings.server.webServer.traefik.modifyEnv": "Env Өзгерту",
"settings.server.webServer.storage.label": "Диск кеңістігі", "settings.server.webServer.storage.label": "Диск кеңістігі",
"settings.server.webServer.storage.cleanUnusedImages": "Пайдаланылмаған образды тазалау", "settings.server.webServer.storage.cleanUnusedImages": "Пайдаланылмаған образды тазалау",
"settings.server.webServer.storage.cleanUnusedVolumes": "Пайдаланылмаған томды тазалау", "settings.server.webServer.storage.cleanUnusedVolumes": "Пайдаланылмаған томды тазалау",
"settings.server.webServer.storage.cleanStoppedContainers": "Тоқтатылған контейнерлерді тазалау", "settings.server.webServer.storage.cleanStoppedContainers": "Тоқтатылған контейнерлерді тазалау",
"settings.server.webServer.storage.cleanDockerBuilder": "Docker Builder & Системаны тазалау", "settings.server.webServer.storage.cleanDockerBuilder": "Docker Builder & Системаны тазалау",
"settings.server.webServer.storage.cleanMonitoring": "Мониторингті тазалау", "settings.server.webServer.storage.cleanMonitoring": "Мониторингті тазалау",
"settings.server.webServer.storage.cleanAll": "Барлығын тазалау", "settings.server.webServer.storage.cleanAll": "Барлығын тазалау",
"settings.profile.title": "Аккаунт", "settings.profile.title": "Аккаунт",
"settings.profile.description": "Профиль мәліметтерін осы жерден өзгертіңіз.", "settings.profile.description": "Профиль мәліметтерін осы жерден өзгертіңіз.",
"settings.profile.email": "Эл. пошта", "settings.profile.email": "Эл. пошта",
"settings.profile.password": "Құпия сөз", "settings.profile.password": "Құпия сөз",
"settings.profile.avatar": "Аватар", "settings.profile.avatar": "Аватар",
"settings.appearance.title": "Сыртқы түрі", "settings.appearance.title": "Сыртқы түрі",
"settings.appearance.description": "Dokploy сыртқы келбетін өзгерту.", "settings.appearance.description": "Dokploy сыртқы келбетін өзгерту.",
"settings.appearance.theme": "Келбеті", "settings.appearance.theme": "Келбеті",
"settings.appearance.themeDescription": "Жүйе тақтасының келбетің таңдаңыз", "settings.appearance.themeDescription": "Жүйе тақтасының келбетің таңдаңыз",
"settings.appearance.themes.light": "Жарық", "settings.appearance.themes.light": "Жарық",
"settings.appearance.themes.dark": "Қараңғы", "settings.appearance.themes.dark": "Қараңғы",
"settings.appearance.themes.system": "Жүйелік", "settings.appearance.themes.system": "Жүйелік",
"settings.appearance.language": "Тіл", "settings.appearance.language": "Тіл",
"settings.appearance.languageDescription": "Жүйе тақтасының тілің таңдаңыз" "settings.appearance.languageDescription": "Жүйе тақтасының тілің таңдаңыз"
} }

View File

@@ -31,7 +31,7 @@
"settings.profile.email": "Email", "settings.profile.email": "Email",
"settings.profile.password": "Senha", "settings.profile.password": "Senha",
"settings.profile.avatar": "Avatar", "settings.profile.avatar": "Avatar",
"settings.appearance.title": "Aparencia", "settings.appearance.title": "Aparencia",
"settings.appearance.description": "Personalize o tema do seu dashboard.", "settings.appearance.description": "Personalize o tema do seu dashboard.",
"settings.appearance.theme": "Tema", "settings.appearance.theme": "Tema",

View File

@@ -190,7 +190,7 @@ export const notificationRouter = createTRPCRouter({
await sendDiscordNotification(input, { await sendDiscordNotification(input, {
title: "> `🤚` - Test Notification", title: "> `🤚` - Test Notification",
description: "> Hi, From Dokploy 👋", description: "> Hi, From Dokploy 👋",
color: 0xf3f7f4 color: 0xf3f7f4,
}); });
return true; return true;
} catch (error) { } catch (error) {

File diff suppressed because it is too large Load Diff

View File

@@ -1,93 +1,93 @@
import { Secrets } from "@/components/ui/secrets"; import { Secrets } from "@/components/ui/secrets";
import { import {
type DomainSchema, type DomainSchema,
type Schema, type Schema,
type Template, type Template,
generateBase64, generateBase64,
generateRandomDomain, generateRandomDomain,
} from "../utils"; } from "../utils";
export function generate(schema: Schema): Template { export function generate(schema: Schema): Template {
const triggerDomain = generateRandomDomain(schema); const triggerDomain = generateRandomDomain(schema);
const magicLinkSecret = generateBase64(16); const magicLinkSecret = generateBase64(16);
const sessionSecret = generateBase64(16); const sessionSecret = generateBase64(16);
const encryptionKey = generateBase64(32); const encryptionKey = generateBase64(32);
const providerSecret = generateBase64(32); const providerSecret = generateBase64(32);
const coordinatorSecret = generateBase64(32); const coordinatorSecret = generateBase64(32);
const dbPassword = generateBase64(24); const dbPassword = generateBase64(24);
const dbUser = "triggeruser"; const dbUser = "triggeruser";
const dbName = "triggerdb"; const dbName = "triggerdb";
const domains: DomainSchema[] = [ const domains: DomainSchema[] = [
{ {
host: triggerDomain, host: triggerDomain,
port: 3000, port: 3000,
serviceName: "webapp", serviceName: "webapp",
}, },
]; ];
const envs = [ const envs = [
`NODE_ENV=production`, "NODE_ENV=production",
`RUNTIME_PLATFORM=docker-compose`, "RUNTIME_PLATFORM=docker-compose",
`V3_ENABLED=true`, "V3_ENABLED=true",
`# Domain configuration`, "# Domain configuration",
`TRIGGER_DOMAIN=${triggerDomain}`, `TRIGGER_DOMAIN=${triggerDomain}`,
`TRIGGER_PROTOCOL=http`, "TRIGGER_PROTOCOL=http",
`# Database configuration with secure credentials`, "# Database configuration with secure credentials",
`POSTGRES_USER=${dbUser}`, `POSTGRES_USER=${dbUser}`,
`POSTGRES_PASSWORD=${dbPassword}`, `POSTGRES_PASSWORD=${dbPassword}`,
`POSTGRES_DB=${dbName}`, `POSTGRES_DB=${dbName}`,
`DATABASE_URL=postgresql://${dbUser}:${dbPassword}@postgres:5432/${dbName}`, `DATABASE_URL=postgresql://${dbUser}:${dbPassword}@postgres:5432/${dbName}`,
`# Secrets`, "# Secrets",
`MAGIC_LINK_SECRET=${magicLinkSecret}`, `MAGIC_LINK_SECRET=${magicLinkSecret}`,
`SESSION_SECRET=${sessionSecret}`, `SESSION_SECRET=${sessionSecret}`,
`ENCRYPTION_KEY=${encryptionKey}`, `ENCRYPTION_KEY=${encryptionKey}`,
`PROVIDER_SECRET=${providerSecret}`, `PROVIDER_SECRET=${providerSecret}`,
`COORDINATOR_SECRET=${coordinatorSecret}`, `COORDINATOR_SECRET=${coordinatorSecret}`,
`# TRIGGER_TELEMETRY_DISABLED=1`, "# TRIGGER_TELEMETRY_DISABLED=1",
`INTERNAL_OTEL_TRACE_DISABLED=1`, "INTERNAL_OTEL_TRACE_DISABLED=1",
`INTERNAL_OTEL_TRACE_LOGGING_ENABLED=0`, "INTERNAL_OTEL_TRACE_LOGGING_ENABLED=0",
`DEFAULT_ORG_EXECUTION_CONCURRENCY_LIMIT=300`, "DEFAULT_ORG_EXECUTION_CONCURRENCY_LIMIT=300",
`DEFAULT_ENV_EXECUTION_CONCURRENCY_LIMIT=100`, "DEFAULT_ENV_EXECUTION_CONCURRENCY_LIMIT=100",
`DIRECT_URL=\${DATABASE_URL}`, "DIRECT_URL=${DATABASE_URL}",
`REDIS_HOST=redis`, "REDIS_HOST=redis",
`REDIS_PORT=6379`, "REDIS_PORT=6379",
`REDIS_TLS_DISABLED=true`, "REDIS_TLS_DISABLED=true",
`# If this is set, emails that are not specified won't be able to log in`, "# If this is set, emails that are not specified won't be able to log in",
`# WHITELISTED_EMAILS="authorized@yahoo.com|authorized@gmail.com"`, '# WHITELISTED_EMAILS="authorized@yahoo.com|authorized@gmail.com"',
`# Accounts with these emails will become admins when signing up and get access to the admin panel`, "# Accounts with these emails will become admins when signing up and get access to the admin panel",
`# ADMIN_EMAILS="admin@example.com|another-admin@example.com"`, '# ADMIN_EMAILS="admin@example.com|another-admin@example.com"',
`# If this is set, your users will be able to log in via GitHub`, "# If this is set, your users will be able to log in via GitHub",
`# AUTH_GITHUB_CLIENT_ID=`, "# AUTH_GITHUB_CLIENT_ID=",
`# AUTH_GITHUB_CLIENT_SECRET=`, "# AUTH_GITHUB_CLIENT_SECRET=",
`# E-mail settings`, "# E-mail settings",
`# Ensure the FROM_EMAIL matches what you setup with Resend.com`, "# Ensure the FROM_EMAIL matches what you setup with Resend.com",
`# If these are not set, emails will be printed to the console`, "# If these are not set, emails will be printed to the console",
`# FROM_EMAIL=`, "# FROM_EMAIL=",
`# REPLY_TO_EMAIL=`, "# REPLY_TO_EMAIL=",
`# RESEND_API_KEY=`, "# RESEND_API_KEY=",
`# Worker settings`, "# Worker settings",
`HTTP_SERVER_PORT=9020`, "HTTP_SERVER_PORT=9020",
`COORDINATOR_HOST=127.0.0.1`, "COORDINATOR_HOST=127.0.0.1",
`COORDINATOR_PORT=\${HTTP_SERVER_PORT}`, "COORDINATOR_PORT=${HTTP_SERVER_PORT}",
`# REGISTRY_HOST=\${DEPLOY_REGISTRY_HOST}`, "# REGISTRY_HOST=${DEPLOY_REGISTRY_HOST}",
`# REGISTRY_NAMESPACE=\${DEPLOY_REGISTRY_NAMESPACE}`, "# REGISTRY_NAMESPACE=${DEPLOY_REGISTRY_NAMESPACE}",
]; ];
return { return {
envs, envs,
domains, domains,
}; };
} }

View File

@@ -5,8 +5,8 @@ export function getLocale(cookies: NextApiRequestCookies) {
return locale; return locale;
} }
import { serverSideTranslations as originalServerSideTranslations } from "next-i18next/serverSideTranslations";
import { Languages } from "@/lib/languages"; import { Languages } from "@/lib/languages";
import { serverSideTranslations as originalServerSideTranslations } from "next-i18next/serverSideTranslations";
export const serverSideTranslations = ( export const serverSideTranslations = (
locale: string, locale: string,

View File

@@ -95,7 +95,9 @@ export const sendDatabaseBackupNotifications = async ({
}, },
{ {
name: "`❓`・Type", name: "`❓`・Type",
value: type.replace("error", "Failed").replace("success", "Successful"), value: type
.replace("error", "Failed")
.replace("success", "Successful"),
inline: true, inline: true,
}, },
...(type === "error" && errorMessage ...(type === "error" && errorMessage

View File

@@ -48,7 +48,6 @@ export const sendDockerCleanupNotifications = async (
title: "> `✅` - Docker Cleanup", title: "> `✅` - Docker Cleanup",
color: 0x57f287, color: 0x57f287,
fields: [ fields: [
{ {
name: "`📅`・Date", name: "`📅`・Date",
value: date.toLocaleDateString(), value: date.toLocaleDateString(),