Update screenshots
23
README.md
@@ -24,20 +24,31 @@ Admin panel:
|
|||||||
- Server Status: 
|
- Server Status: 
|
||||||
- Server Settings: 
|
- Server Settings: 
|
||||||
- Security Center: 
|
- Security Center: 
|
||||||
|
- Users: 
|
||||||
|
- SSL Manager: 
|
||||||
|
- DNS Zones: 
|
||||||
|
- Backups: 
|
||||||
|
- Services: 
|
||||||
|
|
||||||
User panel and flows (placeholder screenshots; replace with real captures):
|
User panel and flows:
|
||||||
|
|
||||||
- User Dashboard: 
|
- User Dashboard: 
|
||||||
- Domain Management: 
|
- Domain Management: 
|
||||||
- Migration Progress: 
|
- Backups: 
|
||||||
- Backups: 
|
- cPanel Migration: 
|
||||||
|
|
||||||
Regenerate admin screenshots with:
|
Regenerate screenshots with:
|
||||||
|
|
||||||
```
|
```
|
||||||
node tests/take-screenshots.cjs --output-dir=docs/screenshots
|
node tests/take-screenshots.cjs --output-dir=docs/screenshots
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Optional overrides:
|
||||||
|
|
||||||
|
```
|
||||||
|
node tests/take-screenshots.cjs --output-dir=docs/screenshots --base-url=https://panel.example.com
|
||||||
|
```
|
||||||
|
|
||||||
## Feature Map
|
## Feature Map
|
||||||
|
|
||||||
### Admin Panel
|
### Admin Panel
|
||||||
|
|||||||
BIN
docs/screenshots/admin-backups.png
Normal file
|
After Width: | Height: | Size: 91 KiB |
|
Before Width: | Height: | Size: 145 KiB After Width: | Height: | Size: 119 KiB |
BIN
docs/screenshots/admin-dns-zones.png
Normal file
|
After Width: | Height: | Size: 73 KiB |
|
Before Width: | Height: | Size: 76 KiB After Width: | Height: | Size: 152 KiB |
|
Before Width: | Height: | Size: 95 KiB After Width: | Height: | Size: 86 KiB |
|
Before Width: | Height: | Size: 270 KiB After Width: | Height: | Size: 404 KiB |
BIN
docs/screenshots/admin-services.png
Normal file
|
After Width: | Height: | Size: 176 KiB |
BIN
docs/screenshots/admin-ssl-manager.png
Normal file
|
After Width: | Height: | Size: 100 KiB |
BIN
docs/screenshots/admin-users.png
Normal file
|
After Width: | Height: | Size: 88 KiB |
@@ -1,10 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="1200" height="750" viewBox="0 0 1200 750">
|
|
||||||
<rect width="1200" height="750" fill="#f6f7f9" />
|
|
||||||
<rect x="0" y="0" width="1200" height="60" fill="#111827" />
|
|
||||||
<rect x="0" y="60" width="240" height="690" fill="#1f2937" />
|
|
||||||
<rect x="260" y="90" width="900" height="620" fill="#ffffff" stroke="#e5e7eb" />
|
|
||||||
<text x="300" y="120" font-family="Arial, sans-serif" font-size="26" fill="#111827">Backups</text>
|
|
||||||
<rect x="300" y="160" width="840" height="40" fill="#e5e7eb" />
|
|
||||||
<rect x="300" y="220" width="840" height="320" fill="#f3f4f6" />
|
|
||||||
<text x="300" y="620" font-family="Arial, sans-serif" font-size="14" fill="#6b7280">Placeholder screenshot</text>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 709 B |
@@ -1,12 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="1200" height="750" viewBox="0 0 1200 750">
|
|
||||||
<rect width="1200" height="750" fill="#f6f7f9" />
|
|
||||||
<rect x="0" y="0" width="1200" height="60" fill="#111827" />
|
|
||||||
<rect x="0" y="60" width="240" height="690" fill="#1f2937" />
|
|
||||||
<rect x="260" y="90" width="900" height="620" fill="#ffffff" stroke="#e5e7eb" />
|
|
||||||
<text x="300" y="120" font-family="Arial, sans-serif" font-size="26" fill="#111827">Migration Progress</text>
|
|
||||||
<rect x="300" y="160" width="840" height="28" fill="#e5e7eb" />
|
|
||||||
<rect x="300" y="200" width="700" height="28" fill="#d1d5db" />
|
|
||||||
<rect x="300" y="240" width="620" height="28" fill="#d1d5db" />
|
|
||||||
<rect x="300" y="280" width="540" height="28" fill="#d1d5db" />
|
|
||||||
<text x="300" y="340" font-family="Arial, sans-serif" font-size="14" fill="#6b7280">Placeholder screenshot</text>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 851 B |
BIN
docs/screenshots/user-backups.png
Normal file
|
After Width: | Height: | Size: 91 KiB |
BIN
docs/screenshots/user-cpanel-migration.png
Normal file
|
After Width: | Height: | Size: 125 KiB |
BIN
docs/screenshots/user-dashboard.png
Normal file
|
After Width: | Height: | Size: 126 KiB |
@@ -1,11 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="1200" height="750" viewBox="0 0 1200 750">
|
|
||||||
<rect width="1200" height="750" fill="#f6f7f9" />
|
|
||||||
<rect x="0" y="0" width="1200" height="60" fill="#111827" />
|
|
||||||
<rect x="0" y="60" width="240" height="690" fill="#1f2937" />
|
|
||||||
<rect x="260" y="90" width="900" height="620" fill="#ffffff" stroke="#e5e7eb" />
|
|
||||||
<rect x="300" y="140" width="200" height="90" fill="#e5e7eb" />
|
|
||||||
<rect x="520" y="140" width="200" height="90" fill="#e5e7eb" />
|
|
||||||
<rect x="740" y="140" width="200" height="90" fill="#e5e7eb" />
|
|
||||||
<text x="300" y="120" font-family="Arial, sans-serif" font-size="26" fill="#111827">User Dashboard</text>
|
|
||||||
<text x="300" y="200" font-family="Arial, sans-serif" font-size="14" fill="#6b7280">Placeholder screenshot</text>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 781 B |
BIN
docs/screenshots/user-domains.png
Normal file
|
After Width: | Height: | Size: 84 KiB |
@@ -1,10 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="1200" height="750" viewBox="0 0 1200 750">
|
|
||||||
<rect width="1200" height="750" fill="#f6f7f9" />
|
|
||||||
<rect x="0" y="0" width="1200" height="60" fill="#111827" />
|
|
||||||
<rect x="0" y="60" width="240" height="690" fill="#1f2937" />
|
|
||||||
<rect x="260" y="90" width="900" height="620" fill="#ffffff" stroke="#e5e7eb" />
|
|
||||||
<text x="300" y="120" font-family="Arial, sans-serif" font-size="26" fill="#111827">Domain Management</text>
|
|
||||||
<rect x="300" y="160" width="840" height="40" fill="#e5e7eb" />
|
|
||||||
<rect x="300" y="220" width="840" height="360" fill="#f3f4f6" />
|
|
||||||
<text x="300" y="620" font-family="Arial, sans-serif" font-size="14" fill="#6b7280">Placeholder screenshot</text>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 719 B |
31
tests/Unit/ReadmeScreenshotsTest.php
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Tests\Unit;
|
||||||
|
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
|
class ReadmeScreenshotsTest extends TestCase
|
||||||
|
{
|
||||||
|
public function test_readme_references_screenshot_assets(): void
|
||||||
|
{
|
||||||
|
$readmePath = dirname(__DIR__, 2).'/README.md';
|
||||||
|
$content = file_get_contents($readmePath);
|
||||||
|
|
||||||
|
$this->assertNotFalse($content);
|
||||||
|
$this->assertStringContainsString('docs/screenshots/admin-dashboard.png', $content);
|
||||||
|
$this->assertStringContainsString('docs/screenshots/admin-server-status.png', $content);
|
||||||
|
$this->assertStringContainsString('docs/screenshots/admin-server-settings.png', $content);
|
||||||
|
$this->assertStringContainsString('docs/screenshots/admin-security.png', $content);
|
||||||
|
$this->assertStringContainsString('docs/screenshots/admin-users.png', $content);
|
||||||
|
$this->assertStringContainsString('docs/screenshots/admin-ssl-manager.png', $content);
|
||||||
|
$this->assertStringContainsString('docs/screenshots/admin-dns-zones.png', $content);
|
||||||
|
$this->assertStringContainsString('docs/screenshots/admin-backups.png', $content);
|
||||||
|
$this->assertStringContainsString('docs/screenshots/admin-services.png', $content);
|
||||||
|
$this->assertStringContainsString('docs/screenshots/user-dashboard.png', $content);
|
||||||
|
$this->assertStringContainsString('docs/screenshots/user-domains.png', $content);
|
||||||
|
$this->assertStringContainsString('docs/screenshots/user-backups.png', $content);
|
||||||
|
$this->assertStringContainsString('docs/screenshots/user-cpanel-migration.png', $content);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,10 +1,10 @@
|
|||||||
#!/usr/bin/env node
|
#!/usr/bin/env node
|
||||||
/**
|
/**
|
||||||
* Jabali Admin Panel Screenshot Script
|
* Jabali Panel Screenshot Script
|
||||||
*
|
*
|
||||||
* Takes screenshots of admin panel pages for documentation.
|
* Takes screenshots of admin and user panels for documentation.
|
||||||
*
|
*
|
||||||
* Usage: node tests/take-screenshots.js [--output-dir=/path/to/dir]
|
* Usage: node tests/take-screenshots.cjs [--output-dir=/path/to/dir]
|
||||||
*
|
*
|
||||||
* Requires: puppeteer (npm install puppeteer)
|
* Requires: puppeteer (npm install puppeteer)
|
||||||
*/
|
*/
|
||||||
@@ -12,20 +12,36 @@
|
|||||||
const puppeteer = require('puppeteer');
|
const puppeteer = require('puppeteer');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
|
|
||||||
// Configuration
|
const args = process.argv.slice(2);
|
||||||
const CONFIG = {
|
const getArg = (key, fallback) => {
|
||||||
baseUrl: 'https://mx.jabali-panel.com',
|
const arg = args.find((item) => item.startsWith(`--${key}=`));
|
||||||
adminPath: '/jabali-admin',
|
return arg ? arg.split('=').slice(1).join('=') : fallback;
|
||||||
credentials: {
|
|
||||||
email: 'admin@mx.jabali-panel.com',
|
|
||||||
password: 'PycpS1dUuLvxMMQs'
|
|
||||||
},
|
|
||||||
viewport: { width: 1400, height: 900 },
|
|
||||||
outputDir: process.argv.find(a => a.startsWith('--output-dir='))?.split('=')[1] || '/tmp'
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Pages to screenshot
|
const hasFlag = (flag) => args.includes(`--${flag}`);
|
||||||
const PAGES = [
|
let browser;
|
||||||
|
|
||||||
|
// Configuration
|
||||||
|
const CONFIG = {
|
||||||
|
baseUrl: getArg('base-url', 'https://mx.jabali-panel.com'),
|
||||||
|
adminPath: getArg('admin-path', '/jabali-admin'),
|
||||||
|
userPath: getArg('user-path', '/jabali-panel'),
|
||||||
|
admin: {
|
||||||
|
email: getArg('admin-email', 'admin@mx.jabali-panel.com'),
|
||||||
|
password: getArg('admin-password', 'PycpS1dUuLvxMMQs')
|
||||||
|
},
|
||||||
|
user: {
|
||||||
|
email: getArg('user-email', 'user@jabali-panel.com'),
|
||||||
|
password: getArg('user-password', 'PycpS1dUuLvxMMQs')
|
||||||
|
},
|
||||||
|
viewport: { width: 1400, height: 900 },
|
||||||
|
outputDir: getArg('output-dir', '/tmp'),
|
||||||
|
skipAdmin: hasFlag('skip-admin'),
|
||||||
|
skipUser: hasFlag('skip-user')
|
||||||
|
};
|
||||||
|
|
||||||
|
// Admin pages to screenshot
|
||||||
|
const ADMIN_PAGES = [
|
||||||
{ name: 'dashboard', path: '', description: 'Admin Dashboard' },
|
{ name: 'dashboard', path: '', description: 'Admin Dashboard' },
|
||||||
{ name: 'server-status', path: '/server-status', description: 'Server Status' },
|
{ name: 'server-status', path: '/server-status', description: 'Server Status' },
|
||||||
{ name: 'server-settings', path: '/server-settings', description: 'Server Settings' },
|
{ name: 'server-settings', path: '/server-settings', description: 'Server Settings' },
|
||||||
@@ -37,39 +53,40 @@ const PAGES = [
|
|||||||
{ name: 'services', path: '/services', description: 'Services' },
|
{ name: 'services', path: '/services', description: 'Services' },
|
||||||
];
|
];
|
||||||
|
|
||||||
async function takeScreenshots() {
|
// User pages to screenshot
|
||||||
console.log('Starting Jabali Admin Screenshot Script...\n');
|
const USER_PAGES = [
|
||||||
|
{ name: 'dashboard', path: '', description: 'User Dashboard' },
|
||||||
|
{ name: 'domains', path: '/domains', description: 'Domain Management' },
|
||||||
|
{ name: 'backups', path: '/backups', description: 'Backups' },
|
||||||
|
{ name: 'cpanel-migration', path: '/cpanel-migration', description: 'cPanel Migration' }
|
||||||
|
];
|
||||||
|
|
||||||
const browser = await puppeteer.launch({
|
const wait = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
||||||
headless: 'new',
|
|
||||||
args: ['--no-sandbox', '--disable-setuid-sandbox', '--ignore-certificate-errors']
|
|
||||||
});
|
|
||||||
|
|
||||||
const page = await browser.newPage();
|
async function capturePanel({ panelName, basePath, credentials, pages, outputPrefix }) {
|
||||||
|
const context = await browser.createBrowserContext();
|
||||||
|
const page = await context.newPage();
|
||||||
await page.setViewport(CONFIG.viewport);
|
await page.setViewport(CONFIG.viewport);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Login
|
console.log(`Logging in to ${panelName} panel...`);
|
||||||
console.log('Logging in to admin panel...');
|
await page.goto(`${CONFIG.baseUrl}${basePath}/login`, { waitUntil: 'networkidle0' });
|
||||||
await page.goto(`${CONFIG.baseUrl}${CONFIG.adminPath}/login`, { waitUntil: 'networkidle0' });
|
await wait(1500);
|
||||||
await new Promise(r => setTimeout(r, 2000));
|
|
||||||
|
|
||||||
await page.type('input[type="email"]', CONFIG.credentials.email);
|
await page.type('input[type="email"]', credentials.email);
|
||||||
await page.type('input[type="password"]', CONFIG.credentials.password);
|
await page.type('input[type="password"]', credentials.password);
|
||||||
await page.click('button[type="submit"]');
|
await page.click('button[type="submit"]');
|
||||||
await new Promise(r => setTimeout(r, 5000));
|
await wait(4000);
|
||||||
|
|
||||||
// Check if login succeeded
|
|
||||||
const currentUrl = page.url();
|
const currentUrl = page.url();
|
||||||
if (currentUrl.includes('/login')) {
|
if (currentUrl.includes('/login')) {
|
||||||
throw new Error('Login failed - still on login page');
|
throw new Error(`${panelName} login failed - still on login page`);
|
||||||
}
|
}
|
||||||
console.log('Login successful!\n');
|
console.log(`${panelName} login successful!\n`);
|
||||||
|
|
||||||
// Take screenshots
|
for (const pageInfo of pages) {
|
||||||
for (const pageInfo of PAGES) {
|
const url = `${CONFIG.baseUrl}${basePath}${pageInfo.path}`;
|
||||||
const url = `${CONFIG.baseUrl}${CONFIG.adminPath}${pageInfo.path}`;
|
const filename = `${outputPrefix}-${pageInfo.name}.png`;
|
||||||
const filename = `admin-${pageInfo.name}.png`;
|
|
||||||
const filepath = path.join(CONFIG.outputDir, filename);
|
const filepath = path.join(CONFIG.outputDir, filename);
|
||||||
|
|
||||||
console.log(`Taking screenshot: ${pageInfo.description}`);
|
console.log(`Taking screenshot: ${pageInfo.description}`);
|
||||||
@@ -77,17 +94,51 @@ async function takeScreenshots() {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
await page.goto(url, { waitUntil: 'networkidle0', timeout: 30000 });
|
await page.goto(url, { waitUntil: 'networkidle0', timeout: 30000 });
|
||||||
await new Promise(r => setTimeout(r, 3000));
|
await wait(3000);
|
||||||
await page.screenshot({ path: filepath, fullPage: true });
|
await page.screenshot({ path: filepath, fullPage: true });
|
||||||
console.log(` Saved: ${filepath}\n`);
|
console.log(` Saved: ${filepath}\n`);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log(` Error: ${err.message}\n`);
|
console.log(` Error: ${err.message}\n`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error(`${panelName} screenshots failed:`, err.message);
|
||||||
|
} finally {
|
||||||
|
await context.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
console.log('All screenshots completed!');
|
async function takeScreenshots() {
|
||||||
|
console.log('Starting Jabali Panel Screenshot Script...\n');
|
||||||
|
|
||||||
|
browser = await puppeteer.launch({
|
||||||
|
headless: 'new',
|
||||||
|
args: ['--no-sandbox', '--disable-setuid-sandbox', '--ignore-certificate-errors']
|
||||||
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (!CONFIG.skipAdmin) {
|
||||||
|
await capturePanel({
|
||||||
|
panelName: 'Admin',
|
||||||
|
basePath: CONFIG.adminPath,
|
||||||
|
credentials: CONFIG.admin,
|
||||||
|
pages: ADMIN_PAGES,
|
||||||
|
outputPrefix: 'admin'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!CONFIG.skipUser) {
|
||||||
|
await capturePanel({
|
||||||
|
panelName: 'User',
|
||||||
|
basePath: CONFIG.userPath,
|
||||||
|
credentials: CONFIG.user,
|
||||||
|
pages: USER_PAGES,
|
||||||
|
outputPrefix: 'user'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('Screenshot capture completed!');
|
||||||
console.log(`Output directory: ${CONFIG.outputDir}`);
|
console.log(`Output directory: ${CONFIG.outputDir}`);
|
||||||
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('Error:', err.message);
|
console.error('Error:', err.message);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
|
|||||||