|
|
|
|
@@ -14,11 +14,11 @@ const tools = data.tools;
|
|
|
|
|
|
|
|
|
|
// Separate collaboration tools from domain-specific tools
|
|
|
|
|
const collaborationTools = tools.filter((tool: any) =>
|
|
|
|
|
tool.phases.includes('collaboration')
|
|
|
|
|
tool.phases && tool.phases.includes('collaboration')
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
const domainTools = tools.filter((tool: any) =>
|
|
|
|
|
!tool.phases.includes('collaboration')
|
|
|
|
|
!tool.phases || !tool.phases.includes('collaboration')
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// Create matrix structure for domain-specific tools only
|
|
|
|
|
@@ -27,7 +27,7 @@ domains.forEach((domain: any) => {
|
|
|
|
|
matrix[domain.id] = {};
|
|
|
|
|
phases.filter((phase: any) => phase.id !== 'collaboration').forEach((phase: any) => {
|
|
|
|
|
matrix[domain.id][phase.id] = domainTools.filter((tool: any) =>
|
|
|
|
|
tool.domains.includes(domain.id) && tool.phases.includes(phase.id)
|
|
|
|
|
tool.domains && tool.domains.includes(domain.id) && tool.phases && tool.phases.includes(phase.id)
|
|
|
|
|
);
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
@@ -51,6 +51,7 @@ domains.forEach((domain: any) => {
|
|
|
|
|
<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>}
|
|
|
|
|
{tool.knowledgebase === true && <span class="badge-mini badge-error">Infos 📖</span>}
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<p style="font-size: 0.75rem; color: var(--color-text-secondary); margin: 0.25rem 0; line-height: 1.3;">
|
|
|
|
|
@@ -95,8 +96,10 @@ domains.forEach((domain: any) => {
|
|
|
|
|
class={`tool-chip ${hasValidProjectUrl ? 'tool-chip-hosted' : tool.license !== 'Proprietary' ? 'tool-chip-oss' : ''}`}
|
|
|
|
|
data-tool-name={tool.name}
|
|
|
|
|
onclick={`window.showToolDetails('${tool.name}')`}
|
|
|
|
|
title={`${tool.name}${tool.knowledgebase === true ? ' (KB verfügbar)' : ''}`}
|
|
|
|
|
>
|
|
|
|
|
{tool.name}
|
|
|
|
|
{tool.knowledgebase === true && <span style="margin-left: 0.25rem; font-size: 0.6875rem;">📖</span>}
|
|
|
|
|
</span>
|
|
|
|
|
);
|
|
|
|
|
})}
|
|
|
|
|
@@ -131,7 +134,7 @@ domains.forEach((domain: any) => {
|
|
|
|
|
<div id="tool-tags" style="margin-bottom: 1rem;"></div>
|
|
|
|
|
|
|
|
|
|
<!-- Updated button container for dual buttons -->
|
|
|
|
|
<div id="tool-links" style="display: flex; gap: 0.5rem;"></div>
|
|
|
|
|
<div id="tool-links" style="display: flex; gap: 0.5rem; flex-direction: column;"></div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<script define:vars={{ toolsData: tools, collaborationTools, domainTools }}>
|
|
|
|
|
@@ -205,13 +208,14 @@ domains.forEach((domain: any) => {
|
|
|
|
|
<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>' : ''}
|
|
|
|
|
${tool.knowledgebase === true ? '<span class="badge-mini badge-error">Infos 📖</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>${(tool.platforms || []).join(', ')}</span>
|
|
|
|
|
<span>•</span>
|
|
|
|
|
<span>${tool.skillLevel}</span>
|
|
|
|
|
</div>
|
|
|
|
|
@@ -243,14 +247,19 @@ domains.forEach((domain: any) => {
|
|
|
|
|
if (tool.license !== 'Proprietary') {
|
|
|
|
|
badgesContainer.innerHTML += '<span class="badge badge-success">Open Source</span>';
|
|
|
|
|
}
|
|
|
|
|
if (tool.knowledgebase === true) {
|
|
|
|
|
badgesContainer.innerHTML += '<span class="badge badge-error">Infos 📖</span>';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Metadata
|
|
|
|
|
// Metadata - safe array handling
|
|
|
|
|
const metadataContainer = document.getElementById('tool-metadata');
|
|
|
|
|
const domainsText = tool.domains.length > 0 ? tool.domains.join(', ') : 'Domain-agnostic';
|
|
|
|
|
const phasesText = tool.phases.join(', ');
|
|
|
|
|
const domains = tool.domains || [];
|
|
|
|
|
const phases = tool.phases || [];
|
|
|
|
|
const domainsText = domains.length > 0 ? domains.join(', ') : 'Domain-agnostic';
|
|
|
|
|
const phasesText = phases.join(', ');
|
|
|
|
|
metadataContainer.innerHTML = `
|
|
|
|
|
<div style="display: grid; gap: 0.5rem;">
|
|
|
|
|
<div><strong>Betriebssystem:</strong> ${tool.platforms.join(', ')}</div>
|
|
|
|
|
<div><strong>Betriebssystem:</strong> ${(tool.platforms || []).join(', ')}</div>
|
|
|
|
|
<div><strong>Skill Level:</strong> ${tool.skillLevel}</div>
|
|
|
|
|
<div><strong>Lizenzmodell:</strong> ${tool.license}</div>
|
|
|
|
|
<div><strong>Deployment:</strong> ${tool.accessType}</div>
|
|
|
|
|
@@ -259,36 +268,61 @@ domains.forEach((domain: any) => {
|
|
|
|
|
</div>
|
|
|
|
|
`;
|
|
|
|
|
|
|
|
|
|
// Tags
|
|
|
|
|
// Tags - safe array handling
|
|
|
|
|
const tagsContainer = document.getElementById('tool-tags');
|
|
|
|
|
const tags = tool.tags || [];
|
|
|
|
|
tagsContainer.innerHTML = `
|
|
|
|
|
<div style="display: flex; flex-wrap: wrap; gap: 0.25rem;">
|
|
|
|
|
${tool.tags.map(tag => `<span class="tag">${tag}</span>`).join('')}
|
|
|
|
|
${tags.map(tag => `<span class="tag">${tag}</span>`).join('')}
|
|
|
|
|
</div>
|
|
|
|
|
`;
|
|
|
|
|
|
|
|
|
|
// Links - Updated to handle dual buttons for hosted tools
|
|
|
|
|
// Links - Updated to handle dual buttons for hosted tools AND knowledgebase links
|
|
|
|
|
const linksContainer = document.getElementById('tool-links');
|
|
|
|
|
|
|
|
|
|
let linksHTML = '';
|
|
|
|
|
|
|
|
|
|
// Main action buttons
|
|
|
|
|
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;">
|
|
|
|
|
Software-Homepage
|
|
|
|
|
</a>
|
|
|
|
|
<a href="${tool.projectUrl}" target="_blank" rel="noopener noreferrer" class="btn btn-primary" style="flex: 1;">
|
|
|
|
|
Zugreifen
|
|
|
|
|
</a>
|
|
|
|
|
linksHTML += `
|
|
|
|
|
<div style="display: flex; gap: 0.5rem;">
|
|
|
|
|
<a href="${tool.url}" target="_blank" rel="noopener noreferrer" class="btn btn-secondary" style="flex: 1;">
|
|
|
|
|
Software-Homepage
|
|
|
|
|
</a>
|
|
|
|
|
<a href="${tool.projectUrl}" target="_blank" rel="noopener noreferrer" class="btn btn-primary" style="flex: 1;">
|
|
|
|
|
Zugreifen
|
|
|
|
|
</a>
|
|
|
|
|
</div>
|
|
|
|
|
`;
|
|
|
|
|
} else {
|
|
|
|
|
// Single button for tools we're not hosting
|
|
|
|
|
linksContainer.innerHTML = `
|
|
|
|
|
linksHTML += `
|
|
|
|
|
<a href="${tool.url}" target="_blank" rel="noopener noreferrer" class="btn btn-primary" style="width: 100%;">
|
|
|
|
|
Software-Homepage
|
|
|
|
|
</a>
|
|
|
|
|
`;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Add knowledgebase link if available
|
|
|
|
|
if (tool.knowledgebase === true) {
|
|
|
|
|
const kbId = tool.name.toLowerCase().replace(/\s+/g, '-');
|
|
|
|
|
linksHTML += `
|
|
|
|
|
<a href="/knowledgebase#kb-${kbId}" class="btn btn-secondary" style="width: 100%; margin-top: 0.5rem;">
|
|
|
|
|
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="margin-right: 0.5rem;">
|
|
|
|
|
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/>
|
|
|
|
|
<polyline points="14 2 14 8 20 8"/>
|
|
|
|
|
<line x1="16" y1="13" x2="8" y2="13"/>
|
|
|
|
|
<line x1="16" y1="17" x2="8" y2="17"/>
|
|
|
|
|
<polyline points="10 9 9 9 8 9"/>
|
|
|
|
|
</svg>
|
|
|
|
|
Knowledgebase anzeigen
|
|
|
|
|
</a>
|
|
|
|
|
`;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
linksContainer.innerHTML = linksHTML;
|
|
|
|
|
|
|
|
|
|
// Show modal
|
|
|
|
|
document.getElementById('modal-overlay').classList.add('active');
|
|
|
|
|
document.getElementById('tool-details').classList.add('active');
|
|
|
|
|
@@ -336,7 +370,7 @@ domains.forEach((domain: any) => {
|
|
|
|
|
dfirMatrixSection.style.display = 'none';
|
|
|
|
|
|
|
|
|
|
// Filter collaboration tools
|
|
|
|
|
const filteredCollaboration = filtered.filter(tool => tool.phases.includes('collaboration'));
|
|
|
|
|
const filteredCollaboration = filtered.filter(tool => (tool.phases || []).includes('collaboration'));
|
|
|
|
|
collaborationContainer.innerHTML = '';
|
|
|
|
|
|
|
|
|
|
filteredCollaboration.forEach(tool => {
|
|
|
|
|
@@ -352,7 +386,7 @@ domains.forEach((domain: any) => {
|
|
|
|
|
collaborationSection.style.display = 'block';
|
|
|
|
|
|
|
|
|
|
// Show all collaboration tools that pass general filters
|
|
|
|
|
const filteredCollaboration = filtered.filter(tool => tool.phases.includes('collaboration'));
|
|
|
|
|
const filteredCollaboration = filtered.filter(tool => (tool.phases || []).includes('collaboration'));
|
|
|
|
|
collaborationContainer.innerHTML = '';
|
|
|
|
|
|
|
|
|
|
filteredCollaboration.forEach(tool => {
|
|
|
|
|
@@ -369,22 +403,26 @@ domains.forEach((domain: any) => {
|
|
|
|
|
cell.innerHTML = '';
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Re-populate with filtered DFIR tools
|
|
|
|
|
const filteredDfirTools = filtered.filter(tool => !tool.phases.includes('collaboration'));
|
|
|
|
|
// Re-populate with filtered DFIR tools - with safe array handling
|
|
|
|
|
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 => {
|
|
|
|
|
const domains = tool.domains || [];
|
|
|
|
|
const phases = tool.phases || [];
|
|
|
|
|
|
|
|
|
|
domains.forEach(domain => {
|
|
|
|
|
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 ${hasValidProjectUrl ? 'tool-chip-hosted' : tool.license !== 'Proprietary' ? 'tool-chip-oss' : ''}`;
|
|
|
|
|
chip.textContent = tool.name;
|
|
|
|
|
chip.setAttribute('title', `${tool.name}${tool.knowledgebase === true ? ' (KB verfügbar)' : ''}`);
|
|
|
|
|
chip.innerHTML = `${tool.name}${tool.knowledgebase === true ? '<span style="margin-left: 0.25rem; font-size: 0.6875rem;">📖</span>' : ''}`;
|
|
|
|
|
chip.onclick = () => window.showToolDetails(tool.name);
|
|
|
|
|
cell.appendChild(chip);
|
|
|
|
|
}
|
|
|
|
|
|