Added channel filter.

This commit is contained in:
DebaucheryLibrarian 2020-07-20 04:20:33 +02:00
parent 5291a87587
commit 0e4c0d8fff
143 changed files with 537 additions and 302 deletions

View File

@ -296,6 +296,7 @@
:items-total="totalCount" :items-total="totalCount"
:items-per-page="limit" :items-per-page="limit"
:available-tags="actor.tags" :available-tags="actor.tags"
:available-channels="actor.channels"
/> />
<Releases :releases="releases" /> <Releases :releases="releases" />
@ -312,7 +313,7 @@
<script> <script>
import Pagination from '../pagination/pagination.vue'; import Pagination from '../pagination/pagination.vue';
import FilterBar from '../header/filter-bar.vue'; import FilterBar from '../filters/filter-bar.vue';
import Releases from '../releases/releases.vue'; import Releases from '../releases/releases.vue';
import Photos from './photos.vue'; import Photos from './photos.vue';
import Expand from '../expand/expand.vue'; import Expand from '../expand/expand.vue';
@ -402,7 +403,7 @@ export default {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
color: var(--highlight-extreme); color: var(--lighten-extreme);
background: var(--profile); background: var(--profile);
padding: .75rem 1rem; padding: .75rem 1rem;
} }
@ -429,7 +430,7 @@ export default {
.profile { .profile {
background: var(--profile); background: var(--profile);
color: var(--highlight-extreme); color: var(--lighten-extreme);
width: 100%; width: 100%;
max-height: 18rem; max-height: 18rem;
display: flex; display: flex;
@ -486,7 +487,7 @@ export default {
overflow: hidden; overflow: hidden;
&:not(:last-of-type) { &:not(:last-of-type) {
border-bottom: solid 1px var(--highlight-hint); border-bottom: solid 1px var(--lighten-hint);
} }
} }
@ -497,14 +498,14 @@ export default {
} }
.bio-label { .bio-label {
color: var(--highlight); color: var(--lighten);
margin: 0 1rem 0 0; margin: 0 1rem 0 0;
flex-shrink: 0; flex-shrink: 0;
font-style: normal; font-style: normal;
font-weight: 400; font-weight: 400;
.icon { .icon {
fill: var(--highlight); fill: var(--lighten);
margin: -.25rem .5rem 0 0; margin: -.25rem .5rem 0 0;
} }
} }
@ -538,7 +539,7 @@ export default {
.age { .age {
font-weight: bold; font-weight: bold;
padding: 0 0 0 .5rem; padding: 0 0 0 .5rem;
border-left: solid 1px var(--highlight-weak); border-left: solid 1px var(--lighten-weak);
margin: 0 0 0 .5rem; margin: 0 0 0 .5rem;
} }
@ -554,7 +555,7 @@ export default {
.height-imperial, .height-imperial,
.weight-imperial { .weight-imperial {
padding: 0 0 0 .5rem; padding: 0 0 0 .5rem;
border-left: solid 1px var(--highlight-weak); border-left: solid 1px var(--lighten-weak);
margin: 0 0 0 .5rem; margin: 0 0 0 .5rem;
} }
@ -571,7 +572,7 @@ export default {
} }
.scraped { .scraped {
color: var(--highlight-weak); color: var(--lighten-weak);
font-size: .8rem; font-size: .8rem;
} }

View File

@ -110,7 +110,7 @@
<script> <script>
import Vue from 'vue'; import Vue from 'vue';
import FilterBar from '../header/filter-bar.vue'; import FilterBar from '../filters/filter-bar.vue';
import Pagination from '../pagination/pagination.vue'; import Pagination from '../pagination/pagination.vue';
import Releases from '../releases/releases.vue'; import Releases from '../releases/releases.vue';
import Children from './children.vue'; import Children from './children.vue';

View File

@ -0,0 +1,144 @@
<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>

View File

@ -1,6 +1,6 @@
<template> <template>
<div class="filter-bar noselect"> <div class="filter-bar noselect">
<span class="sort"> <div class="sort">
<router-link <router-link
:to="{ params: { range: 'latest', pageNumber: 1 } }" :to="{ params: { range: 'latest', pageNumber: 1 } }"
:class="{ active: $route.name === 'latest' || range === 'latest' }" :class="{ active: $route.name === 'latest' || range === 'latest' }"
@ -18,20 +18,28 @@
:class="{ active: $route.name === 'new' || range === 'new' }" :class="{ active: $route.name === 'new' || range === 'new' }"
class="range-button" class="range-button"
>New</router-link> >New</router-link>
</span> </div>
<Filters <div class="filters">
class="filters" <ChannelFilter
:filter="filter" class="filter"
:available-tags="availableTags" :filter="filter"
@set-filter="setFilter" :available-channels="availableChannels"
/> />
<TagFilter
class="filter"
:filter="filter"
:available-tags="availableTags"
/>
</div>
</div> </div>
</template> </template>
<script> <script>
import { mapState } from 'vuex'; import { mapState } from 'vuex';
import Filters from './filters.vue'; import ChannelFilter from './channel-filter.vue';
import TagFilter from './tag-filter.vue';
function filter(state) { function filter(state) {
return state.ui.filter; return state.ui.filter;
@ -45,12 +53,6 @@ function batch(state) {
return state.ui.batch; return state.ui.batch;
} }
async function setFilter(newFilter) {
this.$store.dispatch('setFilter', newFilter);
await this.fetchReleases();
}
async function setRange(newRange) { async function setRange(newRange) {
this.$store.dispatch('setRange', newRange); this.$store.dispatch('setRange', newRange);
@ -65,7 +67,8 @@ async function setBatch(newBatch) {
export default { export default {
components: { components: {
Filters, ChannelFilter,
TagFilter,
}, },
props: { props: {
fetchReleases: { fetchReleases: {
@ -88,6 +91,10 @@ export default {
type: Array, type: Array,
default: () => [], default: () => [],
}, },
availableChannels: {
type: Array,
default: () => [],
},
}, },
computed: { computed: {
...mapState({ ...mapState({
@ -97,13 +104,156 @@ export default {
}), }),
}, },
methods: { methods: {
setFilter,
setRange, setRange,
setBatch, setBatch,
}, },
}; };
</script> </script>
<style lang="scss">
@import 'breakpoints';
.filter {
color: var(--shadow);
display: inline-flex;
align-items: center;
.icon {
fill: var(--shadow);
margin: -.1rem 0 0 0;
}
&:hover {
cursor: pointer;
.applied {
color: var(--shadow-strong);
}
.icon {
fill: var(--shadow-strong);
}
}
}
.filter-applied {
flex-grow: 1;
padding: .75rem .5rem;
font-size: 1rem;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
text-align: right;
&.empty {
color: var(--shadow);
}
}
.filter-mode {
width: 100%;
background: none;
padding: .75rem;
margin: 0 0 .5rem 0;
font-size: 1rem;
border: none;
border-bottom: solid 1px var(--shadow-hint);
}
.filter-clear {
display: flex;
align-items: center;
justify-content: space-between;
padding: .5rem 1rem;
color: var(--darken-weak);
text-decoration: none;
cursor: default;
.icon {
fill: var(--darken-hint);
margin: 0 0 0 1rem;
}
&.active {
color: var(--darken);
.icon {
fill: var(--darken-weak);
}
&:hover {
color: var(--text);
background: var(--darken-hint);
cursor: pointer;
.icon {
fill: var(--alert);
}
}
}
}
.filter-items .filter-item {
display: flex;
align-items: center;
&:hover {
background: var(--darken-hint);
cursor: pointer;
}
&.selected .filter-include .filter-add {
fill: var(--success);
}
}
.filter-include {
.icon {
width: 1rem;
height: 1rem;
padding: .5rem 1rem;
fill: var(--darken-hint);
}
.filter-remove {
display: none;
fill: var(--alert);
}
&:hover {
cursor: pointer;
&.selected .filter-add {
display: none;
}
&.selected .filter-remove {
display: inline-block;
}
}
}
.filter-name {
min-width: 8rem;
display: flex;
flex-grow: 1;
padding: .5rem .75rem .5rem 1rem;
color: var(--text);
text-decoration: none;
}
.filter-include:hover,
.filter-name:hover {
background: var(--darken-hint);
}
@media(max-width: $breakpoint-micro) {
.filter-applied {
display: none;
}
}
</style>
<style lang="scss" scoped> <style lang="scss" scoped>
@import 'theme'; @import 'theme';
@ -162,8 +312,12 @@ export default {
} }
} }
.filters { .filter {
display: inline-block; display: inline-block;
flex-shrink: 0; flex-shrink: 0;
&:not(:last-child) {
margin: 0 1rem 0 0;
}
} }
</style> </style>

View File

@ -0,0 +1,111 @@
<template>
<v-popover class="filter-container">
<div class="filter">
<Icon icon="price-tag4" />
<div
v-if="selectedTags.length > 0"
class="filter-applied"
>{{ selectedTags.length }} {{ selectedTags.length > 1 ? 'tags' : 'tag' }}</div>
<div
v-else
class="filter-applied empty"
>Tags</div>
</div>
<div slot="popover">
<select
v-model="mode"
class="filter-mode"
@change="$router.push({ query: { ...$route.query, mode }, params: { pageNumber: 1 } })"
>
<option value="all">match all selected</option>
<option value="any">match any selected</option>
</select>
<router-link
class="filter-clear"
:to="{ query: { ...$route.query, tags: undefined, mode: undefined } }"
:class="{ active: selectedTags.length > 0 }"
>clear all<Icon icon="cross2" /></router-link>
<ul class="filter-items nolist">
<li
v-for="tag in availableTags"
:key="`tag-${tag.id}`"
class="filter-item"
:class="{ selected: selectedTags.includes(tag.slug) }"
>
<router-link
:to="{ query: { ...$route.query, tags: tag.slug, mode }, params: { pageNumber: 1 } }"
class="filter-name"
>{{ tag.name }}</router-link>
<router-link
:to="{ query: { ...$route.query, ...getNewRange(tag.slug), mode }, params: { pageNumber: 1 } }"
class="filter-include"
:class="{ selected: selectedTags.includes(tag.slug) }"
>
<Icon
icon="checkmark"
class="filter-add"
/>
<Icon
icon="cross2"
class="filter-remove"
/>
</router-link>
</li>
</ul>
</div>
</v-popover>
</template>
<script>
function getNewRange(tag) {
if (this.selectedTags.includes(tag)) {
return { tags: this.selectedTags.filter(selectedTag => selectedTag !== tag).join(',') || undefined };
}
return { tags: this.selectedTags.concat(tag).join(',') };
}
function selectedTags() {
return this.$route.query.tags ? this.$route.query.tags.split(',') : [];
}
export default {
props: {
filter: {
type: Array,
default: () => [],
},
compact: {
type: Boolean,
default: false,
},
availableTags: {
type: Array,
default: () => [],
},
},
data() {
return {
mode: this.$route.query.mode || 'all',
};
},
computed: {
selectedTags,
},
methods: {
getNewRange,
},
};
</script>
<style lang="scss" scoped>
@import 'theme';
</style>

View File

@ -1,249 +0,0 @@
<template>
<v-popover class="filters-container">
<div class="filters">
<Icon icon="price-tag4" />
<div
v-if="selectedTags.length > 0"
class="applied"
>{{ selectedTags.length }} tag filters</div>
<div
v-else
class="applied empty"
>Filter by tags</div>
</div>
<div slot="popover">
<select
v-model="mode"
class="mode"
@change="$router.push({ query: { ...$route.query, mode }, params: { pageNumber: 1 } })"
>
<option
value="all"
class="option"
>match all selected</option>
<option
value="any"
class="option"
>match any selected</option>
</select>
<router-link
v-if="selectedTags.length > 1"
class="reset"
:to="{}"
><Icon icon="cross2" />clear all</router-link>
<ul class="tags nolist">
<li
v-for="tag in availableTags"
:key="`tag-${tag.id}`"
class="tag"
:class="{ selected: selectedTags.includes(tag.slug) }"
>
<router-link
:to="{ query: { ...getNewRange(tag.slug), mode }, params: { pageNumber: 1 } }"
class="include"
:class="{ selected: selectedTags.includes(tag.slug) }"
>
<Icon
icon="checkmark"
class="add"
/>
<Icon
icon="cross2"
class="remove"
/>
</router-link>
<router-link
:to="{ query: { tags: tag.slug, mode }, params: { pageNumber: 1 } }"
class="name"
>{{ tag.name }}</router-link>
</li>
</ul>
</div>
</v-popover>
</template>
<script>
function getNewRange(tag) {
if (this.selectedTags.includes(tag)) {
if (this.selectedTags.length > 1) {
return { tags: this.selectedTags.filter(selectedTag => selectedTag !== tag).join(',') };
}
return {};
}
return { tags: this.selectedTags.concat(tag).join(',') };
}
function selectedTags() {
return this.$route.query.tags ? this.$route.query.tags.split(',') : [];
}
export default {
props: {
filter: {
type: Array,
default: () => [],
},
compact: {
type: Boolean,
default: false,
},
availableTags: {
type: Array,
default: () => [],
},
},
data() {
return {
mode: this.$route.query.mode || 'all',
};
},
computed: {
selectedTags,
},
methods: {
getNewRange,
},
};
</script>
<style lang="scss" scoped>
@import 'theme';
.filters {
color: var(--shadow);
display: inline-flex;
align-items: center;
.icon {
fill: var(--shadow);
margin: -.1rem 0 0 0;
}
&:hover {
cursor: pointer;
.applied {
color: var(--shadow-strong);
}
.icon {
fill: var(--shadow-strong);
}
}
}
.applied {
flex-grow: 1;
padding: .75rem .5rem;
font-size: 1rem;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
text-align: right;
&.empty {
color: var(--shadow);
}
}
.mode {
width: 100%;
background: none;
padding: .75rem;
margin: 0 0 .5rem 0;
font-size: 1rem;
border: none;
border-bottom: solid 1px var(--shadow-hint);
}
.tag {
display: flex;
align-items: center;
.include {
.icon {
width: 1rem;
height: 1rem;
padding: .5rem .75rem .5rem 1rem;
fill: var(--darken-hint);
}
.remove {
display: none;
fill: var(--alert);
}
&:hover {
cursor: pointer;
&.selected .add {
display: none;
}
&.selected .remove {
display: inline-block;
}
}
}
.name {
min-width: 8rem;
display: flex;
justify-content: space-between;
flex-grow: 1;
padding: .5rem 1rem .5rem .75rem;
color: var(--text);
text-decoration: none;
}
&:hover {
background: var(--darken-hint);
cursor: pointer;
}
.include:hover,
.name:hover {
background: var(--darken-hint);
}
&.selected .include .add {
fill: var(--success);
}
}
.reset {
display: flex;
align-items: center;
padding: .25rem 0;
color: var(--text);
text-decoration: none;
.icon {
fill: var(--darken-weak);
padding: .5rem 1.5rem .5rem 1rem;
}
&:hover {
background: var(--darken-hint);
.icon {
fill: var(--alert);
}
}
}
@media(max-width: $breakpoint0) {
.applied {
display: none;
}
}
</style>

View File

@ -4,13 +4,7 @@
<div <div
class="sidebar-toggle" class="sidebar-toggle"
@click.stop="toggleSidebar" @click.stop="toggleSidebar"
> ><Icon icon="menu" /></div>
<Icon icon="menu" />
<div
class="logo"
v-html="logo"
/>
</div>
<router-link <router-link
to="/" to="/"
@ -82,7 +76,7 @@
<Icon <Icon
v-show="sfw" v-show="sfw"
v-tooltip="'Hit N to disable safe mode'" v-tooltip="'Hit N to disable safe mode'"
icon="evil2" icon="fire"
class="toggle noselect" class="toggle noselect"
@click.native="setSfw(false)" @click.native="setSfw(false)"
/> />
@ -215,11 +209,6 @@ export default {
align-items: center; align-items: center;
height: 100%; height: 100%;
.logo {
fill: var(--primary);
padding: .5rem;
}
.icon { .icon {
display: inline-block; display: inline-block;
fill: var(--shadow-modest); fill: var(--shadow-modest);
@ -354,14 +343,17 @@ export default {
} }
@media(max-width: $breakpoint-micro) { @media(max-width: $breakpoint-micro) {
.nav, .nav {
.header-logo {
display: none; display: none;
} }
.sidebar-toggle { .sidebar-toggle {
display: flex; display: flex;
} }
.header-logo {
padding: 0 0 0 .5rem;
}
} }
@media(max-width: $breakpoint-nano) { @media(max-width: $breakpoint-nano) {

View File

@ -25,7 +25,7 @@
</template> </template>
<script> <script>
import FilterBar from '../header/filter-bar.vue'; import FilterBar from '../filters/filter-bar.vue';
import Releases from '../releases/releases.vue'; import Releases from '../releases/releases.vue';
import Pagination from '../pagination/pagination.vue'; import Pagination from '../pagination/pagination.vue';

View File

@ -96,7 +96,7 @@
v-show="sfw" v-show="sfw"
class="toggle" class="toggle"
@click="setSfw(false)" @click="setSfw(false)"
><Icon icon="evil2" />Disable safe mode</label> ><Icon icon="fire" />Disable safe mode</label>
<label <label
v-show="!sfw" v-show="!sfw"

View File

@ -41,7 +41,7 @@ import { Converter } from 'showdown';
import escapeHtml from '../../../src/utils/escape-html'; import escapeHtml from '../../../src/utils/escape-html';
import FilterBar from '../header/filter-bar.vue'; import FilterBar from '../filters/filter-bar.vue';
import Photos from './photos.vue'; import Photos from './photos.vue';
import Releases from '../releases/releases.vue'; import Releases from '../releases/releases.vue';
import Scroll from '../scroll/scroll.vue'; import Scroll from '../scroll/scroll.vue';

View File

@ -161,7 +161,7 @@ export default {
color: var(--primary); color: var(--primary);
padding: 0 .5rem; padding: 0 .5rem;
margin: .5rem 0 1rem 0; margin: .5rem 0 1rem 0;
font-size: 1rem; font-size: 1.2rem;
text-transform: capitalize; text-transform: capitalize;
} }

View File

@ -0,0 +1,7 @@
<!-- Generated by IcoMoon.io -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
<title>antenna</title>
<path d="M11.182 11.932c-0.192 0-0.384-0.073-0.53-0.22-0.293-0.293-0.293-0.768 0-1.061 1.462-1.462 1.462-3.841 0-5.303s-3.841-1.462-5.303 0c-0.708 0.708-1.098 1.65-1.098 2.652s0.39 1.943 1.098 2.652c0.293 0.293 0.293 0.768 0 1.061s-0.768 0.293-1.061 0c-0.992-0.992-1.538-2.31-1.538-3.712s0.546-2.721 1.538-3.712c2.047-2.047 5.378-2.047 7.425 0s2.047 5.378 0 7.425c-0.146 0.146-0.338 0.22-0.53 0.22v0z"></path>
<path d="M13.127 13.877c-0.192 0-0.384-0.073-0.53-0.22-0.293-0.293-0.293-0.768 0-1.061 2.534-2.534 2.534-6.658 0-9.192s-6.658-2.534-9.192 0c-2.534 2.534-2.534 6.658 0 9.192 0.293 0.293 0.293 0.768 0 1.061s-0.768 0.293-1.061 0c-1.511-1.511-2.343-3.52-2.343-5.657s0.832-4.146 2.343-5.657c1.511-1.511 3.52-2.343 5.657-2.343s4.146 0.832 5.657 2.343c1.511 1.511 2.343 3.52 2.343 5.657s-0.832 4.146-2.343 5.657c-0.146 0.146-0.338 0.22-0.53 0.22v0z"></path>
<path d="M9.5 15h-0.501l0.001-5.268c0.598-0.346 1-0.992 1-1.732 0-1.105-0.895-2-2-2s-2 0.895-2 2c0 0.74 0.402 1.386 1 1.732l-0.001 5.268h-0.499c-0.276 0-0.5 0.224-0.5 0.5s0.224 0.5 0.5 0.5h3c0.276 0 0.5-0.224 0.5-0.5s-0.224-0.5-0.5-0.5z"></path>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -0,0 +1,5 @@
<!-- Generated by IcoMoon.io -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
<title>antenna2</title>
<path d="M5 16h6l-2-2v-7.268c0.598-0.346 1-0.992 1-1.732 0-1.105-0.895-2-2-2s-2 0.895-2 2c0 0.74 0.402 1.386 1 1.732v7.268l-2 2zM11.122 2.5c0.549 0.685 0.878 1.554 0.878 2.5s-0.329 1.815-0.878 2.5l0.781 0.625c0.686-0.856 1.097-1.942 1.097-3.125s-0.411-2.269-1.097-3.125l-0.781 0.625zM4.097 1.875c-0.686 0.856-1.097 1.942-1.097 3.125s0.411 2.269 1.097 3.125l0.781-0.625c-0.549-0.685-0.878-1.554-0.878-2.5s0.329-1.815 0.878-2.5l-0.781-0.625zM1.755 0c-1.098 1.37-1.755 3.108-1.755 5s0.657 3.63 1.755 5l0.781-0.625c-0.961-1.198-1.536-2.719-1.536-4.375s0.575-3.176 1.536-4.375l-0.781-0.625zM14.245 0l-0.781 0.625c0.961 1.198 1.536 2.719 1.536 4.375s-0.575 3.176-1.536 4.375l0.781 0.625c1.098-1.37 1.755-3.108 1.755-5s-0.657-3.63-1.755-5z"></path>
</svg>

After

Width:  |  Height:  |  Size: 904 B

View File

@ -0,0 +1,5 @@
<!-- Generated by IcoMoon.io -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
<title>camera</title>
<path d="M4.75 9.5c0 1.795 1.455 3.25 3.25 3.25s3.25-1.455 3.25-3.25-1.455-3.25-3.25-3.25-3.25 1.455-3.25 3.25zM15 4h-3.5c-0.25-1-0.5-2-1.5-2h-4c-1 0-1.25 1-1.5 2h-3.5c-0.55 0-1 0.45-1 1v9c0 0.55 0.45 1 1 1h14c0.55 0 1-0.45 1-1v-9c0-0.55-0.45-1-1-1zM8 13.938c-2.451 0-4.438-1.987-4.438-4.438s1.987-4.438 4.438-4.438c2.451 0 4.438 1.987 4.438 4.438s-1.987 4.438-4.438 4.438zM15 7h-2v-1h2v1z"></path>
</svg>

After

Width:  |  Height:  |  Size: 559 B

View File

@ -0,0 +1,5 @@
<!-- Generated by IcoMoon.io -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
<title>display</title>
<path d="M0 1v10h16v-10h-16zM15 10h-14v-8h14v8zM10.5 12h-5l-0.5 2-1 1h8l-1-1z"></path>
</svg>

After

Width:  |  Height:  |  Size: 248 B

View File

@ -0,0 +1,5 @@
<!-- Generated by IcoMoon.io -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
<title>display4</title>
<path d="M16 13v-12h-16v12h7v1h-3v1h8v-1h-3v-1h7zM2 3h12v8h-12v-8z"></path>
</svg>

After

Width:  |  Height:  |  Size: 238 B

View File

@ -0,0 +1,5 @@
<!-- Generated by IcoMoon.io -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
<title>station</title>
<path d="M10 5c0-1.105-0.895-2-2-2s-2 0.895-2 2c0 0.709 0.369 1.331 0.925 1.686l-2.54 9.314h1.231l0.273-1h4.224l0.273 1h1.231l-2.54-9.314c0.556-0.355 0.925-0.977 0.925-1.686zM9.294 12h-2.587l0.273-1h2.042l0.273 1zM7.252 10l0.748-2.743 0.748 2.743h-1.496zM6.161 14l0.273-1h3.133l0.273 1h-3.678zM10.38 0.602c1.56 0.846 2.62 2.498 2.62 4.398s-1.059 3.552-2.62 4.398c0.689-1.096 1.12-2.66 1.12-4.398s-0.431-3.302-1.12-4.398zM13.38 0.602c1.56 0.846 2.62 2.498 2.62 4.398s-1.059 3.552-2.62 4.398c0.689-1.096 1.12-2.66 1.12-4.398s-0.431-3.302-1.12-4.398zM5.62 9.398c-1.56-0.846-2.62-2.498-2.62-4.398s1.059-3.552 2.62-4.398c-0.689 1.096-1.12 2.66-1.12 4.398s0.431 3.302 1.12 4.398zM0 5c0-1.9 1.059-3.552 2.62-4.398-0.689 1.096-1.12 2.66-1.12 4.398s0.431 3.302 1.12 4.398c-1.56-0.846-2.62-2.498-2.62-4.398z"></path>
</svg>

After

Width:  |  Height:  |  Size: 968 B

View File

@ -0,0 +1,9 @@
<!-- Generated by IcoMoon.io -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
<title>station2</title>
<path d="M3.128 11.347l0.643-1.415c-1.389-1.193-2.271-2.961-2.271-4.932 0-1.535 0.535-2.947 1.428-4.060l-1.174-0.94c-1.136 1.414-1.754 3.159-1.754 5 0 2.137 0.832 4.146 2.343 5.657 0.249 0.249 0.511 0.478 0.785 0.69z"></path>
<path d="M12.229 9.932l0.643 1.415c0.274-0.211 0.536-0.441 0.785-0.69 1.511-1.511 2.343-3.52 2.343-5.657 0-1.84-0.618-3.585-1.754-5l-1.174 0.94c0.893 1.113 1.428 2.525 1.428 4.060 0 1.971-0.882 3.739-2.271 4.932z"></path>
<path d="M11.006 7.242l0.68 1.496c0.009-0.009 0.018-0.017 0.026-0.025 1.909-1.909 2.037-4.934 0.386-6.993l-1.171 0.937c1.067 1.331 1.093 3.226 0.079 4.585z"></path>
<path d="M4.288 8.712c0.009 0.009 0.017 0.017 0.026 0.025l0.68-1.496c-1.015-1.359-0.988-3.254 0.079-4.585l-1.171-0.937c-1.651 2.060-1.523 5.084 0.386 6.993z"></path>
<path d="M10 5c0-1.105-0.895-2-2-2s-2 0.895-2 2c0 0.583 0.25 1.108 0.648 1.473l-4.33 9.527h1.648l0.909-2h6.252l0.909 2h1.648l-4.33-9.527c0.398-0.366 0.648-0.89 0.648-1.473zM8 7.123l1.308 2.877h-2.616l1.308-2.877zM10.671 13h-5.343l0.909-2h3.525l0.909 2z"></path>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

5
assets/img/icons/tv.svg Normal file
View File

@ -0,0 +1,5 @@
<!-- Generated by IcoMoon.io -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
<title>tv</title>
<path d="M15.331 4.502c-1.388-0.199-2.865-0.344-4.407-0.425l2.576-2.576-1-1-3.509 3.509c-0.328-0.006-0.659-0.009-0.991-0.009v0l-4-4-1 1 3.034 3.034c-1.889 0.066-3.693 0.227-5.365 0.467-0.43 1.683-0.669 3.543-0.669 5.498s0.239 3.815 0.669 5.498c2.244 0.323 4.724 0.502 7.331 0.502s5.087-0.179 7.331-0.502c0.43-1.683 0.669-3.543 0.669-5.498s-0.239-3.815-0.669-5.498zM13.498 13.666c-1.683 0.215-3.543 0.334-5.498 0.334s-3.815-0.119-5.498-0.334c-0.323-1.122-0.502-2.362-0.502-3.666s0.179-2.543 0.502-3.666c1.683-0.215 3.543-0.334 5.498-0.334s3.815 0.119 5.498 0.334c0.323 1.122 0.502 2.362 0.502 3.666s-0.179 2.543-0.502 3.666z"></path>
</svg>

After

Width:  |  Height:  |  Size: 789 B

View File

@ -12,6 +12,7 @@ function initActorActions(store, router) {
range = 'latest', range = 'latest',
}) { }) {
const { before, after, orderBy } = getDateRange(range); const { before, after, orderBy } = getDateRange(range);
const includeChannels = router.currentRoute.query.channels ? router.currentRoute.query.channels.split(',') : [];
const includeTags = router.currentRoute.query.tags ? router.currentRoute.query.tags.split(',') : []; const includeTags = router.currentRoute.query.tags ? router.currentRoute.query.tags.split(',') : [];
const mode = router.currentRoute.query.mode || 'all'; const mode = router.currentRoute.query.mode || 'all';
@ -26,6 +27,7 @@ function initActorActions(store, router) {
$selectableTags: [String], $selectableTags: [String],
$includeTags: [String!], $includeTags: [String!],
$mode: String!, $mode: String!,
${includeChannels.length > 0 ? '$includeChannels: [String!]' : ''}
) { ) {
actor(id: $actorId) { actor(id: $actorId) {
id id
@ -146,12 +148,31 @@ function initActorActions(store, router) {
slug slug
priority priority
} }
channels {
id
name
slug
type
independent
parent {
id
name
slug
type
}
}
scenesConnection( scenesConnection(
filter: { filter: {
date: { date: {
lessThan: $before, lessThan: $before,
greaterThan: $after, greaterThan: $after,
} }
${includeChannels.length > 0 ? `
entity: {
slug: {
in: $includeChannels
}
}` : ''}
} }
selectedTags: $includeTags selectedTags: $includeTags
mode: $mode mode: $mode
@ -176,6 +197,7 @@ function initActorActions(store, router) {
orderBy, orderBy,
excludeTags: store.state.ui.filter, excludeTags: store.state.ui.filter,
includeTags, includeTags,
includeChannels,
mode, mode,
}); });

View File

@ -857,18 +857,25 @@ exports.up = knex => Promise.resolve()
ORDER BY tags.name; ORDER BY tags.name;
$$ LANGUAGE SQL STABLE; $$ LANGUAGE SQL STABLE;
CREATE FUNCTION actors_channels(actor actors) RETURNS SETOF entities AS $$
SELECT entities.*
FROM releases_actors
LEFT JOIN releases ON releases.id = releases_actors.release_id
LEFT JOIN entities ON entities.id = releases.entity_id
WHERE releases_actors.actor_id = actor.id
GROUP BY entities.id;
$$ LANGUAGE SQL STABLE;
CREATE FUNCTION actors_scenes(actor actors, selected_tags text[], mode text DEFAULT 'all') RETURNS SETOF releases AS $$ CREATE FUNCTION actors_scenes(actor actors, selected_tags text[], mode text DEFAULT 'all') RETURNS SETOF releases AS $$
SELECT releases.* SELECT releases.*
FROM releases FROM releases
LEFT JOIN LEFT JOIN
releases_actors ON releases_actors.release_id = releases.id releases_actors ON releases_actors.release_id = releases.id
LEFT JOIN
actors ON actors.id = releases_actors.actor_id
LEFT JOIN LEFT JOIN
releases_tags ON releases_tags.release_id = releases.id releases_tags ON releases_tags.release_id = releases.id
LEFT JOIN LEFT JOIN
tags ON tags.id = releases_tags.tag_id tags ON tags.id = releases_tags.tag_id
WHERE actors.id = actor.id WHERE releases_actors.actor_id = actor.id
AND CASE AND CASE
WHEN mode = 'any' AND array_length(selected_tags, 1) > 0 WHEN mode = 'any' AND array_length(selected_tags, 1) > 0
THEN tags.slug = ANY(selected_tags) THEN tags.slug = ANY(selected_tags)
@ -913,6 +920,8 @@ exports.up = knex => Promise.resolve()
COMMENT ON COLUMN actors.height IS E'@omit read,update,create,delete,all,many'; COMMENT ON COLUMN actors.height IS E'@omit read,update,create,delete,all,many';
COMMENT ON COLUMN actors.weight IS E'@omit read,update,create,delete,all,many'; COMMENT ON COLUMN actors.weight IS E'@omit read,update,create,delete,all,many';
COMMENT ON FUNCTION actors_tags IS E'@sortable';
COMMENT ON FUNCTION actors_channels IS E'@sortable';
COMMENT ON FUNCTION actors_scenes IS E'@sortable'; COMMENT ON FUNCTION actors_scenes IS E'@sortable';
`); `);
}); });
@ -974,6 +983,7 @@ exports.down = (knex) => { // eslint-disable-line arrow-body-style
DROP FUNCTION IF EXISTS releases_is_new; DROP FUNCTION IF EXISTS releases_is_new;
DROP FUNCTION IF EXISTS actors_tags; DROP FUNCTION IF EXISTS actors_tags;
DROP FUNCTION IF EXISTS actors_channels;
DROP FUNCTION IF EXISTS actors_scenes; DROP FUNCTION IF EXISTS actors_scenes;
DROP TEXT SEARCH CONFIGURATION IF EXISTS traxxx; DROP TEXT SEARCH CONFIGURATION IF EXISTS traxxx;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.8 KiB

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.6 KiB

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.3 KiB

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.6 KiB

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.7 KiB

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 KiB

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 KiB

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.6 KiB

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.5 KiB

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.9 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.8 KiB

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.7 KiB

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.3 KiB

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.4 KiB

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.4 KiB

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 60 KiB

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 57 KiB

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 70 KiB

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 58 KiB

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 72 KiB

After

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 62 KiB

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 65 KiB

After

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 62 KiB

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 52 KiB

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 39 KiB

After

Width:  |  Height:  |  Size: 39 KiB

BIN
public/img/tags/69/1.jpeg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

BIN
public/img/tags/anal/5.jpeg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Some files were not shown because too many files have changed in this diff Show More