traxxx/assets/components/filters/channel-filter.vue

180 lines
4.3 KiB
Vue

<template>
<Tooltip class="filter-container">
<div class="filter">
<Icon icon="antenna" />
<div
v-if="selectedLength > 0"
class="filter-applied"
>{{ selectedLength }} {{ selectedLength > 1 ? 'channels' : 'channel' }}</div>
<div
v-else
class="filter-applied empty"
>Channels</div>
</div>
<template v-slot:tooltip>
<div @click.stop>
<router-link
class="filter-clear"
:to="{ query: { ...$route.query, channels: undefined, networks: undefined } }"
:class="{ active: selectedLength > 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,
selected: channel.type === 'network' ? selectedNetworks.includes(channel.slug) : selectedChannels.includes(channel.slug),
disabled: channel.parent && selectedNetworks.includes(channel.parent.slug),
}"
>
<router-link
:to="{ query: {
...$route.query,
[channel.type === 'network' ? 'networks' : 'channels']: channel.slug,
[channel.type === 'network' ? 'channels' : 'networks']: undefined,
}, params: { pageNumber: 1 } }"
class="filter-name"
>
<img
v-if="channel.type === 'network' || 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) }, params: { pageNumber: 1 } }"
class="filter-include"
>
<Icon
icon="checkmark"
class="filter-add"
/>
<Icon
icon="cross2"
class="filter-remove"
/>
</router-link>
</li>
</ul>
</div>
</template>
</Tooltip>
</template>
<script>
function getNewRange(entity) {
if (entity.type === 'network' && this.selectedNetworks.includes(entity.slug)) {
return {
channels: this.selectedChannels.join(',') || undefined,
networks: this.selectedNetworks.filter(selectedTag => selectedTag !== entity.slug).join(',') || undefined,
};
}
if (entity.type === 'network') {
return {
channels: this.selectedChannels.join(',') || undefined,
networks: this.selectedNetworks.concat(entity.slug).join(','),
};
}
if (this.selectedChannels.includes(entity.slug)) {
return {
channels: this.selectedChannels.filter(selectedTag => selectedTag !== entity.slug).join(',') || undefined,
networks: this.selectedNetworks.join(',') || undefined,
};
}
return {
channels: this.selectedChannels.concat(entity.slug).join(','),
networks: this.selectedNetworks.join(',') || undefined,
};
}
function selectedChannels() {
return this.$route.query.channels ? this.$route.query.channels.split(',') : [];
}
function selectedNetworks() {
return this.$route.query.networks ? this.$route.query.networks.split(',') : [];
}
function channelsPerNetwork() {
const networks = this.availableChannels.reduce((acc, channel) => {
if (channel.type === 'network' || 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 || [])], []);
}
function selectedLength() {
return this.selectedChannels.length + this.selectedNetworks.length;
}
export default {
props: {
filter: {
type: Array,
default: () => [],
},
compact: {
type: Boolean,
default: false,
},
availableChannels: {
type: Array,
default: () => [],
},
},
computed: {
channelsPerNetwork,
selectedChannels,
selectedNetworks,
selectedLength,
},
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>