fix: applies pre-filter to download options

This commit is contained in:
2025-08-01 14:12:28 -05:00
parent 7dd61355b7
commit 924472ed56
6 changed files with 49 additions and 56 deletions

View File

@@ -41,6 +41,8 @@ export default class extends Controller {
if (this.countValue === this.totalValue) { if (this.countValue === this.totalValue) {
this.toggleIcon(); this.toggleIcon();
this.countValue = 0; this.countValue = 0;
console.log('filtering')
document.getElementById('filter').filterResults();
} }
} }
} }

View File

@@ -12,14 +12,14 @@ export default class extends Controller {
seasons = [] seasons = []
activeFilter = { activeFilter = {
"resolution": "", "resolution": [],
"codec": "", "codec": [],
"language": "", "language": [],
"provider": "", "provider": [],
"quality": "", "quality": [],
} }
defaultOptions = '<option value="n/a">n/a</option><option value="-">-</option>'; defaultOptions = '<option value="-">-</option>';
static outlets = ['tv-episode-list'] static outlets = ['tv-episode-list']
static targets = ['resolution', 'codec', 'language', 'provider', 'season', 'quality', 'loadingIcon', 'selectAll', 'downloadSelected'] static targets = ['resolution', 'codec', 'language', 'provider', 'season', 'quality', 'loadingIcon', 'selectAll', 'downloadSelected']
@@ -31,13 +31,21 @@ export default class extends Controller {
} }
async connect() { async connect() {
await this.setInitialFilter();
this.setTimerToStopLoadingIcon();
this.element.filterResults = this.filter.bind(this);
document.addEventListener('optionsLoaded', this.loadOptions.bind(this));
}
async setInitialFilter() {
const response = await fetch('/api/user/filters');
const filters = await response.json();
if (filters.length > 0) {
this.activeFilter = filters[0];
}
if (this.mediaTypeValue === "tvshows") { if (this.mediaTypeValue === "tvshows") {
this.activeFilter['season'] = 1; this.activeFilter['season'] = 1;
} }
this.filter();
this.setTimerToStopLoadingIcon();
document.addEventListener('optionsLoaded', this.loadOptions.bind(this));
} }
setTimerToStopLoadingIcon() { setTimerToStopLoadingIcon() {
@@ -45,13 +53,10 @@ export default class extends Controller {
} }
// Event is fired from movies/tvshows controllers to populate this data // Event is fired from movies/tvshows controllers to populate this data
loadOptions({detail: { options }}) { async loadOptions({detail: { options }}) {
options.forEach((option) => { await options.forEach((option) => {
this.addLanguages(option); option.filter({detail: {activeFilter: this.activeFilter }});
this.addProviders(option);
this.addQualities(option);
}) })
this.filter();
} }
selectAllEpisodes() { selectAllEpisodes() {
@@ -66,41 +71,6 @@ export default class extends Controller {
document.dispatchEvent(new CustomEvent('downloadSelectedEpisodes', {})); document.dispatchEvent(new CustomEvent('downloadSelectedEpisodes', {}));
} }
addLanguages(option) {
option.languages.forEach((language) => {
if (!this.languages.includes(language)) {
this.languages.push(language);
}
});
const preferred = JSON.parse(this.languageTarget.dataset.preferred) ?? [];
this.languageTarget.innerHTML = this.#serializeSelectOptions(this.languages);
this.languageTarget.tomselect.items = preferred;
}
addProviders(option) {
if (!this.providers.includes(option.provider)) {
this.providers.push(option.provider);
}
const preferred = JSON.parse(this.providerTarget.dataset.preferred) ?? [];
this.providerTarget.innerHTML = this.#serializeSelectOptions(this.providers);
this.providerTarget.tomselect.items = preferred;
}
addQualities(option) {
if (option.quality.toLowerCase() in this.reverseMappedQualitiesValue) {
let quality = this.reverseMappedQualitiesValue[option.quality.toLowerCase()];
// converts api returned quality with a value the system recognizes
option.quality = quality;
if (!this.qualities.includes(option.quality)) {
this.qualities.push(quality);
}
}
const preferred = JSON.parse(this.qualityTarget.dataset.preferred) ?? [];
this.qualityTarget.innerHTML = this.#serializeSelectOptions(this.qualities);
this.qualityTarget.tomselect.items = preferred;
}
filter() { filter() {
const downloadSeasonSpan = document.querySelector("#downloadSeasonModal"); const downloadSeasonSpan = document.querySelector("#downloadSeasonModal");

View File

@@ -30,11 +30,11 @@ export default class extends Controller {
option.querySelector('.download-btn').dataset['title'] = this.titleValue option.querySelector('.download-btn').dataset['title'] = this.titleValue
); );
this.element.options[0].querySelector('input[type="checkbox"]').checked = true; this.element.options[0].querySelector('input[type="checkbox"]').checked = true;
this.loadingIconOutlet.increaseCount();
document.dispatchEvent(new CustomEvent('optionsLoaded', {detail: {options: this.element.options}})); document.dispatchEvent(new CustomEvent('optionsLoaded', {detail: {options: this.element.options}}));
} else { } else {
this.countTarget.innerText = 0; this.countTarget.innerText = 0;
this.episodeSelectorTarget.disabled = true; this.episodeSelectorTarget.disabled = true;
} }
this.loadingIconOutlet.increaseCount();
} }
} }

View File

@@ -165,9 +165,9 @@ dialog[data-dialog-target="dialog"][closing] {
padding: 0; padding: 0;
.ts-control { .ts-control {
background: transparent !important;
border: none !important; border: none !important;
box-shadow: none !important; box-shadow: none !important;
@apply bg-orange-500/60 backdrop-filter backdrop-blur-md;
} }
.item[data-ts-item] { .item[data-ts-item] {
@@ -175,10 +175,10 @@ dialog[data-dialog-target="dialog"][closing] {
border: none; border: none;
box-shadow: none; box-shadow: none;
text-shadow: none; text-shadow: none;
@apply bg-orange-500 rounded-ms font-bold; @apply bg-orange-500 rounded-ms font-bold text-black;
} }
@apply border-b-2 border-b-orange-600 bg-transparent; @apply border border-orange-500 bg-transparent rounded-ms;
} }
.ts-wrapper.plugin-remove_button:not(.rtl) .item .remove { .ts-wrapper.plugin-remove_button:not(.rtl) .item .remove {

View File

@@ -0,0 +1,21 @@
<?php
namespace App\User\Framework\Controller\Api;
use App\User\Dto\UserPreferences;
use App\User\Dto\UserPreferencesFactory;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;
#[Route('/api/user/filters')]
class UserFilterApiController extends AbstractController
{
#[Route('', 'api.user.filters', methods: ['GET'])]
public function getFilters(): Response
{
return $this->json([
UserPreferencesFactory::createFromUser($this->getUser())
]);
}
}

View File

@@ -22,7 +22,7 @@
<label for="season"> <label for="season">
Season Season
</label> </label>
<select id="season" name="season" value="1" data-result-filter-target="season" class="px-1 mb-4 py-1 md:py-2 text-center bg-orange-500 rounded-ms" <select id="season" name="season" value="1" data-result-filter-target="season" class="px-1 mb-4 py-1 md:py-2 text-center bg-orange-500 rounded-ms text-black"
{{ stimulus_action('result_filter', 'setSeason', 'change') }} {{ stimulus_action('result_filter', 'setSeason', 'change') }}
{{ stimulus_action('result_filter', 'uncheckSelectAllBtn', 'change') }} {{ stimulus_action('result_filter', 'uncheckSelectAllBtn', 'change') }}
> >