mirror of
https://github.com/Dokploy/dokploy
synced 2025-06-26 18:27:59 +00:00
Compare commits
133 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bb59a0cd3f | ||
|
|
1e4217315b | ||
|
|
b373aca0ff | ||
|
|
87e90cb30b | ||
|
|
135fabb852 | ||
|
|
b0b5b94bb7 | ||
|
|
8f1c1e5202 | ||
|
|
e4c243d7a6 | ||
|
|
c3bca21d14 | ||
|
|
1befdb76e7 | ||
|
|
35652c5c53 | ||
|
|
9524609092 | ||
|
|
38c16fe839 | ||
|
|
c0587b9409 | ||
|
|
e249e878f6 | ||
|
|
2d64815c12 | ||
|
|
d0d4182fc1 | ||
|
|
736f7c2d77 | ||
|
|
6e38508477 | ||
|
|
afe8160d46 | ||
|
|
ceb4ae62e2 | ||
|
|
67d0dd5bf7 | ||
|
|
6e28545c3f | ||
|
|
382208ae13 | ||
|
|
906e8de13b | ||
|
|
7a5c71cda3 | ||
|
|
7bc6d0777d | ||
|
|
f684ba7b1f | ||
|
|
86ed884162 | ||
|
|
4ff178ea34 | ||
|
|
2eb5c331a1 | ||
|
|
84c10eec66 | ||
|
|
61673a40e3 | ||
|
|
363ba1d20e | ||
|
|
44e6a117dd | ||
|
|
86bb119052 | ||
|
|
54c70ff177 | ||
|
|
eabe14e4c3 | ||
|
|
9d0edd810e | ||
|
|
35ff65a871 | ||
|
|
675fbb7692 | ||
|
|
295bd06918 | ||
|
|
89635fa27b | ||
|
|
60b19616c1 | ||
|
|
3884dc9259 | ||
|
|
e8648732be | ||
|
|
0f0f32a40d | ||
|
|
1b91376f5e | ||
|
|
aa347abfcd | ||
|
|
e49b190c32 | ||
|
|
bfdc73f8d1 | ||
|
|
525a711c55 | ||
|
|
e0a0f97f70 | ||
|
|
66017c8623 | ||
|
|
bab93f8145 | ||
|
|
45aae520d8 | ||
|
|
c8f14c322e | ||
|
|
334466f28f | ||
|
|
22328eeb83 | ||
|
|
c2201a304e | ||
|
|
f77de1bc52 | ||
|
|
74d6b2d591 | ||
|
|
b7cc3283e2 | ||
|
|
5dfa6c5194 | ||
|
|
59d662396e | ||
|
|
cbfcae4ab6 | ||
|
|
152a54b251 | ||
|
|
1113669bfd | ||
|
|
4d251271b9 | ||
|
|
21263a217c | ||
|
|
3322fdf937 | ||
|
|
b415e2fba1 | ||
|
|
8888a4ce5c | ||
|
|
dd3ba7e836 | ||
|
|
cb6d8fceb4 | ||
|
|
d8641b7b4e | ||
|
|
997a8395b1 | ||
|
|
d2420ed6e8 | ||
|
|
64ada7020a | ||
|
|
faf24dfa25 | ||
|
|
6f4bf428c7 | ||
|
|
a43627d869 | ||
|
|
addd102d39 | ||
|
|
0d85fd0e3c | ||
|
|
86fc59d850 | ||
|
|
3cd3db6828 | ||
|
|
2c6fd0f52b | ||
|
|
5fb682b58d | ||
|
|
b77f330222 | ||
|
|
f0b8f3eaa0 | ||
|
|
36af22630b | ||
|
|
2d53a700f6 | ||
|
|
00eeffee13 | ||
|
|
7a32698031 | ||
|
|
9d834e1a79 | ||
|
|
91819c2488 | ||
|
|
f64392469d | ||
|
|
889e72d21e | ||
|
|
86165d1104 | ||
|
|
54adab16cf | ||
|
|
2e3b0ddcde | ||
|
|
ed0f3cadd6 | ||
|
|
898880634a | ||
|
|
b4e154fb28 | ||
|
|
2e6489d315 | ||
|
|
210fed30a2 | ||
|
|
60521c1025 | ||
|
|
1a496e35c0 | ||
|
|
f37f98aade | ||
|
|
0eb7b3ecb1 | ||
|
|
1a7c602861 | ||
|
|
4706adc0c0 | ||
|
|
85f025c729 | ||
|
|
06005eb333 | ||
|
|
0c01efb249 | ||
|
|
7e9e9dc865 | ||
|
|
b28bf5f9ec | ||
|
|
c071be6ad9 | ||
|
|
059a98c575 | ||
|
|
d2a07195b0 | ||
|
|
4ff1b3c19f | ||
|
|
39abd7e374 | ||
|
|
899d7565f6 | ||
|
|
3cfc2d6cd8 | ||
|
|
817fa91173 | ||
|
|
4d8a4f713d | ||
|
|
4865f4f969 | ||
|
|
0b7feb5483 | ||
|
|
1c139b9503 | ||
|
|
d47b7e62e6 | ||
|
|
33940a345a | ||
|
|
f230bda1f7 | ||
|
|
687524d154 |
2
.github/FUNDING.yml
vendored
2
.github/FUNDING.yml
vendored
@@ -1,6 +1,6 @@
|
||||
# These are supported funding model platforms
|
||||
|
||||
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
|
||||
github: [siumauricio]
|
||||
patreon: #
|
||||
open_collective: dokploy
|
||||
ko_fi: # Replace with a single Ko-fi username
|
||||
|
||||
59
.github/workflows/pull-request.yml
vendored
59
.github/workflows/pull-request.yml
vendored
@@ -1,59 +1,44 @@
|
||||
name: Pull request
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
- canary
|
||||
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- canary
|
||||
|
||||
env:
|
||||
HUSKY: 0
|
||||
|
||||
jobs:
|
||||
build-app:
|
||||
if: github.event_name == 'pull_request'
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [18.18.0]
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: pnpm/action-setup@v3
|
||||
with:
|
||||
version: 8
|
||||
- name: Check out the code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4
|
||||
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v3
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
cache: 'pnpm'
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install
|
||||
|
||||
- name: Run format and lint
|
||||
run: pnpm biome ci
|
||||
|
||||
- name: Run type check
|
||||
run: pnpm typecheck
|
||||
|
||||
- name: Run Build
|
||||
run: pnpm build
|
||||
|
||||
- name: Run Tests
|
||||
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
.github/workflows/push.yml
vendored
Normal file
35
.github/workflows/push.yml
vendored
Normal 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
.husky/install.mjs
Normal file
6
.husky/install.mjs
Normal 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
.husky/pre-commit
Normal file
1
.husky/pre-commit
Normal file
@@ -0,0 +1 @@
|
||||
pnpm lint-staged
|
||||
70
Dockerfile
70
Dockerfile
@@ -1,48 +1,65 @@
|
||||
# Etapa 1: Prepare image for building
|
||||
FROM node:18-slim AS base
|
||||
|
||||
# Install dependencies
|
||||
# Disable husky
|
||||
ENV HUSKY=0
|
||||
|
||||
# Set pnpm home
|
||||
ENV PNPM_HOME="/pnpm"
|
||||
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
|
||||
|
||||
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 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
|
||||
RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --frozen-lockfile
|
||||
|
||||
# Copy the rest of the source code
|
||||
COPY . .
|
||||
|
||||
# Build the application
|
||||
RUN pnpm run build
|
||||
# Build the application
|
||||
RUN pnpm build
|
||||
|
||||
# Stage 2: Prepare image for production
|
||||
FROM node:18-slim AS production
|
||||
FROM base AS production
|
||||
|
||||
# Set production
|
||||
ENV NODE_ENV=production
|
||||
|
||||
# Install dependencies only for production
|
||||
ENV PNPM_HOME="/pnpm"
|
||||
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/*
|
||||
RUN apt-get update && apt-get install -y curl apache2-utils && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# Copy the rest of the source code
|
||||
COPY --from=base /app/.next ./.next
|
||||
COPY --from=base /app/dist ./dist
|
||||
COPY --from=base /app/next.config.mjs ./next.config.mjs
|
||||
COPY --from=base /app/public ./public
|
||||
COPY --from=base /app/package.json ./package.json
|
||||
COPY --from=base /app/drizzle ./drizzle
|
||||
COPY --from=base /app/.env.production ./.env
|
||||
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
|
||||
# Copy the rest of the source code
|
||||
COPY --from=build /app/.next ./.next
|
||||
COPY --from=build /app/dist ./dist
|
||||
COPY --from=build /app/next.config.mjs ./next.config.mjs
|
||||
COPY --from=build /app/public ./public
|
||||
COPY --from=build /app/package.json ./package.json
|
||||
COPY --from=build /app/drizzle ./drizzle
|
||||
COPY --from=build /app/.env.production ./.env
|
||||
COPY --from=build /app/components.json ./components.json
|
||||
COPY --from=prod-deps /app/node_modules ./node_modules
|
||||
|
||||
# Install docker
|
||||
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 \
|
||||
&& pnpm install -g tsx
|
||||
|
||||
|
||||
# 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
|
||||
|
||||
# Expose port
|
||||
EXPOSE 3000
|
||||
|
||||
CMD ["pnpm", "start"]
|
||||
CMD ["pnpm", "start"]
|
||||
|
||||
53
README.md
53
README.md
@@ -1,4 +1,3 @@
|
||||
|
||||
<div align="center">
|
||||
<h1 align="center">Dokploy</h1>
|
||||
<div>
|
||||
@@ -11,74 +10,67 @@
|
||||
<br />
|
||||
Dokploy is a free self-hostable Platform as a Service (PaaS) that simplifies the deployment and management of applications and databases.
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
Dokploy include multiples features to make your life easier.
|
||||
|
||||
|
||||
* **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.
|
||||
* **Backups**: Automate backups for databases to a external storage destination.
|
||||
* **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.
|
||||
* **Templates**: Deploy in a single click open source templates (Plausible, Pocketbase, Calcom, etc.).
|
||||
* **Traefik Integration**: Automatically integrates with Traefik for routing and load balancing.
|
||||
* **Real-time Monitoring**: Monitor CPU, memory, storage, and network usage, for every resource.
|
||||
* **Docker Management**: Easily deploy and manage Docker containers.
|
||||
* **CLI (Soon⌛)**: Manage your applications and databases using the command line.
|
||||
* **Self-Hosted**: Self-host Dokploy on your VPS.
|
||||
|
||||
|
||||
|
||||
- **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.
|
||||
- **Backups**: Automate backups for databases to a external storage destination.
|
||||
- **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.
|
||||
- **Templates**: Deploy in a single click open source templates (Plausible, Pocketbase, Calcom, etc.).
|
||||
- **Traefik Integration**: Automatically integrates with Traefik for routing and load balancing.
|
||||
- **Real-time Monitoring**: Monitor CPU, memory, storage, and network usage, for every resource.
|
||||
- **Docker Management**: Easily deploy and manage Docker containers.
|
||||
- **CLI/API**: Manage your applications and databases using the command line or trought the API.
|
||||
- **Self-Hosted**: Self-host Dokploy on your VPS.
|
||||
|
||||
## 🚀 Getting Started
|
||||
|
||||
To get started run the following command in a VPS:
|
||||
|
||||
|
||||
```bash
|
||||
curl -sSL https://dokploy.com/install.sh | sh
|
||||
```
|
||||
|
||||
|
||||
## 📄 Documentation
|
||||
|
||||
For detailed documentation, visit [docs.dokploy.com](https://docs.dokploy.com).
|
||||
|
||||
|
||||
## Video Tutorial
|
||||
|
||||
<a href="https://youtu.be/mznYKPvhcfw">
|
||||
<img src="https://dokploy.com/banner.webp" alt="Watch the video" width="400" style="border-radius:20px;"/>
|
||||
</a>
|
||||
|
||||
|
||||
## 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:
|
||||
|
||||
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>
|
||||
|
||||
|
||||
## Contributors
|
||||
|
||||
<a href="https://github.com/dokploy/dokploy/graphs/contributors">
|
||||
<img src="https://contrib.rocks/image?repo=dokploy/dokploy" />
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
## Support OS
|
||||
|
||||
- Ubuntu 24.04 LTS
|
||||
- Ubuntu 24.04 LTS
|
||||
- Ubuntu 23.10
|
||||
- Ubuntu 22.04 LTS
|
||||
- Ubuntu 20.04 LTS
|
||||
- Ubuntu 22.04 LTS
|
||||
- Ubuntu 20.04 LTS
|
||||
- Ubuntu 18.04 LTS
|
||||
- Debian 12
|
||||
- Debian 11
|
||||
@@ -86,9 +78,6 @@ https://opencollective.com/dokploy
|
||||
- Centos 9
|
||||
- Centos 8
|
||||
|
||||
|
||||
|
||||
## Explanation
|
||||
|
||||
[English](README.md) | [中文](README-zh.md) | [Deutsch](README-de.md) | [Русский Язык](README-ru.md)
|
||||
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { expect, test } from "vitest";
|
||||
import { load } from "js-yaml";
|
||||
import { addPrefixToAllProperties } from "@/server/utils/docker/compose";
|
||||
import type { ComposeSpecification } from "@/server/utils/docker/types";
|
||||
import { load } from "js-yaml";
|
||||
import { expect, test } from "vitest";
|
||||
|
||||
const composeFile1 = `
|
||||
version: "3.8"
|
||||
|
||||
@@ -79,10 +79,11 @@ test("Add prefix to networks in services with aliases", () => {
|
||||
`frontend-${prefix}`,
|
||||
);
|
||||
|
||||
const networkConfig =
|
||||
actualComposeData?.services?.api?.networks[`frontend-${prefix}`];
|
||||
expect(networkConfig).toBeDefined();
|
||||
expect(networkConfig?.aliases).toContain("api");
|
||||
const networkConfig = actualComposeData?.services?.api?.networks as {
|
||||
[key: string]: { aliases?: string[] };
|
||||
};
|
||||
expect(networkConfig[`frontend-${prefix}`]).toBeDefined();
|
||||
expect(networkConfig[`frontend-${prefix}`]?.aliases).toContain("api");
|
||||
|
||||
expect(actualComposeData.services?.api?.networks).not.toHaveProperty(
|
||||
"frontend-ash",
|
||||
@@ -169,7 +170,9 @@ test("Add prefix to networks in services (combined case)", () => {
|
||||
);
|
||||
|
||||
// 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[`frontend-${prefix}`]).toBeDefined();
|
||||
expect(apiNetworks).not.toHaveProperty("frontend");
|
||||
|
||||
@@ -76,9 +76,11 @@ test("Add prefix to networks in services and root (combined case)", () => {
|
||||
);
|
||||
|
||||
// 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[`frontend-${prefix}`]?.aliases).toContain("api");
|
||||
expect(apiNetworks?.[`frontend-${prefix}`]?.aliases).toContain("api");
|
||||
expect(apiNetworks).not.toHaveProperty("frontend");
|
||||
|
||||
// Caso 3: Objeto con redes simples
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { expect, test } from "vitest";
|
||||
import { load, dump } from "js-yaml";
|
||||
import { generateRandomHash } from "@/server/utils/docker/compose";
|
||||
import type { ComposeSpecification } from "@/server/utils/docker/types";
|
||||
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", () => {
|
||||
const hash = generateRandomHash();
|
||||
|
||||
@@ -42,7 +42,7 @@ test("Add prefix to service names with container_name in compose file", () => {
|
||||
const actualComposeData = { ...composeData, services: updatedComposeData };
|
||||
|
||||
// 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}`,
|
||||
);
|
||||
// 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");
|
||||
|
||||
// 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",
|
||||
);
|
||||
expect(actualComposeData.services[`api-${prefix}`].image).toBe(
|
||||
expect(actualComposeData.services?.[`api-${prefix}`]?.image).toBe(
|
||||
"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");
|
||||
|
||||
// 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",
|
||||
);
|
||||
expect(actualComposeData.services[`api-${prefix}`].image).toBe(
|
||||
expect(actualComposeData.services?.[`api-${prefix}`]?.image).toBe(
|
||||
"myapi:latest",
|
||||
);
|
||||
|
||||
// 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}`,
|
||||
);
|
||||
expect(actualComposeData.services[`web-${prefix}`].depends_on).toContain(
|
||||
expect(actualComposeData.services?.[`web-${prefix}`]?.depends_on).toContain(
|
||||
`api-${prefix}`,
|
||||
);
|
||||
|
||||
// Verificar que los servicios `db` y `api` también tienen el prefijo
|
||||
expect(actualComposeData.services).toHaveProperty(`db-${prefix}`);
|
||||
expect(actualComposeData.services).not.toHaveProperty("db");
|
||||
expect(actualComposeData.services[`db-${prefix}`].image).toBe(
|
||||
expect(actualComposeData.services?.[`db-${prefix}`]?.image).toBe(
|
||||
"postgres:latest",
|
||||
);
|
||||
expect(actualComposeData.services).toHaveProperty(`api-${prefix}`);
|
||||
expect(actualComposeData.services).not.toHaveProperty("api");
|
||||
expect(actualComposeData.services[`api-${prefix}`].image).toBe(
|
||||
expect(actualComposeData.services?.[`api-${prefix}`]?.image).toBe(
|
||||
"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");
|
||||
|
||||
// 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",
|
||||
);
|
||||
expect(actualComposeData.services[`api-${prefix}`].image).toBe(
|
||||
expect(actualComposeData.services?.[`api-${prefix}`]?.image).toBe(
|
||||
"myapi:latest",
|
||||
);
|
||||
|
||||
// Verificar que los nombres en depends_on tienen el prefijo
|
||||
const webDependsOn = actualComposeData.services[`web-${prefix}`]
|
||||
.depends_on as Record<string, any>;
|
||||
const webDependsOn = actualComposeData.services?.[`web-${prefix}`]
|
||||
?.depends_on as Record<string, any>;
|
||||
expect(webDependsOn).toHaveProperty(`db-${prefix}`);
|
||||
expect(webDependsOn).toHaveProperty(`api-${prefix}`);
|
||||
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
|
||||
expect(actualComposeData.services).toHaveProperty(`db-${prefix}`);
|
||||
expect(actualComposeData.services).not.toHaveProperty("db");
|
||||
expect(actualComposeData.services[`db-${prefix}`].image).toBe(
|
||||
expect(actualComposeData.services?.[`db-${prefix}`]?.image).toBe(
|
||||
"postgres:latest",
|
||||
);
|
||||
expect(actualComposeData.services).toHaveProperty(`api-${prefix}`);
|
||||
expect(actualComposeData.services).not.toHaveProperty("api");
|
||||
expect(actualComposeData.services[`api-${prefix}`].image).toBe(
|
||||
expect(actualComposeData.services?.[`api-${prefix}`]?.image).toBe(
|
||||
"myapi:latest",
|
||||
);
|
||||
});
|
||||
|
||||
@@ -49,22 +49,22 @@ test("Add prefix to service names with extends (string) in compose file", () =>
|
||||
expect(actualComposeData.services).not.toHaveProperty("web");
|
||||
|
||||
// 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",
|
||||
);
|
||||
expect(actualComposeData.services[`api-${prefix}`].image).toBe(
|
||||
expect(actualComposeData.services?.[`api-${prefix}`]?.image).toBe(
|
||||
"myapi:latest",
|
||||
);
|
||||
|
||||
// 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}`,
|
||||
);
|
||||
|
||||
// Verificar que el servicio `base_service` también tiene el prefijo
|
||||
expect(actualComposeData.services).toHaveProperty(`base_service-${prefix}`);
|
||||
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",
|
||||
);
|
||||
});
|
||||
@@ -109,23 +109,23 @@ test("Add prefix to service names with extends (object) in compose file", () =>
|
||||
expect(actualComposeData.services).not.toHaveProperty("web");
|
||||
|
||||
// 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",
|
||||
);
|
||||
expect(actualComposeData.services[`api-${prefix}`].image).toBe(
|
||||
expect(actualComposeData.services?.[`api-${prefix}`]?.image).toBe(
|
||||
"myapi:latest",
|
||||
);
|
||||
|
||||
// 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") {
|
||||
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
|
||||
expect(actualComposeData.services).toHaveProperty(`base_service-${prefix}`);
|
||||
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",
|
||||
);
|
||||
});
|
||||
|
||||
@@ -50,27 +50,27 @@ test("Add prefix to service names with links in compose file", () => {
|
||||
expect(actualComposeData.services).not.toHaveProperty("web");
|
||||
|
||||
// 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",
|
||||
);
|
||||
expect(actualComposeData.services[`api-${prefix}`].image).toBe(
|
||||
expect(actualComposeData.services?.[`api-${prefix}`]?.image).toBe(
|
||||
"myapi:latest",
|
||||
);
|
||||
|
||||
// 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}`,
|
||||
);
|
||||
|
||||
// Verificar que los servicios `db` y `api` también tienen el prefijo
|
||||
expect(actualComposeData.services).toHaveProperty(`db-${prefix}`);
|
||||
expect(actualComposeData.services).not.toHaveProperty("db");
|
||||
expect(actualComposeData.services[`db-${prefix}`].image).toBe(
|
||||
expect(actualComposeData.services?.[`db-${prefix}`]?.image).toBe(
|
||||
"postgres:latest",
|
||||
);
|
||||
expect(actualComposeData.services).toHaveProperty(`api-${prefix}`);
|
||||
expect(actualComposeData.services).not.toHaveProperty("api");
|
||||
expect(actualComposeData.services[`api-${prefix}`].image).toBe(
|
||||
expect(actualComposeData.services?.[`api-${prefix}`]?.image).toBe(
|
||||
"myapi:latest",
|
||||
);
|
||||
});
|
||||
|
||||
@@ -54,23 +54,25 @@ test("Add prefix to service names with volumes_from in compose file", () => {
|
||||
expect(actualComposeData.services).not.toHaveProperty("web");
|
||||
|
||||
// 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",
|
||||
);
|
||||
expect(actualComposeData.services[`api-${prefix}`].image).toBe(
|
||||
expect(actualComposeData.services?.[`api-${prefix}`]?.image).toBe(
|
||||
"myapi:latest",
|
||||
);
|
||||
|
||||
// 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}`,
|
||||
);
|
||||
expect(actualComposeData.services[`api-${prefix}`].volumes_from).toContain(
|
||||
expect(actualComposeData.services?.[`api-${prefix}`]?.volumes_from).toContain(
|
||||
`shared-${prefix}`,
|
||||
);
|
||||
|
||||
// Verificar que el servicio shared también tiene el prefijo
|
||||
expect(actualComposeData.services).toHaveProperty(`shared-${prefix}`);
|
||||
expect(actualComposeData.services).not.toHaveProperty("shared");
|
||||
expect(actualComposeData.services[`shared-${prefix}`].image).toBe("busybox");
|
||||
expect(actualComposeData.services?.[`shared-${prefix}`]?.image).toBe(
|
||||
"busybox",
|
||||
);
|
||||
});
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { generateRandomHash } from "@/server/utils/docker/compose";
|
||||
import {
|
||||
addPrefixToVolumesRoot,
|
||||
addPrefixToAllVolumes,
|
||||
addPrefixToVolumesRoot,
|
||||
} from "@/server/utils/docker/compose/volume";
|
||||
import type { ComposeSpecification } from "@/server/utils/docker/types";
|
||||
import { load } from "js-yaml";
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { defineConfig } from "vitest/config";
|
||||
import tsconfigPaths from "vite-tsconfig-paths";
|
||||
import { defineConfig } from "vitest/config";
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [
|
||||
|
||||
49
biome.json
49
biome.json
@@ -1,17 +1,34 @@
|
||||
{
|
||||
"$schema": "./node_modules/@biomejs/biome/configuration_schema.json",
|
||||
"linter":{
|
||||
"rules": {
|
||||
"correctness":{
|
||||
"useExhaustiveDependencies": "off"
|
||||
},
|
||||
"suspicious":{
|
||||
"noArrayIndexKey": "off"
|
||||
},
|
||||
"a11y":{
|
||||
"noSvgWithoutTitle":"off"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
"$schema": "./node_modules/@biomejs/biome/configuration_schema.json",
|
||||
"files": {
|
||||
"ignore": ["node_modules/**", ".next/**", "drizzle/**", ".docker"]
|
||||
},
|
||||
"organizeImports": {
|
||||
"enabled": true
|
||||
},
|
||||
"linter": {
|
||||
"rules": {
|
||||
"complexity": {
|
||||
"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"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
{
|
||||
"$schema": "https://ui.shadcn.com/schema.json",
|
||||
"style": "default",
|
||||
"rsc": false,
|
||||
"tsx": true,
|
||||
"tailwind": {
|
||||
"config": "tailwind.config.ts",
|
||||
"css": "styles/globals.css",
|
||||
"baseColor": "zinc",
|
||||
"cssVariables": true,
|
||||
"prefix": ""
|
||||
},
|
||||
"aliases": {
|
||||
"components": "@/components",
|
||||
"utils": "@/lib/utils"
|
||||
}
|
||||
}
|
||||
"$schema": "https://ui.shadcn.com/schema.json",
|
||||
"style": "default",
|
||||
"rsc": false,
|
||||
"tsx": true,
|
||||
"tailwind": {
|
||||
"config": "tailwind.config.ts",
|
||||
"css": "styles/globals.css",
|
||||
"baseColor": "zinc",
|
||||
"cssVariables": true,
|
||||
"prefix": ""
|
||||
},
|
||||
"aliases": {
|
||||
"components": "@/components",
|
||||
"utils": "@/lib/utils"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,19 +10,19 @@ import {
|
||||
} from "@/components/ui/form";
|
||||
|
||||
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 {
|
||||
InputOTP,
|
||||
InputOTPGroup,
|
||||
InputOTPSlot,
|
||||
} 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 { useEffect } from "react";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { toast } from "sonner";
|
||||
import { z } from "zod";
|
||||
|
||||
const Login2FASchema = z.object({
|
||||
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 {
|
||||
Dialog,
|
||||
@@ -17,21 +19,19 @@ import {
|
||||
FormLabel,
|
||||
FormMessage,
|
||||
} 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 {
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
TooltipProvider,
|
||||
TooltipTrigger,
|
||||
} 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
|
||||
.object({
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import React from "react";
|
||||
import { AlertBlock } from "@/components/shared/alert-block";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
@@ -6,8 +7,6 @@ import {
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} from "@/components/ui/card";
|
||||
import { api } from "@/utils/api";
|
||||
import { z } from "zod";
|
||||
import {
|
||||
Form,
|
||||
FormControl,
|
||||
@@ -16,11 +15,6 @@ import {
|
||||
FormLabel,
|
||||
FormMessage,
|
||||
} 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 {
|
||||
Select,
|
||||
@@ -31,10 +25,16 @@ import {
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} 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 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 { AlertBlock } from "@/components/shared/alert-block";
|
||||
|
||||
interface Props {
|
||||
applicationId: string;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React from "react";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
@@ -6,8 +6,6 @@ import {
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} from "@/components/ui/card";
|
||||
import { api } from "@/utils/api";
|
||||
import { z } from "zod";
|
||||
import {
|
||||
Form,
|
||||
FormControl,
|
||||
@@ -16,12 +14,14 @@ import {
|
||||
FormLabel,
|
||||
FormMessage,
|
||||
} 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 { 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 {
|
||||
applicationId: string;
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { AlertBlock } from "@/components/shared/alert-block";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import {
|
||||
Dialog,
|
||||
@@ -17,13 +18,6 @@ import {
|
||||
FormMessage,
|
||||
} from "@/components/ui/form";
|
||||
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 {
|
||||
Select,
|
||||
SelectContent,
|
||||
@@ -31,6 +25,12 @@ import {
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} 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";
|
||||
|
||||
const AddPortSchema = z.object({
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React from "react";
|
||||
import { AlertBlock } from "@/components/shared/alert-block";
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
@@ -8,10 +8,10 @@ import {
|
||||
} from "@/components/ui/card";
|
||||
import { api } from "@/utils/api";
|
||||
import { Rss } from "lucide-react";
|
||||
import React from "react";
|
||||
import { AddPort } from "./add-port";
|
||||
import { DeletePort } from "./delete-port";
|
||||
import { UpdatePort } from "./update-port";
|
||||
import { AlertBlock } from "@/components/shared/alert-block";
|
||||
interface Props {
|
||||
applicationId: string;
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { AlertBlock } from "@/components/shared/alert-block";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import {
|
||||
Dialog,
|
||||
@@ -17,14 +18,6 @@ import {
|
||||
FormMessage,
|
||||
} from "@/components/ui/form";
|
||||
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 {
|
||||
Select,
|
||||
SelectContent,
|
||||
@@ -32,6 +25,13 @@ import {
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} 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({
|
||||
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 {
|
||||
Dialog,
|
||||
@@ -11,22 +12,21 @@ import {
|
||||
import {
|
||||
Form,
|
||||
FormControl,
|
||||
FormDescription,
|
||||
FormField,
|
||||
FormItem,
|
||||
FormLabel,
|
||||
FormDescription,
|
||||
FormMessage,
|
||||
} from "@/components/ui/form";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Switch } from "@/components/ui/switch";
|
||||
import { api } from "@/utils/api";
|
||||
import { AlertBlock } from "@/components/shared/alert-block";
|
||||
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 { PlusIcon } from "lucide-react";
|
||||
import { z } from "zod";
|
||||
import { Switch } from "@/components/ui/switch";
|
||||
|
||||
const AddRedirectchema = z.object({
|
||||
regex: z.string().min(1, "Regex required"),
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import React from "react";
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
@@ -8,6 +7,7 @@ import {
|
||||
} from "@/components/ui/card";
|
||||
import { api } from "@/utils/api";
|
||||
import { Split } from "lucide-react";
|
||||
import React from "react";
|
||||
import { AddRedirect } from "./add-redirect";
|
||||
import { DeleteRedirect } from "./delete-redirect";
|
||||
import { UpdateRedirect } from "./update-redirect";
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { AlertBlock } from "@/components/shared/alert-block";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import {
|
||||
Dialog,
|
||||
@@ -11,22 +12,21 @@ import {
|
||||
import {
|
||||
Form,
|
||||
FormControl,
|
||||
FormDescription,
|
||||
FormField,
|
||||
FormItem,
|
||||
FormLabel,
|
||||
FormDescription,
|
||||
FormMessage,
|
||||
} from "@/components/ui/form";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Switch } from "@/components/ui/switch";
|
||||
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 { Switch } from "@/components/ui/switch";
|
||||
const UpdateRedirectSchema = z.object({
|
||||
regex: z.string().min(1, "Regex required"),
|
||||
permanent: z.boolean().default(false),
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { AlertBlock } from "@/components/shared/alert-block";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import {
|
||||
Dialog,
|
||||
@@ -18,12 +19,11 @@ import {
|
||||
} from "@/components/ui/form";
|
||||
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 { PlusIcon } from "lucide-react";
|
||||
import { useEffect } from "react";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { toast } from "sonner";
|
||||
import { PlusIcon } from "lucide-react";
|
||||
import { z } from "zod";
|
||||
|
||||
const AddSecuritychema = z.object({
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import React from "react";
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
@@ -8,6 +7,7 @@ import {
|
||||
} from "@/components/ui/card";
|
||||
import { api } from "@/utils/api";
|
||||
import { LockKeyhole } from "lucide-react";
|
||||
import React from "react";
|
||||
import { AddSecurity } from "./add-security";
|
||||
import { DeleteSecurity } from "./delete-security";
|
||||
import { UpdateSecurity } from "./update-security";
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { AlertBlock } from "@/components/shared/alert-block";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import {
|
||||
Dialog,
|
||||
@@ -18,7 +19,6 @@ import {
|
||||
} from "@/components/ui/form";
|
||||
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";
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { AlertBlock } from "@/components/shared/alert-block";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import {
|
||||
Card,
|
||||
@@ -21,7 +22,6 @@ import React, { useEffect } from "react";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { toast } from "sonner";
|
||||
import { z } from "zod";
|
||||
import { AlertBlock } from "@/components/shared/alert-block";
|
||||
|
||||
const addResourcesApplication = z.object({
|
||||
memoryReservation: z.number().nullable().optional(),
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React from "react";
|
||||
import { CodeEditor } from "@/components/shared/code-editor";
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
@@ -8,8 +8,8 @@ import {
|
||||
} from "@/components/ui/card";
|
||||
import { api } from "@/utils/api";
|
||||
import { File } from "lucide-react";
|
||||
import React from "react";
|
||||
import { UpdateTraefikConfig } from "./update-traefik-config";
|
||||
import { CodeEditor } from "@/components/shared/code-editor";
|
||||
interface Props {
|
||||
applicationId: string;
|
||||
}
|
||||
@@ -29,7 +29,7 @@ export const ShowTraefikConfig = ({ applicationId }: Props) => {
|
||||
<CardTitle className="text-xl">Traefik</CardTitle>
|
||||
<CardDescription>
|
||||
Modify the traefik config, in rare cases you may need to add
|
||||
specific config, becarefull because modifying incorrectly can break
|
||||
specific config, be careful because modifying incorrectly can break
|
||||
traefik and your application
|
||||
</CardDescription>
|
||||
</div>
|
||||
|
||||
@@ -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 {
|
||||
Dialog,
|
||||
@@ -17,14 +19,12 @@ import {
|
||||
FormMessage,
|
||||
} from "@/components/ui/form";
|
||||
import { api } from "@/utils/api";
|
||||
import { AlertBlock } from "@/components/shared/alert-block";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import jsyaml from "js-yaml";
|
||||
import { useEffect, useState } from "react";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { toast } from "sonner";
|
||||
import { z } from "zod";
|
||||
import jsyaml from "js-yaml";
|
||||
import { CodeEditor } from "@/components/shared/code-editor";
|
||||
|
||||
const UpdateTraefikConfigSchema = z.object({
|
||||
traefikConfig: z.string(),
|
||||
@@ -110,12 +110,15 @@ export const UpdateTraefikConfig = ({ applicationId }: Props) => {
|
||||
};
|
||||
|
||||
return (
|
||||
<Dialog open={open} onOpenChange={(open) => {
|
||||
setOpen(open)
|
||||
if (!open) {
|
||||
form.reset();
|
||||
}
|
||||
}}>
|
||||
<Dialog
|
||||
open={open}
|
||||
onOpenChange={(open) => {
|
||||
setOpen(open);
|
||||
if (!open) {
|
||||
form.reset();
|
||||
}
|
||||
}}
|
||||
>
|
||||
<DialogTrigger asChild>
|
||||
<Button isLoading={isLoading}>Modify</Button>
|
||||
</DialogTrigger>
|
||||
|
||||
@@ -1,8 +1,4 @@
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import type React from "react";
|
||||
import { useEffect } from "react";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { z } from "zod";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
@@ -22,12 +18,16 @@ import {
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Label } from "@/components/ui/label";
|
||||
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 { api } from "@/utils/api";
|
||||
import { toast } from "sonner";
|
||||
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 {
|
||||
serviceId: string;
|
||||
serviceType:
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import React from "react";
|
||||
import {
|
||||
AlertDialog,
|
||||
AlertDialogAction,
|
||||
@@ -13,6 +12,7 @@ import {
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { api } from "@/utils/api";
|
||||
import { TrashIcon } from "lucide-react";
|
||||
import React from "react";
|
||||
import { toast } from "sonner";
|
||||
|
||||
interface Props {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React from "react";
|
||||
import { AlertBlock } from "@/components/shared/alert-block";
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
@@ -8,10 +8,10 @@ import {
|
||||
} from "@/components/ui/card";
|
||||
import { api } from "@/utils/api";
|
||||
import { AlertTriangle, Package } from "lucide-react";
|
||||
import React from "react";
|
||||
import { AddVolumes } from "./add-volumes";
|
||||
import { DeleteVolume } from "./delete-volume";
|
||||
import { UpdateVolume } from "./update-volume";
|
||||
import { AlertBlock } from "@/components/shared/alert-block";
|
||||
interface Props {
|
||||
applicationId: string;
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { AlertBlock } from "@/components/shared/alert-block";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import {
|
||||
Dialog,
|
||||
@@ -17,15 +18,14 @@ import {
|
||||
FormMessage,
|
||||
} from "@/components/ui/form";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Textarea } from "@/components/ui/textarea";
|
||||
import { api } from "@/utils/api";
|
||||
import { AlertBlock } from "@/components/shared/alert-block";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { Pencil } from "lucide-react";
|
||||
import { useEffect } from "react";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { toast } from "sonner";
|
||||
import { z } from "zod";
|
||||
import { Textarea } from "@/components/ui/textarea";
|
||||
|
||||
const mountSchema = z.object({
|
||||
mountPath: z.string().min(1, "Mount path required"),
|
||||
|
||||
@@ -1,213 +1,213 @@
|
||||
import {
|
||||
Form,
|
||||
FormControl,
|
||||
FormField,
|
||||
FormItem,
|
||||
FormLabel,
|
||||
FormMessage,
|
||||
} from "@/components/ui/form";
|
||||
import { Button } from "@/components/ui/button";
|
||||
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 { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { Cog } from "lucide-react";
|
||||
import { useEffect } from "react";
|
||||
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 { Input } from "@/components/ui/input";
|
||||
import { z } from "zod";
|
||||
|
||||
enum BuildType {
|
||||
dockerfile = "dockerfile",
|
||||
heroku_buildpacks = "heroku_buildpacks",
|
||||
paketo_buildpacks = "paketo_buildpacks",
|
||||
nixpacks = "nixpacks",
|
||||
dockerfile = "dockerfile",
|
||||
heroku_buildpacks = "heroku_buildpacks",
|
||||
paketo_buildpacks = "paketo_buildpacks",
|
||||
nixpacks = "nixpacks",
|
||||
}
|
||||
|
||||
const mySchema = z.discriminatedUnion("buildType", [
|
||||
z.object({
|
||||
buildType: z.literal("dockerfile"),
|
||||
dockerfile: z
|
||||
.string({
|
||||
required_error: "Dockerfile path is required",
|
||||
invalid_type_error: "Dockerfile path is required",
|
||||
})
|
||||
.min(1, "Dockerfile required"),
|
||||
}),
|
||||
z.object({
|
||||
buildType: z.literal("heroku_buildpacks"),
|
||||
}),
|
||||
z.object({
|
||||
buildType: z.literal("paketo_buildpacks"),
|
||||
}),
|
||||
z.object({
|
||||
buildType: z.literal("nixpacks"),
|
||||
}),
|
||||
z.object({
|
||||
buildType: z.literal("dockerfile"),
|
||||
dockerfile: z
|
||||
.string({
|
||||
required_error: "Dockerfile path is required",
|
||||
invalid_type_error: "Dockerfile path is required",
|
||||
})
|
||||
.min(1, "Dockerfile required"),
|
||||
}),
|
||||
z.object({
|
||||
buildType: z.literal("heroku_buildpacks"),
|
||||
}),
|
||||
z.object({
|
||||
buildType: z.literal("paketo_buildpacks"),
|
||||
}),
|
||||
z.object({
|
||||
buildType: z.literal("nixpacks"),
|
||||
}),
|
||||
]);
|
||||
|
||||
type AddTemplate = z.infer<typeof mySchema>;
|
||||
interface Props {
|
||||
applicationId: string;
|
||||
applicationId: string;
|
||||
}
|
||||
|
||||
export const ShowBuildChooseForm = ({ applicationId }: Props) => {
|
||||
const { mutateAsync, isLoading } =
|
||||
api.application.saveBuildType.useMutation();
|
||||
const { data, refetch } = api.application.one.useQuery(
|
||||
{
|
||||
applicationId,
|
||||
},
|
||||
{
|
||||
enabled: !!applicationId,
|
||||
},
|
||||
);
|
||||
const { mutateAsync, isLoading } =
|
||||
api.application.saveBuildType.useMutation();
|
||||
const { data, refetch } = api.application.one.useQuery(
|
||||
{
|
||||
applicationId,
|
||||
},
|
||||
{
|
||||
enabled: !!applicationId,
|
||||
},
|
||||
);
|
||||
|
||||
const form = useForm<AddTemplate>({
|
||||
defaultValues: {
|
||||
buildType: BuildType.nixpacks,
|
||||
},
|
||||
resolver: zodResolver(mySchema),
|
||||
});
|
||||
const form = useForm<AddTemplate>({
|
||||
defaultValues: {
|
||||
buildType: BuildType.nixpacks,
|
||||
},
|
||||
resolver: zodResolver(mySchema),
|
||||
});
|
||||
|
||||
const buildType = form.watch("buildType");
|
||||
useEffect(() => {
|
||||
if (data) {
|
||||
// TODO: refactor this
|
||||
if (data.buildType === "dockerfile") {
|
||||
form.reset({
|
||||
buildType: data.buildType,
|
||||
...(data.buildType && {
|
||||
dockerfile: data.dockerfile || "",
|
||||
}),
|
||||
});
|
||||
} else {
|
||||
form.reset({
|
||||
buildType: data.buildType,
|
||||
});
|
||||
}
|
||||
}
|
||||
}, [form.formState.isSubmitSuccessful, form.reset, data, form]);
|
||||
const buildType = form.watch("buildType");
|
||||
useEffect(() => {
|
||||
if (data) {
|
||||
// TODO: refactor this
|
||||
if (data.buildType === "dockerfile") {
|
||||
form.reset({
|
||||
buildType: data.buildType,
|
||||
...(data.buildType && {
|
||||
dockerfile: data.dockerfile || "",
|
||||
}),
|
||||
});
|
||||
} else {
|
||||
form.reset({
|
||||
buildType: data.buildType,
|
||||
});
|
||||
}
|
||||
}
|
||||
}, [form.formState.isSubmitSuccessful, form.reset, data, form]);
|
||||
|
||||
const onSubmit = async (data: AddTemplate) => {
|
||||
await mutateAsync({
|
||||
applicationId,
|
||||
buildType: data.buildType,
|
||||
dockerfile: data.buildType === "dockerfile" ? data.dockerfile : null,
|
||||
})
|
||||
.then(async () => {
|
||||
toast.success("Build type saved");
|
||||
await refetch();
|
||||
})
|
||||
.catch(() => {
|
||||
toast.error("Error to save the build type");
|
||||
});
|
||||
};
|
||||
const onSubmit = async (data: AddTemplate) => {
|
||||
await mutateAsync({
|
||||
applicationId,
|
||||
buildType: data.buildType,
|
||||
dockerfile: data.buildType === "dockerfile" ? data.dockerfile : null,
|
||||
})
|
||||
.then(async () => {
|
||||
toast.success("Build type saved");
|
||||
await refetch();
|
||||
})
|
||||
.catch(() => {
|
||||
toast.error("Error to save the build type");
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<Card className="group relative w-full bg-transparent">
|
||||
<CardHeader>
|
||||
<CardTitle className="flex items-start justify-between">
|
||||
<div className="flex flex-col gap-2">
|
||||
<span className="flex flex-col space-y-0.5">Build Type</span>
|
||||
<p className="flex items-center text-sm font-normal text-muted-foreground">
|
||||
Select the way of building your code
|
||||
</p>
|
||||
</div>
|
||||
<div className="hidden space-y-1 text-sm font-normal md:block">
|
||||
<Cog className="size-6 text-muted-foreground" />
|
||||
</div>
|
||||
</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<Form {...form}>
|
||||
<form
|
||||
onSubmit={form.handleSubmit(onSubmit)}
|
||||
className="grid w-full gap-4 p-2"
|
||||
>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="buildType"
|
||||
defaultValue={form.control._defaultValues.buildType}
|
||||
render={({ field }) => {
|
||||
return (
|
||||
<FormItem className="space-y-3">
|
||||
<FormLabel>Build Type</FormLabel>
|
||||
<FormControl>
|
||||
<RadioGroup
|
||||
onValueChange={field.onChange}
|
||||
value={field.value}
|
||||
className="flex flex-col space-y-1"
|
||||
>
|
||||
<FormItem className="flex items-center space-x-3 space-y-0">
|
||||
<FormControl>
|
||||
<RadioGroupItem value="dockerfile" />
|
||||
</FormControl>
|
||||
<FormLabel className="font-normal">
|
||||
Dockerfile
|
||||
</FormLabel>
|
||||
</FormItem>
|
||||
<FormItem className="flex items-center space-x-3 space-y-0">
|
||||
<FormControl>
|
||||
<RadioGroupItem value="nixpacks" />
|
||||
</FormControl>
|
||||
<FormLabel className="font-normal">
|
||||
Nixpacks
|
||||
</FormLabel>
|
||||
</FormItem>
|
||||
<FormItem className="flex items-center space-x-3 space-y-0">
|
||||
<FormControl>
|
||||
<RadioGroupItem value="heroku_buildpacks" />
|
||||
</FormControl>
|
||||
<FormLabel className="font-normal">
|
||||
Heroku Buildpacks
|
||||
</FormLabel>
|
||||
</FormItem>
|
||||
<FormItem className="flex items-center space-x-3 space-y-0">
|
||||
<FormControl>
|
||||
<RadioGroupItem value="paketo_buildpacks" />
|
||||
</FormControl>
|
||||
<FormLabel className="font-normal">
|
||||
Paketo Buildpacks
|
||||
</FormLabel>
|
||||
</FormItem>
|
||||
</RadioGroup>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
{buildType === "dockerfile" && (
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="dockerfile"
|
||||
render={({ field }) => {
|
||||
return (
|
||||
<FormItem>
|
||||
<FormLabel>Docker File</FormLabel>
|
||||
<FormControl>
|
||||
<Input
|
||||
placeholder={"Path of your docker file"}
|
||||
{...field}
|
||||
value={field.value ?? ""}
|
||||
/>
|
||||
</FormControl>
|
||||
return (
|
||||
<Card className="group relative w-full bg-transparent">
|
||||
<CardHeader>
|
||||
<CardTitle className="flex items-start justify-between">
|
||||
<div className="flex flex-col gap-2">
|
||||
<span className="flex flex-col space-y-0.5">Build Type</span>
|
||||
<p className="flex items-center text-sm font-normal text-muted-foreground">
|
||||
Select the way of building your code
|
||||
</p>
|
||||
</div>
|
||||
<div className="hidden space-y-1 text-sm font-normal md:block">
|
||||
<Cog className="size-6 text-muted-foreground" />
|
||||
</div>
|
||||
</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<Form {...form}>
|
||||
<form
|
||||
onSubmit={form.handleSubmit(onSubmit)}
|
||||
className="grid w-full gap-4 p-2"
|
||||
>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="buildType"
|
||||
defaultValue={form.control._defaultValues.buildType}
|
||||
render={({ field }) => {
|
||||
return (
|
||||
<FormItem className="space-y-3">
|
||||
<FormLabel>Build Type</FormLabel>
|
||||
<FormControl>
|
||||
<RadioGroup
|
||||
onValueChange={field.onChange}
|
||||
value={field.value}
|
||||
className="flex flex-col space-y-1"
|
||||
>
|
||||
<FormItem className="flex items-center space-x-3 space-y-0">
|
||||
<FormControl>
|
||||
<RadioGroupItem value="dockerfile" />
|
||||
</FormControl>
|
||||
<FormLabel className="font-normal">
|
||||
Dockerfile
|
||||
</FormLabel>
|
||||
</FormItem>
|
||||
<FormItem className="flex items-center space-x-3 space-y-0">
|
||||
<FormControl>
|
||||
<RadioGroupItem value="nixpacks" />
|
||||
</FormControl>
|
||||
<FormLabel className="font-normal">
|
||||
Nixpacks
|
||||
</FormLabel>
|
||||
</FormItem>
|
||||
<FormItem className="flex items-center space-x-3 space-y-0">
|
||||
<FormControl>
|
||||
<RadioGroupItem value="heroku_buildpacks" />
|
||||
</FormControl>
|
||||
<FormLabel className="font-normal">
|
||||
Heroku Buildpacks
|
||||
</FormLabel>
|
||||
</FormItem>
|
||||
<FormItem className="flex items-center space-x-3 space-y-0">
|
||||
<FormControl>
|
||||
<RadioGroupItem value="paketo_buildpacks" />
|
||||
</FormControl>
|
||||
<FormLabel className="font-normal">
|
||||
Paketo Buildpacks
|
||||
</FormLabel>
|
||||
</FormItem>
|
||||
</RadioGroup>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
{buildType === "dockerfile" && (
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="dockerfile"
|
||||
render={({ field }) => {
|
||||
return (
|
||||
<FormItem>
|
||||
<FormLabel>Docker File</FormLabel>
|
||||
<FormControl>
|
||||
<Input
|
||||
placeholder={"Path of your docker file"}
|
||||
{...field}
|
||||
value={field.value ?? ""}
|
||||
/>
|
||||
</FormControl>
|
||||
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
<div className="flex w-full justify-end">
|
||||
<Button isLoading={isLoading} type="submit">
|
||||
Save
|
||||
</Button>
|
||||
</div>
|
||||
</form>
|
||||
</Form>
|
||||
</CardContent>
|
||||
</Card>
|
||||
);
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
<div className="flex w-full justify-end">
|
||||
<Button isLoading={isLoading} type="submit">
|
||||
Save
|
||||
</Button>
|
||||
</div>
|
||||
</form>
|
||||
</Form>
|
||||
</CardContent>
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import React from "react";
|
||||
import {
|
||||
AlertDialog,
|
||||
AlertDialogAction,
|
||||
@@ -12,6 +11,7 @@ import {
|
||||
} from "@/components/ui/alert-dialog";
|
||||
import { api } from "@/utils/api";
|
||||
import { RefreshCcw } from "lucide-react";
|
||||
import React from "react";
|
||||
import { toast } from "sonner";
|
||||
|
||||
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 {
|
||||
Card,
|
||||
@@ -10,10 +12,8 @@ import { api } from "@/utils/api";
|
||||
import { RocketIcon } from "lucide-react";
|
||||
import React, { useEffect, useState } from "react";
|
||||
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 { ShowDeployment } from "./show-deployment";
|
||||
|
||||
interface Props {
|
||||
applicationId: string;
|
||||
@@ -86,6 +86,11 @@ export const ShowDeployments = ({ applicationId }: Props) => {
|
||||
<span className="text-sm text-muted-foreground">
|
||||
{deployment.title}
|
||||
</span>
|
||||
{deployment.description && (
|
||||
<span className="text-sm text-muted-foreground">
|
||||
{deployment.description}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
<div className="flex flex-col items-end gap-2">
|
||||
<div className="text-sm capitalize text-muted-foreground">
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { AlertBlock } from "@/components/shared/alert-block";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import {
|
||||
Dialog,
|
||||
@@ -27,7 +28,6 @@ import {
|
||||
} from "@/components/ui/select";
|
||||
import { Switch } from "@/components/ui/switch";
|
||||
import { api } from "@/utils/api";
|
||||
import { AlertBlock } from "@/components/shared/alert-block";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { PlusIcon } from "lucide-react";
|
||||
import { useEffect } from "react";
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import React from "react";
|
||||
import {
|
||||
AlertDialog,
|
||||
AlertDialogAction,
|
||||
@@ -13,6 +12,7 @@ import {
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { api } from "@/utils/api";
|
||||
import { TrashIcon } from "lucide-react";
|
||||
import React from "react";
|
||||
import { toast } from "sonner";
|
||||
|
||||
interface Props {
|
||||
|
||||
79
components/dashboard/application/domains/generate-domain.tsx
Normal file
79
components/dashboard/application/domains/generate-domain.tsx
Normal file
@@ -0,0 +1,79 @@
|
||||
import { Button } from "@/components/ui/button";
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogDescription,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
} from "@/components/ui/dialog";
|
||||
import { api } from "@/utils/api";
|
||||
import { RefreshCcw } from "lucide-react";
|
||||
import Link from "next/link";
|
||||
import { GenerateTraefikMe } from "./generate-traefikme";
|
||||
import { GenerateWildCard } from "./generate-wildcard";
|
||||
|
||||
interface Props {
|
||||
applicationId: string;
|
||||
}
|
||||
|
||||
export const GenerateDomain = ({ applicationId }: Props) => {
|
||||
return (
|
||||
<Dialog>
|
||||
<DialogTrigger className="" asChild>
|
||||
<Button variant="secondary">
|
||||
Generate Domain
|
||||
<RefreshCcw className="size-4 text-muted-foreground " />
|
||||
</Button>
|
||||
</DialogTrigger>
|
||||
<DialogContent className="max-h-screen overflow-y-auto sm:max-w-2xl">
|
||||
<DialogHeader>
|
||||
<DialogTitle>Generate Domain</DialogTitle>
|
||||
<DialogDescription>
|
||||
Generate Domains for your applications
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
|
||||
<div className="flex flex-col gap-4 w-full">
|
||||
<ul className="flex flex-col gap-4">
|
||||
<li className="flex flex-row items-center gap-4">
|
||||
<div className="flex flex-col gap-2">
|
||||
<div className="text-base font-bold">
|
||||
1. Generate TraefikMe Domain
|
||||
</div>
|
||||
<div className="text-sm text-muted-foreground">
|
||||
This option generates a free domain provided by{" "}
|
||||
<Link
|
||||
href="https://traefik.me"
|
||||
className="text-primary"
|
||||
target="_blank"
|
||||
>
|
||||
TraefikMe
|
||||
</Link>
|
||||
. We recommend using this for quick domain testing or if you
|
||||
don't have a domain yet.
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
{/* <li className="flex flex-row items-center gap-4">
|
||||
<div className="flex flex-col gap-2">
|
||||
<div className="text-base font-bold">
|
||||
2. Use Wildcard Domain
|
||||
</div>
|
||||
<div className="text-sm text-muted-foreground">
|
||||
To use this option, you need to set up an 'A' record in your
|
||||
domain provider. For example, create a record for
|
||||
*.yourdomain.com.
|
||||
</div>
|
||||
</div>
|
||||
</li> */}
|
||||
</ul>
|
||||
<div className="flex flex-row gap-4 w-full">
|
||||
<GenerateTraefikMe applicationId={applicationId} />
|
||||
{/* <GenerateWildCard applicationId={applicationId} /> */}
|
||||
</div>
|
||||
</div>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,69 @@
|
||||
import {
|
||||
AlertDialog,
|
||||
AlertDialogAction,
|
||||
AlertDialogCancel,
|
||||
AlertDialogContent,
|
||||
AlertDialogDescription,
|
||||
AlertDialogFooter,
|
||||
AlertDialogHeader,
|
||||
AlertDialogTitle,
|
||||
AlertDialogTrigger,
|
||||
} from "@/components/ui/alert-dialog";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { api } from "@/utils/api";
|
||||
import { RefreshCcw } from "lucide-react";
|
||||
import React from "react";
|
||||
import { toast } from "sonner";
|
||||
|
||||
interface Props {
|
||||
applicationId: string;
|
||||
}
|
||||
export const GenerateTraefikMe = ({ applicationId }: Props) => {
|
||||
const { mutateAsync, isLoading } = api.domain.generateDomain.useMutation();
|
||||
const utils = api.useUtils();
|
||||
return (
|
||||
<AlertDialog>
|
||||
<AlertDialogTrigger asChild>
|
||||
<Button variant="secondary" isLoading={isLoading}>
|
||||
Generate Domain
|
||||
<RefreshCcw className="size-4 text-muted-foreground " />
|
||||
</Button>
|
||||
</AlertDialogTrigger>
|
||||
<AlertDialogContent>
|
||||
<AlertDialogHeader>
|
||||
<AlertDialogTitle>
|
||||
Are you sure to generate a new domain?
|
||||
</AlertDialogTitle>
|
||||
<AlertDialogDescription>
|
||||
This will generate a new domain and will be used to access to the
|
||||
application
|
||||
</AlertDialogDescription>
|
||||
</AlertDialogHeader>
|
||||
<AlertDialogFooter>
|
||||
<AlertDialogCancel>Cancel</AlertDialogCancel>
|
||||
<AlertDialogAction
|
||||
onClick={async () => {
|
||||
await mutateAsync({
|
||||
applicationId,
|
||||
})
|
||||
.then((data) => {
|
||||
utils.domain.byApplicationId.invalidate({
|
||||
applicationId: applicationId,
|
||||
});
|
||||
utils.application.readTraefikConfig.invalidate({
|
||||
applicationId: applicationId,
|
||||
});
|
||||
toast.success("Generated Domain succesfully");
|
||||
})
|
||||
.catch(() => {
|
||||
toast.error("Error to generate Domain");
|
||||
});
|
||||
}}
|
||||
>
|
||||
Confirm
|
||||
</AlertDialogAction>
|
||||
</AlertDialogFooter>
|
||||
</AlertDialogContent>
|
||||
</AlertDialog>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,69 @@
|
||||
import {
|
||||
AlertDialog,
|
||||
AlertDialogAction,
|
||||
AlertDialogCancel,
|
||||
AlertDialogContent,
|
||||
AlertDialogDescription,
|
||||
AlertDialogFooter,
|
||||
AlertDialogHeader,
|
||||
AlertDialogTitle,
|
||||
AlertDialogTrigger,
|
||||
} from "@/components/ui/alert-dialog";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { api } from "@/utils/api";
|
||||
import { SquareAsterisk } from "lucide-react";
|
||||
import React from "react";
|
||||
import { toast } from "sonner";
|
||||
|
||||
interface Props {
|
||||
applicationId: string;
|
||||
}
|
||||
export const GenerateWildCard = ({ applicationId }: Props) => {
|
||||
const { mutateAsync, isLoading } = api.domain.generateWildcard.useMutation();
|
||||
const utils = api.useUtils();
|
||||
return (
|
||||
<AlertDialog>
|
||||
<AlertDialogTrigger asChild>
|
||||
<Button variant="secondary" isLoading={isLoading}>
|
||||
Generate Wildcard Domain
|
||||
<SquareAsterisk className="size-4 text-muted-foreground " />
|
||||
</Button>
|
||||
</AlertDialogTrigger>
|
||||
<AlertDialogContent>
|
||||
<AlertDialogHeader>
|
||||
<AlertDialogTitle>
|
||||
Are you sure to generate a new wildcard domain?
|
||||
</AlertDialogTitle>
|
||||
<AlertDialogDescription>
|
||||
This will generate a new domain and will be used to access to the
|
||||
application
|
||||
</AlertDialogDescription>
|
||||
</AlertDialogHeader>
|
||||
<AlertDialogFooter>
|
||||
<AlertDialogCancel>Cancel</AlertDialogCancel>
|
||||
<AlertDialogAction
|
||||
onClick={async () => {
|
||||
await mutateAsync({
|
||||
applicationId,
|
||||
})
|
||||
.then((data) => {
|
||||
utils.domain.byApplicationId.invalidate({
|
||||
applicationId: applicationId,
|
||||
});
|
||||
utils.application.readTraefikConfig.invalidate({
|
||||
applicationId: applicationId,
|
||||
});
|
||||
toast.success("Generated Domain succesfully");
|
||||
})
|
||||
.catch((e) => {
|
||||
toast.error(`Error to generate Domain: ${e.message}`);
|
||||
});
|
||||
}}
|
||||
>
|
||||
Confirm
|
||||
</AlertDialogAction>
|
||||
</AlertDialogFooter>
|
||||
</AlertDialogContent>
|
||||
</AlertDialog>
|
||||
);
|
||||
};
|
||||
@@ -1,4 +1,4 @@
|
||||
import React from "react";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
@@ -6,13 +6,14 @@ import {
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} from "@/components/ui/card";
|
||||
import { ExternalLink, GlobeIcon } from "lucide-react";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { api } from "@/utils/api";
|
||||
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 React from "react";
|
||||
import { AddDomain } from "./add-domain";
|
||||
import { DeleteDomain } from "./delete-domain";
|
||||
import { GenerateDomain } from "./generate-domain";
|
||||
import { UpdateDomain } from "./update-domain";
|
||||
|
||||
interface Props {
|
||||
@@ -31,7 +32,7 @@ export const ShowDomains = ({ applicationId }: Props) => {
|
||||
return (
|
||||
<div className="flex w-full flex-col gap-5 ">
|
||||
<Card className="bg-background">
|
||||
<CardHeader className="flex flex-row items-center justify-between">
|
||||
<CardHeader className="flex flex-row items-center flex-wrap gap-4 justify-between">
|
||||
<div className="flex flex-col gap-1">
|
||||
<CardTitle className="text-xl">Domains</CardTitle>
|
||||
<CardDescription>
|
||||
@@ -39,11 +40,16 @@ export const ShowDomains = ({ applicationId }: Props) => {
|
||||
</CardDescription>
|
||||
</div>
|
||||
|
||||
{data && data?.length > 0 && (
|
||||
<AddDomain applicationId={applicationId}>
|
||||
<GlobeIcon className="size-4" /> Add Domain
|
||||
</AddDomain>
|
||||
)}
|
||||
<div className="flex flex-row gap-4 flex-wrap">
|
||||
{data && data?.length > 0 && (
|
||||
<AddDomain applicationId={applicationId}>
|
||||
<GlobeIcon className="size-4" /> Add Domain
|
||||
</AddDomain>
|
||||
)}
|
||||
{data && data?.length > 0 && (
|
||||
<GenerateDomain applicationId={applicationId} />
|
||||
)}
|
||||
</div>
|
||||
</CardHeader>
|
||||
<CardContent className="flex w-full flex-row gap-4">
|
||||
{data?.length === 0 ? (
|
||||
@@ -53,9 +59,13 @@ export const ShowDomains = ({ applicationId }: Props) => {
|
||||
To access to the application is required to set at least 1
|
||||
domain
|
||||
</span>
|
||||
<AddDomain applicationId={applicationId}>
|
||||
<GlobeIcon className="size-4" /> Add Domain
|
||||
</AddDomain>
|
||||
<div className="flex flex-row gap-4 flex-wrap">
|
||||
<AddDomain applicationId={applicationId}>
|
||||
<GlobeIcon className="size-4" /> Add Domain
|
||||
</AddDomain>
|
||||
|
||||
<GenerateDomain applicationId={applicationId} />
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<div className="flex w-full flex-col gap-4">
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { AlertBlock } from "@/components/shared/alert-block";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import {
|
||||
Dialog,
|
||||
@@ -27,7 +28,6 @@ import {
|
||||
} from "@/components/ui/select";
|
||||
import { Switch } from "@/components/ui/switch";
|
||||
import { api } from "@/utils/api";
|
||||
import { AlertBlock } from "@/components/shared/alert-block";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { PenBoxIcon } from "lucide-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 {
|
||||
Card,
|
||||
CardContent,
|
||||
@@ -6,10 +7,6 @@ import {
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} 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 {
|
||||
Form,
|
||||
FormControl,
|
||||
@@ -17,11 +14,14 @@ import {
|
||||
FormItem,
|
||||
FormMessage,
|
||||
} from "@/components/ui/form";
|
||||
import { api } from "@/utils/api";
|
||||
import { toast } from "sonner";
|
||||
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 React, { useEffect, useState } from "react";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { toast } from "sonner";
|
||||
import { z } from "zod";
|
||||
|
||||
const addEnvironmentSchema = z.object({
|
||||
environment: z.string(),
|
||||
|
||||
@@ -11,7 +11,6 @@ import {
|
||||
} from "@/components/ui/alert-dialog";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { api } from "@/utils/api";
|
||||
import { useEffect, useState } from "react";
|
||||
import { toast } from "sonner";
|
||||
|
||||
interface Props {
|
||||
@@ -26,8 +25,6 @@ export const DeployApplication = ({ applicationId }: Props) => {
|
||||
{ enabled: !!applicationId },
|
||||
);
|
||||
|
||||
const { mutateAsync: markRunning } =
|
||||
api.application.markRunning.useMutation();
|
||||
const { mutateAsync: deploy } = api.application.deploy.useMutation();
|
||||
|
||||
return (
|
||||
@@ -48,24 +45,16 @@ export const DeployApplication = ({ applicationId }: Props) => {
|
||||
<AlertDialogCancel>Cancel</AlertDialogCancel>
|
||||
<AlertDialogAction
|
||||
onClick={async () => {
|
||||
await markRunning({
|
||||
toast.success("Deploying Application....");
|
||||
|
||||
await refetch();
|
||||
await deploy({
|
||||
applicationId,
|
||||
})
|
||||
.then(async () => {
|
||||
toast.success("Deploying Application....");
|
||||
}).catch(() => {
|
||||
toast.error("Error to deploy Application");
|
||||
});
|
||||
|
||||
await refetch();
|
||||
await deploy({
|
||||
applicationId,
|
||||
}).catch(() => {
|
||||
toast.error("Error to deploy Application");
|
||||
});
|
||||
|
||||
await refetch();
|
||||
})
|
||||
.catch((e) => {
|
||||
toast.error(e.message || "Error to deploy Application");
|
||||
});
|
||||
await refetch();
|
||||
}}
|
||||
>
|
||||
Confirm
|
||||
|
||||
@@ -1,8 +1,4 @@
|
||||
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 {
|
||||
Form,
|
||||
FormControl,
|
||||
@@ -11,9 +7,13 @@ import {
|
||||
FormLabel,
|
||||
FormMessage,
|
||||
} from "@/components/ui/form";
|
||||
import { useEffect } from "react";
|
||||
import { Input } from "@/components/ui/input";
|
||||
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 { z } from "zod";
|
||||
|
||||
const DockerProviderSchema = z.object({
|
||||
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 { Toggle } from "@/components/ui/toggle";
|
||||
import { api } from "@/utils/api";
|
||||
import { CheckCircle2, Terminal } from "lucide-react";
|
||||
import React from "react";
|
||||
import { toast } from "sonner";
|
||||
import { DockerTerminalModal } from "../../settings/web-server/docker-terminal-modal";
|
||||
import { RedbuildApplication } from "../rebuild-application";
|
||||
import { StartApplication } from "../start-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 { ResetApplication } from "./reset-application";
|
||||
interface Props {
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import dynamic from "next/dynamic";
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
@@ -6,6 +5,7 @@ import {
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} from "@/components/ui/card";
|
||||
import { Label } from "@/components/ui/label";
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
@@ -16,8 +16,8 @@ import {
|
||||
SelectValue,
|
||||
} from "@/components/ui/select";
|
||||
import { api } from "@/utils/api";
|
||||
import dynamic from "next/dynamic";
|
||||
import { useEffect, useState } from "react";
|
||||
import { Label } from "@/components/ui/label";
|
||||
export const DockerLogs = dynamic(
|
||||
() =>
|
||||
import("@/components/dashboard/docker/logs/docker-logs-id").then(
|
||||
|
||||
@@ -25,8 +25,7 @@ export const RedbuildApplication = ({ applicationId }: Props) => {
|
||||
},
|
||||
{ enabled: !!applicationId },
|
||||
);
|
||||
const { mutateAsync: markRunning } =
|
||||
api.application.markRunning.useMutation();
|
||||
|
||||
const { mutateAsync } = api.application.redeploy.useMutation();
|
||||
const utils = api.useUtils();
|
||||
return (
|
||||
@@ -54,22 +53,14 @@ export const RedbuildApplication = ({ applicationId }: Props) => {
|
||||
<AlertDialogCancel>Cancel</AlertDialogCancel>
|
||||
<AlertDialogAction
|
||||
onClick={async () => {
|
||||
await markRunning({
|
||||
toast.success("Redeploying Application....");
|
||||
await mutateAsync({
|
||||
applicationId,
|
||||
})
|
||||
.then(async () => {
|
||||
await mutateAsync({
|
||||
await utils.application.one.invalidate({
|
||||
applicationId,
|
||||
})
|
||||
.then(async () => {
|
||||
await utils.application.one.invalidate({
|
||||
applicationId,
|
||||
});
|
||||
toast.success("Application rebuild succesfully");
|
||||
})
|
||||
.catch(() => {
|
||||
toast.error("Error to rebuild the application");
|
||||
});
|
||||
});
|
||||
})
|
||||
.catch(() => {
|
||||
toast.error("Error to rebuild the application");
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { AlertBlock } from "@/components/shared/alert-block";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
@@ -7,7 +9,6 @@ import {
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
} from "@/components/ui/dialog";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import {
|
||||
Form,
|
||||
FormControl,
|
||||
@@ -16,16 +17,15 @@ import {
|
||||
FormLabel,
|
||||
FormMessage,
|
||||
} 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 { AlertTriangle, SquarePen } from "lucide-react";
|
||||
import { Textarea } from "@/components/ui/textarea";
|
||||
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({
|
||||
name: z.string().min(1, {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React from "react";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
@@ -6,8 +6,6 @@ import {
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} from "@/components/ui/card";
|
||||
import { api } from "@/utils/api";
|
||||
import { z } from "zod";
|
||||
import {
|
||||
Form,
|
||||
FormControl,
|
||||
@@ -17,12 +15,14 @@ import {
|
||||
FormLabel,
|
||||
FormMessage,
|
||||
} 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 { 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 {
|
||||
composeId: string;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React from "react";
|
||||
import { AlertBlock } from "@/components/shared/alert-block";
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
@@ -8,10 +8,10 @@ import {
|
||||
} from "@/components/ui/card";
|
||||
import { api } from "@/utils/api";
|
||||
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 { DeleteVolume } from "../../application/advanced/volumes/delete-volume";
|
||||
import { UpdateVolume } from "../../application/advanced/volumes/update-volume";
|
||||
import { AlertBlock } from "@/components/shared/alert-block";
|
||||
interface Props {
|
||||
composeId: string;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import React from "react";
|
||||
import {
|
||||
AlertDialog,
|
||||
AlertDialogAction,
|
||||
@@ -12,6 +11,7 @@ import {
|
||||
} from "@/components/ui/alert-dialog";
|
||||
import { api } from "@/utils/api";
|
||||
import { RefreshCcw } from "lucide-react";
|
||||
import React from "react";
|
||||
import { toast } from "sonner";
|
||||
|
||||
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 {
|
||||
Card,
|
||||
@@ -9,14 +11,9 @@ import {
|
||||
import { api } from "@/utils/api";
|
||||
import { RocketIcon } from "lucide-react";
|
||||
import React, { useEffect, useState } from "react";
|
||||
// import { CancelQueues } from "./cancel-queues";
|
||||
// import { ShowDeployment } from "./show-deployment-compose";
|
||||
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 { RefreshToken } from "./refresh-token";//
|
||||
import { RefreshTokenCompose } from "./refresh-token-compose";
|
||||
import { ShowDeploymentCompose } from "./show-deployment-compose";
|
||||
|
||||
interface Props {
|
||||
composeId: string;
|
||||
@@ -90,6 +87,11 @@ export const ShowDeploymentsCompose = ({ composeId }: Props) => {
|
||||
<span className="text-sm text-muted-foreground">
|
||||
{deployment.title}
|
||||
</span>
|
||||
{deployment.description && (
|
||||
<span className="text-sm text-muted-foreground">
|
||||
{deployment.description}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
<div className="flex flex-col items-end gap-2">
|
||||
<div className="text-sm capitalize text-muted-foreground">
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { CodeEditor } from "@/components/shared/code-editor";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
@@ -6,10 +7,6 @@ import {
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} 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 {
|
||||
Form,
|
||||
FormControl,
|
||||
@@ -17,11 +14,14 @@ import {
|
||||
FormItem,
|
||||
FormMessage,
|
||||
} 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 { api } from "@/utils/api";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
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({
|
||||
environment: z.string(),
|
||||
|
||||
@@ -1,12 +1,4 @@
|
||||
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 {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
@@ -16,7 +8,15 @@ import {
|
||||
DropdownMenuSeparator,
|
||||
DropdownMenuTrigger,
|
||||
} 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 { 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 {
|
||||
composeId: string;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { api } from "@/utils/api";
|
||||
import { useEffect } from "react";
|
||||
import { CodeEditor } from "@/components/shared/code-editor";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import {
|
||||
Form,
|
||||
FormControl,
|
||||
@@ -7,14 +7,14 @@ import {
|
||||
FormItem,
|
||||
FormMessage,
|
||||
} from "@/components/ui/form";
|
||||
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 { z } from "zod";
|
||||
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 { CodeEditor } from "@/components/shared/code-editor";
|
||||
|
||||
interface Props {
|
||||
composeId: string;
|
||||
|
||||
@@ -25,7 +25,6 @@ export const DeployCompose = ({ composeId }: Props) => {
|
||||
{ enabled: !!composeId },
|
||||
);
|
||||
|
||||
const { mutateAsync: markRunning } = api.compose.update.useMutation();
|
||||
const { mutateAsync: deploy } = api.compose.deploy.useMutation();
|
||||
|
||||
return (
|
||||
@@ -44,25 +43,16 @@ export const DeployCompose = ({ composeId }: Props) => {
|
||||
<AlertDialogCancel>Cancel</AlertDialogCancel>
|
||||
<AlertDialogAction
|
||||
onClick={async () => {
|
||||
await markRunning({
|
||||
toast.success("Deploying Compose....");
|
||||
|
||||
await refetch();
|
||||
await deploy({
|
||||
composeId,
|
||||
composeStatus: "running",
|
||||
})
|
||||
.then(async () => {
|
||||
toast.success("Deploying Compose....");
|
||||
}).catch(() => {
|
||||
toast.error("Error to deploy Compose");
|
||||
});
|
||||
|
||||
await refetch();
|
||||
await deploy({
|
||||
composeId,
|
||||
}).catch(() => {
|
||||
toast.error("Error to deploy Compose");
|
||||
});
|
||||
|
||||
await refetch();
|
||||
})
|
||||
.catch((e) => {
|
||||
toast.error(e.message || "Error to deploy Compose");
|
||||
});
|
||||
await refetch();
|
||||
}}
|
||||
>
|
||||
Confirm
|
||||
|
||||
@@ -4,9 +4,9 @@ import { api } from "@/utils/api";
|
||||
import { GitBranch, LockIcon } from "lucide-react";
|
||||
import Link from "next/link";
|
||||
import { useState } from "react";
|
||||
import { SaveGithubProviderCompose } from "./save-github-provider-compose";
|
||||
import { ComposeFileEditor } from "../compose-file-editor";
|
||||
import { SaveGitProviderCompose } from "./save-git-provider-compose";
|
||||
import { SaveGithubProviderCompose } from "./save-github-provider-compose";
|
||||
|
||||
type TabState = "github" | "git" | "raw";
|
||||
interface Props {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { AlertBlock } from "@/components/shared/alert-block";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import {
|
||||
Dialog,
|
||||
@@ -7,12 +8,11 @@ import {
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
} from "@/components/ui/dialog";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { api } from "@/utils/api";
|
||||
import { AlertBlock } from "@/components/shared/alert-block";
|
||||
import { Dices } from "lucide-react";
|
||||
import { useState } from "react";
|
||||
import { toast } from "sonner";
|
||||
import { Input } from "@/components/ui/input";
|
||||
|
||||
interface Props {
|
||||
composeId: string;
|
||||
|
||||
@@ -25,7 +25,6 @@ export const RedbuildCompose = ({ composeId }: Props) => {
|
||||
},
|
||||
{ enabled: !!composeId },
|
||||
);
|
||||
const { mutateAsync: markRunning } = api.compose.update.useMutation();
|
||||
const { mutateAsync } = api.compose.redeploy.useMutation();
|
||||
const utils = api.useUtils();
|
||||
return (
|
||||
@@ -53,23 +52,14 @@ export const RedbuildCompose = ({ composeId }: Props) => {
|
||||
<AlertDialogCancel>Cancel</AlertDialogCancel>
|
||||
<AlertDialogAction
|
||||
onClick={async () => {
|
||||
await markRunning({
|
||||
toast.success("Redeploying Compose....");
|
||||
await mutateAsync({
|
||||
composeId,
|
||||
composeStatus: "running",
|
||||
})
|
||||
.then(async () => {
|
||||
await mutateAsync({
|
||||
await utils.compose.one.invalidate({
|
||||
composeId,
|
||||
})
|
||||
.then(async () => {
|
||||
await utils.compose.one.invalidate({
|
||||
composeId,
|
||||
});
|
||||
toast.success("Compose rebuild succesfully");
|
||||
})
|
||||
.catch(() => {
|
||||
toast.error("Error to rebuild the compose");
|
||||
});
|
||||
});
|
||||
})
|
||||
.catch(() => {
|
||||
toast.error("Error to rebuild the compose");
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
@@ -5,11 +6,10 @@ import {
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} 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 React from "react";
|
||||
import { ComposeActions } from "./actions";
|
||||
import { ShowProviderFormCompose } from "./generic/show";
|
||||
interface Props {
|
||||
composeId: string;
|
||||
}
|
||||
|
||||
@@ -25,7 +25,6 @@ export const StopCompose = ({ composeId }: Props) => {
|
||||
},
|
||||
{ enabled: !!composeId },
|
||||
);
|
||||
const { mutateAsync: markRunning } = api.compose.update.useMutation();
|
||||
const { mutateAsync, isLoading } = api.compose.stop.useMutation();
|
||||
const utils = api.useUtils();
|
||||
return (
|
||||
@@ -47,26 +46,17 @@ export const StopCompose = ({ composeId }: Props) => {
|
||||
<AlertDialogCancel>Cancel</AlertDialogCancel>
|
||||
<AlertDialogAction
|
||||
onClick={async () => {
|
||||
await markRunning({
|
||||
await mutateAsync({
|
||||
composeId,
|
||||
composeStatus: "running",
|
||||
})
|
||||
.then(async () => {
|
||||
await mutateAsync({
|
||||
await utils.compose.one.invalidate({
|
||||
composeId,
|
||||
})
|
||||
.then(async () => {
|
||||
await utils.compose.one.invalidate({
|
||||
composeId,
|
||||
});
|
||||
toast.success("Compose rebuild succesfully");
|
||||
})
|
||||
.catch(() => {
|
||||
toast.error("Error to rebuild the compose");
|
||||
});
|
||||
});
|
||||
toast.success("Compose stopped succesfully");
|
||||
})
|
||||
.catch(() => {
|
||||
toast.error("Error to rebuild the compose");
|
||||
toast.error("Error to stop the compose");
|
||||
});
|
||||
}}
|
||||
>
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import dynamic from "next/dynamic";
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
@@ -6,6 +5,7 @@ import {
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} from "@/components/ui/card";
|
||||
import { Label } from "@/components/ui/label";
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
@@ -16,8 +16,8 @@ import {
|
||||
SelectValue,
|
||||
} from "@/components/ui/select";
|
||||
import { api } from "@/utils/api";
|
||||
import dynamic from "next/dynamic";
|
||||
import { useEffect, useState } from "react";
|
||||
import { Label } from "@/components/ui/label";
|
||||
export const DockerLogs = dynamic(
|
||||
() =>
|
||||
import("@/components/dashboard/docker/logs/docker-logs-id").then(
|
||||
|
||||
@@ -5,8 +5,7 @@ import {
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} from "@/components/ui/card";
|
||||
import { api } from "@/utils/api";
|
||||
import { useEffect, useState } from "react";
|
||||
import { Label } from "@/components/ui/label";
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
@@ -16,7 +15,8 @@ import {
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} 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";
|
||||
|
||||
interface Props {
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { AlertBlock } from "@/components/shared/alert-block";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
@@ -7,7 +9,6 @@ import {
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
} from "@/components/ui/dialog";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import {
|
||||
Form,
|
||||
FormControl,
|
||||
@@ -16,16 +17,15 @@ import {
|
||||
FormLabel,
|
||||
FormMessage,
|
||||
} 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 { SquarePen } from "lucide-react";
|
||||
import { Textarea } from "@/components/ui/textarea";
|
||||
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({
|
||||
name: z.string().min(1, {
|
||||
|
||||
@@ -1,4 +1,11 @@
|
||||
import { Button } from "@/components/ui/button";
|
||||
import {
|
||||
Command,
|
||||
CommandEmpty,
|
||||
CommandGroup,
|
||||
CommandInput,
|
||||
CommandItem,
|
||||
} from "@/components/ui/command";
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
@@ -11,36 +18,29 @@ import {
|
||||
import {
|
||||
Form,
|
||||
FormControl,
|
||||
FormDescription,
|
||||
FormField,
|
||||
FormItem,
|
||||
FormLabel,
|
||||
FormDescription,
|
||||
FormMessage,
|
||||
} from "@/components/ui/form";
|
||||
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 {
|
||||
Popover,
|
||||
PopoverContent,
|
||||
PopoverTrigger,
|
||||
} from "@/components/ui/popover";
|
||||
import { z } from "zod";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { ScrollArea } from "@/components/ui/scroll-area";
|
||||
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({
|
||||
destinationId: z.string().min(1, "Destination required"),
|
||||
|
||||
@@ -1,4 +1,11 @@
|
||||
import { Button } from "@/components/ui/button";
|
||||
import {
|
||||
Command,
|
||||
CommandEmpty,
|
||||
CommandGroup,
|
||||
CommandInput,
|
||||
CommandItem,
|
||||
} from "@/components/ui/command";
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
@@ -18,28 +25,21 @@ import {
|
||||
FormMessage,
|
||||
} from "@/components/ui/form";
|
||||
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 {
|
||||
Popover,
|
||||
PopoverContent,
|
||||
PopoverTrigger,
|
||||
} from "@/components/ui/popover";
|
||||
import { ScrollArea } from "@/components/ui/scroll-area";
|
||||
import { Switch } from "@/components/ui/switch";
|
||||
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({
|
||||
destinationId: z.string().min(1, "Destination required"),
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Label } from "@/components/ui/label";
|
||||
import React, { useEffect } from "react";
|
||||
import { Terminal } from "@xterm/xterm";
|
||||
import React, { useEffect } from "react";
|
||||
import { FitAddon } from "xterm-addon-fit";
|
||||
import "@xterm/xterm/css/xterm.css";
|
||||
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
import dynamic from "next/dynamic";
|
||||
import React from "react";
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
@@ -9,6 +7,8 @@ import {
|
||||
DialogTrigger,
|
||||
} from "@/components/ui/dialog";
|
||||
import { DropdownMenuItem } from "@/components/ui/dropdown-menu";
|
||||
import dynamic from "next/dynamic";
|
||||
import type React from "react";
|
||||
export const DockerLogsId = dynamic(
|
||||
() =>
|
||||
import("@/components/dashboard/docker/logs/docker-logs-id").then(
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import * as React from "react";
|
||||
import type { ColumnDef } from "@tanstack/react-table";
|
||||
import { ArrowUpDown, MoreHorizontal } from "lucide-react";
|
||||
import * as React from "react";
|
||||
|
||||
import { Button } from "@/components/ui/button";
|
||||
import {
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import * as React from "react";
|
||||
import {
|
||||
type ColumnFiltersState,
|
||||
type SortingState,
|
||||
@@ -11,6 +10,7 @@ import {
|
||||
useReactTable,
|
||||
} from "@tanstack/react-table";
|
||||
import { ChevronDown } from "lucide-react";
|
||||
import * as React from "react";
|
||||
|
||||
import { Button } from "@/components/ui/button";
|
||||
import {
|
||||
@@ -28,7 +28,7 @@ import {
|
||||
TableHeader,
|
||||
TableRow,
|
||||
} from "@/components/ui/table";
|
||||
import { api, type RouterOutputs } from "@/utils/api";
|
||||
import { type RouterOutputs, api } from "@/utils/api";
|
||||
import { columns } from "./colums";
|
||||
export type Container = NonNullable<
|
||||
RouterOutputs["docker"]["getContainers"]
|
||||
@@ -161,10 +161,6 @@ export const ShowContainers = () => {
|
||||
</Table>
|
||||
</div>
|
||||
<div className="flex items-center justify-end space-x-2 py-4">
|
||||
<div className="flex-1 text-sm text-muted-foreground">
|
||||
{table.getFilteredSelectedRowModel().rows.length} of{" "}
|
||||
{table.getFilteredRowModel().rows.length} row(s) selected.
|
||||
</div>
|
||||
<div className="space-x-2 flex flex-wrap">
|
||||
<Button
|
||||
variant="outline"
|
||||
|
||||
@@ -6,8 +6,8 @@ import {
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
} from "@/components/ui/dialog";
|
||||
import dynamic from "next/dynamic";
|
||||
import { DropdownMenuItem } from "@/components/ui/dropdown-menu";
|
||||
import dynamic from "next/dynamic";
|
||||
|
||||
const Terminal = dynamic(
|
||||
() => import("./docker-terminal").then((e) => e.DockerTerminal),
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import React, { useEffect, useRef } from "react";
|
||||
import { Terminal } from "@xterm/xterm";
|
||||
import React, { useEffect, useRef } from "react";
|
||||
import { FitAddon } from "xterm-addon-fit";
|
||||
import "@xterm/xterm/css/xterm.css";
|
||||
import { AttachAddon } from "@xterm/addon-attach";
|
||||
import { Tabs, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
||||
import { AttachAddon } from "@xterm/addon-attach";
|
||||
|
||||
interface Props {
|
||||
id: string;
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import { Button } from "@/components/ui/button";
|
||||
|
||||
import { AlertBlock } from "@/components/shared/alert-block";
|
||||
import { CodeEditor } from "@/components/shared/code-editor";
|
||||
import {
|
||||
Form,
|
||||
FormControl,
|
||||
@@ -10,14 +12,12 @@ import {
|
||||
FormMessage,
|
||||
} from "@/components/ui/form";
|
||||
import { api } from "@/utils/api";
|
||||
import { AlertBlock } from "@/components/shared/alert-block";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { useEffect, useState } from "react";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { toast } from "sonner";
|
||||
import { z } from "zod";
|
||||
import { validateAndFormatYAML } from "../application/advanced/traefik/update-traefik-config";
|
||||
import { CodeEditor } from "@/components/shared/code-editor";
|
||||
|
||||
const UpdateServerMiddlewareConfigSchema = z.object({
|
||||
traefikConfig: z.string(),
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import React from "react";
|
||||
|
||||
import { api } from "@/utils/api";
|
||||
import { Workflow, Folder, FileIcon } from "lucide-react";
|
||||
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 { 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 { api } from "@/utils/api";
|
||||
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 { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
||||
import {
|
||||
Form,
|
||||
FormControl,
|
||||
@@ -15,8 +8,15 @@ import {
|
||||
FormLabel,
|
||||
FormMessage,
|
||||
} 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 { toast } from "sonner";
|
||||
import { z } from "zod";
|
||||
import { ShowVolumes } from "../volumes/show-volumes";
|
||||
import { ShowMariadbResources } from "./show-mariadb-resources";
|
||||
|
||||
const addDockerImage = z.object({
|
||||
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 {
|
||||
Card,
|
||||
@@ -21,7 +22,6 @@ import React, { useEffect } from "react";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { toast } from "sonner";
|
||||
import { z } from "zod";
|
||||
import { AlertBlock } from "@/components/shared/alert-block";
|
||||
|
||||
const addResourcesMariadb = z.object({
|
||||
memoryReservation: z.number().nullable().optional(),
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React from "react";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
@@ -6,20 +6,20 @@ import {
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} 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 {
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
TooltipProvider,
|
||||
TooltipTrigger,
|
||||
} 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 {
|
||||
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 {
|
||||
Card,
|
||||
CardContent,
|
||||
@@ -6,10 +7,6 @@ import {
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} 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 {
|
||||
Form,
|
||||
FormControl,
|
||||
@@ -18,8 +15,11 @@ import {
|
||||
FormMessage,
|
||||
} from "@/components/ui/form";
|
||||
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 { CodeEditor } from "@/components/shared/code-editor";
|
||||
import { z } from "zod";
|
||||
|
||||
const addEnvironmentSchema = z.object({
|
||||
environment: z.string(),
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { ToggleVisibilityInput } from "@/components/shared/toggle-visibility-input";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import {
|
||||
Card,
|
||||
@@ -22,7 +23,6 @@ import React, { useEffect, useState } from "react";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { toast } from "sonner";
|
||||
import { z } from "zod";
|
||||
import { ToggleVisibilityInput } from "@/components/shared/toggle-visibility-input";
|
||||
|
||||
const DockerProviderSchema = z.object({
|
||||
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 { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
||||
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 React from "react";
|
||||
import { DockerTerminalModal } from "../../settings/web-server/docker-terminal-modal";
|
||||
import { StartMariadb } from "../start-mariadb";
|
||||
import { DeployMariadb } from "./deploy-mariadb";
|
||||
import { ResetMariadb } from "./reset-mariadb";
|
||||
import { StopMariadb } from "./stop-mariadb";
|
||||
|
||||
interface Props {
|
||||
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 { Input } from "@/components/ui/input";
|
||||
import { Label } from "@/components/ui/label";
|
||||
import { api } from "@/utils/api";
|
||||
import { ToggleVisibilityInput } from "@/components/shared/toggle-visibility-input";
|
||||
import React from "react";
|
||||
|
||||
interface Props {
|
||||
mariadbId: string;
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import {
|
||||
AlertDialog,
|
||||
AlertDialogAction,
|
||||
AlertDialogCancel,
|
||||
AlertDialogContent,
|
||||
AlertDialogDescription,
|
||||
AlertDialogFooter,
|
||||
AlertDialogHeader,
|
||||
AlertDialogTitle,
|
||||
AlertDialogTrigger,
|
||||
AlertDialog,
|
||||
AlertDialogAction,
|
||||
AlertDialogCancel,
|
||||
AlertDialogContent,
|
||||
AlertDialogDescription,
|
||||
AlertDialogFooter,
|
||||
AlertDialogHeader,
|
||||
AlertDialogTitle,
|
||||
AlertDialogTrigger,
|
||||
} from "@/components/ui/alert-dialog";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { api } from "@/utils/api";
|
||||
@@ -15,51 +15,51 @@ import { Ban } from "lucide-react";
|
||||
import { toast } from "sonner";
|
||||
|
||||
interface Props {
|
||||
mariadbId: string;
|
||||
mariadbId: string;
|
||||
}
|
||||
|
||||
export const StopMariadb = ({ mariadbId }: Props) => {
|
||||
const { mutateAsync, isLoading } = api.mariadb.stop.useMutation();
|
||||
const utils = api.useUtils();
|
||||
return (
|
||||
<AlertDialog>
|
||||
<AlertDialogTrigger asChild>
|
||||
<Button variant="destructive" isLoading={isLoading}>
|
||||
Stop
|
||||
<Ban className="size-4" />
|
||||
</Button>
|
||||
</AlertDialogTrigger>
|
||||
<AlertDialogContent>
|
||||
<AlertDialogHeader>
|
||||
<AlertDialogTitle>
|
||||
Are you absolutely sure to stop the database?
|
||||
</AlertDialogTitle>
|
||||
<AlertDialogDescription>
|
||||
This will stop the database
|
||||
</AlertDialogDescription>
|
||||
</AlertDialogHeader>
|
||||
<AlertDialogFooter>
|
||||
<AlertDialogCancel>Cancel</AlertDialogCancel>
|
||||
<AlertDialogAction
|
||||
onClick={async () => {
|
||||
await mutateAsync({
|
||||
mariadbId,
|
||||
})
|
||||
.then(async () => {
|
||||
await utils.mariadb.one.invalidate({
|
||||
mariadbId,
|
||||
});
|
||||
toast.success("Application stopped succesfully");
|
||||
})
|
||||
.catch(() => {
|
||||
toast.error("Error to stop the Application");
|
||||
});
|
||||
}}
|
||||
>
|
||||
Confirm
|
||||
</AlertDialogAction>
|
||||
</AlertDialogFooter>
|
||||
</AlertDialogContent>
|
||||
</AlertDialog>
|
||||
);
|
||||
const { mutateAsync, isLoading } = api.mariadb.stop.useMutation();
|
||||
const utils = api.useUtils();
|
||||
return (
|
||||
<AlertDialog>
|
||||
<AlertDialogTrigger asChild>
|
||||
<Button variant="destructive" isLoading={isLoading}>
|
||||
Stop
|
||||
<Ban className="size-4" />
|
||||
</Button>
|
||||
</AlertDialogTrigger>
|
||||
<AlertDialogContent>
|
||||
<AlertDialogHeader>
|
||||
<AlertDialogTitle>
|
||||
Are you absolutely sure to stop the database?
|
||||
</AlertDialogTitle>
|
||||
<AlertDialogDescription>
|
||||
This will stop the database
|
||||
</AlertDialogDescription>
|
||||
</AlertDialogHeader>
|
||||
<AlertDialogFooter>
|
||||
<AlertDialogCancel>Cancel</AlertDialogCancel>
|
||||
<AlertDialogAction
|
||||
onClick={async () => {
|
||||
await mutateAsync({
|
||||
mariadbId,
|
||||
})
|
||||
.then(async () => {
|
||||
await utils.mariadb.one.invalidate({
|
||||
mariadbId,
|
||||
});
|
||||
toast.success("Application stopped succesfully");
|
||||
})
|
||||
.catch(() => {
|
||||
toast.error("Error to stop the Application");
|
||||
});
|
||||
}}
|
||||
>
|
||||
Confirm
|
||||
</AlertDialogAction>
|
||||
</AlertDialogFooter>
|
||||
</AlertDialogContent>
|
||||
</AlertDialog>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import {
|
||||
AlertDialog,
|
||||
AlertDialogAction,
|
||||
AlertDialogCancel,
|
||||
AlertDialogContent,
|
||||
AlertDialogDescription,
|
||||
AlertDialogFooter,
|
||||
AlertDialogHeader,
|
||||
AlertDialogTitle,
|
||||
AlertDialogTrigger,
|
||||
AlertDialog,
|
||||
AlertDialogAction,
|
||||
AlertDialogCancel,
|
||||
AlertDialogContent,
|
||||
AlertDialogDescription,
|
||||
AlertDialogFooter,
|
||||
AlertDialogHeader,
|
||||
AlertDialogTitle,
|
||||
AlertDialogTrigger,
|
||||
} from "@/components/ui/alert-dialog";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { api } from "@/utils/api";
|
||||
@@ -15,51 +15,51 @@ import { CheckCircle2 } from "lucide-react";
|
||||
import { toast } from "sonner";
|
||||
|
||||
interface Props {
|
||||
mariadbId: string;
|
||||
mariadbId: string;
|
||||
}
|
||||
|
||||
export const StartMariadb = ({ mariadbId }: Props) => {
|
||||
const { mutateAsync, isLoading } = api.mariadb.start.useMutation();
|
||||
const utils = api.useUtils();
|
||||
return (
|
||||
<AlertDialog>
|
||||
<AlertDialogTrigger asChild>
|
||||
<Button variant="secondary" isLoading={isLoading}>
|
||||
Start
|
||||
<CheckCircle2 className="size-4" />
|
||||
</Button>
|
||||
</AlertDialogTrigger>
|
||||
<AlertDialogContent>
|
||||
<AlertDialogHeader>
|
||||
<AlertDialogTitle>
|
||||
Are you sure to start the database?
|
||||
</AlertDialogTitle>
|
||||
<AlertDialogDescription>
|
||||
This will start the database
|
||||
</AlertDialogDescription>
|
||||
</AlertDialogHeader>
|
||||
<AlertDialogFooter>
|
||||
<AlertDialogCancel>Cancel</AlertDialogCancel>
|
||||
<AlertDialogAction
|
||||
onClick={async () => {
|
||||
await mutateAsync({
|
||||
mariadbId,
|
||||
})
|
||||
.then(async () => {
|
||||
await utils.mariadb.one.invalidate({
|
||||
mariadbId,
|
||||
});
|
||||
toast.success("Database started succesfully");
|
||||
})
|
||||
.catch(() => {
|
||||
toast.error("Error to start the Database");
|
||||
});
|
||||
}}
|
||||
>
|
||||
Confirm
|
||||
</AlertDialogAction>
|
||||
</AlertDialogFooter>
|
||||
</AlertDialogContent>
|
||||
</AlertDialog>
|
||||
);
|
||||
const { mutateAsync, isLoading } = api.mariadb.start.useMutation();
|
||||
const utils = api.useUtils();
|
||||
return (
|
||||
<AlertDialog>
|
||||
<AlertDialogTrigger asChild>
|
||||
<Button variant="secondary" isLoading={isLoading}>
|
||||
Start
|
||||
<CheckCircle2 className="size-4" />
|
||||
</Button>
|
||||
</AlertDialogTrigger>
|
||||
<AlertDialogContent>
|
||||
<AlertDialogHeader>
|
||||
<AlertDialogTitle>
|
||||
Are you sure to start the database?
|
||||
</AlertDialogTitle>
|
||||
<AlertDialogDescription>
|
||||
This will start the database
|
||||
</AlertDialogDescription>
|
||||
</AlertDialogHeader>
|
||||
<AlertDialogFooter>
|
||||
<AlertDialogCancel>Cancel</AlertDialogCancel>
|
||||
<AlertDialogAction
|
||||
onClick={async () => {
|
||||
await mutateAsync({
|
||||
mariadbId,
|
||||
})
|
||||
.then(async () => {
|
||||
await utils.mariadb.one.invalidate({
|
||||
mariadbId,
|
||||
});
|
||||
toast.success("Database started succesfully");
|
||||
})
|
||||
.catch(() => {
|
||||
toast.error("Error to start the Database");
|
||||
});
|
||||
}}
|
||||
>
|
||||
Confirm
|
||||
</AlertDialogAction>
|
||||
</AlertDialogFooter>
|
||||
</AlertDialogContent>
|
||||
</AlertDialog>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { AlertBlock } from "@/components/shared/alert-block";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
@@ -7,7 +9,6 @@ import {
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
} from "@/components/ui/dialog";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import {
|
||||
Form,
|
||||
FormControl,
|
||||
@@ -16,16 +17,15 @@ import {
|
||||
FormLabel,
|
||||
FormMessage,
|
||||
} 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 { AlertTriangle, SquarePen } from "lucide-react";
|
||||
import { Textarea } from "@/components/ui/textarea";
|
||||
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({
|
||||
name: z.string().min(1, {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React from "react";
|
||||
import { AlertBlock } from "@/components/shared/alert-block";
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
@@ -8,10 +8,10 @@ import {
|
||||
} from "@/components/ui/card";
|
||||
import { api } from "@/utils/api";
|
||||
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 { DeleteVolume } from "../../application/advanced/volumes/delete-volume";
|
||||
import { UpdateVolume } from "../../application/advanced/volumes/update-volume";
|
||||
import { AlertBlock } from "@/components/shared/alert-block";
|
||||
interface Props {
|
||||
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 { api } from "@/utils/api";
|
||||
import { z } from "zod";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { toast } from "sonner";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
||||
import {
|
||||
Form,
|
||||
FormControl,
|
||||
@@ -14,9 +8,15 @@ import {
|
||||
FormLabel,
|
||||
FormMessage,
|
||||
} 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 { ShowMongoResources } from "./show-mongo-resources";
|
||||
import { toast } from "sonner";
|
||||
import { z } from "zod";
|
||||
import { ShowVolumes } from "../volumes/show-volumes";
|
||||
import { ShowMongoResources } from "./show-mongo-resources";
|
||||
|
||||
const addDockerImage = z.object({
|
||||
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 {
|
||||
Card,
|
||||
@@ -21,7 +22,6 @@ import React, { useEffect } from "react";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { toast } from "sonner";
|
||||
import { z } from "zod";
|
||||
import { AlertBlock } from "@/components/shared/alert-block";
|
||||
|
||||
const addResourcesMongo = z.object({
|
||||
memoryReservation: z.number().nullable().optional(),
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React from "react";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
@@ -6,20 +6,20 @@ import {
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} 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 {
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
TooltipProvider,
|
||||
TooltipTrigger,
|
||||
} 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 {
|
||||
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 { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
||||
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 React from "react";
|
||||
import { DockerTerminalModal } from "../../settings/web-server/docker-terminal-modal";
|
||||
import { StartMongo } from "../start-mongo";
|
||||
import { DeployMongo } from "./deploy-mongo";
|
||||
import { ResetMongo } from "./reset-mongo";
|
||||
import { StopMongo } from "./stop-mongo";
|
||||
interface Props {
|
||||
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 { Input } from "@/components/ui/input";
|
||||
import { Label } from "@/components/ui/label";
|
||||
import { api } from "@/utils/api";
|
||||
import { ToggleVisibilityInput } from "@/components/shared/toggle-visibility-input";
|
||||
import React from "react";
|
||||
|
||||
interface Props {
|
||||
mongoId: string;
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import {
|
||||
AlertDialog,
|
||||
AlertDialogAction,
|
||||
AlertDialogCancel,
|
||||
AlertDialogContent,
|
||||
AlertDialogDescription,
|
||||
AlertDialogFooter,
|
||||
AlertDialogHeader,
|
||||
AlertDialogTitle,
|
||||
AlertDialogTrigger,
|
||||
AlertDialog,
|
||||
AlertDialogAction,
|
||||
AlertDialogCancel,
|
||||
AlertDialogContent,
|
||||
AlertDialogDescription,
|
||||
AlertDialogFooter,
|
||||
AlertDialogHeader,
|
||||
AlertDialogTitle,
|
||||
AlertDialogTrigger,
|
||||
} from "@/components/ui/alert-dialog";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { api } from "@/utils/api";
|
||||
@@ -15,51 +15,51 @@ import { Ban } from "lucide-react";
|
||||
import { toast } from "sonner";
|
||||
|
||||
interface Props {
|
||||
mongoId: string;
|
||||
mongoId: string;
|
||||
}
|
||||
|
||||
export const StopMongo = ({ mongoId }: Props) => {
|
||||
const { mutateAsync, isLoading } = api.mongo.stop.useMutation();
|
||||
const utils = api.useUtils();
|
||||
return (
|
||||
<AlertDialog>
|
||||
<AlertDialogTrigger asChild>
|
||||
<Button variant="destructive" isLoading={isLoading}>
|
||||
Stop
|
||||
<Ban className="size-4" />
|
||||
</Button>
|
||||
</AlertDialogTrigger>
|
||||
<AlertDialogContent>
|
||||
<AlertDialogHeader>
|
||||
<AlertDialogTitle>
|
||||
Are you absolutely sure to stop the database?
|
||||
</AlertDialogTitle>
|
||||
<AlertDialogDescription>
|
||||
This will stop the database
|
||||
</AlertDialogDescription>
|
||||
</AlertDialogHeader>
|
||||
<AlertDialogFooter>
|
||||
<AlertDialogCancel>Cancel</AlertDialogCancel>
|
||||
<AlertDialogAction
|
||||
onClick={async () => {
|
||||
await mutateAsync({
|
||||
mongoId,
|
||||
})
|
||||
.then(async () => {
|
||||
await utils.mongo.one.invalidate({
|
||||
mongoId,
|
||||
});
|
||||
toast.success("Application stopped succesfully");
|
||||
})
|
||||
.catch(() => {
|
||||
toast.error("Error to stop the Application");
|
||||
});
|
||||
}}
|
||||
>
|
||||
Confirm
|
||||
</AlertDialogAction>
|
||||
</AlertDialogFooter>
|
||||
</AlertDialogContent>
|
||||
</AlertDialog>
|
||||
);
|
||||
const { mutateAsync, isLoading } = api.mongo.stop.useMutation();
|
||||
const utils = api.useUtils();
|
||||
return (
|
||||
<AlertDialog>
|
||||
<AlertDialogTrigger asChild>
|
||||
<Button variant="destructive" isLoading={isLoading}>
|
||||
Stop
|
||||
<Ban className="size-4" />
|
||||
</Button>
|
||||
</AlertDialogTrigger>
|
||||
<AlertDialogContent>
|
||||
<AlertDialogHeader>
|
||||
<AlertDialogTitle>
|
||||
Are you absolutely sure to stop the database?
|
||||
</AlertDialogTitle>
|
||||
<AlertDialogDescription>
|
||||
This will stop the database
|
||||
</AlertDialogDescription>
|
||||
</AlertDialogHeader>
|
||||
<AlertDialogFooter>
|
||||
<AlertDialogCancel>Cancel</AlertDialogCancel>
|
||||
<AlertDialogAction
|
||||
onClick={async () => {
|
||||
await mutateAsync({
|
||||
mongoId,
|
||||
})
|
||||
.then(async () => {
|
||||
await utils.mongo.one.invalidate({
|
||||
mongoId,
|
||||
});
|
||||
toast.success("Application stopped succesfully");
|
||||
})
|
||||
.catch(() => {
|
||||
toast.error("Error to stop the Application");
|
||||
});
|
||||
}}
|
||||
>
|
||||
Confirm
|
||||
</AlertDialogAction>
|
||||
</AlertDialogFooter>
|
||||
</AlertDialogContent>
|
||||
</AlertDialog>
|
||||
);
|
||||
};
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user