first draft enhancement 2

This commit is contained in:
overcuriousity
2025-08-05 13:03:33 +02:00
parent c267681e7d
commit 99117e8e7a
7 changed files with 714 additions and 67 deletions

View File

@@ -1,5 +1,6 @@
---
import { getToolsData } from '../utils/dataService.js';
import { isToolHosted } from '../utils/toolHelpers.js';
const data = await getToolsData();
const tools = data.tools;
@@ -698,7 +699,10 @@ class AIQueryInterface {
if (fullTool) {
toolsByPhase[recTool.phase].push({
...fullTool,
recommendation: recTool
recommendation: recTool,
confidence: recTool.confidence,
justification: recTool.justification,
priority: recTool.priority
});
}
}
@@ -999,6 +1003,151 @@ class AIQueryInterface {
return String(data);
}
renderConfidenceIndicator(confidence) {
if (!confidence || typeof confidence.overall !== 'number') return '';
const confidenceColor = confidence.overall >= 80 ? 'var(--color-accent)' :
confidence.overall >= 60 ? 'var(--color-warning)' : 'var(--color-error)';
const strengthText = confidence.overall >= 80 ? 'HOCH' :
confidence.overall >= 60 ? 'MITTEL' : 'NIEDRIG';
return `
<div class="confidence-indicator-integrated" style="display: flex; align-items: center; gap: 0.5rem; margin-bottom: 0.75rem;">
<div class="confidence-bar-wrapper" style="flex: 1; height: 4px; background-color: var(--color-bg-tertiary); border-radius: 2px; overflow: hidden;">
<div class="confidence-bar-fill" style="width: ${confidence.overall}%; height: 100%; background-color: ${confidenceColor}; transition: var(--transition-fast);"></div>
</div>
<div class="confidence-badge-compact" style="display: flex; align-items: center; gap: 0.375rem;">
<span class="badge badge-mini" style="background-color: ${confidenceColor}; color: white; font-weight: 600; font-size: 0.625rem;">
${confidence.overall}%
</span>
<button class="btn-icon" style="width: 16px; height: 16px; padding: 0.125rem; font-size: 0.625rem;" onclick="this.parentElement.nextElementSibling.style.display = this.parentElement.nextElementSibling.style.display === 'none' ? 'block' : 'none'; this.textContent = this.textContent === '' ? '✕' : '';" title="Vertrauens-Details"></button>
</div>
<div style="display: none; position: absolute; z-index: 20; background: var(--color-bg); border: 1px solid var(--color-border); border-radius: 0.5rem; padding: 1rem; margin-top: 6rem; right: 0; min-width: 320px; box-shadow: var(--shadow-lg);" class="confidence-details-popup">
<div style="margin-bottom: 0.75rem;">
<div style="display: flex; justify-content: between; align-items: center; margin-bottom: 0.5rem;">
<strong class="text-sm">Vertrauens-Komponenten</strong>
<span class="badge badge-mini" style="background-color: ${confidenceColor}; color: white;">${strengthText}</span>
</div>
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 0.5rem; font-size: 0.75rem;">
<div style="display: flex; justify-content: space-between; padding: 0.25rem; background: var(--color-bg-secondary); border-radius: 0.25rem;">
<span>Ähnlichkeit:</span>
<span class="font-semibold">${confidence.embeddingsQuality}%</span>
</div>
<div style="display: flex; justify-content: space-between; padding: 0.25rem; background: var(--color-bg-secondary); border-radius: 0.25rem;">
<span>Domain:</span>
<span class="font-semibold">${confidence.domainAlignment}%</span>
</div>
<div style="display: flex; justify-content: space-between; padding: 0.25rem; background: var(--color-bg-secondary); border-radius: 0.25rem;">
<span>Konsens:</span>
<span class="font-semibold">${confidence.consensus}%</span>
</div>
<div style="display: flex; justify-content: space-between; padding: 0.25rem; background: var(--color-bg-secondary); border-radius: 0.25rem;">
<span>Aktualität:</span>
<span class="font-semibold">${confidence.freshness}%</span>
</div>
</div>
</div>
${confidence.strengthIndicators && confidence.strengthIndicators.length > 0 ? `
<div style="margin-bottom: 0.75rem;">
<strong class="text-accent" style="font-size: 0.75rem;">✓ Stärken:</strong>
<ul style="font-size: 0.6875rem; margin-top: 0.25rem; padding-left: 1rem; line-height: 1.3;">
${confidence.strengthIndicators.slice(0, 2).map(strength => `<li style="margin-bottom: 0.25rem;">${this.sanitizeText(strength)}</li>`).join('')}
</ul>
</div>
` : ''}
${confidence.uncertaintyFactors && confidence.uncertaintyFactors.length > 0 ? `
<div style="padding-top: 0.75rem; border-top: 1px solid var(--color-border);">
<strong class="text-warning" style="font-size: 0.75rem;">⚠ Unsicherheiten:</strong>
<ul style="font-size: 0.6875rem; margin-top: 0.25rem; padding-left: 1rem; line-height: 1.3;">
${confidence.uncertaintyFactors.slice(0, 2).map(factor => `<li style="margin-bottom: 0.25rem;">${this.sanitizeText(factor)}</li>`).join('')}
</ul>
</div>
` : ''}
</div>
</div>
`;
}
renderWorkflowTool(tool) {
const hasValidProjectUrl = isToolHosted(tool);
const priorityColors = {
high: 'var(--color-error)',
medium: 'var(--color-warning)',
low: 'var(--color-accent)'
};
return `
<div class="tool-recommendation ${this.getToolClass(tool, 'recommendation')}" onclick="window.showToolDetails('${tool.name}')" style="position: relative;">
<div class="tool-rec-header">
<h4 class="tool-rec-name">
${tool.icon ? `<span style="margin-right: 0.5rem;">${tool.icon}</span>` : ''}
${tool.name}
</h4>
<div class="flex items-center gap-2">
<span class="tool-rec-priority ${tool.recommendation ? tool.recommendation.priority : tool.priority}"
style="background-color: ${priorityColors[tool.recommendation ? tool.recommendation.priority : tool.priority]}; color: white; padding: 0.25rem 0.5rem; border-radius: 1rem; font-size: 0.75rem;">
${tool.recommendation ? tool.recommendation.priority : tool.priority}
</span>
</div>
</div>
${tool.confidence ? this.renderConfidenceIndicator(tool.confidence) : ''}
<div class="tool-rec-justification" style="background-color: var(--color-bg-tertiary); padding: 0.75rem; border-radius: 0.375rem; border-left: 3px solid var(--color-primary); margin: 0.75rem 0; font-style: italic; white-space: pre-wrap; word-wrap: break-word;">
"${this.sanitizeText(tool.justification || (tool.recommendation && tool.recommendation.justification) || `Empfohlen für ${tool.phase}`)}"
</div>
<div style="font-size: 0.75rem; color: var(--color-text-secondary);">
${this.renderToolBadges(tool)}
<div style="margin-top: 0.5rem;">
${tool.type === 'method' ? 'Methode' : tool.platforms.join(', ') + ' • ' + tool.license}
</div>
</div>
</div>
`;
}
renderDetailedTool(tool, recommendation, rank) {
const rankColors = { 1: 'var(--color-accent)', 2: 'var(--color-primary)', 3: 'var(--color-warning)' };
const suitabilityColors = { high: 'var(--color-accent)', medium: 'var(--color-warning)', low: 'var(--color-text-secondary)' };
return `
<div class="card ${this.getToolClass(tool, 'card')}" style="cursor: pointer; position: relative;" onclick="window.showToolDetails('${tool.name}')">
<div style="position: absolute; top: -8px; right: -8px; width: 32px; height: 32px; background-color: ${rankColors[rank]}; color: white; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-weight: bold; font-size: 1.125rem;">
${rank}
</div>
<div style="margin-bottom: 1rem;">
<h3 style="margin: 0 0 0.5rem 0;">${tool.name}</h3>
<div style="display: flex; flex-wrap: wrap; gap: 0.5rem; align-items: center; margin-bottom: 0.75rem;">
<span class="badge" style="background-color: ${suitabilityColors[recommendation.suitability_score]}; color: white;">
${this.getSuitabilityText(recommendation.suitability_score)}
</span>
${this.renderToolBadges(tool)}
</div>
${recommendation.confidence ? this.renderConfidenceIndicator(recommendation.confidence) : ''}
</div>
<div style="margin-bottom: 1.5rem;">
<h4 style="margin: 0.8rem 0 0.75rem 0; color: var(--color-accent);">Warum diese Methode?</h4>
<div style="margin: 0; line-height: 1.6; white-space: pre-wrap; word-wrap: break-word;">${this.sanitizeText(recommendation.detailed_explanation)}</div>
${recommendation.implementation_approach ? `
<h4 style="margin: 0.8rem 0 0.75rem 0; color: var(--color-primary);">Anwendungsansatz</h4>
<div style="margin: 0; line-height: 1.6; white-space: pre-wrap; word-wrap: break-word;">${this.sanitizeText(recommendation.implementation_approach)}</div>
` : ''}
</div>
${this.renderProsAndCons(recommendation.pros, recommendation.cons)}
${this.renderToolMetadata(tool)}
${recommendation.alternatives ? this.renderAlternatives(recommendation.alternatives) : ''}
</div>
`;
}
renderHeader(title, query) {
return `
<div style="text-align: center; margin-bottom: 2rem; padding: 1.5rem; background: linear-gradient(135deg, var(--color-primary) 0%, #525252 100%); color: white; border-radius: 0.75rem;">
@@ -1099,7 +1248,7 @@ class AIQueryInterface {
}
renderWorkflowTool(tool) {
const hasValidProjectUrl = this.isToolHosted(tool);
const hasValidProjectUrl = isToolHosted(tool);
const priorityColors = {
high: 'var(--color-error)',
medium: 'var(--color-warning)',
@@ -1142,7 +1291,10 @@ class AIQueryInterface {
const fullTool = tools.find(t => t.name === toolRec.name);
if (!fullTool) return '';
return this.renderDetailedTool(fullTool, toolRec, index + 1);
return this.renderDetailedTool(fullTool, {
...toolRec,
confidence: toolRec.confidence
}, index + 1);
}).join('')}
</div>
`;
@@ -1256,7 +1408,7 @@ class AIQueryInterface {
renderToolBadges(tool) {
const isMethod = tool.type === 'method';
const hasValidProjectUrl = this.isToolHosted(tool);
const hasValidProjectUrl = isToolHosted(tool);
let badges = '';
if (isMethod) {
@@ -1300,16 +1452,9 @@ class AIQueryInterface {
.trim();
}
isToolHosted(tool) {
return tool.projectUrl !== undefined &&
tool.projectUrl !== null &&
tool.projectUrl !== "" &&
tool.projectUrl.trim() !== "";
}
getToolClass(tool, context = 'card') {
const isMethod = tool.type === 'method';
const hasValidProjectUrl = this.isToolHosted(tool);
const hasValidProjectUrl = isToolHosted(tool);
if (context === 'recommendation') {
if (isMethod) return 'method';
@@ -1402,5 +1547,6 @@ document.addEventListener('DOMContentLoaded', () => {
aiInterface.hideError();
}
};
window.isToolHosted = window.isToolHosted || isToolHosted
});
</script>