forked from DebaucheryLibrarian/traxxx
180 lines
4.3 KiB
Vue
Executable File
180 lines
4.3 KiB
Vue
Executable File
<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>
|