feat(filter): move filter string creating to component

Move the filter string creation the the FilterButton component, so the
view only has to handle fetching the data based on the options received
from the FilterButton event.
Also fix a lot of the other comments raised in the pull requests
This commit is contained in:
Alf Sebastian Houge 2020-10-28 17:04:16 +01:00
parent 06bbf5c948
commit 39348feff1
4 changed files with 146 additions and 198 deletions

View File

@ -17,8 +17,9 @@
:value="filter.value"
:true-value="true"
:false-value="false"
@change="$emit('input', filters)"
@change="emitFiltersOptions"
>
<!-- @change="$emit('change', filters)" -->
</v-checkbox>
</v-form>
</v-expansion-panel-content>
@ -38,17 +39,16 @@ interface FilterItem {
export default Vue.extend({
props: {
value: {
collectionInfoItem: {
type: Object,
required: true
}
},
data() {
return {
selectedFilters: this.value,
filters: {
filters: {
header: this.$t('filters'),
status: {
header: this.$t('status'),
items: [
{ label: this.$t('played'), value: 'IsPlayed', selected: false },
{
@ -119,74 +119,151 @@ export default Vue.extend({
header: this.$t('years'),
items: [] as FilterItem[]
}
}
},
selectedFilters: {}
};
},
computed: {
itemType() {
if (this.collectionInfoItem.CollectionType === 'tvshows') {
return 'Series';
} else if (this.collectionInfoItem.CollectionType === 'movies') {
return 'Movie';
} else if (this.collectionInfoItem.CollectionType === 'books') {
return 'Book';
}
return '';
}
},
methods: {
async getFilters() {
try {
const collectionInfo = await this.$api.items.getItems({
uId: this.$auth.user.Id,
userId: this.$auth.user.Id,
ids: this.$route.params.viewId
});
const options = {
userId: this.$auth.user.Id,
parentId: this.$route.params.viewId,
includeItemTypes: ''
};
if (!collectionInfo.data.Items) {
return;
}
if (collectionInfo.data.Items) {
options.includeItemTypes = 'sike';
}
if (collectionInfo.data.Items[0].CollectionType === 'tvshows') {
options.includeItemTypes = 'Series';
} else if (collectionInfo.data.Items[0].CollectionType === 'movies') {
options.includeItemTypes = 'Movie';
} else if (collectionInfo.data.Items[0].CollectionType === 'books') {
options.includeItemTypes = 'Book';
}
const result = await this.$api.filter.getQueryFiltersLegacy(options);
if (!result.data.Genres) {
if (this.itemType === '') {
return;
}
this.filters.genres.items = result.data.Genres.map((x) => ({
label: x,
value: x,
selected: false
}));
const response = (
await this.$api.filter.getQueryFiltersLegacy({
userId: this.$auth.user.Id,
parentId: this.$route.params.viewId,
includeItemTypes: this.itemType
})
).data;
if (!result.data.OfficialRatings) {
return;
}
this.filters.officialRatings.items = result.data.OfficialRatings.map(
(x) => ({
if (response.Genres) {
this.filters.genres.items = response.Genres.map((x) => ({
label: x,
value: x,
selected: false
})
);
if (!result.data.Years) {
return;
}));
}
if (response.OfficialRatings) {
this.filters.officialRatings.items = response.OfficialRatings.map(
(x) => ({
label: x,
value: x,
selected: false
})
);
}
if (response.Years) {
this.filters.years.items = response.Years.map((x) => ({
label: x.toString(),
value: x.toString(),
selected: false
}));
}
this.filters.years.items = result.data.Years.map((x) => ({
label: x.toString(),
value: x.toString(),
selected: false
}));
} catch (error) {
this.$nuxt.error({
statusCode: 404,
message: this.$t('filtersNotFound') as string
});
}
},
emitFiltersOptions() {
try {
if (
this.collectionInfoItem !== {} &&
(this.collectionInfoItem.Type === 'CollectionFolder' ||
this.collectionInfoItem.Type === 'Folder')
) {
const options: any = {
uId: this.$auth.user.Id,
userId: this.$auth.user.Id,
parentId: this.$route.params.viewId,
includeItemTypes: this.itemType,
recursive: true
};
options.filters = this.makeFilterString(
this.filters.status.items,
','
);
for (const feature of this.filters.features.items) {
if (!feature.selected) {
continue;
}
options[feature.value] = true;
}
options.genres = this.makeFilterString(
this.filters.genres.items,
'|'
);
options.officialRatings = this.makeFilterString(
this.filters.officialRatings.items,
'|'
);
let videoTypeString = '';
for (const videoType of this.filters.videoTypes.items) {
if (!videoType.selected) {
continue;
}
if (videoType.label === 'SD') {
options.isHd = false;
continue;
}
if (videoType.label === 'HD') {
options.isHd = true;
continue;
}
if (videoType.label === '4K' || videoType.label === '3D') {
options[videoType.value] = true;
} else {
if (videoTypeString.length > 0) {
videoTypeString += ',';
}
videoTypeString += videoType.value;
}
}
options.videoTypes = videoTypeString;
options.years = this.makeFilterString(this.filters.years.items, ',');
this.$emit('change', options);
}
} catch (error) {
this.$emit('change', error);
}
},
makeFilterString(filterList: FilterItem[], seperator: string) {
let filterString = '';
for (const filter of filterList) {
if (!filter.selected) {
continue;
}
if (filterString.length > 0) {
filterString += seperator;
}
filterString += filter.value;
}
return filterString;
}
}
});

View File

@ -33,7 +33,7 @@
"unexpectedError": "Unexpected error",
"upNext": "Up next",
"filtersNotFound": "Unable to load filters",
"filters": "Filters",
"status": "Status",
"played": "Played",
"unplayed": "Unplayed",
"resumable": "Resumable",

View File

@ -32,7 +32,7 @@
"endDate": "Sluttdato",
"releaseDate": "Slippdato",
"alphabetically": "Alfabetisk",
"filters": "Filtere",
"status": "Status",
"played": "Avspilt",
"unplayed": "Uspilt",
"resumable": "Gjenopptakbar",

View File

@ -19,7 +19,10 @@
</v-col>
<v-col>
<filter-button v-model="allFilters" @input="filterMedia()" />
<filter-button
:collection-info-item="collectionInfoItem"
@change="filterMedia"
/>
</v-col>
</v-row>
<v-row v-if="!loaded">
@ -64,12 +67,6 @@ import Vue from 'vue';
import { chunk } from 'lodash';
import { BaseItemDto } from '~/api/api';
interface FilterItem {
label: string;
value: string;
selected: boolean;
}
export default Vue.extend({
data() {
return {
@ -83,32 +80,6 @@ export default Vue.extend({
],
orderMethod: 'SortName',
sortDirection: true,
allFilters: {
filters: {
header: '',
items: [] as FilterItem[]
},
features: {
header: '',
items: [] as FilterItem[]
},
genres: {
header: '',
items: [] as FilterItem[]
},
officialRatings: {
header: '',
items: [] as FilterItem[]
},
videoTypes: {
header: '',
items: [] as FilterItem[]
},
years: {
header: '',
items: [] as FilterItem[]
}
},
collectionInfoItem: {}
};
},
@ -201,104 +172,19 @@ export default Vue.extend({
}
},
methods: {
async filterMedia() {
async filterMedia(options: any) {
try {
const collectionInfo = await this.$api.items.getItems({
uId: this.$auth.user.Id,
userId: this.$auth.user.Id,
ids: this.$route.params.viewId
});
options.sortBy = this.orderMethod;
options.sortOrder = this.sortDirection;
options.fields = this.orderMethod;
if (
collectionInfo.data.Items &&
(collectionInfo.data.Items[0].Type === 'CollectionFolder' ||
collectionInfo.data.Items[0].Type === 'Folder')
) {
const options: any = {
uId: this.$auth.user.Id,
userId: this.$auth.user.Id,
parentId: this.$route.params.viewId,
includeItemTypes: '',
recursive: true,
sortBy: this.orderMethod,
sortOrder: this.sortDirection,
fields: this.orderMethod
};
const itemsResponse = await this.$api.items.getItems(options);
if (collectionInfo.data.Items[0].CollectionType === 'tvshows') {
options.includeItemTypes = 'Series';
} else if (collectionInfo.data.Items[0].CollectionType === 'movies') {
options.includeItemTypes = 'Movie';
} else if (collectionInfo.data.Items[0].CollectionType === 'books') {
options.includeItemTypes = 'Book';
}
const filterString = this.makeFilterString(
this.allFilters.filters.items,
','
);
options.filters = filterString;
for (let i = 0; i < this.allFilters.features.items.length; i++) {
const feature = this.allFilters.features.items[i];
if (!feature.selected) {
continue;
}
options[feature.value] = true;
}
const genreString = this.makeFilterString(
this.allFilters.genres.items,
'|'
);
options.genres = genreString;
const ratingString = this.makeFilterString(
this.allFilters.officialRatings.items,
'|'
);
options.officialRatings = ratingString;
let videoTypeString = '';
for (let i = 0; i < this.allFilters.videoTypes.items.length; i++) {
const videoType = this.allFilters.videoTypes.items[i];
if (!videoType.selected) {
continue;
}
if (videoType.label === 'SD') {
options.isHd = false;
continue;
}
if (videoType.label === 'HD') {
options.isHd = true;
continue;
}
if (videoType.label === '4K' || videoType.label === '3D') {
options[videoType.value] = true;
} else {
if (videoTypeString.length > 0) {
videoTypeString += ',';
}
videoTypeString += videoType.value;
}
}
options.videoTypes = videoTypeString;
const yearString = this.makeFilterString(
this.allFilters.years.items,
','
);
options.years = yearString;
const itemsResponse = await this.$api.items.getItems(options);
if (itemsResponse.data) {
this.loaded = true;
}
this.items = itemsResponse.data.Items || [];
if (itemsResponse.data) {
this.loaded = true;
}
this.items = itemsResponse.data.Items || [];
} catch (error) {
// Can't get given library ID
this.$nuxt.error({
@ -307,21 +193,6 @@ export default Vue.extend({
});
}
},
makeFilterString(filterList: FilterItem[], seperator: string) {
let filterString = '';
for (let i = 0; i < filterList.length; i++) {
const filter = filterList[i];
if (!filter.selected) {
continue;
}
if (filterString.length > 0) {
filterString += seperator;
}
filterString += filter.value;
}
return filterString;
},
sortItems() {
if (this.sortDirection) {
this.items.sort((a, b) =>