change framework
This commit is contained in:
53
src/pages/about.astro
Normal file
53
src/pages/about.astro
Normal file
@@ -0,0 +1,53 @@
|
||||
---
|
||||
import BaseLayout from '../layouts/BaseLayout.astro';
|
||||
---
|
||||
|
||||
<BaseLayout title="About">
|
||||
<section style="padding: 2rem 0; max-width: 800px; margin: 0 auto;">
|
||||
<h1 style="text-align: center; margin-bottom: 2rem;">About DFIR Tools Hub</h1>
|
||||
|
||||
<div class="card" style="margin-bottom: 2rem;">
|
||||
<h2>Project Overview</h2>
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
|
||||
</p>
|
||||
<p>
|
||||
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="card" style="margin-bottom: 2rem;">
|
||||
<h2>DFIR Methodology</h2>
|
||||
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit:</p>
|
||||
<ul style="margin-left: 1.5rem; margin-bottom: 1rem;">
|
||||
<li><strong>Data Collection:</strong> Lorem ipsum dolor sit amet</li>
|
||||
<li><strong>Examination:</strong> Consectetur adipiscing elit</li>
|
||||
<li><strong>Analysis:</strong> Sed do eiusmod tempor incididunt</li>
|
||||
<li><strong>Reporting:</strong> Ut labore et dolore magna aliqua</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="card" style="margin-bottom: 2rem;">
|
||||
<h2>Forensic Domains</h2>
|
||||
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit:</p>
|
||||
<ul style="margin-left: 1.5rem;">
|
||||
<li>Storage & File System Artifacts</li>
|
||||
<li>Memory & Runtime Artifacts</li>
|
||||
<li>Network & Communication Artifacts</li>
|
||||
<li>Application & Code Artifacts</li>
|
||||
<li>Multimedia & Content Artifacts</li>
|
||||
<li>Transaction & Financial Artifacts</li>
|
||||
<li>Platform & Infrastructure Artifacts</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h2>Contributing</h2>
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
|
||||
Visit our <a href="https://github.com/your-org/dfir-tools-hub" target="_blank" rel="noopener noreferrer">GitHub repository</a>
|
||||
to contribute or report issues.
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
</BaseLayout>
|
||||
163
src/pages/index.astro
Normal file
163
src/pages/index.astro
Normal file
@@ -0,0 +1,163 @@
|
||||
---
|
||||
import BaseLayout from '../layouts/BaseLayout.astro';
|
||||
import ToolCard from '../components/ToolCard.astro';
|
||||
import ToolFilters from '../components/ToolFilters.astro';
|
||||
import ToolMatrix from '../components/ToolMatrix.astro';
|
||||
import { promises as fs } from 'fs';
|
||||
import { load } from 'js-yaml';
|
||||
import path from 'path';
|
||||
|
||||
// Load tools data
|
||||
const yamlPath = path.join(process.cwd(), 'src/data/tools.yaml');
|
||||
const yamlContent = await fs.readFile(yamlPath, 'utf8');
|
||||
const data = load(yamlContent) as any;
|
||||
const tools = data.tools;
|
||||
---
|
||||
|
||||
<BaseLayout title="Home">
|
||||
<!-- Hero Section -->
|
||||
<section style="text-align: center; padding: 3rem 0; border-bottom: 1px solid var(--color-border);">
|
||||
<h1 style="margin-bottom: 1rem;">DFIR Tools Hub</h1>
|
||||
<p class="text-muted" style="font-size: 1.125rem; max-width: 800px; margin: 0 auto;">
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<!-- Filters Section -->
|
||||
<section style="padding: 2rem 0;">
|
||||
<ToolFilters />
|
||||
</section>
|
||||
|
||||
<!-- Tools Grid -->
|
||||
<section id="tools-grid" style="padding-bottom: 2rem;">
|
||||
<div class="grid grid-cols-3 gap-4" id="tools-container">
|
||||
{tools.map((tool: any) => (
|
||||
<ToolCard tool={tool} />
|
||||
))}
|
||||
</div>
|
||||
|
||||
<!-- No results message -->
|
||||
<div id="no-results" style="display: none; text-align: center; padding: 4rem 0;">
|
||||
<p class="text-muted" style="font-size: 1.125rem;">No tools found matching your criteria.</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Matrix View -->
|
||||
<ToolMatrix />
|
||||
</BaseLayout>
|
||||
|
||||
<script>
|
||||
// Handle view changes and filtering
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
const toolsContainer = document.getElementById('tools-container');
|
||||
const toolsGrid = document.getElementById('tools-grid');
|
||||
const matrixContainer = document.getElementById('matrix-container');
|
||||
const noResults = document.getElementById('no-results');
|
||||
|
||||
// Initial tools HTML
|
||||
const initialToolsHTML = toolsContainer.innerHTML;
|
||||
|
||||
// Handle filtered results
|
||||
window.addEventListener('toolsFiltered', (event) => {
|
||||
const filtered = event.detail;
|
||||
const currentView = document.querySelector('.view-toggle.active')?.getAttribute('data-view');
|
||||
|
||||
if (currentView === 'matrix') {
|
||||
// Matrix view handles its own rendering
|
||||
return;
|
||||
}
|
||||
|
||||
// Clear container
|
||||
toolsContainer.innerHTML = '';
|
||||
|
||||
if (filtered.length === 0) {
|
||||
noResults.style.display = 'block';
|
||||
} else {
|
||||
noResults.style.display = 'none';
|
||||
|
||||
// Render filtered tools
|
||||
filtered.forEach(tool => {
|
||||
const toolCard = createToolCard(tool);
|
||||
toolsContainer.appendChild(toolCard);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Handle view changes
|
||||
window.addEventListener('viewChanged', (event) => {
|
||||
const view = event.detail;
|
||||
|
||||
if (view === 'matrix') {
|
||||
toolsGrid.style.display = 'none';
|
||||
matrixContainer.style.display = 'block';
|
||||
} else {
|
||||
toolsGrid.style.display = 'block';
|
||||
matrixContainer.style.display = 'none';
|
||||
}
|
||||
});
|
||||
|
||||
// Create tool card element
|
||||
function createToolCard(tool) {
|
||||
const cardDiv = document.createElement('div');
|
||||
const cardClass = tool.isHosted ? 'card card-hosted' : (tool.license !== 'Proprietary' ? 'card card-oss' : 'card');
|
||||
cardDiv.className = cardClass;
|
||||
|
||||
cardDiv.innerHTML = `
|
||||
<div style="display: flex; justify-content: space-between; align-items: start; margin-bottom: 0.75rem;">
|
||||
<h3 style="margin: 0;">${tool.name}</h3>
|
||||
<div style="display: flex; gap: 0.5rem;">
|
||||
${tool.isHosted ? '<span class="badge badge-primary">Self-Hosted</span>' : ''}
|
||||
${tool.license !== 'Proprietary' ? '<span class="badge badge-success">Open Source</span>' : ''}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p class="text-muted" style="font-size: 0.875rem; margin-bottom: 1rem;">
|
||||
${tool.description}
|
||||
</p>
|
||||
|
||||
<div style="display: flex; flex-wrap: wrap; gap: 0.5rem; margin-bottom: 1rem;">
|
||||
<div style="display: flex; align-items: center; gap: 0.25rem;">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<rect x="3" y="3" width="18" height="18" rx="2" ry="2"></rect>
|
||||
<line x1="9" y1="9" x2="15" y2="9"></line>
|
||||
<line x1="9" y1="15" x2="15" y2="15"></line>
|
||||
</svg>
|
||||
<span class="text-muted" style="font-size: 0.75rem;">
|
||||
${tool.platforms.join(', ')}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div style="display: flex; align-items: center; gap: 0.25rem;">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<circle cx="12" cy="12" r="10"></circle>
|
||||
<path d="M12 6v6l4 2"></path>
|
||||
</svg>
|
||||
<span class="text-muted" style="font-size: 0.75rem;">
|
||||
${tool.skillLevel}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div style="display: flex; align-items: center; gap: 0.25rem;">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
|
||||
<polyline points="14 2 14 8 20 8"></polyline>
|
||||
</svg>
|
||||
<span class="text-muted" style="font-size: 0.75rem;">
|
||||
${tool.license}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="display: flex; flex-wrap: wrap; gap: 0.25rem; margin-bottom: 1rem;">
|
||||
${tool.tags.map(tag => `<span class="tag">${tag}</span>`).join('')}
|
||||
</div>
|
||||
|
||||
<a href="${tool.url}" target="_blank" rel="noopener noreferrer" class="btn btn-primary" style="width: 100%;">
|
||||
${tool.isHosted ? 'Access Service' : 'Visit Website'}
|
||||
</a>
|
||||
`;
|
||||
|
||||
return cardDiv;
|
||||
}
|
||||
});
|
||||
</script>
|
||||
83
src/pages/status.astro
Normal file
83
src/pages/status.astro
Normal file
@@ -0,0 +1,83 @@
|
||||
---
|
||||
import BaseLayout from '../layouts/BaseLayout.astro';
|
||||
import { promises as fs } from 'fs';
|
||||
import { load } from 'js-yaml';
|
||||
import path from 'path';
|
||||
|
||||
// Load tools data to get self-hosted services
|
||||
const yamlPath = path.join(process.cwd(), 'src/data/tools.yaml');
|
||||
const yamlContent = await fs.readFile(yamlPath, 'utf8');
|
||||
const data = load(yamlContent) as any;
|
||||
const hostedServices = data.tools.filter((tool: any) => tool.isHosted);
|
||||
---
|
||||
|
||||
<BaseLayout title="Service Status">
|
||||
<section style="padding: 2rem 0;">
|
||||
<h1 style="text-align: center; margin-bottom: 1rem;">Service Status</h1>
|
||||
<p class="text-muted" style="text-align: center; max-width: 600px; margin: 0 auto 3rem;">
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Real-time monitoring of our self-hosted DFIR services.
|
||||
</p>
|
||||
|
||||
<!-- Service Status Grid -->
|
||||
<div class="grid grid-cols-2 gap-4" style="margin-bottom: 3rem;">
|
||||
{hostedServices.map((service: any) => (
|
||||
<div class="card">
|
||||
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 1rem;">
|
||||
<h3 style="margin: 0;">{service.name}</h3>
|
||||
<div id={`status-${service.name.toLowerCase().replace(/\s+/g, '-')}`}>
|
||||
<!-- Status badge will be inserted here -->
|
||||
<span class="badge badge-warning">Loading...</span>
|
||||
</div>
|
||||
</div>
|
||||
<p class="text-muted" style="font-size: 0.875rem; margin-bottom: 1rem;">
|
||||
{service.description}
|
||||
</p>
|
||||
<a href={service.url} target="_blank" rel="noopener noreferrer" class="btn btn-secondary">
|
||||
Access Service →
|
||||
</a>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<!-- Uptime Kuma Embed -->
|
||||
<div class="card" style="padding: 0; overflow: hidden;">
|
||||
<iframe
|
||||
src="https://uptime.example.lab/status/lab-services"
|
||||
style="width: 100%; height: 600px; border: none;"
|
||||
title="Uptime Kuma Status Page"
|
||||
></iframe>
|
||||
</div>
|
||||
</section>
|
||||
</BaseLayout>
|
||||
|
||||
<script define:vars={{ hostedServices }}>
|
||||
// Fetch status for each service
|
||||
document.addEventListener('DOMContentLoaded', async () => {
|
||||
for (const service of hostedServices) {
|
||||
if (service.statusUrl) {
|
||||
try {
|
||||
// Fetch status badge/API endpoint
|
||||
const response = await fetch(service.statusUrl);
|
||||
const data = await response.json();
|
||||
|
||||
// Update status badge
|
||||
const statusElement = document.getElementById(`status-${service.name.toLowerCase().replace(/\s+/g, '-')}`);
|
||||
if (statusElement) {
|
||||
const isUp = data.status === 'up' || data.status === 1;
|
||||
statusElement.innerHTML = `
|
||||
<span class="badge ${isUp ? 'badge-success' : 'badge-error'}">
|
||||
${isUp ? 'Operational' : 'Down'}
|
||||
</span>
|
||||
`;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`Failed to fetch status for ${service.name}:`, error);
|
||||
const statusElement = document.getElementById(`status-${service.name.toLowerCase().replace(/\s+/g, '-')}`);
|
||||
if (statusElement) {
|
||||
statusElement.innerHTML = '<span class="badge badge-warning">Unknown</span>';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
Reference in New Issue
Block a user