überarbeitung backend-code

This commit is contained in:
overcuriousity
2025-07-14 17:34:48 +02:00
parent b842df040c
commit 92dcd2ab74
6 changed files with 303 additions and 141 deletions

View File

@@ -12,28 +12,27 @@ export interface Props {
projectUrl?: string;
license: string;
tags: string[];
isHosted: boolean;
statusUrl?: string;
};
}
const { tool } = Astro.props;
// Determine card styling
const cardClass = tool.isHosted ? 'card card-hosted' : (tool.license !== 'Proprietary' ? 'card card-oss' : 'card');
// Check if tool has a valid project URL for hosted services
// Check if tool has a valid project URL (means we're hosting it)
const hasValidProjectUrl = tool.projectUrl !== undefined &&
tool.projectUrl !== null &&
tool.projectUrl !== "" &&
tool.projectUrl.trim() !== "";
// Determine card styling based on hosting status (derived from projectUrl)
const cardClass = hasValidProjectUrl ? 'card card-hosted' : (tool.license !== 'Proprietary' ? 'card card-oss' : 'card');
---
<div class={cardClass}>
<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>}
{hasValidProjectUrl && <span class="badge badge-primary">Self-Hosted</span>}
{tool.license !== 'Proprietary' && <span class="badge badge-success">Open Source</span>}
</div>
</div>
@@ -81,9 +80,9 @@ const hasValidProjectUrl = tool.projectUrl !== undefined &&
))}
</div>
<!-- Button section - different layouts for hosted vs non-hosted -->
{tool.isHosted && hasValidProjectUrl ? (
<!-- Two buttons for self-hosted tools with both URLs -->
<!-- Button section - dual buttons for hosted tools, single for others -->
{hasValidProjectUrl ? (
<!-- Two buttons for tools we're hosting -->
<div style="display: flex; gap: 0.5rem;">
<a href={tool.url} target="_blank" rel="noopener noreferrer" class="btn btn-secondary" style="flex: 1;">
Project Page
@@ -92,13 +91,8 @@ const hasValidProjectUrl = tool.projectUrl !== undefined &&
Access Service
</a>
</div>
) : tool.isHosted ? (
<!-- Single button for self-hosted tools with only project URL -->
<a href={tool.url} target="_blank" rel="noopener noreferrer" class="btn btn-primary" style="width: 100%;">
Project Page
</a>
) : (
<!-- Single button for non-hosted tools -->
<!-- Single button for tools we're not hosting -->
<a href={tool.url} target="_blank" rel="noopener noreferrer" class="btn btn-primary" style="width: 100%;">
Visit Website
</a>

View File

@@ -207,6 +207,14 @@ const sortedTags = Object.entries(tagFrequency)
window.dispatchEvent(new CustomEvent('toolsFiltered', { detail: filtered }));
}
// Check if tool is hosted (has valid projectUrl)
function isToolHosted(tool) {
return tool.projectUrl !== undefined &&
tool.projectUrl !== null &&
tool.projectUrl !== "" &&
tool.projectUrl.trim() !== "";
}
// Handle tag cloud clicks
function handleTagClick(tagItem) {
const tag = tagItem.getAttribute('data-tag');
@@ -232,7 +240,8 @@ const sortedTags = Object.entries(tagFrequency)
// Apply view-specific filters
if (view === 'hosted') {
const hosted = window.toolsData.filter(tool => tool.isHosted);
// Filter for hosted tools only (tools with valid projectUrl)
const hosted = window.toolsData.filter(tool => isToolHosted(tool));
window.dispatchEvent(new CustomEvent('toolsFiltered', { detail: hosted }));
} else {
filterTools();

View File

@@ -38,26 +38,32 @@ domains.forEach((domain: any) => {
<div id="collaboration-tools-section" style="margin-bottom: 1.5rem;">
<h3 style="margin-bottom: 0.75rem; color: var(--color-text); font-size: 1.125rem;">General Tools for Collaboration</h3>
<div class="collaboration-tools-compact" id="collaboration-tools-container">
{collaborationTools.map((tool: any) => (
<div class={`collaboration-tool-compact ${tool.isHosted ? 'hosted' : tool.license !== 'Proprietary' ? 'oss' : ''}`}
onclick={`window.showToolDetails('${tool.name}')`}>
<div class="tool-compact-header">
<h4 style="margin: 0; font-size: 0.875rem; font-weight: 600;">{tool.name}</h4>
<div style="display: flex; gap: 0.25rem;">
{tool.isHosted && <span class="badge-mini badge-primary">Self-Hosted</span>}
{tool.license !== 'Proprietary' && <span class="badge-mini badge-success">OSS</span>}
{collaborationTools.map((tool: any) => {
const hasValidProjectUrl = tool.projectUrl !== undefined &&
tool.projectUrl !== null &&
tool.projectUrl !== "" &&
tool.projectUrl.trim() !== "";
return (
<div class={`collaboration-tool-compact ${hasValidProjectUrl ? 'hosted' : tool.license !== 'Proprietary' ? 'oss' : ''}`}
onclick={`window.showToolDetails('${tool.name}')`}>
<div class="tool-compact-header">
<h4 style="margin: 0; font-size: 0.875rem; font-weight: 600;">{tool.name}</h4>
<div style="display: flex; gap: 0.25rem;">
{hasValidProjectUrl && <span class="badge-mini badge-primary">Self-Hosted</span>}
{tool.license !== 'Proprietary' && <span class="badge-mini badge-success">OSS</span>}
</div>
</div>
<p style="font-size: 0.75rem; color: var(--color-text-secondary); margin: 0.25rem 0; line-height: 1.3;">
{tool.description}
</p>
<div style="display: flex; gap: 0.75rem; font-size: 0.6875rem; color: var(--color-text-secondary);">
<span>{tool.platforms.join(', ')}</span>
<span>•</span>
<span>{tool.skillLevel}</span>
</div>
</div>
<p style="font-size: 0.75rem; color: var(--color-text-secondary); margin: 0.25rem 0; line-height: 1.3;">
{tool.description}
</p>
<div style="display: flex; gap: 0.75rem; font-size: 0.6875rem; color: var(--color-text-secondary);">
<span>{tool.platforms.join(', ')}</span>
<span>•</span>
<span>{tool.skillLevel}</span>
</div>
</div>
))}
);
})}
</div>
</div>
@@ -79,15 +85,21 @@ domains.forEach((domain: any) => {
<th>{domain.name}</th>
{phases.filter((phase: any) => phase.id !== 'collaboration').map((phase: any) => (
<td class="matrix-cell" data-domain={domain.id} data-phase={phase.id}>
{matrix[domain.id][phase.id].map((tool: any) => (
{matrix[domain.id][phase.id].map((tool: any) => {
const hasValidProjectUrl = tool.projectUrl !== undefined &&
tool.projectUrl !== null &&
tool.projectUrl !== "" &&
tool.projectUrl.trim() !== "";
return (
<span
class={`tool-chip ${tool.isHosted ? 'tool-chip-hosted' : tool.license !== 'Proprietary' ? 'tool-chip-oss' : ''}`}
class={`tool-chip ${hasValidProjectUrl ? 'tool-chip-hosted' : tool.license !== 'Proprietary' ? 'tool-chip-oss' : ''}`}
data-tool-name={tool.name}
onclick={`window.showToolDetails('${tool.name}')`}
>
{tool.name}
</span>
))}
);
})}
</td>
))}
</tr>
@@ -134,8 +146,13 @@ domains.forEach((domain: any) => {
// Badges
const badgesContainer = document.getElementById('tool-badges');
const hasValidProjectUrl = tool.projectUrl !== undefined &&
tool.projectUrl !== null &&
tool.projectUrl !== "" &&
tool.projectUrl.trim() !== "";
badgesContainer.innerHTML = '';
if (tool.isHosted) {
if (hasValidProjectUrl) {
badgesContainer.innerHTML += '<span class="badge badge-primary">Self-Hosted</span>';
}
if (tool.license !== 'Proprietary') {
@@ -165,15 +182,11 @@ domains.forEach((domain: any) => {
</div>
`;
// Links - Updated to handle dual buttons for self-hosted tools
// Links - Updated to handle dual buttons for hosted tools
const linksContainer = document.getElementById('tool-links');
const hasValidProjectUrl = tool.projectUrl !== undefined &&
tool.projectUrl !== null &&
tool.projectUrl !== "" &&
tool.projectUrl.trim() !== "";
if (tool.isHosted && hasValidProjectUrl) {
// Two buttons for self-hosted tools with both URLs
if (hasValidProjectUrl) {
// Two buttons for tools we're hosting
linksContainer.innerHTML = `
<a href="${tool.url}" target="_blank" rel="noopener noreferrer" class="btn btn-secondary" style="flex: 1;">
Project Page
@@ -182,15 +195,8 @@ domains.forEach((domain: any) => {
Access Service
</a>
`;
} else if (tool.isHosted) {
// Single button for self-hosted tools with only project URL
linksContainer.innerHTML = `
<a href="${tool.url}" target="_blank" rel="noopener noreferrer" class="btn btn-primary" style="width: 100%;">
Project Page
</a>
`;
} else {
// Single button for non-hosted tools
// Single button for tools we're not hosting
linksContainer.innerHTML = `
<a href="${tool.url}" target="_blank" rel="noopener noreferrer" class="btn btn-primary" style="width: 100%;">
Visit Website
@@ -263,13 +269,18 @@ domains.forEach((domain: any) => {
// Re-populate with filtered DFIR tools
const filteredDfirTools = filtered.filter(tool => !tool.phases.includes('collaboration'));
filteredDfirTools.forEach(tool => {
const hasValidProjectUrl = tool.projectUrl !== undefined &&
tool.projectUrl !== null &&
tool.projectUrl !== "" &&
tool.projectUrl.trim() !== "";
tool.domains.forEach(domain => {
tool.phases.forEach(phase => {
if (phase !== 'collaboration') {
const cell = document.querySelector(`[data-domain="${domain}"][data-phase="${phase}"]`);
if (cell) {
const chip = document.createElement('span');
chip.className = `tool-chip ${tool.isHosted ? 'tool-chip-hosted' : tool.license !== 'Proprietary' ? 'tool-chip-oss' : ''}`;
chip.className = `tool-chip ${hasValidProjectUrl ? 'tool-chip-hosted' : tool.license !== 'Proprietary' ? 'tool-chip-oss' : ''}`;
chip.textContent = tool.name;
chip.onclick = () => window.showToolDetails(tool.name);
cell.appendChild(chip);
@@ -284,8 +295,13 @@ domains.forEach((domain: any) => {
// Helper function to create compact collaboration tool cards for matrix view
function createCollaborationToolCardCompact(tool) {
const hasValidProjectUrl = tool.projectUrl !== undefined &&
tool.projectUrl !== null &&
tool.projectUrl !== "" &&
tool.projectUrl.trim() !== "";
const cardDiv = document.createElement('div');
const cardClass = `collaboration-tool-compact ${tool.isHosted ? 'hosted' : tool.license !== 'Proprietary' ? 'oss' : ''}`;
const cardClass = `collaboration-tool-compact ${hasValidProjectUrl ? 'hosted' : tool.license !== 'Proprietary' ? 'oss' : ''}`;
cardDiv.className = cardClass;
cardDiv.onclick = () => window.showToolDetails(tool.name);
@@ -293,7 +309,7 @@ domains.forEach((domain: any) => {
<div class="tool-compact-header">
<h4 style="margin: 0; font-size: 0.875rem; font-weight: 600;">${tool.name}</h4>
<div style="display: flex; gap: 0.25rem;">
${tool.isHosted ? '<span class="badge-mini badge-primary">Self-Hosted</span>' : ''}
${hasValidProjectUrl ? '<span class="badge-mini badge-primary">Self-Hosted</span>' : ''}
${tool.license !== 'Proprietary' ? '<span class="badge-mini badge-success">OSS</span>' : ''}
</div>
</div>