Compare commits

2 Commits

Author SHA1 Message Date
1cec74fc78 fix: correct deployment workflow to force sync with remote
All checks were successful
CI / update (push) Successful in 1m11s
Fix the deployment script to properly force the remote server to always
match the git repository state, regardless of local changes.

Changes:
- Replace invalid `git pull --force` with proper fetch and reset
- Add `git remote set-url origin` to ensure correct URL with auth token
- Use `git fetch origin` to download latest changes
- Use `git reset --hard origin/master` to force match remote state

This ensures clean deployments even if there are local modifications or
conflicts on the remote server, while preserving untracked files like .env.
2026-01-02 21:46:37 +01:00
626f4b039a feat: add graceful degradation and conditional favorites filter
Add progressive enhancement to hide filter panel when JavaScript is
disabled, and conditionally render favorites filter based on login status.

Search Component:
- Added showFilters state (default false)
- Set showFilters to true in onMount when JS is enabled
- Wrapped FilterPanel in {#if showFilters} for graceful degradation
- Filters hidden without JavaScript, visible with JS

FilterPanel:
- Split grid layout into two variants:
  - with-favorites: 5 columns (120px 120px 1fr 160px 90px)
  - without-favorites: 4 columns (120px 120px 1fr 160px)
- Conditionally render FavoritesFilter only when isLoggedIn
- Apply appropriate class based on login status

FavoritesFilter:
- Simplified template (no internal login check)
- Only rendered when user is logged in via FilterPanel

UX:
- Non-JS browsers: Simple search only, filters gracefully hidden
- Not logged in: 4-column layout without favorites filter
- Logged in: 5-column layout with favorites filter
2026-01-02 21:41:24 +01:00
4 changed files with 48 additions and 44 deletions

View File

@@ -28,7 +28,8 @@ jobs:
port: 22 port: 22
script: | script: |
cd /usr/share/webapps/homepage cd /usr/share/webapps/homepage
git pull --force https://Alexander:${{ secrets.homepage_gitea_token }}@git.bocken.org/Alexander/homepage git remote set-url origin https://Alexander:${{ secrets.homepage_gitea_token }}@git.bocken.org/Alexander/homepage
git fetch origin
git reset --hard origin/master git reset --hard origin/master
npm run build npm run build
sudo systemctl restart homepage.service sudo systemctl restart homepage.service

View File

@@ -10,8 +10,7 @@
} = $props(); } = $props();
const isEnglish = $derived(lang === 'en'); const isEnglish = $derived(lang === 'en');
const label = $derived(isEnglish ? 'Favorites Only' : 'Nur Favoriten'); const label = $derived(isEnglish ? 'Favorites' : 'Favoriten');
const loginRequiredLabel = $derived(isEnglish ? 'Login required' : 'Anmeldung erforderlich');
let checked = $state(enabled); let checked = $state(enabled);
@@ -57,24 +56,13 @@
text-align: left; text-align: left;
} }
} }
.login-required {
font-size: 0.85rem;
color: var(--nord3);
font-style: italic;
padding: 0.5rem 0;
}
</style> </style>
<div class="filter-section"> <div class="filter-section">
<div class="filter-label">{label}</div> <div class="filter-label">{label}</div>
{#if isLoggedIn} <Toggle
<Toggle bind:checked={checked}
bind:checked={checked} label=""
label="" on:change={handleChange}
on:change={handleChange} />
/>
{:else}
<div class="login-required">{loginRequiredLabel}</div>
{/if}
</div> </div>

View File

@@ -79,11 +79,18 @@
.filter-panel { .filter-panel {
display: grid; display: grid;
grid-template-columns: 120px 120px 1fr 160px 140px;
gap: 2rem; gap: 2rem;
align-items: start; align-items: start;
} }
.filter-panel.with-favorites {
grid-template-columns: 120px 120px 1fr 160px 90px;
}
.filter-panel.without-favorites {
grid-template-columns: 120px 120px 1fr 160px;
}
@media (max-width: 968px) { @media (max-width: 968px) {
.toggle-button { .toggle-button {
display: flex; display: flex;
@@ -125,7 +132,7 @@
<span class="arrow" class:open={filtersOpen}>▼</span> <span class="arrow" class:open={filtersOpen}>▼</span>
</button> </button>
<div class="filter-panel" class:open={filtersOpen}> <div class="filter-panel" class:open={filtersOpen} class:with-favorites={isLoggedIn} class:without-favorites={!isLoggedIn}>
<CategoryFilter <CategoryFilter
categories={availableCategories} categories={availableCategories}
selected={selectedCategory} selected={selectedCategory}
@@ -154,11 +161,13 @@
{months} {months}
/> />
<FavoritesFilter {#if isLoggedIn}
enabled={selectedFavoritesOnly} <FavoritesFilter
onToggle={onFavoritesToggle} enabled={selectedFavoritesOnly}
{isLoggedIn} onToggle={onFavoritesToggle}
{lang} {isLoggedIn}
/> {lang}
/>
{/if}
</div> </div>
</div> </div>

View File

@@ -27,6 +27,7 @@
}); });
let searchQuery = $state(''); let searchQuery = $state('');
let showFilters = $state(false);
// Filter data loaded from APIs // Filter data loaded from APIs
let availableTags = $state([]); let availableTags = $state([]);
@@ -246,6 +247,9 @@
clearButton.style.display = 'flex'; clearButton.style.display = 'flex';
} }
// Enable filter panel for JS-enabled browsers
showFilters = true;
// Get initial search value from URL if present // Get initial search value from URL if present
const urlParams = new URLSearchParams(window.location.search); const urlParams = new URLSearchParams(window.location.search);
const urlQuery = urlParams.get('q'); const urlQuery = urlParams.get('q');
@@ -340,20 +344,22 @@ scale: 0.8 0.8;
</button> </button>
</form> </form>
<FilterPanel {#if showFilters}
availableCategories={categories} <FilterPanel
{availableTags} availableCategories={categories}
{availableIcons} {availableTags}
{selectedCategory} {availableIcons}
{selectedTags} {selectedCategory}
{selectedIcon} {selectedTags}
{selectedSeasons} {selectedIcon}
{selectedFavoritesOnly} {selectedSeasons}
{lang} {selectedFavoritesOnly}
{isLoggedIn} {lang}
onCategoryChange={handleCategoryChange} {isLoggedIn}
onTagToggle={handleTagToggle} onCategoryChange={handleCategoryChange}
onIconChange={handleIconChange} onTagToggle={handleTagToggle}
onSeasonChange={handleSeasonChange} onIconChange={handleIconChange}
onFavoritesToggle={handleFavoritesToggle} onSeasonChange={handleSeasonChange}
/> onFavoritesToggle={handleFavoritesToggle}
/>
{/if}