Merge pull request #230 from Dokploy/canary

v0.3.3
This commit is contained in:
Mauricio Siu
2024-07-18 00:11:10 -06:00
committed by GitHub
370 changed files with 4132 additions and 3757 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
# These are supported funding model platforms # These are supported funding model platforms
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] github: [siumauricio]
patreon: # patreon: #
open_collective: dokploy open_collective: dokploy
ko_fi: # Replace with a single Ko-fi username ko_fi: # Replace with a single Ko-fi username
+22 -37
View File
@@ -1,59 +1,44 @@
name: Pull request name: Pull request
on: on:
pull_request: pull_request:
branches:
- main
- canary
push:
branches: branches:
- main - main
- canary - canary
env:
HUSKY: 0
jobs: jobs:
build-app: build-app:
if: github.event_name == 'pull_request' runs-on: ubuntu-latest
runs-on: ubuntu-20.04
strategy: strategy:
matrix: matrix:
node-version: [18.18.0] node-version: [18.18.0]
steps: steps:
- uses: actions/checkout@v3 - name: Check out the code
- uses: pnpm/action-setup@v3 uses: actions/checkout@v4
with:
version: 8 - name: Setup pnpm
uses: pnpm/action-setup@v4
- name: Use Node.js ${{ matrix.node-version }} - name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v3 uses: actions/setup-node@v4
with: with:
node-version: ${{ matrix.node-version }} node-version: ${{ matrix.node-version }}
cache: 'pnpm' cache: 'pnpm'
- name: Install dependencies - name: Install dependencies
run: pnpm install run: pnpm install
- name: Run format and lint
run: pnpm biome ci
- name: Run type check
run: pnpm typecheck
- name: Run Build - name: Run Build
run: pnpm build run: pnpm build
- name: Run Tests - name: Run Tests
run: pnpm run test run: pnpm run test
build-and-push-docker-on-push:
if: github.event_name == 'push'
runs-on: ubuntu-latest
steps:
- name: Check out the code
uses: actions/checkout@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Prepare .env file
run: |
cp .env.production.example .env.production
- name: Build and push Docker image using custom script
run: |
chmod +x ./docker/push.sh
./docker/push.sh ${{ github.ref_name == 'canary' && 'canary' || '' }}
+35
View File
@@ -0,0 +1,35 @@
name: Push
on:
push:
branches:
- main
- canary
env:
HUSKY: 0
jobs:
build-and-push-docker-on-push:
runs-on: ubuntu-latest
steps:
- name: Check out the code
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Prepare .env file
run: |
cp .env.production.example .env.production
- name: Build and push Docker image using custom script
run: |
chmod +x ./docker/push.sh
./docker/push.sh ${{ github.ref_name == 'canary' && 'canary' || '' }}
+6
View File
@@ -0,0 +1,6 @@
// Skip Husky install in production and CI
if (process.env.NODE_ENV === "production" || process.env.CI === "true") {
process.exit(0);
}
const husky = (await import("husky")).default;
console.log(husky());
+1
View File
@@ -0,0 +1 @@
pnpm lint-staged
+43 -27
View File
@@ -1,48 +1,65 @@
# Etapa 1: Prepare image for building
FROM node:18-slim AS base FROM node:18-slim AS base
# Install dependencies # Disable husky
ENV HUSKY=0
# Set pnpm home
ENV PNPM_HOME="/pnpm" ENV PNPM_HOME="/pnpm"
ENV PATH="$PNPM_HOME:$PATH" ENV PATH="$PNPM_HOME:$PATH"
RUN corepack enable && apt-get update && apt-get install -y python3 make g++ git && rm -rf /var/lib/apt/lists/*
# Enable corepack
RUN corepack enable
# Set workdir
WORKDIR /app WORKDIR /app
FROM base AS base-deps
# Install dependencies only for production
RUN apt-get update && apt-get install -y python3 make g++ git && rm -rf /var/lib/apt/lists/*
# Copy install script for husky
COPY .husky/install.mjs ./.husky/install.mjs
# Copy package.json and pnpm-lock.yaml # Copy package.json and pnpm-lock.yaml
COPY package.json pnpm-lock.yaml ./ COPY package.json pnpm-lock.yaml ./
FROM base-deps AS prod-deps
# Set production
ENV NODE_ENV=production
# Install dependencies only for production
RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --prod --frozen-lockfile
FROM base-deps AS build
# Install dependencies only for building # Install dependencies only for building
RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --frozen-lockfile RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --frozen-lockfile
# Copy the rest of the source code # Copy the rest of the source code
COPY . . COPY . .
# Build the application # Build the application
RUN pnpm run build RUN pnpm build
# Stage 2: Prepare image for production FROM base AS production
FROM node:18-slim AS production
# Set production
ENV NODE_ENV=production
# Install dependencies only for production # Install dependencies only for production
ENV PNPM_HOME="/pnpm" RUN apt-get update && apt-get install -y curl apache2-utils && rm -rf /var/lib/apt/lists/*
ENV PATH="$PNPM_HOME:$PATH"
RUN corepack enable && apt-get update && apt-get install -y curl && apt-get install -y apache2-utils && rm -rf /var/lib/apt/lists/*
WORKDIR /app # Copy the rest of the source code
COPY --from=build /app/.next ./.next
# Copy the rest of the source code COPY --from=build /app/dist ./dist
COPY --from=base /app/.next ./.next COPY --from=build /app/next.config.mjs ./next.config.mjs
COPY --from=base /app/dist ./dist COPY --from=build /app/public ./public
COPY --from=base /app/next.config.mjs ./next.config.mjs COPY --from=build /app/package.json ./package.json
COPY --from=base /app/public ./public COPY --from=build /app/drizzle ./drizzle
COPY --from=base /app/package.json ./package.json COPY --from=build /app/.env.production ./.env
COPY --from=base /app/drizzle ./drizzle COPY --from=build /app/components.json ./components.json
COPY --from=base /app/.env.production ./.env COPY --from=prod-deps /app/node_modules ./node_modules
COPY --from=base /app/components.json ./components.json
# Install dependencies only for production
COPY package.json pnpm-lock.yaml ./
RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --prod --frozen-lockfile
# Install docker # Install docker
RUN curl -fsSL https://get.docker.com -o get-docker.sh && sh get-docker.sh && rm get-docker.sh RUN curl -fsSL https://get.docker.com -o get-docker.sh && sh get-docker.sh && rm get-docker.sh
@@ -54,11 +71,10 @@ RUN curl -sSL https://nixpacks.com/install.sh -o install.sh \
&& ./install.sh \ && ./install.sh \
&& pnpm install -g tsx && pnpm install -g tsx
# Install buildpacks # Install buildpacks
RUN curl -sSL "https://github.com/buildpacks/pack/releases/download/v0.32.1/pack-v0.32.1-linux.tgz" | tar -C /usr/local/bin/ --no-same-owner -xzv pack RUN curl -sSL "https://github.com/buildpacks/pack/releases/download/v0.32.1/pack-v0.32.1-linux.tgz" | tar -C /usr/local/bin/ --no-same-owner -xzv pack
# Expose port # Expose port
EXPOSE 3000 EXPOSE 3000
CMD ["pnpm", "start"] CMD ["pnpm", "start"]
+21 -32
View File
@@ -1,4 +1,3 @@
<div align="center"> <div align="center">
<h1 align="center">Dokploy</h1> <h1 align="center">Dokploy</h1>
<div> <div>
@@ -11,74 +10,67 @@
<br /> <br />
Dokploy is a free self-hostable Platform as a Service (PaaS) that simplifies the deployment and management of applications and databases. Dokploy is a free self-hostable Platform as a Service (PaaS) that simplifies the deployment and management of applications and databases.
### Features ### Features
Dokploy include multiples features to make your life easier. Dokploy include multiples features to make your life easier.
- **Applications**: Deploy any type of application (Node.js, PHP, Python, Go, Ruby, etc.).
* **Applications**: Deploy any type of application (Node.js, PHP, Python, Go, Ruby, etc.). - **Databases**: Create and manage databases with support for MySQL, PostgreSQL, MongoDB, MariaDB, Redis.
* **Databases**: Create and manage databases with support for MySQL, PostgreSQL, MongoDB, MariaDB, Redis. - **Backups**: Automate backups for databases to a external storage destination.
* **Backups**: Automate backups for databases to a external storage destination. - **Docker Compose**: Native support for Docker Compose to manage complex applications.
* **Docker Compose**: Native support for Docker Compose to manage complex applications. - **Multi Node**: Scale applications to multiples nodes using docker swarm to manage the cluster.
* **Multi Node**: Scale applications to multiples nodes using docker swarm to manage the cluster. - **Templates**: Deploy in a single click open source templates (Plausible, Pocketbase, Calcom, etc.).
* **Templates**: Deploy in a single click open source templates (Plausible, Pocketbase, Calcom, etc.). - **Traefik Integration**: Automatically integrates with Traefik for routing and load balancing.
* **Traefik Integration**: Automatically integrates with Traefik for routing and load balancing. - **Real-time Monitoring**: Monitor CPU, memory, storage, and network usage, for every resource.
* **Real-time Monitoring**: Monitor CPU, memory, storage, and network usage, for every resource. - **Docker Management**: Easily deploy and manage Docker containers.
* **Docker Management**: Easily deploy and manage Docker containers. - **CLI/API**: Manage your applications and databases using the command line or trought the API.
* **CLI/API**: Manage your applications and databases using the command line or trought the API. - **Self-Hosted**: Self-host Dokploy on your VPS.
* **Self-Hosted**: Self-host Dokploy on your VPS.
## 🚀 Getting Started ## 🚀 Getting Started
To get started run the following command in a VPS: To get started run the following command in a VPS:
```bash ```bash
curl -sSL https://dokploy.com/install.sh | sh curl -sSL https://dokploy.com/install.sh | sh
``` ```
## 📄 Documentation ## 📄 Documentation
For detailed documentation, visit [docs.dokploy.com](https://docs.dokploy.com). For detailed documentation, visit [docs.dokploy.com](https://docs.dokploy.com).
## Video Tutorial ## Video Tutorial
<a href="https://youtu.be/mznYKPvhcfw"> <a href="https://youtu.be/mznYKPvhcfw">
<img src="https://dokploy.com/banner.webp" alt="Watch the video" width="400" style="border-radius:20px;"/> <img src="https://dokploy.com/banner.webp" alt="Watch the video" width="400" style="border-radius:20px;"/>
</a> </a>
## Donations ## Donations
If you like dokploy, and want to support the project to cover the costs of hosting, testing and development new features, you can donate to the project using the following link: If you like dokploy, and want to support the project to cover the costs of hosting, testing and development new features, you can donate to the project using the following link:
Thanks to all the supporters! Thanks to all the supporters!
https://opencollective.com/dokploy [Dokploy Open Collective](https://opencollective.com/dokploy)
Organizations:
<a href="https://opencollective.com/dokploy"><img src="https://opencollective.com/dokploy/organizations.svg?width=890"></a>
Individuals:
<a href="https://opencollective.com/dokploy"><img src="https://opencollective.com/dokploy/individuals.svg?width=890"></a> <a href="https://opencollective.com/dokploy"><img src="https://opencollective.com/dokploy/individuals.svg?width=890"></a>
## Contributors ## Contributors
<a href="https://github.com/dokploy/dokploy/graphs/contributors"> <a href="https://github.com/dokploy/dokploy/graphs/contributors">
<img src="https://contrib.rocks/image?repo=dokploy/dokploy" /> <img src="https://contrib.rocks/image?repo=dokploy/dokploy" />
</a> </a>
## Support OS ## Support OS
- Ubuntu 24.04 LTS - Ubuntu 24.04 LTS
- Ubuntu 23.10 - Ubuntu 23.10
- Ubuntu 22.04 LTS - Ubuntu 22.04 LTS
- Ubuntu 20.04 LTS - Ubuntu 20.04 LTS
- Ubuntu 18.04 LTS - Ubuntu 18.04 LTS
- Debian 12 - Debian 12
- Debian 11 - Debian 11
@@ -86,9 +78,6 @@ https://opencollective.com/dokploy
- Centos 9 - Centos 9
- Centos 8 - Centos 8
## Explanation ## Explanation
[English](README.md) | [中文](README-zh.md) | [Deutsch](README-de.md) | [Русский Язык](README-ru.md) [English](README.md) | [中文](README-zh.md) | [Deutsch](README-de.md) | [Русский Язык](README-ru.md)
+2 -2
View File
@@ -1,7 +1,7 @@
import { expect, test } from "vitest";
import { load } from "js-yaml";
import { addPrefixToAllProperties } from "@/server/utils/docker/compose"; import { addPrefixToAllProperties } from "@/server/utils/docker/compose";
import type { ComposeSpecification } from "@/server/utils/docker/types"; import type { ComposeSpecification } from "@/server/utils/docker/types";
import { load } from "js-yaml";
import { expect, test } from "vitest";
const composeFile1 = ` const composeFile1 = `
version: "3.8" version: "3.8"
@@ -79,10 +79,11 @@ test("Add prefix to networks in services with aliases", () => {
`frontend-${prefix}`, `frontend-${prefix}`,
); );
const networkConfig = const networkConfig = actualComposeData?.services?.api?.networks as {
actualComposeData?.services?.api?.networks[`frontend-${prefix}`]; [key: string]: { aliases?: string[] };
expect(networkConfig).toBeDefined(); };
expect(networkConfig?.aliases).toContain("api"); expect(networkConfig[`frontend-${prefix}`]).toBeDefined();
expect(networkConfig[`frontend-${prefix}`]?.aliases).toContain("api");
expect(actualComposeData.services?.api?.networks).not.toHaveProperty( expect(actualComposeData.services?.api?.networks).not.toHaveProperty(
"frontend-ash", "frontend-ash",
@@ -169,7 +170,9 @@ test("Add prefix to networks in services (combined case)", () => {
); );
// Caso 2: Objeto con aliases // Caso 2: Objeto con aliases
const apiNetworks = actualComposeData.services?.api?.networks; const apiNetworks = actualComposeData.services?.api?.networks as {
[key: string]: unknown;
};
expect(apiNetworks).toHaveProperty(`frontend-${prefix}`); expect(apiNetworks).toHaveProperty(`frontend-${prefix}`);
expect(apiNetworks[`frontend-${prefix}`]).toBeDefined(); expect(apiNetworks[`frontend-${prefix}`]).toBeDefined();
expect(apiNetworks).not.toHaveProperty("frontend"); expect(apiNetworks).not.toHaveProperty("frontend");
+4 -2
View File
@@ -76,9 +76,11 @@ test("Add prefix to networks in services and root (combined case)", () => {
); );
// Caso 2: Objeto con aliases // Caso 2: Objeto con aliases
const apiNetworks = actualComposeData.services?.api?.networks; const apiNetworks = actualComposeData.services?.api?.networks as {
[key: string]: { aliases?: string[] };
};
expect(apiNetworks).toHaveProperty(`frontend-${prefix}`); expect(apiNetworks).toHaveProperty(`frontend-${prefix}`);
expect(apiNetworks[`frontend-${prefix}`]?.aliases).toContain("api"); expect(apiNetworks?.[`frontend-${prefix}`]?.aliases).toContain("api");
expect(apiNetworks).not.toHaveProperty("frontend"); expect(apiNetworks).not.toHaveProperty("frontend");
// Caso 3: Objeto con redes simples // Caso 3: Objeto con redes simples
+3 -3
View File
@@ -1,8 +1,8 @@
import { expect, test } from "vitest";
import { load, dump } from "js-yaml";
import { generateRandomHash } from "@/server/utils/docker/compose"; import { generateRandomHash } from "@/server/utils/docker/compose";
import type { ComposeSpecification } from "@/server/utils/docker/types";
import { addPrefixToSecretsRoot } from "@/server/utils/docker/compose/secrets"; import { addPrefixToSecretsRoot } from "@/server/utils/docker/compose/secrets";
import type { ComposeSpecification } from "@/server/utils/docker/types";
import { dump, load } from "js-yaml";
import { expect, test } from "vitest";
test("Generate random hash with 8 characters", () => { test("Generate random hash with 8 characters", () => {
const hash = generateRandomHash(); const hash = generateRandomHash();
@@ -42,7 +42,7 @@ test("Add prefix to service names with container_name in compose file", () => {
const actualComposeData = { ...composeData, services: updatedComposeData }; const actualComposeData = { ...composeData, services: updatedComposeData };
// Verificar que el nombre del contenedor ha cambiado correctamente // Verificar que el nombre del contenedor ha cambiado correctamente
expect(actualComposeData.services[`web-${prefix}`].container_name).toBe( expect(actualComposeData.services?.[`web-${prefix}`]?.container_name).toBe(
`web_container-${prefix}`, `web_container-${prefix}`,
); );
// Verificar que la nueva clave del servicio tiene el prefijo y la vieja clave no existe // Verificar que la nueva clave del servicio tiene el prefijo y la vieja clave no existe
@@ -50,10 +50,10 @@ test("Add prefix to service names with container_name in compose file", () => {
expect(actualComposeData.services).not.toHaveProperty("web"); expect(actualComposeData.services).not.toHaveProperty("web");
// Verificar que la configuración de la imagen sigue igual // Verificar que la configuración de la imagen sigue igual
expect(actualComposeData.services[`web-${prefix}`].image).toBe( expect(actualComposeData.services?.[`web-${prefix}`]?.image).toBe(
"nginx:latest", "nginx:latest",
); );
expect(actualComposeData.services[`api-${prefix}`].image).toBe( expect(actualComposeData.services?.[`api-${prefix}`]?.image).toBe(
"myapi:latest", "myapi:latest",
); );
}); });
@@ -51,30 +51,30 @@ test("Add prefix to service names with depends_on (array) in compose file", () =
expect(actualComposeData.services).not.toHaveProperty("web"); expect(actualComposeData.services).not.toHaveProperty("web");
// Verificar que la configuración de la imagen sigue igual // Verificar que la configuración de la imagen sigue igual
expect(actualComposeData.services[`web-${prefix}`].image).toBe( expect(actualComposeData.services?.[`web-${prefix}`]?.image).toBe(
"nginx:latest", "nginx:latest",
); );
expect(actualComposeData.services[`api-${prefix}`].image).toBe( expect(actualComposeData.services?.[`api-${prefix}`]?.image).toBe(
"myapi:latest", "myapi:latest",
); );
// Verificar que los nombres en depends_on tienen el prefijo // Verificar que los nombres en depends_on tienen el prefijo
expect(actualComposeData.services[`web-${prefix}`].depends_on).toContain( expect(actualComposeData.services?.[`web-${prefix}`]?.depends_on).toContain(
`db-${prefix}`, `db-${prefix}`,
); );
expect(actualComposeData.services[`web-${prefix}`].depends_on).toContain( expect(actualComposeData.services?.[`web-${prefix}`]?.depends_on).toContain(
`api-${prefix}`, `api-${prefix}`,
); );
// Verificar que los servicios `db` y `api` también tienen el prefijo // Verificar que los servicios `db` y `api` también tienen el prefijo
expect(actualComposeData.services).toHaveProperty(`db-${prefix}`); expect(actualComposeData.services).toHaveProperty(`db-${prefix}`);
expect(actualComposeData.services).not.toHaveProperty("db"); expect(actualComposeData.services).not.toHaveProperty("db");
expect(actualComposeData.services[`db-${prefix}`].image).toBe( expect(actualComposeData.services?.[`db-${prefix}`]?.image).toBe(
"postgres:latest", "postgres:latest",
); );
expect(actualComposeData.services).toHaveProperty(`api-${prefix}`); expect(actualComposeData.services).toHaveProperty(`api-${prefix}`);
expect(actualComposeData.services).not.toHaveProperty("api"); expect(actualComposeData.services).not.toHaveProperty("api");
expect(actualComposeData.services[`api-${prefix}`].image).toBe( expect(actualComposeData.services?.[`api-${prefix}`]?.image).toBe(
"myapi:latest", "myapi:latest",
); );
}); });
@@ -121,16 +121,16 @@ test("Add prefix to service names with depends_on (object) in compose file", ()
expect(actualComposeData.services).not.toHaveProperty("web"); expect(actualComposeData.services).not.toHaveProperty("web");
// Verificar que la configuración de la imagen sigue igual // Verificar que la configuración de la imagen sigue igual
expect(actualComposeData.services[`web-${prefix}`].image).toBe( expect(actualComposeData.services?.[`web-${prefix}`]?.image).toBe(
"nginx:latest", "nginx:latest",
); );
expect(actualComposeData.services[`api-${prefix}`].image).toBe( expect(actualComposeData.services?.[`api-${prefix}`]?.image).toBe(
"myapi:latest", "myapi:latest",
); );
// Verificar que los nombres en depends_on tienen el prefijo // Verificar que los nombres en depends_on tienen el prefijo
const webDependsOn = actualComposeData.services[`web-${prefix}`] const webDependsOn = actualComposeData.services?.[`web-${prefix}`]
.depends_on as Record<string, any>; ?.depends_on as Record<string, any>;
expect(webDependsOn).toHaveProperty(`db-${prefix}`); expect(webDependsOn).toHaveProperty(`db-${prefix}`);
expect(webDependsOn).toHaveProperty(`api-${prefix}`); expect(webDependsOn).toHaveProperty(`api-${prefix}`);
expect(webDependsOn[`db-${prefix}`].condition).toBe("service_healthy"); expect(webDependsOn[`db-${prefix}`].condition).toBe("service_healthy");
@@ -139,12 +139,12 @@ test("Add prefix to service names with depends_on (object) in compose file", ()
// Verificar que los servicios `db` y `api` también tienen el prefijo // Verificar que los servicios `db` y `api` también tienen el prefijo
expect(actualComposeData.services).toHaveProperty(`db-${prefix}`); expect(actualComposeData.services).toHaveProperty(`db-${prefix}`);
expect(actualComposeData.services).not.toHaveProperty("db"); expect(actualComposeData.services).not.toHaveProperty("db");
expect(actualComposeData.services[`db-${prefix}`].image).toBe( expect(actualComposeData.services?.[`db-${prefix}`]?.image).toBe(
"postgres:latest", "postgres:latest",
); );
expect(actualComposeData.services).toHaveProperty(`api-${prefix}`); expect(actualComposeData.services).toHaveProperty(`api-${prefix}`);
expect(actualComposeData.services).not.toHaveProperty("api"); expect(actualComposeData.services).not.toHaveProperty("api");
expect(actualComposeData.services[`api-${prefix}`].image).toBe( expect(actualComposeData.services?.[`api-${prefix}`]?.image).toBe(
"myapi:latest", "myapi:latest",
); );
}); });
@@ -49,22 +49,22 @@ test("Add prefix to service names with extends (string) in compose file", () =>
expect(actualComposeData.services).not.toHaveProperty("web"); expect(actualComposeData.services).not.toHaveProperty("web");
// Verificar que la configuración de la imagen sigue igual // Verificar que la configuración de la imagen sigue igual
expect(actualComposeData.services[`web-${prefix}`].image).toBe( expect(actualComposeData.services?.[`web-${prefix}`]?.image).toBe(
"nginx:latest", "nginx:latest",
); );
expect(actualComposeData.services[`api-${prefix}`].image).toBe( expect(actualComposeData.services?.[`api-${prefix}`]?.image).toBe(
"myapi:latest", "myapi:latest",
); );
// Verificar que el nombre en extends tiene el prefijo // Verificar que el nombre en extends tiene el prefijo
expect(actualComposeData.services[`web-${prefix}`].extends).toBe( expect(actualComposeData.services?.[`web-${prefix}`]?.extends).toBe(
`base_service-${prefix}`, `base_service-${prefix}`,
); );
// Verificar que el servicio `base_service` también tiene el prefijo // Verificar que el servicio `base_service` también tiene el prefijo
expect(actualComposeData.services).toHaveProperty(`base_service-${prefix}`); expect(actualComposeData.services).toHaveProperty(`base_service-${prefix}`);
expect(actualComposeData.services).not.toHaveProperty("base_service"); expect(actualComposeData.services).not.toHaveProperty("base_service");
expect(actualComposeData.services[`base_service-${prefix}`].image).toBe( expect(actualComposeData.services?.[`base_service-${prefix}`]?.image).toBe(
"base:latest", "base:latest",
); );
}); });
@@ -109,23 +109,23 @@ test("Add prefix to service names with extends (object) in compose file", () =>
expect(actualComposeData.services).not.toHaveProperty("web"); expect(actualComposeData.services).not.toHaveProperty("web");
// Verificar que la configuración de la imagen sigue igual // Verificar que la configuración de la imagen sigue igual
expect(actualComposeData.services[`web-${prefix}`].image).toBe( expect(actualComposeData.services?.[`web-${prefix}`]?.image).toBe(
"nginx:latest", "nginx:latest",
); );
expect(actualComposeData.services[`api-${prefix}`].image).toBe( expect(actualComposeData.services?.[`api-${prefix}`]?.image).toBe(
"myapi:latest", "myapi:latest",
); );
// Verificar que el nombre en extends.service tiene el prefijo // Verificar que el nombre en extends.service tiene el prefijo
const webExtends = actualComposeData.services[`web-${prefix}`].extends; const webExtends = actualComposeData.services?.[`web-${prefix}`]?.extends;
if (typeof webExtends !== "string") { if (typeof webExtends !== "string") {
expect(webExtends.service).toBe(`base_service-${prefix}`); expect(webExtends?.service).toBe(`base_service-${prefix}`);
} }
// Verificar que el servicio `base_service` también tiene el prefijo // Verificar que el servicio `base_service` también tiene el prefijo
expect(actualComposeData.services).toHaveProperty(`base_service-${prefix}`); expect(actualComposeData.services).toHaveProperty(`base_service-${prefix}`);
expect(actualComposeData.services).not.toHaveProperty("base_service"); expect(actualComposeData.services).not.toHaveProperty("base_service");
expect(actualComposeData.services[`base_service-${prefix}`].image).toBe( expect(actualComposeData.services?.[`base_service-${prefix}`]?.image).toBe(
"base:latest", "base:latest",
); );
}); });
@@ -50,27 +50,27 @@ test("Add prefix to service names with links in compose file", () => {
expect(actualComposeData.services).not.toHaveProperty("web"); expect(actualComposeData.services).not.toHaveProperty("web");
// Verificar que la configuración de la imagen sigue igual // Verificar que la configuración de la imagen sigue igual
expect(actualComposeData.services[`web-${prefix}`].image).toBe( expect(actualComposeData.services?.[`web-${prefix}`]?.image).toBe(
"nginx:latest", "nginx:latest",
); );
expect(actualComposeData.services[`api-${prefix}`].image).toBe( expect(actualComposeData.services?.[`api-${prefix}`]?.image).toBe(
"myapi:latest", "myapi:latest",
); );
// Verificar que los nombres en links tienen el prefijo // Verificar que los nombres en links tienen el prefijo
expect(actualComposeData.services[`web-${prefix}`].links).toContain( expect(actualComposeData.services?.[`web-${prefix}`]?.links).toContain(
`db-${prefix}`, `db-${prefix}`,
); );
// Verificar que los servicios `db` y `api` también tienen el prefijo // Verificar que los servicios `db` y `api` también tienen el prefijo
expect(actualComposeData.services).toHaveProperty(`db-${prefix}`); expect(actualComposeData.services).toHaveProperty(`db-${prefix}`);
expect(actualComposeData.services).not.toHaveProperty("db"); expect(actualComposeData.services).not.toHaveProperty("db");
expect(actualComposeData.services[`db-${prefix}`].image).toBe( expect(actualComposeData.services?.[`db-${prefix}`]?.image).toBe(
"postgres:latest", "postgres:latest",
); );
expect(actualComposeData.services).toHaveProperty(`api-${prefix}`); expect(actualComposeData.services).toHaveProperty(`api-${prefix}`);
expect(actualComposeData.services).not.toHaveProperty("api"); expect(actualComposeData.services).not.toHaveProperty("api");
expect(actualComposeData.services[`api-${prefix}`].image).toBe( expect(actualComposeData.services?.[`api-${prefix}`]?.image).toBe(
"myapi:latest", "myapi:latest",
); );
}); });
@@ -54,23 +54,25 @@ test("Add prefix to service names with volumes_from in compose file", () => {
expect(actualComposeData.services).not.toHaveProperty("web"); expect(actualComposeData.services).not.toHaveProperty("web");
// Verificar que la configuración de la imagen sigue igual // Verificar que la configuración de la imagen sigue igual
expect(actualComposeData.services[`web-${prefix}`].image).toBe( expect(actualComposeData.services?.[`web-${prefix}`]?.image).toBe(
"nginx:latest", "nginx:latest",
); );
expect(actualComposeData.services[`api-${prefix}`].image).toBe( expect(actualComposeData.services?.[`api-${prefix}`]?.image).toBe(
"myapi:latest", "myapi:latest",
); );
// Verificar que los nombres en volumes_from tienen el prefijo // Verificar que los nombres en volumes_from tienen el prefijo
expect(actualComposeData.services[`web-${prefix}`].volumes_from).toContain( expect(actualComposeData.services?.[`web-${prefix}`]?.volumes_from).toContain(
`shared-${prefix}`, `shared-${prefix}`,
); );
expect(actualComposeData.services[`api-${prefix}`].volumes_from).toContain( expect(actualComposeData.services?.[`api-${prefix}`]?.volumes_from).toContain(
`shared-${prefix}`, `shared-${prefix}`,
); );
// Verificar que el servicio shared también tiene el prefijo // Verificar que el servicio shared también tiene el prefijo
expect(actualComposeData.services).toHaveProperty(`shared-${prefix}`); expect(actualComposeData.services).toHaveProperty(`shared-${prefix}`);
expect(actualComposeData.services).not.toHaveProperty("shared"); expect(actualComposeData.services).not.toHaveProperty("shared");
expect(actualComposeData.services[`shared-${prefix}`].image).toBe("busybox"); expect(actualComposeData.services?.[`shared-${prefix}`]?.image).toBe(
"busybox",
);
}); });
+1 -1
View File
@@ -1,7 +1,7 @@
import { generateRandomHash } from "@/server/utils/docker/compose"; import { generateRandomHash } from "@/server/utils/docker/compose";
import { import {
addPrefixToVolumesRoot,
addPrefixToAllVolumes, addPrefixToAllVolumes,
addPrefixToVolumesRoot,
} from "@/server/utils/docker/compose/volume"; } from "@/server/utils/docker/compose/volume";
import type { ComposeSpecification } from "@/server/utils/docker/types"; import type { ComposeSpecification } from "@/server/utils/docker/types";
import { load } from "js-yaml"; import { load } from "js-yaml";
+1 -1
View File
@@ -1,5 +1,5 @@
import { defineConfig } from "vitest/config";
import tsconfigPaths from "vite-tsconfig-paths"; import tsconfigPaths from "vite-tsconfig-paths";
import { defineConfig } from "vitest/config";
export default defineConfig({ export default defineConfig({
plugins: [ plugins: [
+33 -16
View File
@@ -1,17 +1,34 @@
{ {
"$schema": "./node_modules/@biomejs/biome/configuration_schema.json", "$schema": "./node_modules/@biomejs/biome/configuration_schema.json",
"linter":{ "files": {
"rules": { "ignore": ["node_modules/**", ".next/**", "drizzle/**", ".docker"]
"correctness":{ },
"useExhaustiveDependencies": "off" "organizeImports": {
}, "enabled": true
"suspicious":{ },
"noArrayIndexKey": "off" "linter": {
}, "rules": {
"a11y":{ "complexity": {
"noSvgWithoutTitle":"off" "noUselessCatch": "off",
} "noBannedTypes": "off"
} },
} "correctness": {
"useExhaustiveDependencies": "off",
} "noUnsafeOptionalChaining": "off"
},
"style": {
"noNonNullAssertion": "off"
},
"suspicious": {
"noArrayIndexKey": "off",
"noExplicitAny": "off",
"noRedeclare": "off"
},
"a11y": {
"noSvgWithoutTitle": "off",
"useKeyWithClickEvents": "off",
"useAriaPropsForRole": "off"
}
}
}
}
+16 -16
View File
@@ -1,17 +1,17 @@
{ {
"$schema": "https://ui.shadcn.com/schema.json", "$schema": "https://ui.shadcn.com/schema.json",
"style": "default", "style": "default",
"rsc": false, "rsc": false,
"tsx": true, "tsx": true,
"tailwind": { "tailwind": {
"config": "tailwind.config.ts", "config": "tailwind.config.ts",
"css": "styles/globals.css", "css": "styles/globals.css",
"baseColor": "zinc", "baseColor": "zinc",
"cssVariables": true, "cssVariables": true,
"prefix": "" "prefix": ""
}, },
"aliases": { "aliases": {
"components": "@/components", "components": "@/components",
"utils": "@/lib/utils" "utils": "@/lib/utils"
} }
} }
+7 -7
View File
@@ -10,19 +10,19 @@ import {
} from "@/components/ui/form"; } from "@/components/ui/form";
import { CardTitle } from "@/components/ui/card"; import { CardTitle } from "@/components/ui/card";
import { api } from "@/utils/api";
import { zodResolver } from "@hookform/resolvers/zod";
import { AlertTriangle } from "lucide-react";
import { useEffect } from "react";
import { useForm } from "react-hook-form";
import { toast } from "sonner";
import { z } from "zod";
import { import {
InputOTP, InputOTP,
InputOTPGroup, InputOTPGroup,
InputOTPSlot, InputOTPSlot,
} from "@/components/ui/input-otp"; } from "@/components/ui/input-otp";
import { api } from "@/utils/api";
import { zodResolver } from "@hookform/resolvers/zod";
import { AlertTriangle } from "lucide-react";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
import { useEffect } from "react";
import { useForm } from "react-hook-form";
import { toast } from "sonner";
import { z } from "zod";
const Login2FASchema = z.object({ const Login2FASchema = z.object({
pin: z.string().min(6, { pin: z.string().min(6, {
@@ -1,3 +1,5 @@
import { AlertBlock } from "@/components/shared/alert-block";
import { CodeEditor } from "@/components/shared/code-editor";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { import {
Dialog, Dialog,
@@ -17,21 +19,19 @@ import {
FormLabel, FormLabel,
FormMessage, FormMessage,
} from "@/components/ui/form"; } from "@/components/ui/form";
import { api } from "@/utils/api";
import { AlertBlock } from "@/components/shared/alert-block";
import { zodResolver } from "@hookform/resolvers/zod";
import { useEffect } from "react";
import { useForm } from "react-hook-form";
import { toast } from "sonner";
import { z } from "zod";
import { HelpCircle, Settings } from "lucide-react";
import { import {
Tooltip, Tooltip,
TooltipContent, TooltipContent,
TooltipProvider, TooltipProvider,
TooltipTrigger, TooltipTrigger,
} from "@/components/ui/tooltip"; } from "@/components/ui/tooltip";
import { CodeEditor } from "@/components/shared/code-editor"; import { api } from "@/utils/api";
import { zodResolver } from "@hookform/resolvers/zod";
import { HelpCircle, Settings } from "lucide-react";
import { useEffect } from "react";
import { useForm } from "react-hook-form";
import { toast } from "sonner";
import { z } from "zod";
const HealthCheckSwarmSchema = z const HealthCheckSwarmSchema = z
.object({ .object({
@@ -1,4 +1,5 @@
import React from "react"; import { AlertBlock } from "@/components/shared/alert-block";
import { Button } from "@/components/ui/button";
import { import {
Card, Card,
CardContent, CardContent,
@@ -6,8 +7,6 @@ import {
CardHeader, CardHeader,
CardTitle, CardTitle,
} from "@/components/ui/card"; } from "@/components/ui/card";
import { api } from "@/utils/api";
import { z } from "zod";
import { import {
Form, Form,
FormControl, FormControl,
@@ -16,11 +15,6 @@ import {
FormLabel, FormLabel,
FormMessage, FormMessage,
} from "@/components/ui/form"; } from "@/components/ui/form";
import { toast } from "sonner";
import { zodResolver } from "@hookform/resolvers/zod";
import { useForm } from "react-hook-form";
import { useEffect } from "react";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input"; import { Input } from "@/components/ui/input";
import { import {
Select, Select,
@@ -31,10 +25,16 @@ import {
SelectTrigger, SelectTrigger,
SelectValue, SelectValue,
} from "@/components/ui/select"; } from "@/components/ui/select";
import Link from "next/link"; import { api } from "@/utils/api";
import { zodResolver } from "@hookform/resolvers/zod";
import { Server } from "lucide-react"; import { Server } from "lucide-react";
import Link from "next/link";
import React from "react";
import { useEffect } from "react";
import { useForm } from "react-hook-form";
import { toast } from "sonner";
import { z } from "zod";
import { AddSwarmSettings } from "./modify-swarm-settings"; import { AddSwarmSettings } from "./modify-swarm-settings";
import { AlertBlock } from "@/components/shared/alert-block";
interface Props { interface Props {
applicationId: string; applicationId: string;
@@ -1,4 +1,4 @@
import React from "react"; import { Button } from "@/components/ui/button";
import { import {
Card, Card,
CardContent, CardContent,
@@ -6,8 +6,6 @@ import {
CardHeader, CardHeader,
CardTitle, CardTitle,
} from "@/components/ui/card"; } from "@/components/ui/card";
import { api } from "@/utils/api";
import { z } from "zod";
import { import {
Form, Form,
FormControl, FormControl,
@@ -16,12 +14,14 @@ import {
FormLabel, FormLabel,
FormMessage, FormMessage,
} from "@/components/ui/form"; } from "@/components/ui/form";
import { toast } from "sonner";
import { zodResolver } from "@hookform/resolvers/zod";
import { useForm } from "react-hook-form";
import { useEffect } from "react";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input"; import { Input } from "@/components/ui/input";
import { api } from "@/utils/api";
import { zodResolver } from "@hookform/resolvers/zod";
import React from "react";
import { useEffect } from "react";
import { useForm } from "react-hook-form";
import { toast } from "sonner";
import { z } from "zod";
interface Props { interface Props {
applicationId: string; applicationId: string;
} }
@@ -1,3 +1,4 @@
import { AlertBlock } from "@/components/shared/alert-block";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { import {
Dialog, Dialog,
@@ -17,13 +18,6 @@ import {
FormMessage, FormMessage,
} from "@/components/ui/form"; } from "@/components/ui/form";
import { Input } from "@/components/ui/input"; import { Input } from "@/components/ui/input";
import { api } from "@/utils/api";
import { AlertBlock } from "@/components/shared/alert-block";
import { zodResolver } from "@hookform/resolvers/zod";
import { useEffect } from "react";
import { useForm } from "react-hook-form";
import { toast } from "sonner";
import { PlusIcon } from "lucide-react";
import { import {
Select, Select,
SelectContent, SelectContent,
@@ -31,6 +25,12 @@ import {
SelectTrigger, SelectTrigger,
SelectValue, SelectValue,
} from "@/components/ui/select"; } from "@/components/ui/select";
import { api } from "@/utils/api";
import { zodResolver } from "@hookform/resolvers/zod";
import { PlusIcon } from "lucide-react";
import { useEffect } from "react";
import { useForm } from "react-hook-form";
import { toast } from "sonner";
import { z } from "zod"; import { z } from "zod";
const AddPortSchema = z.object({ const AddPortSchema = z.object({
@@ -1,4 +1,4 @@
import React from "react"; import { AlertBlock } from "@/components/shared/alert-block";
import { import {
Card, Card,
CardContent, CardContent,
@@ -8,10 +8,10 @@ import {
} from "@/components/ui/card"; } from "@/components/ui/card";
import { api } from "@/utils/api"; import { api } from "@/utils/api";
import { Rss } from "lucide-react"; import { Rss } from "lucide-react";
import React from "react";
import { AddPort } from "./add-port"; import { AddPort } from "./add-port";
import { DeletePort } from "./delete-port"; import { DeletePort } from "./delete-port";
import { UpdatePort } from "./update-port"; import { UpdatePort } from "./update-port";
import { AlertBlock } from "@/components/shared/alert-block";
interface Props { interface Props {
applicationId: string; applicationId: string;
} }
@@ -1,3 +1,4 @@
import { AlertBlock } from "@/components/shared/alert-block";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { import {
Dialog, Dialog,
@@ -17,14 +18,6 @@ import {
FormMessage, FormMessage,
} from "@/components/ui/form"; } from "@/components/ui/form";
import { Input } from "@/components/ui/input"; import { Input } from "@/components/ui/input";
import { api } from "@/utils/api";
import { AlertBlock } from "@/components/shared/alert-block";
import { zodResolver } from "@hookform/resolvers/zod";
import { PenBoxIcon, Pencil } from "lucide-react";
import { useEffect } from "react";
import { useForm } from "react-hook-form";
import { toast } from "sonner";
import { z } from "zod";
import { import {
Select, Select,
SelectContent, SelectContent,
@@ -32,6 +25,13 @@ import {
SelectTrigger, SelectTrigger,
SelectValue, SelectValue,
} from "@/components/ui/select"; } from "@/components/ui/select";
import { api } from "@/utils/api";
import { zodResolver } from "@hookform/resolvers/zod";
import { PenBoxIcon, Pencil } from "lucide-react";
import { useEffect } from "react";
import { useForm } from "react-hook-form";
import { toast } from "sonner";
import { z } from "zod";
const UpdatePortSchema = z.object({ const UpdatePortSchema = z.object({
publishedPort: z.number().int().min(1).max(65535), publishedPort: z.number().int().min(1).max(65535),
@@ -1,3 +1,4 @@
import { AlertBlock } from "@/components/shared/alert-block";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { import {
Dialog, Dialog,
@@ -11,22 +12,21 @@ import {
import { import {
Form, Form,
FormControl, FormControl,
FormDescription,
FormField, FormField,
FormItem, FormItem,
FormLabel, FormLabel,
FormDescription,
FormMessage, FormMessage,
} from "@/components/ui/form"; } from "@/components/ui/form";
import { Input } from "@/components/ui/input"; import { Input } from "@/components/ui/input";
import { Switch } from "@/components/ui/switch";
import { api } from "@/utils/api"; import { api } from "@/utils/api";
import { AlertBlock } from "@/components/shared/alert-block";
import { zodResolver } from "@hookform/resolvers/zod"; import { zodResolver } from "@hookform/resolvers/zod";
import { PlusIcon } from "lucide-react";
import { useEffect } from "react"; import { useEffect } from "react";
import { useForm } from "react-hook-form"; import { useForm } from "react-hook-form";
import { toast } from "sonner"; import { toast } from "sonner";
import { PlusIcon } from "lucide-react";
import { z } from "zod"; import { z } from "zod";
import { Switch } from "@/components/ui/switch";
const AddRedirectchema = z.object({ const AddRedirectchema = z.object({
regex: z.string().min(1, "Regex required"), regex: z.string().min(1, "Regex required"),
@@ -1,4 +1,3 @@
import React from "react";
import { import {
Card, Card,
CardContent, CardContent,
@@ -8,6 +7,7 @@ import {
} from "@/components/ui/card"; } from "@/components/ui/card";
import { api } from "@/utils/api"; import { api } from "@/utils/api";
import { Split } from "lucide-react"; import { Split } from "lucide-react";
import React from "react";
import { AddRedirect } from "./add-redirect"; import { AddRedirect } from "./add-redirect";
import { DeleteRedirect } from "./delete-redirect"; import { DeleteRedirect } from "./delete-redirect";
import { UpdateRedirect } from "./update-redirect"; import { UpdateRedirect } from "./update-redirect";
@@ -1,3 +1,4 @@
import { AlertBlock } from "@/components/shared/alert-block";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { import {
Dialog, Dialog,
@@ -11,22 +12,21 @@ import {
import { import {
Form, Form,
FormControl, FormControl,
FormDescription,
FormField, FormField,
FormItem, FormItem,
FormLabel, FormLabel,
FormDescription,
FormMessage, FormMessage,
} from "@/components/ui/form"; } from "@/components/ui/form";
import { Input } from "@/components/ui/input"; import { Input } from "@/components/ui/input";
import { Switch } from "@/components/ui/switch";
import { api } from "@/utils/api"; import { api } from "@/utils/api";
import { AlertBlock } from "@/components/shared/alert-block";
import { zodResolver } from "@hookform/resolvers/zod"; import { zodResolver } from "@hookform/resolvers/zod";
import { PenBoxIcon, Pencil } from "lucide-react"; import { PenBoxIcon, Pencil } from "lucide-react";
import { useEffect } from "react"; import { useEffect } from "react";
import { useForm } from "react-hook-form"; import { useForm } from "react-hook-form";
import { toast } from "sonner"; import { toast } from "sonner";
import { z } from "zod"; import { z } from "zod";
import { Switch } from "@/components/ui/switch";
const UpdateRedirectSchema = z.object({ const UpdateRedirectSchema = z.object({
regex: z.string().min(1, "Regex required"), regex: z.string().min(1, "Regex required"),
permanent: z.boolean().default(false), permanent: z.boolean().default(false),
@@ -1,3 +1,4 @@
import { AlertBlock } from "@/components/shared/alert-block";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { import {
Dialog, Dialog,
@@ -18,12 +19,11 @@ import {
} from "@/components/ui/form"; } from "@/components/ui/form";
import { Input } from "@/components/ui/input"; import { Input } from "@/components/ui/input";
import { api } from "@/utils/api"; import { api } from "@/utils/api";
import { AlertBlock } from "@/components/shared/alert-block";
import { zodResolver } from "@hookform/resolvers/zod"; import { zodResolver } from "@hookform/resolvers/zod";
import { PlusIcon } from "lucide-react";
import { useEffect } from "react"; import { useEffect } from "react";
import { useForm } from "react-hook-form"; import { useForm } from "react-hook-form";
import { toast } from "sonner"; import { toast } from "sonner";
import { PlusIcon } from "lucide-react";
import { z } from "zod"; import { z } from "zod";
const AddSecuritychema = z.object({ const AddSecuritychema = z.object({
@@ -1,4 +1,3 @@
import React from "react";
import { import {
Card, Card,
CardContent, CardContent,
@@ -8,6 +7,7 @@ import {
} from "@/components/ui/card"; } from "@/components/ui/card";
import { api } from "@/utils/api"; import { api } from "@/utils/api";
import { LockKeyhole } from "lucide-react"; import { LockKeyhole } from "lucide-react";
import React from "react";
import { AddSecurity } from "./add-security"; import { AddSecurity } from "./add-security";
import { DeleteSecurity } from "./delete-security"; import { DeleteSecurity } from "./delete-security";
import { UpdateSecurity } from "./update-security"; import { UpdateSecurity } from "./update-security";
@@ -1,3 +1,4 @@
import { AlertBlock } from "@/components/shared/alert-block";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { import {
Dialog, Dialog,
@@ -18,7 +19,6 @@ import {
} from "@/components/ui/form"; } from "@/components/ui/form";
import { Input } from "@/components/ui/input"; import { Input } from "@/components/ui/input";
import { api } from "@/utils/api"; import { api } from "@/utils/api";
import { AlertBlock } from "@/components/shared/alert-block";
import { zodResolver } from "@hookform/resolvers/zod"; import { zodResolver } from "@hookform/resolvers/zod";
import { PenBoxIcon, Pencil } from "lucide-react"; import { PenBoxIcon, Pencil } from "lucide-react";
import { useEffect } from "react"; import { useEffect } from "react";
@@ -1,3 +1,4 @@
import { AlertBlock } from "@/components/shared/alert-block";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { import {
Card, Card,
@@ -21,7 +22,6 @@ import React, { useEffect } from "react";
import { useForm } from "react-hook-form"; import { useForm } from "react-hook-form";
import { toast } from "sonner"; import { toast } from "sonner";
import { z } from "zod"; import { z } from "zod";
import { AlertBlock } from "@/components/shared/alert-block";
const addResourcesApplication = z.object({ const addResourcesApplication = z.object({
memoryReservation: z.number().nullable().optional(), memoryReservation: z.number().nullable().optional(),
@@ -1,4 +1,4 @@
import React from "react"; import { CodeEditor } from "@/components/shared/code-editor";
import { import {
Card, Card,
CardContent, CardContent,
@@ -8,8 +8,8 @@ import {
} from "@/components/ui/card"; } from "@/components/ui/card";
import { api } from "@/utils/api"; import { api } from "@/utils/api";
import { File } from "lucide-react"; import { File } from "lucide-react";
import React from "react";
import { UpdateTraefikConfig } from "./update-traefik-config"; import { UpdateTraefikConfig } from "./update-traefik-config";
import { CodeEditor } from "@/components/shared/code-editor";
interface Props { interface Props {
applicationId: string; applicationId: string;
} }
@@ -1,3 +1,5 @@
import { AlertBlock } from "@/components/shared/alert-block";
import { CodeEditor } from "@/components/shared/code-editor";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { import {
Dialog, Dialog,
@@ -17,14 +19,12 @@ import {
FormMessage, FormMessage,
} from "@/components/ui/form"; } from "@/components/ui/form";
import { api } from "@/utils/api"; import { api } from "@/utils/api";
import { AlertBlock } from "@/components/shared/alert-block";
import { zodResolver } from "@hookform/resolvers/zod"; import { zodResolver } from "@hookform/resolvers/zod";
import jsyaml from "js-yaml";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { useForm } from "react-hook-form"; import { useForm } from "react-hook-form";
import { toast } from "sonner"; import { toast } from "sonner";
import { z } from "zod"; import { z } from "zod";
import jsyaml from "js-yaml";
import { CodeEditor } from "@/components/shared/code-editor";
const UpdateTraefikConfigSchema = z.object({ const UpdateTraefikConfigSchema = z.object({
traefikConfig: z.string(), traefikConfig: z.string(),
@@ -110,12 +110,15 @@ export const UpdateTraefikConfig = ({ applicationId }: Props) => {
}; };
return ( return (
<Dialog open={open} onOpenChange={(open) => { <Dialog
setOpen(open) open={open}
if (!open) { onOpenChange={(open) => {
form.reset(); setOpen(open);
} if (!open) {
}}> form.reset();
}
}}
>
<DialogTrigger asChild> <DialogTrigger asChild>
<Button isLoading={isLoading}>Modify</Button> <Button isLoading={isLoading}>Modify</Button>
</DialogTrigger> </DialogTrigger>
@@ -1,8 +1,4 @@
import { zodResolver } from "@hookform/resolvers/zod"; import { Button } from "@/components/ui/button";
import type React from "react";
import { useEffect } from "react";
import { useForm } from "react-hook-form";
import { z } from "zod";
import { import {
Dialog, Dialog,
DialogContent, DialogContent,
@@ -22,12 +18,16 @@ import {
import { Input } from "@/components/ui/input"; import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label"; import { Label } from "@/components/ui/label";
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group"; import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group";
import { Button } from "@/components/ui/button";
import { PlusIcon } from "lucide-react";
import { Textarea } from "@/components/ui/textarea"; import { Textarea } from "@/components/ui/textarea";
import { api } from "@/utils/api";
import { toast } from "sonner";
import { cn } from "@/lib/utils"; import { cn } from "@/lib/utils";
import { api } from "@/utils/api";
import { zodResolver } from "@hookform/resolvers/zod";
import { PlusIcon } from "lucide-react";
import type React from "react";
import { useEffect } from "react";
import { useForm } from "react-hook-form";
import { toast } from "sonner";
import { z } from "zod";
interface Props { interface Props {
serviceId: string; serviceId: string;
serviceType: serviceType:
@@ -1,4 +1,3 @@
import React from "react";
import { import {
AlertDialog, AlertDialog,
AlertDialogAction, AlertDialogAction,
@@ -13,6 +12,7 @@ import {
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { api } from "@/utils/api"; import { api } from "@/utils/api";
import { TrashIcon } from "lucide-react"; import { TrashIcon } from "lucide-react";
import React from "react";
import { toast } from "sonner"; import { toast } from "sonner";
interface Props { interface Props {
@@ -1,4 +1,4 @@
import React from "react"; import { AlertBlock } from "@/components/shared/alert-block";
import { import {
Card, Card,
CardContent, CardContent,
@@ -8,10 +8,10 @@ import {
} from "@/components/ui/card"; } from "@/components/ui/card";
import { api } from "@/utils/api"; import { api } from "@/utils/api";
import { AlertTriangle, Package } from "lucide-react"; import { AlertTriangle, Package } from "lucide-react";
import React from "react";
import { AddVolumes } from "./add-volumes"; import { AddVolumes } from "./add-volumes";
import { DeleteVolume } from "./delete-volume"; import { DeleteVolume } from "./delete-volume";
import { UpdateVolume } from "./update-volume"; import { UpdateVolume } from "./update-volume";
import { AlertBlock } from "@/components/shared/alert-block";
interface Props { interface Props {
applicationId: string; applicationId: string;
} }
@@ -1,3 +1,4 @@
import { AlertBlock } from "@/components/shared/alert-block";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { import {
Dialog, Dialog,
@@ -17,15 +18,14 @@ import {
FormMessage, FormMessage,
} from "@/components/ui/form"; } from "@/components/ui/form";
import { Input } from "@/components/ui/input"; import { Input } from "@/components/ui/input";
import { Textarea } from "@/components/ui/textarea";
import { api } from "@/utils/api"; import { api } from "@/utils/api";
import { AlertBlock } from "@/components/shared/alert-block";
import { zodResolver } from "@hookform/resolvers/zod"; import { zodResolver } from "@hookform/resolvers/zod";
import { Pencil } from "lucide-react"; import { Pencil } from "lucide-react";
import { useEffect } from "react"; import { useEffect } from "react";
import { useForm } from "react-hook-form"; import { useForm } from "react-hook-form";
import { toast } from "sonner"; import { toast } from "sonner";
import { z } from "zod"; import { z } from "zod";
import { Textarea } from "@/components/ui/textarea";
const mountSchema = z.object({ const mountSchema = z.object({
mountPath: z.string().min(1, "Mount path required"), mountPath: z.string().min(1, "Mount path required"),
+188 -188
View File
@@ -1,213 +1,213 @@
import { import { Button } from "@/components/ui/button";
Form,
FormControl,
FormField,
FormItem,
FormLabel,
FormMessage,
} from "@/components/ui/form";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import {
Form,
FormControl,
FormField,
FormItem,
FormLabel,
FormMessage,
} from "@/components/ui/form";
import { Input } from "@/components/ui/input";
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group";
import { api } from "@/utils/api"; import { api } from "@/utils/api";
import { zodResolver } from "@hookform/resolvers/zod"; import { zodResolver } from "@hookform/resolvers/zod";
import { Cog } from "lucide-react"; import { Cog } from "lucide-react";
import { useEffect } from "react"; import { useEffect } from "react";
import { useForm } from "react-hook-form"; import { useForm } from "react-hook-form";
import { z } from "zod";
import { Button } from "@/components/ui/button";
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group";
import { toast } from "sonner"; import { toast } from "sonner";
import { Input } from "@/components/ui/input"; import { z } from "zod";
enum BuildType { enum BuildType {
dockerfile = "dockerfile", dockerfile = "dockerfile",
heroku_buildpacks = "heroku_buildpacks", heroku_buildpacks = "heroku_buildpacks",
paketo_buildpacks = "paketo_buildpacks", paketo_buildpacks = "paketo_buildpacks",
nixpacks = "nixpacks", nixpacks = "nixpacks",
} }
const mySchema = z.discriminatedUnion("buildType", [ const mySchema = z.discriminatedUnion("buildType", [
z.object({ z.object({
buildType: z.literal("dockerfile"), buildType: z.literal("dockerfile"),
dockerfile: z dockerfile: z
.string({ .string({
required_error: "Dockerfile path is required", required_error: "Dockerfile path is required",
invalid_type_error: "Dockerfile path is required", invalid_type_error: "Dockerfile path is required",
}) })
.min(1, "Dockerfile required"), .min(1, "Dockerfile required"),
}), }),
z.object({ z.object({
buildType: z.literal("heroku_buildpacks"), buildType: z.literal("heroku_buildpacks"),
}), }),
z.object({ z.object({
buildType: z.literal("paketo_buildpacks"), buildType: z.literal("paketo_buildpacks"),
}), }),
z.object({ z.object({
buildType: z.literal("nixpacks"), buildType: z.literal("nixpacks"),
}), }),
]); ]);
type AddTemplate = z.infer<typeof mySchema>; type AddTemplate = z.infer<typeof mySchema>;
interface Props { interface Props {
applicationId: string; applicationId: string;
} }
export const ShowBuildChooseForm = ({ applicationId }: Props) => { export const ShowBuildChooseForm = ({ applicationId }: Props) => {
const { mutateAsync, isLoading } = const { mutateAsync, isLoading } =
api.application.saveBuildType.useMutation(); api.application.saveBuildType.useMutation();
const { data, refetch } = api.application.one.useQuery( const { data, refetch } = api.application.one.useQuery(
{ {
applicationId, applicationId,
}, },
{ {
enabled: !!applicationId, enabled: !!applicationId,
}, },
); );
const form = useForm<AddTemplate>({ const form = useForm<AddTemplate>({
defaultValues: { defaultValues: {
buildType: BuildType.nixpacks, buildType: BuildType.nixpacks,
}, },
resolver: zodResolver(mySchema), resolver: zodResolver(mySchema),
}); });
const buildType = form.watch("buildType"); const buildType = form.watch("buildType");
useEffect(() => { useEffect(() => {
if (data) { if (data) {
// TODO: refactor this // TODO: refactor this
if (data.buildType === "dockerfile") { if (data.buildType === "dockerfile") {
form.reset({ form.reset({
buildType: data.buildType, buildType: data.buildType,
...(data.buildType && { ...(data.buildType && {
dockerfile: data.dockerfile || "", dockerfile: data.dockerfile || "",
}), }),
}); });
} else { } else {
form.reset({ form.reset({
buildType: data.buildType, buildType: data.buildType,
}); });
} }
} }
}, [form.formState.isSubmitSuccessful, form.reset, data, form]); }, [form.formState.isSubmitSuccessful, form.reset, data, form]);
const onSubmit = async (data: AddTemplate) => { const onSubmit = async (data: AddTemplate) => {
await mutateAsync({ await mutateAsync({
applicationId, applicationId,
buildType: data.buildType, buildType: data.buildType,
dockerfile: data.buildType === "dockerfile" ? data.dockerfile : null, dockerfile: data.buildType === "dockerfile" ? data.dockerfile : null,
}) })
.then(async () => { .then(async () => {
toast.success("Build type saved"); toast.success("Build type saved");
await refetch(); await refetch();
}) })
.catch(() => { .catch(() => {
toast.error("Error to save the build type"); toast.error("Error to save the build type");
}); });
}; };
return ( return (
<Card className="group relative w-full bg-transparent"> <Card className="group relative w-full bg-transparent">
<CardHeader> <CardHeader>
<CardTitle className="flex items-start justify-between"> <CardTitle className="flex items-start justify-between">
<div className="flex flex-col gap-2"> <div className="flex flex-col gap-2">
<span className="flex flex-col space-y-0.5">Build Type</span> <span className="flex flex-col space-y-0.5">Build Type</span>
<p className="flex items-center text-sm font-normal text-muted-foreground"> <p className="flex items-center text-sm font-normal text-muted-foreground">
Select the way of building your code Select the way of building your code
</p> </p>
</div> </div>
<div className="hidden space-y-1 text-sm font-normal md:block"> <div className="hidden space-y-1 text-sm font-normal md:block">
<Cog className="size-6 text-muted-foreground" /> <Cog className="size-6 text-muted-foreground" />
</div> </div>
</CardTitle> </CardTitle>
</CardHeader> </CardHeader>
<CardContent> <CardContent>
<Form {...form}> <Form {...form}>
<form <form
onSubmit={form.handleSubmit(onSubmit)} onSubmit={form.handleSubmit(onSubmit)}
className="grid w-full gap-4 p-2" className="grid w-full gap-4 p-2"
> >
<FormField <FormField
control={form.control} control={form.control}
name="buildType" name="buildType"
defaultValue={form.control._defaultValues.buildType} defaultValue={form.control._defaultValues.buildType}
render={({ field }) => { render={({ field }) => {
return ( return (
<FormItem className="space-y-3"> <FormItem className="space-y-3">
<FormLabel>Build Type</FormLabel> <FormLabel>Build Type</FormLabel>
<FormControl> <FormControl>
<RadioGroup <RadioGroup
onValueChange={field.onChange} onValueChange={field.onChange}
value={field.value} value={field.value}
className="flex flex-col space-y-1" className="flex flex-col space-y-1"
> >
<FormItem className="flex items-center space-x-3 space-y-0"> <FormItem className="flex items-center space-x-3 space-y-0">
<FormControl> <FormControl>
<RadioGroupItem value="dockerfile" /> <RadioGroupItem value="dockerfile" />
</FormControl> </FormControl>
<FormLabel className="font-normal"> <FormLabel className="font-normal">
Dockerfile Dockerfile
</FormLabel> </FormLabel>
</FormItem> </FormItem>
<FormItem className="flex items-center space-x-3 space-y-0"> <FormItem className="flex items-center space-x-3 space-y-0">
<FormControl> <FormControl>
<RadioGroupItem value="nixpacks" /> <RadioGroupItem value="nixpacks" />
</FormControl> </FormControl>
<FormLabel className="font-normal"> <FormLabel className="font-normal">
Nixpacks Nixpacks
</FormLabel> </FormLabel>
</FormItem> </FormItem>
<FormItem className="flex items-center space-x-3 space-y-0"> <FormItem className="flex items-center space-x-3 space-y-0">
<FormControl> <FormControl>
<RadioGroupItem value="heroku_buildpacks" /> <RadioGroupItem value="heroku_buildpacks" />
</FormControl> </FormControl>
<FormLabel className="font-normal"> <FormLabel className="font-normal">
Heroku Buildpacks Heroku Buildpacks
</FormLabel> </FormLabel>
</FormItem> </FormItem>
<FormItem className="flex items-center space-x-3 space-y-0"> <FormItem className="flex items-center space-x-3 space-y-0">
<FormControl> <FormControl>
<RadioGroupItem value="paketo_buildpacks" /> <RadioGroupItem value="paketo_buildpacks" />
</FormControl> </FormControl>
<FormLabel className="font-normal"> <FormLabel className="font-normal">
Paketo Buildpacks Paketo Buildpacks
</FormLabel> </FormLabel>
</FormItem> </FormItem>
</RadioGroup> </RadioGroup>
</FormControl> </FormControl>
<FormMessage /> <FormMessage />
</FormItem> </FormItem>
); );
}} }}
/> />
{buildType === "dockerfile" && ( {buildType === "dockerfile" && (
<FormField <FormField
control={form.control} control={form.control}
name="dockerfile" name="dockerfile"
render={({ field }) => { render={({ field }) => {
return ( return (
<FormItem> <FormItem>
<FormLabel>Docker File</FormLabel> <FormLabel>Docker File</FormLabel>
<FormControl> <FormControl>
<Input <Input
placeholder={"Path of your docker file"} placeholder={"Path of your docker file"}
{...field} {...field}
value={field.value ?? ""} value={field.value ?? ""}
/> />
</FormControl> </FormControl>
<FormMessage /> <FormMessage />
</FormItem> </FormItem>
); );
}} }}
/> />
)} )}
<div className="flex w-full justify-end"> <div className="flex w-full justify-end">
<Button isLoading={isLoading} type="submit"> <Button isLoading={isLoading} type="submit">
Save Save
</Button> </Button>
</div> </div>
</form> </form>
</Form> </Form>
</CardContent> </CardContent>
</Card> </Card>
); );
}; };
@@ -1,4 +1,3 @@
import React from "react";
import { import {
AlertDialog, AlertDialog,
AlertDialogAction, AlertDialogAction,
@@ -12,6 +11,7 @@ import {
} from "@/components/ui/alert-dialog"; } from "@/components/ui/alert-dialog";
import { api } from "@/utils/api"; import { api } from "@/utils/api";
import { RefreshCcw } from "lucide-react"; import { RefreshCcw } from "lucide-react";
import React from "react";
import { toast } from "sonner"; import { toast } from "sonner";
interface Props { interface Props {
@@ -1,3 +1,5 @@
import { DateTooltip } from "@/components/shared/date-tooltip";
import { StatusTooltip } from "@/components/shared/status-tooltip";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { import {
Card, Card,
@@ -10,10 +12,8 @@ import { api } from "@/utils/api";
import { RocketIcon } from "lucide-react"; import { RocketIcon } from "lucide-react";
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from "react";
import { CancelQueues } from "./cancel-queues"; import { CancelQueues } from "./cancel-queues";
import { ShowDeployment } from "./show-deployment";
import { StatusTooltip } from "@/components/shared/status-tooltip";
import { DateTooltip } from "@/components/shared/date-tooltip";
import { RefreshToken } from "./refresh-token"; import { RefreshToken } from "./refresh-token";
import { ShowDeployment } from "./show-deployment";
interface Props { interface Props {
applicationId: string; applicationId: string;
@@ -1,3 +1,4 @@
import { AlertBlock } from "@/components/shared/alert-block";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { import {
Dialog, Dialog,
@@ -27,7 +28,6 @@ import {
} from "@/components/ui/select"; } from "@/components/ui/select";
import { Switch } from "@/components/ui/switch"; import { Switch } from "@/components/ui/switch";
import { api } from "@/utils/api"; import { api } from "@/utils/api";
import { AlertBlock } from "@/components/shared/alert-block";
import { zodResolver } from "@hookform/resolvers/zod"; import { zodResolver } from "@hookform/resolvers/zod";
import { PlusIcon } from "lucide-react"; import { PlusIcon } from "lucide-react";
import { useEffect } from "react"; import { useEffect } from "react";
@@ -1,4 +1,3 @@
import React from "react";
import { import {
AlertDialog, AlertDialog,
AlertDialogAction, AlertDialogAction,
@@ -13,6 +12,7 @@ import {
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { api } from "@/utils/api"; import { api } from "@/utils/api";
import { TrashIcon } from "lucide-react"; import { TrashIcon } from "lucide-react";
import React from "react";
import { toast } from "sonner"; import { toast } from "sonner";
interface Props { interface Props {
@@ -7,11 +7,11 @@ import {
DialogTitle, DialogTitle,
DialogTrigger, DialogTrigger,
} from "@/components/ui/dialog"; } from "@/components/ui/dialog";
import { api } from "@/utils/api";
import { RefreshCcw } from "lucide-react"; import { RefreshCcw } from "lucide-react";
import Link from "next/link";
import { GenerateTraefikMe } from "./generate-traefikme"; import { GenerateTraefikMe } from "./generate-traefikme";
import { GenerateWildCard } from "./generate-wildcard"; import { GenerateWildCard } from "./generate-wildcard";
import Link from "next/link";
import { api } from "@/utils/api";
interface Props { interface Props {
applicationId: string; applicationId: string;
@@ -1,4 +1,3 @@
import React from "react";
import { import {
AlertDialog, AlertDialog,
AlertDialogAction, AlertDialogAction,
@@ -13,6 +12,7 @@ import {
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { api } from "@/utils/api"; import { api } from "@/utils/api";
import { RefreshCcw } from "lucide-react"; import { RefreshCcw } from "lucide-react";
import React from "react";
import { toast } from "sonner"; import { toast } from "sonner";
interface Props { interface Props {
@@ -1,4 +1,3 @@
import React from "react";
import { import {
AlertDialog, AlertDialog,
AlertDialogAction, AlertDialogAction,
@@ -13,6 +12,7 @@ import {
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { api } from "@/utils/api"; import { api } from "@/utils/api";
import { SquareAsterisk } from "lucide-react"; import { SquareAsterisk } from "lucide-react";
import React from "react";
import { toast } from "sonner"; import { toast } from "sonner";
interface Props { interface Props {
@@ -1,4 +1,4 @@
import React from "react"; import { Button } from "@/components/ui/button";
import { import {
Card, Card,
CardContent, CardContent,
@@ -6,15 +6,15 @@ import {
CardHeader, CardHeader,
CardTitle, CardTitle,
} from "@/components/ui/card"; } from "@/components/ui/card";
import { ExternalLink, GlobeIcon, RefreshCcw } from "lucide-react";
import { Button } from "@/components/ui/button";
import { api } from "@/utils/api";
import { Input } from "@/components/ui/input"; import { Input } from "@/components/ui/input";
import { DeleteDomain } from "./delete-domain"; import { api } from "@/utils/api";
import { ExternalLink, GlobeIcon, RefreshCcw } from "lucide-react";
import Link from "next/link"; import Link from "next/link";
import React from "react";
import { AddDomain } from "./add-domain"; import { AddDomain } from "./add-domain";
import { UpdateDomain } from "./update-domain"; import { DeleteDomain } from "./delete-domain";
import { GenerateDomain } from "./generate-domain"; import { GenerateDomain } from "./generate-domain";
import { UpdateDomain } from "./update-domain";
interface Props { interface Props {
applicationId: string; applicationId: string;
@@ -1,3 +1,4 @@
import { AlertBlock } from "@/components/shared/alert-block";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { import {
Dialog, Dialog,
@@ -27,7 +28,6 @@ import {
} from "@/components/ui/select"; } from "@/components/ui/select";
import { Switch } from "@/components/ui/switch"; import { Switch } from "@/components/ui/switch";
import { api } from "@/utils/api"; import { api } from "@/utils/api";
import { AlertBlock } from "@/components/shared/alert-block";
import { zodResolver } from "@hookform/resolvers/zod"; import { zodResolver } from "@hookform/resolvers/zod";
import { PenBoxIcon } from "lucide-react"; import { PenBoxIcon } from "lucide-react";
import { useEffect } from "react"; import { useEffect } from "react";
@@ -1,4 +1,5 @@
import React, { useEffect, useState } from "react"; import { CodeEditor } from "@/components/shared/code-editor";
import { Button } from "@/components/ui/button";
import { import {
Card, Card,
CardContent, CardContent,
@@ -6,10 +7,6 @@ import {
CardHeader, CardHeader,
CardTitle, CardTitle,
} from "@/components/ui/card"; } from "@/components/ui/card";
import { Button } from "@/components/ui/button";
import { z } from "zod";
import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { import {
Form, Form,
FormControl, FormControl,
@@ -17,11 +14,14 @@ import {
FormItem, FormItem,
FormMessage, FormMessage,
} from "@/components/ui/form"; } from "@/components/ui/form";
import { api } from "@/utils/api";
import { toast } from "sonner";
import { Toggle } from "@/components/ui/toggle"; import { Toggle } from "@/components/ui/toggle";
import { CodeEditor } from "@/components/shared/code-editor"; import { api } from "@/utils/api";
import { zodResolver } from "@hookform/resolvers/zod";
import { EyeIcon, EyeOffIcon } from "lucide-react"; import { EyeIcon, EyeOffIcon } from "lucide-react";
import React, { useEffect, useState } from "react";
import { useForm } from "react-hook-form";
import { toast } from "sonner";
import { z } from "zod";
const addEnvironmentSchema = z.object({ const addEnvironmentSchema = z.object({
environment: z.string(), environment: z.string(),
@@ -1,8 +1,4 @@
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { z } from "zod";
import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { import {
Form, Form,
FormControl, FormControl,
@@ -11,9 +7,13 @@ import {
FormLabel, FormLabel,
FormMessage, FormMessage,
} from "@/components/ui/form"; } from "@/components/ui/form";
import { useEffect } from "react"; import { Input } from "@/components/ui/input";
import { api } from "@/utils/api"; import { api } from "@/utils/api";
import { zodResolver } from "@hookform/resolvers/zod";
import { useEffect } from "react";
import { useForm } from "react-hook-form";
import { toast } from "sonner"; import { toast } from "sonner";
import { z } from "zod";
const DockerProviderSchema = z.object({ const DockerProviderSchema = z.object({
dockerImage: z.string().min(1, { dockerImage: z.string().min(1, {
@@ -4,13 +4,13 @@ import { Button } from "@/components/ui/button";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Toggle } from "@/components/ui/toggle"; import { Toggle } from "@/components/ui/toggle";
import { api } from "@/utils/api"; import { api } from "@/utils/api";
import { CheckCircle2, Terminal } from "lucide-react";
import React from "react"; import React from "react";
import { toast } from "sonner"; import { toast } from "sonner";
import { DockerTerminalModal } from "../../settings/web-server/docker-terminal-modal";
import { RedbuildApplication } from "../rebuild-application"; import { RedbuildApplication } from "../rebuild-application";
import { StartApplication } from "../start-application"; import { StartApplication } from "../start-application";
import { StopApplication } from "../stop-application"; import { StopApplication } from "../stop-application";
import { DockerTerminalModal } from "../../settings/web-server/docker-terminal-modal";
import { CheckCircle2, Terminal } from "lucide-react";
import { DeployApplication } from "./deploy-application"; import { DeployApplication } from "./deploy-application";
import { ResetApplication } from "./reset-application"; import { ResetApplication } from "./reset-application";
interface Props { interface Props {
@@ -1,4 +1,3 @@
import dynamic from "next/dynamic";
import { import {
Card, Card,
CardContent, CardContent,
@@ -6,6 +5,7 @@ import {
CardHeader, CardHeader,
CardTitle, CardTitle,
} from "@/components/ui/card"; } from "@/components/ui/card";
import { Label } from "@/components/ui/label";
import { import {
Select, Select,
SelectContent, SelectContent,
@@ -16,8 +16,8 @@ import {
SelectValue, SelectValue,
} from "@/components/ui/select"; } from "@/components/ui/select";
import { api } from "@/utils/api"; import { api } from "@/utils/api";
import dynamic from "next/dynamic";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { Label } from "@/components/ui/label";
export const DockerLogs = dynamic( export const DockerLogs = dynamic(
() => () =>
import("@/components/dashboard/docker/logs/docker-logs-id").then( import("@/components/dashboard/docker/logs/docker-logs-id").then(
@@ -1,3 +1,5 @@
import { AlertBlock } from "@/components/shared/alert-block";
import { Button } from "@/components/ui/button";
import { import {
Dialog, Dialog,
DialogContent, DialogContent,
@@ -7,7 +9,6 @@ import {
DialogTitle, DialogTitle,
DialogTrigger, DialogTrigger,
} from "@/components/ui/dialog"; } from "@/components/ui/dialog";
import { Button } from "@/components/ui/button";
import { import {
Form, Form,
FormControl, FormControl,
@@ -16,16 +17,15 @@ import {
FormLabel, FormLabel,
FormMessage, FormMessage,
} from "@/components/ui/form"; } from "@/components/ui/form";
import { useForm } from "react-hook-form";
import { z } from "zod";
import { AlertBlock } from "@/components/shared/alert-block";
import { zodResolver } from "@hookform/resolvers/zod";
import { useEffect } from "react";
import { toast } from "sonner";
import { Input } from "@/components/ui/input"; import { Input } from "@/components/ui/input";
import { AlertTriangle, SquarePen } from "lucide-react";
import { Textarea } from "@/components/ui/textarea"; import { Textarea } from "@/components/ui/textarea";
import { api } from "@/utils/api"; import { api } from "@/utils/api";
import { zodResolver } from "@hookform/resolvers/zod";
import { AlertTriangle, SquarePen } from "lucide-react";
import { useEffect } from "react";
import { useForm } from "react-hook-form";
import { toast } from "sonner";
import { z } from "zod";
const updateApplicationSchema = z.object({ const updateApplicationSchema = z.object({
name: z.string().min(1, { name: z.string().min(1, {
@@ -1,4 +1,4 @@
import React from "react"; import { Button } from "@/components/ui/button";
import { import {
Card, Card,
CardContent, CardContent,
@@ -6,8 +6,6 @@ import {
CardHeader, CardHeader,
CardTitle, CardTitle,
} from "@/components/ui/card"; } from "@/components/ui/card";
import { api } from "@/utils/api";
import { z } from "zod";
import { import {
Form, Form,
FormControl, FormControl,
@@ -17,12 +15,14 @@ import {
FormLabel, FormLabel,
FormMessage, FormMessage,
} from "@/components/ui/form"; } from "@/components/ui/form";
import { toast } from "sonner";
import { zodResolver } from "@hookform/resolvers/zod";
import { useForm } from "react-hook-form";
import { useEffect } from "react";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input"; import { Input } from "@/components/ui/input";
import { api } from "@/utils/api";
import { zodResolver } from "@hookform/resolvers/zod";
import React from "react";
import { useEffect } from "react";
import { useForm } from "react-hook-form";
import { toast } from "sonner";
import { z } from "zod";
interface Props { interface Props {
composeId: string; composeId: string;
} }
@@ -1,4 +1,4 @@
import React from "react"; import { AlertBlock } from "@/components/shared/alert-block";
import { import {
Card, Card,
CardContent, CardContent,
@@ -8,10 +8,10 @@ import {
} from "@/components/ui/card"; } from "@/components/ui/card";
import { api } from "@/utils/api"; import { api } from "@/utils/api";
import { Package } from "lucide-react"; import { Package } from "lucide-react";
import { DeleteVolume } from "../../application/advanced/volumes/delete-volume"; import React from "react";
import { AddVolumes } from "../../application/advanced/volumes/add-volumes"; import { AddVolumes } from "../../application/advanced/volumes/add-volumes";
import { DeleteVolume } from "../../application/advanced/volumes/delete-volume";
import { UpdateVolume } from "../../application/advanced/volumes/update-volume"; import { UpdateVolume } from "../../application/advanced/volumes/update-volume";
import { AlertBlock } from "@/components/shared/alert-block";
interface Props { interface Props {
composeId: string; composeId: string;
} }
@@ -1,4 +1,3 @@
import React from "react";
import { import {
AlertDialog, AlertDialog,
AlertDialogAction, AlertDialogAction,
@@ -12,6 +11,7 @@ import {
} from "@/components/ui/alert-dialog"; } from "@/components/ui/alert-dialog";
import { api } from "@/utils/api"; import { api } from "@/utils/api";
import { RefreshCcw } from "lucide-react"; import { RefreshCcw } from "lucide-react";
import React from "react";
import { toast } from "sonner"; import { toast } from "sonner";
interface Props { interface Props {
@@ -1,3 +1,5 @@
import { DateTooltip } from "@/components/shared/date-tooltip";
import { StatusTooltip } from "@/components/shared/status-tooltip";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { import {
Card, Card,
@@ -9,11 +11,9 @@ import {
import { api } from "@/utils/api"; import { api } from "@/utils/api";
import { RocketIcon } from "lucide-react"; import { RocketIcon } from "lucide-react";
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from "react";
import { StatusTooltip } from "@/components/shared/status-tooltip";
import { DateTooltip } from "@/components/shared/date-tooltip";
import { ShowDeploymentCompose } from "./show-deployment-compose";
import { RefreshTokenCompose } from "./refresh-token-compose";
import { CancelQueuesCompose } from "./cancel-queues-compose"; import { CancelQueuesCompose } from "./cancel-queues-compose";
import { RefreshTokenCompose } from "./refresh-token-compose";
import { ShowDeploymentCompose } from "./show-deployment-compose";
interface Props { interface Props {
composeId: string; composeId: string;
@@ -1,4 +1,5 @@
import React, { useEffect, useState } from "react"; import { CodeEditor } from "@/components/shared/code-editor";
import { Button } from "@/components/ui/button";
import { import {
Card, Card,
CardContent, CardContent,
@@ -6,10 +7,6 @@ import {
CardHeader, CardHeader,
CardTitle, CardTitle,
} from "@/components/ui/card"; } from "@/components/ui/card";
import { Button } from "@/components/ui/button";
import { z } from "zod";
import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { import {
Form, Form,
FormControl, FormControl,
@@ -17,11 +14,14 @@ import {
FormItem, FormItem,
FormMessage, FormMessage,
} from "@/components/ui/form"; } from "@/components/ui/form";
import { api } from "@/utils/api";
import { toast } from "sonner";
import { CodeEditor } from "@/components/shared/code-editor";
import { Toggle } from "@/components/ui/toggle"; import { Toggle } from "@/components/ui/toggle";
import { api } from "@/utils/api";
import { zodResolver } from "@hookform/resolvers/zod";
import { EyeIcon, EyeOffIcon } from "lucide-react"; import { EyeIcon, EyeOffIcon } from "lucide-react";
import React, { useEffect, useState } from "react";
import { useForm } from "react-hook-form";
import { toast } from "sonner";
import { z } from "zod";
const addEnvironmentSchema = z.object({ const addEnvironmentSchema = z.object({
environment: z.string(), environment: z.string(),
@@ -1,12 +1,4 @@
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { ExternalLink, Globe, Terminal } from "lucide-react";
import { api } from "@/utils/api";
import { toast } from "sonner";
import { Toggle } from "@/components/ui/toggle";
import { RedbuildCompose } from "./rebuild-compose";
import { DeployCompose } from "./deploy-compose";
import { StopCompose } from "./stop-compose";
import { DockerTerminalModal } from "../../settings/web-server/docker-terminal-modal";
import { import {
DropdownMenu, DropdownMenu,
DropdownMenuContent, DropdownMenuContent,
@@ -16,7 +8,15 @@ import {
DropdownMenuSeparator, DropdownMenuSeparator,
DropdownMenuTrigger, DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu"; } from "@/components/ui/dropdown-menu";
import { Toggle } from "@/components/ui/toggle";
import { api } from "@/utils/api";
import { ExternalLink, Globe, Terminal } from "lucide-react";
import Link from "next/link"; import Link from "next/link";
import { toast } from "sonner";
import { DockerTerminalModal } from "../../settings/web-server/docker-terminal-modal";
import { DeployCompose } from "./deploy-compose";
import { RedbuildCompose } from "./rebuild-compose";
import { StopCompose } from "./stop-compose";
interface Props { interface Props {
composeId: string; composeId: string;
@@ -1,5 +1,5 @@
import { api } from "@/utils/api"; import { CodeEditor } from "@/components/shared/code-editor";
import { useEffect } from "react"; import { Button } from "@/components/ui/button";
import { import {
Form, Form,
FormControl, FormControl,
@@ -7,14 +7,14 @@ import {
FormItem, FormItem,
FormMessage, FormMessage,
} from "@/components/ui/form"; } from "@/components/ui/form";
import { api } from "@/utils/api";
import { zodResolver } from "@hookform/resolvers/zod"; import { zodResolver } from "@hookform/resolvers/zod";
import { useEffect } from "react";
import { useForm } from "react-hook-form"; import { useForm } from "react-hook-form";
import { toast } from "sonner";
import { z } from "zod"; import { z } from "zod";
import { validateAndFormatYAML } from "../../application/advanced/traefik/update-traefik-config"; import { validateAndFormatYAML } from "../../application/advanced/traefik/update-traefik-config";
import { toast } from "sonner";
import { Button } from "@/components/ui/button";
import { RandomizeCompose } from "./randomize-compose"; import { RandomizeCompose } from "./randomize-compose";
import { CodeEditor } from "@/components/shared/code-editor";
interface Props { interface Props {
composeId: string; composeId: string;
@@ -4,9 +4,9 @@ import { api } from "@/utils/api";
import { GitBranch, LockIcon } from "lucide-react"; import { GitBranch, LockIcon } from "lucide-react";
import Link from "next/link"; import Link from "next/link";
import { useState } from "react"; import { useState } from "react";
import { SaveGithubProviderCompose } from "./save-github-provider-compose";
import { ComposeFileEditor } from "../compose-file-editor"; import { ComposeFileEditor } from "../compose-file-editor";
import { SaveGitProviderCompose } from "./save-git-provider-compose"; import { SaveGitProviderCompose } from "./save-git-provider-compose";
import { SaveGithubProviderCompose } from "./save-github-provider-compose";
type TabState = "github" | "git" | "raw"; type TabState = "github" | "git" | "raw";
interface Props { interface Props {
@@ -1,3 +1,4 @@
import { AlertBlock } from "@/components/shared/alert-block";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { import {
Dialog, Dialog,
@@ -7,12 +8,11 @@ import {
DialogTitle, DialogTitle,
DialogTrigger, DialogTrigger,
} from "@/components/ui/dialog"; } from "@/components/ui/dialog";
import { Input } from "@/components/ui/input";
import { api } from "@/utils/api"; import { api } from "@/utils/api";
import { AlertBlock } from "@/components/shared/alert-block";
import { Dices } from "lucide-react"; import { Dices } from "lucide-react";
import { useState } from "react"; import { useState } from "react";
import { toast } from "sonner"; import { toast } from "sonner";
import { Input } from "@/components/ui/input";
interface Props { interface Props {
composeId: string; composeId: string;
@@ -1,3 +1,4 @@
import { Badge } from "@/components/ui/badge";
import { import {
Card, Card,
CardContent, CardContent,
@@ -5,11 +6,10 @@ import {
CardHeader, CardHeader,
CardTitle, CardTitle,
} from "@/components/ui/card"; } from "@/components/ui/card";
import React from "react";
import { ShowProviderFormCompose } from "./generic/show";
import { ComposeActions } from "./actions";
import { Badge } from "@/components/ui/badge";
import { api } from "@/utils/api"; import { api } from "@/utils/api";
import React from "react";
import { ComposeActions } from "./actions";
import { ShowProviderFormCompose } from "./generic/show";
interface Props { interface Props {
composeId: string; composeId: string;
} }
+2 -2
View File
@@ -1,4 +1,3 @@
import dynamic from "next/dynamic";
import { import {
Card, Card,
CardContent, CardContent,
@@ -6,6 +5,7 @@ import {
CardHeader, CardHeader,
CardTitle, CardTitle,
} from "@/components/ui/card"; } from "@/components/ui/card";
import { Label } from "@/components/ui/label";
import { import {
Select, Select,
SelectContent, SelectContent,
@@ -16,8 +16,8 @@ import {
SelectValue, SelectValue,
} from "@/components/ui/select"; } from "@/components/ui/select";
import { api } from "@/utils/api"; import { api } from "@/utils/api";
import dynamic from "next/dynamic";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { Label } from "@/components/ui/label";
export const DockerLogs = dynamic( export const DockerLogs = dynamic(
() => () =>
import("@/components/dashboard/docker/logs/docker-logs-id").then( import("@/components/dashboard/docker/logs/docker-logs-id").then(
@@ -5,8 +5,7 @@ import {
CardHeader, CardHeader,
CardTitle, CardTitle,
} from "@/components/ui/card"; } from "@/components/ui/card";
import { api } from "@/utils/api"; import { Label } from "@/components/ui/label";
import { useEffect, useState } from "react";
import { import {
Select, Select,
SelectContent, SelectContent,
@@ -16,7 +15,8 @@ import {
SelectTrigger, SelectTrigger,
SelectValue, SelectValue,
} from "@/components/ui/select"; } from "@/components/ui/select";
import { Label } from "@/components/ui/label"; import { api } from "@/utils/api";
import { useEffect, useState } from "react";
import { DockerMonitoring } from "../../monitoring/docker/show"; import { DockerMonitoring } from "../../monitoring/docker/show";
interface Props { interface Props {
@@ -1,3 +1,5 @@
import { AlertBlock } from "@/components/shared/alert-block";
import { Button } from "@/components/ui/button";
import { import {
Dialog, Dialog,
DialogContent, DialogContent,
@@ -7,7 +9,6 @@ import {
DialogTitle, DialogTitle,
DialogTrigger, DialogTrigger,
} from "@/components/ui/dialog"; } from "@/components/ui/dialog";
import { Button } from "@/components/ui/button";
import { import {
Form, Form,
FormControl, FormControl,
@@ -16,16 +17,15 @@ import {
FormLabel, FormLabel,
FormMessage, FormMessage,
} from "@/components/ui/form"; } from "@/components/ui/form";
import { useForm } from "react-hook-form";
import { z } from "zod";
import { AlertBlock } from "@/components/shared/alert-block";
import { zodResolver } from "@hookform/resolvers/zod";
import { useEffect } from "react";
import { toast } from "sonner";
import { Input } from "@/components/ui/input"; import { Input } from "@/components/ui/input";
import { SquarePen } from "lucide-react";
import { Textarea } from "@/components/ui/textarea"; import { Textarea } from "@/components/ui/textarea";
import { api } from "@/utils/api"; import { api } from "@/utils/api";
import { zodResolver } from "@hookform/resolvers/zod";
import { SquarePen } from "lucide-react";
import { useEffect } from "react";
import { useForm } from "react-hook-form";
import { toast } from "sonner";
import { z } from "zod";
const updateComposeSchema = z.object({ const updateComposeSchema = z.object({
name: z.string().min(1, { name: z.string().min(1, {
@@ -1,4 +1,11 @@
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import {
Command,
CommandEmpty,
CommandGroup,
CommandInput,
CommandItem,
} from "@/components/ui/command";
import { import {
Dialog, Dialog,
DialogContent, DialogContent,
@@ -11,36 +18,29 @@ import {
import { import {
Form, Form,
FormControl, FormControl,
FormDescription,
FormField, FormField,
FormItem, FormItem,
FormLabel, FormLabel,
FormDescription,
FormMessage, FormMessage,
} from "@/components/ui/form"; } from "@/components/ui/form";
import { Input } from "@/components/ui/input"; import { Input } from "@/components/ui/input";
import { api } from "@/utils/api";
import { zodResolver } from "@hookform/resolvers/zod";
import { PlusIcon } from "lucide-react";
import { useEffect } from "react";
import { useForm } from "react-hook-form";
import { toast } from "sonner";
import { CheckIcon, ChevronsUpDown } from "lucide-react";
import { ScrollArea } from "@/components/ui/scroll-area";
import {
Command,
CommandEmpty,
CommandGroup,
CommandInput,
CommandItem,
} from "@/components/ui/command";
import { import {
Popover, Popover,
PopoverContent, PopoverContent,
PopoverTrigger, PopoverTrigger,
} from "@/components/ui/popover"; } from "@/components/ui/popover";
import { z } from "zod"; import { ScrollArea } from "@/components/ui/scroll-area";
import { cn } from "@/lib/utils";
import { Switch } from "@/components/ui/switch"; import { Switch } from "@/components/ui/switch";
import { cn } from "@/lib/utils";
import { api } from "@/utils/api";
import { zodResolver } from "@hookform/resolvers/zod";
import { PlusIcon } from "lucide-react";
import { CheckIcon, ChevronsUpDown } from "lucide-react";
import { useEffect } from "react";
import { useForm } from "react-hook-form";
import { toast } from "sonner";
import { z } from "zod";
const AddPostgresBackup1Schema = z.object({ const AddPostgresBackup1Schema = z.object({
destinationId: z.string().min(1, "Destination required"), destinationId: z.string().min(1, "Destination required"),
@@ -1,4 +1,11 @@
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import {
Command,
CommandEmpty,
CommandGroup,
CommandInput,
CommandItem,
} from "@/components/ui/command";
import { import {
Dialog, Dialog,
DialogContent, DialogContent,
@@ -18,28 +25,21 @@ import {
FormMessage, FormMessage,
} from "@/components/ui/form"; } from "@/components/ui/form";
import { Input } from "@/components/ui/input"; import { Input } from "@/components/ui/input";
import { api } from "@/utils/api";
import { zodResolver } from "@hookform/resolvers/zod";
import { Pencil, CheckIcon, ChevronsUpDown, PenBoxIcon } from "lucide-react";
import { useEffect } from "react";
import { useForm } from "react-hook-form";
import { toast } from "sonner";
import { ScrollArea } from "@/components/ui/scroll-area";
import { z } from "zod";
import { Switch } from "@/components/ui/switch";
import {
Command,
CommandEmpty,
CommandGroup,
CommandInput,
CommandItem,
} from "@/components/ui/command";
import { import {
Popover, Popover,
PopoverContent, PopoverContent,
PopoverTrigger, PopoverTrigger,
} from "@/components/ui/popover"; } from "@/components/ui/popover";
import { ScrollArea } from "@/components/ui/scroll-area";
import { Switch } from "@/components/ui/switch";
import { cn } from "@/lib/utils"; import { cn } from "@/lib/utils";
import { api } from "@/utils/api";
import { zodResolver } from "@hookform/resolvers/zod";
import { CheckIcon, ChevronsUpDown, PenBoxIcon, Pencil } from "lucide-react";
import { useEffect } from "react";
import { useForm } from "react-hook-form";
import { toast } from "sonner";
import { z } from "zod";
const UpdateBackupSchema = z.object({ const UpdateBackupSchema = z.object({
destinationId: z.string().min(1, "Destination required"), destinationId: z.string().min(1, "Destination required"),
@@ -1,7 +1,7 @@
import { Input } from "@/components/ui/input"; import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label"; import { Label } from "@/components/ui/label";
import React, { useEffect } from "react";
import { Terminal } from "@xterm/xterm"; import { Terminal } from "@xterm/xterm";
import React, { useEffect } from "react";
import { FitAddon } from "xterm-addon-fit"; import { FitAddon } from "xterm-addon-fit";
import "@xterm/xterm/css/xterm.css"; import "@xterm/xterm/css/xterm.css";
@@ -1,5 +1,3 @@
import dynamic from "next/dynamic";
import React from "react";
import { import {
Dialog, Dialog,
DialogContent, DialogContent,
@@ -9,6 +7,8 @@ import {
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 type React from "react";
export const DockerLogsId = dynamic( export const DockerLogsId = dynamic(
() => () =>
import("@/components/dashboard/docker/logs/docker-logs-id").then( import("@/components/dashboard/docker/logs/docker-logs-id").then(
+1 -1
View File
@@ -1,6 +1,6 @@
import * as React from "react";
import type { ColumnDef } from "@tanstack/react-table"; import type { ColumnDef } from "@tanstack/react-table";
import { ArrowUpDown, MoreHorizontal } from "lucide-react"; import { ArrowUpDown, MoreHorizontal } from "lucide-react";
import * as React from "react";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { import {
@@ -1,4 +1,3 @@
import * as React from "react";
import { import {
type ColumnFiltersState, type ColumnFiltersState,
type SortingState, type SortingState,
@@ -11,6 +10,7 @@ import {
useReactTable, useReactTable,
} from "@tanstack/react-table"; } from "@tanstack/react-table";
import { ChevronDown } from "lucide-react"; import { ChevronDown } from "lucide-react";
import * as React from "react";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { import {
@@ -28,7 +28,7 @@ import {
TableHeader, TableHeader,
TableRow, TableRow,
} from "@/components/ui/table"; } from "@/components/ui/table";
import { api, type RouterOutputs } from "@/utils/api"; import { type RouterOutputs, api } from "@/utils/api";
import { columns } from "./colums"; import { columns } from "./colums";
export type Container = NonNullable< export type Container = NonNullable<
RouterOutputs["docker"]["getContainers"] RouterOutputs["docker"]["getContainers"]
@@ -6,8 +6,8 @@ import {
DialogTitle, DialogTitle,
DialogTrigger, DialogTrigger,
} from "@/components/ui/dialog"; } from "@/components/ui/dialog";
import dynamic from "next/dynamic";
import { DropdownMenuItem } from "@/components/ui/dropdown-menu"; import { DropdownMenuItem } from "@/components/ui/dropdown-menu";
import dynamic from "next/dynamic";
const Terminal = dynamic( const Terminal = dynamic(
() => import("./docker-terminal").then((e) => e.DockerTerminal), () => import("./docker-terminal").then((e) => e.DockerTerminal),
@@ -1,9 +1,9 @@
import React, { useEffect, useRef } from "react";
import { Terminal } from "@xterm/xterm"; import { Terminal } from "@xterm/xterm";
import React, { useEffect, useRef } from "react";
import { FitAddon } from "xterm-addon-fit"; import { FitAddon } from "xterm-addon-fit";
import "@xterm/xterm/css/xterm.css"; import "@xterm/xterm/css/xterm.css";
import { AttachAddon } from "@xterm/addon-attach";
import { Tabs, TabsList, TabsTrigger } from "@/components/ui/tabs"; import { Tabs, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { AttachAddon } from "@xterm/addon-attach";
interface Props { interface Props {
id: string; id: string;
@@ -1,5 +1,7 @@
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { AlertBlock } from "@/components/shared/alert-block";
import { CodeEditor } from "@/components/shared/code-editor";
import { import {
Form, Form,
FormControl, FormControl,
@@ -10,14 +12,12 @@ import {
FormMessage, FormMessage,
} from "@/components/ui/form"; } from "@/components/ui/form";
import { api } from "@/utils/api"; import { api } from "@/utils/api";
import { AlertBlock } from "@/components/shared/alert-block";
import { zodResolver } from "@hookform/resolvers/zod"; import { zodResolver } from "@hookform/resolvers/zod";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { useForm } from "react-hook-form"; import { useForm } from "react-hook-form";
import { toast } from "sonner"; import { toast } from "sonner";
import { z } from "zod"; import { z } from "zod";
import { validateAndFormatYAML } from "../application/advanced/traefik/update-traefik-config"; import { validateAndFormatYAML } from "../application/advanced/traefik/update-traefik-config";
import { CodeEditor } from "@/components/shared/code-editor";
const UpdateServerMiddlewareConfigSchema = z.object({ const UpdateServerMiddlewareConfigSchema = z.object({
traefikConfig: z.string(), traefikConfig: z.string(),
@@ -1,8 +1,8 @@
import React from "react"; import React from "react";
import { api } from "@/utils/api";
import { Workflow, Folder, FileIcon } from "lucide-react";
import { Tree } from "@/components/ui/file-tree"; import { Tree } from "@/components/ui/file-tree";
import { api } from "@/utils/api";
import { FileIcon, Folder, Workflow } from "lucide-react";
import { cn } from "@/lib/utils"; import { cn } from "@/lib/utils";
import { ShowTraefikFile } from "./show-traefik-file"; import { ShowTraefikFile } from "./show-traefik-file";
@@ -1,12 +1,5 @@
import React, { useEffect } from "react";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { api } from "@/utils/api"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { z } from "zod";
import { Input } from "@/components/ui/input";
import { ShowMariadbResources } from "./show-mariadb-resources";
import { toast } from "sonner";
import { zodResolver } from "@hookform/resolvers/zod";
import { import {
Form, Form,
FormControl, FormControl,
@@ -15,8 +8,15 @@ import {
FormLabel, FormLabel,
FormMessage, FormMessage,
} from "@/components/ui/form"; } from "@/components/ui/form";
import { Input } from "@/components/ui/input";
import { api } from "@/utils/api";
import { zodResolver } from "@hookform/resolvers/zod";
import React, { useEffect } from "react";
import { useForm } from "react-hook-form"; import { useForm } from "react-hook-form";
import { toast } from "sonner";
import { z } from "zod";
import { ShowVolumes } from "../volumes/show-volumes"; import { ShowVolumes } from "../volumes/show-volumes";
import { ShowMariadbResources } from "./show-mariadb-resources";
const addDockerImage = z.object({ const addDockerImage = z.object({
dockerImage: z.string().min(1, "Docker image is required"), dockerImage: z.string().min(1, "Docker image is required"),
@@ -1,3 +1,4 @@
import { AlertBlock } from "@/components/shared/alert-block";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { import {
Card, Card,
@@ -21,7 +22,6 @@ import React, { useEffect } from "react";
import { useForm } from "react-hook-form"; import { useForm } from "react-hook-form";
import { toast } from "sonner"; import { toast } from "sonner";
import { z } from "zod"; import { z } from "zod";
import { AlertBlock } from "@/components/shared/alert-block";
const addResourcesMariadb = z.object({ const addResourcesMariadb = z.object({
memoryReservation: z.number().nullable().optional(), memoryReservation: z.number().nullable().optional(),
@@ -1,4 +1,4 @@
import React from "react"; import { Button } from "@/components/ui/button";
import { import {
Card, Card,
CardContent, CardContent,
@@ -6,20 +6,20 @@ import {
CardHeader, CardHeader,
CardTitle, CardTitle,
} from "@/components/ui/card"; } from "@/components/ui/card";
import { Button } from "@/components/ui/button";
import { api } from "@/utils/api";
import { DatabaseBackup, Play } from "lucide-react";
import Link from "next/link";
import { AddBackup } from "../../database/backups/add-backup";
import { DeleteBackup } from "../../database/backups/delete-backup";
import { UpdateBackup } from "../../database/backups/update-backup";
import { toast } from "sonner";
import { import {
Tooltip, Tooltip,
TooltipContent, TooltipContent,
TooltipProvider, TooltipProvider,
TooltipTrigger, TooltipTrigger,
} from "@/components/ui/tooltip"; } from "@/components/ui/tooltip";
import { api } from "@/utils/api";
import { DatabaseBackup, Play } from "lucide-react";
import Link from "next/link";
import React from "react";
import { toast } from "sonner";
import { AddBackup } from "../../database/backups/add-backup";
import { DeleteBackup } from "../../database/backups/delete-backup";
import { UpdateBackup } from "../../database/backups/update-backup";
interface Props { interface Props {
mariadbId: string; mariadbId: string;
} }
@@ -1,4 +1,5 @@
import React, { useEffect } from "react"; import { CodeEditor } from "@/components/shared/code-editor";
import { Button } from "@/components/ui/button";
import { import {
Card, Card,
CardContent, CardContent,
@@ -6,10 +7,6 @@ import {
CardHeader, CardHeader,
CardTitle, CardTitle,
} from "@/components/ui/card"; } from "@/components/ui/card";
import { Button } from "@/components/ui/button";
import { z } from "zod";
import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { import {
Form, Form,
FormControl, FormControl,
@@ -18,8 +15,11 @@ import {
FormMessage, FormMessage,
} from "@/components/ui/form"; } from "@/components/ui/form";
import { api } from "@/utils/api"; import { api } from "@/utils/api";
import { zodResolver } from "@hookform/resolvers/zod";
import React, { useEffect } from "react";
import { useForm } from "react-hook-form";
import { toast } from "sonner"; import { toast } from "sonner";
import { CodeEditor } from "@/components/shared/code-editor"; import { z } from "zod";
const addEnvironmentSchema = z.object({ const addEnvironmentSchema = z.object({
environment: z.string(), environment: z.string(),
@@ -1,3 +1,4 @@
import { ToggleVisibilityInput } from "@/components/shared/toggle-visibility-input";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { import {
Card, Card,
@@ -22,7 +23,6 @@ import React, { useEffect, useState } from "react";
import { useForm } from "react-hook-form"; import { useForm } from "react-hook-form";
import { toast } from "sonner"; import { toast } from "sonner";
import { z } from "zod"; import { z } from "zod";
import { ToggleVisibilityInput } from "@/components/shared/toggle-visibility-input";
const DockerProviderSchema = z.object({ const DockerProviderSchema = z.object({
externalPort: z.preprocess((a) => { externalPort: z.preprocess((a) => {
@@ -1,13 +1,13 @@
import React from "react";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { api } from "@/utils/api"; import { api } from "@/utils/api";
import { StopMariadb } from "./stop-mariadb";
import { StartMariadb } from "../start-mariadb";
import { DockerTerminalModal } from "../../settings/web-server/docker-terminal-modal";
import { Terminal } from "lucide-react"; import { Terminal } from "lucide-react";
import React from "react";
import { DockerTerminalModal } from "../../settings/web-server/docker-terminal-modal";
import { StartMariadb } from "../start-mariadb";
import { DeployMariadb } from "./deploy-mariadb"; import { DeployMariadb } from "./deploy-mariadb";
import { ResetMariadb } from "./reset-mariadb"; import { ResetMariadb } from "./reset-mariadb";
import { StopMariadb } from "./stop-mariadb";
interface Props { interface Props {
mariadbId: string; mariadbId: string;
@@ -1,9 +1,9 @@
import React from "react"; import { ToggleVisibilityInput } from "@/components/shared/toggle-visibility-input";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Input } from "@/components/ui/input"; import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label"; import { Label } from "@/components/ui/label";
import { api } from "@/utils/api"; import { api } from "@/utils/api";
import { ToggleVisibilityInput } from "@/components/shared/toggle-visibility-input"; import React from "react";
interface Props { interface Props {
mariadbId: string; mariadbId: string;
@@ -1,13 +1,13 @@
import { import {
AlertDialog, AlertDialog,
AlertDialogAction, AlertDialogAction,
AlertDialogCancel, AlertDialogCancel,
AlertDialogContent, AlertDialogContent,
AlertDialogDescription, AlertDialogDescription,
AlertDialogFooter, AlertDialogFooter,
AlertDialogHeader, AlertDialogHeader,
AlertDialogTitle, AlertDialogTitle,
AlertDialogTrigger, AlertDialogTrigger,
} from "@/components/ui/alert-dialog"; } from "@/components/ui/alert-dialog";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { api } from "@/utils/api"; import { api } from "@/utils/api";
@@ -15,51 +15,51 @@ import { Ban } from "lucide-react";
import { toast } from "sonner"; import { toast } from "sonner";
interface Props { interface Props {
mariadbId: string; mariadbId: string;
} }
export const StopMariadb = ({ mariadbId }: Props) => { export const StopMariadb = ({ mariadbId }: Props) => {
const { mutateAsync, isLoading } = api.mariadb.stop.useMutation(); const { mutateAsync, isLoading } = api.mariadb.stop.useMutation();
const utils = api.useUtils(); const utils = api.useUtils();
return ( return (
<AlertDialog> <AlertDialog>
<AlertDialogTrigger asChild> <AlertDialogTrigger asChild>
<Button variant="destructive" isLoading={isLoading}> <Button variant="destructive" isLoading={isLoading}>
Stop Stop
<Ban className="size-4" /> <Ban className="size-4" />
</Button> </Button>
</AlertDialogTrigger> </AlertDialogTrigger>
<AlertDialogContent> <AlertDialogContent>
<AlertDialogHeader> <AlertDialogHeader>
<AlertDialogTitle> <AlertDialogTitle>
Are you absolutely sure to stop the database? Are you absolutely sure to stop the database?
</AlertDialogTitle> </AlertDialogTitle>
<AlertDialogDescription> <AlertDialogDescription>
This will stop the database This will stop the database
</AlertDialogDescription> </AlertDialogDescription>
</AlertDialogHeader> </AlertDialogHeader>
<AlertDialogFooter> <AlertDialogFooter>
<AlertDialogCancel>Cancel</AlertDialogCancel> <AlertDialogCancel>Cancel</AlertDialogCancel>
<AlertDialogAction <AlertDialogAction
onClick={async () => { onClick={async () => {
await mutateAsync({ await mutateAsync({
mariadbId, mariadbId,
}) })
.then(async () => { .then(async () => {
await utils.mariadb.one.invalidate({ await utils.mariadb.one.invalidate({
mariadbId, mariadbId,
}); });
toast.success("Application stopped succesfully"); toast.success("Application stopped succesfully");
}) })
.catch(() => { .catch(() => {
toast.error("Error to stop the Application"); toast.error("Error to stop the Application");
}); });
}} }}
> >
Confirm Confirm
</AlertDialogAction> </AlertDialogAction>
</AlertDialogFooter> </AlertDialogFooter>
</AlertDialogContent> </AlertDialogContent>
</AlertDialog> </AlertDialog>
); );
}; };
+53 -53
View File
@@ -1,13 +1,13 @@
import { import {
AlertDialog, AlertDialog,
AlertDialogAction, AlertDialogAction,
AlertDialogCancel, AlertDialogCancel,
AlertDialogContent, AlertDialogContent,
AlertDialogDescription, AlertDialogDescription,
AlertDialogFooter, AlertDialogFooter,
AlertDialogHeader, AlertDialogHeader,
AlertDialogTitle, AlertDialogTitle,
AlertDialogTrigger, AlertDialogTrigger,
} from "@/components/ui/alert-dialog"; } from "@/components/ui/alert-dialog";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { api } from "@/utils/api"; import { api } from "@/utils/api";
@@ -15,51 +15,51 @@ import { CheckCircle2 } from "lucide-react";
import { toast } from "sonner"; import { toast } from "sonner";
interface Props { interface Props {
mariadbId: string; mariadbId: string;
} }
export const StartMariadb = ({ mariadbId }: Props) => { export const StartMariadb = ({ mariadbId }: Props) => {
const { mutateAsync, isLoading } = api.mariadb.start.useMutation(); const { mutateAsync, isLoading } = api.mariadb.start.useMutation();
const utils = api.useUtils(); const utils = api.useUtils();
return ( return (
<AlertDialog> <AlertDialog>
<AlertDialogTrigger asChild> <AlertDialogTrigger asChild>
<Button variant="secondary" isLoading={isLoading}> <Button variant="secondary" isLoading={isLoading}>
Start Start
<CheckCircle2 className="size-4" /> <CheckCircle2 className="size-4" />
</Button> </Button>
</AlertDialogTrigger> </AlertDialogTrigger>
<AlertDialogContent> <AlertDialogContent>
<AlertDialogHeader> <AlertDialogHeader>
<AlertDialogTitle> <AlertDialogTitle>
Are you sure to start the database? Are you sure to start the database?
</AlertDialogTitle> </AlertDialogTitle>
<AlertDialogDescription> <AlertDialogDescription>
This will start the database This will start the database
</AlertDialogDescription> </AlertDialogDescription>
</AlertDialogHeader> </AlertDialogHeader>
<AlertDialogFooter> <AlertDialogFooter>
<AlertDialogCancel>Cancel</AlertDialogCancel> <AlertDialogCancel>Cancel</AlertDialogCancel>
<AlertDialogAction <AlertDialogAction
onClick={async () => { onClick={async () => {
await mutateAsync({ await mutateAsync({
mariadbId, mariadbId,
}) })
.then(async () => { .then(async () => {
await utils.mariadb.one.invalidate({ await utils.mariadb.one.invalidate({
mariadbId, mariadbId,
}); });
toast.success("Database started succesfully"); toast.success("Database started succesfully");
}) })
.catch(() => { .catch(() => {
toast.error("Error to start the Database"); toast.error("Error to start the Database");
}); });
}} }}
> >
Confirm Confirm
</AlertDialogAction> </AlertDialogAction>
</AlertDialogFooter> </AlertDialogFooter>
</AlertDialogContent> </AlertDialogContent>
</AlertDialog> </AlertDialog>
); );
}; };
@@ -1,3 +1,5 @@
import { AlertBlock } from "@/components/shared/alert-block";
import { Button } from "@/components/ui/button";
import { import {
Dialog, Dialog,
DialogContent, DialogContent,
@@ -7,7 +9,6 @@ import {
DialogTitle, DialogTitle,
DialogTrigger, DialogTrigger,
} from "@/components/ui/dialog"; } from "@/components/ui/dialog";
import { Button } from "@/components/ui/button";
import { import {
Form, Form,
FormControl, FormControl,
@@ -16,16 +17,15 @@ import {
FormLabel, FormLabel,
FormMessage, FormMessage,
} from "@/components/ui/form"; } from "@/components/ui/form";
import { useForm } from "react-hook-form";
import { z } from "zod";
import { AlertBlock } from "@/components/shared/alert-block";
import { zodResolver } from "@hookform/resolvers/zod";
import { useEffect } from "react";
import { toast } from "sonner";
import { Input } from "@/components/ui/input"; import { Input } from "@/components/ui/input";
import { AlertTriangle, SquarePen } from "lucide-react";
import { Textarea } from "@/components/ui/textarea"; import { Textarea } from "@/components/ui/textarea";
import { api } from "@/utils/api"; import { api } from "@/utils/api";
import { zodResolver } from "@hookform/resolvers/zod";
import { AlertTriangle, SquarePen } from "lucide-react";
import { useEffect } from "react";
import { useForm } from "react-hook-form";
import { toast } from "sonner";
import { z } from "zod";
const updateMariadbSchema = z.object({ const updateMariadbSchema = z.object({
name: z.string().min(1, { name: z.string().min(1, {
@@ -1,4 +1,4 @@
import React from "react"; import { AlertBlock } from "@/components/shared/alert-block";
import { import {
Card, Card,
CardContent, CardContent,
@@ -8,10 +8,10 @@ import {
} from "@/components/ui/card"; } from "@/components/ui/card";
import { api } from "@/utils/api"; import { api } from "@/utils/api";
import { AlertTriangle, Package } from "lucide-react"; import { AlertTriangle, Package } from "lucide-react";
import { DeleteVolume } from "../../application/advanced/volumes/delete-volume"; import React from "react";
import { AddVolumes } from "../../application/advanced/volumes/add-volumes"; import { AddVolumes } from "../../application/advanced/volumes/add-volumes";
import { DeleteVolume } from "../../application/advanced/volumes/delete-volume";
import { UpdateVolume } from "../../application/advanced/volumes/update-volume"; import { UpdateVolume } from "../../application/advanced/volumes/update-volume";
import { AlertBlock } from "@/components/shared/alert-block";
interface Props { interface Props {
mariadbId: string; mariadbId: string;
} }
@@ -1,11 +1,5 @@
import React, { useEffect } from "react";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { api } from "@/utils/api"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { z } from "zod";
import { Input } from "@/components/ui/input";
import { toast } from "sonner";
import { zodResolver } from "@hookform/resolvers/zod";
import { import {
Form, Form,
FormControl, FormControl,
@@ -14,9 +8,15 @@ import {
FormLabel, FormLabel,
FormMessage, FormMessage,
} from "@/components/ui/form"; } from "@/components/ui/form";
import { Input } from "@/components/ui/input";
import { api } from "@/utils/api";
import { zodResolver } from "@hookform/resolvers/zod";
import React, { useEffect } from "react";
import { useForm } from "react-hook-form"; import { useForm } from "react-hook-form";
import { ShowMongoResources } from "./show-mongo-resources"; import { toast } from "sonner";
import { z } from "zod";
import { ShowVolumes } from "../volumes/show-volumes"; import { ShowVolumes } from "../volumes/show-volumes";
import { ShowMongoResources } from "./show-mongo-resources";
const addDockerImage = z.object({ const addDockerImage = z.object({
dockerImage: z.string().min(1, "Docker image is required"), dockerImage: z.string().min(1, "Docker image is required"),
@@ -1,3 +1,4 @@
import { AlertBlock } from "@/components/shared/alert-block";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { import {
Card, Card,
@@ -21,7 +22,6 @@ import React, { useEffect } from "react";
import { useForm } from "react-hook-form"; import { useForm } from "react-hook-form";
import { toast } from "sonner"; import { toast } from "sonner";
import { z } from "zod"; import { z } from "zod";
import { AlertBlock } from "@/components/shared/alert-block";
const addResourcesMongo = z.object({ const addResourcesMongo = z.object({
memoryReservation: z.number().nullable().optional(), memoryReservation: z.number().nullable().optional(),
@@ -1,4 +1,4 @@
import React from "react"; import { Button } from "@/components/ui/button";
import { import {
Card, Card,
CardContent, CardContent,
@@ -6,20 +6,20 @@ import {
CardHeader, CardHeader,
CardTitle, CardTitle,
} from "@/components/ui/card"; } from "@/components/ui/card";
import { Button } from "@/components/ui/button";
import { api } from "@/utils/api";
import { DatabaseBackup, Play } from "lucide-react";
import Link from "next/link";
import { AddBackup } from "../../database/backups/add-backup";
import { DeleteBackup } from "../../database/backups/delete-backup";
import { UpdateBackup } from "../../database/backups/update-backup";
import { toast } from "sonner";
import { import {
Tooltip, Tooltip,
TooltipContent, TooltipContent,
TooltipProvider, TooltipProvider,
TooltipTrigger, TooltipTrigger,
} from "@/components/ui/tooltip"; } from "@/components/ui/tooltip";
import { api } from "@/utils/api";
import { DatabaseBackup, Play } from "lucide-react";
import Link from "next/link";
import React from "react";
import { toast } from "sonner";
import { AddBackup } from "../../database/backups/add-backup";
import { DeleteBackup } from "../../database/backups/delete-backup";
import { UpdateBackup } from "../../database/backups/update-backup";
interface Props { interface Props {
mongoId: string; mongoId: string;
} }
@@ -1,13 +1,13 @@
import React from "react";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { api } from "@/utils/api"; import { api } from "@/utils/api";
import { StopMongo } from "./stop-mongo";
import { StartMongo } from "../start-mongo";
import { DockerTerminalModal } from "../../settings/web-server/docker-terminal-modal";
import { Terminal } from "lucide-react"; import { Terminal } from "lucide-react";
import React from "react";
import { DockerTerminalModal } from "../../settings/web-server/docker-terminal-modal";
import { StartMongo } from "../start-mongo";
import { DeployMongo } from "./deploy-mongo"; import { DeployMongo } from "./deploy-mongo";
import { ResetMongo } from "./reset-mongo"; import { ResetMongo } from "./reset-mongo";
import { StopMongo } from "./stop-mongo";
interface Props { interface Props {
mongoId: string; mongoId: string;
} }
@@ -1,9 +1,9 @@
import React from "react"; import { ToggleVisibilityInput } from "@/components/shared/toggle-visibility-input";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Input } from "@/components/ui/input"; import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label"; import { Label } from "@/components/ui/label";
import { api } from "@/utils/api"; import { api } from "@/utils/api";
import { ToggleVisibilityInput } from "@/components/shared/toggle-visibility-input"; import React from "react";
interface Props { interface Props {
mongoId: string; mongoId: string;
@@ -1,13 +1,13 @@
import { import {
AlertDialog, AlertDialog,
AlertDialogAction, AlertDialogAction,
AlertDialogCancel, AlertDialogCancel,
AlertDialogContent, AlertDialogContent,
AlertDialogDescription, AlertDialogDescription,
AlertDialogFooter, AlertDialogFooter,
AlertDialogHeader, AlertDialogHeader,
AlertDialogTitle, AlertDialogTitle,
AlertDialogTrigger, AlertDialogTrigger,
} from "@/components/ui/alert-dialog"; } from "@/components/ui/alert-dialog";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { api } from "@/utils/api"; import { api } from "@/utils/api";
@@ -15,51 +15,51 @@ import { Ban } from "lucide-react";
import { toast } from "sonner"; import { toast } from "sonner";
interface Props { interface Props {
mongoId: string; mongoId: string;
} }
export const StopMongo = ({ mongoId }: Props) => { export const StopMongo = ({ mongoId }: Props) => {
const { mutateAsync, isLoading } = api.mongo.stop.useMutation(); const { mutateAsync, isLoading } = api.mongo.stop.useMutation();
const utils = api.useUtils(); const utils = api.useUtils();
return ( return (
<AlertDialog> <AlertDialog>
<AlertDialogTrigger asChild> <AlertDialogTrigger asChild>
<Button variant="destructive" isLoading={isLoading}> <Button variant="destructive" isLoading={isLoading}>
Stop Stop
<Ban className="size-4" /> <Ban className="size-4" />
</Button> </Button>
</AlertDialogTrigger> </AlertDialogTrigger>
<AlertDialogContent> <AlertDialogContent>
<AlertDialogHeader> <AlertDialogHeader>
<AlertDialogTitle> <AlertDialogTitle>
Are you absolutely sure to stop the database? Are you absolutely sure to stop the database?
</AlertDialogTitle> </AlertDialogTitle>
<AlertDialogDescription> <AlertDialogDescription>
This will stop the database This will stop the database
</AlertDialogDescription> </AlertDialogDescription>
</AlertDialogHeader> </AlertDialogHeader>
<AlertDialogFooter> <AlertDialogFooter>
<AlertDialogCancel>Cancel</AlertDialogCancel> <AlertDialogCancel>Cancel</AlertDialogCancel>
<AlertDialogAction <AlertDialogAction
onClick={async () => { onClick={async () => {
await mutateAsync({ await mutateAsync({
mongoId, mongoId,
}) })
.then(async () => { .then(async () => {
await utils.mongo.one.invalidate({ await utils.mongo.one.invalidate({
mongoId, mongoId,
}); });
toast.success("Application stopped succesfully"); toast.success("Application stopped succesfully");
}) })
.catch(() => { .catch(() => {
toast.error("Error to stop the Application"); toast.error("Error to stop the Application");
}); });
}} }}
> >
Confirm Confirm
</AlertDialogAction> </AlertDialogAction>
</AlertDialogFooter> </AlertDialogFooter>
</AlertDialogContent> </AlertDialogContent>
</AlertDialog> </AlertDialog>
); );
}; };
+53 -53
View File
@@ -1,13 +1,13 @@
import { import {
AlertDialog, AlertDialog,
AlertDialogAction, AlertDialogAction,
AlertDialogCancel, AlertDialogCancel,
AlertDialogContent, AlertDialogContent,
AlertDialogDescription, AlertDialogDescription,
AlertDialogFooter, AlertDialogFooter,
AlertDialogHeader, AlertDialogHeader,
AlertDialogTitle, AlertDialogTitle,
AlertDialogTrigger, AlertDialogTrigger,
} from "@/components/ui/alert-dialog"; } from "@/components/ui/alert-dialog";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { api } from "@/utils/api"; import { api } from "@/utils/api";
@@ -15,51 +15,51 @@ import { CheckCircle2 } from "lucide-react";
import { toast } from "sonner"; import { toast } from "sonner";
interface Props { interface Props {
mongoId: string; mongoId: string;
} }
export const StartMongo = ({ mongoId }: Props) => { export const StartMongo = ({ mongoId }: Props) => {
const { mutateAsync, isLoading } = api.mongo.start.useMutation(); const { mutateAsync, isLoading } = api.mongo.start.useMutation();
const utils = api.useUtils(); const utils = api.useUtils();
return ( return (
<AlertDialog> <AlertDialog>
<AlertDialogTrigger asChild> <AlertDialogTrigger asChild>
<Button variant="secondary" isLoading={isLoading}> <Button variant="secondary" isLoading={isLoading}>
Start Start
<CheckCircle2 className="size-4" /> <CheckCircle2 className="size-4" />
</Button> </Button>
</AlertDialogTrigger> </AlertDialogTrigger>
<AlertDialogContent> <AlertDialogContent>
<AlertDialogHeader> <AlertDialogHeader>
<AlertDialogTitle> <AlertDialogTitle>
Are you sure to start the database? Are you sure to start the database?
</AlertDialogTitle> </AlertDialogTitle>
<AlertDialogDescription> <AlertDialogDescription>
This will start the database This will start the database
</AlertDialogDescription> </AlertDialogDescription>
</AlertDialogHeader> </AlertDialogHeader>
<AlertDialogFooter> <AlertDialogFooter>
<AlertDialogCancel>Cancel</AlertDialogCancel> <AlertDialogCancel>Cancel</AlertDialogCancel>
<AlertDialogAction <AlertDialogAction
onClick={async () => { onClick={async () => {
await mutateAsync({ await mutateAsync({
mongoId, mongoId,
}) })
.then(async () => { .then(async () => {
await utils.mongo.one.invalidate({ await utils.mongo.one.invalidate({
mongoId, mongoId,
}); });
toast.success("Database started succesfully"); toast.success("Database started succesfully");
}) })
.catch(() => { .catch(() => {
toast.error("Error to start the Database"); toast.error("Error to start the Database");
}); });
}} }}
> >
Confirm Confirm
</AlertDialogAction> </AlertDialogAction>
</AlertDialogFooter> </AlertDialogFooter>
</AlertDialogContent> </AlertDialogContent>
</AlertDialog> </AlertDialog>
); );
}; };
+8 -8
View File
@@ -1,3 +1,5 @@
import { AlertBlock } from "@/components/shared/alert-block";
import { Button } from "@/components/ui/button";
import { import {
Dialog, Dialog,
DialogContent, DialogContent,
@@ -7,7 +9,6 @@ import {
DialogTitle, DialogTitle,
DialogTrigger, DialogTrigger,
} from "@/components/ui/dialog"; } from "@/components/ui/dialog";
import { Button } from "@/components/ui/button";
import { import {
Form, Form,
FormControl, FormControl,
@@ -16,16 +17,15 @@ import {
FormLabel, FormLabel,
FormMessage, FormMessage,
} from "@/components/ui/form"; } from "@/components/ui/form";
import { useForm } from "react-hook-form";
import { z } from "zod";
import { AlertBlock } from "@/components/shared/alert-block";
import { zodResolver } from "@hookform/resolvers/zod";
import { useEffect } from "react";
import { toast } from "sonner";
import { Input } from "@/components/ui/input"; import { Input } from "@/components/ui/input";
import { AlertTriangle, SquarePen } from "lucide-react";
import { Textarea } from "@/components/ui/textarea"; import { Textarea } from "@/components/ui/textarea";
import { api } from "@/utils/api"; import { api } from "@/utils/api";
import { zodResolver } from "@hookform/resolvers/zod";
import { AlertTriangle, SquarePen } from "lucide-react";
import { useEffect } from "react";
import { useForm } from "react-hook-form";
import { toast } from "sonner";
import { z } from "zod";
const updateMongoSchema = z.object({ const updateMongoSchema = z.object({
name: z.string().min(1, { name: z.string().min(1, {
@@ -1,4 +1,4 @@
import React from "react"; import { AlertBlock } from "@/components/shared/alert-block";
import { import {
Card, Card,
CardContent, CardContent,
@@ -8,10 +8,10 @@ import {
} from "@/components/ui/card"; } from "@/components/ui/card";
import { api } from "@/utils/api"; import { api } from "@/utils/api";
import { AlertTriangle, Package } from "lucide-react"; import { AlertTriangle, Package } from "lucide-react";
import { DeleteVolume } from "../../application/advanced/volumes/delete-volume"; import React from "react";
import { AddVolumes } from "../../application/advanced/volumes/add-volumes"; import { AddVolumes } from "../../application/advanced/volumes/add-volumes";
import { DeleteVolume } from "../../application/advanced/volumes/delete-volume";
import { UpdateVolume } from "../../application/advanced/volumes/update-volume"; import { UpdateVolume } from "../../application/advanced/volumes/update-volume";
import { AlertBlock } from "@/components/shared/alert-block";
interface Props { interface Props {
mongoId: string; mongoId: string;
} }
@@ -1,14 +1,14 @@
import { format } from "date-fns";
import { import {
AreaChart,
Area, Area,
YAxis, AreaChart,
CartesianGrid, CartesianGrid,
Tooltip,
ResponsiveContainer,
Legend, Legend,
ResponsiveContainer,
Tooltip,
YAxis,
} from "recharts"; } from "recharts";
import type { DockerStatsJSON } from "./show"; import type { DockerStatsJSON } from "./show";
import { format } from "date-fns";
interface Props { interface Props {
acummulativeData: DockerStatsJSON["block"]; acummulativeData: DockerStatsJSON["block"];
@@ -1,14 +1,14 @@
import { format } from "date-fns";
import { import {
AreaChart,
Area, Area,
YAxis, AreaChart,
CartesianGrid, CartesianGrid,
Tooltip,
ResponsiveContainer,
Legend, Legend,
ResponsiveContainer,
Tooltip,
YAxis,
} from "recharts"; } from "recharts";
import type { DockerStatsJSON } from "./show"; import type { DockerStatsJSON } from "./show";
import { format } from "date-fns";
interface Props { interface Props {
acummulativeData: DockerStatsJSON["cpu"]; acummulativeData: DockerStatsJSON["cpu"];

Some files were not shown because too many files have changed in this diff Show More