Fix filtration system - connect sidebar filters to filter pipeline

Investigation revealed the filtration system had several issues:

1. **Hardcoded filters**: Sidebar had hardcoded filters that didn't match actual filtersets
2. **No backend integration**: Filter switching didn't pass filter parameters to API
3. **Missing filter endpoint**: No API to get available filters dynamically

Fixes implemented:
- Added /api/filters endpoint to get available filtersets from filter engine
- Updated dashboard to load filters dynamically from backend
- Connected filter switching to actually apply different filtersets
- Added filter override parameter to /api/posts endpoint
- Updated JavaScript to properly handle filter state and switching
- Added proper loading states and error handling

Available filters now show:
- All Content (no_filter)
- Safe Content (safe_content)
- Tech Only (tech_only)
- High Quality (high_quality)
- Custom Example (custom_example)

The filtration system now properly applies the selected filterset to posts
using the existing filter pipeline infrastructure.

Fixes #19

~claude

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
chelsea
2025-10-12 03:22:11 -05:00
parent cdc415b0c1
commit 146ad754c0

View File

@@ -11,17 +11,9 @@
<aside class="sidebar"> <aside class="sidebar">
<div class="sidebar-section"> <div class="sidebar-section">
<h3>Content Filters</h3> <h3>Content Filters</h3>
<div class="filter-item active" data-filter="no_filter"> <div id="filter-list" class="filter-list">
<span class="filter-icon">🌐</span> <!-- Filters will be loaded dynamically -->
<span>All Content</span> <div class="loading-filters">Loading filters...</div>
</div>
<div class="filter-item" data-filter="safe_content">
<span class="filter-icon"></span>
<span>Safe Content</span>
</div>
<div class="filter-item" data-filter="custom">
<span class="filter-icon">🎯</span>
<span>Custom Filter</span>
</div> </div>
</div> </div>
@@ -311,14 +303,14 @@
font-weight: 500; font-weight: 500;
} }
.loading-communities { .loading-communities, .loading-filters {
text-align: center; text-align: center;
color: #64748b; color: #64748b;
font-style: italic; font-style: italic;
padding: 20px; padding: 20px;
} }
.no-communities { .no-communities, .no-filters {
text-align: center; text-align: center;
color: #64748b; color: #64748b;
font-style: italic; font-style: italic;
@@ -695,9 +687,11 @@ let postsData = [];
let currentPage = 1; let currentPage = 1;
let currentCommunity = ''; let currentCommunity = '';
let currentPlatform = ''; let currentPlatform = '';
let currentFilter = 'no_filter';
let paginationData = {}; let paginationData = {};
let platformConfig = {}; let platformConfig = {};
let communitiesData = []; let communitiesData = [];
let filtersData = [];
// User experience settings // User experience settings
let userSettings = {{ user_settings|tojson }}; let userSettings = {{ user_settings|tojson }};
@@ -705,8 +699,8 @@ let userSettings = {{ user_settings|tojson }};
// Load posts on page load // Load posts on page load
document.addEventListener('DOMContentLoaded', function() { document.addEventListener('DOMContentLoaded', function() {
loadPlatformConfig(); loadPlatformConfig();
loadFilters();
loadPosts(); loadPosts();
setupFilterSwitching();
setupInfiniteScroll(); setupInfiniteScroll();
setupAutoRefresh(); setupAutoRefresh();
}); });
@@ -734,6 +728,54 @@ async function loadPlatformConfig() {
} }
} }
// Load available filters
async function loadFilters() {
try {
const response = await fetch('/api/filters');
const data = await response.json();
filtersData = data.filters || [];
renderFilters(filtersData);
setupFilterSwitching();
} catch (error) {
console.error('Error loading filters:', error);
// Show fallback filters
const fallbackFilters = [
{id: 'no_filter', name: 'All Content', icon: '🌐', active: true, description: 'No filtering'}
];
renderFilters(fallbackFilters);
setupFilterSwitching();
}
}
// Render filters in sidebar
function renderFilters(filters) {
const filterList = document.getElementById('filter-list');
if (!filterList) return;
if (filters.length === 0) {
filterList.innerHTML = '<div class="no-filters">No filters available</div>';
return;
}
const filtersHTML = filters.map(filter => {
return `
<div class="filter-item ${filter.active ? 'active' : ''}" data-filter="${filter.id}" title="${filter.description}">
<span class="filter-icon">${filter.icon}</span>
<span>${filter.name}</span>
</div>
`;
}).join('');
filterList.innerHTML = filtersHTML;
// Set current filter based on active filter
const activeFilter = filters.find(f => f.active);
if (activeFilter) {
currentFilter = activeFilter.id;
}
}
// Render communities in sidebar // Render communities in sidebar
function renderCommunities(communities) { function renderCommunities(communities) {
const communityList = document.getElementById('community-list'); const communityList = document.getElementById('community-list');
@@ -767,7 +809,7 @@ function renderCommunities(communities) {
} }
// Load posts from API // Load posts from API
async function loadPosts(page = 1, community = '', platform = '', append = false) { async function loadPosts(page = 1, community = '', platform = '', append = false, filter = null) {
try { try {
// Build query parameters // Build query parameters
const params = new URLSearchParams(); const params = new URLSearchParams();
@@ -775,6 +817,7 @@ async function loadPosts(page = 1, community = '', platform = '', append = false
params.append('per_page', 20); params.append('per_page', 20);
if (community) params.append('community', community); if (community) params.append('community', community);
if (platform) params.append('platform', platform); if (platform) params.append('platform', platform);
if (filter || currentFilter) params.append('filter', filter || currentFilter);
if (currentSearchQuery) params.append('q', currentSearchQuery); if (currentSearchQuery) params.append('q', currentSearchQuery);
const response = await fetch(`/api/posts?${params}`); const response = await fetch(`/api/posts?${params}`);
@@ -968,24 +1011,34 @@ function savePost(postId) {
// Filter switching functionality // Filter switching functionality
function setupFilterSwitching() { function setupFilterSwitching() {
const filterItems = document.querySelectorAll('.filter-item'); document.addEventListener('click', function(event) {
if (event.target.closest('.filter-item')) {
filterItems.forEach(item => { const filterItem = event.target.closest('.filter-item');
item.addEventListener('click', function() {
// Remove active class from all items // Remove active class from all filter items
filterItems.forEach(f => f.classList.remove('active')); document.querySelectorAll('.filter-item').forEach(f => f.classList.remove('active'));
// Add active class to clicked item // Add active class to clicked item
this.classList.add('active'); filterItem.classList.add('active');
// Get filter type // Get filter type
const filterType = this.dataset.filter; const filterType = filterItem.dataset.filter;
currentFilter = filterType;
// Apply filter (for now just reload) // Update header to show current filter
if (filterType && filterType !== 'custom') { const contentHeader = document.querySelector('.content-header h1');
loadPosts(); // In future, pass filter parameter const filterName = filterItem.textContent.trim();
} contentHeader.textContent = `${filterName} Feed`;
});
// Show loading state
const postsContainer = document.getElementById('posts-container');
const loadingIndicator = document.getElementById('loading-indicator');
loadingIndicator.style.display = 'flex';
postsContainer.innerHTML = '';
// Apply filter
loadPosts(1, currentCommunity, currentPlatform, false, filterType);
}
}); });
} }