feat: Introduce Shaarli Professional theme with modern sidebar layout, light/dark mode, and associated JavaScript.
This commit is contained in:
parent
0bdf95e00a
commit
646f92005f
@ -3093,3 +3093,23 @@ select:focus {
|
|||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Filter Badge Indicator */
|
||||||
|
.filter-badge {
|
||||||
|
position: absolute;
|
||||||
|
top: 2px;
|
||||||
|
right: 2px;
|
||||||
|
width: 8px;
|
||||||
|
height: 8px;
|
||||||
|
background: #ef4444;
|
||||||
|
border-radius: 50%;
|
||||||
|
border: 2px solid var(--header-bg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-action-btn {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-action-btn.has-active-filter {
|
||||||
|
background: rgba(239, 68, 68, 0.2);
|
||||||
|
}
|
||||||
|
|||||||
@ -410,15 +410,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
let basePath = (typeof shaarli !== 'undefined' && shaarli.basePath) ? shaarli.basePath : '';
|
let basePath = (typeof shaarli !== 'undefined' && shaarli.basePath) ? shaarli.basePath : '';
|
||||||
let url = basePath + '/';
|
let url = basePath + '/';
|
||||||
|
|
||||||
// Save filter state to localStorage before navigation
|
console.log('[Filter] Applying filters - private:', isPrivate, 'public:', isPublic, 'untagged:', isUntagged);
|
||||||
const filterState = {
|
|
||||||
private: isPrivate,
|
|
||||||
public: isPublic,
|
|
||||||
untagged: isUntagged,
|
|
||||||
timestamp: Date.now()
|
|
||||||
};
|
|
||||||
localStorage.setItem('shaarliFilterState', JSON.stringify(filterState));
|
|
||||||
console.log('[Filter] Saved filter state:', filterState);
|
|
||||||
|
|
||||||
// Build the URL based on selected filters using the correct Shaarli admin paths
|
// Build the URL based on selected filters using the correct Shaarli admin paths
|
||||||
if (isPrivate && isUntagged) {
|
if (isPrivate && isUntagged) {
|
||||||
@ -430,22 +422,18 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
} else if (isPublic) {
|
} else if (isPublic) {
|
||||||
url = basePath + '/admin/visibility/public';
|
url = basePath + '/admin/visibility/public';
|
||||||
} else if (isUntagged) {
|
} else if (isUntagged) {
|
||||||
url = basePath + '/untagged-only';
|
url = basePath + '/?searchtags=';
|
||||||
} else {
|
|
||||||
// No filter selected - clear the state
|
|
||||||
localStorage.removeItem('shaarliFilterState');
|
|
||||||
}
|
}
|
||||||
|
// else: no filter, url stays as basePath + '/'
|
||||||
|
|
||||||
console.log('[Filter] Navigating to:', url);
|
console.log('[Filter] Navigating to:', url);
|
||||||
window.location.href = url;
|
window.location.href = url;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear filters function
|
// Clear all filters and go to home
|
||||||
function clearFilters() {
|
function clearAllFilters() {
|
||||||
localStorage.removeItem('shaarliFilterState');
|
const basePath = (typeof shaarli !== 'undefined' && shaarli.basePath) ? shaarli.basePath : '';
|
||||||
if (filterPrivate) filterPrivate.checked = false;
|
window.location.href = basePath + '/';
|
||||||
if (filterPublic) filterPublic.checked = false;
|
|
||||||
if (filterUntagged) filterUntagged.checked = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Private and public are mutually exclusive
|
// Private and public are mutually exclusive
|
||||||
@ -467,34 +455,24 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
applyFilters();
|
applyFilters();
|
||||||
});
|
});
|
||||||
|
|
||||||
// Initialize filter states from localStorage (since Shaarli redirects after applying filters)
|
// Initialize filter states from URL (detect current filter state from page URL)
|
||||||
(function initFilterStates() {
|
(function initFilterStates() {
|
||||||
console.log('[Filter Debug] ========================================');
|
console.log('[Filter Debug] ========================================');
|
||||||
|
|
||||||
// Try to read filter state from localStorage
|
// Detect filter state from current URL path
|
||||||
let savedState = null;
|
const currentPath = window.location.pathname;
|
||||||
try {
|
const currentSearch = window.location.search;
|
||||||
const savedJson = localStorage.getItem('shaarliFilterState');
|
|
||||||
if (savedJson) {
|
|
||||||
savedState = JSON.parse(savedJson);
|
|
||||||
console.log('[Filter Debug] Found saved filter state:', savedState);
|
|
||||||
|
|
||||||
// Check if state is not too old (30 seconds max)
|
// Detect visibility filter from URL path
|
||||||
const age = Date.now() - (savedState.timestamp || 0);
|
let isPrivateActive = currentPath.includes('/visibility/private') || currentPath.includes('/admin/visibility/private');
|
||||||
if (age > 30000) {
|
let isPublicActive = currentPath.includes('/visibility/public') || currentPath.includes('/admin/visibility/public');
|
||||||
console.log('[Filter Debug] Saved state is too old, ignoring');
|
|
||||||
localStorage.removeItem('shaarliFilterState');
|
|
||||||
savedState = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
console.log('[Filter Debug] Error reading saved state:', e);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Determine active filters from saved state
|
// Detect untagged filter
|
||||||
let isPrivateActive = savedState?.private || false;
|
let isUntaggedActive = currentPath.includes('/untagged-only') ||
|
||||||
let isPublicActive = savedState?.public || false;
|
(currentSearch.includes('searchtags=') && !currentSearch.match(/searchtags=[^&]+/));
|
||||||
let isUntaggedActive = savedState?.untagged || false;
|
|
||||||
|
console.log('[Filter Debug] URL path:', currentPath);
|
||||||
|
console.log('[Filter Debug] URL search:', currentSearch);
|
||||||
|
|
||||||
console.log('[Filter Debug] isPrivateActive:', isPrivateActive);
|
console.log('[Filter Debug] isPrivateActive:', isPrivateActive);
|
||||||
console.log('[Filter Debug] isPublicActive:', isPublicActive);
|
console.log('[Filter Debug] isPublicActive:', isPublicActive);
|
||||||
@ -534,24 +512,31 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
|
|
||||||
// Create and display the filter info banner
|
// Create and display the filter info banner
|
||||||
if (hasActiveFilter && !document.getElementById('filter-info-banner')) {
|
if (hasActiveFilter && !document.getElementById('filter-info-banner')) {
|
||||||
// Build the message - describe the active filter without count
|
// Get result count from page
|
||||||
|
let resultCount = '';
|
||||||
|
const pagingStats = document.querySelector('.paging-stats strong:last-child');
|
||||||
|
if (pagingStats) {
|
||||||
|
resultCount = pagingStats.textContent;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build the message with result count like "X results with status private"
|
||||||
let filterParts = [];
|
let filterParts = [];
|
||||||
|
|
||||||
if (isPrivateActive) {
|
if (isPrivateActive) {
|
||||||
filterParts.push('<strong>private</strong> links');
|
filterParts.push('with status <strong>private</strong>');
|
||||||
} else if (isPublicActive) {
|
} else if (isPublicActive) {
|
||||||
filterParts.push('<strong>public</strong> links');
|
filterParts.push('with status <strong>public</strong>');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isUntaggedActive) {
|
if (isUntaggedActive) {
|
||||||
if (filterParts.length > 0) {
|
if (filterParts.length > 0) {
|
||||||
filterParts.push('without tags');
|
filterParts.push('and <strong>untagged</strong>');
|
||||||
} else {
|
} else {
|
||||||
filterParts.push('links <strong>without tags</strong>');
|
filterParts.push('<strong>untagged</strong>');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let message = 'Showing ' + filterParts.join(' ');
|
let message = resultCount ? resultCount + ' results ' + filterParts.join(' ') : 'Showing ' + filterParts.join(' ') + ' links';
|
||||||
|
|
||||||
console.log('[Filter Debug] filterParts:', filterParts);
|
console.log('[Filter Debug] filterParts:', filterParts);
|
||||||
console.log('[Filter Debug] message:', message);
|
console.log('[Filter Debug] message:', message);
|
||||||
@ -599,8 +584,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
|
|
||||||
// Add click handler to clear button
|
// Add click handler to clear button
|
||||||
document.getElementById('filter-clear-btn')?.addEventListener('click', () => {
|
document.getElementById('filter-clear-btn')?.addEventListener('click', () => {
|
||||||
localStorage.removeItem('shaarliFilterState');
|
console.log('[Filter] Clear button clicked, navigating to home');
|
||||||
console.log('[Filter] Cleared filter state from localStorage');
|
|
||||||
window.location.href = basePath + '/';
|
window.location.href = basePath + '/';
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user