mirror of
https://github.com/DeNNiiInc/Advanced-Raid-Calculator.git
synced 2026-04-17 12:45:59 +00:00
Add git commit info to UI and update deployment script
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -9,3 +9,4 @@ cron.log
|
|||||||
# System files
|
# System files
|
||||||
.DS_Store
|
.DS_Store
|
||||||
Thumbs.db
|
Thumbs.db
|
||||||
|
version.json
|
||||||
|
|||||||
@@ -13,6 +13,10 @@ echo "Deploying $APP_NAME..."
|
|||||||
# If we are running this script FROM the repo, we assume we are already in the right place or we are setting it up.
|
# If we are running this script FROM the repo, we assume we are already in the right place or we are setting it up.
|
||||||
# This script assumes it is being run inside the destination directory /var/www/advanced-raid-calculator
|
# This script assumes it is being run inside the destination directory /var/www/advanced-raid-calculator
|
||||||
|
|
||||||
|
# Generate version info
|
||||||
|
echo "Generating version info..."
|
||||||
|
node update-version.js
|
||||||
|
|
||||||
# Install dependencies
|
# Install dependencies
|
||||||
echo "Installing dependencies..."
|
echo "Installing dependencies..."
|
||||||
npm install
|
npm install
|
||||||
|
|||||||
184
index.html
184
index.html
@@ -1,35 +1,45 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
|
<head>
|
||||||
<head>
|
<meta charset="UTF-8" />
|
||||||
<meta charset="UTF-8">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
||||||
<title>Beyond Cloud Technology - RAID Calculator</title>
|
<title>Beyond Cloud Technology - RAID Calculator</title>
|
||||||
<meta name="description"
|
<meta
|
||||||
content="Professional RAID calculator by Beyond Cloud Technology supporting standard RAID, Synology SHR, ZFS, and Unraid configurations with accurate usable storage calculations.">
|
name="description"
|
||||||
<link rel="icon" type="image/png" href="Logo.png">
|
content="Professional RAID calculator by Beyond Cloud Technology supporting standard RAID, Synology SHR, ZFS, and Unraid configurations with accurate usable storage calculations."
|
||||||
<link rel="stylesheet" href="styles.css">
|
/>
|
||||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
<link rel="icon" type="image/png" href="Logo.png" />
|
||||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
<link rel="stylesheet" href="styles.css" />
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet">
|
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||||
</head>
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||||
|
<link
|
||||||
|
href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap"
|
||||||
|
rel="stylesheet"
|
||||||
|
/>
|
||||||
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<header class="header">
|
<header class="header">
|
||||||
<div class="header-content">
|
<div class="header-content">
|
||||||
<h1 class="title">
|
<h1 class="title">
|
||||||
<img src="Logo.png" alt="BCT Logo" class="title-icon">
|
<img src="Logo.png" alt="BCT Logo" class="title-icon" />
|
||||||
Beyond Cloud Technology - RAID Calculator
|
Beyond Cloud Technology - RAID Calculator
|
||||||
</h1>
|
</h1>
|
||||||
<p class="subtitle">Professional storage capacity planning for RAID, Synology SHR, ZFS & Unraid
|
<p class="subtitle">
|
||||||
configurations
|
Professional storage capacity planning for RAID, Synology SHR, ZFS &
|
||||||
|
Unraid configurations
|
||||||
</p>
|
</p>
|
||||||
<a href="https://www.youtube.com/@beyondcloudtechnology" target="_blank" rel="noopener noreferrer"
|
<a
|
||||||
class="youtube-link">
|
href="https://www.youtube.com/@beyondcloudtechnology"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
class="youtube-link"
|
||||||
|
>
|
||||||
<svg class="youtube-icon" viewBox="0 0 24 24" fill="currentColor">
|
<svg class="youtube-icon" viewBox="0 0 24 24" fill="currentColor">
|
||||||
<path
|
<path
|
||||||
d="M23.498 6.186a3.016 3.016 0 0 0-2.122-2.136C19.505 3.545 12 3.545 12 3.545s-7.505 0-9.377.505A3.017 3.017 0 0 0 .502 6.186C0 8.07 0 12 0 12s0 3.93.502 5.814a3.016 3.016 0 0 0 2.122 2.136c1.871.505 9.376.505 9.376.505s7.505 0 9.377-.505a3.015 3.015 0 0 0 2.122-2.136C24 15.93 24 12 24 12s0-3.93-.502-5.814zM9.545 15.568V8.432L15.818 12l-6.273 3.568z" />
|
d="M23.498 6.186a3.016 3.016 0 0 0-2.122-2.136C19.505 3.545 12 3.545 12 3.545s-7.505 0-9.377.505A3.017 3.017 0 0 0 .502 6.186C0 8.07 0 12 0 12s0 3.93.502 5.814a3.016 3.016 0 0 0 2.122 2.136c1.871.505 9.376.505 9.376.505s7.505 0 9.377-.505a3.015 3.015 0 0 0 2.122-2.136C24 15.93 24 12 24 12s0-3.93-.502-5.814zM9.545 15.568V8.432L15.818 12l-6.273 3.568z"
|
||||||
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
Watch on YouTube @beyondcloudtechnology
|
Watch on YouTube @beyondcloudtechnology
|
||||||
</a>
|
</a>
|
||||||
@@ -46,7 +56,9 @@
|
|||||||
<label for="raid-type" class="label">RAID Type</label>
|
<label for="raid-type" class="label">RAID Type</label>
|
||||||
<select id="raid-type" class="select">
|
<select id="raid-type" class="select">
|
||||||
<optgroup label="Standard RAID">
|
<optgroup label="Standard RAID">
|
||||||
<option value="raid0">RAID 0 - Striping (No Redundancy)</option>
|
<option value="raid0">
|
||||||
|
RAID 0 - Striping (No Redundancy)
|
||||||
|
</option>
|
||||||
<option value="raid1">RAID 1 - Mirroring</option>
|
<option value="raid1">RAID 1 - Mirroring</option>
|
||||||
<option value="raid5" selected>RAID 5 - Single Parity</option>
|
<option value="raid5" selected>RAID 5 - Single Parity</option>
|
||||||
<option value="raid6">RAID 6 - Double Parity</option>
|
<option value="raid6">RAID 6 - Double Parity</option>
|
||||||
@@ -54,7 +66,9 @@
|
|||||||
</optgroup>
|
</optgroup>
|
||||||
<optgroup label="Synology RAID">
|
<optgroup label="Synology RAID">
|
||||||
<option value="shr">SHR - Synology Hybrid RAID</option>
|
<option value="shr">SHR - Synology Hybrid RAID</option>
|
||||||
<option value="shr2">SHR-2 - Synology Hybrid RAID (2-disk fault tolerance)</option>
|
<option value="shr2">
|
||||||
|
SHR-2 - Synology Hybrid RAID (2-disk fault tolerance)
|
||||||
|
</option>
|
||||||
</optgroup>
|
</optgroup>
|
||||||
<optgroup label="ZFS RAID">
|
<optgroup label="ZFS RAID">
|
||||||
<option value="zfs-stripe">ZFS Stripe (No Redundancy)</option>
|
<option value="zfs-stripe">ZFS Stripe (No Redundancy)</option>
|
||||||
@@ -73,7 +87,14 @@
|
|||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="num-drives" class="label">Number of Drives</label>
|
<label for="num-drives" class="label">Number of Drives</label>
|
||||||
<div class="input-with-display">
|
<div class="input-with-display">
|
||||||
<input type="range" id="num-drives" class="slider" min="2" max="24" value="4">
|
<input
|
||||||
|
type="range"
|
||||||
|
id="num-drives"
|
||||||
|
class="slider"
|
||||||
|
min="2"
|
||||||
|
max="24"
|
||||||
|
value="4"
|
||||||
|
/>
|
||||||
<span id="num-drives-display" class="value-display">4</span>
|
<span id="num-drives-display" class="value-display">4</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -98,20 +119,42 @@
|
|||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="zfs-vdev-config" class="form-group" style="display: none;">
|
<div id="zfs-vdev-config" class="form-group" style="display: none">
|
||||||
<label for="num-vdevs" class="label">Number of vdevs</label>
|
<label for="num-vdevs" class="label">Number of vdevs</label>
|
||||||
<div class="input-with-display">
|
<div class="input-with-display">
|
||||||
<input type="range" id="num-vdevs" class="slider" min="1" max="8" value="2">
|
<input
|
||||||
|
type="range"
|
||||||
|
id="num-vdevs"
|
||||||
|
class="slider"
|
||||||
|
min="1"
|
||||||
|
max="8"
|
||||||
|
value="2"
|
||||||
|
/>
|
||||||
<span id="num-vdevs-display" class="value-display">2</span>
|
<span id="num-vdevs-display" class="value-display">2</span>
|
||||||
</div>
|
</div>
|
||||||
<p class="helper-text">Each vdev will use the selected RAID type (mirror/RAIDZ)</p>
|
<p class="helper-text">
|
||||||
|
Each vdev will use the selected RAID type (mirror/RAIDZ)
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="drives-per-vdev-config" class="form-group" style="display: none;">
|
<div
|
||||||
|
id="drives-per-vdev-config"
|
||||||
|
class="form-group"
|
||||||
|
style="display: none"
|
||||||
|
>
|
||||||
<label for="drives-per-vdev" class="label">Drives per vdev</label>
|
<label for="drives-per-vdev" class="label">Drives per vdev</label>
|
||||||
<div class="input-with-display">
|
<div class="input-with-display">
|
||||||
<input type="range" id="drives-per-vdev" class="slider" min="2" max="12" value="3">
|
<input
|
||||||
<span id="drives-per-vdev-display" class="value-display">3</span>
|
type="range"
|
||||||
|
id="drives-per-vdev"
|
||||||
|
class="slider"
|
||||||
|
min="2"
|
||||||
|
max="12"
|
||||||
|
value="3"
|
||||||
|
/>
|
||||||
|
<span id="drives-per-vdev-display" class="value-display"
|
||||||
|
>3</span
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
<p class="helper-text" id="total-drives-text">Total drives: 6</p>
|
<p class="helper-text" id="total-drives-text">Total drives: 6</p>
|
||||||
</div>
|
</div>
|
||||||
@@ -119,20 +162,32 @@
|
|||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="label">Mixed Drive Sizes</label>
|
<label class="label">Mixed Drive Sizes</label>
|
||||||
<div class="toggle-container">
|
<div class="toggle-container">
|
||||||
<input type="checkbox" id="mixed-drives" class="toggle-input">
|
<input type="checkbox" id="mixed-drives" class="toggle-input" />
|
||||||
<label for="mixed-drives" class="toggle-label">
|
<label for="mixed-drives" class="toggle-label">
|
||||||
<span class="toggle-slider"></span>
|
<span class="toggle-slider"></span>
|
||||||
</label>
|
</label>
|
||||||
<span class="toggle-text">Enable custom drive configuration</span>
|
<span class="toggle-text"
|
||||||
|
>Enable custom drive configuration</span
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="custom-drives-container" class="custom-drives-container" style="display: none;">
|
<div
|
||||||
|
id="custom-drives-container"
|
||||||
|
class="custom-drives-container"
|
||||||
|
style="display: none"
|
||||||
|
>
|
||||||
<div id="drive-inputs" class="drive-inputs"></div>
|
<div id="drive-inputs" class="drive-inputs"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button id="calculate-btn" class="btn-primary">
|
<button id="calculate-btn" class="btn-primary">
|
||||||
<svg class="btn-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
<svg
|
||||||
|
class="btn-icon"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
stroke-width="2"
|
||||||
|
>
|
||||||
<path d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" />
|
<path d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" />
|
||||||
</svg>
|
</svg>
|
||||||
Calculate Storage
|
Calculate Storage
|
||||||
@@ -145,12 +200,21 @@
|
|||||||
|
|
||||||
<div id="results-content" class="results-content">
|
<div id="results-content" class="results-content">
|
||||||
<div class="empty-state">
|
<div class="empty-state">
|
||||||
<svg class="empty-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor"
|
<svg
|
||||||
stroke-width="2">
|
class="empty-icon"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
stroke-width="2"
|
||||||
|
>
|
||||||
<path
|
<path
|
||||||
d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2" />
|
d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"
|
||||||
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
<p>Configure your RAID array and click "Calculate Storage" to see results</p>
|
<p>
|
||||||
|
Configure your RAID array and click "Calculate Storage" to see
|
||||||
|
results
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
@@ -160,46 +224,72 @@
|
|||||||
<div class="info-grid">
|
<div class="info-grid">
|
||||||
<div class="info-card card">
|
<div class="info-card card">
|
||||||
<div class="info-icon info-icon-blue">
|
<div class="info-icon info-icon-blue">
|
||||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
<svg
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
stroke-width="2"
|
||||||
|
>
|
||||||
<circle cx="12" cy="12" r="10" />
|
<circle cx="12" cy="12" r="10" />
|
||||||
<path d="M12 16v-4m0-4h.01" />
|
<path d="M12 16v-4m0-4h.01" />
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
<h3 class="info-title">Accurate Calculations</h3>
|
<h3 class="info-title">Accurate Calculations</h3>
|
||||||
<p class="info-text">Accounts for binary vs decimal differences - 12TB drives show actual ~10.9TB
|
<p class="info-text">
|
||||||
usable capacity</p>
|
Accounts for binary vs decimal differences - 12TB drives show
|
||||||
|
actual ~10.9TB usable capacity
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="info-card card">
|
<div class="info-card card">
|
||||||
<div class="info-icon info-icon-green">
|
<div class="info-icon info-icon-green">
|
||||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
<svg
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
stroke-width="2"
|
||||||
|
>
|
||||||
<path
|
<path
|
||||||
d="M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z" />
|
d="M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z"
|
||||||
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
<h3 class="info-title">Fault Tolerance</h3>
|
<h3 class="info-title">Fault Tolerance</h3>
|
||||||
<p class="info-text">See exactly how many drives can fail while maintaining data integrity</p>
|
<p class="info-text">
|
||||||
|
See exactly how many drives can fail while maintaining data
|
||||||
|
integrity
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="info-card card">
|
<div class="info-card card">
|
||||||
<div class="info-icon info-icon-purple">
|
<div class="info-icon info-icon-purple">
|
||||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
<svg
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
stroke-width="2"
|
||||||
|
>
|
||||||
<path d="M13 10V3L4 14h7v7l9-11h-7z" />
|
<path d="M13 10V3L4 14h7v7l9-11h-7z" />
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
<h3 class="info-title">Performance Insights</h3>
|
<h3 class="info-title">Performance Insights</h3>
|
||||||
<p class="info-text">Understand read/write performance characteristics of each RAID configuration
|
<p class="info-text">
|
||||||
|
Understand read/write performance characteristics of each RAID
|
||||||
|
configuration
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<footer class="footer">
|
<footer class="footer">
|
||||||
<p>© 2025 Beyond Cloud Technology. Professional storage planning tool.</p>
|
<p>
|
||||||
|
© 2025 Beyond Cloud Technology. Professional storage planning
|
||||||
|
tool.
|
||||||
|
</p>
|
||||||
</footer>
|
</footer>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div id="version-display"></div>
|
||||||
<script src="script.js"></script>
|
<script src="script.js"></script>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
38
script.js
38
script.js
@@ -715,4 +715,42 @@ class RAIDCalculator {
|
|||||||
|
|
||||||
document.addEventListener('DOMContentLoaded', () => {
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
new RAIDCalculator();
|
new RAIDCalculator();
|
||||||
|
initVersionDisplay();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/* ===================================
|
||||||
|
Version Display Logic
|
||||||
|
=================================== */
|
||||||
|
function initVersionDisplay() {
|
||||||
|
const versionDisplay = document.getElementById('version-display');
|
||||||
|
if (!versionDisplay) return;
|
||||||
|
|
||||||
|
// Add cache buster to ensure fresh version info
|
||||||
|
fetch(`version.json?t=${new Date().getTime()}`)
|
||||||
|
.then(response => {
|
||||||
|
if (!response.ok) throw new Error('Version info not found');
|
||||||
|
return response.json();
|
||||||
|
})
|
||||||
|
.then(data => {
|
||||||
|
if (!data.commit || !data.date) return;
|
||||||
|
|
||||||
|
versionDisplay.innerHTML = `
|
||||||
|
<a href="https://github.com/DeNNiiInc/Advanced-Raid-Calculator/commit/${data.commit}"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
class="version-tag"
|
||||||
|
title="View commit on GitHub">
|
||||||
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="width: 14px; height: 14px; opacity: 0.7;">
|
||||||
|
<path d="M9 19c-5 1.5-5-2.5-7-3m14 6v-3.87a3.37 3.37 0 0 0-.94-2.61c3.14-.35 6.44-1.54 6.44-7A5.44 5.44 0 0 0 20 4.77 5.07 5.07 0 0 0 19.91 1S18.73.65 16 2.48a13.38 13.38 0 0 0-7 0C6.27.65 5.09 1 5.09 1A5.07 5.07 0 0 0 5 4.77a5.44 5.44 0 0 0-1.5 3.78c0 5.42 3.3 6.61 6.44 7A3.37 3.37 0 0 0 9 18.13V22"></path>
|
||||||
|
</svg>
|
||||||
|
<span class="version-commit">${data.commit}</span>
|
||||||
|
<span class="version-divider"></span>
|
||||||
|
<span class="version-date">${data.date}</span>
|
||||||
|
</a>
|
||||||
|
`;
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.log('Version info unavailable:', error);
|
||||||
|
versionDisplay.style.display = 'none';
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|||||||
103
styles.css
103
styles.css
@@ -20,7 +20,11 @@
|
|||||||
--gradient-primary: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
--gradient-primary: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||||
--gradient-secondary: linear-gradient(135deg, #3b82f6 0%, #8b5cf6 100%);
|
--gradient-secondary: linear-gradient(135deg, #3b82f6 0%, #8b5cf6 100%);
|
||||||
--gradient-success: linear-gradient(135deg, #10b981 0%, #059669 100%);
|
--gradient-success: linear-gradient(135deg, #10b981 0%, #059669 100%);
|
||||||
--gradient-card: linear-gradient(135deg, rgba(59, 130, 246, 0.1) 0%, rgba(139, 92, 246, 0.1) 100%);
|
--gradient-card: linear-gradient(
|
||||||
|
135deg,
|
||||||
|
rgba(59, 130, 246, 0.1) 0%,
|
||||||
|
rgba(139, 92, 246, 0.1) 100%
|
||||||
|
);
|
||||||
|
|
||||||
/* Text Colors */
|
/* Text Colors */
|
||||||
--color-text-primary: #f8fafc;
|
--color-text-primary: #f8fafc;
|
||||||
@@ -32,9 +36,12 @@
|
|||||||
--color-border: rgba(148, 163, 184, 0.1);
|
--color-border: rgba(148, 163, 184, 0.1);
|
||||||
--color-border-focus: rgba(59, 130, 246, 0.5);
|
--color-border-focus: rgba(59, 130, 246, 0.5);
|
||||||
--shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
|
--shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
|
||||||
--shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
|
--shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1),
|
||||||
--shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.3), 0 4px 6px -2px rgba(0, 0, 0, 0.2);
|
0 2px 4px -1px rgba(0, 0, 0, 0.06);
|
||||||
--shadow-xl: 0 20px 25px -5px rgba(0, 0, 0, 0.4), 0 10px 10px -5px rgba(0, 0, 0, 0.2);
|
--shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.3),
|
||||||
|
0 4px 6px -2px rgba(0, 0, 0, 0.2);
|
||||||
|
--shadow-xl: 0 20px 25px -5px rgba(0, 0, 0, 0.4),
|
||||||
|
0 10px 10px -5px rgba(0, 0, 0, 0.2);
|
||||||
--shadow-glow: 0 0 20px rgba(59, 130, 246, 0.3);
|
--shadow-glow: 0 0 20px rgba(59, 130, 246, 0.3);
|
||||||
|
|
||||||
/* Spacing */
|
/* Spacing */
|
||||||
@@ -52,7 +59,8 @@
|
|||||||
--radius-xl: 1rem;
|
--radius-xl: 1rem;
|
||||||
|
|
||||||
/* Typography */
|
/* Typography */
|
||||||
--font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
|
--font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI",
|
||||||
|
sans-serif;
|
||||||
--font-size-xs: 0.75rem;
|
--font-size-xs: 0.75rem;
|
||||||
--font-size-sm: 0.875rem;
|
--font-size-sm: 0.875rem;
|
||||||
--font-size-base: 1rem;
|
--font-size-base: 1rem;
|
||||||
@@ -88,22 +96,32 @@ body {
|
|||||||
|
|
||||||
/* Animated Background */
|
/* Animated Background */
|
||||||
body::before {
|
body::before {
|
||||||
content: '';
|
content: "";
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
background:
|
background: radial-gradient(
|
||||||
radial-gradient(circle at 20% 50%, rgba(59, 130, 246, 0.1) 0%, transparent 50%),
|
circle at 20% 50%,
|
||||||
radial-gradient(circle at 80% 80%, rgba(139, 92, 246, 0.1) 0%, transparent 50%),
|
rgba(59, 130, 246, 0.1) 0%,
|
||||||
radial-gradient(circle at 40% 20%, rgba(16, 185, 129, 0.05) 0%, transparent 50%);
|
transparent 50%
|
||||||
|
),
|
||||||
|
radial-gradient(
|
||||||
|
circle at 80% 80%,
|
||||||
|
rgba(139, 92, 246, 0.1) 0%,
|
||||||
|
transparent 50%
|
||||||
|
),
|
||||||
|
radial-gradient(
|
||||||
|
circle at 40% 20%,
|
||||||
|
rgba(16, 185, 129, 0.05) 0%,
|
||||||
|
transparent 50%
|
||||||
|
);
|
||||||
z-index: -1;
|
z-index: -1;
|
||||||
animation: backgroundShift 20s ease-in-out infinite;
|
animation: backgroundShift 20s ease-in-out infinite;
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes backgroundShift {
|
@keyframes backgroundShift {
|
||||||
|
|
||||||
0%,
|
0%,
|
||||||
100% {
|
100% {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
@@ -172,7 +190,7 @@ body::before {
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
gap: var(--spacing-sm);
|
gap: var(--spacing-sm);
|
||||||
padding: var(--spacing-sm) var(--spacing-md);
|
padding: var(--spacing-sm) var(--spacing-md);
|
||||||
background: linear-gradient(135deg, #FF0000 0%, #CC0000 100%);
|
background: linear-gradient(135deg, #ff0000 0%, #cc0000 100%);
|
||||||
color: white;
|
color: white;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
border-radius: var(--radius-md);
|
border-radius: var(--radius-md);
|
||||||
@@ -197,7 +215,6 @@ body::before {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@keyframes pulse-glow {
|
@keyframes pulse-glow {
|
||||||
|
|
||||||
0%,
|
0%,
|
||||||
100% {
|
100% {
|
||||||
box-shadow: 0 2px 8px rgba(255, 0, 0, 0.3);
|
box-shadow: 0 2px 8px rgba(255, 0, 0, 0.3);
|
||||||
@@ -256,7 +273,7 @@ body::before {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.section-title::before {
|
.section-title::before {
|
||||||
content: '';
|
content: "";
|
||||||
width: 4px;
|
width: 4px;
|
||||||
height: 1.5rem;
|
height: 1.5rem;
|
||||||
background: var(--gradient-secondary);
|
background: var(--gradient-secondary);
|
||||||
@@ -401,12 +418,12 @@ body::before {
|
|||||||
transition: all var(--transition-base);
|
transition: all var(--transition-base);
|
||||||
}
|
}
|
||||||
|
|
||||||
.toggle-input:checked+.toggle-label {
|
.toggle-input:checked + .toggle-label {
|
||||||
background: var(--gradient-secondary);
|
background: var(--gradient-secondary);
|
||||||
border-color: var(--color-accent-primary);
|
border-color: var(--color-accent-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
.toggle-input:checked+.toggle-label .toggle-slider {
|
.toggle-input:checked + .toggle-label .toggle-slider {
|
||||||
transform: translateX(24px);
|
transform: translateX(24px);
|
||||||
background: white;
|
background: white;
|
||||||
}
|
}
|
||||||
@@ -755,7 +772,6 @@ body::before {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@keyframes pulse {
|
@keyframes pulse {
|
||||||
|
|
||||||
0%,
|
0%,
|
||||||
100% {
|
100% {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
@@ -797,3 +813,56 @@ body::before {
|
|||||||
.hidden {
|
.hidden {
|
||||||
display: none !important;
|
display: none !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ===================================
|
||||||
|
Version Tag
|
||||||
|
=================================== */
|
||||||
|
.version-tag {
|
||||||
|
position: fixed;
|
||||||
|
bottom: 20px;
|
||||||
|
right: 20px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 12px;
|
||||||
|
background: rgba(30, 41, 59, 0.85);
|
||||||
|
backdrop-filter: blur(8px);
|
||||||
|
padding: 8px 16px;
|
||||||
|
border-radius: 9999px; /* Pill shape */
|
||||||
|
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||||
|
font-size: var(--font-size-xs);
|
||||||
|
font-weight: 500;
|
||||||
|
color: var(--color-text-secondary);
|
||||||
|
z-index: 1000;
|
||||||
|
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1),
|
||||||
|
0 2px 4px -1px rgba(0, 0, 0, 0.06);
|
||||||
|
transition: all var(--transition-base);
|
||||||
|
text-decoration: none;
|
||||||
|
font-family: var(--font-family);
|
||||||
|
}
|
||||||
|
|
||||||
|
.version-tag:hover {
|
||||||
|
background: rgba(30, 41, 59, 0.95);
|
||||||
|
border-color: rgba(255, 255, 255, 0.2);
|
||||||
|
transform: translateY(-2px);
|
||||||
|
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1),
|
||||||
|
0 4px 6px -2px rgba(0, 0, 0, 0.05);
|
||||||
|
}
|
||||||
|
|
||||||
|
.version-commit {
|
||||||
|
font-family: "Consolas", "Monaco", monospace;
|
||||||
|
color: var(--color-accent-secondary);
|
||||||
|
font-weight: 600;
|
||||||
|
letter-spacing: 0.05em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.version-divider {
|
||||||
|
width: 4px;
|
||||||
|
height: 4px;
|
||||||
|
background-color: var(--color-text-tertiary);
|
||||||
|
border-radius: 50%;
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.version-date {
|
||||||
|
color: var(--color-text-muted);
|
||||||
|
}
|
||||||
|
|||||||
28
update-version.js
Normal file
28
update-version.js
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
const fs = require('fs');
|
||||||
|
const { execSync } = require('child_process');
|
||||||
|
|
||||||
|
try {
|
||||||
|
console.log('Generating version information...');
|
||||||
|
const commit = execSync('git rev-parse --short HEAD').toString().trim();
|
||||||
|
const date = execSync('git log -1 --format=%cd --date=relative').toString().trim();
|
||||||
|
|
||||||
|
const versionInfo = {
|
||||||
|
commit: commit,
|
||||||
|
date: date
|
||||||
|
};
|
||||||
|
|
||||||
|
fs.writeFileSync('version.json', JSON.stringify(versionInfo, null, 2));
|
||||||
|
console.log('version.json updated:', versionInfo);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to update version info:', error);
|
||||||
|
// Fallback if git fails (e.g. not a repo)
|
||||||
|
const versionInfo = {
|
||||||
|
commit: 'unknown',
|
||||||
|
date: 'unknown'
|
||||||
|
};
|
||||||
|
try {
|
||||||
|
fs.writeFileSync('version.json', JSON.stringify(versionInfo, null, 2));
|
||||||
|
} catch (e) {
|
||||||
|
console.error('Failed to write fallback version.json', e);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user