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">
<div class="sidebar-section">
<h3>Content Filters</h3>
<div class="filter-item active" data-filter="no_filter">
<span class="filter-icon">🌐</span>
<span>All Content</span>
</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 id="filter-list" class="filter-list">
<!-- Filters will be loaded dynamically -->
<div class="loading-filters">Loading filters...</div>
</div>
</div>
@@ -311,14 +303,14 @@
font-weight: 500;
}
.loading-communities {
.loading-communities, .loading-filters {
text-align: center;
color: #64748b;
font-style: italic;
padding: 20px;
}
.no-communities {
.no-communities, .no-filters {
text-align: center;
color: #64748b;
font-style: italic;
@@ -695,9 +687,11 @@ let postsData = [];
let currentPage = 1;
let currentCommunity = '';
let currentPlatform = '';
let currentFilter = 'no_filter';
let paginationData = {};
let platformConfig = {};
let communitiesData = [];
let filtersData = [];
// User experience settings
let userSettings = {{ user_settings|tojson }};
@@ -705,8 +699,8 @@ let userSettings = {{ user_settings|tojson }};
// Load posts on page load
document.addEventListener('DOMContentLoaded', function() {
loadPlatformConfig();
loadFilters();
loadPosts();
setupFilterSwitching();
setupInfiniteScroll();
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
function renderCommunities(communities) {
const communityList = document.getElementById('community-list');
@@ -767,7 +809,7 @@ function renderCommunities(communities) {
}
// 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 {
// Build query parameters
const params = new URLSearchParams();
@@ -775,6 +817,7 @@ async function loadPosts(page = 1, community = '', platform = '', append = false
params.append('per_page', 20);
if (community) params.append('community', community);
if (platform) params.append('platform', platform);
if (filter || currentFilter) params.append('filter', filter || currentFilter);
if (currentSearchQuery) params.append('q', currentSearchQuery);
const response = await fetch(`/api/posts?${params}`);
@@ -968,24 +1011,34 @@ function savePost(postId) {
// Filter switching functionality
function setupFilterSwitching() {
const filterItems = document.querySelectorAll('.filter-item');
document.addEventListener('click', function(event) {
if (event.target.closest('.filter-item')) {
const filterItem = event.target.closest('.filter-item');
filterItems.forEach(item => {
item.addEventListener('click', function() {
// Remove active class from all items
filterItems.forEach(f => f.classList.remove('active'));
// Remove active class from all filter items
document.querySelectorAll('.filter-item').forEach(f => f.classList.remove('active'));
// Add active class to clicked item
this.classList.add('active');
filterItem.classList.add('active');
// Get filter type
const filterType = this.dataset.filter;
const filterType = filterItem.dataset.filter;
currentFilter = filterType;
// Apply filter (for now just reload)
if (filterType && filterType !== 'custom') {
loadPosts(); // In future, pass filter parameter
}
});
// Update header to show current filter
const contentHeader = document.querySelector('.content-header h1');
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);
}
});
}