Improved actor scraping and display.

This commit is contained in:
2020-05-18 01:22:56 +02:00
parent af5543190a
commit 8733fdc657
28 changed files with 1033 additions and 793 deletions

View File

@@ -44,7 +44,7 @@
class="avatar-link"
>
<img
:src="`/media/${actor.avatar.thumbnail}`"
:src="sfw ? `/img/${actor.avatar.sfw.thumbnail}` : `/media/${actor.avatar.thumbnail}`"
:title="actor.avatar.copyright && `© ${actor.avatar.copyright}`"
class="avatar"
>
@@ -153,7 +153,7 @@
<Icon
v-if="actor.naturalBoobs === false"
v-tooltip="'Enhanced boobs'"
icon="star"
icon="magic-wand2"
class="enhanced"
/>{{ actor.bust || '??' }}{{ actor.cup || '?' }}-{{ actor.waist || '??' }}-{{ actor.hip || '??' }}
</span>
@@ -271,6 +271,10 @@ async function fetchActor() {
});
}
function sfw() {
return this.$store.state.ui.sfw;
}
async function route() {
await this.fetchActor();
}
@@ -303,6 +307,9 @@ export default {
expanded: false,
};
},
computed: {
sfw,
},
watch: {
$route: route,
},
@@ -495,6 +502,7 @@ export default {
.enhanced.icon {
fill: $primary;
padding: 0 .5rem;
transform: scaleX(-1);
}
.ethnicity {

View File

@@ -1,60 +1,60 @@
<template>
<div class="actors">
<nav class="filter">
<ul class="genders nolist">
<li class="gender">
<router-link
:to="{ name: 'actors', params: { gender: 'female', letter } }"
:class="{ selected: gender === 'female' }"
class="gender-link female"
><Gender gender="female" /></router-link>
</li>
<li class="gender">
<router-link
:to="{ name: 'actors', params: { gender: 'male', letter } }"
:class="{ selected: gender === 'male' }"
class="gender-link male"
><Gender gender="male" /></router-link>
</li>
<li class="gender">
<router-link
:to="{ name: 'actors', params: { gender: 'trans', letter } }"
:class="{ selected: gender === 'trans' }"
class="gender-link transsexual"
><Gender gender="transsexual" /></router-link>
</li>
<li class="gender">
<router-link
:to="{ name: 'actors', params: { gender: 'other', letter } }"
:class="{ selected: gender === 'other' }"
class="gender-link other"
><Icon icon="question5" /></router-link>
</li>
</ul>
<div class="actors">
<nav class="filter">
<ul class="genders nolist">
<li class="gender">
<router-link
:to="{ name: 'actors', params: { gender: 'female', letter } }"
:class="{ selected: gender === 'female' }"
class="gender-link female"
><Gender gender="female" /></router-link>
</li>
<li class="gender">
<router-link
:to="{ name: 'actors', params: { gender: 'male', letter } }"
:class="{ selected: gender === 'male' }"
class="gender-link male"
><Gender gender="male" /></router-link>
</li>
<li class="gender">
<router-link
:to="{ name: 'actors', params: { gender: 'trans', letter } }"
:class="{ selected: gender === 'trans' }"
class="gender-link transsexual"
><Gender gender="transsexual" /></router-link>
</li>
<li class="gender">
<router-link
:to="{ name: 'actors', params: { gender: 'other', letter } }"
:class="{ selected: gender === 'other' }"
class="gender-link other"
><Icon icon="question5" /></router-link>
</li>
</ul>
<ul class="letters nolist">
<li
v-for="letterX in letters"
:key="letterX"
class="letter"
>
<router-link
:to="{ name: 'actors', params: { gender, letter: letterX } }"
:class="{ selected: letterX === letter }"
class="letter-link"
>{{ letterX || 'All' }}</router-link>
</li>
</ul>
</nav>
<ul class="letters nolist">
<li
v-for="letterX in letters"
:key="letterX"
class="letter"
>
<router-link
:to="{ name: 'actors', params: { gender, letter: letterX } }"
:class="{ selected: letterX === letter }"
class="letter-link"
>{{ letterX || 'All' }}</router-link>
</li>
</ul>
</nav>
<div class="tiles">
<Actor
v-for="actor in actors"
:key="`actor-${actor.id}`"
:actor="actor"
/>
</div>
</div>
<div class="tiles">
<Actor
v-for="actor in actors"
:key="`actor-${actor.id}`"
:actor="actor"
/>
</div>
</div>
</template>
<script>
@@ -62,56 +62,56 @@ import Actor from '../tile/actor.vue';
import Gender from './gender.vue';
async function fetchActors() {
const curatedGender = this.gender.replace('trans', 'transsexual');
const curatedGender = this.gender.replace('trans', 'transsexual');
this.actors = await this.$store.dispatch('fetchActors', {
limit: 1000,
letter: this.letter.replace('all', ''),
gender: curatedGender === 'other' ? null : curatedGender,
});
this.actors = await this.$store.dispatch('fetchActors', {
limit: 1000,
letter: this.letter.replace('all', ''),
gender: curatedGender === 'other' ? null : curatedGender,
});
}
function letter() {
return this.$route.params.letter || 'all';
return this.$route.params.letter || 'all';
}
function gender() {
return this.$route.params.gender || 'female';
return this.$route.params.gender || 'female';
}
async function route() {
await this.fetchActors();
await this.fetchActors();
}
async function mounted() {
this.pageTitle = 'Actors';
this.pageTitle = 'Actors';
await this.fetchActors();
await this.fetchActors();
}
export default {
components: {
Actor,
Gender,
},
data() {
return {
actors: [],
pageTitle: null,
letters: ['all'].concat(Array.from({ length: 26 }, (value, index) => String.fromCharCode(index + 97).toUpperCase())),
};
},
computed: {
letter,
gender,
},
watch: {
$route: route,
},
mounted,
methods: {
fetchActors,
},
components: {
Actor,
Gender,
},
data() {
return {
actors: [],
pageTitle: null,
letters: ['all'].concat(Array.from({ length: 26 }, (value, index) => String.fromCharCode(index + 97).toUpperCase())),
};
},
computed: {
letter,
gender,
},
watch: {
$route: route,
},
mounted,
methods: {
fetchActors,
},
};
</script>
@@ -226,7 +226,7 @@ export default {
}
}
@media(max-width: $breakpoint) {
@media(max-width: $breakpoint0) {
.tiles {
grid-template-columns: repeat(auto-fill, minmax(8rem, 1fr));
}

View File

@@ -11,7 +11,7 @@
class="avatar-link photo-link"
>
<img
:src="`/media/${actor.avatar.thumbnail}`"
:src="sfw ? `/img/${actor.avatar.sfw.thumbnail}` : `/media/${actor.avatar.thumbnail}`"
:title="actor.avatar.copyright && `© ${actor.avatar.copyright}`"
class="avatar photo"
>
@@ -26,7 +26,7 @@
class="photo-link"
>
<img
:src="`/media/${photo.thumbnail}`"
:src="sfw ? `/img/${photo.sfw.thumbnail}` : `/media/${photo.thumbnail}`"
:title="photo.copyright && `© ${photo.copyright}`"
class="photo"
>
@@ -35,6 +35,10 @@
</template>
<script>
function sfw() {
return this.$store.state.ui.sfw;
}
export default {
props: {
actor: {
@@ -42,6 +46,9 @@ export default {
default: null,
},
},
computed: {
sfw,
},
};
</script>

View File

@@ -1,128 +1,128 @@
<template>
<header class="header">
<div class="header-nav">
<Icon
icon="menu"
class="sidebar-toggle"
@click.native.stop="toggleSidebar"
/>
<header class="header">
<div class="header-nav">
<Icon
icon="menu"
class="sidebar-toggle"
@click.native.stop="toggleSidebar"
/>
<router-link
to="/"
class="logo-link"
><h1 class="header-logo">
<div
class="logo"
v-html="logo"
/>
</h1></router-link>
<router-link
to="/"
class="logo-link"
><h1 class="header-logo">
<div
class="logo"
v-html="logo"
/>
</h1></router-link>
<nav class="nav">
<ul class="nav-list nolist">
<li class="nav-item">
<router-link
v-slot="{ href, isActive, navigate }"
to="/actors"
>
<a
class="nav-link"
:href="href"
:class="{ active: isActive }"
@click="navigate"
>Actors</a>
</router-link>
</li>
<nav class="nav">
<ul class="nav-list nolist">
<li class="nav-item">
<router-link
v-slot="{ href, isActive, navigate }"
to="/actors"
>
<a
class="nav-link"
:href="href"
:class="{ active: isActive }"
@click="navigate"
>Actors</a>
</router-link>
</li>
<li class="nav-item">
<router-link
v-slot="{ href, isActive, navigate }"
to="/networks"
>
<a
class="nav-link"
:href="href"
:class="{ active: isActive }"
@click="navigate"
>Sites</a>
</router-link>
</li>
<li class="nav-item">
<router-link
v-slot="{ href, isActive, navigate }"
to="/networks"
>
<a
class="nav-link"
:href="href"
:class="{ active: isActive }"
@click="navigate"
>Sites</a>
</router-link>
</li>
<li class="nav-item">
<router-link
v-slot="{ href, isActive, navigate }"
to="/tags"
>
<a
class="nav-link"
:href="href"
:class="{ active: isActive }"
@click="navigate"
>Tags</a>
</router-link>
</li>
</ul>
</nav>
</div>
<li class="nav-item">
<router-link
v-slot="{ href, isActive, navigate }"
to="/tags"
>
<a
class="nav-link"
:href="href"
:class="{ active: isActive }"
@click="navigate"
>Tags</a>
</router-link>
</li>
</ul>
</nav>
</div>
<div class="header-section">
<div class="header-toggles">
<Icon
v-show="!sfw"
v-tooltip="'Hit S to use SFW mode'"
icon="flower"
class="toggle noselect"
@click.native="setSfw(true)"
/>
<div class="header-section">
<div class="header-toggles">
<Icon
v-show="!sfw"
v-tooltip="'Hit S to use SFW mode'"
icon="flower"
class="toggle noselect"
@click.native="setSfw(true)"
/>
<Icon
v-show="sfw"
v-tooltip="'Hit N to use NSFW mode'"
icon="flower"
class="toggle active noselect"
@click.native="setSfw(false)"
/>
<Icon
v-show="sfw"
v-tooltip="'Hit N to use NSFW mode'"
icon="flower"
class="toggle active noselect"
@click.native="setSfw(false)"
/>
<Icon
v-show="theme === 'light'"
v-tooltip="'Hit D to use dark theme'"
icon="moon"
class="toggle noselect"
@click.native="setTheme('dark')"
/>
<Icon
v-show="theme === 'light'"
v-tooltip="'Hit D to use dark theme'"
icon="moon"
class="toggle noselect"
@click.native="setTheme('dark')"
/>
<Icon
v-show="theme === 'dark'"
v-tooltip="'Hit L to use light theme'"
icon="sun"
class="toggle noselect"
@click.native="setTheme('light')"
/>
</div>
<Icon
v-show="theme === 'dark'"
v-tooltip="'Hit L to use light theme'"
icon="sun"
class="toggle noselect"
@click.native="setTheme('light')"
/>
</div>
<Search class="search-full" />
<Search class="search-full" />
<v-popover
class="search-compact"
:open="searching"
@show="searching = true"
@hide="searching = false"
>
<button
type="button"
class="search-button"
><Icon
icon="search"
/></button>
<v-popover
class="search-compact"
:open="searching"
@show="searching = true"
@hide="searching = false"
>
<button
type="button"
class="search-button"
><Icon
icon="search"
/></button>
<Search
slot="popover"
:searching="searching"
class="compact"
@search="searching = false"
/>
</v-popover>
</div>
</header>
<Search
slot="popover"
:searching="searching"
class="compact"
@search="searching = false"
/>
</v-popover>
</div>
</header>
</template>
<script>
@@ -133,47 +133,47 @@ import Search from './search.vue';
import logo from '../../img/logo.svg';
function sfw(state) {
return state.ui.sfw;
return state.ui.sfw;
}
function theme(state) {
return state.ui.theme;
return state.ui.theme;
}
function setTheme(newTheme) {
this.$store.dispatch('setTheme', newTheme);
this.$store.dispatch('setTheme', newTheme);
}
function setSfw(enabled) {
this.$store.dispatch('setSfw', enabled);
this.$store.dispatch('setSfw', enabled);
}
export default {
components: {
Search,
},
props: {
toggleSidebar: {
type: Function,
default: null,
},
},
data() {
return {
logo,
searching: false,
};
},
computed: {
...mapState({
sfw,
theme,
}),
},
methods: {
setSfw,
setTheme,
},
components: {
Search,
},
props: {
toggleSidebar: {
type: Function,
default: null,
},
},
data() {
return {
logo,
searching: false,
};
},
computed: {
...mapState({
sfw,
theme,
}),
},
methods: {
setSfw,
setTheme,
},
};
</script>

View File

@@ -1,57 +1,64 @@
<template>
<form
class="search"
@submit.prevent="search"
>
<input
ref="search"
v-model="query"
type="search"
class="search-input"
placeholder="Search..."
>
<button
type="submit"
class="search-button"
><Icon
icon="search"
/></button>
</form>
<form
class="search"
@submit.prevent="search"
>
<input
ref="search"
v-model="query"
type="search"
class="search-input"
placeholder="Search..."
>
<button
type="submit"
class="search-button"
><Icon
icon="search"
/></button>
</form>
</template>
<script>
async function search() {
this.$router.push({ name: 'search', query: { q: this.query } });
this.$emit('search');
this.$router.push({ name: 'search', query: { q: this.query } });
this.$emit('search');
}
function searching(to) {
if (to) {
setTimeout(() => {
// nextTick does not seem to work
this.$refs.search.focus();
}, 20);
}
if (to) {
setTimeout(() => {
// nextTick does not seem to work
this.$refs.search.focus();
}, 20);
}
}
function route(to) {
if (to.name !== 'search') {
this.query = null;
}
}
export default {
props: {
searching: {
type: Boolean,
default: false,
},
},
data() {
return {
query: this.$route.query ? this.$route.query.q : null,
};
},
watch: {
searching,
},
methods: {
search,
},
props: {
searching: {
type: Boolean,
default: false,
},
},
data() {
return {
query: this.$route.query ? this.$route.query.q : null,
};
},
watch: {
$route: route,
searching,
},
methods: {
search,
},
};
</script>

View File

@@ -1,72 +1,72 @@
<template>
<div class="releases">
<h3
v-if="context"
class="heading"
><span class="range">{{ range }}</span> releases for '{{ context }}'</h3>
<div class="releases">
<h3
v-if="context"
class="heading"
><span class="range">{{ range }}</span> releases for '{{ context }}'</h3>
<ul
:key="sfw"
v-lazy-container="{ selector: '.thumbnail' }"
class="nolist tiles"
>
<li
v-for="(release, index) in releases"
:key="`release-${release.id}`"
>
<ReleaseTile
:release="release"
:referer="referer"
:index="index"
/>
</li>
</ul>
<ul
:key="sfw"
v-lazy-container="{ selector: '.thumbnail' }"
class="nolist tiles"
>
<li
v-for="(release, index) in releases"
:key="`release-${release.id}`"
>
<ReleaseTile
:release="release"
:referer="referer"
:index="index"
/>
</li>
</ul>
<span
v-if="releases.length === 0 && range !== 'all'"
class="empty"
>No {{ range }} releases</span>
<span
v-if="releases.length === 0 && range !== 'all'"
class="empty"
>No {{ range }} releases</span>
<span
v-else-if="releases.length === 0"
class="empty"
>No recent or upcoming releases</span>
</div>
<span
v-else-if="releases.length === 0"
class="empty"
>No recent or upcoming releases</span>
</div>
</template>
<script>
import ReleaseTile from '../tile/release.vue';
function range() {
return this.$route.params.range;
return this.$route.params.range;
}
function sfw() {
return this.$store.state.ui.sfw;
return this.$store.state.ui.sfw;
}
export default {
components: {
ReleaseTile,
},
props: {
releases: {
type: Array,
default: () => [],
},
context: {
type: String,
default: null,
},
referer: {
type: String,
default: null,
},
},
computed: {
range,
sfw,
},
components: {
ReleaseTile,
},
props: {
releases: {
type: Array,
default: () => [],
},
context: {
type: String,
default: null,
},
referer: {
type: String,
default: null,
},
},
computed: {
range,
sfw,
},
};
</script>

View File

@@ -1,47 +1,89 @@
<template>
<div class="content-inner">
<span
v-if="!loading"
class="summary"
>Found {{ releases.length }} results for '{{ query }}'</span>
<div class="content-inner">
<span
v-if="loading"
class="summary"
>Searching...</span>
<span
v-else
class="summary"
>Searching...</span>
<div v-if="!loading && actors.length > 0">
<span
v-if="!loading"
class="summary"
>Found {{ actors.length }} actors for '{{ query }}'</span>
<Releases :releases="releases" />
</div>
<div class="tiles">
<Actor
v-for="actor in actors"
:key="`actor-${actor.id}`"
:actor="actor.aliasFor || actor"
:alias="actor.aliasFor && actor"
/>
</div>
</div>
<div v-if="!loading && actors.length > 0">
<span
v-if="!loading"
class="summary"
>Found {{ releases.length }} releases for '{{ query }}'</span>
<Releases :releases="releases" />
</div>
</div>
</template>
<script>
import Actor from '../tile/actor.vue';
import Releases from '../releases/releases.vue';
async function search() {
const results = await this.$store.dispatch('search', {
query: this.query,
limit: 100,
});
this.loading = false;
if (results) {
this.actors = results.actors;
this.releases = results.releases;
}
}
function query() {
return this.$route.query.query || this.$route.query.q;
}
async function mounted() {
const results = await this.$store.dispatch('searchReleases', {
query: this.query,
limit: 100,
});
await this.search();
}
this.loading = false;
if (results) {
this.releases = results;
}
async function watchQuery() {
await this.search();
}
export default {
components: {
Releases,
},
data() {
return {
loading: true,
releases: [],
query: this.$route.query.query || this.$route.query.q,
};
},
mounted,
components: {
Actor,
Releases,
},
data() {
return {
loading: true,
actors: [],
releases: [],
};
},
computed: {
query,
},
watch: {
query: watchQuery,
},
mounted,
methods: {
search,
},
};
</script>
@@ -54,4 +96,12 @@ export default {
color: $shadow;
font-weight: bold;
}
.tiles {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(12rem, 1fr));
grid-gap: 0 .5rem;
flex-grow: 1;
margin: 0 0 1rem 0;
}
</style>

View File

@@ -8,29 +8,37 @@
class="link"
>
<span
v-if="actor.network"
v-tooltip.top="`${actor.name} (${actor.network.name})`"
class="handle"
>
<img
:src="`/img/logos/${actor.network.slug}/favicon.png`"
<span
v-tooltip.top="actor.name"
class="name"
>{{ actor.name }}</span>
<router-link
v-if="actor.network"
v-tooltip="actor.network.name"
:to="{ name: 'network', params: { networkSlug: actor.network.slug } }"
class="favicon"
>
<span class="name">{{ actor.name }}</span>
</span>
<img
:src="`/img/logos/${actor.network.slug}/favicon.png`"
class="favicon-icon"
>
</router-link>
<span
v-else
v-tooltip.top="actor.name"
class="handle"
>
<span class="name">{{ actor.name }}</span>
<Icon
v-if="alias"
v-tooltip="`Alias for ${alias.name}`"
icon="users3"
class="favicon alias"
/>
</span>
<div class="avatar-container">
<img
v-if="actor.avatar"
:src="`/media/${actor.avatar.thumbnail || actor.avatar}`"
:src="sfw ? `/img/${actor.avatar.sfw.thumbnail}` : `/media/${actor.avatar.thumbnail}`"
class="avatar"
>
@@ -45,7 +53,9 @@
<span
class="details"
>
<span class="age">
<span class="gender-age">
<Gender :gender="actor.gender" />
<span
v-if="actor.age"
v-tooltip="`Born on ${formatDate(actor.birthdate, 'MMMM D, YYYY')}`"
@@ -59,8 +69,6 @@
>{{ actor.ageThen }}</span>
</span>
<Gender :gender="actor.gender" />
<span
v-if="actor.origin"
v-tooltip="`Born in ${actor.origin.country.alias || actor.origin.country.name}`"
@@ -86,6 +94,10 @@
<script>
import Gender from '../actors/gender.vue';
function sfw() {
return this.$store.state.ui.sfw;
}
export default {
components: {
Gender,
@@ -95,6 +107,13 @@ export default {
type: Object,
default: null,
},
alias: {
type: Object,
default: null,
},
},
computed: {
sfw,
},
};
</script>
@@ -137,18 +156,29 @@ export default {
display: flex;
align-items: center;
justify-content: center;
padding: .5rem;
font-weight: bold;
.name {
padding: .5rem;
}
.alias {
fill: var(--highlight);
}
}
.favicon {
font-size: 0;
padding: .5rem .25rem;
&:last-child {
padding: .5rem;
}
}
.favicon-icon {
width: 1rem;
height: 1rem;
margin: 0 .5rem 0 0;
& + .name {
padding: 0 1rem 0 0;
}
}
.name {
@@ -156,13 +186,13 @@ export default {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
text-align: center;
}
.avatar-container {
display: flex;
flex-grow: 1;
position: relative;
overflow: hidden;
}
.avatar {
@@ -191,6 +221,7 @@ export default {
height: 1.75rem;
display: flex;
align-items: center;
justify-content: space-between;
box-sizing: border-box;
padding: .5rem;
position: absolute;
@@ -199,14 +230,13 @@ export default {
font-weight: bold;
}
.age,
.country,
.gender {
flex: 1;
.gender-age {
display: flex;
align-items: center;
}
.gender {
text-align: center;
margin: .25rem .25rem 0 0;
}
.country {
@@ -216,7 +246,7 @@ export default {
}
.flag {
height: 1rem;
height: .75rem;
margin: 0 0 0 .5rem;
}

View File

@@ -1,175 +1,175 @@
<template>
<div
:id="`${release.type}-${release.id}`"
:class="{ [release.type]: true }"
class="tile"
>
<span class="poster">
<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>
<div
:id="`${release.type}-${release.id}`"
:class="{ [release.type]: true }"
class="tile"
>
<span class="poster">
<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
v-else-if="release.network"
class="site"
>
<router-link
v-tooltip.bottom="`Part of ${release.network.name}`"
:title="`Part of ${release.network.name}`"
:to="`/network/${release.network.slug}`"
class="site-link"
><img
:src="`/img/logos/${release.network.slug}/favicon.png`"
class="favicon"
></router-link>
<span
v-else-if="release.network"
class="site"
>
<router-link
v-tooltip.bottom="`Part of ${release.network.name}`"
:title="`Part of ${release.network.name}`"
:to="`/network/${release.network.slug}`"
class="site-link"
><img
:src="`/img/logos/${release.network.slug}/favicon.png`"
class="favicon"
></router-link>
<router-link
v-tooltip.bottom="`More from ${release.site.name}`"
:title="`More from ${release.site.name}`"
:to="`/site/${release.site.slug}`"
class="site-link"
>{{ release.site.name }}</router-link>
</span>
<router-link
v-tooltip.bottom="`More from ${release.site.name}`"
:title="`More from ${release.site.name}`"
:to="`/site/${release.site.slug}`"
class="site-link"
>{{ release.site.name }}</router-link>
</span>
<span v-else />
<span v-else />
<a
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="{ upcoming: isAfter(release.date, new Date()), new: release.isNew }"
target="_blank"
rel="noopener noreferrer"
class="date"
>{{ formatDate(release.date, 'MMM D, YYYY') }}</a>
<a
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="{ upcoming: isAfter(release.date, new Date()), new: release.isNew }"
target="_blank"
rel="noopener noreferrer"
class="date"
>{{ formatDate(release.date, 'MMM D, YYYY') }}</a>
<a
v-else
:href="release.url"
:class="{ upcoming: isAfter(release.date, new Date()), new: release.isNew }"
title="Scene date N/A, showing date added"
target="_blank"
rel="noopener noreferrer"
class="date"
>{{ `(${formatDate(release.dateAdded, 'MMM D, YYYY')})` }}</a>
</span>
<a
v-else
:href="release.url"
:class="{ upcoming: isAfter(release.date, new Date()), new: release.isNew }"
title="Scene date N/A, showing date added"
target="_blank"
rel="noopener noreferrer"
class="date"
>{{ `(${formatDate(release.dateAdded, 'MMM D, YYYY')})` }}</a>
</span>
<a
:href="`/${release.type || 'scene'}/${release.id}/${release.slug}`"
target="_blank"
rel="noopener noreferrer"
class="link"
>
<img
v-if="release.poster"
:data-src="sfw ? `/img/${release.poster.sfw.thumbnail}` : `/media/${release.poster.thumbnail}`"
:data-loading="sfw ? `/img/${release.poster.sfw.lazy}` : `/media/${release.poster.lazy}`"
:alt="release.title"
class="thumbnail"
>
<a
:href="`/${release.type || 'scene'}/${release.id}/${release.slug}`"
target="_blank"
rel="noopener noreferrer"
class="link"
>
<img
v-if="release.poster"
:data-src="sfw ? `/img/${release.poster.sfw.thumbnail}` : `/media/${release.poster.thumbnail}`"
:data-loading="sfw ? `/img/${release.poster.sfw.lazy}` : `/media/${release.poster.lazy}`"
:alt="release.title"
class="thumbnail"
>
<span
v-else-if="release.covers && release.covers.length > 0"
class="covers"
>
<img
v-for="cover in release.covers"
:key="cover.id"
:data-src="sfw ? `/img/${cover.sfw.thumbnail}` : `/media/${cover.thumbnail}`"
:data-loading="sfw ? `/img/${cover.sfw.lazy}` : `/media/${cover.lazy}`"
:alt="release.title"
class="thumbnail cover"
>
</span>
<span
v-else-if="release.covers && release.covers.length > 0"
class="covers"
>
<img
v-for="cover in release.covers"
:key="cover.id"
:data-src="sfw ? `/img/${cover.sfw.thumbnail}` : `/media/${cover.thumbnail}`"
:data-loading="sfw ? `/img/${cover.sfw.lazy}` : `/media/${cover.lazy}`"
:alt="release.title"
class="thumbnail cover"
>
</span>
<div
v-else
:title="release.title"
class="thumbnail"
>No thumbnail available</div>
</a>
</span>
<div
v-else
:title="release.title"
class="thumbnail"
>No thumbnail available</div>
</a>
</span>
<div class="info">
<a
:href="`/${release.type || 'scene'}/${release.id}/${release.slug}`"
target="_blank"
rel="noopener noreferrer"
class="row link"
>
<h3
v-tooltip.top="release.title"
:title="release.title"
class="title"
>
<Icon
v-if="release.type === 'movie'"
icon="film"
/>{{ release.title }}
</h3>
</a>
<div class="info">
<a
:href="`/${release.type || 'scene'}/${release.id}/${release.slug}`"
target="_blank"
rel="noopener noreferrer"
class="row link"
>
<h3
v-tooltip.top="release.title"
:title="release.title"
class="title"
>
<Icon
v-if="release.type === 'movie'"
icon="film"
/>{{ release.title }}
</h3>
</a>
<span class="row">
<ul class="actors nolist">
<li
v-for="actor in release.actors"
:key="actor.id"
class="actor"
>
<a
:href="`/actor/${actor.slug}`"
class="actor-link"
>{{ actor.name }}</a>
</li>
</ul>
</span>
<span class="row">
<ul class="actors nolist">
<li
v-for="actor in release.actors"
:key="actor.id"
class="actor"
>
<a
:href="`/actor/${actor.slug}`"
class="actor-link"
>{{ actor.name }}</a>
</li>
</ul>
</span>
<ul
v-if="release.tags.length > 0"
:title="release.tags.map(tag => tag.name).join(', ')"
class="tags nolist"
>
<li
v-for="tag in release.tags"
:key="`tag-${tag.slug}`"
class="tag"
>
<router-link
:to="`/tag/${tag.slug}`"
class="tag-link"
>{{ tag.name }}</router-link>
</li>
</ul>
</div>
</div>
<ul
v-if="release.tags.length > 0"
:title="release.tags.map(tag => tag.name).join(', ')"
class="tags nolist"
>
<li
v-for="tag in release.tags"
:key="`tag-${tag.slug}`"
class="tag"
>
<router-link
:to="`/tag/${tag.slug}`"
class="tag-link"
>{{ tag.name }}</router-link>
</li>
</ul>
</div>
</div>
</template>
<script>
function sfw() {
return this.$store.state.ui.sfw;
return this.$store.state.ui.sfw;
}
export default {
props: {
release: {
type: Object,
default: null,
},
referer: {
type: String,
default: null,
},
},
computed: {
sfw,
},
props: {
release: {
type: Object,
default: null,
},
referer: {
type: String,
default: null,
},
},
computed: {
sfw,
},
};
</script>

View File

@@ -1,68 +1,68 @@
<template>
<router-link
:to="{ name: 'tag', params: { tagSlug: tag.slug } }"
:title="tag.name"
class="tile"
>
<span class="title">{{ tag.name }}</span>
<router-link
:to="{ name: 'tag', params: { tagSlug: tag.slug } }"
:title="tag.name"
class="tile"
>
<span class="title">{{ tag.name }}</span>
<template v-if="tag.poster">
<img
v-if="!lazy && !sfw"
:src="`/img/${tag.poster.thumbnail}`"
:title="tag.poster.comment"
:alt="tag.name"
class="poster"
>
<template v-if="tag.poster">
<img
v-if="!lazy && !sfw"
:src="`/img/${tag.poster.thumbnail}`"
:title="tag.poster.comment"
:alt="tag.name"
class="poster"
>
<img
v-if="!lazy && sfw"
:src="`/img/${tag.poster.sfw.thumbnail}`"
:title="tag.poster.sfw.comment"
:alt="tag.name"
class="poster"
>
<img
v-if="!lazy && sfw"
:src="`/img/${tag.poster.sfw.thumbnail}`"
:title="tag.poster.sfw.comment"
:alt="tag.name"
class="poster"
>
<img
v-if="lazy && !sfw"
:data-src="`/img/${tag.poster.thumbnail}`"
:data-loading="`/img/${tag.poster.lazy}`"
:title="tag.poster.comment"
:alt="tag.name"
class="poster"
>
<img
v-if="lazy && !sfw"
:data-src="`/img/${tag.poster.thumbnail}`"
:data-loading="`/img/${tag.poster.lazy}`"
:title="tag.poster.comment"
:alt="tag.name"
class="poster"
>
<img
v-if="lazy && sfw"
:data-src="`/img/${tag.poster.sfw.thumbnail}`"
:data-loading="`/img/${tag.poster.sfw.lazy}`"
:title="tag.poster.sfw.comment"
:alt="tag.name"
class="poster"
>
</template>
</router-link>
<img
v-if="lazy && sfw"
:data-src="`/img/${tag.poster.sfw.thumbnail}`"
:data-loading="`/img/${tag.poster.sfw.lazy}`"
:title="tag.poster.sfw.comment"
:alt="tag.name"
class="poster"
>
</template>
</router-link>
</template>
<script>
function sfw() {
return this.$store.state.ui.sfw;
return this.$store.state.ui.sfw;
}
export default {
props: {
tag: {
type: Object,
default: null,
},
lazy: {
type: Boolean,
default: false,
},
},
computed: {
sfw,
},
props: {
tag: {
type: Object,
default: null,
},
lazy: {
type: Boolean,
default: false,
},
},
computed: {
sfw,
},
};
</script>