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:
@@ -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');
|
||||
|
||||
filterItems.forEach(item => {
|
||||
item.addEventListener('click', function() {
|
||||
// Remove active class from all items
|
||||
filterItems.forEach(f => f.classList.remove('active'));
|
||||
document.addEventListener('click', function(event) {
|
||||
if (event.target.closest('.filter-item')) {
|
||||
const filterItem = event.target.closest('.filter-item');
|
||||
|
||||
// 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);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user