Compare commits
24 Commits
8abcc7194a
...
1f444e58ce
Author | SHA1 | Date |
---|---|---|
|
1f444e58ce | |
|
53870fda89 | |
|
240f53047d | |
|
b803afa973 | |
|
3fba2d8a77 | |
|
ff384fb734 | |
|
08dc06c810 | |
|
b22fdd841b | |
|
8f9eb91b13 | |
|
98c19b560f | |
|
41d7d2fa34 | |
|
f4029f0ef7 | |
|
087d349cec | |
|
4bf4183a2a | |
|
6d337e7cb2 | |
|
7d31dd8d52 | |
|
3462d7af2a | |
|
0e8b4caac3 | |
|
af56378ee2 | |
|
4959dfd14f | |
|
f0a89df6ab | |
|
1907ce1e54 | |
|
79465d9634 | |
|
09d849eb9d |
|
@ -5,7 +5,7 @@
|
||||||
>
|
>
|
||||||
<div class="actor-header">
|
<div class="actor-header">
|
||||||
<h2 class="header-name">
|
<h2 class="header-name">
|
||||||
<span v-if="actor.network">{{ actor.name }} ({{ actor.network.name }})</span>
|
<span v-if="actor.entity">{{ actor.name }} ({{ actor.entity.name }})</span>
|
||||||
<span v-else="">{{ actor.name }}</span>
|
<span v-else="">{{ actor.name }}</span>
|
||||||
|
|
||||||
<Gender
|
<Gender
|
||||||
|
@ -248,20 +248,20 @@
|
||||||
>
|
>
|
||||||
<p
|
<p
|
||||||
v-for="description in actor.descriptions"
|
v-for="description in actor.descriptions"
|
||||||
:key="`description-${description.network.id}`"
|
:key="`description-${description.entity.id}`"
|
||||||
class="description"
|
class="description"
|
||||||
>
|
>
|
||||||
{{ description.text }}
|
{{ description.text }}
|
||||||
<router-link :to="{ name: 'network', params: { networkSlug: description.network.slug } }">
|
<router-link :to="`/${description.entity.type}/${description.entity.slug}`">
|
||||||
<img
|
<img
|
||||||
v-if="description.site"
|
v-if="description.entity.type === 'network'"
|
||||||
:src="`/img/logos/${description.network.slug}/thumbs/${description.site.slug}.png`"
|
:src="`/img/logos/${description.entity.slug}/thumbs/network.png`"
|
||||||
class="description-logo"
|
class="description-logo"
|
||||||
>
|
>
|
||||||
|
|
||||||
<img
|
<img
|
||||||
v-else
|
v-else
|
||||||
:src="`/img/logos/${description.network.slug}/thumbs/network.png`"
|
:src="`/img/logos/${description.entity.parent.slug}/thumbs/${description.entity.slug}.png`"
|
||||||
class="description-logo"
|
class="description-logo"
|
||||||
>
|
>
|
||||||
</router-link>
|
</router-link>
|
||||||
|
@ -283,15 +283,25 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="actor-content">
|
<div class="actor-content">
|
||||||
<Photos
|
<Scroll
|
||||||
v-if="actor.avatar || (actor.photos && actor.photos.length > 0)"
|
v-if="actor.avatar || (actor.photos && actor.photos.length > 0)"
|
||||||
:actor="actor"
|
class="scroll-light"
|
||||||
/>
|
>
|
||||||
|
<Photos :actor="actor" />
|
||||||
|
|
||||||
|
<template v-slot:expanded>
|
||||||
|
<Photos
|
||||||
|
class="expanded"
|
||||||
|
:actor="actor"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</Scroll>
|
||||||
|
|
||||||
<FilterBar
|
<FilterBar
|
||||||
:fetch-releases="fetchActor"
|
:fetch-releases="fetchActor"
|
||||||
:items-total="totalCount"
|
:items-total="totalCount"
|
||||||
:items-per-page="limit"
|
:items-per-page="limit"
|
||||||
|
:available-tags="actor.tags"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Releases :releases="releases" />
|
<Releases :releases="releases" />
|
||||||
|
@ -307,10 +317,11 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import Photos from './photos.vue';
|
|
||||||
import Pagination from '../pagination/pagination.vue';
|
import Pagination from '../pagination/pagination.vue';
|
||||||
import FilterBar from '../header/filter-bar.vue';
|
import FilterBar from '../header/filter-bar.vue';
|
||||||
import Releases from '../releases/releases.vue';
|
import Releases from '../releases/releases.vue';
|
||||||
|
import Photos from './photos.vue';
|
||||||
|
import Scroll from '../scroll/scroll.vue';
|
||||||
import Gender from './gender.vue';
|
import Gender from './gender.vue';
|
||||||
import Social from './social.vue';
|
import Social from './social.vue';
|
||||||
|
|
||||||
|
@ -348,6 +359,7 @@ export default {
|
||||||
FilterBar,
|
FilterBar,
|
||||||
Pagination,
|
Pagination,
|
||||||
Photos,
|
Photos,
|
||||||
|
Scroll,
|
||||||
Releases,
|
Releases,
|
||||||
Gender,
|
Gender,
|
||||||
Social,
|
Social,
|
||||||
|
@ -633,19 +645,66 @@ export default {
|
||||||
background: var(--background-dim);
|
background: var(--background-dim);
|
||||||
}
|
}
|
||||||
|
|
||||||
.releases {
|
|
||||||
flex-grow: 1;
|
|
||||||
border-top: solid 1px var(--crease);
|
|
||||||
padding: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.profile-social {
|
.profile-social {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.expand,
|
.expand {
|
||||||
.collapse-header {
|
|
||||||
display: none;
|
display: none;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
padding: .5rem .25rem;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: .9rem;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
fill: $shadow;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: $shadow-hint;
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
fill: $shadow-strong;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.expand-sidebar:hover {
|
||||||
|
background: $shadow-hint;
|
||||||
|
}
|
||||||
|
|
||||||
|
.expand-header {
|
||||||
|
display: none;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: $shadow-hint;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.collapse-header {
|
||||||
|
display: none;
|
||||||
|
width: 100%;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
padding: 0;
|
||||||
|
background: $profile;
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
width: 100%;
|
||||||
|
fill: $highlight;
|
||||||
|
padding: .5rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover .icon {
|
||||||
|
background: $highlight-hint;
|
||||||
|
fill: $text-contrast;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.scroll {
|
||||||
|
border-bottom: solid 1px var(--shadow-hint);
|
||||||
}
|
}
|
||||||
|
|
||||||
@media(max-width: $breakpoint4) {
|
@media(max-width: $breakpoint4) {
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
:to="{ name: 'actors', params: { gender: 'male', letter } }"
|
:to="{ name: 'actors', params: { gender: 'male', letter } }"
|
||||||
:class="{ selected: gender === 'male' }"
|
:class="{ selected: gender === 'male' }"
|
||||||
class="gender-link male"
|
class="gender-link male"
|
||||||
|
replace
|
||||||
><Gender gender="male" /></router-link>
|
><Gender gender="male" /></router-link>
|
||||||
</li>
|
</li>
|
||||||
<li class="gender">
|
<li class="gender">
|
||||||
|
@ -21,6 +22,7 @@
|
||||||
:to="{ name: 'actors', params: { gender: 'trans', letter } }"
|
:to="{ name: 'actors', params: { gender: 'trans', letter } }"
|
||||||
:class="{ selected: gender === 'trans' }"
|
:class="{ selected: gender === 'trans' }"
|
||||||
class="gender-link transsexual"
|
class="gender-link transsexual"
|
||||||
|
replace
|
||||||
><Gender gender="transsexual" /></router-link>
|
><Gender gender="transsexual" /></router-link>
|
||||||
</li>
|
</li>
|
||||||
<li class="gender">
|
<li class="gender">
|
||||||
|
@ -28,6 +30,7 @@
|
||||||
:to="{ name: 'actors', params: { gender: 'other', letter } }"
|
:to="{ name: 'actors', params: { gender: 'other', letter } }"
|
||||||
:class="{ selected: gender === 'other' }"
|
:class="{ selected: gender === 'other' }"
|
||||||
class="gender-link other"
|
class="gender-link other"
|
||||||
|
replace
|
||||||
><Icon icon="question5" /></router-link>
|
><Icon icon="question5" /></router-link>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
@ -42,6 +45,7 @@
|
||||||
:to="{ name: 'actors', params: { gender, letter: letterX } }"
|
:to="{ name: 'actors', params: { gender, letter: letterX } }"
|
||||||
:class="{ selected: letterX === letter }"
|
:class="{ selected: letterX === letter }"
|
||||||
class="letter-link"
|
class="letter-link"
|
||||||
|
replace
|
||||||
>{{ letterX || 'All' }}</router-link>
|
>{{ letterX || 'All' }}</router-link>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
@ -73,7 +77,7 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import Actor from '../tile/actor.vue';
|
import Actor from './tile.vue';
|
||||||
import Gender from './gender.vue';
|
import Gender from './gender.vue';
|
||||||
import Pagination from '../pagination/pagination.vue';
|
import Pagination from '../pagination/pagination.vue';
|
||||||
|
|
||||||
|
@ -179,7 +183,7 @@ export default {
|
||||||
.tiles {
|
.tiles {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(auto-fill, minmax(11rem, 1fr));
|
grid-template-columns: repeat(auto-fill, minmax(11rem, 1fr));
|
||||||
grid-gap: 0 .5rem;
|
grid-gap: .5rem;
|
||||||
padding: 1rem;
|
padding: 1rem;
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,17 +5,17 @@
|
||||||
:class="{
|
:class="{
|
||||||
avatar: !!actor.avatar,
|
avatar: !!actor.avatar,
|
||||||
empty: actor.photos.length === 0,
|
empty: actor.photos.length === 0,
|
||||||
wide: actor.photos.length > 2
|
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
<a
|
<a
|
||||||
v-if="actor.avatar"
|
v-show="actor.avatar"
|
||||||
:href="`/media/${actor.avatar.path}`"
|
:href="`/media/${actor.avatar.path}`"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noopener noreferrer"
|
rel="noopener noreferrer"
|
||||||
class="avatar-link photo-link"
|
class="avatar-link photo-link"
|
||||||
>
|
>
|
||||||
<img
|
<img
|
||||||
|
:src="sfw ? `/img/${actor.avatar.sfw.thumbnail}` : `/media/${actor.avatar.thumbnail}`"
|
||||||
:data-src="sfw ? `/img/${actor.avatar.sfw.thumbnail}` : `/media/${actor.avatar.thumbnail}`"
|
:data-src="sfw ? `/img/${actor.avatar.sfw.thumbnail}` : `/media/${actor.avatar.thumbnail}`"
|
||||||
:data-loading="sfw ? `/img/${actor.avatar.sfw.lazy}` : `/media/${actor.avatar.lazy}`"
|
:data-loading="sfw ? `/img/${actor.avatar.sfw.lazy}` : `/media/${actor.avatar.lazy}`"
|
||||||
:title="actor.avatar.copyright && `© ${actor.avatar.copyright}`"
|
:title="actor.avatar.copyright && `© ${actor.avatar.copyright}`"
|
||||||
|
@ -32,9 +32,10 @@
|
||||||
class="photo-link"
|
class="photo-link"
|
||||||
>
|
>
|
||||||
<img
|
<img
|
||||||
|
:src="sfw ? `/img/${photo.sfw.thumbnail}` : `/media/${photo.thumbnail}`"
|
||||||
:data-src="sfw ? `/img/${photo.sfw.thumbnail}` : `/media/${photo.thumbnail}`"
|
:data-src="sfw ? `/img/${photo.sfw.thumbnail}` : `/media/${photo.thumbnail}`"
|
||||||
:data-loading="sfw ? `/img/${photo.sfw.lazy}` : `/media/${photo.lazy}`"
|
:data-loading="sfw ? `/img/${photo.sfw.lazy}` : `/media/${photo.lazy}`"
|
||||||
:title="photo.copyright && `© ${photo.copyright}`"
|
:title="`© ${photo.copyright || photo.entity.name}`"
|
||||||
class="photo"
|
class="photo"
|
||||||
>
|
>
|
||||||
</a>
|
</a>
|
||||||
|
@ -63,15 +64,33 @@ export default {
|
||||||
@import 'theme';
|
@import 'theme';
|
||||||
|
|
||||||
.photos {
|
.photos {
|
||||||
width: 100%;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
padding: 1rem;
|
padding: .5rem 1rem;
|
||||||
border-bottom: solid 1px var(--darken-hint);
|
|
||||||
font-size: 0;
|
font-size: 0;
|
||||||
overflow-x: scroll;
|
overflow-x: scroll;
|
||||||
|
scroll-behavior: smooth;
|
||||||
scrollbar-width: none;
|
scrollbar-width: none;
|
||||||
|
|
||||||
|
&.expanded {
|
||||||
|
flex-wrap: wrap;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
/*
|
||||||
|
display: grid;
|
||||||
|
grid-gap: .5rem;
|
||||||
|
grid-template-columns: repeat(auto-fill, minmax(13rem, 1fr));
|
||||||
|
*/
|
||||||
|
|
||||||
|
.photo-link {
|
||||||
|
margin: 0 .5rem .5rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.photo {
|
||||||
|
height: 18rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
&.empty {
|
&.empty {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
@ -86,14 +105,13 @@ export default {
|
||||||
}
|
}
|
||||||
|
|
||||||
.photo-link {
|
.photo-link {
|
||||||
height: 16rem;
|
|
||||||
flex-shrink: 0;
|
|
||||||
margin: 0 .5rem 0 0;
|
margin: 0 .5rem 0 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.photo {
|
.photo {
|
||||||
height: 100%;
|
height: 15rem;
|
||||||
box-shadow: 0 0 3px $shadow-weak;
|
box-shadow: 0 0 3px $shadow-weak;
|
||||||
|
object-fit: cover;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media(max-width: $breakpoint3) {
|
@media(max-width: $breakpoint3) {
|
||||||
|
@ -105,6 +123,16 @@ export default {
|
||||||
.avatar-link {
|
.avatar-link {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.expanded {
|
||||||
|
grid-template-columns: repeat(auto-fill, minmax(10rem, 1fr));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media(max-width: $breakpoint0) {
|
||||||
|
.photos.expanded {
|
||||||
|
grid-template-columns: repeat(auto-fill, minmax(8rem, 1fr));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -106,7 +106,7 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import Gender from '../actors/gender.vue';
|
import Gender from './gender.vue';
|
||||||
|
|
||||||
function sfw() {
|
function sfw() {
|
||||||
return this.$store.state.ui.sfw;
|
return this.$store.state.ui.sfw;
|
||||||
|
@ -139,7 +139,6 @@ export default {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
position: relative;
|
position: relative;
|
||||||
margin: 0 .5rem .5rem 0;
|
|
||||||
box-shadow: 0 0 3px var(--darken-weak);
|
box-shadow: 0 0 3px var(--darken-weak);
|
||||||
background: var(--background);
|
background: var(--background);
|
||||||
overflow: hidden;
|
overflow: hidden;
|
|
@ -80,11 +80,11 @@ export default {
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
|
overflow-x: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.content-inner {
|
.content-inner {
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
padding: 1rem;
|
overflow-y: auto;
|
||||||
border-top: solid 1px var(--crease);
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -0,0 +1,64 @@
|
||||||
|
<template>
|
||||||
|
<div class="children">
|
||||||
|
<EntityTile
|
||||||
|
v-for="child in entity.children"
|
||||||
|
:key="`child-${child.id}`"
|
||||||
|
:entity="child"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import EntityTile from './tile.vue';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
EntityTile,
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
entity: {
|
||||||
|
type: Object,
|
||||||
|
default: null,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
@import 'theme';
|
||||||
|
|
||||||
|
.children {
|
||||||
|
display: flex;
|
||||||
|
box-sizing: border-box;
|
||||||
|
padding: 1rem;
|
||||||
|
border-bottom: solid 1px var(--darken-hint);
|
||||||
|
overflow-x: auto;
|
||||||
|
scroll-behavior: smooth;
|
||||||
|
scrollbar-width: none;
|
||||||
|
|
||||||
|
.tile {
|
||||||
|
width: 15rem;
|
||||||
|
margin: 0 1rem 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.expanded {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr));
|
||||||
|
grid-gap: 1rem;
|
||||||
|
|
||||||
|
.tile {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&::-webkit-scrollbar {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media(max-width: $breakpoint0) {
|
||||||
|
.children.expanded {
|
||||||
|
grid-template-columns: repeat(auto-fill, minmax(10rem, 1fr));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,202 @@
|
||||||
|
<template>
|
||||||
|
<div
|
||||||
|
v-if="entity"
|
||||||
|
class="entity content"
|
||||||
|
>
|
||||||
|
<div class="info">
|
||||||
|
<a
|
||||||
|
:href="entity.url"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener"
|
||||||
|
class="link link-child"
|
||||||
|
>
|
||||||
|
<template v-if="entity.hasLogo">
|
||||||
|
<img
|
||||||
|
v-if="$route.name === 'network'"
|
||||||
|
class="logo logo-child"
|
||||||
|
:src="`/img/logos/${entity.slug}/thumbs/network.png`"
|
||||||
|
>
|
||||||
|
|
||||||
|
<img
|
||||||
|
v-else-if="entity.parent"
|
||||||
|
class="logo logo-child"
|
||||||
|
:src="`/img/logos/${entity.parent.slug}/thumbs/${entity.slug}.png`"
|
||||||
|
>
|
||||||
|
|
||||||
|
<img
|
||||||
|
v-else
|
||||||
|
class="logo logo-child"
|
||||||
|
:src="`/img/logos/${entity.slug}/thumbs/${entity.slug}.png`"
|
||||||
|
>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<h2
|
||||||
|
v-else
|
||||||
|
class="name"
|
||||||
|
>{{ entity.name }}</h2>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<router-link
|
||||||
|
v-if="entity.parent"
|
||||||
|
:to="`/${entity.parent.type}/${entity.parent.slug}`"
|
||||||
|
class="link link-parent"
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
v-if="entity.parent.hasLogo"
|
||||||
|
class="logo logo-parent"
|
||||||
|
:src="`/img/logos/${entity.parent.slug}/thumbs/network.png`"
|
||||||
|
>
|
||||||
|
|
||||||
|
<h3
|
||||||
|
v-else
|
||||||
|
class="name parent-name"
|
||||||
|
>{{ entity.parent.name }}</h3>
|
||||||
|
</router-link>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
ref="content"
|
||||||
|
class="content-inner"
|
||||||
|
>
|
||||||
|
<Scroll
|
||||||
|
v-if="entity.children.length > 0"
|
||||||
|
class="scroll-dark"
|
||||||
|
>
|
||||||
|
<Children :entity="entity" />
|
||||||
|
|
||||||
|
<template v-slot:expanded>
|
||||||
|
<Children
|
||||||
|
class="expanded"
|
||||||
|
:entity="entity"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</Scroll>
|
||||||
|
|
||||||
|
<FilterBar
|
||||||
|
:fetch-releases="fetchEntity"
|
||||||
|
:items-total="totalCount"
|
||||||
|
:items-per-page="limit"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<div class="releases">
|
||||||
|
<Releases :releases="entity.releases" />
|
||||||
|
|
||||||
|
<Pagination
|
||||||
|
:items-total="totalCount"
|
||||||
|
:items-per-page="limit"
|
||||||
|
class="pagination-top"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import Vue from 'vue';
|
||||||
|
|
||||||
|
import FilterBar from '../header/filter-bar.vue';
|
||||||
|
import Pagination from '../pagination/pagination.vue';
|
||||||
|
import Releases from '../releases/releases.vue';
|
||||||
|
import Children from './children.vue';
|
||||||
|
import Scroll from '../scroll/scroll.vue';
|
||||||
|
|
||||||
|
async function fetchEntity() {
|
||||||
|
const { entity, totalCount } = await this.$store.dispatch('fetchEntityBySlugAndType', {
|
||||||
|
entitySlug: this.$route.params.entitySlug,
|
||||||
|
entityType: this.$route.name,
|
||||||
|
limit: this.limit,
|
||||||
|
range: this.$route.params.range,
|
||||||
|
pageNumber: Number(this.$route.params.pageNumber),
|
||||||
|
});
|
||||||
|
|
||||||
|
this.entity = entity;
|
||||||
|
this.totalCount = totalCount;
|
||||||
|
|
||||||
|
this.pageTitle = entity.name;
|
||||||
|
|
||||||
|
Vue.nextTick(() => {
|
||||||
|
this.$refs.content.scrollTop = 0;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async function mounted() {
|
||||||
|
await this.fetchEntity();
|
||||||
|
}
|
||||||
|
|
||||||
|
async function route() {
|
||||||
|
await this.fetchEntity();
|
||||||
|
}
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
FilterBar,
|
||||||
|
Pagination,
|
||||||
|
Children,
|
||||||
|
Releases,
|
||||||
|
Scroll,
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
entity: null,
|
||||||
|
totalCount: null,
|
||||||
|
limit: 20,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
$route: route,
|
||||||
|
},
|
||||||
|
mounted,
|
||||||
|
methods: {
|
||||||
|
fetchEntity,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
@import 'theme';
|
||||||
|
|
||||||
|
.info {
|
||||||
|
height: 2.5rem;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 1rem;
|
||||||
|
background: var(--profile);
|
||||||
|
border-bottom: solid 1px var(--lighten-hint);
|
||||||
|
|
||||||
|
.link {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
text-decoration: none;
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.link-child {
|
||||||
|
margin: 0 2rem 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.link-parent {
|
||||||
|
flex-direction: row-reverse;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo {
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
max-width: 20rem;
|
||||||
|
object-fit: contain;
|
||||||
|
object-position: 0 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.name {
|
||||||
|
color: var(--text-light);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 0;
|
||||||
|
white-space: nowrap;
|
||||||
|
font-size: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo-parent {
|
||||||
|
object-position: 100% 50%;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,79 @@
|
||||||
|
<template>
|
||||||
|
<router-link
|
||||||
|
:to="`/${entity.type}/${entity.slug}`"
|
||||||
|
:title="entity.name"
|
||||||
|
class="tile"
|
||||||
|
>
|
||||||
|
<template v-if="entity.hasLogo">
|
||||||
|
<img
|
||||||
|
v-if="entity.type === 'network'"
|
||||||
|
:src="`/img/logos/${entity.slug}/thumbs/network.png`"
|
||||||
|
:alt="entity.name"
|
||||||
|
class="logo"
|
||||||
|
>
|
||||||
|
|
||||||
|
<img
|
||||||
|
v-else-if="entity.parent"
|
||||||
|
:src="`/img/logos/${entity.parent.slug}/thumbs/${entity.slug}.png`"
|
||||||
|
:alt="entity.name"
|
||||||
|
class="logo"
|
||||||
|
>
|
||||||
|
|
||||||
|
<img
|
||||||
|
v-else
|
||||||
|
:src="`/img/logos/${entity.slug}/thumbs/${entity.slug}.png`"
|
||||||
|
:alt="entity.name"
|
||||||
|
class="logo"
|
||||||
|
>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<span
|
||||||
|
v-else
|
||||||
|
class="name"
|
||||||
|
>{{ entity.name }}</span>
|
||||||
|
</router-link>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
entity: {
|
||||||
|
type: Object,
|
||||||
|
default: null,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
@import 'theme';
|
||||||
|
|
||||||
|
.tile {
|
||||||
|
height: 6rem;
|
||||||
|
background: $tile;
|
||||||
|
display: flex;
|
||||||
|
flex-shrink: 0;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
box-sizing: border-box;
|
||||||
|
padding: .5rem 1rem;
|
||||||
|
border-radius: .25rem;
|
||||||
|
box-shadow: 0 0 3px rgba(0, 0, 0, .25);
|
||||||
|
text-align: center;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo {
|
||||||
|
max-width: 100%;
|
||||||
|
max-height: 100%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.name {
|
||||||
|
color: var(--text-light);
|
||||||
|
font-size: 1.25rem;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,63 @@
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<div
|
||||||
|
v-show="expanded"
|
||||||
|
class="expand-button expanded noselect"
|
||||||
|
@click="$emit('expand', false)"
|
||||||
|
><Icon icon="arrow-up3" /></div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
v-show="!expanded"
|
||||||
|
class="expand-button noselect"
|
||||||
|
@click="$emit('expand', true)"
|
||||||
|
><Icon icon="arrow-down3" /></div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
expanded: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.expand-button {
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: .5rem;
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
fill: var(--shadow);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
cursor: pointer;
|
||||||
|
background: var(--shadow-hint);
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
fill: var(--text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.expand-dark {
|
||||||
|
.icon {
|
||||||
|
fill: var(--lighten);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: var(--lighten-hint);
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
fill: var(--text-light);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -20,37 +20,18 @@
|
||||||
>New</router-link>
|
>New</router-link>
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<Pagination
|
<Filters
|
||||||
:items-total="itemsTotal"
|
class="filters"
|
||||||
:items-per-page="itemsPerPage"
|
:filter="filter"
|
||||||
|
:available-tags="availableTags"
|
||||||
|
@set-filter="setFilter"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<span class="tags">
|
|
||||||
<Filters
|
|
||||||
class="filters-block"
|
|
||||||
:filter="filter"
|
|
||||||
@set-filter="setFilter"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<v-popover class="filters-compact">
|
|
||||||
<Icon icon="filter" />
|
|
||||||
|
|
||||||
<div slot="popover">
|
|
||||||
<Filters
|
|
||||||
:compact="true"
|
|
||||||
:filter="filter"
|
|
||||||
@set-filter="setFilter"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</v-popover>
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { mapState } from 'vuex';
|
import { mapState } from 'vuex';
|
||||||
import Filters from './filters.vue';
|
import Filters from './filters.vue';
|
||||||
import Pagination from '../pagination/pagination.vue';
|
|
||||||
|
|
||||||
function filter(state) {
|
function filter(state) {
|
||||||
return state.ui.filter;
|
return state.ui.filter;
|
||||||
|
@ -85,7 +66,6 @@ async function setBatch(newBatch) {
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
Filters,
|
Filters,
|
||||||
Pagination,
|
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
fetchReleases: {
|
fetchReleases: {
|
||||||
|
@ -104,6 +84,10 @@ export default {
|
||||||
type: Number,
|
type: Number,
|
||||||
default: 10,
|
default: 10,
|
||||||
},
|
},
|
||||||
|
availableTags: {
|
||||||
|
type: Array,
|
||||||
|
default: () => [],
|
||||||
|
},
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapState({
|
...mapState({
|
||||||
|
@ -141,25 +125,14 @@ export default {
|
||||||
.sort {
|
.sort {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
margin: 0 0 -1px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.filters-block {
|
|
||||||
display: inline-block;
|
|
||||||
}
|
|
||||||
|
|
||||||
.filters-compact {
|
|
||||||
font-size: 1rem;
|
|
||||||
font-weight: bold;
|
|
||||||
display: none;
|
|
||||||
margin: 0 0 0 .5rem;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.range-button {
|
.range-button {
|
||||||
color: var(--shadow);
|
color: var(--shadow);
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
padding: .75rem 1rem 1rem 1rem;
|
padding: .8rem 1rem;
|
||||||
border: none;
|
border: none;
|
||||||
|
position: relative;
|
||||||
font-size: .8rem;
|
font-size: .8rem;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
|
@ -175,26 +148,22 @@ export default {
|
||||||
color: var(--primary);
|
color: var(--primary);
|
||||||
background: var(--background-soft);
|
background: var(--background-soft);
|
||||||
border-color: var(--crease);
|
border-color: var(--crease);
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
/* hide grey border for tab effect, negative margin shows grey crease on mobile */
|
||||||
|
content: '';
|
||||||
|
width: 100%;
|
||||||
|
height: 2px;
|
||||||
|
background: var(--background-soft);
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
bottom: -1px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.tags {
|
.filters {
|
||||||
|
display: inline-block;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media(max-width: $breakpoint2) {
|
|
||||||
.pagination {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media(max-width: $breakpoint) {
|
|
||||||
.filters-container {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.filters-compact {
|
|
||||||
display: inline-block;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -1,28 +1,28 @@
|
||||||
<template>
|
<template>
|
||||||
<v-popover class="filters-container">
|
<v-popover class="filters-container">
|
||||||
<div class="filters">
|
<div class="filters">
|
||||||
<Icon icon="filter" />
|
|
||||||
|
|
||||||
<div
|
<div
|
||||||
v-if="selectedTags.length > 0"
|
v-if="selectedTags.length > 0"
|
||||||
class="applied"
|
class="applied"
|
||||||
>{{ selectedTags.join(', ') }}</div>
|
>{{ selectedTags.length }} selected</div>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
v-else
|
v-else
|
||||||
class="applied empty"
|
class="applied empty"
|
||||||
>Filter by tags</div>
|
>Filter by tags</div>
|
||||||
|
|
||||||
|
<Icon icon="filter" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div slot="popover">
|
<div slot="popover">
|
||||||
<ul class="tags nolist">
|
<ul class="tags nolist">
|
||||||
<li
|
<li
|
||||||
v-for="tag in tags"
|
v-for="tag in availableTags"
|
||||||
:key="`tag-${tag}`"
|
:key="`tag-${tag.id}`"
|
||||||
class="tag"
|
class="tag"
|
||||||
:class="{ selected: selectedTags.includes(tag) }"
|
:class="{ selected: selectedTags.includes(tag.slug) }"
|
||||||
>
|
>
|
||||||
<router-link :to="{ params: { tags: getNewRange(tag) } }">
|
<router-link :to="{ query: { ...getNewRange(tag.slug) } }">
|
||||||
<Icon
|
<Icon
|
||||||
icon="checkmark"
|
icon="checkmark"
|
||||||
class="include"
|
class="include"
|
||||||
|
@ -30,9 +30,9 @@
|
||||||
</router-link>
|
</router-link>
|
||||||
|
|
||||||
<router-link
|
<router-link
|
||||||
:to="{ params: { tags: selectedTags.length === 1 && selectedTags.includes(tag) ? 'all-tags' : tag } }"
|
:to="{ query: { ...(selectedTags.length === 1 && selectedTags.includes(tag.slug) ? null : { tags: tag.slug }) } }"
|
||||||
class="name"
|
class="name"
|
||||||
>{{ tag }}</router-link>
|
>{{ tag.name }}</router-link>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
@ -40,33 +40,20 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
const tags = [
|
|
||||||
'airtight',
|
|
||||||
'anal',
|
|
||||||
'blowjob',
|
|
||||||
'double-penetration',
|
|
||||||
'facial',
|
|
||||||
'gangbang',
|
|
||||||
'lesbian',
|
|
||||||
'mff',
|
|
||||||
'mfm',
|
|
||||||
'orgy',
|
|
||||||
];
|
|
||||||
|
|
||||||
function getNewRange(tag) {
|
function getNewRange(tag) {
|
||||||
if (this.selectedTags.includes(tag)) {
|
if (this.selectedTags.includes(tag)) {
|
||||||
if (this.selectedTags.length === 1) {
|
if (this.selectedTags.length > 1) {
|
||||||
return 'all-tags';
|
return { tags: this.selectedTags.filter(selectedTag => selectedTag !== tag).join(',') };
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.selectedTags.filter(selectedTag => selectedTag !== tag).join('+');
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.selectedTags.concat(tag).join('+');
|
return { tags: this.selectedTags.concat(tag).join(',') };
|
||||||
}
|
}
|
||||||
|
|
||||||
function selectedTags() {
|
function selectedTags() {
|
||||||
return this.$route.params.tags.split('+').filter(selectedTag => selectedTag !== 'all-tags');
|
return this.$route.query.tags ? this.$route.query.tags.split(',') : [];
|
||||||
}
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
@ -79,11 +66,10 @@ export default {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false,
|
default: false,
|
||||||
},
|
},
|
||||||
},
|
availableTags: {
|
||||||
data() {
|
type: Array,
|
||||||
return {
|
default: () => [],
|
||||||
tags,
|
},
|
||||||
};
|
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
selectedTags,
|
selectedTags,
|
||||||
|
@ -105,17 +91,28 @@ export default {
|
||||||
fill: var(--shadow);
|
fill: var(--shadow);
|
||||||
margin: 0 .5rem 0 0;
|
margin: 0 .5rem 0 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
.applied {
|
||||||
|
color: var(--shadow-strong);
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
fill: var(--shadow-strong);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.applied {
|
.applied {
|
||||||
width: 12rem;
|
flex-grow: 1;
|
||||||
background: var(--background);
|
padding: .75rem .5rem;
|
||||||
padding: .5rem;
|
|
||||||
border: solid 1px var(--shadow-hint);
|
|
||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
overflow-x: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
|
text-align: right;
|
||||||
|
|
||||||
&.empty {
|
&.empty {
|
||||||
color: var(--shadow);
|
color: var(--shadow);
|
||||||
|
@ -142,6 +139,7 @@ export default {
|
||||||
}
|
}
|
||||||
|
|
||||||
.name {
|
.name {
|
||||||
|
min-width: 8rem;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
|
@ -165,4 +163,10 @@ export default {
|
||||||
fill: var(--success);
|
fill: var(--success);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media(max-width: $breakpoint0) {
|
||||||
|
.applied {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -43,7 +43,7 @@
|
||||||
:href="href"
|
:href="href"
|
||||||
:class="{ active: isActive }"
|
:class="{ active: isActive }"
|
||||||
@click="navigate"
|
@click="navigate"
|
||||||
>Sites</a>
|
>Channels</a>
|
||||||
</router-link>
|
</router-link>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
|
|
@ -1,13 +1,17 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<FilterBar
|
<div
|
||||||
:fetch-releases="fetchReleases"
|
ref="content"
|
||||||
:is-home="true"
|
class="content-inner"
|
||||||
:items-total="totalCount"
|
>
|
||||||
:items-per-page="limit"
|
<FilterBar
|
||||||
/>
|
:fetch-releases="fetchReleases"
|
||||||
|
:is-home="true"
|
||||||
|
:items-total="totalCount"
|
||||||
|
:items-per-page="limit"
|
||||||
|
:content="$refs.content"
|
||||||
|
/>
|
||||||
|
|
||||||
<div class="content-inner">
|
|
||||||
<Releases :releases="releases" />
|
<Releases :releases="releases" />
|
||||||
|
|
||||||
<Pagination
|
<Pagination
|
||||||
|
@ -34,6 +38,8 @@ async function fetchReleases() {
|
||||||
|
|
||||||
this.totalCount = totalCount;
|
this.totalCount = totalCount;
|
||||||
this.releases = releases;
|
this.releases = releases;
|
||||||
|
|
||||||
|
this.$refs.content.scrollTop = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function route() {
|
async function route() {
|
||||||
|
@ -57,7 +63,7 @@ export default {
|
||||||
releases: [],
|
releases: [],
|
||||||
networks: [],
|
networks: [],
|
||||||
pageTitle: null,
|
pageTitle: null,
|
||||||
limit: 15,
|
limit: 20,
|
||||||
totalCount: 0,
|
totalCount: 0,
|
||||||
from: null,
|
from: null,
|
||||||
};
|
};
|
||||||
|
|
|
@ -132,28 +132,19 @@ import Sites from '../sites/sites.vue';
|
||||||
import Network from '../tile/network.vue';
|
import Network from '../tile/network.vue';
|
||||||
|
|
||||||
async function fetchNetwork() {
|
async function fetchNetwork() {
|
||||||
const { network, totalCount } = await this.$store.dispatch('fetchNetworkBySlug', {
|
const { entity, totalCount } = await this.$store.dispatch('fetchEntityBySlugAndType', {
|
||||||
networkSlug: this.$route.params.networkSlug,
|
entitySlug: this.$route.params.networkSlug,
|
||||||
|
entityType: 'network',
|
||||||
limit: this.limit,
|
limit: this.limit,
|
||||||
range: this.$route.params.range,
|
range: this.$route.params.range,
|
||||||
pageNumber: Number(this.$route.params.pageNumber),
|
pageNumber: Number(this.$route.params.pageNumber),
|
||||||
});
|
});
|
||||||
|
|
||||||
this.network = network;
|
this.network = entity;
|
||||||
this.totalCount = totalCount;
|
this.networks = this.network.children;
|
||||||
|
|
||||||
if (this.network.studios) {
|
|
||||||
this.studios = this.network.studios.map(studio => ({
|
|
||||||
...studio,
|
|
||||||
network: this.network,
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
this.networks = this.network.networks;
|
|
||||||
this.sites = this.network.sites
|
|
||||||
.filter(site => !site.independent);
|
|
||||||
|
|
||||||
this.releases = this.network.releases;
|
this.releases = this.network.releases;
|
||||||
|
|
||||||
|
this.totalCount = totalCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function route() {
|
async function route() {
|
||||||
|
|
|
@ -2,13 +2,13 @@
|
||||||
<div class="networks">
|
<div class="networks">
|
||||||
<form
|
<form
|
||||||
class="search"
|
class="search"
|
||||||
@submit.prevent="searchSites"
|
@submit.prevent="searchEntities"
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
v-model="query"
|
v-model="query"
|
||||||
:placeholder="`Find ${siteCount} sites in ${networks.length} networks`"
|
:placeholder="`Find ${channelCount} channels in ${entities.length} networks`"
|
||||||
class="query"
|
class="query"
|
||||||
@input="searchSites"
|
@input="searchEntities"
|
||||||
>
|
>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
|
@ -19,12 +19,12 @@
|
||||||
|
|
||||||
<div
|
<div
|
||||||
v-if="query.length"
|
v-if="query.length"
|
||||||
class="network-tiles"
|
class="entity-tiles"
|
||||||
>
|
>
|
||||||
<Site
|
<Entity
|
||||||
v-for="site in searchResults"
|
v-for="entity in searchResults"
|
||||||
:key="`site-tile-${site.slug}`"
|
:key="`${entity.type}-tile-${entity.slug}`"
|
||||||
:site="site"
|
:entity="entity"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<span v-if="searchResults.length === 0">No results for "{{ query }}"</span>
|
<span v-if="searchResults.length === 0">No results for "{{ query }}"</span>
|
||||||
|
@ -32,56 +32,62 @@
|
||||||
|
|
||||||
<div
|
<div
|
||||||
v-if="query.length === 0"
|
v-if="query.length === 0"
|
||||||
class="network-tiles"
|
class="entity-tiles"
|
||||||
>
|
>
|
||||||
<Network
|
<Entity
|
||||||
v-for="network in networks"
|
v-for="entity in entities"
|
||||||
:key="`network-tile-${network.slug}`"
|
:key="`entity-tile-${entity.slug}`"
|
||||||
:network="network"
|
:entity="entity"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import Network from '../tile/network.vue';
|
import Entity from '../entities/tile.vue';
|
||||||
import Site from '../tile/site.vue';
|
|
||||||
|
|
||||||
async function searchSites() {
|
async function searchEntities() {
|
||||||
this.searchResults = await this.$store.dispatch('searchSites', {
|
this.searchResults = await this.$store.dispatch('searchEntities', {
|
||||||
query: this.query,
|
query: this.query,
|
||||||
limit: 20,
|
limit: 50,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async function mounted() {
|
async function mounted() {
|
||||||
this.networks = await this.$store.dispatch('fetchNetworks');
|
this.entities = await this.$store.dispatch('fetchEntities', {
|
||||||
|
type: 'network',
|
||||||
|
entitySlugs: [
|
||||||
|
'bamvisions',
|
||||||
|
'evilangel',
|
||||||
|
'legalporno',
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
this.pageTitle = 'Networks';
|
this.pageTitle = 'Networks';
|
||||||
}
|
}
|
||||||
|
|
||||||
function siteCount() {
|
function channelCount() {
|
||||||
return this.networks.map(network => network.sites).flat().length;
|
return this.entities.reduce((acc, entity) => acc + entity.childrenTotal, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
Network,
|
Entity,
|
||||||
Site,
|
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
query: '',
|
query: '',
|
||||||
pageTitle: null,
|
pageTitle: null,
|
||||||
networks: [],
|
entities: [],
|
||||||
searchResults: [],
|
searchResults: [],
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
siteCount,
|
channelCount,
|
||||||
},
|
},
|
||||||
mounted,
|
mounted,
|
||||||
methods: {
|
methods: {
|
||||||
searchSites,
|
searchEntities,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
@ -135,7 +141,7 @@ export default {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.network-tiles {
|
.entity-tiles {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
|
grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
|
||||||
grid-gap: 1rem;
|
grid-gap: 1rem;
|
||||||
|
|
|
@ -89,7 +89,6 @@ export default {
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.pagination {
|
.pagination {
|
||||||
width: 100%;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
@ -99,7 +98,7 @@ export default {
|
||||||
}
|
}
|
||||||
|
|
||||||
.pagination-bottom {
|
.pagination-bottom {
|
||||||
margin: 1rem 0 0 0;
|
margin: .5rem 0 1rem 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.pagination-button {
|
.pagination-button {
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
<template>
|
<template>
|
||||||
<div
|
<div class="media">
|
||||||
class="banner"
|
<div
|
||||||
@wheel.prevent="scrollBanner"
|
v-if="release.trailer || release.teaser"
|
||||||
>
|
class="trailer-container"
|
||||||
<div class="trailer">
|
>
|
||||||
<video
|
<video
|
||||||
v-if="release.trailer"
|
v-if="release.trailer"
|
||||||
:src="`/media/${release.trailer.path}`"
|
:src="`/media/${release.trailer.path}`"
|
||||||
:poster="release.poster && (sfw ? `/img/${release.poster.sfw.thumbnail}` : `/media/${release.poster.thumbnail}`)"
|
:poster="release.poster && (sfw ? `/img/${release.poster.sfw.thumbnail}` : `/media/${release.poster.thumbnail}`)"
|
||||||
:alt="release.title"
|
:alt="release.title"
|
||||||
:class="{ sfw: sfw && paused }"
|
:class="{ sfw: sfw && paused }"
|
||||||
class="item trailer-video"
|
class="item trailer"
|
||||||
controls
|
controls
|
||||||
@playing="playing = true; paused = false;"
|
@playing="playing = true; paused = false;"
|
||||||
@pause="playing = false; paused = true;"
|
@pause="playing = false; paused = true;"
|
||||||
|
@ -22,7 +22,7 @@
|
||||||
:poster="release.poster && (sfw ? `/img/${release.poster.sfw.thumbnail}` : `/media/${release.poster.thumbnail}`)"
|
:poster="release.poster && (sfw ? `/img/${release.poster.sfw.thumbnail}` : `/media/${release.poster.thumbnail}`)"
|
||||||
:alt="release.title"
|
:alt="release.title"
|
||||||
:class="{ sfw: sfw && paused }"
|
:class="{ sfw: sfw && paused }"
|
||||||
class="item trailer-video"
|
class="item trailer"
|
||||||
controls
|
controls
|
||||||
@playing="playing = true; paused = false;"
|
@playing="playing = true; paused = false;"
|
||||||
@pause="playing = false; paused = true;"
|
@pause="playing = false; paused = true;"
|
||||||
|
@ -32,7 +32,7 @@
|
||||||
v-else-if="release.teaser && /^image\//.test(release.teaser.mime)"
|
v-else-if="release.teaser && /^image\//.test(release.teaser.mime)"
|
||||||
:src="sfw ? `/img/${release.teaser.sfw.thumbnail}` : `/media/${release.teaser.path}`"
|
:src="sfw ? `/img/${release.teaser.sfw.thumbnail}` : `/media/${release.teaser.path}`"
|
||||||
:alt="release.title"
|
:alt="release.title"
|
||||||
class="item trailer-video"
|
class="item trailer"
|
||||||
>
|
>
|
||||||
|
|
||||||
<a
|
<a
|
||||||
|
@ -69,7 +69,7 @@
|
||||||
|
|
||||||
<a
|
<a
|
||||||
v-for="photo in photos"
|
v-for="photo in photos"
|
||||||
:key="`banner-${photo.index}`"
|
:key="`media-${photo.index}`"
|
||||||
:href="`/media/${photo.path}`"
|
:href="`/media/${photo.path}`"
|
||||||
:class="{ sfw }"
|
:class="{ sfw }"
|
||||||
class="item-link"
|
class="item-link"
|
||||||
|
@ -104,16 +104,14 @@ function photos() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.release.poster) {
|
if (this.release.poster) {
|
||||||
|
// no trailer, add poster to photos
|
||||||
return [this.release.poster].concat(this.release.photos);
|
return [this.release.poster].concat(this.release.photos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// no poster available
|
||||||
return this.release.photos;
|
return this.release.photos;
|
||||||
}
|
}
|
||||||
|
|
||||||
function scrollBanner(event) {
|
|
||||||
event.currentTarget.scrollLeft += event.deltaY; // eslint-disable-line no-param-reassign
|
|
||||||
}
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
props: {
|
props: {
|
||||||
release: {
|
release: {
|
||||||
|
@ -131,24 +129,38 @@ export default {
|
||||||
photos,
|
photos,
|
||||||
sfw,
|
sfw,
|
||||||
},
|
},
|
||||||
methods: {
|
|
||||||
scrollBanner,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
@import 'theme';
|
@import 'theme';
|
||||||
|
|
||||||
.banner {
|
.media {
|
||||||
background: var(--empty);
|
background: var(--background-dim);
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
scrollbar-width: none;
|
scrollbar-width: none;
|
||||||
box-shadow: 0 0 3px var(--shadow);
|
scroll-behavior: smooth;
|
||||||
font-size: 0;
|
font-size: 0;
|
||||||
|
|
||||||
|
&.expanded {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
|
||||||
|
.item-link,
|
||||||
|
.trailer {
|
||||||
|
margin: 0 .5rem .5rem 0;
|
||||||
|
max-width: 100%;
|
||||||
|
height: 18rem;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
&::-webkit-scrollbar {
|
&::-webkit-scrollbar {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
@ -182,11 +194,12 @@ export default {
|
||||||
}
|
}
|
||||||
|
|
||||||
.item-link,
|
.item-link,
|
||||||
.trailer {
|
.trailer-container {
|
||||||
position: relative;
|
position: relative;
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
box-shadow: 0 0 3px var(--shadow-weak);
|
||||||
|
|
||||||
.warning {
|
.warning {
|
||||||
display: none;
|
display: none;
|
||||||
|
@ -223,15 +236,19 @@ export default {
|
||||||
.item {
|
.item {
|
||||||
height: 18rem;
|
height: 18rem;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
|
object-fit: cover;
|
||||||
|
}
|
||||||
|
|
||||||
|
.trailer-container {
|
||||||
|
height: 18rem;
|
||||||
|
width: 32rem;
|
||||||
|
max-width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.trailer {
|
.trailer {
|
||||||
max-width: 100vw;
|
max-width: 100%;
|
||||||
}
|
max-height: 100%;
|
||||||
|
object-fit: cover;
|
||||||
.trailer-video {
|
|
||||||
max-width: 100%;
|
|
||||||
object-fit: cover;
|
|
||||||
|
|
||||||
&.sfw {
|
&.sfw {
|
||||||
filter: blur(2rem);
|
filter: blur(2rem);
|
||||||
|
@ -249,9 +266,10 @@ export default {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media(max-width: $breakpoint2) {
|
@media(max-width: $breakpoint0) {
|
||||||
.trailer-video {
|
.media:not(.expanded) .item,
|
||||||
object-fit: contain;
|
.trailer-container {
|
||||||
|
height: 56vw; /* 16:9 ratio for full-width video */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
|
@ -3,77 +3,49 @@
|
||||||
v-if="release"
|
v-if="release"
|
||||||
class="content"
|
class="content"
|
||||||
>
|
>
|
||||||
<Banner :release="release" />
|
<Expand
|
||||||
|
v-if="expanded"
|
||||||
|
class="expand"
|
||||||
|
:expanded="expanded"
|
||||||
|
@expand="(state) => expanded = state"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Scroll
|
||||||
|
class="scroll-light"
|
||||||
|
:expandable="false"
|
||||||
|
>
|
||||||
|
<Media
|
||||||
|
:release="release"
|
||||||
|
:class="{ expanded }"
|
||||||
|
/>
|
||||||
|
</Scroll>
|
||||||
|
|
||||||
<div class="details">
|
<div class="details">
|
||||||
<div class="column">
|
<div class="column">
|
||||||
<a
|
<div class="tidbits">
|
||||||
v-if="release.date"
|
|
||||||
v-tooltip.bottom="release.url && `View scene on ${release.site.name}`"
|
|
||||||
:title="release.url && `View scene on ${release.site.name}`"
|
|
||||||
:href="release.url"
|
|
||||||
:class="{ link: release.url }"
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
class="tidbit date"
|
|
||||||
>
|
|
||||||
<Icon
|
|
||||||
v-if="isAfter(new Date(), release.date)"
|
|
||||||
icon="calendar2"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<Icon
|
|
||||||
v-else
|
|
||||||
v-tooltip.bottom="'To be released'"
|
|
||||||
icon="sun3"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<span class="showable">{{ formatDate(release.date, 'MMM D, YYYY') }}</span>
|
|
||||||
<span class="hideable">{{ formatDate(release.date, 'MMMM D, YYYY') }}</span>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<span
|
|
||||||
v-if="release.shootId"
|
|
||||||
v-tooltip.bottom="`Shoot #`"
|
|
||||||
class="tidbit shoot hideable"
|
|
||||||
>
|
|
||||||
<Icon icon="clapboard-play" />
|
|
||||||
{{ release.shootId }}
|
|
||||||
</span>
|
|
||||||
|
|
||||||
<span
|
|
||||||
v-if="release.duration"
|
|
||||||
v-tooltip.bottom="`Duration`"
|
|
||||||
class="tidbit duration hideable"
|
|
||||||
>
|
|
||||||
<Icon icon="stopwatch" />
|
|
||||||
|
|
||||||
<span
|
|
||||||
v-if="release.duration >= 3600"
|
|
||||||
class="duration-segment"
|
|
||||||
>{{ Math.floor(release.duration / 3600).toString().padStart(2, '0') }}:</span>
|
|
||||||
<span class="duration-segment">{{ Math.floor((release.duration % 3600) / 60).toString().padStart(2, '0') }}:</span>
|
|
||||||
<span class="duration-segment">{{ (release.duration % 60).toString().padStart(2, '0') }}</span>
|
|
||||||
</span>
|
|
||||||
|
|
||||||
<span class="tidbit site">
|
|
||||||
<a
|
<a
|
||||||
v-if="release.site.independent"
|
v-if="release.date"
|
||||||
:href="`/network/${release.network.slug}`"
|
v-tooltip.bottom="release.url && `View scene on ${release.entity.name}`"
|
||||||
|
:title="release.url && `View scene on ${release.entity.name}`"
|
||||||
|
:href="release.url"
|
||||||
|
:class="{ link: release.url }"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
class="tidbit date"
|
||||||
>
|
>
|
||||||
<img
|
<span class="showable">{{ formatDate(release.date, 'MMM D, YYYY') }}</span>
|
||||||
:src="`/img/logos/${release.network.slug}/thumbs/network.png`"
|
<span class="hideable">{{ formatDate(release.date, 'MMMM D, YYYY') }}</span>
|
||||||
:title="release.network.name"
|
<Icon icon="share2" />
|
||||||
class="logo logo-site"
|
|
||||||
>
|
|
||||||
</a>
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
<template v-else>
|
<div class="site">
|
||||||
<a :href="`/network/${release.network.slug}`">
|
<template v-if="release.entity.parent">
|
||||||
|
<a :href="`/network/${release.entity.parent.slug}`">
|
||||||
<img
|
<img
|
||||||
:src="`/img/logos/${release.network.slug}/thumbs/network.png`"
|
:src="`/img/logos/${release.entity.parent.slug}/thumbs/network.png`"
|
||||||
:title="release.network.name"
|
:title="release.entity.parent.name"
|
||||||
:alt="release.network.name"
|
:alt="release.entity.parent.name"
|
||||||
class="logo logo-network"
|
class="logo logo-network"
|
||||||
>
|
>
|
||||||
</a>
|
</a>
|
||||||
|
@ -81,22 +53,72 @@
|
||||||
<span class="chain">presents</span>
|
<span class="chain">presents</span>
|
||||||
|
|
||||||
<a
|
<a
|
||||||
:href="`/site/${release.site.slug}`"
|
:href="`/${release.entity.type}/${release.entity.slug}`"
|
||||||
>
|
>
|
||||||
<img
|
<img
|
||||||
:src="`/img/logos/${release.network.slug}/thumbs/${release.site.slug}.png`"
|
v-if="release.entity.type === 'network'"
|
||||||
:title="release.site.name"
|
:src="`/img/logos/${release.entity.slug}/thumbs/network.png`"
|
||||||
|
:title="release.entity.name"
|
||||||
|
class="logo logo-site"
|
||||||
|
>
|
||||||
|
|
||||||
|
<img
|
||||||
|
v-else
|
||||||
|
:src="`/img/logos/${release.entity.parent.slug}/thumbs/${release.entity.slug}.png`"
|
||||||
|
:title="release.entity.name"
|
||||||
class="logo logo-site"
|
class="logo logo-site"
|
||||||
>
|
>
|
||||||
</a>
|
</a>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
</span>
|
<a
|
||||||
|
v-else
|
||||||
|
:href="`/channel/${release.entity.slug}`"
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
:src="`/img/logos/${release.entity.slug}/thumbs/network.png`"
|
||||||
|
:title="release.entity.name"
|
||||||
|
class="logo logo-site"
|
||||||
|
>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<Expand
|
||||||
|
v-if="release.photos.length > 0 || release.trailer || release.teaser"
|
||||||
|
class="expand-bottom"
|
||||||
|
:expanded="expanded"
|
||||||
|
@expand="(state) => expanded = state"
|
||||||
|
/>
|
||||||
|
|
||||||
<div class="info column">
|
<div class="info column">
|
||||||
<h2 class="row title">{{ release.title }}</h2>
|
<div class="row title-container">
|
||||||
|
<h2 class="title">{{ release.title }}</h2>
|
||||||
|
|
||||||
|
<span
|
||||||
|
v-if="release.shootId"
|
||||||
|
class="title-shoot"
|
||||||
|
>{{ release.shootId }}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
v-if="release.tags.length > 0"
|
||||||
|
class="row"
|
||||||
|
>
|
||||||
|
<ul class="tags nolist">
|
||||||
|
<li
|
||||||
|
v-for="tag in release.tags"
|
||||||
|
:key="`tag-${tag.slug}`"
|
||||||
|
class="tag"
|
||||||
|
>
|
||||||
|
<a
|
||||||
|
:href="`/tag/${tag.slug}`"
|
||||||
|
class="link"
|
||||||
|
>{{ tag.name }}</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="row associations">
|
<div class="row associations">
|
||||||
<ul
|
<ul
|
||||||
|
@ -131,67 +153,47 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
v-if="release.tags.length > 0"
|
v-if="release.description"
|
||||||
class="row"
|
class="row"
|
||||||
>
|
>
|
||||||
<Icon icon="price-tags3" />
|
<span class="row-label">Description</span>
|
||||||
|
|
||||||
<ul class="tags nolist">
|
<p class="description">{{ release.description }}</p>
|
||||||
<li
|
|
||||||
v-for="tag in release.tags"
|
|
||||||
:key="`tag-${tag.slug}`"
|
|
||||||
class="tag"
|
|
||||||
>
|
|
||||||
<a
|
|
||||||
:href="`/tag/${tag.slug}`"
|
|
||||||
class="link"
|
|
||||||
>{{ tag.name }}</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
v-if="release.duration"
|
v-if="release.duration"
|
||||||
class="row duration showable"
|
class="row"
|
||||||
>
|
>
|
||||||
<Icon icon="stopwatch" />
|
<span class="row-label">Duration</span>
|
||||||
|
|
||||||
<span
|
<div class="duration">
|
||||||
v-if="release.duration >= 3600"
|
<span
|
||||||
class="duration-segment"
|
v-if="release.duration >= 3600"
|
||||||
>{{ Math.floor(release.duration / 3600).toString().padStart(2, '0') }}:</span>
|
class="duration-segment"
|
||||||
<span class="duration-segment">{{ Math.floor((release.duration % 3600) / 60).toString().padStart(2, '0') }}:</span>
|
>{{ Math.floor(release.duration / 3600).toString().padStart(2, '0') }}:</span>
|
||||||
<span class="duration-segment">{{ (release.duration % 60).toString().padStart(2, '0') }}</span>
|
<span class="duration-segment">{{ Math.floor((release.duration % 3600) / 60).toString().padStart(2, '0') }}:</span>
|
||||||
|
<span class="duration-segment">{{ (release.duration % 60).toString().padStart(2, '0') }}</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p
|
|
||||||
v-if="release.description"
|
|
||||||
class="row description"
|
|
||||||
>
|
|
||||||
<Icon icon="info2" />
|
|
||||||
{{ release.description }}
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<div
|
<div
|
||||||
v-if="release.studio"
|
v-if="release.studio"
|
||||||
class="row"
|
class="row"
|
||||||
>
|
>
|
||||||
<Icon icon="video-camera2" />
|
<span class="row-label">Studio</span>
|
||||||
|
|
||||||
<a
|
<router-link
|
||||||
v-if="release.studio"
|
:to="`/studio/${release.studio.slug}`"
|
||||||
:href="release.studio.url"
|
class="link studio"
|
||||||
target="_blank"
|
>{{ release.studio.name }}</router-link>
|
||||||
rel="noopener noreferrer"
|
|
||||||
class="link"
|
|
||||||
>{{ release.studio.name }}</a>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
v-if="release.shootId"
|
v-if="release.shootId"
|
||||||
class="row showable"
|
class="row"
|
||||||
>
|
>
|
||||||
<Icon icon="clapboard-play" />
|
<span class="row-label">Shoot #</span>
|
||||||
|
|
||||||
<a
|
<a
|
||||||
:href="release.url"
|
:href="release.url"
|
||||||
|
@ -203,7 +205,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<span class="row">
|
<span class="row">
|
||||||
<Icon icon="drawer-in" />
|
<span class="row-label">Added</span>
|
||||||
|
|
||||||
<a
|
<a
|
||||||
:href="`/added/${formatDate(release.dateAdded, 'YYYY-MM-DD')}`"
|
:href="`/added/${formatDate(release.dateAdded, 'YYYY-MM-DD')}`"
|
||||||
|
@ -211,71 +213,50 @@
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noopener noreferrer"
|
rel="noopener noreferrer"
|
||||||
class="link added"
|
class="link added"
|
||||||
>{{ formatDate(release.dateAdded, 'MMMM D, YYYY') }}</a>
|
>{{ formatDate(release.createdAt, 'MMMM D, YYYY HH:mm') }}</a>
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<div class="row">
|
|
||||||
<Icon icon="paste2" />
|
|
||||||
|
|
||||||
<input
|
|
||||||
class="filename"
|
|
||||||
:value="filename"
|
|
||||||
@focus="copyFilename"
|
|
||||||
>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import config from 'config';
|
// import config from 'config';
|
||||||
import format from 'template-format';
|
// import format from 'template-format';
|
||||||
|
|
||||||
import Banner from './banner.vue';
|
import Media from './media.vue';
|
||||||
import Actor from '../tile/actor.vue';
|
import Actor from '../actors/tile.vue';
|
||||||
import Release from '../tile/release.vue';
|
import Release from './tile.vue';
|
||||||
import Releases from './releases.vue';
|
import Releases from './releases.vue';
|
||||||
|
import Scroll from '../scroll/scroll.vue';
|
||||||
|
import Expand from '../expand/expand.vue';
|
||||||
|
|
||||||
function pageTitle() {
|
function pageTitle() {
|
||||||
return this.release && this.release.title;
|
return this.release && this.release.title;
|
||||||
}
|
}
|
||||||
|
|
||||||
function copyFilename(event) {
|
|
||||||
event.target.setSelectionRange(0, event.target.value.length);
|
|
||||||
document.execCommand('copy');
|
|
||||||
}
|
|
||||||
|
|
||||||
async function mounted() {
|
async function mounted() {
|
||||||
this.release = await this.$store.dispatch('fetchReleaseById', this.$route.params.releaseId);
|
this.release = await this.$store.dispatch('fetchReleaseById', this.$route.params.releaseId);
|
||||||
this.filename = format(config.filename.pattern, {
|
|
||||||
...this.release,
|
|
||||||
shootId: this.release.shootId || '',
|
|
||||||
date: this.formatDate(this.release.date, config.filename.date),
|
|
||||||
}, {
|
|
||||||
spreadSeparator: config.filename.separator,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
Actor,
|
Actor,
|
||||||
Banner,
|
Media,
|
||||||
Release,
|
Release,
|
||||||
Releases,
|
Releases,
|
||||||
|
Scroll,
|
||||||
|
Expand,
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
release: null,
|
release: null,
|
||||||
filename: null,
|
expanded: false,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
pageTitle,
|
pageTitle,
|
||||||
},
|
},
|
||||||
mounted,
|
mounted,
|
||||||
methods: {
|
|
||||||
copyFilename,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -289,30 +270,6 @@ export default {
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
.info {
|
|
||||||
padding: 1rem;
|
|
||||||
border-left: solid 1px var(--shadow-hint);
|
|
||||||
border-right: solid 1px var(--shadow-hint);
|
|
||||||
flex-grow: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.row {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
margin: 0 0 1rem 0;
|
|
||||||
|
|
||||||
&.associations {
|
|
||||||
align-items: start;
|
|
||||||
}
|
|
||||||
|
|
||||||
.icon {
|
|
||||||
display: inline-block;
|
|
||||||
width: 1rem;
|
|
||||||
fill: var(--shadow-strong);
|
|
||||||
margin: 0 1rem 0 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.details {
|
.details {
|
||||||
background: var(--profile);
|
background: var(--profile);
|
||||||
color: var(--text-light);
|
color: var(--text-light);
|
||||||
|
@ -320,7 +277,9 @@ export default {
|
||||||
cursor: default;
|
cursor: default;
|
||||||
|
|
||||||
.column {
|
.column {
|
||||||
|
height: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding: 0 1rem;
|
padding: 0 1rem;
|
||||||
}
|
}
|
||||||
|
@ -330,33 +289,35 @@ export default {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.tidbits {
|
||||||
|
flex-shrink: 0;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
.tidbit {
|
.tidbit {
|
||||||
display: inline-block;
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|
||||||
&:not(:last-child) {
|
&:not(:last-child) {
|
||||||
border-right: solid 1px var(--lighten-hint);
|
border-right: solid 1px var(--lighten-hint);
|
||||||
}
|
}
|
||||||
|
|
||||||
.icon {
|
&.date {
|
||||||
fill: var(--lighten-weak);
|
|
||||||
margin: 0 .25rem 0 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.date,
|
|
||||||
&.duration,
|
|
||||||
&.shoot {
|
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
padding: 1.25rem 1rem 1.25rem 0;
|
padding: 0 2rem 0 0;
|
||||||
margin: 0 1rem 0 0;
|
font-weight: bold;
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
fill: var(--lighten);
|
||||||
|
margin: -.2rem 0 0 .5rem;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.site {
|
.site {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
flex-grow: 1;
|
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: flex-end;
|
|
||||||
padding: .25rem 0;
|
padding: .25rem 0;
|
||||||
font-size: 0;
|
font-size: 0;
|
||||||
}
|
}
|
||||||
|
@ -366,8 +327,9 @@ export default {
|
||||||
}
|
}
|
||||||
|
|
||||||
.logo-site {
|
.logo-site {
|
||||||
height: 3rem;
|
height: 2.5rem;
|
||||||
max-width: 15rem;
|
max-width: 15rem;
|
||||||
|
margin: .25rem 0;
|
||||||
object-fit: contain;
|
object-fit: contain;
|
||||||
object-position: 100% 50%;
|
object-position: 100% 50%;
|
||||||
}
|
}
|
||||||
|
@ -386,12 +348,63 @@ export default {
|
||||||
font-size: .8rem;
|
font-size: .8rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.expand-bottom {
|
||||||
|
border-bottom: solid 1px var(--shadow-hint);
|
||||||
|
}
|
||||||
|
|
||||||
|
.info {
|
||||||
|
padding: 1rem;
|
||||||
|
border-left: solid 1px var(--shadow-hint);
|
||||||
|
border-right: solid 1px var(--shadow-hint);
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.row {
|
||||||
|
margin: 0 0 1rem 0;
|
||||||
|
|
||||||
|
&.associations {
|
||||||
|
align-items: start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
display: inline-block;
|
||||||
|
width: 1rem;
|
||||||
|
fill: var(--shadow-strong);
|
||||||
|
margin: 0 1rem 0 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.row-label {
|
||||||
|
display: block;
|
||||||
|
margin: 0 0 .5rem 0;
|
||||||
|
color: var(--shadow);
|
||||||
|
font-weight: bold;
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
margin: 0 .5rem 0 0;
|
||||||
|
fill: var(--shadow);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.title-container {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
.title {
|
.title {
|
||||||
margin: 0 0 1.5rem 0;
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title-shoot {
|
||||||
|
margin: 0 0 0 .5rem;
|
||||||
|
color: var(--shadow);
|
||||||
|
font-size: .9rem;
|
||||||
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
.description {
|
.description {
|
||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
|
margin: -.25rem 0 0 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.duration {
|
.duration {
|
||||||
|
@ -405,28 +418,13 @@ export default {
|
||||||
.actors {
|
.actors {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(auto-fill, minmax(10rem, 1fr));
|
grid-template-columns: repeat(auto-fill, minmax(10rem, 1fr));
|
||||||
grid-gap: 1rem;
|
grid-gap: .5rem;
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
.actor {
|
|
||||||
margin: 0 1rem .5rem 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.movies {
|
|
||||||
}
|
|
||||||
|
|
||||||
.filename {
|
|
||||||
width: 100%;
|
|
||||||
padding: .5rem;
|
|
||||||
color: var(--text);
|
|
||||||
border: solid 1px var(--shadow-weak);
|
|
||||||
background: var(--background);
|
|
||||||
}
|
|
||||||
|
|
||||||
.link {
|
.link {
|
||||||
display: inline-block;
|
display: inline-flex;
|
||||||
color: var(--link);
|
color: var(--link);
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
|
|
||||||
|
@ -462,6 +460,10 @@ export default {
|
||||||
.chain {
|
.chain {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.logo-site {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media(max-width: $breakpoint) {
|
@media(max-width: $breakpoint) {
|
||||||
|
@ -477,11 +479,6 @@ export default {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
}
|
}
|
||||||
|
|
||||||
.logo-site {
|
|
||||||
width: 15rem;
|
|
||||||
max-width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.actors {
|
.actors {
|
||||||
grid-template-columns: repeat(auto-fill, minmax(8rem, 1fr));
|
grid-template-columns: repeat(auto-fill, minmax(8rem, 1fr));
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
><span class="range">{{ range }}</span> releases for '{{ context }}'</h3>
|
><span class="range">{{ range }}</span> releases for '{{ context }}'</h3>
|
||||||
|
|
||||||
<ul
|
<ul
|
||||||
|
v-if="releases.length > 0"
|
||||||
:key="sfw"
|
:key="sfw"
|
||||||
v-lazy-container="{ selector: '.thumbnail' }"
|
v-lazy-container="{ selector: '.thumbnail' }"
|
||||||
class="nolist tiles"
|
class="nolist tiles"
|
||||||
|
@ -35,7 +36,7 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import ReleaseTile from '../tile/release.vue';
|
import ReleaseTile from './tile.vue';
|
||||||
|
|
||||||
function range() {
|
function range() {
|
||||||
return this.$route.params.range;
|
return this.$route.params.range;
|
||||||
|
@ -82,14 +83,30 @@ export default {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.releases {
|
||||||
|
border-top: solid 1px var(--crease);
|
||||||
|
|
||||||
|
&.embedded {
|
||||||
|
border: none;
|
||||||
|
|
||||||
|
.tiles {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.tiles {
|
.tiles {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(auto-fill, minmax(22rem, 1fr));
|
grid-template-columns: repeat(auto-fill, minmax(22rem, 1fr));
|
||||||
grid-gap: 1rem;
|
grid-gap: 1rem;
|
||||||
|
box-sizing: border-box;
|
||||||
|
padding: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.empty {
|
.empty {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 1rem;
|
||||||
color: var(--shadow-strong);
|
color: var(--shadow-strong);
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,43 +6,41 @@
|
||||||
>
|
>
|
||||||
<span class="poster">
|
<span class="poster">
|
||||||
<span class="details">
|
<span class="details">
|
||||||
<router-link
|
|
||||||
v-if="release.site && release.site.independent"
|
|
||||||
:to="`/network/${release.network.slug}`"
|
|
||||||
class="site site-link"
|
|
||||||
><img
|
|
||||||
:src="`/img/logos/${release.network.slug}/favicon.png`"
|
|
||||||
class="favicon"
|
|
||||||
>{{ release.network.name }}</router-link>
|
|
||||||
|
|
||||||
<span
|
<span
|
||||||
v-else-if="release.network"
|
v-if="release.entity.type !== 'network' && release.entity.parent"
|
||||||
class="site"
|
class="site"
|
||||||
>
|
>
|
||||||
<router-link
|
<router-link
|
||||||
v-tooltip.bottom="`Part of ${release.network.name}`"
|
v-tooltip.bottom="`Part of ${release.entity.parent.name}`"
|
||||||
:title="`Part of ${release.network.name}`"
|
:title="`Part of ${release.entity.parent.name}`"
|
||||||
:to="`/network/${release.network.slug}`"
|
:to="`/${release.entity.parent.type}/${release.entity.parent.slug}`"
|
||||||
class="site-link"
|
class="site-link"
|
||||||
><img
|
><img
|
||||||
:src="`/img/logos/${release.network.slug}/favicon.png`"
|
:src="`/img/logos/${release.entity.parent.slug}/favicon.png`"
|
||||||
class="favicon"
|
class="favicon"
|
||||||
></router-link>
|
></router-link>
|
||||||
|
|
||||||
<router-link
|
<router-link
|
||||||
v-tooltip.bottom="`More from ${release.site.name}`"
|
v-tooltip.bottom="`More from ${release.entity.name}`"
|
||||||
:title="`More from ${release.site.name}`"
|
:title="`More from ${release.entity.name}`"
|
||||||
:to="`/site/${release.site.slug}`"
|
:to="`/${release.entity.type}/${release.entity.slug}`"
|
||||||
class="site-link"
|
class="site-link"
|
||||||
>{{ release.site.name }}</router-link>
|
>{{ release.entity.name }}</router-link>
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<span v-else />
|
<router-link
|
||||||
|
v-else
|
||||||
|
:to="`/${release.entity.type}/${release.entity.slug}`"
|
||||||
|
class="site site-link"
|
||||||
|
><img
|
||||||
|
:src="`/img/logos/${release.entity.slug}/favicon.png`"
|
||||||
|
class="favicon"
|
||||||
|
>{{ release.entity.name }}</router-link>
|
||||||
|
|
||||||
<a
|
<a
|
||||||
v-if="release.date"
|
v-if="release.date"
|
||||||
v-tooltip.bottom="release.url && `View scene on ${release.site.name}`"
|
v-tooltip.bottom="release.url && `View scene on ${release.entity.name}`"
|
||||||
:title="release.url && `View scene on ${release.site.name}`"
|
:title="release.url && `View scene on ${release.entity.name}`"
|
||||||
:href="release.url"
|
:href="release.url"
|
||||||
:class="{ upcoming: isAfter(release.date, new Date()), new: release.isNew }"
|
:class="{ upcoming: isAfter(release.date, new Date()), new: release.isNew }"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
|
@ -250,7 +248,7 @@ export default {
|
||||||
}
|
}
|
||||||
|
|
||||||
.date {
|
.date {
|
||||||
&.upcoming:before {
|
&.new:before {
|
||||||
content: '';
|
content: '';
|
||||||
background: var(--primary);
|
background: var(--primary);
|
||||||
width: .5rem;
|
width: .5rem;
|
||||||
|
@ -260,10 +258,6 @@ export default {
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
left: -.5rem;
|
left: -.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.new {
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.site {
|
.site {
|
|
@ -0,0 +1,258 @@
|
||||||
|
<template>
|
||||||
|
<div class="scroll">
|
||||||
|
<Expand
|
||||||
|
v-if="expanded"
|
||||||
|
:expanded="expanded"
|
||||||
|
class="expand-dark"
|
||||||
|
@expand="(state) => $emit('expand', state)"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<div class="scrollable">
|
||||||
|
<Expand
|
||||||
|
v-if="expanded"
|
||||||
|
:expanded="expanded"
|
||||||
|
class="expand-light"
|
||||||
|
@expand="(state) => $emit('expand', state)"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<div
|
||||||
|
v-show="enabled && !expanded"
|
||||||
|
class="scroll-button scroll-left noselect"
|
||||||
|
:class="{ 'scroll-start': scrollAtStart }"
|
||||||
|
@click="scroll('left')"
|
||||||
|
><Icon icon="arrow-left3" /></div>
|
||||||
|
|
||||||
|
<slot />
|
||||||
|
|
||||||
|
<div
|
||||||
|
v-show="enabled && !expanded"
|
||||||
|
class="scroll-button scroll-right noselect"
|
||||||
|
:class="{ 'scroll-end': scrollAtEnd }"
|
||||||
|
@click="scroll('right')"
|
||||||
|
><Icon icon="arrow-right3" /></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Expand
|
||||||
|
v-if="expanded || (expandable && scrollable)"
|
||||||
|
:expanded="expanded"
|
||||||
|
class="expand-dark"
|
||||||
|
@expand="(state) => $emit('expand', state)"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Expand
|
||||||
|
v-if="expanded || (expandable && scrollable)"
|
||||||
|
:expanded="expanded"
|
||||||
|
class="expand-light"
|
||||||
|
@expand="(state) => $emit('expand', state)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import Expand from '../expand/expand.vue';
|
||||||
|
|
||||||
|
function updateScroll() {
|
||||||
|
this.scrollable = this.target.scrollWidth > this.target.clientWidth;
|
||||||
|
this.scrollAtStart = this.target.scrollLeft === 0;
|
||||||
|
this.scrollAtEnd = this.target.scrollWidth - this.target.clientWidth === this.target.scrollLeft;
|
||||||
|
}
|
||||||
|
|
||||||
|
function scroll(direction) {
|
||||||
|
if (direction === 'right') {
|
||||||
|
this.target.scrollLeft = this.target.scrollLeft + this.target.clientWidth - 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (direction === 'left') {
|
||||||
|
this.target.scrollLeft = this.target.scrollLeft - this.target.clientWidth + 100;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function mounted() {
|
||||||
|
this.target = this.$slots.default[0].elm;
|
||||||
|
|
||||||
|
this.target.addEventListener('scroll', () => {
|
||||||
|
this.updateScroll();
|
||||||
|
});
|
||||||
|
|
||||||
|
window.addEventListener('resize', this.updateScroll);
|
||||||
|
|
||||||
|
this.updateScroll();
|
||||||
|
setTimeout(() => this.updateScroll(), 500); // allow CSS to calculate
|
||||||
|
}
|
||||||
|
|
||||||
|
function beforeDestroy() {
|
||||||
|
this.target.removeEventListener('scroll', this.updateScroll);
|
||||||
|
window.removeEventListener('resize', this.updateScroll);
|
||||||
|
}
|
||||||
|
|
||||||
|
function updated() {
|
||||||
|
this.updateScroll();
|
||||||
|
}
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
Expand,
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
enabled: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true,
|
||||||
|
},
|
||||||
|
expandable: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true,
|
||||||
|
},
|
||||||
|
expanded: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
target: null,
|
||||||
|
scrollable: true,
|
||||||
|
scrollAtStart: true,
|
||||||
|
scrollAtEnd: false,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
mounted,
|
||||||
|
updated,
|
||||||
|
beforeDestroy,
|
||||||
|
methods: {
|
||||||
|
scroll,
|
||||||
|
updateScroll,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
@import 'theme';
|
||||||
|
|
||||||
|
.scroll {
|
||||||
|
background: var(--profile);
|
||||||
|
|
||||||
|
&.expanded {
|
||||||
|
padding: 0;
|
||||||
|
|
||||||
|
.scroll {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.scrollable {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.expand-light {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scroll-light {
|
||||||
|
background: var(--background-dim);
|
||||||
|
|
||||||
|
.scroll-button {
|
||||||
|
.icon {
|
||||||
|
fill: var(--darken);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.scroll-start .icon,
|
||||||
|
&.scroll-end .icon {
|
||||||
|
fill: var(--darken-weak);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover:not(.scroll-start):not(.scroll-end) .icon {
|
||||||
|
fill: var(--text-dark);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.scroll-left {
|
||||||
|
background: linear-gradient(to right, var(--background-dim) 50%, transparent);
|
||||||
|
}
|
||||||
|
|
||||||
|
.scroll-right {
|
||||||
|
background: linear-gradient(to left, var(--background-dim) 50%, transparent);
|
||||||
|
}
|
||||||
|
|
||||||
|
.expand-dark {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.expand-light {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.scroll-dark {
|
||||||
|
background: var(--profile);
|
||||||
|
|
||||||
|
.scroll-button {
|
||||||
|
.icon {
|
||||||
|
fill: var(--lighten);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.scroll-start .icon,
|
||||||
|
&.scroll-end .icon {
|
||||||
|
fill: var(--darken-weak);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover:not(.scroll-start):not(.scroll-end) .icon {
|
||||||
|
fill: var(--text-light);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.scroll-left {
|
||||||
|
background: linear-gradient(to right, var(--profile) 50%, transparent);
|
||||||
|
}
|
||||||
|
|
||||||
|
.scroll-right {
|
||||||
|
background: linear-gradient(to left, var(--profile) 50%, transparent);
|
||||||
|
}
|
||||||
|
|
||||||
|
.expand-light {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.expand-dark {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.scroll-button {
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
box-sizing: border-box;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
z-index: 10;
|
||||||
|
|
||||||
|
&.scroll-start,
|
||||||
|
&.scroll-end {
|
||||||
|
/* use over v-show so button stays visible while still hovered */
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
display: flex;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.scroll-left {
|
||||||
|
left: 0;
|
||||||
|
padding: 1rem 2rem 1rem 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scroll-right {
|
||||||
|
right: 0;
|
||||||
|
padding: 1rem 1rem 1rem 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media(max-width: $breakpoint) {
|
||||||
|
.scroll-button {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -30,13 +30,14 @@
|
||||||
|
|
||||||
<Releases
|
<Releases
|
||||||
v-if="!loading && releases.length > 0"
|
v-if="!loading && releases.length > 0"
|
||||||
|
class="embedded"
|
||||||
:releases="releases"
|
:releases="releases"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import Actor from '../tile/actor.vue';
|
import Actor from '../actors/tile.vue';
|
||||||
import Releases from '../releases/releases.vue';
|
import Releases from '../releases/releases.vue';
|
||||||
|
|
||||||
async function search() {
|
async function search() {
|
||||||
|
@ -93,6 +94,10 @@ export default {
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
@import 'theme';
|
@import 'theme';
|
||||||
|
|
||||||
|
.content-inner {
|
||||||
|
padding: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
.summary {
|
.summary {
|
||||||
display: block;
|
display: block;
|
||||||
margin: 0 0 1rem 0;
|
margin: 0 0 1rem 0;
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<router-link
|
<router-link
|
||||||
to="/home"
|
to="/updates"
|
||||||
class="logo-link"
|
class="logo-link"
|
||||||
@click.native="toggleSidebar(false)"
|
@click.native="toggleSidebar(false)"
|
||||||
>
|
>
|
||||||
|
@ -29,7 +29,7 @@
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<router-link
|
<router-link
|
||||||
v-slot="{ href, isActive, navigate }"
|
v-slot="{ href, isActive, navigate }"
|
||||||
to="/home"
|
to="/updates"
|
||||||
@click.native="toggleSidebar(false)"
|
@click.native="toggleSidebar(false)"
|
||||||
>
|
>
|
||||||
<a
|
<a
|
||||||
|
@ -67,7 +67,7 @@
|
||||||
:href="href"
|
:href="href"
|
||||||
:class="{ active: isActive }"
|
:class="{ active: isActive }"
|
||||||
@click="navigate"
|
@click="navigate"
|
||||||
>Sites</a>
|
>Channels</a>
|
||||||
</router-link>
|
</router-link>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import Tag from '../tile/tag.vue';
|
import Tag from './tile.vue';
|
||||||
|
|
||||||
function sfw() {
|
function sfw() {
|
||||||
return this.$store.state.ui.sfw;
|
return this.$store.state.ui.sfw;
|
||||||
|
@ -45,6 +45,7 @@ async function mounted() {
|
||||||
'double-penetration',
|
'double-penetration',
|
||||||
'facial',
|
'facial',
|
||||||
'creampie',
|
'creampie',
|
||||||
|
'squirting',
|
||||||
],
|
],
|
||||||
appearance: [
|
appearance: [
|
||||||
'asian',
|
'asian',
|
||||||
|
@ -100,6 +101,7 @@ async function mounted() {
|
||||||
],
|
],
|
||||||
misc: [
|
misc: [
|
||||||
'gaping',
|
'gaping',
|
||||||
|
'squirting',
|
||||||
'oil',
|
'oil',
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
@ -145,7 +147,7 @@ export default {
|
||||||
.tiles {
|
.tiles {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(auto-fill, minmax(23rem, .33fr));
|
grid-template-columns: repeat(auto-fill, minmax(23rem, .33fr));
|
||||||
grid-gap: 1rem;
|
grid-gap: .5rem;
|
||||||
margin: 0 0 1.5rem 0;
|
margin: 0 0 1.5rem 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -156,13 +158,19 @@ export default {
|
||||||
|
|
||||||
@media(max-width: $breakpoint3) {
|
@media(max-width: $breakpoint3) {
|
||||||
.tiles {
|
.tiles {
|
||||||
grid-template-columns: repeat(auto-fill, minmax(21rem, .5fr));
|
grid-template-columns: repeat(auto-fill, minmax(20rem, .5fr));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media(max-width: $breakpoint) {
|
@media(max-width: $breakpoint) {
|
||||||
.tiles {
|
.tiles {
|
||||||
grid-template-columns: repeat(auto-fill, minmax(20rem, 1fr));
|
grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media(max-width: $breakpoint0) {
|
||||||
|
.tiles {
|
||||||
|
grid-template-columns: repeat(auto-fill, minmax(11rem, 1fr));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -1,11 +1,9 @@
|
||||||
<template>
|
<template>
|
||||||
<router-link
|
<router-link
|
||||||
:to="{ name: 'tag', params: { tagSlug: tag.slug } }"
|
:to="{ name: 'tag', params: { tagSlug: tag.slug, range: 'latest' } }"
|
||||||
:title="tag.name"
|
:title="tag.name"
|
||||||
class="tile"
|
class="tile"
|
||||||
>
|
>
|
||||||
<span class="title">{{ tag.name }}</span>
|
|
||||||
|
|
||||||
<template v-if="tag.poster">
|
<template v-if="tag.poster">
|
||||||
<img
|
<img
|
||||||
v-if="!lazy && !sfw"
|
v-if="!lazy && !sfw"
|
||||||
|
@ -41,6 +39,8 @@
|
||||||
class="poster"
|
class="poster"
|
||||||
>
|
>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<span class="title">{{ tag.name }}</span>
|
||||||
</router-link>
|
</router-link>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -71,20 +71,19 @@ export default {
|
||||||
|
|
||||||
.tile {
|
.tile {
|
||||||
color: var(--text-light);
|
color: var(--text-light);
|
||||||
background: var(--profile);
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
position: relative;
|
position: relative;
|
||||||
text-align: center;
|
text-decoration: none;
|
||||||
text-decoration: none;
|
|
||||||
box-shadow: 0 0 3px var(--darken-weak);
|
box-shadow: 0 0 3px var(--darken-weak);
|
||||||
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.poster {
|
.poster {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 17rem;
|
height: 100%;
|
||||||
object-fit: cover;
|
object-fit: cover;
|
||||||
object-position: 50% 100%;
|
object-position: 50% 100%;
|
||||||
}
|
}
|
||||||
|
@ -97,9 +96,25 @@ export default {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
background: var(--darken);
|
background: var(--darken);
|
||||||
|
overflow: hidden;
|
||||||
|
white-space: nowrap;
|
||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
text-transform: capitalize;
|
text-transform: capitalize;
|
||||||
text-shadow: 0 0 3px var(--darken-strong);
|
text-shadow: 0 0 3px var(--darken-strong);
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media(max-width: $breakpoint) {
|
||||||
|
.tile {
|
||||||
|
position: initial;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
position: initial;
|
||||||
|
color: var(--text);
|
||||||
|
background: var(--background);
|
||||||
|
text-shadow: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
|
@ -1,74 +0,0 @@
|
||||||
<template>
|
|
||||||
<a
|
|
||||||
:href="`/network/${network.slug}`"
|
|
||||||
:title="network.name"
|
|
||||||
class="tile"
|
|
||||||
:class="{ sfw }"
|
|
||||||
>
|
|
||||||
<img
|
|
||||||
:src="`/img/logos/${network.slug}/thumbs/network.png`"
|
|
||||||
:alt="network.name"
|
|
||||||
class="logo"
|
|
||||||
>
|
|
||||||
</a>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
function sfw() {
|
|
||||||
return this.$store.state.ui.sfw;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default {
|
|
||||||
props: {
|
|
||||||
network: {
|
|
||||||
type: Object,
|
|
||||||
default: null,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
sfw,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
@import 'theme';
|
|
||||||
|
|
||||||
.tile {
|
|
||||||
height: 6rem;
|
|
||||||
background: var(--profile);
|
|
||||||
display: flex;
|
|
||||||
flex-shrink: 0;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
box-sizing: border-box;
|
|
||||||
padding: .5rem 1rem;
|
|
||||||
box-shadow: 0 0 3px rgba(0, 0, 0, .25);
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.link {
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.logo {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
color: $text;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
object-fit: contain;
|
|
||||||
font-size: 1rem;
|
|
||||||
font-weight: bold;
|
|
||||||
/* filter: $logo-highlight; */
|
|
||||||
}
|
|
||||||
|
|
||||||
.title {
|
|
||||||
color: var(--text);
|
|
||||||
height: 100%;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
</style>
|
|
|
@ -1,67 +0,0 @@
|
||||||
<template>
|
|
||||||
<a
|
|
||||||
:href="`/site/${site.slug}`"
|
|
||||||
:title="site.name"
|
|
||||||
class="tile"
|
|
||||||
>
|
|
||||||
<img
|
|
||||||
:src="`/img/logos/${site.network.slug}/thumbs/${site.slug}.png`"
|
|
||||||
:alt="site.name"
|
|
||||||
class="logo"
|
|
||||||
>
|
|
||||||
</a>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
props: {
|
|
||||||
site: {
|
|
||||||
type: Object,
|
|
||||||
default: null,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
@import 'theme';
|
|
||||||
|
|
||||||
.tile {
|
|
||||||
height: 6rem;
|
|
||||||
background: $tile;
|
|
||||||
display: flex;
|
|
||||||
flex-shrink: 0;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
box-sizing: border-box;
|
|
||||||
padding: .5rem 1rem;
|
|
||||||
border-radius: .25rem;
|
|
||||||
box-shadow: 0 0 3px rgba(0, 0, 0, .25);
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.link {
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.logo {
|
|
||||||
width: 100%;
|
|
||||||
height: 5rem;
|
|
||||||
color: $text-contrast;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
object-fit: contain;
|
|
||||||
font-size: 1rem;
|
|
||||||
font-weight: bold;
|
|
||||||
filter: $logo-highlight;
|
|
||||||
}
|
|
||||||
|
|
||||||
.title {
|
|
||||||
color: $text;
|
|
||||||
height: 100%;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
</style>
|
|
|
@ -51,7 +51,7 @@ $female: #f0a;
|
||||||
--lighten-strong: rgba(255, 255, 255, .7);
|
--lighten-strong: rgba(255, 255, 255, .7);
|
||||||
--lighten-extreme: rgba(255, 255, 255, .9);
|
--lighten-extreme: rgba(255, 255, 255, .9);
|
||||||
--lighten-weak: rgba(255, 255, 255, .2);
|
--lighten-weak: rgba(255, 255, 255, .2);
|
||||||
--lighten-hint: rgba(255, 255, 255, .1);
|
--lighten-hint: rgba(255, 255, 255, .05);
|
||||||
|
|
||||||
--logo-shadow: drop-shadow(1px 0 0 $shadow-weak) drop-shadow(-1px 0 0 $shadow-weak) drop-shadow(0 1px 0 $shadow-weak) drop-shadow(0 -1px 0 $shadow-weak);
|
--logo-shadow: drop-shadow(1px 0 0 $shadow-weak) drop-shadow(-1px 0 0 $shadow-weak) drop-shadow(0 1px 0 $shadow-weak) drop-shadow(0 -1px 0 $shadow-weak);
|
||||||
--logo-highlight: drop-shadow(0 0 1px $highlight);
|
--logo-highlight: drop-shadow(0 0 1px $highlight);
|
||||||
|
|
|
@ -9,6 +9,10 @@
|
||||||
border-radius: 16px;
|
border-radius: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&:not(.popover) .tooltip-inner {
|
||||||
|
padding: .25rem .5rem;
|
||||||
|
}
|
||||||
|
|
||||||
.tooltip-arrow {
|
.tooltip-arrow {
|
||||||
width: 0;
|
width: 0;
|
||||||
height: 0;
|
height: 0;
|
||||||
|
|
|
@ -37,56 +37,3 @@ body {
|
||||||
fill: $primary;
|
fill: $primary;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.expand {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
padding: .5rem .25rem;
|
|
||||||
font-weight: bold;
|
|
||||||
font-size: .9rem;
|
|
||||||
cursor: pointer;
|
|
||||||
|
|
||||||
.icon {
|
|
||||||
fill: $shadow;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background: $shadow-hint;
|
|
||||||
|
|
||||||
.icon {
|
|
||||||
fill: $shadow-strong;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.expand-sidebar:hover {
|
|
||||||
background: $shadow-hint;
|
|
||||||
}
|
|
||||||
|
|
||||||
.expand-header {
|
|
||||||
display: none;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background: $shadow-hint;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.collapse-header {
|
|
||||||
width: 100%;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
padding: 0;
|
|
||||||
background: $profile;
|
|
||||||
|
|
||||||
.icon {
|
|
||||||
width: 100%;
|
|
||||||
fill: $highlight;
|
|
||||||
padding: .5rem 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover .icon {
|
|
||||||
background: $highlight-hint;
|
|
||||||
fill: $text-contrast;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -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>arrow-left2</title>
|
||||||
|
<path d="M10.5 16l2-2-6-6 6-6-2-2-8 8 8 8z"></path>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 217 B |
|
@ -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>arrow-right2</title>
|
||||||
|
<path d="M5.5 0l-2 2 6 6-6 6 2 2 8-8-8-8z"></path>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 217 B |
|
@ -1,3 +1,4 @@
|
||||||
|
import config from 'config';
|
||||||
import { graphql, get } from '../api';
|
import { graphql, get } from '../api';
|
||||||
import {
|
import {
|
||||||
releaseFields,
|
releaseFields,
|
||||||
|
@ -8,7 +9,7 @@ import {
|
||||||
import { curateActor, curateRelease } from '../curate';
|
import { curateActor, curateRelease } from '../curate';
|
||||||
import getDateRange from '../get-date-range';
|
import getDateRange from '../get-date-range';
|
||||||
|
|
||||||
function initActorActions(store, _router) {
|
function initActorActions(store, router) {
|
||||||
async function fetchActorById({ _commit }, {
|
async function fetchActorById({ _commit }, {
|
||||||
actorId,
|
actorId,
|
||||||
limit = 10,
|
limit = 10,
|
||||||
|
@ -16,6 +17,7 @@ function initActorActions(store, _router) {
|
||||||
range = 'latest',
|
range = 'latest',
|
||||||
}) {
|
}) {
|
||||||
const { before, after, orderBy } = getDateRange(range);
|
const { before, after, orderBy } = getDateRange(range);
|
||||||
|
const includeTags = router.currentRoute.query.tags ? router.currentRoute.query.tags.split(',') : [];
|
||||||
|
|
||||||
const { actor, connection: { releases, totalCount } } = await graphql(`
|
const { actor, connection: { releases, totalCount } } = await graphql(`
|
||||||
query Actor(
|
query Actor(
|
||||||
|
@ -25,7 +27,9 @@ function initActorActions(store, _router) {
|
||||||
$after:Date = "1900-01-01",
|
$after:Date = "1900-01-01",
|
||||||
$before:Date = "2100-01-01",
|
$before:Date = "2100-01-01",
|
||||||
$orderBy:[ReleasesActorsOrderBy!]
|
$orderBy:[ReleasesActorsOrderBy!]
|
||||||
$exclude: [String!]
|
$selectableTags: [String],
|
||||||
|
$excludeTags: [String!]
|
||||||
|
${includeTags.length > 0 ? '$includeTags: [String!]' : ''}
|
||||||
) {
|
) {
|
||||||
actor(id: $actorId) {
|
actor(id: $actorId) {
|
||||||
id
|
id
|
||||||
|
@ -57,10 +61,17 @@ function initActorActions(store, _router) {
|
||||||
description
|
description
|
||||||
createdAt
|
createdAt
|
||||||
updatedAt
|
updatedAt
|
||||||
network {
|
entity {
|
||||||
id
|
id
|
||||||
name
|
name
|
||||||
slug
|
slug
|
||||||
|
type
|
||||||
|
parent {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
slug
|
||||||
|
type
|
||||||
|
}
|
||||||
}
|
}
|
||||||
avatar: avatarMedia {
|
avatar: avatarMedia {
|
||||||
id
|
id
|
||||||
|
@ -80,15 +91,17 @@ function initActorActions(store, _router) {
|
||||||
profiles: actorsProfiles {
|
profiles: actorsProfiles {
|
||||||
description
|
description
|
||||||
descriptionHash
|
descriptionHash
|
||||||
network {
|
entity {
|
||||||
id
|
id
|
||||||
slug
|
|
||||||
name
|
name
|
||||||
}
|
|
||||||
site {
|
|
||||||
id
|
|
||||||
slug
|
slug
|
||||||
name
|
type
|
||||||
|
parent {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
slug
|
||||||
|
type
|
||||||
|
}
|
||||||
}
|
}
|
||||||
avatar: avatarMedia {
|
avatar: avatarMedia {
|
||||||
id
|
id
|
||||||
|
@ -130,22 +143,28 @@ function initActorActions(store, _router) {
|
||||||
name
|
name
|
||||||
slug
|
slug
|
||||||
}
|
}
|
||||||
|
tags(selectableTags: $selectableTags) {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
slug
|
||||||
|
priority
|
||||||
|
}
|
||||||
releasesConnection: releasesActorsConnection(
|
releasesConnection: releasesActorsConnection(
|
||||||
filter: {
|
filter: {
|
||||||
release: {
|
release: {
|
||||||
date: {
|
date: {
|
||||||
lessThan: $before,
|
lessThan: $before,
|
||||||
greaterThan: $after,
|
greaterThan: $after,
|
||||||
},
|
|
||||||
releasesTagsConnection: {
|
|
||||||
none: {
|
|
||||||
tag: {
|
|
||||||
slug: {
|
|
||||||
in: $exclude
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
releasesTagsConnection: {
|
||||||
|
none: {
|
||||||
|
tag: {
|
||||||
|
slug: {
|
||||||
|
in: $excludeTags
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
first: $limit
|
first: $limit
|
||||||
|
@ -162,12 +181,12 @@ function initActorActions(store, _router) {
|
||||||
${releaseActorsFragment}
|
${releaseActorsFragment}
|
||||||
${releaseTagsFragment}
|
${releaseTagsFragment}
|
||||||
${releasePosterFragment}
|
${releasePosterFragment}
|
||||||
site {
|
entity {
|
||||||
id
|
id
|
||||||
name
|
name
|
||||||
slug
|
slug
|
||||||
url
|
url
|
||||||
network {
|
parent {
|
||||||
id
|
id
|
||||||
name
|
name
|
||||||
slug
|
slug
|
||||||
|
@ -182,10 +201,10 @@ function initActorActions(store, _router) {
|
||||||
first: $limit
|
first: $limit
|
||||||
offset: $offset
|
offset: $offset
|
||||||
orderBy: $orderBy
|
orderBy: $orderBy
|
||||||
|
condition: {
|
||||||
|
actorId: $actorId
|
||||||
|
}
|
||||||
filter: {
|
filter: {
|
||||||
actorId: {
|
|
||||||
equalTo: $actorId
|
|
||||||
}
|
|
||||||
or: [
|
or: [
|
||||||
{
|
{
|
||||||
release: {
|
release: {
|
||||||
|
@ -196,6 +215,17 @@ function initActorActions(store, _router) {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
${includeTags.length > 0 ? `release: {
|
||||||
|
releasesTagsConnection: {
|
||||||
|
some: {
|
||||||
|
tag: {
|
||||||
|
slug: {
|
||||||
|
in: $includeTags
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}` : ''}
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
releases: nodes {
|
releases: nodes {
|
||||||
|
@ -212,8 +242,10 @@ function initActorActions(store, _router) {
|
||||||
offset: Math.max(0, (pageNumber - 1)) * limit,
|
offset: Math.max(0, (pageNumber - 1)) * limit,
|
||||||
after,
|
after,
|
||||||
before,
|
before,
|
||||||
|
selectableTags: config.selectableTags,
|
||||||
orderBy: orderBy === 'DATE_DESC' ? 'RELEASE_BY_RELEASE_ID__DATE_DESC' : 'RELEASE_BY_RELEASE_ID__DATE_ASC',
|
orderBy: orderBy === 'DATE_DESC' ? 'RELEASE_BY_RELEASE_ID__DATE_DESC' : 'RELEASE_BY_RELEASE_ID__DATE_ASC',
|
||||||
exclude: store.state.ui.filter,
|
excludeTags: store.state.ui.filter,
|
||||||
|
includeTags,
|
||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -265,10 +297,17 @@ function initActorActions(store, _router) {
|
||||||
dateOfBirth
|
dateOfBirth
|
||||||
dateOfDeath
|
dateOfDeath
|
||||||
gender
|
gender
|
||||||
network {
|
entity {
|
||||||
id
|
id
|
||||||
name
|
name
|
||||||
slug
|
slug
|
||||||
|
type
|
||||||
|
parent {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
slug
|
||||||
|
type
|
||||||
|
}
|
||||||
}
|
}
|
||||||
avatar: avatarMedia {
|
avatar: avatarMedia {
|
||||||
id
|
id
|
||||||
|
|
|
@ -2,9 +2,28 @@ export default {
|
||||||
api: {
|
api: {
|
||||||
url: `${window.location.origin}/api`,
|
url: `${window.location.origin}/api`,
|
||||||
},
|
},
|
||||||
filename: {
|
selectableTags: [
|
||||||
pattern: '{site.name} - {title} ({actors.$n.name}, {date} {shootId})',
|
'airtight',
|
||||||
separator: ', ',
|
'anal',
|
||||||
date: 'DD-MM-YYYY',
|
'blowjob',
|
||||||
},
|
'creampie',
|
||||||
|
'deepthroat',
|
||||||
|
'double-anal',
|
||||||
|
'double-penetration',
|
||||||
|
'double-vaginal',
|
||||||
|
'facefucking',
|
||||||
|
'facial',
|
||||||
|
'fisting',
|
||||||
|
'gaping',
|
||||||
|
'gangbang',
|
||||||
|
'interracial',
|
||||||
|
'lesbian',
|
||||||
|
'mff',
|
||||||
|
'mfm',
|
||||||
|
'orgy',
|
||||||
|
'pov',
|
||||||
|
'solo',
|
||||||
|
'squirting',
|
||||||
|
'swallowing',
|
||||||
|
],
|
||||||
};
|
};
|
||||||
|
|
|
@ -31,16 +31,15 @@ function curateActor(actor, release) {
|
||||||
|
|
||||||
if (actor.profiles && actor.profiles.length > 0) {
|
if (actor.profiles && actor.profiles.length > 0) {
|
||||||
const photos = actor.profiles
|
const photos = actor.profiles
|
||||||
.map(profile => profile.avatar)
|
.map(profile => ({ entity: profile.entity, ...profile.avatar }))
|
||||||
.filter(avatar => avatar && (!curatedActor.avatar || avatar.hash !== curatedActor.avatar.hash));
|
.filter(avatar => avatar.id && (!curatedActor.avatar || avatar.hash !== curatedActor.avatar.hash));
|
||||||
|
|
||||||
const descriptions = actor.profiles.reduce((acc, profile) => ({
|
const descriptions = actor.profiles.reduce((acc, profile) => ({
|
||||||
...acc,
|
...acc,
|
||||||
...(profile.description && {
|
...(profile.description && {
|
||||||
[profile.descriptionHash]: {
|
[profile.descriptionHash]: {
|
||||||
text: profile.description,
|
text: profile.description,
|
||||||
network: profile.network,
|
entity: profile.entity,
|
||||||
site: profile.site,
|
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
}), {});
|
}), {});
|
||||||
|
@ -68,7 +67,6 @@ function curateRelease(release) {
|
||||||
tags: release.tags ? release.tags.map(({ tag }) => tag) : [],
|
tags: release.tags ? release.tags.map(({ tag }) => tag) : [],
|
||||||
};
|
};
|
||||||
|
|
||||||
if (release.site) curatedRelease.network = release.site.network;
|
|
||||||
if (release.scenes) curatedRelease.scenes = release.scenes.map(({ scene }) => curateRelease(scene));
|
if (release.scenes) curatedRelease.scenes = release.scenes.map(({ scene }) => curateRelease(scene));
|
||||||
if (release.movies) curatedRelease.movies = release.movies.map(({ movie }) => curateRelease(movie));
|
if (release.movies) curatedRelease.movies = release.movies.map(({ movie }) => curateRelease(movie));
|
||||||
if (release.photos) curatedRelease.photos = release.photos.map(({ media }) => media);
|
if (release.photos) curatedRelease.photos = release.photos.map(({ media }) => media);
|
||||||
|
@ -100,6 +98,7 @@ function curateSite(site, network) {
|
||||||
|
|
||||||
function curateNetwork(network, releases) {
|
function curateNetwork(network, releases) {
|
||||||
const curatedNetwork = {
|
const curatedNetwork = {
|
||||||
|
...network,
|
||||||
id: network.id,
|
id: network.id,
|
||||||
name: network.name,
|
name: network.name,
|
||||||
slug: network.slug,
|
slug: network.slug,
|
||||||
|
@ -116,6 +115,26 @@ function curateNetwork(network, releases) {
|
||||||
return curatedNetwork;
|
return curatedNetwork;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function curateEntity(entity, parent, releases) {
|
||||||
|
const curatedEntity = {
|
||||||
|
...entity,
|
||||||
|
children: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
if (entity.children) {
|
||||||
|
if (entity.children.nodes) {
|
||||||
|
curatedEntity.children = entity.children.nodes.map(childEntity => curateEntity(childEntity, curatedEntity));
|
||||||
|
}
|
||||||
|
|
||||||
|
curatedEntity.childrenTotal = entity.children.totalCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entity.parent || parent) curatedEntity.parent = curateEntity(entity.parent || parent);
|
||||||
|
if (releases) curatedEntity.releases = releases.map(release => curateRelease(release));
|
||||||
|
|
||||||
|
return curatedEntity;
|
||||||
|
}
|
||||||
|
|
||||||
function curateTag(tag) {
|
function curateTag(tag) {
|
||||||
const curatedTag = {
|
const curatedTag = {
|
||||||
...tag,
|
...tag,
|
||||||
|
@ -130,6 +149,7 @@ function curateTag(tag) {
|
||||||
|
|
||||||
export {
|
export {
|
||||||
curateActor,
|
curateActor,
|
||||||
|
curateEntity,
|
||||||
curateRelease,
|
curateRelease,
|
||||||
curateSite,
|
curateSite,
|
||||||
curateNetwork,
|
curateNetwork,
|
||||||
|
|
|
@ -0,0 +1,219 @@
|
||||||
|
import { graphql } from '../api';
|
||||||
|
// import { sitesFragment, releaseFields } from '../fragments';
|
||||||
|
import { releaseFields } from '../fragments';
|
||||||
|
import { curateEntity } from '../curate';
|
||||||
|
import getDateRange from '../get-date-range';
|
||||||
|
|
||||||
|
function initEntitiesActions(store, _router) {
|
||||||
|
async function fetchEntityBySlugAndType({ _commit }, {
|
||||||
|
entitySlug,
|
||||||
|
entityType,
|
||||||
|
limit = 10,
|
||||||
|
pageNumber = 1,
|
||||||
|
range = 'latest',
|
||||||
|
}) {
|
||||||
|
const { before, after, orderBy } = getDateRange(range);
|
||||||
|
|
||||||
|
const { entity, connection: { releases, totalCount } } = await graphql(`
|
||||||
|
query Entity(
|
||||||
|
$entitySlug: String!
|
||||||
|
$entityType: String! = "channel"
|
||||||
|
$limit: Int = 10,
|
||||||
|
$offset: Int = 0,
|
||||||
|
$after: Date = "1900-01-01",
|
||||||
|
$before: Date = "2100-01-01",
|
||||||
|
$afterTime: Datetime = "1900-01-01",
|
||||||
|
$beforeTime: Datetime = "2100-01-01",
|
||||||
|
$orderBy: [ReleasesOrderBy!]
|
||||||
|
$exclude: [String!]
|
||||||
|
) {
|
||||||
|
entity: entityBySlugAndType(slug: $entitySlug, type: $entityType) {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
slug
|
||||||
|
url
|
||||||
|
hasLogo
|
||||||
|
children: childEntitiesConnection(
|
||||||
|
orderBy: [PRIORITY_DESC, NAME_ASC],
|
||||||
|
) {
|
||||||
|
nodes {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
slug
|
||||||
|
url
|
||||||
|
type
|
||||||
|
priority
|
||||||
|
hasLogo
|
||||||
|
}
|
||||||
|
}
|
||||||
|
parent {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
slug
|
||||||
|
type
|
||||||
|
url
|
||||||
|
hasLogo
|
||||||
|
}
|
||||||
|
}
|
||||||
|
connection: releasesConnection(
|
||||||
|
first: $limit
|
||||||
|
offset: $offset
|
||||||
|
orderBy: $orderBy
|
||||||
|
filter: {
|
||||||
|
and: [
|
||||||
|
{
|
||||||
|
or: [
|
||||||
|
{
|
||||||
|
entity: {
|
||||||
|
or: [
|
||||||
|
{ slug: { equalTo: $entitySlug } },
|
||||||
|
{ parent: { slug: { equalTo: $entitySlug } } },
|
||||||
|
{ parent: { parent: { slug: { equalTo: $entitySlug } } } }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
studio: {
|
||||||
|
slug: { equalTo: $entitySlug },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
{
|
||||||
|
or: [
|
||||||
|
{
|
||||||
|
date: {
|
||||||
|
lessThan: $before,
|
||||||
|
greaterThan: $after
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: {
|
||||||
|
isNull: true
|
||||||
|
},
|
||||||
|
createdAt: {
|
||||||
|
lessThan: $beforeTime,
|
||||||
|
greaterThan: $afterTime,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
releasesTagsConnection: {
|
||||||
|
none: {
|
||||||
|
tag: {
|
||||||
|
slug: {
|
||||||
|
in: $exclude
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
releases: nodes {
|
||||||
|
${releaseFields}
|
||||||
|
}
|
||||||
|
totalCount
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`, {
|
||||||
|
entitySlug,
|
||||||
|
entityType,
|
||||||
|
limit,
|
||||||
|
offset: Math.max(0, (pageNumber - 1)) * limit,
|
||||||
|
after,
|
||||||
|
before,
|
||||||
|
orderBy,
|
||||||
|
afterTime: store.getters.after,
|
||||||
|
beforeTime: store.getters.before,
|
||||||
|
exclude: store.state.ui.filter,
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
entity: curateEntity(entity, null, releases),
|
||||||
|
totalCount,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
async function fetchEntities({ _commit }, { type, entitySlugs }) {
|
||||||
|
const { entities } = await graphql(`
|
||||||
|
query Entities(
|
||||||
|
$type: String! = "network"
|
||||||
|
$entitySlugs: [String!] = []
|
||||||
|
) {
|
||||||
|
entities(
|
||||||
|
orderBy: NAME_ASC
|
||||||
|
filter: {
|
||||||
|
or: [
|
||||||
|
{
|
||||||
|
type: {
|
||||||
|
equalTo: $type
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
slug: {
|
||||||
|
in: $entitySlugs
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
slug
|
||||||
|
type
|
||||||
|
url
|
||||||
|
hasLogo
|
||||||
|
children: childEntitiesConnection {
|
||||||
|
totalCount
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`, {
|
||||||
|
type,
|
||||||
|
entitySlugs,
|
||||||
|
});
|
||||||
|
|
||||||
|
return entities.map(entity => curateEntity(entity));
|
||||||
|
}
|
||||||
|
|
||||||
|
async function searchEntities({ _commit }, { query, limit = 20 }) {
|
||||||
|
const { entities } = await graphql(`
|
||||||
|
query SearchEntities(
|
||||||
|
$query: String!
|
||||||
|
$limit:Int = 20,
|
||||||
|
) {
|
||||||
|
entities: searchEntities(
|
||||||
|
search: $query,
|
||||||
|
first: $limit
|
||||||
|
) {
|
||||||
|
name
|
||||||
|
slug
|
||||||
|
type
|
||||||
|
url
|
||||||
|
hasLogo
|
||||||
|
parent {
|
||||||
|
name
|
||||||
|
slug
|
||||||
|
type
|
||||||
|
url
|
||||||
|
hasLogo
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`, {
|
||||||
|
query,
|
||||||
|
limit,
|
||||||
|
});
|
||||||
|
|
||||||
|
return entities.map(entity => curateEntity(entity));
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
fetchEntityBySlugAndType,
|
||||||
|
fetchEntities,
|
||||||
|
searchEntities,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export default initEntitiesActions;
|
|
@ -0,0 +1,13 @@
|
||||||
|
import state from './state';
|
||||||
|
import mutations from './mutations';
|
||||||
|
import actions from './actions';
|
||||||
|
|
||||||
|
function initEntitiesStore(store, router) {
|
||||||
|
return {
|
||||||
|
state,
|
||||||
|
mutations,
|
||||||
|
actions: actions(store, router),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export default initEntitiesStore;
|
|
@ -0,0 +1 @@
|
||||||
|
export default {};
|
|
@ -0,0 +1 @@
|
||||||
|
export default {};
|
|
@ -1,31 +1,33 @@
|
||||||
const siteFragment = `
|
const siteFragment = `
|
||||||
site {
|
entity {
|
||||||
id
|
id
|
||||||
name
|
name
|
||||||
slug
|
slug
|
||||||
url
|
url
|
||||||
independent
|
type
|
||||||
network {
|
parent {
|
||||||
id
|
id
|
||||||
name
|
name
|
||||||
slug
|
slug
|
||||||
url
|
url
|
||||||
|
type
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const sitesFragment = `
|
const sitesFragment = `
|
||||||
sites {
|
entities {
|
||||||
id
|
id
|
||||||
name
|
name
|
||||||
slug
|
slug
|
||||||
url
|
url
|
||||||
independent
|
type
|
||||||
network {
|
parent {
|
||||||
id
|
id
|
||||||
name
|
name
|
||||||
slug
|
slug
|
||||||
url
|
url
|
||||||
|
type
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
@ -49,12 +51,12 @@ const actorFields = `
|
||||||
lazy
|
lazy
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
network {
|
network: entity {
|
||||||
id
|
id
|
||||||
name
|
name
|
||||||
slug
|
slug
|
||||||
}
|
}
|
||||||
originCountry: countryByBirthCountryAlpha2 {
|
birthCountry: countryByBirthCountryAlpha2 {
|
||||||
alpha2
|
alpha2
|
||||||
name
|
name
|
||||||
alias
|
alias
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import { graphql } from '../api';
|
import { graphql } from '../api';
|
||||||
import { sitesFragment, releaseFields } from '../fragments';
|
// import { sitesFragment, releaseFields } from '../fragments';
|
||||||
|
import { releaseFields } from '../fragments';
|
||||||
import { curateNetwork } from '../curate';
|
import { curateNetwork } from '../curate';
|
||||||
import getDateRange from '../get-date-range';
|
import getDateRange from '../get-date-range';
|
||||||
|
|
||||||
|
@ -24,50 +25,26 @@ function initNetworksActions(store, _router) {
|
||||||
$orderBy: [ReleasesOrderBy!]
|
$orderBy: [ReleasesOrderBy!]
|
||||||
$exclude: [String!]
|
$exclude: [String!]
|
||||||
) {
|
) {
|
||||||
network: networkBySlug(slug: $networkSlug) {
|
network: entityBySlugAndType(slug: $networkSlug, type: "network") {
|
||||||
id
|
id
|
||||||
name
|
name
|
||||||
slug
|
slug
|
||||||
url
|
url
|
||||||
networks: childNetworks(
|
sites: childEntities(
|
||||||
orderBy: NAME_ASC,
|
|
||||||
) {
|
|
||||||
id
|
|
||||||
name
|
|
||||||
slug
|
|
||||||
url
|
|
||||||
}
|
|
||||||
sites(
|
|
||||||
orderBy: [PRIORITY_DESC, NAME_ASC],
|
orderBy: [PRIORITY_DESC, NAME_ASC],
|
||||||
filter: {
|
|
||||||
show: {
|
|
||||||
equalTo: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
) {
|
) {
|
||||||
id
|
id
|
||||||
name
|
name
|
||||||
slug
|
slug
|
||||||
url
|
url
|
||||||
independent
|
type
|
||||||
priority
|
priority
|
||||||
network {
|
|
||||||
id
|
|
||||||
name
|
|
||||||
slug
|
|
||||||
url
|
|
||||||
}
|
|
||||||
}
|
|
||||||
studios {
|
|
||||||
id
|
|
||||||
name
|
|
||||||
slug
|
|
||||||
url
|
|
||||||
}
|
}
|
||||||
parent {
|
parent {
|
||||||
id
|
id
|
||||||
name
|
name
|
||||||
slug
|
slug
|
||||||
|
type
|
||||||
url
|
url
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -76,10 +53,10 @@ function initNetworksActions(store, _router) {
|
||||||
offset: $offset
|
offset: $offset
|
||||||
orderBy: $orderBy
|
orderBy: $orderBy
|
||||||
filter: {
|
filter: {
|
||||||
site: {
|
entity: {
|
||||||
or: [
|
or: [
|
||||||
{ network: { slug: { equalTo: $networkSlug } } },
|
{ parent: { slug: { equalTo: $networkSlug } } },
|
||||||
{ network: { parent: { slug: { equalTo: $networkSlug } } } }
|
{ parent: { parent: { slug: { equalTo: $networkSlug } } } }
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
or: [
|
or: [
|
||||||
|
@ -137,12 +114,19 @@ function initNetworksActions(store, _router) {
|
||||||
async function fetchNetworks({ _commit }) {
|
async function fetchNetworks({ _commit }) {
|
||||||
const { networks } = await graphql(`
|
const { networks } = await graphql(`
|
||||||
query Networks {
|
query Networks {
|
||||||
networks(orderBy: NAME_ASC) {
|
networks: entities(
|
||||||
|
orderBy: NAME_ASC
|
||||||
|
filter: {
|
||||||
|
type: {
|
||||||
|
equalTo: "network"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
) {
|
||||||
id
|
id
|
||||||
name
|
name
|
||||||
slug
|
slug
|
||||||
|
type
|
||||||
url
|
url
|
||||||
${sitesFragment}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`);
|
`);
|
||||||
|
|
|
@ -4,7 +4,7 @@ import VueRouter from 'vue-router';
|
||||||
import Home from '../components/home/home.vue';
|
import Home from '../components/home/home.vue';
|
||||||
import Release from '../components/releases/release.vue';
|
import Release from '../components/releases/release.vue';
|
||||||
import Site from '../components/sites/site.vue';
|
import Site from '../components/sites/site.vue';
|
||||||
import Network from '../components/networks/network.vue';
|
import Entity from '../components/entities/entity.vue';
|
||||||
import Networks from '../components/networks/networks.vue';
|
import Networks from '../components/networks/networks.vue';
|
||||||
import Actor from '../components/actors/actor.vue';
|
import Actor from '../components/actors/actor.vue';
|
||||||
import Actors from '../components/actors/actors.vue';
|
import Actors from '../components/actors/actors.vue';
|
||||||
|
@ -22,7 +22,7 @@ const routes = [
|
||||||
name: 'updates',
|
name: 'updates',
|
||||||
params: {
|
params: {
|
||||||
range: 'latest',
|
range: 'latest',
|
||||||
tags: 'all-tags',
|
tags: 'all',
|
||||||
pageNumber: 1,
|
pageNumber: 1,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -33,13 +33,12 @@ const routes = [
|
||||||
name: 'updates',
|
name: 'updates',
|
||||||
params: {
|
params: {
|
||||||
range: 'latest',
|
range: 'latest',
|
||||||
tags: 'all-tags',
|
|
||||||
pageNumber: 1,
|
pageNumber: 1,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/updates/:tags/:range/:pageNumber',
|
path: '/updates/:range/:pageNumber',
|
||||||
component: Home,
|
component: Home,
|
||||||
name: 'updates',
|
name: 'updates',
|
||||||
},
|
},
|
||||||
|
@ -61,53 +60,63 @@ const routes = [
|
||||||
params: {
|
params: {
|
||||||
...from.params,
|
...from.params,
|
||||||
range: 'latest',
|
range: 'latest',
|
||||||
tags: 'all-tags',
|
|
||||||
pageNumber: 1,
|
pageNumber: 1,
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/actor/:actorId/:actorSlug/:tags/:range/:pageNumber',
|
path: '/actor/:actorId/:actorSlug/:range/:pageNumber',
|
||||||
component: Actor,
|
component: Actor,
|
||||||
name: 'actorRange',
|
name: 'actorRange',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/site/:siteSlug',
|
path: '/channel/:entitySlug',
|
||||||
component: Site,
|
component: Site,
|
||||||
name: 'site',
|
|
||||||
redirect: from => ({
|
redirect: from => ({
|
||||||
name: 'siteRange',
|
name: 'channel',
|
||||||
params: {
|
params: {
|
||||||
...from.params,
|
...from.params,
|
||||||
range: 'latest',
|
range: 'latest',
|
||||||
tags: 'all-tags',
|
|
||||||
pageNumber: 1,
|
pageNumber: 1,
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/site/:siteSlug/:tags/:range/:pageNumber',
|
path: '/channel/:entitySlug/:range/:pageNumber',
|
||||||
component: Site,
|
component: Entity,
|
||||||
name: 'siteRange',
|
name: 'channel',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/network/:networkSlug',
|
path: '/network/:entitySlug',
|
||||||
component: Network,
|
redirect: from => ({
|
||||||
|
name: 'network',
|
||||||
|
params: {
|
||||||
|
...from.params,
|
||||||
|
range: 'latest',
|
||||||
|
pageNumber: 1,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/network/:entitySlug/:range/:pageNumber',
|
||||||
|
component: Entity,
|
||||||
name: 'network',
|
name: 'network',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/studio/:entitySlug',
|
||||||
redirect: from => ({
|
redirect: from => ({
|
||||||
name: 'networkRange',
|
name: 'studio',
|
||||||
params: {
|
params: {
|
||||||
...from.params,
|
...from.params,
|
||||||
range: 'latest',
|
range: 'latest',
|
||||||
tags: 'all-tags',
|
|
||||||
pageNumber: 1,
|
pageNumber: 1,
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/network/:networkSlug/:tags/:range/:pageNumber',
|
path: '/studio/:entitySlug/:range/:pageNumber',
|
||||||
component: Network,
|
component: Entity,
|
||||||
name: 'networkRange',
|
name: 'studio',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/tag/:tagSlug',
|
path: '/tag/:tagSlug',
|
||||||
|
@ -116,12 +125,11 @@ const routes = [
|
||||||
params: {
|
params: {
|
||||||
...from.params,
|
...from.params,
|
||||||
range: 'latest',
|
range: 'latest',
|
||||||
tags: 'all-tags',
|
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/tag/:tagSlug/:tags/:range',
|
path: '/tag/:tagSlug/:range',
|
||||||
component: Tag,
|
component: Tag,
|
||||||
name: 'tag',
|
name: 'tag',
|
||||||
},
|
},
|
||||||
|
@ -133,7 +141,7 @@ const routes = [
|
||||||
...from.params,
|
...from.params,
|
||||||
gender: 'female',
|
gender: 'female',
|
||||||
letter: 'all',
|
letter: 'all',
|
||||||
tags: 'all-tags',
|
tags: 'all',
|
||||||
range: 'latest',
|
range: 'latest',
|
||||||
pageNumber: 1,
|
pageNumber: 1,
|
||||||
},
|
},
|
||||||
|
|
|
@ -22,18 +22,18 @@ function initSitesActions(store, _router) {
|
||||||
$orderBy:[ReleasesOrderBy!]
|
$orderBy:[ReleasesOrderBy!]
|
||||||
$exclude: [String!]
|
$exclude: [String!]
|
||||||
) {
|
) {
|
||||||
site: siteBySlug(slug: $siteSlug) {
|
site: entityBySlugAndType(slug: $siteSlug, type: 2) {
|
||||||
name
|
name
|
||||||
slug
|
slug
|
||||||
url
|
url
|
||||||
tags: sitesTags {
|
tags: entitiesTags {
|
||||||
tag {
|
tag {
|
||||||
id
|
id
|
||||||
slug
|
slug
|
||||||
name
|
name
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
network {
|
network: parent {
|
||||||
id
|
id
|
||||||
name
|
name
|
||||||
slug
|
slug
|
||||||
|
@ -70,7 +70,7 @@ function initSitesActions(store, _router) {
|
||||||
offset: $offset
|
offset: $offset
|
||||||
orderBy: $orderBy
|
orderBy: $orderBy
|
||||||
filter: {
|
filter: {
|
||||||
site: {
|
entity: {
|
||||||
slug: {
|
slug: {
|
||||||
equalTo: $siteSlug
|
equalTo: $siteSlug
|
||||||
}
|
}
|
||||||
|
@ -122,7 +122,7 @@ function initSitesActions(store, _router) {
|
||||||
$after:Date = "1900-01-01",
|
$after:Date = "1900-01-01",
|
||||||
$before:Date = "2100-01-01",
|
$before:Date = "2100-01-01",
|
||||||
) {
|
) {
|
||||||
site {
|
site: entity {
|
||||||
name
|
name
|
||||||
slug
|
slug
|
||||||
url
|
url
|
||||||
|
@ -137,38 +137,9 @@ function initSitesActions(store, _router) {
|
||||||
return sites;
|
return sites;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function searchSites({ _commit }, { query, limit = 20 }) {
|
|
||||||
const { sites } = await graphql(`
|
|
||||||
query SearchSites(
|
|
||||||
$query: String!
|
|
||||||
$limit:Int = 20,
|
|
||||||
) {
|
|
||||||
sites: searchSites(
|
|
||||||
search: $query,
|
|
||||||
first: $limit
|
|
||||||
) {
|
|
||||||
name
|
|
||||||
slug
|
|
||||||
url
|
|
||||||
network {
|
|
||||||
name
|
|
||||||
slug
|
|
||||||
url
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`, {
|
|
||||||
query,
|
|
||||||
limit,
|
|
||||||
});
|
|
||||||
|
|
||||||
return sites;
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
fetchSiteBySlug,
|
fetchSiteBySlug,
|
||||||
fetchSites,
|
fetchSites,
|
||||||
searchSites,
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@ import Vuex from 'vuex';
|
||||||
import initUiStore from './ui/ui';
|
import initUiStore from './ui/ui';
|
||||||
import initAuthStore from './auth/auth';
|
import initAuthStore from './auth/auth';
|
||||||
import initReleasesStore from './releases/releases';
|
import initReleasesStore from './releases/releases';
|
||||||
|
import initEntitiesStore from './entities/entities';
|
||||||
import initSitesStore from './sites/sites';
|
import initSitesStore from './sites/sites';
|
||||||
import initNetworksStore from './networks/networks';
|
import initNetworksStore from './networks/networks';
|
||||||
import initActorsStore from './actors/actors';
|
import initActorsStore from './actors/actors';
|
||||||
|
@ -18,6 +19,7 @@ function initStore(router) {
|
||||||
store.registerModule('auth', initAuthStore(store, router));
|
store.registerModule('auth', initAuthStore(store, router));
|
||||||
store.registerModule('releases', initReleasesStore(store, router));
|
store.registerModule('releases', initReleasesStore(store, router));
|
||||||
store.registerModule('actors', initActorsStore(store, router));
|
store.registerModule('actors', initActorsStore(store, router));
|
||||||
|
store.registerModule('entities', initEntitiesStore(store, router));
|
||||||
store.registerModule('sites', initSitesStore(store, router));
|
store.registerModule('sites', initSitesStore(store, router));
|
||||||
store.registerModule('networks', initNetworksStore(store, router));
|
store.registerModule('networks', initNetworksStore(store, router));
|
||||||
store.registerModule('tags', initTagsStore(store, router));
|
store.registerModule('tags', initTagsStore(store, router));
|
||||||
|
|
|
@ -43,12 +43,12 @@ function initUiActions(_store, _router) {
|
||||||
url
|
url
|
||||||
type
|
type
|
||||||
isNew
|
isNew
|
||||||
site {
|
entity {
|
||||||
id
|
id
|
||||||
slug
|
slug
|
||||||
name
|
name
|
||||||
url
|
url
|
||||||
network {
|
parent {
|
||||||
id
|
id
|
||||||
slug
|
slug
|
||||||
name
|
name
|
||||||
|
@ -105,7 +105,7 @@ function initUiActions(_store, _router) {
|
||||||
dateOfBirth
|
dateOfBirth
|
||||||
dateOfDeath
|
dateOfDeath
|
||||||
gender
|
gender
|
||||||
network {
|
entity {
|
||||||
id
|
id
|
||||||
name
|
name
|
||||||
slug
|
slug
|
||||||
|
@ -124,7 +124,7 @@ function initUiActions(_store, _router) {
|
||||||
alias
|
alias
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
network {
|
entity {
|
||||||
id
|
id
|
||||||
name
|
name
|
||||||
slug
|
slug
|
||||||
|
|
|
@ -14,54 +14,49 @@ module.exports = {
|
||||||
// include: [],
|
// include: [],
|
||||||
// exclude: [],
|
// exclude: [],
|
||||||
exclude: [
|
exclude: [
|
||||||
['21sextreme', [
|
// 21sextreme, no longer updated
|
||||||
// no longer updated
|
'mightymistress',
|
||||||
'mightymistress',
|
'dominatedgirls',
|
||||||
'dominatedgirls',
|
'homepornreality',
|
||||||
'homepornreality',
|
'peeandblow',
|
||||||
'peeandblow',
|
'cummingmatures',
|
||||||
'cummingmatures',
|
'mandyiskinky',
|
||||||
'mandyiskinky',
|
'speculumplays',
|
||||||
'speculumplays',
|
'creampiereality',
|
||||||
'creampiereality',
|
// aziani
|
||||||
]],
|
'amberathome',
|
||||||
['aziani', [
|
'marycarey',
|
||||||
'amberathome',
|
'racqueldevonshire',
|
||||||
'marycarey',
|
// boobpedia
|
||||||
'racqueldevonshire',
|
|
||||||
]],
|
|
||||||
'boobpedia',
|
'boobpedia',
|
||||||
['blowpass', ['sunlustxxx']],
|
// blowpass
|
||||||
['ddfnetwork', [
|
'sunlustxxx',
|
||||||
'fuckinhd',
|
// ddfnetwork
|
||||||
'bustylover',
|
'fuckinhd',
|
||||||
]],
|
'bustylover',
|
||||||
['famedigital', [
|
// famedigital
|
||||||
'daringsex',
|
'daringsex',
|
||||||
'lowartfilms',
|
'lowartfilms',
|
||||||
]],
|
// freeones
|
||||||
'freeones',
|
'freeones',
|
||||||
['pornpros', [
|
// pornpros
|
||||||
'milfhumiliation',
|
'milfhumiliation',
|
||||||
'humiliated',
|
'humiliated',
|
||||||
'flexiblepositions',
|
'flexiblepositions',
|
||||||
'publicviolations',
|
'publicviolations',
|
||||||
'amateurviolations',
|
'amateurviolations',
|
||||||
'squirtdisgrace',
|
'squirtdisgrace',
|
||||||
'cumdisgrace',
|
'cumdisgrace',
|
||||||
'webcamhackers',
|
'webcamhackers',
|
||||||
'collegeteens',
|
'collegeteens',
|
||||||
]],
|
// score
|
||||||
['score', [
|
'bigboobbundle',
|
||||||
'bigboobbundle',
|
'milfbundle',
|
||||||
'milfbundle',
|
'pornmegaload',
|
||||||
'pornmegaload',
|
'scorelandtv',
|
||||||
'scorelandtv',
|
'scoretv',
|
||||||
'scoretv',
|
// mindgeek
|
||||||
]],
|
'pornhub',
|
||||||
['mindgeek', [
|
|
||||||
'pornhub',
|
|
||||||
]],
|
|
||||||
],
|
],
|
||||||
profiles: [
|
profiles: [
|
||||||
[
|
[
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
SELECT tags.name FROM actors
|
||||||
|
LEFT JOIN releases_actors ON releases_actors.actor_id = actors.id
|
||||||
|
LEFT JOIN releases_tags ON releases_tags.release_id = releases_actors.release_id
|
||||||
|
LEFT JOIN tags ON tags.id = releases_tags.tag_id
|
||||||
|
WHERE actors.slug = 'vina-sky'
|
||||||
|
GROUP BY tags.id
|
||||||
|
ORDER BY tags.name;
|
||||||
|
|
||||||
|
SELECT tags.*
|
||||||
|
FROM releases_actors
|
||||||
|
LEFT JOIN releases_tags ON releases_tags.release_id = releases_actors.release_id
|
||||||
|
LEFT JOIN tags ON tags.id = releases_tags.tag_id
|
||||||
|
WHERE releases_actors.actor_id = actor.id
|
||||||
|
GROUP BY tags.id
|
||||||
|
ORDER BY tags.name;
|
|
@ -97,6 +97,9 @@ exports.up = knex => Promise.resolve()
|
||||||
table.integer('priority', 2)
|
table.integer('priority', 2)
|
||||||
.defaultTo(0);
|
.defaultTo(0);
|
||||||
|
|
||||||
|
table.boolean('filter')
|
||||||
|
.defaultTo(false);
|
||||||
|
|
||||||
table.boolean('secondary')
|
table.boolean('secondary')
|
||||||
.defaultTo(false);
|
.defaultTo(false);
|
||||||
|
|
||||||
|
@ -140,52 +143,36 @@ exports.up = knex => Promise.resolve()
|
||||||
|
|
||||||
table.unique(['tag_id', 'media_id']);
|
table.unique(['tag_id', 'media_id']);
|
||||||
}))
|
}))
|
||||||
.then(() => knex.schema.createTable('networks', (table) => {
|
.then(() => knex.schema.createTable('entities_types', (table) => {
|
||||||
|
table.text('type')
|
||||||
|
.primary();
|
||||||
|
}))
|
||||||
|
.then(() => { // eslint-disable-line arrow-body-style
|
||||||
|
// allow vim fold
|
||||||
|
return knex('entities_types').insert([
|
||||||
|
{ type: 'network' },
|
||||||
|
{ type: 'channel' },
|
||||||
|
{ type: 'studio' },
|
||||||
|
{ type: 'info' },
|
||||||
|
]);
|
||||||
|
})
|
||||||
|
.then(() => knex.schema.createTable('entities', (table) => {
|
||||||
table.increments('id', 12);
|
table.increments('id', 12);
|
||||||
|
|
||||||
table.text('name');
|
|
||||||
table.text('alias');
|
|
||||||
table.text('url');
|
|
||||||
table.text('description');
|
|
||||||
table.json('parameters');
|
|
||||||
|
|
||||||
table.integer('parent_id', 12)
|
table.integer('parent_id', 12)
|
||||||
.references('id')
|
.references('id')
|
||||||
.inTable('networks');
|
.inTable('entities');
|
||||||
|
|
||||||
table.text('slug', 32)
|
|
||||||
.unique();
|
|
||||||
|
|
||||||
table.datetime('created_at')
|
|
||||||
.defaultTo(knex.fn.now());
|
|
||||||
}))
|
|
||||||
.then(() => knex.schema.createTable('networks_social', (table) => {
|
|
||||||
table.increments('id', 16);
|
|
||||||
|
|
||||||
table.text('url');
|
|
||||||
table.text('platform');
|
|
||||||
|
|
||||||
table.integer('network_id', 12)
|
|
||||||
.notNullable()
|
|
||||||
.references('id')
|
|
||||||
.inTable('networks');
|
|
||||||
|
|
||||||
table.unique(['url', 'network_id']);
|
|
||||||
|
|
||||||
table.datetime('created_at')
|
|
||||||
.defaultTo(knex.fn.now());
|
|
||||||
}))
|
|
||||||
.then(() => knex.schema.createTable('sites', (table) => {
|
|
||||||
table.increments('id', 12);
|
|
||||||
|
|
||||||
table.integer('network_id', 12)
|
|
||||||
.notNullable()
|
|
||||||
.references('id')
|
|
||||||
.inTable('networks');
|
|
||||||
|
|
||||||
table.text('name');
|
table.text('name');
|
||||||
table.text('slug', 32)
|
table.text('slug', 32);
|
||||||
.unique();
|
|
||||||
|
table.text('type')
|
||||||
|
.notNullable()
|
||||||
|
.references('type')
|
||||||
|
.inTable('entities_types')
|
||||||
|
.defaultTo('channel');
|
||||||
|
|
||||||
|
table.unique(['slug', 'type']);
|
||||||
|
|
||||||
table.text('alias');
|
table.text('alias');
|
||||||
|
|
||||||
|
@ -196,58 +183,40 @@ exports.up = knex => Promise.resolve()
|
||||||
table.integer('priority', 3)
|
table.integer('priority', 3)
|
||||||
.defaultTo(0);
|
.defaultTo(0);
|
||||||
|
|
||||||
table.boolean('show')
|
table.boolean('has_logo')
|
||||||
.defaultTo(true);
|
.defaultTo(true);
|
||||||
|
|
||||||
table.datetime('created_at')
|
table.datetime('created_at')
|
||||||
.defaultTo(knex.fn.now());
|
.defaultTo(knex.fn.now());
|
||||||
}))
|
}))
|
||||||
.then(() => knex.schema.createTable('sites_tags', (table) => {
|
.then(() => knex.schema.createTable('entities_tags', (table) => {
|
||||||
table.integer('tag_id', 12)
|
table.integer('tag_id', 12)
|
||||||
.notNullable()
|
.notNullable()
|
||||||
.references('id')
|
.references('id')
|
||||||
.inTable('tags');
|
.inTable('tags');
|
||||||
|
|
||||||
table.integer('site_id', 12)
|
table.integer('entity_id', 12)
|
||||||
.notNullable()
|
.notNullable()
|
||||||
.references('id')
|
.references('id')
|
||||||
.inTable('sites');
|
.inTable('entities');
|
||||||
|
|
||||||
table.boolean('inherit')
|
table.boolean('inherit')
|
||||||
.defaultTo(false);
|
.defaultTo(false);
|
||||||
|
|
||||||
table.unique(['tag_id', 'site_id']);
|
table.unique(['tag_id', 'entity_id']);
|
||||||
}))
|
}))
|
||||||
.then(() => knex.schema.createTable('sites_social', (table) => {
|
.then(() => knex.schema.createTable('entities_social', (table) => {
|
||||||
table.increments('id', 16);
|
table.increments('id', 16);
|
||||||
|
|
||||||
table.text('url');
|
table.text('url');
|
||||||
table.text('platform');
|
table.text('platform');
|
||||||
|
|
||||||
table.integer('site_id', 12)
|
table.integer('entity_id', 12)
|
||||||
.notNullable()
|
.notNullable()
|
||||||
.references('id')
|
.references('id')
|
||||||
.inTable('sites');
|
.inTable('entities');
|
||||||
|
|
||||||
table.unique(['url', 'site_id']);
|
table.unique(['url', 'entity_id']);
|
||||||
|
|
||||||
table.datetime('created_at')
|
|
||||||
.defaultTo(knex.fn.now());
|
|
||||||
}))
|
|
||||||
.then(() => knex.schema.createTable('studios', (table) => {
|
|
||||||
table.increments('id', 12);
|
|
||||||
|
|
||||||
table.integer('network_id', 12)
|
|
||||||
.notNullable()
|
|
||||||
.references('id')
|
|
||||||
.inTable('networks');
|
|
||||||
|
|
||||||
table.text('name');
|
|
||||||
table.text('url');
|
|
||||||
table.text('description');
|
|
||||||
|
|
||||||
table.text('slug', 32)
|
|
||||||
.unique();
|
|
||||||
|
|
||||||
table.datetime('created_at')
|
table.datetime('created_at')
|
||||||
.defaultTo(knex.fn.now());
|
.defaultTo(knex.fn.now());
|
||||||
|
@ -270,9 +239,9 @@ exports.up = knex => Promise.resolve()
|
||||||
|
|
||||||
table.text('real_name');
|
table.text('real_name');
|
||||||
|
|
||||||
table.integer('network_id', 12)
|
table.integer('entity_id', 12)
|
||||||
.references('id')
|
.references('id')
|
||||||
.inTable('networks');
|
.inTable('entities');
|
||||||
|
|
||||||
table.integer('alias_for', 12)
|
table.integer('alias_for', 12)
|
||||||
.references('id')
|
.references('id')
|
||||||
|
@ -337,15 +306,11 @@ exports.up = knex => Promise.resolve()
|
||||||
.references('id')
|
.references('id')
|
||||||
.inTable('actors');
|
.inTable('actors');
|
||||||
|
|
||||||
table.integer('network_id', 12)
|
table.integer('entity_id', 12)
|
||||||
.references('id')
|
.references('id')
|
||||||
.inTable('networks');
|
.inTable('entities');
|
||||||
|
|
||||||
table.integer('site_id', 12)
|
table.unique(['actor_id', 'entity_id']);
|
||||||
.references('id')
|
|
||||||
.inTable('sites');
|
|
||||||
|
|
||||||
table.unique(['actor_id', 'network_id', 'site_id']);
|
|
||||||
table.integer('priority', 4)
|
table.integer('priority', 4)
|
||||||
.defaultTo(1);
|
.defaultTo(1);
|
||||||
|
|
||||||
|
@ -624,24 +589,21 @@ exports.up = knex => Promise.resolve()
|
||||||
.then(() => knex.schema.createTable('releases', (table) => {
|
.then(() => knex.schema.createTable('releases', (table) => {
|
||||||
table.increments('id', 16);
|
table.increments('id', 16);
|
||||||
|
|
||||||
table.integer('site_id', 12)
|
table.integer('entity_id', 12)
|
||||||
.references('id')
|
.references('id')
|
||||||
.inTable('sites');
|
.inTable('entities')
|
||||||
|
.notNullable();
|
||||||
table.integer('network_id', 12)
|
|
||||||
.references('id')
|
|
||||||
.inTable('networks');
|
|
||||||
|
|
||||||
table.integer('studio_id', 12)
|
table.integer('studio_id', 12)
|
||||||
.references('id')
|
.references('id')
|
||||||
.inTable('studios');
|
.inTable('entities');
|
||||||
|
|
||||||
table.text('type', 10)
|
table.text('type', 10)
|
||||||
.defaultTo('scene');
|
.defaultTo('scene');
|
||||||
|
|
||||||
table.text('shoot_id');
|
table.text('shoot_id');
|
||||||
table.text('entry_id');
|
table.text('entry_id');
|
||||||
table.unique(['site_id', 'network_id', 'entry_id', 'type']);
|
table.unique(['entity_id', 'entry_id', 'type']);
|
||||||
|
|
||||||
table.text('url', 1000);
|
table.text('url', 1000);
|
||||||
table.text('title');
|
table.text('title');
|
||||||
|
@ -797,18 +759,10 @@ exports.up = knex => Promise.resolve()
|
||||||
.references('id')
|
.references('id')
|
||||||
.inTable('releases');
|
.inTable('releases');
|
||||||
}))
|
}))
|
||||||
|
// SEARCH
|
||||||
.then(() => { // eslint-disable-line arrow-body-style
|
.then(() => { // eslint-disable-line arrow-body-style
|
||||||
// allow vim fold
|
// allow vim fold
|
||||||
return knex.raw(`
|
return knex.raw(`
|
||||||
ALTER TABLE releases
|
|
||||||
ADD CONSTRAINT ensure_site_or_network CHECK (site_id IS NOT NULL OR network_id IS NOT NULL);
|
|
||||||
|
|
||||||
ALTER TABLE releases_search
|
|
||||||
ADD COLUMN document tsvector;
|
|
||||||
|
|
||||||
CREATE UNIQUE INDEX unique_actor_slugs_network ON actors (slug, network_id);
|
|
||||||
CREATE UNIQUE INDEX unique_actor_slugs ON actors (slug, (network_id IS NULL));
|
|
||||||
|
|
||||||
CREATE TEXT SEARCH DICTIONARY traxxx_dict (
|
CREATE TEXT SEARCH DICTIONARY traxxx_dict (
|
||||||
TEMPLATE = pg_catalog.simple,
|
TEMPLATE = pg_catalog.simple,
|
||||||
stopwords = traxxx
|
stopwords = traxxx
|
||||||
|
@ -818,12 +772,28 @@ exports.up = knex => Promise.resolve()
|
||||||
COPY = english
|
COPY = english
|
||||||
);
|
);
|
||||||
|
|
||||||
|
ALTER TABLE releases_search
|
||||||
|
ADD COLUMN document tsvector;
|
||||||
|
|
||||||
ALTER TEXT SEARCH CONFIGURATION traxxx
|
ALTER TEXT SEARCH CONFIGURATION traxxx
|
||||||
ALTER MAPPING FOR word, numword, hword, numhword, hword_part, hword_numpart, asciiword, asciihword, hword_asciipart WITH traxxx_dict, simple, english_stem;
|
ALTER MAPPING FOR word, numword, hword, numhword, hword_part, hword_numpart, asciiword, asciihword, hword_asciipart WITH traxxx_dict, simple, english_stem;
|
||||||
|
`);
|
||||||
|
})
|
||||||
|
// INDEXES
|
||||||
|
.then(() => { // eslint-disable-line arrow-body-style
|
||||||
|
// allow vim fold
|
||||||
|
return knex.raw(`
|
||||||
|
CREATE UNIQUE INDEX unique_actor_slugs_network ON actors (slug, entity_id);
|
||||||
|
CREATE UNIQUE INDEX unique_actor_slugs ON actors (slug, (entity_id IS NULL));
|
||||||
|
|
||||||
CREATE UNIQUE INDEX releases_search_unique ON releases_search (release_id);
|
CREATE UNIQUE INDEX releases_search_unique ON releases_search (release_id);
|
||||||
CREATE INDEX releases_search_index ON releases_search USING GIN (document);
|
CREATE INDEX releases_search_index ON releases_search USING GIN (document);
|
||||||
|
`);
|
||||||
|
})
|
||||||
|
// FUNCTIONS
|
||||||
|
.then(() => { // eslint-disable-line arrow-body-style
|
||||||
|
// allow vim fold
|
||||||
|
return knex.raw(`
|
||||||
CREATE FUNCTION search_releases(query text) RETURNS SETOF releases AS $$
|
CREATE FUNCTION search_releases(query text) RETURNS SETOF releases AS $$
|
||||||
SELECT * FROM releases WHERE releases.id IN (
|
SELECT * FROM releases WHERE releases.id IN (
|
||||||
SELECT release_id FROM releases_search AS search
|
SELECT release_id FROM releases_search AS search
|
||||||
|
@ -832,8 +802,8 @@ exports.up = knex => Promise.resolve()
|
||||||
);
|
);
|
||||||
$$ LANGUAGE SQL STABLE;
|
$$ LANGUAGE SQL STABLE;
|
||||||
|
|
||||||
CREATE FUNCTION search_sites(search text) RETURNS SETOF sites AS $$
|
CREATE FUNCTION search_entities(search text) RETURNS SETOF entities AS $$
|
||||||
SELECT * FROM sites
|
SELECT * FROM entities
|
||||||
WHERE
|
WHERE
|
||||||
name ILIKE ('%' || search || '%') OR
|
name ILIKE ('%' || search || '%') OR
|
||||||
slug ILIKE ('%' || search || '%') OR
|
slug ILIKE ('%' || search || '%') OR
|
||||||
|
@ -846,10 +816,33 @@ exports.up = knex => Promise.resolve()
|
||||||
AND name ILIKE ('%' || search || '%')
|
AND name ILIKE ('%' || search || '%')
|
||||||
$$ LANGUAGE SQL STABLE;
|
$$ LANGUAGE SQL STABLE;
|
||||||
|
|
||||||
CREATE FUNCTION releases_is_new(release releases) RETURNS boolean AS $$
|
CREATE FUNCTION actors_tags(actor actors, selectable_tags text[]) RETURNS SETOF tags AS $$
|
||||||
SELECT NOT EXISTS(SELECT true FROM batches WHERE batches.id = release.created_batch_id + 1 LIMIT 1);
|
SELECT tags.*
|
||||||
$$ LANGUAGE sql STABLE;
|
FROM releases_actors
|
||||||
|
LEFT JOIN
|
||||||
|
releases_tags ON releases_tags.release_id = releases_actors.release_id
|
||||||
|
LEFT JOIN
|
||||||
|
tags ON tags.id = releases_tags.tag_id
|
||||||
|
WHERE
|
||||||
|
releases_actors.actor_id = actor.id
|
||||||
|
AND
|
||||||
|
CASE WHEN array_length(selectable_tags, 1) IS NOT NULL
|
||||||
|
THEN tags.slug = ANY(selectable_tags)
|
||||||
|
ELSE true
|
||||||
|
END
|
||||||
|
GROUP BY tags.id
|
||||||
|
ORDER BY tags.name;
|
||||||
|
$$ LANGUAGE SQL STABLE;
|
||||||
|
|
||||||
|
CREATE FUNCTION releases_is_new(release releases) RETURNS boolean AS $$
|
||||||
|
SELECT EXISTS(SELECT true WHERE (SELECT id FROM batches ORDER BY created_at DESC LIMIT 1) = release.created_batch_id);
|
||||||
|
$$ LANGUAGE sql STABLE;
|
||||||
|
`);
|
||||||
|
})
|
||||||
|
// VIEWS AND COMMENTS
|
||||||
|
.then(() => { // eslint-disable-line arrow-body-style
|
||||||
|
// allow vim fold
|
||||||
|
return knex.raw(`
|
||||||
CREATE VIEW movie_actors AS
|
CREATE VIEW movie_actors AS
|
||||||
SELECT releases_movies.movie_id, releases_actors.actor_id FROM releases_movies
|
SELECT releases_movies.movie_id, releases_actors.actor_id FROM releases_movies
|
||||||
LEFT JOIN releases ON releases.id = releases_movies.scene_id
|
LEFT JOIN releases ON releases.id = releases_movies.scene_id
|
||||||
|
@ -897,6 +890,8 @@ exports.down = (knex) => { // eslint-disable-line arrow-body-style
|
||||||
DROP TABLE IF EXISTS actors_piercings CASCADE;
|
DROP TABLE IF EXISTS actors_piercings CASCADE;
|
||||||
DROP TABLE IF EXISTS body CASCADE;
|
DROP TABLE IF EXISTS body CASCADE;
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS entities_tags CASCADE;
|
||||||
|
DROP TABLE IF EXISTS entities_social CASCADE;
|
||||||
DROP TABLE IF EXISTS sites_tags CASCADE;
|
DROP TABLE IF EXISTS sites_tags CASCADE;
|
||||||
DROP TABLE IF EXISTS sites_social CASCADE;
|
DROP TABLE IF EXISTS sites_social CASCADE;
|
||||||
DROP TABLE IF EXISTS networks_social CASCADE;
|
DROP TABLE IF EXISTS networks_social CASCADE;
|
||||||
|
@ -915,10 +910,17 @@ exports.down = (knex) => { // eslint-disable-line arrow-body-style
|
||||||
DROP TABLE IF EXISTS countries CASCADE;
|
DROP TABLE IF EXISTS countries CASCADE;
|
||||||
DROP TABLE IF EXISTS networks CASCADE;
|
DROP TABLE IF EXISTS networks CASCADE;
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS entities_types CASCADE;
|
||||||
|
DROP TABLE IF EXISTS entities CASCADE;
|
||||||
|
|
||||||
DROP FUNCTION IF EXISTS search_sites;
|
DROP FUNCTION IF EXISTS search_sites;
|
||||||
|
DROP FUNCTION IF EXISTS search_entities;
|
||||||
DROP FUNCTION IF EXISTS search_actors;
|
DROP FUNCTION IF EXISTS search_actors;
|
||||||
DROP FUNCTION IF EXISTS get_random_sfw_media_id;
|
DROP FUNCTION IF EXISTS get_random_sfw_media_id;
|
||||||
|
|
||||||
|
DROP FUNCTION IF EXISTS releases_is_new;
|
||||||
|
DROP FUNCTION IF EXISTS actors_tags;
|
||||||
|
|
||||||
DROP TEXT SEARCH CONFIGURATION IF EXISTS traxxx;
|
DROP TEXT SEARCH CONFIGURATION IF EXISTS traxxx;
|
||||||
DROP TEXT SEARCH DICTIONARY IF EXISTS traxxx_dict;
|
DROP TEXT SEARCH DICTIONARY IF EXISTS traxxx_dict;
|
||||||
`);
|
`);
|
||||||
|
|
After Width: | Height: | Size: 56 KiB |
After Width: | Height: | Size: 94 KiB |
After Width: | Height: | Size: 5.0 KiB |
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.5 KiB |
Before Width: | Height: | Size: 5.0 KiB After Width: | Height: | Size: 5.0 KiB |
After Width: | Height: | Size: 19 KiB |
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 2.7 KiB |
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 19 KiB |
After Width: | Height: | Size: 20 KiB |
After Width: | Height: | Size: 5.8 KiB |
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.4 KiB |
Before Width: | Height: | Size: 5.1 KiB After Width: | Height: | Size: 5.1 KiB |
After Width: | Height: | Size: 19 KiB |
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 3.1 KiB |
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
After Width: | Height: | Size: 1.8 KiB |
After Width: | Height: | Size: 45 KiB |
Before Width: | Height: | Size: 6.7 KiB After Width: | Height: | Size: 6.7 KiB |
Before Width: | Height: | Size: 4.8 KiB After Width: | Height: | Size: 4.8 KiB |
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 5.7 KiB After Width: | Height: | Size: 5.7 KiB |
Before Width: | Height: | Size: 6.4 KiB After Width: | Height: | Size: 6.4 KiB |
Before Width: | Height: | Size: 6.3 KiB After Width: | Height: | Size: 6.3 KiB |
Before Width: | Height: | Size: 5.6 KiB After Width: | Height: | Size: 5.6 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 6.2 KiB After Width: | Height: | Size: 6.2 KiB |
Before Width: | Height: | Size: 5.3 KiB After Width: | Height: | Size: 5.3 KiB |
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.2 KiB |
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 3.4 KiB |
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.2 KiB |
Before Width: | Height: | Size: 5.8 KiB After Width: | Height: | Size: 5.8 KiB |
Before Width: | Height: | Size: 9.3 KiB After Width: | Height: | Size: 9.3 KiB |
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 3.5 KiB |
Before Width: | Height: | Size: 8.3 KiB After Width: | Height: | Size: 8.3 KiB |
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 2.0 KiB |
Before Width: | Height: | Size: 5.3 KiB After Width: | Height: | Size: 5.3 KiB |
Before Width: | Height: | Size: 4.5 KiB After Width: | Height: | Size: 4.5 KiB |
After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 5.1 KiB After Width: | Height: | Size: 5.1 KiB |
Before Width: | Height: | Size: 9.1 KiB After Width: | Height: | Size: 9.1 KiB |
Before Width: | Height: | Size: 6.8 KiB After Width: | Height: | Size: 6.8 KiB |
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 2.8 KiB |
Before Width: | Height: | Size: 5.8 KiB After Width: | Height: | Size: 5.8 KiB |
Before Width: | Height: | Size: 3.6 KiB After Width: | Height: | Size: 3.6 KiB |
Before Width: | Height: | Size: 6.2 KiB After Width: | Height: | Size: 6.2 KiB |
Before Width: | Height: | Size: 4.7 KiB After Width: | Height: | Size: 4.7 KiB |
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 5.6 KiB After Width: | Height: | Size: 5.6 KiB |
Before Width: | Height: | Size: 7.8 KiB After Width: | Height: | Size: 7.8 KiB |
Before Width: | Height: | Size: 4.7 KiB After Width: | Height: | Size: 4.7 KiB |
Before Width: | Height: | Size: 5.1 KiB After Width: | Height: | Size: 5.1 KiB |
Before Width: | Height: | Size: 4.0 KiB After Width: | Height: | Size: 4.0 KiB |