Compare commits

..

1 Commits

Author SHA1 Message Date
renovate[bot]
a1f506ae9d chore(deps): update dependency @vitejs/plugin-react to v5 2025-10-28 17:07:20 +00:00
7 changed files with 1299 additions and 191 deletions

View File

@@ -48,7 +48,7 @@ WORKDIR /app/backend
RUN npm cache clean --force &&\
rm -rf node_modules ~/.npm /root/.npm &&\
npm ci --ignore-scripts --legacy-peer-deps --no-audit --prefer-online --fetch-retries=3 --fetch-retry-mintimeout=20000 --fetch-retry-maxtimeout=120000 &&\
npm ci --ignore-scripts --legacy-peer-deps --no-audit --prefer-online --fetch-retries=0 &&\
PRISMA_CLI_BINARY_TYPE=binary npm run db:generate &&\
npm prune --omit=dev &&\
npm cache clean --force

View File

@@ -21,13 +21,9 @@ WORKDIR /app/frontend
COPY frontend/package*.json ./
RUN echo "=== Starting npm install ===" &&\
npm cache clean --force &&\
RUN npm cache clean --force &&\
rm -rf node_modules ~/.npm /root/.npm &&\
echo "=== npm install ===" &&\
npm install --ignore-scripts --legacy-peer-deps --no-audit --prefer-online --fetch-retries=3 --fetch-retry-mintimeout=20000 --fetch-retry-maxtimeout=120000 &&\
echo "=== npm install completed ===" &&\
npm cache clean --force
npm install --ignore-scripts --legacy-peer-deps --no-audit --prefer-online --fetch-retries=0
COPY frontend/ ./

View File

@@ -27,15 +27,16 @@
"react-chartjs-2": "^5.2.0",
"react-dom": "^18.3.1",
"react-icons": "^5.5.0",
"react-router-dom": "^6.30.1"
"react-router-dom": "^6.30.1",
"trianglify": "^4.1.1"
},
"devDependencies": {
"@types/react": "^18.3.14",
"@types/react-dom": "^18.3.1",
"@vitejs/plugin-react": "^4.3.4",
"@vitejs/plugin-react": "^5.0.0",
"autoprefixer": "^10.4.20",
"postcss": "^8.5.6",
"tailwindcss": "^4.0.0",
"tailwindcss": "^3.4.17",
"vite": "^7.1.5"
},
"overrides": {

View File

@@ -28,6 +28,7 @@ import {
import { useCallback, useEffect, useRef, useState } from "react";
import { FaReddit, FaYoutube } from "react-icons/fa";
import { Link, useLocation, useNavigate } from "react-router-dom";
import trianglify from "trianglify";
import { useAuth } from "../contexts/AuthContext";
import { useColorTheme } from "../contexts/ColorThemeContext";
import { useUpdateNotification } from "../contexts/UpdateNotificationContext";
@@ -236,93 +237,31 @@ const Layout = ({ children }) => {
navigate("/hosts?action=add");
};
// Generate clean radial gradient background with subtle triangular accents for dark mode
// Generate Trianglify background for dark mode
useEffect(() => {
const generateBackground = () => {
if (
!bgCanvasRef.current ||
!themeConfig?.login ||
!document.documentElement.classList.contains("dark")
bgCanvasRef.current &&
themeConfig?.login &&
document.documentElement.classList.contains("dark")
) {
return;
}
// Get current date as seed for daily variation
const today = new Date();
const dateSeed = `${today.getFullYear()}-${today.getMonth()}-${today.getDate()}`;
const canvas = bgCanvasRef.current;
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
const ctx = canvas.getContext("2d");
// Generate pattern with selected theme configuration
const pattern = trianglify({
width: window.innerWidth,
height: window.innerHeight,
cellSize: themeConfig.login.cellSize,
variance: themeConfig.login.variance,
seed: dateSeed,
xColors: themeConfig.login.xColors,
yColors: themeConfig.login.yColors,
});
// Get theme colors - pick first color from each palette
const xColors = themeConfig.login.xColors || [
"#667eea",
"#764ba2",
"#f093fb",
"#4facfe",
];
const yColors = themeConfig.login.yColors || [
"#667eea",
"#764ba2",
"#f093fb",
"#4facfe",
];
// Use date for daily color rotation
const today = new Date();
const seed =
today.getFullYear() * 10000 + today.getMonth() * 100 + today.getDate();
const random = (s) => {
const x = Math.sin(s) * 10000;
return x - Math.floor(x);
};
const color1 = xColors[Math.floor(random(seed) * xColors.length)];
const color2 = yColors[Math.floor(random(seed + 1000) * yColors.length)];
// Create clean radial gradient from center to bottom-right corner
const gradient = ctx.createRadialGradient(
canvas.width * 0.3, // Center slightly left
canvas.height * 0.3, // Center slightly up
0,
canvas.width * 0.5, // Expand to cover screen
canvas.height * 0.5,
Math.max(canvas.width, canvas.height) * 1.2,
);
// Subtle gradient with darker corners
gradient.addColorStop(0, color1);
gradient.addColorStop(0.6, color2);
gradient.addColorStop(1, "#0a0a0a"); // Very dark edges
ctx.fillStyle = gradient;
ctx.fillRect(0, 0, canvas.width, canvas.height);
// Add subtle triangular shapes as accents across entire background
const cellSize = 180;
const cols = Math.ceil(canvas.width / cellSize) + 1;
const rows = Math.ceil(canvas.height / cellSize) + 1;
for (let y = 0; y < rows; y++) {
for (let x = 0; x < cols; x++) {
const idx = y * cols + x;
// Draw more triangles (less sparse)
if (random(seed + idx + 5000) > 0.4) {
const baseX =
x * cellSize + random(seed + idx * 3) * cellSize * 0.8;
const baseY =
y * cellSize + random(seed + idx * 3 + 100) * cellSize * 0.8;
const size = 50 + random(seed + idx * 4) * 100;
ctx.beginPath();
ctx.moveTo(baseX, baseY);
ctx.lineTo(baseX + size, baseY);
ctx.lineTo(baseX + size / 2, baseY - size * 0.866);
ctx.closePath();
// More visible white with slightly higher opacity
ctx.fillStyle = `rgba(255, 255, 255, ${0.05 + random(seed + idx * 5) * 0.08})`;
ctx.fill();
}
}
// Render to canvas
pattern.toCanvas(bgCanvasRef.current);
}
};

View File

@@ -17,6 +17,7 @@ import { useEffect, useId, useRef, useState } from "react";
import { FaReddit, FaYoutube } from "react-icons/fa";
import { useNavigate } from "react-router-dom";
import trianglify from "trianglify";
import DiscordIcon from "../components/DiscordIcon";
import { useAuth } from "../contexts/AuthContext";
import { useColorTheme } from "../contexts/ColorThemeContext";
@@ -56,87 +57,27 @@ const Login = () => {
const navigate = useNavigate();
// Generate clean radial gradient background with subtle triangular accents
// Generate Trianglify background based on selected theme
useEffect(() => {
const generateBackground = () => {
if (!canvasRef.current || !themeConfig?.login) return;
if (canvasRef.current && themeConfig?.login) {
// Get current date as seed for daily variation
const today = new Date();
const dateSeed = `${today.getFullYear()}-${today.getMonth()}-${today.getDate()}`;
const canvas = canvasRef.current;
canvas.width = canvas.offsetWidth;
canvas.height = canvas.offsetHeight;
const ctx = canvas.getContext("2d");
// Generate pattern with selected theme configuration
const pattern = trianglify({
width: canvasRef.current.offsetWidth,
height: canvasRef.current.offsetHeight,
cellSize: themeConfig.login.cellSize,
variance: themeConfig.login.variance,
seed: dateSeed,
xColors: themeConfig.login.xColors,
yColors: themeConfig.login.yColors,
});
// Get theme colors - pick first color from each palette
const xColors = themeConfig.login.xColors || [
"#667eea",
"#764ba2",
"#f093fb",
"#4facfe",
];
const yColors = themeConfig.login.yColors || [
"#667eea",
"#764ba2",
"#f093fb",
"#4facfe",
];
// Use date for daily color rotation
const today = new Date();
const seed =
today.getFullYear() * 10000 + today.getMonth() * 100 + today.getDate();
const random = (s) => {
const x = Math.sin(s) * 10000;
return x - Math.floor(x);
};
const color1 = xColors[Math.floor(random(seed) * xColors.length)];
const color2 = yColors[Math.floor(random(seed + 1000) * yColors.length)];
// Create clean radial gradient from center to bottom-right corner
const gradient = ctx.createRadialGradient(
canvas.width * 0.3, // Center slightly left
canvas.height * 0.3, // Center slightly up
0,
canvas.width * 0.5, // Expand to cover screen
canvas.height * 0.5,
Math.max(canvas.width, canvas.height) * 1.2,
);
// Subtle gradient with darker corners
gradient.addColorStop(0, color1);
gradient.addColorStop(0.6, color2);
gradient.addColorStop(1, "#0a0a0a"); // Very dark edges
ctx.fillStyle = gradient;
ctx.fillRect(0, 0, canvas.width, canvas.height);
// Add subtle triangular shapes as accents across entire background
const cellSize = 180;
const cols = Math.ceil(canvas.width / cellSize) + 1;
const rows = Math.ceil(canvas.height / cellSize) + 1;
for (let y = 0; y < rows; y++) {
for (let x = 0; x < cols; x++) {
const idx = y * cols + x;
// Draw more triangles (less sparse)
if (random(seed + idx + 5000) > 0.4) {
const baseX =
x * cellSize + random(seed + idx * 3) * cellSize * 0.8;
const baseY =
y * cellSize + random(seed + idx * 3 + 100) * cellSize * 0.8;
const size = 50 + random(seed + idx * 4) * 100;
ctx.beginPath();
ctx.moveTo(baseX, baseY);
ctx.lineTo(baseX + size, baseY);
ctx.lineTo(baseX + size / 2, baseY - size * 0.866);
ctx.closePath();
// More visible white with slightly higher opacity
ctx.fillStyle = `rgba(255, 255, 255, ${0.05 + random(seed + idx * 5) * 0.08})`;
ctx.fill();
}
}
// Render to canvas
pattern.toCanvas(canvasRef.current);
}
};
@@ -149,7 +90,7 @@ const Login = () => {
window.addEventListener("resize", handleResize);
return () => window.removeEventListener("resize", handleResize);
}, [themeConfig]);
}, [themeConfig]); // Regenerate when theme changes
// Check if signup is enabled
useEffect(() => {

1273
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -2931,8 +2931,6 @@ update_installation() {
# Load existing .env to get database credentials
if [ -f "$instance_dir/backend/.env" ]; then
# Unset color variables before sourcing to prevent ANSI escape sequences from leaking into .env
unset RED GREEN YELLOW BLUE NC
source "$instance_dir/backend/.env"
print_status "Loaded existing configuration"