finalize methods implementation

This commit is contained in:
overcuriousity
2025-07-19 18:54:31 +02:00
parent 1d048e816c
commit a8cc30d5ac
7 changed files with 245 additions and 33 deletions

View File

@@ -2,6 +2,7 @@
export interface Props {
tool: {
name: string;
type?: string;
description: string;
domains: string[];
phases: string[];
@@ -19,6 +20,9 @@ export interface Props {
const { tool } = Astro.props;
// Check if this is a method vs software
const isMethod = tool.type === 'method';
// Check if tool has a valid project URL (means we're hosting it)
const hasValidProjectUrl = tool.projectUrl !== undefined &&
tool.projectUrl !== null &&
@@ -28,19 +32,22 @@ const hasValidProjectUrl = tool.projectUrl !== undefined &&
// Check if tool has knowledgebase entry
const hasKnowledgebase = tool.knowledgebase === true;
// Determine card styling based on hosting status (derived from projectUrl)
const cardClass = hasValidProjectUrl ? 'card card-hosted tool-card' : (tool.license !== 'Proprietary' ? 'card card-oss tool-card' : 'card tool-card');
// Determine card styling based on type and hosting status
const cardClass = isMethod ? 'card card-method tool-card' :
hasValidProjectUrl ? 'card card-hosted tool-card' :
(tool.license !== 'Proprietary' ? 'card card-oss tool-card' : 'card tool-card');
---
<div class={cardClass} onclick={`window.showToolDetails('${tool.name}')`} style="cursor: pointer; border-left: 4px solid ${hasValidProjectUrl ? 'var(--color-hosted)' : tool.license !== 'Proprietary' ? 'var(--color-oss)' : 'var(--color-border)'};">
<!-- Card Header with Fixed Height -->
<div class={cardClass} onclick={`window.showToolDetails('${tool.name}')`} style="cursor: pointer; border-left: 4px solid ${isMethod ? 'var(--color-method)' : hasValidProjectUrl ? 'var(--color-hosted)' : tool.license !== 'Proprietary' ? 'var(--color-oss)' : 'var(--color-border)'};">
<!-- Card Header with Fixed Height -->
<div class="tool-card-header">
<h3>{tool.name}</h3>
<div class="tool-card-badges">
{hasValidProjectUrl && <span class="badge badge-primary">CC24-Server</span>}
{tool.license !== 'Proprietary' && <span class="badge badge-success">OSS</span>}
{hasKnowledgebase && <span class="badge badge-error">📖</span>}
</div>
<div class="tool-card-badges">
{isMethod && <span class="badge" style="background-color: var(--color-method); color: white;">Methode</span>}
{!isMethod && hasValidProjectUrl && <span class="badge badge-primary">Self-Hosted</span>}
{!isMethod && tool.license !== 'Proprietary' && <span class="badge badge-success">OSS</span>}
{hasKnowledgebase && <span class="badge badge-error">📖</span>}
</div>
</div>
<!-- Description - Truncated to 2 lines -->
@@ -77,7 +84,7 @@ const cardClass = hasValidProjectUrl ? 'card card-hosted tool-card' : (tool.lice
<polyline points="14 2 14 8 20 8"></polyline>
</svg>
<span style="overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0;">
{tool.license === 'Proprietary' ? 'Prop.' : tool.license.split(' ')[0]}
{isMethod ? 'Methode' : tool.license === 'Proprietary' ? 'Prop.' : tool.license?.split(' ')[0]}
</span>
</div>
</div>
@@ -91,7 +98,12 @@ const cardClass = hasValidProjectUrl ? 'card card-hosted tool-card' : (tool.lice
<!-- Buttons - Fixed at Bottom -->
<div class="tool-card-buttons" onclick="event.stopPropagation();">
{hasValidProjectUrl ? (
{isMethod ? (
<!-- Method button -->
<a href={tool.projectUrl || tool.url} target="_blank" rel="noopener noreferrer" class="btn btn-primary single-button" style="background-color: var(--color-method); border-color: var(--color-method);">
Zur Methode
</a>
) : hasValidProjectUrl ? (
<!-- Two buttons for hosted tools -->
<div class="button-row">
<a href={tool.url} target="_blank" rel="noopener noreferrer" class="btn btn-secondary">

View File

@@ -251,6 +251,11 @@ const sortedTags = Object.entries(tagFrequency)
tool.projectUrl.trim() !== "";
}
// Check if item is a method
function isMethod(tool) {
return tool.type === 'method';
}
// Update matrix highlighting based on current filters
function updateMatrixHighlighting() {
const currentView = document.querySelector('.view-toggle.active')?.getAttribute('data-view');
@@ -324,8 +329,8 @@ const sortedTags = Object.entries(tagFrequency)
return false;
}
// Proprietary filter
if (!includeProprietary && tool.license === 'Proprietary') {
// Proprietary filter (skip for methods since they don't have licenses)
if (!includeProprietary && !isMethod(tool) && tool.license === 'Proprietary') {
return false;
}
@@ -337,21 +342,30 @@ const sortedTags = Object.entries(tagFrequency)
return true;
});
// Sort filtered results: server-based first, proprietary last
// Sort filtered results: methods first, then self-hosted, then OSS, proprietary last
filtered.sort((a, b) => {
const aMethod = isMethod(a);
const bMethod = isMethod(b);
const aHosted = isToolHosted(a);
const bHosted = isToolHosted(b);
const aProprietary = a.license === 'Proprietary';
const bProprietary = b.license === 'Proprietary';
const aProprietary = !aMethod && a.license === 'Proprietary';
const bProprietary = !bMethod && b.license === 'Proprietary';
// Self-hosted tools first (regardless of license)
if (aHosted && !bHosted) return -1;
if (!aHosted && bHosted) return 1;
// Methods first
//if (aMethod && !bMethod) return -1;
//if (!aMethod && bMethod) return 1;
// If both have same hosting status, proprietary tools go last
if (aHosted === bHosted) {
if (!aProprietary && bProprietary) return -1;
if (aProprietary && !bProprietary) return 1;
// If both are methods or both are tools
if (aMethod === bMethod) {
// Self-hosted tools first (regardless of license)
if (aHosted && !bHosted) return -1;
if (!aHosted && bHosted) return 1;
// If both have same hosting status, proprietary tools go last
if (aHosted === bHosted) {
if (!aProprietary && bProprietary) return -1;
if (aProprietary && !bProprietary) return 1;
}
}
return 0;
@@ -359,7 +373,6 @@ const sortedTags = Object.entries(tagFrequency)
// Update matrix highlighting
updateMatrixHighlighting();
// Emit custom event with filtered results
window.dispatchEvent(new CustomEvent('toolsFiltered', { detail: filtered }));
}

View File

@@ -107,13 +107,17 @@ domains.forEach((domain: any) => {
{phases.map((phase: any) => (
<td class="matrix-cell" data-domain={domain.id} data-phase={phase.id}>
{matrix[domain.id][phase.id].map((tool: any) => {
const isMethod = tool.type === 'method';
const hasValidProjectUrl = tool.projectUrl !== undefined &&
tool.projectUrl !== null &&
tool.projectUrl !== "" &&
tool.projectUrl.trim() !== "";
const chipClass = isMethod ? 'tool-chip-method' :
hasValidProjectUrl ? 'tool-chip-hosted' :
tool.license !== 'Proprietary' ? 'tool-chip-oss' : '';
return (
<span
class={`tool-chip ${hasValidProjectUrl ? 'tool-chip-hosted' : tool.license !== 'Proprietary' ? 'tool-chip-oss' : ''}`}
class={`tool-chip ${chipClass}`}
data-tool-name={tool.name}
onclick={`window.showToolDetails('${tool.name}')`}
title={`${tool.name}${tool.knowledgebase === true ? ' (KB verfügbar)' : ''}`}
@@ -392,6 +396,7 @@ domains.forEach((domain: any) => {
// Re-populate with filtered tools based on domains × phases
filtered.forEach(tool => {
const isMethod = tool.type === 'method';
const hasValidProjectUrl = tool.projectUrl !== undefined &&
tool.projectUrl !== null &&
tool.projectUrl !== "" &&
@@ -405,7 +410,10 @@ domains.forEach((domain: any) => {
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' : ''}`;
const chipClass = isMethod ? 'tool-chip-method' :
hasValidProjectUrl ? 'tool-chip-hosted' :
tool.license !== 'Proprietary' ? 'tool-chip-oss' : '';
chip.className = `tool-chip ${chipClass}`;
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);