feat(ui): integrate value pluralism documents in docs viewer
- Update docs.html with MongoDB-integrated documents - Add value pluralism documents to sidebar categories - Update docs-app.js for proper document retrieval - Sync navbar changes across UI pages Documents now searchable and properly categorized in docs viewer 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
db3126c041
commit
39111d4a8e
3 changed files with 118 additions and 134 deletions
|
|
@ -442,7 +442,7 @@
|
|||
<option value="">All Audiences</option>
|
||||
<option value="researcher">Researcher</option>
|
||||
<option value="implementer">Implementer</option>
|
||||
<option value="advocate">Advocate / Leader</option>
|
||||
<option value="leader">Leader</option>
|
||||
<option value="technical">Technical</option>
|
||||
<option value="general">General</option>
|
||||
</select>
|
||||
|
|
@ -662,7 +662,7 @@
|
|||
</li>
|
||||
<li class="flex items-start">
|
||||
<span class="font-medium text-blue-600 mr-2">•</span>
|
||||
<span><strong>Audience:</strong> Filter for Researcher, Implementer, Advocate/Leader, Technical, or General audience</span>
|
||||
<span><strong>Audience:</strong> Filter for Researcher, Implementer, Leader, Technical, or General audience</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@
|
|||
class TractatusNavbar {
|
||||
constructor() {
|
||||
this.mobileMenuOpen = false;
|
||||
this.audiencesDropdownOpen = false;
|
||||
this.init();
|
||||
}
|
||||
|
||||
|
|
@ -30,32 +29,9 @@ class TractatusNavbar {
|
|||
</a>
|
||||
</div>
|
||||
|
||||
<!-- Desktop Menu (hidden on mobile) -->
|
||||
<div class="hidden md:flex items-center space-x-8">
|
||||
<!-- Audiences Dropdown -->
|
||||
<div class="relative">
|
||||
<button id="audiences-dropdown-btn" class="text-gray-600 hover:text-gray-900 flex items-center space-x-1 focus:outline-none focus:ring-2 focus:ring-blue-500 rounded px-2 py-1">
|
||||
<span>Audiences</span>
|
||||
<svg class="w-4 h-4 transition-transform" id="audiences-dropdown-arrow" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7" />
|
||||
</svg>
|
||||
</button>
|
||||
<div id="audiences-dropdown-menu" class="hidden absolute left-0 mt-2 w-48 bg-white rounded-lg shadow-lg border border-gray-200 py-2">
|
||||
<a href="/researcher.html" class="block px-4 py-2 text-sm text-gray-700 hover:bg-blue-50 hover:text-blue-700">Researcher</a>
|
||||
<a href="/implementer.html" class="block px-4 py-2 text-sm text-gray-700 hover:bg-blue-50 hover:text-blue-700">Implementer</a>
|
||||
<a href="/leader.html" class="block px-4 py-2 text-sm text-gray-700 hover:bg-blue-50 hover:text-blue-700">Leader</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<a href="/docs.html" class="text-gray-600 hover:text-gray-900 font-medium">Docs</a>
|
||||
<a href="/blog.html" class="text-gray-600 hover:text-gray-900 font-medium">Blog</a>
|
||||
<a href="/faq.html" class="text-gray-600 hover:text-gray-900 font-medium">FAQ</a>
|
||||
<a href="/about.html" class="text-gray-600 hover:text-gray-900">About</a>
|
||||
</div>
|
||||
|
||||
<!-- Menu Button (always visible) -->
|
||||
<!-- Right: Menu Button (always visible) -->
|
||||
<div class="flex items-center">
|
||||
<button id="mobile-menu-btn" class="text-gray-600 hover:text-gray-900 focus:outline-none focus:ring-2 focus:ring-blue-500 rounded p-2 md:ml-4" aria-label="Toggle menu">
|
||||
<button id="mobile-menu-btn" class="text-gray-600 hover:text-gray-900 focus:outline-none focus:ring-2 focus:ring-blue-500 rounded p-2" aria-label="Toggle menu">
|
||||
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16" />
|
||||
</svg>
|
||||
|
|
@ -99,6 +75,9 @@ class TractatusNavbar {
|
|||
<a href="/docs.html" class="block px-3 py-2.5 text-gray-700 hover:bg-blue-50 hover:text-blue-700 rounded-lg transition">
|
||||
<span class="text-sm font-semibold">📚 Documentation</span>
|
||||
</a>
|
||||
<a href="/api-reference.html" class="block px-3 py-2.5 text-gray-700 hover:bg-blue-50 hover:text-blue-700 rounded-lg transition">
|
||||
<span class="text-sm font-semibold">🔌 API Reference</span>
|
||||
</a>
|
||||
<a href="/blog.html" class="block px-3 py-2.5 text-gray-700 hover:bg-blue-50 hover:text-blue-700 rounded-lg transition">
|
||||
<span class="text-sm font-semibold">📝 Blog</span>
|
||||
</a>
|
||||
|
|
@ -128,29 +107,6 @@ class TractatusNavbar {
|
|||
}
|
||||
|
||||
attachEventListeners() {
|
||||
// Audiences Dropdown (Desktop)
|
||||
const audiencesBtn = document.getElementById('audiences-dropdown-btn');
|
||||
const audiencesMenu = document.getElementById('audiences-dropdown-menu');
|
||||
const audiencesArrow = document.getElementById('audiences-dropdown-arrow');
|
||||
|
||||
if (audiencesBtn) {
|
||||
audiencesBtn.addEventListener('click', (e) => {
|
||||
e.stopPropagation();
|
||||
this.audiencesDropdownOpen = !this.audiencesDropdownOpen;
|
||||
audiencesMenu.classList.toggle('hidden', !this.audiencesDropdownOpen);
|
||||
audiencesArrow.style.transform = this.audiencesDropdownOpen ? 'rotate(180deg)' : 'rotate(0deg)';
|
||||
});
|
||||
|
||||
// Close dropdown when clicking outside
|
||||
document.addEventListener('click', () => {
|
||||
if (this.audiencesDropdownOpen) {
|
||||
this.audiencesDropdownOpen = false;
|
||||
audiencesMenu.classList.add('hidden');
|
||||
audiencesArrow.style.transform = 'rotate(0deg)';
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Mobile Menu (Navigation Drawer)
|
||||
const mobileMenuBtn = document.getElementById('mobile-menu-btn');
|
||||
const mobileMenuCloseBtn = document.getElementById('mobile-menu-close-btn');
|
||||
|
|
|
|||
|
|
@ -7,12 +7,12 @@ if (typeof DocumentCards !== 'undefined') {
|
|||
documentCards = new DocumentCards('document-content');
|
||||
}
|
||||
|
||||
// Document categorization - Organized by audience and expertise level
|
||||
// Document categorization - Granular categories for better organization
|
||||
const CATEGORIES = {
|
||||
'introduction': {
|
||||
label: '📘 Introduction',
|
||||
icon: '📘',
|
||||
description: 'Start here - core concepts for all audiences',
|
||||
'getting-started': {
|
||||
label: '🚀 Getting Started',
|
||||
icon: '🚀',
|
||||
description: 'Introduction, core concepts, and quick start guides',
|
||||
order: 1,
|
||||
color: 'blue',
|
||||
bgColor: 'bg-blue-50',
|
||||
|
|
@ -20,10 +20,10 @@ const CATEGORIES = {
|
|||
textColor: 'text-blue-700',
|
||||
collapsed: false
|
||||
},
|
||||
'implementation': {
|
||||
label: '⚙️ Implementation',
|
||||
icon: '⚙️',
|
||||
description: 'Practical guides for developers and implementers',
|
||||
'technical-reference': {
|
||||
label: '🔌 Technical Reference',
|
||||
icon: '🔌',
|
||||
description: 'API docs, implementation guides, code examples',
|
||||
order: 2,
|
||||
color: 'green',
|
||||
bgColor: 'bg-green-50',
|
||||
|
|
@ -31,10 +31,10 @@ const CATEGORIES = {
|
|||
textColor: 'text-green-700',
|
||||
collapsed: false
|
||||
},
|
||||
'case-studies': {
|
||||
label: '📊 Case Studies',
|
||||
icon: '📊',
|
||||
description: 'Real-world examples and failure analysis',
|
||||
'research-theory': {
|
||||
label: '🔬 Research & Theory',
|
||||
icon: '🔬',
|
||||
description: 'Research papers, theoretical foundations',
|
||||
order: 3,
|
||||
color: 'purple',
|
||||
bgColor: 'bg-purple-50',
|
||||
|
|
@ -42,27 +42,49 @@ const CATEGORIES = {
|
|||
textColor: 'text-purple-700',
|
||||
collapsed: false
|
||||
},
|
||||
'business': {
|
||||
label: '💼 Business Strategy',
|
||||
icon: '💼',
|
||||
description: 'ROI, business case, and strategic planning',
|
||||
'case-studies': {
|
||||
label: '📊 Case Studies',
|
||||
icon: '📊',
|
||||
description: 'Real-world examples, failure modes, success stories',
|
||||
order: 4,
|
||||
color: 'amber',
|
||||
bgColor: 'bg-amber-50',
|
||||
borderColor: 'border-l-4 border-amber-500',
|
||||
textColor: 'text-amber-700',
|
||||
collapsed: false
|
||||
},
|
||||
'deployment-operations': {
|
||||
label: '⚙️ Deployment & Operations',
|
||||
icon: '⚙️',
|
||||
description: 'Deployment guides, architecture, troubleshooting',
|
||||
order: 5,
|
||||
color: 'indigo',
|
||||
bgColor: 'bg-indigo-50',
|
||||
borderColor: 'border-l-4 border-indigo-500',
|
||||
textColor: 'text-indigo-700',
|
||||
collapsed: false
|
||||
collapsed: true
|
||||
},
|
||||
'advanced': {
|
||||
label: '🔬 Advanced Topics',
|
||||
icon: '🔬',
|
||||
description: 'Deep technical details and research',
|
||||
order: 5,
|
||||
color: 'red',
|
||||
bgColor: 'bg-red-50',
|
||||
borderColor: 'border-l-4 border-red-500',
|
||||
textColor: 'text-red-700',
|
||||
collapsed: true // Collapsed by default
|
||||
'business-leadership': {
|
||||
label: '💼 Business & Leadership',
|
||||
icon: '💼',
|
||||
description: 'Business cases, executive briefs, ROI analysis',
|
||||
order: 6,
|
||||
color: 'pink',
|
||||
bgColor: 'bg-pink-50',
|
||||
borderColor: 'border-l-4 border-pink-500',
|
||||
textColor: 'text-pink-700',
|
||||
collapsed: true
|
||||
},
|
||||
'downloads-resources': {
|
||||
label: '📥 Downloads & Resources',
|
||||
icon: '📥',
|
||||
description: 'PDFs, sample configs, external resources',
|
||||
order: 7,
|
||||
color: 'gray',
|
||||
bgColor: 'bg-gray-50',
|
||||
borderColor: 'border-l-4 border-gray-400',
|
||||
textColor: 'text-gray-700',
|
||||
collapsed: true
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -75,8 +97,8 @@ const HIDDEN_DOCS = [
|
|||
'cover-letter'
|
||||
];
|
||||
|
||||
// Categorize a document based on order field
|
||||
// Order ranges map to categories for audience/expertise-based organization
|
||||
// Categorize a document using database category field
|
||||
// New granular category system for better document organization
|
||||
function categorizeDocument(doc) {
|
||||
const slug = doc.slug.toLowerCase();
|
||||
|
||||
|
|
@ -85,35 +107,17 @@ function categorizeDocument(doc) {
|
|||
return null;
|
||||
}
|
||||
|
||||
const order = doc.order || 999;
|
||||
// Use category from database
|
||||
const category = doc.category || 'downloads-resources';
|
||||
|
||||
// Introduction: 1-5 (beginner level, all audiences)
|
||||
if (order >= 1 && order <= 5) {
|
||||
return 'introduction';
|
||||
// Validate category exists in CATEGORIES constant
|
||||
if (CATEGORIES[category]) {
|
||||
return category;
|
||||
}
|
||||
|
||||
// Implementation: 10-19 (practical/technical for implementers)
|
||||
if (order >= 10 && order <= 19) {
|
||||
return 'implementation';
|
||||
}
|
||||
|
||||
// Case Studies: 20-29 (real-world examples)
|
||||
if (order >= 20 && order <= 29) {
|
||||
return 'case-studies';
|
||||
}
|
||||
|
||||
// Business Strategy: 30-35 (for leaders/decision makers)
|
||||
if (order >= 30 && order <= 35) {
|
||||
return 'business';
|
||||
}
|
||||
|
||||
// Advanced Topics: 40-49 (deep technical/research)
|
||||
if (order >= 40 && order <= 49) {
|
||||
return 'advanced';
|
||||
}
|
||||
|
||||
// Fallback to introduction for uncategorized (order 999)
|
||||
return 'introduction';
|
||||
// Fallback to downloads-resources for uncategorized
|
||||
console.warn(`Document "${doc.title}" has invalid category "${category}", using fallback`);
|
||||
return 'downloads-resources';
|
||||
}
|
||||
|
||||
// Group documents by category
|
||||
|
|
@ -140,21 +144,36 @@ function groupDocuments(docs) {
|
|||
function renderDocLink(doc, isHighlighted = false) {
|
||||
const highlightClass = isHighlighted ? 'text-blue-700 bg-blue-50 border border-blue-200' : '';
|
||||
|
||||
// Determine if PDF download is available
|
||||
// Check if metadata indicates PDF existence (presence in slugs that typically have PDFs)
|
||||
// Documents with download_formats.pdf, markdown files, or most docs should have PDFs
|
||||
// API Reference docs and technical diagrams might not have PDFs
|
||||
const hasPDF = !doc.slug.includes('api-reference-complete') &&
|
||||
!doc.slug.includes('openapi-specification') &&
|
||||
!doc.slug.includes('api-javascript-examples') &&
|
||||
!doc.slug.includes('api-python-examples') &&
|
||||
!doc.slug.includes('technical-architecture-diagram');
|
||||
|
||||
// Add download button styling
|
||||
const paddingClass = hasPDF ? 'pr-10' : 'pr-3';
|
||||
|
||||
return `
|
||||
<div class="relative mb-1">
|
||||
<button class="doc-link w-full text-left px-3 py-2 pr-10 rounded text-sm hover:bg-blue-50 transition ${highlightClass}"
|
||||
<button class="doc-link w-full text-left px-3 py-2 ${paddingClass} rounded text-sm hover:bg-blue-50 transition ${highlightClass}"
|
||||
data-slug="${doc.slug}">
|
||||
<div class="font-medium text-gray-900">${doc.title}</div>
|
||||
</button>
|
||||
<a href="/downloads/${doc.slug}.pdf"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
class="doc-download-link"
|
||||
title="Download PDF (opens in new tab)">
|
||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 10v6m0 0l-3-3m3 3l3-3m2 8H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"/>
|
||||
</svg>
|
||||
</a>
|
||||
${hasPDF ? `
|
||||
<a href="/downloads/${doc.slug}.pdf"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
class="doc-download-link"
|
||||
title="Download PDF (opens in new tab)">
|
||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 10v6m0 0l-3-3m3 3l3-3m2 8H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"/>
|
||||
</svg>
|
||||
</a>
|
||||
` : ''}
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
|
@ -211,8 +230,8 @@ async function loadDocuments() {
|
|||
|
||||
// Render documents in category
|
||||
docs.forEach(doc => {
|
||||
// Highlight the first document in Introduction category
|
||||
const isHighlighted = categoryId === 'introduction' && doc.order === 1;
|
||||
// Highlight the first document in Getting Started category
|
||||
const isHighlighted = categoryId === 'getting-started' && doc.order === 1;
|
||||
html += renderDocLink(doc, isHighlighted);
|
||||
});
|
||||
|
||||
|
|
@ -290,15 +309,15 @@ async function loadDocuments() {
|
|||
}
|
||||
});
|
||||
|
||||
// Auto-load first document in "Introduction" category (order: 1)
|
||||
const introductionDocs = grouped['introduction'] || [];
|
||||
if (introductionDocs.length > 0) {
|
||||
// Auto-load first document in "Getting Started" category (order: 1)
|
||||
const gettingStartedDocs = grouped['getting-started'] || [];
|
||||
if (gettingStartedDocs.length > 0) {
|
||||
// Load the first document (order: 1) if available
|
||||
const firstDoc = introductionDocs.find(d => d.order === 1);
|
||||
const firstDoc = gettingStartedDocs.find(d => d.order === 1);
|
||||
if (firstDoc) {
|
||||
loadDocument(firstDoc.slug);
|
||||
} else {
|
||||
loadDocument(introductionDocs[0].slug);
|
||||
loadDocument(gettingStartedDocs[0].slug);
|
||||
}
|
||||
} else if (documents.length > 0) {
|
||||
// Fallback to first available document in any category
|
||||
|
|
@ -361,6 +380,13 @@ async function loadDocument(slug) {
|
|||
// Fallback to traditional view with header
|
||||
const hasToC = currentDocument.toc && currentDocument.toc.length > 0;
|
||||
|
||||
// Check if PDF is available (same logic as sidebar)
|
||||
const hasPDF = !currentDocument.slug.includes('api-reference-complete') &&
|
||||
!currentDocument.slug.includes('openapi-specification') &&
|
||||
!currentDocument.slug.includes('api-javascript-examples') &&
|
||||
!currentDocument.slug.includes('api-python-examples') &&
|
||||
!currentDocument.slug.includes('technical-architecture-diagram');
|
||||
|
||||
let headerHTML = `
|
||||
<div class="flex items-center justify-between mb-6 pb-4 border-b border-gray-200">
|
||||
<h1 class="text-3xl font-bold text-gray-900">${currentDocument.title}</h1>
|
||||
|
|
@ -375,16 +401,18 @@ async function loadDocument(slug) {
|
|||
</svg>
|
||||
</button>
|
||||
` : ''}
|
||||
<a href="/downloads/${currentDocument.slug}.pdf"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
class="p-2 text-gray-600 hover:text-blue-600 hover:bg-blue-50 rounded transition"
|
||||
title="Download PDF"
|
||||
aria-label="Download PDF">
|
||||
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 10v6m0 0l-3-3m3 3l3-3m2 8H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"/>
|
||||
</svg>
|
||||
</a>
|
||||
${hasPDF ? `
|
||||
<a href="/downloads/${currentDocument.slug}.pdf"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
class="p-2 text-gray-600 hover:text-blue-600 hover:bg-blue-50 rounded transition"
|
||||
title="Download PDF"
|
||||
aria-label="Download PDF">
|
||||
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 10v6m0 0l-3-3m3 3l3-3m2 8H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"/>
|
||||
</svg>
|
||||
</a>
|
||||
` : ''}
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue