forked from DebaucheryLibrarian/traxxx
145 lines
3.1 KiB
Vue
145 lines
3.1 KiB
Vue
|
<template>
|
||
|
<v-popover class="filter-container">
|
||
|
<div class="filter">
|
||
|
<Icon icon="antenna" />
|
||
|
|
||
|
<div
|
||
|
v-if="selectedChannels.length > 0"
|
||
|
class="filter-applied"
|
||
|
>{{ selectedChannels.length }} {{ selectedChannels.length > 1 ? 'channels' : 'channel' }}</div>
|
||
|
|
||
|
<div
|
||
|
v-else
|
||
|
class="filter-applied empty"
|
||
|
>Channels</div>
|
||
|
</div>
|
||
|
|
||
|
<div slot="popover">
|
||
|
<router-link
|
||
|
class="filter-clear"
|
||
|
:to="{ query: { ...$route.query, channels: undefined } }"
|
||
|
:class="{ active: selectedChannels.length > 0 }"
|
||
|
>clear all<Icon icon="cross2" /></router-link>
|
||
|
|
||
|
<ul class="filter-items nolist">
|
||
|
<li
|
||
|
v-for="channel in channelsPerNetwork"
|
||
|
:key="`channel-${channel.id}`"
|
||
|
class="filter-item"
|
||
|
:class="{ [channel.type]: true, independent: channel.independent }"
|
||
|
>
|
||
|
<router-link
|
||
|
:to="{ query: { ...$route.query, channels: channel.slug, mode }, params: { pageNumber: 1 } }"
|
||
|
class="filter-name"
|
||
|
>
|
||
|
<img
|
||
|
v-if="channel.independent || !channel.parent"
|
||
|
:src="`/img/logos/${channel.slug}/favicon.png`"
|
||
|
class="favicon"
|
||
|
>
|
||
|
|
||
|
{{ channel.name }}
|
||
|
</router-link>
|
||
|
|
||
|
<router-link
|
||
|
:to="{ query: { ...$route.query, ...getNewRange(channel.slug), mode }, params: { pageNumber: 1 } }"
|
||
|
class="filter-include"
|
||
|
:class="{ selected: selectedChannels.includes(channel.slug) }"
|
||
|
>
|
||
|
<Icon
|
||
|
icon="checkmark"
|
||
|
class="filter-add"
|
||
|
/>
|
||
|
|
||
|
<Icon
|
||
|
icon="cross2"
|
||
|
class="filter-remove"
|
||
|
/>
|
||
|
</router-link>
|
||
|
</li>
|
||
|
</ul>
|
||
|
</div>
|
||
|
</v-popover>
|
||
|
</template>
|
||
|
|
||
|
<script>
|
||
|
function getNewRange(channel) {
|
||
|
if (this.selectedChannels.includes(channel)) {
|
||
|
return { channels: this.selectedChannels.filter(selectedTag => selectedTag !== channel).join(',') || undefined };
|
||
|
}
|
||
|
|
||
|
return { channels: this.selectedChannels.concat(channel).join(',') };
|
||
|
}
|
||
|
|
||
|
function selectedChannels() {
|
||
|
return this.$route.query.channels ? this.$route.query.channels.split(',') : [];
|
||
|
}
|
||
|
|
||
|
function channelsPerNetwork() {
|
||
|
const networks = this.availableChannels.reduce((acc, channel) => {
|
||
|
if (channel.independent || !channel.parent) {
|
||
|
acc[channel.slug] = { ...channel, children: [] };
|
||
|
return acc;
|
||
|
}
|
||
|
|
||
|
if (!acc[channel.parent.slug]) {
|
||
|
acc[channel.parent.slug] = { ...channel.parent, children: [] };
|
||
|
}
|
||
|
|
||
|
acc[channel.parent.slug].children.push(channel);
|
||
|
|
||
|
return acc;
|
||
|
}, {});
|
||
|
|
||
|
return Object.values(networks).reduce((acc, network) => [...acc, network, ...(network.children || [])], []);
|
||
|
}
|
||
|
|
||
|
export default {
|
||
|
props: {
|
||
|
filter: {
|
||
|
type: Array,
|
||
|
default: () => [],
|
||
|
},
|
||
|
compact: {
|
||
|
type: Boolean,
|
||
|
default: false,
|
||
|
},
|
||
|
availableChannels: {
|
||
|
type: Array,
|
||
|
default: () => [],
|
||
|
},
|
||
|
},
|
||
|
data() {
|
||
|
return {
|
||
|
mode: this.$route.query.mode || 'all',
|
||
|
};
|
||
|
},
|
||
|
computed: {
|
||
|
channelsPerNetwork,
|
||
|
selectedChannels,
|
||
|
},
|
||
|
methods: {
|
||
|
getNewRange,
|
||
|
},
|
||
|
};
|
||
|
</script>
|
||
|
|
||
|
<style lang="scss" scoped>
|
||
|
.favicon {
|
||
|
width: 1rem;
|
||
|
height: 1rem;
|
||
|
padding: 0 .75rem 0 0;
|
||
|
filter: drop-shadow(0 0 1px var(--darken));
|
||
|
}
|
||
|
|
||
|
.network .filter-name,
|
||
|
.independent .filter-name {
|
||
|
font-weight: bold;
|
||
|
padding: .5rem;
|
||
|
}
|
||
|
|
||
|
.channel:not(.independent) .filter-name {
|
||
|
padding: .5rem .5rem .5rem 2.25rem;
|
||
|
}
|
||
|
</style>
|