forked from DebaucheryLibrarian/traxxx
Added timerange filters. Refactored releases module for more efficient queries.
This commit is contained in:
parent
a089bf892c
commit
1c3f17ec82
|
@ -2,7 +2,7 @@
|
|||
"root": true,
|
||||
"extends": ["airbnb-base", "plugin:vue/recommended"],
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 2017,
|
||||
"ecmaVersion": 2019,
|
||||
"sourceType": "module"
|
||||
},
|
||||
"rules": {
|
||||
|
|
|
@ -1,5 +1,50 @@
|
|||
<template>
|
||||
<div class="filter-bar noselect">
|
||||
<span>
|
||||
<label class="range">
|
||||
<input
|
||||
:id="`${_uid}-all`"
|
||||
:checked="range === 'all'"
|
||||
type="radio"
|
||||
class="range-input"
|
||||
@click="$emit('set-range', 'all')"
|
||||
>
|
||||
<label
|
||||
:for="`${_uid}-all`"
|
||||
class="range-button"
|
||||
>All</label>
|
||||
</label>
|
||||
|
||||
<label class="range">
|
||||
<input
|
||||
:id="`${_uid}-new`"
|
||||
:checked="range === 'new'"
|
||||
type="radio"
|
||||
class="range-input"
|
||||
@click="$emit('set-range', 'new')"
|
||||
>
|
||||
<label
|
||||
:for="`${_uid}-new`"
|
||||
class="range-button"
|
||||
>New</label>
|
||||
</label>
|
||||
|
||||
<label class="range">
|
||||
<input
|
||||
:id="`${_uid}-upcoming`"
|
||||
:checked="range === 'upcoming'"
|
||||
type="radio"
|
||||
class="range-input"
|
||||
@click="$emit('set-range', 'upcoming')"
|
||||
>
|
||||
<label
|
||||
:for="`${_uid}-upcoming`"
|
||||
class="range-button"
|
||||
>Upcoming</label>
|
||||
</label>
|
||||
</span>
|
||||
|
||||
<span>
|
||||
<Icon icon="filter" />
|
||||
|
||||
<Filters
|
||||
|
@ -19,6 +64,7 @@
|
|||
/>
|
||||
</div>
|
||||
</v-popover>
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -34,6 +80,10 @@ export default {
|
|||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
range: {
|
||||
type: String,
|
||||
default: null,
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
@ -43,7 +93,8 @@ export default {
|
|||
|
||||
.filter-bar {
|
||||
background: $background;
|
||||
display: block;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: .5rem 1rem;
|
||||
font-size: 0;
|
||||
box-shadow: 0 0 3px $shadow;
|
||||
|
@ -64,6 +115,30 @@ export default {
|
|||
margin: 0 0 0 .5rem;
|
||||
}
|
||||
|
||||
.range-button {
|
||||
color: $shadow;
|
||||
background: $background;
|
||||
display: inline-block;
|
||||
padding: .5rem 1rem;
|
||||
border: none;
|
||||
box-shadow: 0 0 2px $shadow-weak;
|
||||
font-size: .8rem;
|
||||
font-weight: bold;
|
||||
|
||||
&:hover {
|
||||
color: $text;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.range-input {
|
||||
display: none;
|
||||
|
||||
&:checked + .range-button {
|
||||
color: $primary;
|
||||
}
|
||||
}
|
||||
|
||||
@media(max-width: $breakpoint) {
|
||||
.filters-container {
|
||||
display: none;
|
||||
|
|
|
@ -1,25 +1,6 @@
|
|||
<template>
|
||||
<div :class="{ compact }">
|
||||
<ul class="filters">
|
||||
<li
|
||||
v-tooltip.bottom="'Not yet available'"
|
||||
class="filter"
|
||||
>
|
||||
<label
|
||||
class="toggle"
|
||||
:class="{ active: !localFilter.includes('straight') }"
|
||||
>
|
||||
<input
|
||||
v-model="localFilter"
|
||||
value="straight"
|
||||
type="checkbox"
|
||||
class="check"
|
||||
disabled
|
||||
@change="$emit('set-filter', localFilter)"
|
||||
>straight
|
||||
</label>
|
||||
</li>
|
||||
|
||||
<li class="filter">
|
||||
<label
|
||||
class="toggle"
|
||||
|
@ -82,23 +63,6 @@
|
|||
</label>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<ul class="filters">
|
||||
<li class="filter">
|
||||
<label
|
||||
class="toggle"
|
||||
:class="{ active: !localFilter.includes('femdom') }"
|
||||
>
|
||||
<input
|
||||
v-model="localFilter"
|
||||
value="femdom"
|
||||
type="checkbox"
|
||||
class="check"
|
||||
@change="$emit('set-filter', localFilter)"
|
||||
>femdom
|
||||
</label>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
|
@ -2,7 +2,9 @@
|
|||
<div class="content">
|
||||
<FilterBar
|
||||
:filter="filter"
|
||||
:range="range"
|
||||
@set-filter="setFilter"
|
||||
@set-range="setRange"
|
||||
/>
|
||||
|
||||
<div class="content-inner">
|
||||
|
@ -23,9 +25,12 @@
|
|||
import FilterBar from './filter-bar.vue';
|
||||
import ReleaseTile from '../tile/release.vue';
|
||||
|
||||
import rangeDates from '../../js/range-dates';
|
||||
|
||||
async function fetchReleases() {
|
||||
this.releases = await this.$store.dispatch('fetchReleases', {
|
||||
filter: this.filter,
|
||||
...rangeDates(this.range),
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -36,6 +41,13 @@ async function setFilter(filter) {
|
|||
await this.fetchReleases();
|
||||
}
|
||||
|
||||
async function setRange(range) {
|
||||
this.range = range;
|
||||
localStorage.setItem('range', this.range);
|
||||
|
||||
await this.fetchReleases();
|
||||
}
|
||||
|
||||
async function mounted() {
|
||||
this.pageTitle = '';
|
||||
|
||||
|
@ -49,9 +61,11 @@ export default {
|
|||
},
|
||||
data() {
|
||||
const storedFilter = localStorage.getItem('filter');
|
||||
const storedRange = localStorage.getItem('range');
|
||||
|
||||
return {
|
||||
filter: storedFilter ? storedFilter.split(',') : ['gay', 'transsexual'],
|
||||
range: storedRange || 'new',
|
||||
releases: [],
|
||||
networks: [],
|
||||
pageTitle: null,
|
||||
|
@ -61,6 +75,7 @@ export default {
|
|||
methods: {
|
||||
fetchReleases,
|
||||
setFilter,
|
||||
setRange,
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
<div class="column">
|
||||
<a
|
||||
v-if="release.date"
|
||||
v-tooltip.bottom="`View scene on ${release.site.name}`"
|
||||
:title="`View scene on ${release.site.name}`"
|
||||
:href="release.url"
|
||||
target="_blank"
|
||||
|
@ -21,6 +22,7 @@
|
|||
|
||||
<a
|
||||
v-if="release.date"
|
||||
v-tooltip.bottom="`View scene on ${release.site.name}`"
|
||||
:title="`View scene on ${release.site.name}`"
|
||||
:href="release.url"
|
||||
target="_blank"
|
||||
|
@ -33,6 +35,7 @@
|
|||
|
||||
<span
|
||||
v-if="release.shootId"
|
||||
v-tooltip.bottom="`Shoot #`"
|
||||
class="tidbit shoot hideable"
|
||||
>
|
||||
<Icon icon="clapboard-play" />
|
||||
|
@ -41,6 +44,7 @@
|
|||
|
||||
<span
|
||||
v-if="release.duration"
|
||||
v-tooltip.bottom="`Duration`"
|
||||
class="tidbit duration hideable"
|
||||
>
|
||||
<Icon icon="stopwatch" />
|
||||
|
@ -127,6 +131,20 @@
|
|||
</ul>
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-if="release.duration"
|
||||
class="row duration showable"
|
||||
>
|
||||
<Icon icon="stopwatch" />
|
||||
|
||||
<span
|
||||
v-if="release.duration >= 3600"
|
||||
class="duration-segment"
|
||||
>{{ Math.floor(release.duration / 3600) }}:</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>
|
||||
|
||||
<p
|
||||
v-if="release.description"
|
||||
class="row description"
|
||||
|
@ -150,29 +168,19 @@
|
|||
>{{ release.studio.name }}</a>
|
||||
</div>
|
||||
|
||||
<a
|
||||
<div
|
||||
v-if="release.shootId"
|
||||
class="row showable"
|
||||
>
|
||||
<Icon icon="clapboard-play" />
|
||||
|
||||
<a
|
||||
:href="release.url"
|
||||
:title="`release.shootId`"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
class="row shoot showable"
|
||||
>
|
||||
<Icon icon="clapboard-play" />{{ release.shootId }}
|
||||
</a>
|
||||
|
||||
<div
|
||||
v-if="release.duration"
|
||||
class="row duration showable"
|
||||
>
|
||||
<Icon icon="stopwatch" />
|
||||
|
||||
<span
|
||||
v-if="release.duration >= 3600"
|
||||
class="duration-segment"
|
||||
>{{ Math.floor(release.duration / 3600) }}:</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>
|
||||
class="link shoot"
|
||||
>{{ release.shootId }}</a>
|
||||
</div>
|
||||
|
||||
<span class="row">
|
||||
|
@ -199,7 +207,7 @@ function pageTitle() {
|
|||
}
|
||||
|
||||
async function mounted() {
|
||||
[this.release] = await this.$store.dispatch('fetchReleases', { id: this.$route.params.releaseId });
|
||||
this.release = await this.$store.dispatch('fetchReleases', { id: this.$route.params.releaseId });
|
||||
}
|
||||
|
||||
export default {
|
||||
|
@ -271,6 +279,7 @@ export default {
|
|||
&.date,
|
||||
&.duration,
|
||||
&.shoot {
|
||||
flex-shrink: 0;
|
||||
padding: 1.25rem 1rem 1.25rem 0;
|
||||
margin: 0 1rem 0 0;
|
||||
}
|
||||
|
@ -293,12 +302,14 @@ export default {
|
|||
height: 3rem;
|
||||
max-width: 15rem;
|
||||
object-fit: contain;
|
||||
object-position: 100% 50%;
|
||||
}
|
||||
|
||||
.logo-network {
|
||||
height: 1.5rem;
|
||||
max-width: 10rem;
|
||||
object-fit: contain;
|
||||
object-position: 100% 50%;
|
||||
}
|
||||
|
||||
.chain {
|
||||
|
@ -373,7 +384,8 @@ export default {
|
|||
}
|
||||
|
||||
.logo-site {
|
||||
max-width: 10rem;
|
||||
width: 15rem;
|
||||
max-width: 100%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -46,6 +46,6 @@ body {
|
|||
|
||||
@media(max-width: $breakpoint) {
|
||||
.scenes {
|
||||
grid-template-columns: repeat(auto-fit, minmax(22.5rem, 1fr));
|
||||
grid-template-columns: repeat(auto-fit, minmax(20rem, 1fr));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
function rangeDates(range) {
|
||||
return ({
|
||||
new: () => ({
|
||||
after: new Date(0),
|
||||
before: new Date(),
|
||||
}),
|
||||
upcoming: () => ({
|
||||
after: new Date(),
|
||||
before: new Date(2 ** 42),
|
||||
}),
|
||||
all: () => ({
|
||||
after: new Date(0),
|
||||
before: new Date(2 ** 42),
|
||||
}),
|
||||
})[range]();
|
||||
}
|
||||
|
||||
export default rangeDates;
|
|
@ -1,8 +1,22 @@
|
|||
import dayjs from 'dayjs';
|
||||
|
||||
import { get } from '../api';
|
||||
|
||||
function initReleasesActions(_store, _router) {
|
||||
async function fetchReleases({ _commit }, { id, filter }) {
|
||||
const releases = await get(`/releases/${id || ''}`, { filter });
|
||||
async function fetchReleases({ _commit }, {
|
||||
id,
|
||||
filter,
|
||||
after,
|
||||
before,
|
||||
}) {
|
||||
const afterString = dayjs(after).format('YYYY-MM-DD');
|
||||
const beforeString = dayjs(before).format('YYYY-MM-DD');
|
||||
|
||||
const releases = await get(`/releases/${id || ''}`, {
|
||||
filter,
|
||||
after: afterString,
|
||||
before: beforeString,
|
||||
});
|
||||
|
||||
return releases;
|
||||
}
|
||||
|
|
|
@ -42,7 +42,8 @@
|
|||
/* $primary: #ff886c; */
|
||||
.filter-bar[data-v-a678373a] {
|
||||
background: #fff;
|
||||
display: block;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: .5rem 1rem;
|
||||
font-size: 0;
|
||||
box-shadow: 0 0 3px rgba(0, 0, 0, 0.5);
|
||||
|
@ -59,6 +60,26 @@
|
|||
display: none;
|
||||
margin: 0 0 0 .5rem;
|
||||
}
|
||||
.range-button[data-v-a678373a] {
|
||||
color: rgba(0, 0, 0, 0.5);
|
||||
background: #fff;
|
||||
display: inline-block;
|
||||
padding: .5rem 1rem;
|
||||
border: none;
|
||||
box-shadow: 0 0 2px rgba(0, 0, 0, 0.2);
|
||||
font-size: .8rem;
|
||||
font-weight: bold;
|
||||
}
|
||||
.range-button[data-v-a678373a]:hover {
|
||||
color: #222;
|
||||
cursor: pointer;
|
||||
}
|
||||
.range-input[data-v-a678373a] {
|
||||
display: none;
|
||||
}
|
||||
.range-input:checked + .range-button[data-v-a678373a] {
|
||||
color: #ff6c88;
|
||||
}
|
||||
@media (max-width: 720px) {
|
||||
.filters-container[data-v-a678373a] {
|
||||
display: none;
|
||||
|
@ -271,6 +292,7 @@
|
|||
margin: 0 .25rem 0 0;
|
||||
}
|
||||
.tidbit.date[data-v-2bc41e74], .tidbit.duration[data-v-2bc41e74], .tidbit.shoot[data-v-2bc41e74] {
|
||||
flex-shrink: 0;
|
||||
padding: 1.25rem 1rem 1.25rem 0;
|
||||
margin: 0 1rem 0 0;
|
||||
}
|
||||
|
@ -290,12 +312,16 @@
|
|||
max-width: 15rem;
|
||||
-o-object-fit: contain;
|
||||
object-fit: contain;
|
||||
-o-object-position: 100% 50%;
|
||||
object-position: 100% 50%;
|
||||
}
|
||||
.logo-network[data-v-2bc41e74] {
|
||||
height: 1.5rem;
|
||||
max-width: 10rem;
|
||||
-o-object-fit: contain;
|
||||
object-fit: contain;
|
||||
-o-object-position: 100% 50%;
|
||||
object-position: 100% 50%;
|
||||
}
|
||||
.chain[data-v-2bc41e74] {
|
||||
color: rgba(0, 0, 0, 0.5);
|
||||
|
@ -355,7 +381,8 @@
|
|||
display: block;
|
||||
}
|
||||
.logo-site[data-v-2bc41e74] {
|
||||
max-width: 10rem;
|
||||
width: 15rem;
|
||||
max-width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -686,7 +713,7 @@ body {
|
|||
|
||||
@media (max-width: 720px) {
|
||||
.scenes {
|
||||
grid-template-columns: repeat(auto-fit, minmax(22.5rem, 1fr)); } }
|
||||
grid-template-columns: repeat(auto-fit, minmax(20rem, 1fr)); } }
|
||||
|
||||
/* $primary: #ff886c; */
|
||||
.header[data-v-10b7ec04] {
|
||||
|
|
|
@ -992,6 +992,7 @@ function getSites(networksMap) {
|
|||
name: 'Evil Angel',
|
||||
url: 'https://evilangel.com',
|
||||
description: 'Welcome to the award winning Evil Angel website, home to the most popular pornstars of today, yesterday and tomorrow in their most extreme and hardcore porn scenes to date. We feature almost 30 years of rough sex videos and hardcore anal porn like you\'ve never seen before, and have won countless AVN and XBiz awards including \'Best Site\' and \'Best Studio\'.',
|
||||
parameters: JSON.stringify({ independent: true }),
|
||||
network_id: networksMap['evilangel'],
|
||||
},
|
||||
// JULES JORDAN
|
||||
|
|
105
src/releases.js
105
src/releases.js
|
@ -1,6 +1,7 @@
|
|||
'use strict';
|
||||
|
||||
const knex = require('./knex');
|
||||
const whereOr = require('./utils/where-or');
|
||||
|
||||
async function curateRelease(release) {
|
||||
const [actors, tags, media] = await Promise.all([
|
||||
|
@ -70,10 +71,13 @@ function curateReleases(releases) {
|
|||
return Promise.all(releases.map(async release => curateRelease(release)));
|
||||
}
|
||||
|
||||
async function fetchReleases(releaseId, filter = []) {
|
||||
// const straightFilter = filter.includes('straight') ? ['gay', 'lesbian'] : [];
|
||||
|
||||
const releases = await knex('releases')
|
||||
function commonQuery(queryBuilder, {
|
||||
filter = [],
|
||||
after = new Date(0), // January 1970
|
||||
before = new Date(2 ** 44), // May 2109
|
||||
limit = 100,
|
||||
}) {
|
||||
queryBuilder
|
||||
.leftJoin('sites', 'releases.site_id', 'sites.id')
|
||||
.leftJoin('studios', 'releases.studio_id', 'studios.id')
|
||||
.leftJoin('networks', 'sites.network_id', 'networks.id')
|
||||
|
@ -84,7 +88,7 @@ async function fetchReleases(releaseId, filter = []) {
|
|||
'networks.name as network_name', 'networks.slug as network_slug', 'networks.url as network_url', 'networks.description as network_description',
|
||||
)
|
||||
.whereNotExists((builder) => {
|
||||
// apply filters
|
||||
// apply tag filters
|
||||
builder
|
||||
.select('*')
|
||||
.from('tags_associated')
|
||||
|
@ -92,91 +96,58 @@ async function fetchReleases(releaseId, filter = []) {
|
|||
.whereIn('tags.slug', filter)
|
||||
.andWhereRaw('tags_associated.release_id = releases.id');
|
||||
})
|
||||
.andWhere(releaseId ? { 'releases.id': releaseId } : {})
|
||||
.andWhere('date', '>', after)
|
||||
.andWhere('date', '<=', before)
|
||||
.orderBy([{ column: 'date', order: 'desc' }, { column: 'created_at', order: 'desc' }])
|
||||
.limit(100);
|
||||
|
||||
return curateReleases(releases);
|
||||
.limit(limit);
|
||||
}
|
||||
|
||||
async function fetchSiteReleases(siteId, siteSlug) {
|
||||
async function fetchReleases(queryObject = {}, options = {}) {
|
||||
const releases = await knex('releases')
|
||||
.where({ 'sites.id': siteId })
|
||||
.orWhere({ 'sites.slug': siteSlug })
|
||||
.select(
|
||||
'releases.*',
|
||||
'sites.name as site_name', 'sites.slug as site_slug', 'sites.url as site_url', 'sites.network_id', 'sites.parameters as site_parameters',
|
||||
'studios.name as studio_name', 'sites.slug as site_slug', 'studios.url as studio_url',
|
||||
'networks.name as network_name', 'networks.slug as network_slug', 'networks.url as network_url',
|
||||
)
|
||||
.leftJoin('sites', 'releases.site_id', 'sites.id')
|
||||
.leftJoin('studios', 'releases.studio_id', 'studios.id')
|
||||
.leftJoin('networks', 'sites.network_id', 'networks.id')
|
||||
.orderBy([{ column: 'date', order: 'desc' }, { column: 'created_at', order: 'desc' }])
|
||||
.limit(100);
|
||||
.modify(commonQuery, options)
|
||||
.andWhere(builder => whereOr(queryObject, 'releases', builder));
|
||||
|
||||
return curateReleases(releases);
|
||||
}
|
||||
|
||||
async function fetchNetworkReleases(networkId, networkSlug) {
|
||||
async function fetchSiteReleases(queryObject, options = {}) {
|
||||
const releases = await knex('releases')
|
||||
.where({ 'networks.id': networkId })
|
||||
.orWhere({ 'networks.slug': networkSlug })
|
||||
.select(
|
||||
'releases.*',
|
||||
'sites.name as site_name', 'sites.slug as site_slug', 'sites.url as site_url', 'sites.network_id', 'sites.parameters as site_parameters',
|
||||
'studios.name as studio_name', 'sites.slug as site_slug', 'studios.url as studio_url',
|
||||
'networks.name as network_name', 'networks.slug as network_slug', 'networks.url as network_url',
|
||||
)
|
||||
.leftJoin('sites', 'releases.site_id', 'sites.id')
|
||||
.leftJoin('studios', 'releases.studio_id', 'studios.id')
|
||||
.leftJoin('networks', 'sites.network_id', 'networks.id')
|
||||
.orderBy([{ column: 'date', order: 'desc' }, { column: 'created_at', order: 'desc' }])
|
||||
.limit(100);
|
||||
.modify(commonQuery, options)
|
||||
.where(builder => whereOr(queryObject, 'sites', builder));
|
||||
|
||||
return curateReleases(releases);
|
||||
}
|
||||
|
||||
async function fetchActorReleases(actorId, actorSlug) {
|
||||
async function fetchNetworkReleases(queryObject, options = {}) {
|
||||
const releases = await knex('releases')
|
||||
.modify(commonQuery, options)
|
||||
.where(builder => whereOr(queryObject, 'networks', builder));
|
||||
|
||||
return curateReleases(releases);
|
||||
}
|
||||
|
||||
async function fetchActorReleases(queryObject, options = {}) {
|
||||
const releases = await knex('actors_associated')
|
||||
.where({ 'actors.id': actorId })
|
||||
.orWhere({ 'actors.slug': actorSlug })
|
||||
.select(
|
||||
'releases.*',
|
||||
'actors.name as actor_name',
|
||||
'sites.name as site_name', 'sites.slug as site_slug', 'sites.url as site_url', 'sites.network_id', 'sites.parameters as site_parameters',
|
||||
'studios.name as studio_name', 'sites.slug as site_slug', 'studios.url as studio_url',
|
||||
'networks.name as network_name', 'networks.slug as network_slug', 'networks.url as network_url',
|
||||
)
|
||||
.leftJoin('releases', 'actors_associated.release_id', 'releases.id')
|
||||
.leftJoin('actors', 'actors_associated.actor_id', 'actors.id')
|
||||
.leftJoin('sites', 'releases.site_id', 'sites.id')
|
||||
.leftJoin('studios', 'releases.studio_id', 'studios.id')
|
||||
.leftJoin('networks', 'sites.network_id', 'networks.id')
|
||||
.orderBy([{ column: 'releases.date', order: 'desc' }, { column: 'releases.created_at', order: 'desc' }])
|
||||
.limit(100);
|
||||
.select(
|
||||
'actors.name as actor_name',
|
||||
)
|
||||
.modify(commonQuery, options)
|
||||
.where(builder => whereOr(queryObject, 'actors', builder));
|
||||
|
||||
return curateReleases(releases);
|
||||
}
|
||||
|
||||
async function fetchTagReleases(tagId, tagSlug) {
|
||||
async function fetchTagReleases(queryObject, options = {}) {
|
||||
const releases = await knex('tags_associated')
|
||||
.where({ 'tags.id': tagId })
|
||||
.orWhere({ 'tags.slug': tagSlug })
|
||||
.select(
|
||||
'releases.*',
|
||||
'tags.name as tag_name',
|
||||
'sites.name as site_name', 'sites.slug as site_slug', 'sites.url as site_url', 'sites.network_id',
|
||||
'studios.name as studio_name', 'sites.slug as site_slug', 'studios.url as studio_url',
|
||||
'networks.name as network_name', 'networks.slug as network_slug', 'networks.url as network_url',
|
||||
)
|
||||
.leftJoin('releases', 'tags_associated.release_id', 'releases.id')
|
||||
.leftJoin('tags', 'tags_associated.tag_id', 'tags.id')
|
||||
.leftJoin('sites', 'releases.site_id', 'sites.id')
|
||||
.leftJoin('studios', 'releases.studio_id', 'studios.id')
|
||||
.leftJoin('networks', 'sites.network_id', 'networks.id')
|
||||
.orderBy([{ column: 'releases.date', order: 'desc' }, { column: 'releases.created_at', order: 'desc' }])
|
||||
.limit(100);
|
||||
.select(
|
||||
'tags.name as tag_name',
|
||||
)
|
||||
.modify(commonQuery, options)
|
||||
.where(builder => whereOr(queryObject, 'tags', builder));
|
||||
|
||||
return curateReleases(releases);
|
||||
}
|
||||
|
|
|
@ -9,16 +9,33 @@ const {
|
|||
} = require('../releases');
|
||||
|
||||
async function fetchReleasesApi(req, res) {
|
||||
const releases = await fetchReleases(req.params.releaseId, req.query.filter ? [].concat(req.query.filter) : []);
|
||||
const filter = req.query.filter ? [].concat(req.query.filter) : []; // don't filter for 'undefined'
|
||||
|
||||
const releases = await fetchReleases({}, {
|
||||
filter,
|
||||
after: req.query.after,
|
||||
before: req.query.before,
|
||||
});
|
||||
|
||||
res.send(releases);
|
||||
}
|
||||
|
||||
async function fetchReleaseByIdApi(req, res) {
|
||||
const [release] = await fetchReleases({
|
||||
id: req.params.releaseId,
|
||||
});
|
||||
|
||||
res.send(release);
|
||||
}
|
||||
|
||||
async function fetchActorReleasesApi(req, res) {
|
||||
const actorId = Number.isInteger(Number(req.params.actorId)) ? Number(req.params.actorId) : null;
|
||||
const actorSlug = typeof req.params.actorId === 'string' ? req.params.actorId : null;
|
||||
|
||||
const releases = await fetchActorReleases(actorId, actorSlug);
|
||||
const releases = await fetchActorReleases({
|
||||
id: actorId,
|
||||
slug: actorSlug,
|
||||
});
|
||||
|
||||
res.send(releases);
|
||||
}
|
||||
|
@ -27,7 +44,10 @@ async function fetchNetworkReleasesApi(req, res) {
|
|||
const networkId = typeof req.params.networkId === 'number' ? req.params.networkId : null;
|
||||
const networkSlug = typeof req.params.networkId === 'string' ? req.params.networkId : null;
|
||||
|
||||
const releases = await fetchNetworkReleases(networkId, networkSlug);
|
||||
const releases = await fetchNetworkReleases({
|
||||
id: networkId,
|
||||
slug: networkSlug,
|
||||
});
|
||||
|
||||
res.send(releases);
|
||||
}
|
||||
|
@ -36,7 +56,10 @@ async function fetchSiteReleasesApi(req, res) {
|
|||
const siteId = typeof req.params.siteId === 'number' ? req.params.siteId : null;
|
||||
const siteSlug = typeof req.params.siteId === 'string' ? req.params.siteId : null;
|
||||
|
||||
const releases = await fetchSiteReleases(siteId, siteSlug);
|
||||
const releases = await fetchSiteReleases({
|
||||
id: siteId,
|
||||
slug: siteSlug,
|
||||
});
|
||||
|
||||
res.send(releases);
|
||||
}
|
||||
|
@ -45,13 +68,17 @@ async function fetchTagReleasesApi(req, res) {
|
|||
const tagId = typeof req.params.tagId === 'number' ? req.params.tagId : null;
|
||||
const tagSlug = typeof req.params.tagId === 'string' ? req.params.tagId : null;
|
||||
|
||||
const releases = await fetchTagReleases(tagId, tagSlug);
|
||||
const releases = await fetchTagReleases({
|
||||
id: tagId,
|
||||
slug: tagSlug,
|
||||
});
|
||||
|
||||
res.send(releases);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
fetchReleases: fetchReleasesApi,
|
||||
fetchReleaseById: fetchReleaseByIdApi,
|
||||
fetchActorReleases: fetchActorReleasesApi,
|
||||
fetchNetworkReleases: fetchNetworkReleasesApi,
|
||||
fetchSiteReleases: fetchSiteReleasesApi,
|
||||
|
|
|
@ -8,6 +8,7 @@ const bodyParser = require('body-parser');
|
|||
|
||||
const {
|
||||
fetchReleases,
|
||||
fetchReleaseById,
|
||||
fetchActorReleases,
|
||||
fetchNetworkReleases,
|
||||
fetchSiteReleases,
|
||||
|
@ -37,7 +38,7 @@ function initServer() {
|
|||
router.use(bodyParser.json({ strict: false }));
|
||||
|
||||
router.get('/api/releases', fetchReleases);
|
||||
router.get('/api/releases/:releaseId', fetchReleases);
|
||||
router.get('/api/releases/:releaseId', fetchReleaseById);
|
||||
router.get('/api/releases/networks', fetchNetworksFromReleases);
|
||||
|
||||
router.get('/api/actors', fetchActors);
|
||||
|
|
Loading…
Reference in New Issue