Integrated channel filter, partially restored actor bio.
This commit is contained in:
parent
d242eb3b73
commit
63f2bdbe60
|
@ -0,0 +1,629 @@
|
||||||
|
<template>
|
||||||
|
<div
|
||||||
|
class="content-inner actor-inner"
|
||||||
|
@scroll="events.emit('scroll', $event)"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="profile"
|
||||||
|
:class="{ expanded, 'with-avatar': !!actor.avatar }"
|
||||||
|
>
|
||||||
|
<a
|
||||||
|
v-if="actor.avatar"
|
||||||
|
:href="getMediaPath(actor.avatar)"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
class="avatar-link"
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
:src="getMediaPath(actor.avatar, 'thumbnail')"
|
||||||
|
:title="actor.avatar.credit && `© ${actor.avatar.credit}`"
|
||||||
|
class="avatar"
|
||||||
|
>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<ul class="bio nolist">
|
||||||
|
<li
|
||||||
|
v-if="actor.dateOfBirth"
|
||||||
|
class="bio-item"
|
||||||
|
>
|
||||||
|
<dfn class="bio-label"><Icon icon="cake" />Date of birth</dfn>
|
||||||
|
|
||||||
|
<span class="birthdate">{{ formatDate(actor.dateOfBirth, 'MMMM d, yyyy') }}<span
|
||||||
|
v-if="!actor.dateOfDeath"
|
||||||
|
class="age"
|
||||||
|
>{{ actor.ageFromBirth }}</span></span>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li
|
||||||
|
v-else-if="actor.age && !actor.dateOfDeath"
|
||||||
|
class="bio-item"
|
||||||
|
>
|
||||||
|
<dfn class="bio-label"><Icon icon="cake" />Age</dfn>
|
||||||
|
|
||||||
|
<span
|
||||||
|
:title="'Exact date of birth or age unknown'"
|
||||||
|
class="birthdate"
|
||||||
|
>> {{ actor.age }}</span>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li
|
||||||
|
v-if="actor.dateOfDeath"
|
||||||
|
class="bio-item"
|
||||||
|
>
|
||||||
|
<dfn class="bio-label"><Icon icon="tombstone" />Date of death</dfn>
|
||||||
|
|
||||||
|
<span class="birthdate">{{ formatDate(actor.dateOfDeath, 'MMMM d, yyyy') }}<span
|
||||||
|
v-if="actor.ageAtDeath"
|
||||||
|
class="age"
|
||||||
|
>{{ actor.ageAtDeath }}</span></span>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li
|
||||||
|
v-if="actor.orientation"
|
||||||
|
class="bio-item"
|
||||||
|
>
|
||||||
|
<dfn class="bio-label"><Icon icon="heart7" />Orientation</dfn>
|
||||||
|
|
||||||
|
<span class="orientation">{{ actor.orientation }}</span>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li
|
||||||
|
v-if="actor.origin"
|
||||||
|
class="bio-item birth"
|
||||||
|
>
|
||||||
|
<dfn class="bio-label"><Icon icon="home2" />Born in</dfn>
|
||||||
|
|
||||||
|
<span>
|
||||||
|
<span
|
||||||
|
v-if="actor.origin.city"
|
||||||
|
class="city"
|
||||||
|
>{{ actor.origin.city }}</span><span
|
||||||
|
v-if="actor.origin.state && (!actor.origin.city || (actor.origin.country && actor.origin.country.alpha2 === 'US'))"
|
||||||
|
class="state"
|
||||||
|
>{{ actor.origin.city ? `, ${actor.origin.state}` : actor.origin.state }}</span>
|
||||||
|
|
||||||
|
<span
|
||||||
|
v-if="actor.origin.country"
|
||||||
|
class="country birthcountry"
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
class="flag"
|
||||||
|
:src="`/img/flags/${actor.origin.country.alpha2.toLowerCase()}.svg`"
|
||||||
|
>{{ actor.origin.country.alias || actor.origin.country.name }}
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li
|
||||||
|
v-if="actor.residence"
|
||||||
|
class="bio-item residence hideable"
|
||||||
|
>
|
||||||
|
<dfn class="bio-label"><Icon icon="location" />Lives in</dfn>
|
||||||
|
|
||||||
|
<span>
|
||||||
|
<span
|
||||||
|
v-if="actor.residence.city"
|
||||||
|
class="city"
|
||||||
|
>{{ actor.residence.city }}</span><span
|
||||||
|
v-if="actor.residence.state && actor.residence.country && actor.residence.country.alpha2 === 'US'"
|
||||||
|
class="state"
|
||||||
|
>{{ actor.residence.city ? `, ${actor.residence.state}` : actor.residence.state }}</span>
|
||||||
|
|
||||||
|
<span
|
||||||
|
v-if="actor.residence.country"
|
||||||
|
class="country"
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
class="flag"
|
||||||
|
:src="`/img/flags/${actor.residence.country.alpha2.toLowerCase()}.svg`"
|
||||||
|
>{{ actor.residence.country.alias || actor.residence.country.name }}
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li
|
||||||
|
v-if="actor.ethnicity"
|
||||||
|
class="bio-item ethnicity hideable"
|
||||||
|
>
|
||||||
|
<dfn class="bio-label"><Icon icon="earth2" />Ethnicity</dfn>
|
||||||
|
<span>{{ actor.ethnicity }}</span>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li
|
||||||
|
v-if="actor.bust || actor.waist || actor.hip"
|
||||||
|
title="bust-waist-hip"
|
||||||
|
class="bio-item figure"
|
||||||
|
>
|
||||||
|
<dfn class="bio-label"><Icon icon="ruler" />Figure</dfn>
|
||||||
|
<span class="bio-value">
|
||||||
|
<Icon
|
||||||
|
v-if="actor.naturalBoobs === false"
|
||||||
|
:title="'Enhanced boobs'"
|
||||||
|
icon="magic-wand2"
|
||||||
|
class="enhanced"
|
||||||
|
/>{{ actor.bust || '??' }}{{ actor.cup || '?' }}-{{ actor.waist || '??' }}-{{ actor.hip || '??' }}
|
||||||
|
</span>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li
|
||||||
|
v-if="actor.penisLength || actor.penisGirth || actor.circumcised"
|
||||||
|
class="bio-item penis"
|
||||||
|
>
|
||||||
|
<dfn class="bio-label"><Icon icon="pencil-ruler" />Dick</dfn>
|
||||||
|
|
||||||
|
<span>
|
||||||
|
<Icon
|
||||||
|
v-if="actor.circumcised"
|
||||||
|
:title="'Circumcised'"
|
||||||
|
icon="page-break"
|
||||||
|
class="circumcised"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<template v-if="actor.penisLengthMetric && actor.penisGirthMetric">
|
||||||
|
<span>{{ actor.penisLengthMetric }} * {{ actor.penisGirthMetric }} cm</span>
|
||||||
|
<span class="bio-segment">{{ actor.penisLengthImperial }}" * {{ actor.penisGirthImperial }}"</span>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template v-else-if="actor.penisLengthMetric">
|
||||||
|
<span>{{ actor.penisLengthMetric }} cm</span>
|
||||||
|
<span class="bio-segment">{{ actor.penisLengthImperial }}"</span>
|
||||||
|
</template>
|
||||||
|
</span>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li
|
||||||
|
v-if="actor.height"
|
||||||
|
class="bio-item height"
|
||||||
|
>
|
||||||
|
<dfn class="bio-label"><Icon icon="height" />Height</dfn>
|
||||||
|
<span>
|
||||||
|
<span class="height-metric">{{ actor.height.metric }} cm</span>
|
||||||
|
<span class="height-imperial">{{ actor.height.imperial[0] }}' {{ actor.height.imperial[1] }}"</span>
|
||||||
|
</span>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li
|
||||||
|
v-if="actor.weight"
|
||||||
|
class="bio-item weight hideable"
|
||||||
|
>
|
||||||
|
<dfn class="bio-label"><Icon icon="scale" />Weight</dfn>
|
||||||
|
|
||||||
|
<span>
|
||||||
|
<span class="weight-metric">{{ actor.weight.metric }} kg</span>
|
||||||
|
<span class="weight-imperial">{{ actor.weight.imperial }} lbs</span>
|
||||||
|
</span>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li
|
||||||
|
v-if="actor.eyes"
|
||||||
|
class="bio-item eyes hideable"
|
||||||
|
>
|
||||||
|
<dfn class="bio-label"><Icon icon="eye" />Eyes</dfn>
|
||||||
|
<span>{{ actor.eyes }}</span>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li
|
||||||
|
v-if="actor.hairColor"
|
||||||
|
class="bio-item hair hideable"
|
||||||
|
>
|
||||||
|
<dfn class="bio-label"><Icon icon="haircut" />Hair</dfn>
|
||||||
|
<span><span v-if="actor.hairLength">{{ actor.hairLength }}, </span>{{ actor.hairColor }}</span>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li
|
||||||
|
v-if="actor.hasTattoos"
|
||||||
|
class="bio-item tattoos hideable"
|
||||||
|
>
|
||||||
|
<dfn class="bio-label"><Icon icon="lotus" />Tattoos</dfn>
|
||||||
|
|
||||||
|
<span
|
||||||
|
v-if="actor.tattoos"
|
||||||
|
:title="actor.tattoos"
|
||||||
|
class="bio-value"
|
||||||
|
>{{ actor.tattoos }}</span>
|
||||||
|
<span v-else>Yes</span>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li
|
||||||
|
v-if="actor.hasPiercings"
|
||||||
|
class="bio-item piercings hideable"
|
||||||
|
>
|
||||||
|
<dfn class="bio-label"><Icon icon="trophy4" />Piercings</dfn>
|
||||||
|
|
||||||
|
<span
|
||||||
|
v-if="actor.piercings"
|
||||||
|
:title="actor.piercings"
|
||||||
|
class="bio-value"
|
||||||
|
>{{ actor.piercings }}</span>
|
||||||
|
<span v-else>Yes</span>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="bio-item scraped hideable">Updated {{ formatDate(actor.updatedAt, 'yyyy-MM-dd hh:mm') }}, ID: {{ actor.id }}</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<div class="descriptions-container">
|
||||||
|
<div
|
||||||
|
v-if="actor.descriptions && actor.descriptions.length > 0"
|
||||||
|
class="descriptions"
|
||||||
|
>
|
||||||
|
<p
|
||||||
|
v-for="description in actor.descriptions"
|
||||||
|
:key="`description-${description.entity.id}`"
|
||||||
|
class="description"
|
||||||
|
>
|
||||||
|
{{ description.text }}
|
||||||
|
<a :href="`/${description.entity.type}/${description.entity.slug}`">
|
||||||
|
<img
|
||||||
|
v-if="description.entity.type === 'network' || !description.entity.parent || description.entity.independent"
|
||||||
|
:src="`/img/logos/${description.entity.slug}/thumbs/network.png`"
|
||||||
|
class="description-logo"
|
||||||
|
>
|
||||||
|
|
||||||
|
<img
|
||||||
|
v-else
|
||||||
|
:src="`/img/logos/${description.entity.parent.slug}/thumbs/${description.entity.slug}.png`"
|
||||||
|
class="description-logo"
|
||||||
|
>
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref } from 'vue';
|
||||||
|
|
||||||
|
import { getMediaPath } from '#/utils/media-path.js';
|
||||||
|
import { formatDate } from '#/utils/format.js';
|
||||||
|
|
||||||
|
const expanded = ref(true);
|
||||||
|
|
||||||
|
defineProps({
|
||||||
|
actor: {
|
||||||
|
type: Object,
|
||||||
|
default: null,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.header-gender .icon {
|
||||||
|
width: 1.25rem;
|
||||||
|
height: 1.25rem;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.profile {
|
||||||
|
background: var(--grey-dark-40);
|
||||||
|
color: var(--highlight-strong-30);
|
||||||
|
width: 100%;
|
||||||
|
max-height: 18rem;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
flex-shrink: 0;
|
||||||
|
|
||||||
|
&.with-avatar {
|
||||||
|
height: 18rem; /* profile overlaps avatar in chrome */
|
||||||
|
}
|
||||||
|
|
||||||
|
.avatar-link {
|
||||||
|
padding: 0 0 1rem 1rem;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.avatar {
|
||||||
|
height: 100%;
|
||||||
|
flex-shrink: 0;
|
||||||
|
border: solid 3px var(--highlight-hint);
|
||||||
|
margin: 0 .5rem 0 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.bio {
|
||||||
|
flex-grow: 1;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
box-sizing: border-box;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bio-header {
|
||||||
|
width: calc(50% - 2rem);
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
padding: 0 .5rem .5rem 0;
|
||||||
|
margin: 0 0 0 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bio-item {
|
||||||
|
width: calc(50% - 4rem);
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
box-sizing: border-box;
|
||||||
|
padding: .25rem 0 ;
|
||||||
|
margin: 0 0 .25rem 1rem;
|
||||||
|
line-height: 1.75;
|
||||||
|
text-align: right;
|
||||||
|
font-size: .9rem;
|
||||||
|
font-weight: 600;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
&:not(:last-of-type) {
|
||||||
|
border-bottom: solid 1px var(--highlight-weak-40);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.bio-label,
|
||||||
|
.bio-value {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bio-label {
|
||||||
|
color: var(--highlight-strong-20);
|
||||||
|
margin: 0 1rem 0 0;
|
||||||
|
flex-shrink: 0;
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 400;
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
fill: var(--highlight);
|
||||||
|
margin: -.25rem .5rem 0 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.bio-value {
|
||||||
|
margin: 0 0 0 2rem;
|
||||||
|
white-space: nowrap;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
margin: -.25rem 0 0 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.flag {
|
||||||
|
height: 1rem;
|
||||||
|
margin: .25rem .25rem 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bio-name {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.birthdate {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.age {
|
||||||
|
font-weight: bold;
|
||||||
|
padding: 0 0 0 .5rem;
|
||||||
|
border-left: solid 1px var(--highlight-weak);
|
||||||
|
margin: 0 0 0 .5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.country {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
|
||||||
|
.figure .bio-label .icon {
|
||||||
|
margin: -.5rem .5rem 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.height-imperial,
|
||||||
|
.weight-imperial,
|
||||||
|
.penis-girth-imperial,
|
||||||
|
.penis-length-imperial,
|
||||||
|
.bio-segment {
|
||||||
|
padding: 0 0 0 .5rem;
|
||||||
|
border-left: solid 1px var(--highlight-weak);
|
||||||
|
margin: 0 0 0 .5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.enhanced.icon,
|
||||||
|
.circumcised.icon {
|
||||||
|
fill: var(--primary);
|
||||||
|
padding: 0 .5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.enhanced.icon {
|
||||||
|
transform: scaleX(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.ethnicity,
|
||||||
|
.hair,
|
||||||
|
.eyes,
|
||||||
|
.orientation {
|
||||||
|
text-transform: capitalize;
|
||||||
|
}
|
||||||
|
|
||||||
|
.alias:not(:last-child)::after {
|
||||||
|
content: ',\00a0';
|
||||||
|
}
|
||||||
|
|
||||||
|
.scraped {
|
||||||
|
color: var(--highlight-weak);
|
||||||
|
font-size: .8rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.descriptions-container {
|
||||||
|
max-width: 30rem;
|
||||||
|
max-height: 100%;
|
||||||
|
position: relative;
|
||||||
|
display: block;
|
||||||
|
flex-grow: 1;
|
||||||
|
box-sizing: border-box;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
content: '';
|
||||||
|
width: 100%;
|
||||||
|
height: 1.5rem;
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
background: linear-gradient(transparent, 25%, var(--profile) 75%);
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.descriptions {
|
||||||
|
height: 100%;
|
||||||
|
overflow: auto;
|
||||||
|
scrollbar-width: none;
|
||||||
|
|
||||||
|
&::-webkit-scrollbar {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.description {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0 1rem;
|
||||||
|
border-left: solid 3px var(--highlight-hint);
|
||||||
|
line-height: 1.5;
|
||||||
|
font-size: .9rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.description-logo {
|
||||||
|
display: block;
|
||||||
|
width: 12rem;
|
||||||
|
max-height: 1.5rem;
|
||||||
|
margin: .5rem 0 1.5rem 0;
|
||||||
|
object-fit: contain;
|
||||||
|
object-position: 0 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.actor-content {
|
||||||
|
display: flex;
|
||||||
|
flex-grow: 1;
|
||||||
|
flex-direction: column;
|
||||||
|
background: var(--background-soft);
|
||||||
|
}
|
||||||
|
|
||||||
|
.heading {
|
||||||
|
padding: 0;
|
||||||
|
margin: 0 0 1rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile-social {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.expand {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scroll {
|
||||||
|
background: var(--background-dim);
|
||||||
|
border-bottom: solid 1px var(--shadow-hint);
|
||||||
|
}
|
||||||
|
|
||||||
|
.stash.icon {
|
||||||
|
width: 1.5rem;
|
||||||
|
height: 1.5rem;
|
||||||
|
padding: 0 1rem;
|
||||||
|
fill: var(--highlight);
|
||||||
|
|
||||||
|
&.stashed {
|
||||||
|
fill: var(--primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
fill: var(--primary);
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
@media(max-width: $breakpoint4) {
|
||||||
|
.descriptions-container {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media(max-width: $breakpoint3) {
|
||||||
|
.profile .avatar-link {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.actor-content {
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media(max-width: $breakpoint) {
|
||||||
|
.profile {
|
||||||
|
height: auto;
|
||||||
|
max-height: none;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
&.with-avatar {
|
||||||
|
height: auto;
|
||||||
|
max-height: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:not(.expanded) .hideable {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.bio {
|
||||||
|
width: 100%;
|
||||||
|
height: auto;
|
||||||
|
padding: 0 1rem;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bio-item {
|
||||||
|
width: 100%;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.expanded .bio-value {
|
||||||
|
white-space: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.expand {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.actor-stash {
|
||||||
|
margin: 0 .5rem 0 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media(max-width: $breakpoint0) {
|
||||||
|
.header-social {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.expanded .profile-social {
|
||||||
|
display: block;
|
||||||
|
margin: 1rem 0 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-name {
|
||||||
|
flex-grow: 1;
|
||||||
|
font-size: 1.3rem;
|
||||||
|
padding: .5rem .5rem .5rem 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stash.icon {
|
||||||
|
width: 1.25rem;
|
||||||
|
height: 1.25rem;
|
||||||
|
padding: 0 1rem 0 .25rem;
|
||||||
|
transform: translate(0, -.1rem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
</style>
|
|
@ -32,13 +32,13 @@
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<span
|
<span
|
||||||
v-if="actor.birthCountry"
|
v-if="actor.origin.country"
|
||||||
:title="`Born in ${actor.birthCountry.name}`"
|
:title="`Born in ${actor.origin.country.name}`"
|
||||||
class="country"
|
class="country"
|
||||||
>
|
>
|
||||||
{{ actor.birthCountry.alpha2 }}
|
{{ actor.origin.country.alpha2 }}
|
||||||
<img
|
<img
|
||||||
:src="`/img/flags/${actor.birthCountry.alpha2.toLowerCase()}.svg`"
|
:src="`/img/flags/${actor.origin.country.alpha2.toLowerCase()}.svg`"
|
||||||
class="flag"
|
class="flag"
|
||||||
>
|
>
|
||||||
</span>
|
</span>
|
||||||
|
@ -47,7 +47,7 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { formatDate } from '#/src/format.js';
|
import { formatDate } from '#/utils/format.js';
|
||||||
|
|
||||||
import Gender from './gender.vue';
|
import Gender from './gender.vue';
|
||||||
|
|
||||||
|
|
|
@ -78,7 +78,7 @@
|
||||||
:title="actor.name"
|
:title="actor.name"
|
||||||
>{{ actor.name }}</span>
|
>{{ actor.name }}</span>
|
||||||
|
|
||||||
<span class="actor-details">
|
<span class="filter-details">
|
||||||
<div class="actor-gender">
|
<div class="actor-gender">
|
||||||
<Gender
|
<Gender
|
||||||
:gender="actor.gender"
|
:gender="actor.gender"
|
||||||
|
@ -180,12 +180,6 @@ function selectGender() {
|
||||||
align-items: stretch;
|
align-items: stretch;
|
||||||
}
|
}
|
||||||
|
|
||||||
.actor-details {
|
|
||||||
display: flex;
|
|
||||||
align-items: stretch;
|
|
||||||
margin-left: .5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.actor-gender {
|
.actor-gender {
|
||||||
width: 1rem;
|
width: 1rem;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
|
@ -13,41 +13,36 @@
|
||||||
class="filter-sort order noselect"
|
class="filter-sort order noselect"
|
||||||
@click="order = 'count'"
|
@click="order = 'count'"
|
||||||
>
|
>
|
||||||
<Icon
|
<Icon icon="sort-alpha-asc" />
|
||||||
icon="sort-alpha-asc"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
v-show="order === 'count'"
|
v-show="order === 'count'"
|
||||||
class="filter-sort order noselect"
|
class="filter-sort order noselect"
|
||||||
@click="order = 'priority'"
|
@click="order = 'name'"
|
||||||
>
|
>
|
||||||
<Icon
|
<Icon icon="sort-numeric-desc" />
|
||||||
icon="sort-numeric-desc"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<ul
|
<ul
|
||||||
class="filter-items nolist"
|
class="filter-items nolist"
|
||||||
>
|
>
|
||||||
<template v-for="network in networks">
|
|
||||||
<li
|
<li
|
||||||
v-for="(channel) in [network, ...(network.children || [])]"
|
v-for="entity in entities"
|
||||||
:key="`filter-channel-${channel.id}`"
|
:key="`filter-channel-${entity.id}`"
|
||||||
class="filter-item"
|
class="filter-item"
|
||||||
:class="{ channel: !channel.isIndependent && channel.type !== 'network', selected: filters.channel?.id === channel.id }"
|
:class="{ channel: !entity.isIndependent && entity.type !== 'network', selected: filters.entity?.id === entity.id }"
|
||||||
@click="emit('update', 'channel', channel)"
|
@click="emit('update', 'entity', entity)"
|
||||||
>
|
>
|
||||||
<span class="filter-name">
|
<span class="filter-name">
|
||||||
<span
|
<span
|
||||||
class="filter-text"
|
class="filter-text"
|
||||||
:title="channel.name"
|
:title="entity.name"
|
||||||
>
|
>
|
||||||
<img
|
<img
|
||||||
v-if="channel.isIndependent || channel.type === 'network'"
|
v-if="entity.isIndependent || entity.type === 'network'"
|
||||||
:src="`/logos/${channel.slug}/favicon_dark.png`"
|
:src="`/logos/${entity.slug}/favicon_dark.png`"
|
||||||
class="favicon"
|
class="favicon"
|
||||||
>
|
>
|
||||||
|
|
||||||
|
@ -56,18 +51,24 @@
|
||||||
icon="arrow-up4"
|
icon="arrow-up4"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{{ channel.name }}
|
{{ entity.name }}
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<span class="channel-details">
|
<span class="filter-details">
|
||||||
<span
|
<span
|
||||||
v-if="channel.count"
|
v-if="entity.count"
|
||||||
class="filter-count"
|
class="filter-count"
|
||||||
>{{ channel.count }}</span>
|
>{{ entity.count }}</span>
|
||||||
|
|
||||||
|
<Icon
|
||||||
|
v-if="filters.entity?.id === entity.id"
|
||||||
|
icon="cross2"
|
||||||
|
class="filter-remove"
|
||||||
|
@click.native.stop="emit('update', 'entity', null)"
|
||||||
|
/>
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
</li>
|
</li>
|
||||||
</template>
|
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -95,7 +96,15 @@ const order = ref('name');
|
||||||
const { pageProps } = inject('pageContext');
|
const { pageProps } = inject('pageContext');
|
||||||
const { channel: pageChannel } = pageProps;
|
const { channel: pageChannel } = pageProps;
|
||||||
|
|
||||||
const networks = computed(() => {
|
function sort(channelA, channelB) {
|
||||||
|
if (order.value === 'count') {
|
||||||
|
return channelB.count - channelA.count;
|
||||||
|
}
|
||||||
|
|
||||||
|
return channelA.name.localeCompare(channelB.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
const entities = computed(() => {
|
||||||
const filteredChannels = props.channels.filter((channel) => channel.id !== pageChannel?.id
|
const filteredChannels = props.channels.filter((channel) => channel.id !== pageChannel?.id
|
||||||
&& (searchRegexp.value.test(channel.name)
|
&& (searchRegexp.value.test(channel.name)
|
||||||
|| searchRegexp.value.test(channel.slug)
|
|| searchRegexp.value.test(channel.slug)
|
||||||
|
@ -119,7 +128,14 @@ const networks = computed(() => {
|
||||||
acc[channel.parent.id].children.push(channel);
|
acc[channel.parent.id].children.push(channel);
|
||||||
|
|
||||||
return acc;
|
return acc;
|
||||||
}, {}));
|
}, {}))
|
||||||
|
.map((network) => ({
|
||||||
|
...network,
|
||||||
|
children: network.children?.sort(sort),
|
||||||
|
count: network.count || network.children?.reduce((acc, channel) => acc + channel.count, 0),
|
||||||
|
}))
|
||||||
|
.sort(sort)
|
||||||
|
.flatMap((network) => [network, ...(network.children || [])]);
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -134,11 +150,12 @@ const networks = computed(() => {
|
||||||
}
|
}
|
||||||
|
|
||||||
.filter-item.channel {
|
.filter-item.channel {
|
||||||
.icon {
|
.filter-text .icon {
|
||||||
width: 1.5rem;
|
width: 1.5rem;
|
||||||
height: 1rem;
|
height: 1rem;
|
||||||
transform: rotate(-135deg);
|
transform: rotate(-135deg);
|
||||||
fill: var(--shadow-weak-30);
|
fill: var(--shadow-weak-30);
|
||||||
|
overflow: hidden; /* prevent parent jumping on load */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
<Icon
|
<Icon
|
||||||
v-if="selectedCountry === country.alpha2"
|
v-if="selectedCountry === country.alpha2"
|
||||||
icon="cross2"
|
icon="cross2"
|
||||||
|
class="filter-remove"
|
||||||
@click.native.stop="emit('country', null)"
|
@click.native.stop="emit('country', null)"
|
||||||
/>
|
/>
|
||||||
</li>
|
</li>
|
||||||
|
@ -55,15 +56,6 @@ const emit = defineEmits(['country']);
|
||||||
padding: .25rem .25rem .25rem .5rem;
|
padding: .25rem .25rem .25rem .5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.icon {
|
|
||||||
padding: .25rem .6rem;
|
|
||||||
fill: var(--shadow);
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
fill: var(--shadow-strong-10);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background: var(--shadow-weak-30);
|
background: var(--shadow-weak-30);
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
|
@ -250,6 +250,21 @@ function toggleFilters(state) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.filter-details {
|
||||||
|
display: flex;
|
||||||
|
align-items: stretch;
|
||||||
|
margin-left: .5rem;
|
||||||
|
|
||||||
|
.filter-remove.icon {
|
||||||
|
padding: .25rem .6rem;
|
||||||
|
fill: var(--shadow);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
fill: var(--alert);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.filter-count {
|
.filter-count {
|
||||||
width: 1.5rem;
|
width: 1.5rem;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
|
@ -0,0 +1,90 @@
|
||||||
|
<template>
|
||||||
|
<div class="load-container">
|
||||||
|
<div class="load-ellipsis">
|
||||||
|
<div />
|
||||||
|
<div />
|
||||||
|
<div />
|
||||||
|
<div />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.load-container {
|
||||||
|
display: inline-flex;
|
||||||
|
position: relative;
|
||||||
|
padding: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.load-ellipsis {
|
||||||
|
display: inline-block;
|
||||||
|
position: relative;
|
||||||
|
width: 5rem;
|
||||||
|
height: .75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.load-ellipsis div {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
width: .75rem;
|
||||||
|
height: .75rem;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: var(--primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.load-ellipsis div:nth-child(1) {
|
||||||
|
left: .5rem;
|
||||||
|
animation: load-ellipsis1 0.5s infinite linear;
|
||||||
|
}
|
||||||
|
|
||||||
|
.load-ellipsis div:nth-child(2) {
|
||||||
|
left: .5rem;
|
||||||
|
animation: load-ellipsis2 0.5s infinite linear;
|
||||||
|
}
|
||||||
|
|
||||||
|
.load-ellipsis div:nth-child(3) {
|
||||||
|
left: 2rem;
|
||||||
|
animation: load-ellipsis3 0.5s infinite linear;
|
||||||
|
}
|
||||||
|
|
||||||
|
.load-ellipsis div:nth-child(4) {
|
||||||
|
left: 3.5rem;
|
||||||
|
animation: load-ellipsis4 0.5s infinite linear;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes load-ellipsis1 {
|
||||||
|
0% {
|
||||||
|
transform: scale(0);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: scale(0.5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes load-ellipsis2 {
|
||||||
|
0% {
|
||||||
|
transform: translate(0, 0) scale(0.5);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: translate(1.5rem, 0) scale(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes load-ellipsis3 {
|
||||||
|
0% {
|
||||||
|
transform: translate(0, 0) scale(1);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: translate(1.5rem, 0) scale(0.5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes load-ellipsis4 {
|
||||||
|
0% {
|
||||||
|
transform: scale(0.5);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: scale(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -1,6 +1,11 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="page">
|
<div
|
||||||
<Filters v-if="showFilters">
|
class="page"
|
||||||
|
>
|
||||||
|
<Filters
|
||||||
|
v-if="showFilters"
|
||||||
|
:class="{ loading }"
|
||||||
|
>
|
||||||
<TagsFilter
|
<TagsFilter
|
||||||
:filters="filters"
|
:filters="filters"
|
||||||
:tags="aggTags"
|
:tags="aggTags"
|
||||||
|
@ -20,7 +25,10 @@
|
||||||
/>
|
/>
|
||||||
</Filters>
|
</Filters>
|
||||||
|
|
||||||
<div class="scenes-container">
|
<div
|
||||||
|
class="scenes-container"
|
||||||
|
:class="{ loading }"
|
||||||
|
>
|
||||||
<div
|
<div
|
||||||
v-if="showMeta"
|
v-if="showMeta"
|
||||||
class="scenes-header"
|
class="scenes-header"
|
||||||
|
@ -48,7 +56,9 @@
|
||||||
>New</Link>
|
>New</Link>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<ul class="scenes nolist">
|
<ul
|
||||||
|
class="scenes nolist"
|
||||||
|
>
|
||||||
<li
|
<li
|
||||||
v-for="scene in scenes"
|
v-for="scene in scenes"
|
||||||
:key="scene.id"
|
:key="scene.id"
|
||||||
|
@ -59,6 +69,11 @@
|
||||||
|
|
||||||
<Pagination />
|
<Pagination />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<Ellipsis
|
||||||
|
class="ellipsis"
|
||||||
|
:class="{ loading }"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -75,8 +90,9 @@ import Filters from '#/components/filters/filters.vue';
|
||||||
import ActorsFilter from '#/components/filters/actors.vue';
|
import ActorsFilter from '#/components/filters/actors.vue';
|
||||||
import TagsFilter from '#/components/filters/tags.vue';
|
import TagsFilter from '#/components/filters/tags.vue';
|
||||||
import ChannelsFilter from '#/components/filters/channels.vue';
|
import ChannelsFilter from '#/components/filters/channels.vue';
|
||||||
import Scene from './tile.vue';
|
import Scene from '#/components/scenes/tile.vue';
|
||||||
import Pagination from '../pagination/pagination.vue';
|
import Pagination from '#/components/pagination/pagination.vue';
|
||||||
|
import Ellipsis from '#/components/loading/ellipsis.vue';
|
||||||
|
|
||||||
defineProps({
|
defineProps({
|
||||||
showFilters: {
|
showFilters: {
|
||||||
|
@ -99,12 +115,13 @@ const {
|
||||||
} = pageProps;
|
} = pageProps;
|
||||||
|
|
||||||
const scenes = ref(pageProps.scenes);
|
const scenes = ref(pageProps.scenes);
|
||||||
const aggActors = ref(pageProps.aggActors);
|
const aggActors = ref(pageProps.aggActors || []);
|
||||||
const aggTags = ref(pageProps.aggTags);
|
const aggTags = ref(pageProps.aggTags || []);
|
||||||
const aggChannels = ref(pageProps.aggChannels);
|
const aggChannels = ref(pageProps.aggChannels || []);
|
||||||
|
|
||||||
const currentPage = ref(Number(routeParams.page));
|
const currentPage = ref(Number(routeParams.page));
|
||||||
const total = ref(Number(pageProps.total));
|
const total = ref(Number(pageProps.total));
|
||||||
|
const loading = ref(false);
|
||||||
|
|
||||||
const actorIds = urlParsed.search.actors?.split(',').map((identifier) => parseActorIdentifier(identifier)?.id).filter(Boolean) || [];
|
const actorIds = urlParsed.search.actors?.split(',').map((identifier) => parseActorIdentifier(identifier)?.id).filter(Boolean) || [];
|
||||||
const queryActors = actorIds.map((urlActorId) => aggActors.value.find((aggActor) => aggActor.id === urlActorId)).filter(Boolean);
|
const queryActors = actorIds.map((urlActorId) => aggActors.value.find((aggActor) => aggActor.id === urlActorId)).filter(Boolean);
|
||||||
|
@ -112,11 +129,11 @@ const queryActors = actorIds.map((urlActorId) => aggActors.value.find((aggActor)
|
||||||
const networks = Object.fromEntries(aggChannels.value.map((channel) => (channel.type === 'network' ? channel : channel.parent)).filter(Boolean).map((parent) => [`_${parent.slug}`, parent]));
|
const networks = Object.fromEntries(aggChannels.value.map((channel) => (channel.type === 'network' ? channel : channel.parent)).filter(Boolean).map((parent) => [`_${parent.slug}`, parent]));
|
||||||
const channels = Object.fromEntries(aggChannels.value.filter((channel) => channel.type === 'channel').map((channel) => [channel.slug, channel]));
|
const channels = Object.fromEntries(aggChannels.value.filter((channel) => channel.type === 'channel').map((channel) => [channel.slug, channel]));
|
||||||
|
|
||||||
const queryChannel = networks[urlParsed.search.e] || channels[urlParsed.search.e];
|
const queryEntity = networks[urlParsed.search.e] || channels[urlParsed.search.e];
|
||||||
|
|
||||||
const filters = ref({
|
const filters = ref({
|
||||||
tags: urlParsed.search.tags?.split(',').filter(Boolean) || [],
|
tags: urlParsed.search.tags?.split(',').filter(Boolean) || [],
|
||||||
channel: queryChannel,
|
entity: queryEntity,
|
||||||
actors: queryActors,
|
actors: queryActors,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -149,14 +166,16 @@ async function search(resetPage = true) {
|
||||||
|
|
||||||
const query = {};
|
const query = {};
|
||||||
|
|
||||||
const entity = filters.value.channel || pageChannel;
|
const entity = filters.value.entity || pageChannel;
|
||||||
const entitySlug = entity?.type === 'network' ? `_${entity.slug}` : entity?.slug;
|
const entitySlug = entity?.type === 'network' ? `_${entity.slug}` : entity?.slug;
|
||||||
|
|
||||||
|
loading.value = true;
|
||||||
|
|
||||||
const res = await get('/scenes', {
|
const res = await get('/scenes', {
|
||||||
...query,
|
...query,
|
||||||
actors: [pageActor, ...filters.value.actors].filter(Boolean).map((filterActor) => getActorIdentifier(filterActor)).join(','), // if we're on an actor page, that actor ID needs to be included
|
actors: [pageActor, ...filters.value.actors].filter(Boolean).map((filterActor) => getActorIdentifier(filterActor)).join(','), // if we're on an actor page, that actor ID needs to be included
|
||||||
tags: [pageTag?.slug, ...filters.value.tags].filter(Boolean).join(','),
|
tags: [pageTag?.slug, ...filters.value.tags].filter(Boolean).join(','),
|
||||||
entity: entitySlug,
|
e: entitySlug,
|
||||||
scope,
|
scope,
|
||||||
page: currentPage.value, // client uses param rather than query pagination
|
page: currentPage.value, // client uses param rather than query pagination
|
||||||
});
|
});
|
||||||
|
@ -164,15 +183,17 @@ async function search(resetPage = true) {
|
||||||
scenes.value = res.scenes;
|
scenes.value = res.scenes;
|
||||||
aggActors.value = res.aggActors;
|
aggActors.value = res.aggActors;
|
||||||
aggTags.value = res.aggTags;
|
aggTags.value = res.aggTags;
|
||||||
|
aggChannels.value = res.aggChannels;
|
||||||
total.value = res.total;
|
total.value = res.total;
|
||||||
|
|
||||||
|
loading.value = false;
|
||||||
events.emit('scrollUp');
|
events.emit('scrollUp');
|
||||||
|
|
||||||
navigate(getPath(scope, false), {
|
navigate(getPath(scope, false), {
|
||||||
...query,
|
...query,
|
||||||
actors: filters.value.actors.map((filterActor) => getActorIdentifier(filterActor)).join(',') || undefined, // don't include page actor ID in query, already a parameter
|
actors: filters.value.actors.map((filterActor) => getActorIdentifier(filterActor)).join(',') || undefined, // don't include page actor ID in query, already a parameter
|
||||||
tags: filters.value.tags.join(',') || undefined,
|
tags: filters.value.tags.join(',') || undefined,
|
||||||
e: filters.value.channel?.type === 'network' ? `_${filters.value.channel.slug}` : (filters.value.channel?.slug || undefined),
|
e: filters.value.entity?.type === 'network' ? `_${filters.value.entity.slug}` : (filters.value.entity?.slug || undefined),
|
||||||
}, { redirect: false });
|
}, { redirect: false });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -189,12 +210,13 @@ function updateFilter(prop, value, reload = true) {
|
||||||
.page {
|
.page {
|
||||||
display: flex;
|
display: flex;
|
||||||
background: var(--background-base-10);
|
background: var(--background-base-10);
|
||||||
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
.scenes-header {
|
.scenes-header {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding: .5rem 0 .25rem 2rem;
|
padding: 1rem 0 .25rem 3rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.scenes-container {
|
.scenes-container {
|
||||||
|
@ -233,4 +255,20 @@ function updateFilter(prop, value, reload = true) {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.loading:not(.ellipsis) {
|
||||||
|
opacity: .3;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ellipsis {
|
||||||
|
display: none;
|
||||||
|
position: absolute;
|
||||||
|
top: 1rem;
|
||||||
|
left: 50%;
|
||||||
|
|
||||||
|
&.loading {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
"@vue/server-renderer": "^3.3.10",
|
"@vue/server-renderer": "^3.3.10",
|
||||||
"compression": "^1.7.4",
|
"compression": "^1.7.4",
|
||||||
"config": "^3.3.9",
|
"config": "^3.3.9",
|
||||||
|
"convert": "^4.14.1",
|
||||||
"cross-env": "^7.0.3",
|
"cross-env": "^7.0.3",
|
||||||
"date-fns": "^3.0.0",
|
"date-fns": "^3.0.0",
|
||||||
"error-stack-parser": "^2.1.4",
|
"error-stack-parser": "^2.1.4",
|
||||||
|
@ -23,6 +24,7 @@
|
||||||
"express-query-boolean": "^2.0.0",
|
"express-query-boolean": "^2.0.0",
|
||||||
"knex": "^3.1.0",
|
"knex": "^3.1.0",
|
||||||
"manticoresearch": "^4.0.0",
|
"manticoresearch": "^4.0.0",
|
||||||
|
"mathjs": "^12.2.1",
|
||||||
"mitt": "^3.0.1",
|
"mitt": "^3.0.1",
|
||||||
"nanoid": "^5.0.4",
|
"nanoid": "^5.0.4",
|
||||||
"path-to-regexp": "^6.2.1",
|
"path-to-regexp": "^6.2.1",
|
||||||
|
@ -1771,7 +1773,6 @@
|
||||||
"version": "7.23.6",
|
"version": "7.23.6",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.6.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.6.tgz",
|
||||||
"integrity": "sha512-zHd0eUrf5GZoOWVCXp6koAKQTfZV07eit6bGPmJgnZdnSAvvZee6zniW2XMF7Cmc4ISOOnPy3QaSiIJGJkVEDQ==",
|
"integrity": "sha512-zHd0eUrf5GZoOWVCXp6koAKQTfZV07eit6bGPmJgnZdnSAvvZee6zniW2XMF7Cmc4ISOOnPy3QaSiIJGJkVEDQ==",
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"regenerator-runtime": "^0.14.0"
|
"regenerator-runtime": "^0.14.0"
|
||||||
},
|
},
|
||||||
|
@ -3424,6 +3425,18 @@
|
||||||
"node": ">=14"
|
"node": ">=14"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/complex.js": {
|
||||||
|
"version": "2.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/complex.js/-/complex.js-2.1.1.tgz",
|
||||||
|
"integrity": "sha512-8njCHOTtFFLtegk6zQo0kkVX1rngygb/KQI6z1qZxlFI3scluC+LVTCFbrkWjBv4vvLlbQ9t88IPMC6k95VTTg==",
|
||||||
|
"engines": {
|
||||||
|
"node": "*"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "patreon",
|
||||||
|
"url": "https://www.patreon.com/infusion"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/component-emitter": {
|
"node_modules/component-emitter": {
|
||||||
"version": "1.3.1",
|
"version": "1.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.1.tgz",
|
||||||
|
@ -3521,6 +3534,11 @@
|
||||||
"node": ">= 0.6"
|
"node": ">= 0.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/convert": {
|
||||||
|
"version": "4.14.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/convert/-/convert-4.14.1.tgz",
|
||||||
|
"integrity": "sha512-haeYUERJCdvILEfZC2OHZd8JIIvU6Kl93zfDrDCG3dvws4icuWC2D5O7jyaKh8vjECdfkWkVB6qDycQpGhWWSA=="
|
||||||
|
},
|
||||||
"node_modules/convert-source-map": {
|
"node_modules/convert-source-map": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
|
||||||
|
@ -3622,6 +3640,11 @@
|
||||||
"ms": "2.0.0"
|
"ms": "2.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/decimal.js": {
|
||||||
|
"version": "10.4.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz",
|
||||||
|
"integrity": "sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA=="
|
||||||
|
},
|
||||||
"node_modules/deep-is": {
|
"node_modules/deep-is": {
|
||||||
"version": "0.1.4",
|
"version": "0.1.4",
|
||||||
"resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
|
"resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
|
||||||
|
@ -3875,6 +3898,11 @@
|
||||||
"resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
|
||||||
"integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow=="
|
"integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow=="
|
||||||
},
|
},
|
||||||
|
"node_modules/escape-latex": {
|
||||||
|
"version": "1.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/escape-latex/-/escape-latex-1.2.0.tgz",
|
||||||
|
"integrity": "sha512-nV5aVWW1K0wEiUIEdZ4erkGGH8mDxGyxSeqPzRNtWP7ataw+/olFObw7hujFWlVjNsaDFw5VZ5NzVSIqRgfTiw=="
|
||||||
|
},
|
||||||
"node_modules/escape-string-regexp": {
|
"node_modules/escape-string-regexp": {
|
||||||
"version": "1.0.5",
|
"version": "1.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
|
||||||
|
@ -4722,6 +4750,18 @@
|
||||||
"node": ">= 0.6"
|
"node": ">= 0.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/fraction.js": {
|
||||||
|
"version": "4.3.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.4.tgz",
|
||||||
|
"integrity": "sha512-pwiTgt0Q7t+GHZA4yaLjObx4vXmmdcS0iSJ19o8d/goUGgItX9UZWKWNnLHehxviD8wU2IWRsnR8cD5+yOJP2Q==",
|
||||||
|
"engines": {
|
||||||
|
"node": "*"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "patreon",
|
||||||
|
"url": "https://github.com/sponsors/rawify"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/fresh": {
|
"node_modules/fresh": {
|
||||||
"version": "0.5.2",
|
"version": "0.5.2",
|
||||||
"resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
|
"resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
|
||||||
|
@ -5386,6 +5426,11 @@
|
||||||
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
|
||||||
"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="
|
"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="
|
||||||
},
|
},
|
||||||
|
"node_modules/javascript-natural-sort": {
|
||||||
|
"version": "0.7.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/javascript-natural-sort/-/javascript-natural-sort-0.7.1.tgz",
|
||||||
|
"integrity": "sha512-nO6jcEfZWQXDhOiBtG2KvKyEptz7RVbpGP4vTD2hLBdmNQSsCiicO2Ioinv6UI4y9ukqnBpy+XZ9H6uLNgJTlw=="
|
||||||
|
},
|
||||||
"node_modules/js-tokens": {
|
"node_modules/js-tokens": {
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
|
||||||
|
@ -5651,6 +5696,28 @@
|
||||||
"superagent": "5.1.0"
|
"superagent": "5.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/mathjs": {
|
||||||
|
"version": "12.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/mathjs/-/mathjs-12.2.1.tgz",
|
||||||
|
"integrity": "sha512-/uG/yMP0wUSfALCyJkKco0gYlrp0kHFt4yNT3E+ZCoiWpsT9GdtLqydxHp3gjDCQrR4GGBDXMnKOQtJbmIe9SQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/runtime": "^7.23.6",
|
||||||
|
"complex.js": "^2.1.1",
|
||||||
|
"decimal.js": "^10.4.3",
|
||||||
|
"escape-latex": "^1.2.0",
|
||||||
|
"fraction.js": "4.3.4",
|
||||||
|
"javascript-natural-sort": "^0.7.1",
|
||||||
|
"seedrandom": "^3.0.5",
|
||||||
|
"tiny-emitter": "^2.1.0",
|
||||||
|
"typed-function": "^4.1.1"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"mathjs": "bin/cli.js"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 18"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/media-typer": {
|
"node_modules/media-typer": {
|
||||||
"version": "0.3.0",
|
"version": "0.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
|
||||||
|
@ -6497,8 +6564,7 @@
|
||||||
"node_modules/regenerator-runtime": {
|
"node_modules/regenerator-runtime": {
|
||||||
"version": "0.14.1",
|
"version": "0.14.1",
|
||||||
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz",
|
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz",
|
||||||
"integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==",
|
"integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw=="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"node_modules/regenerator-transform": {
|
"node_modules/regenerator-transform": {
|
||||||
"version": "0.15.2",
|
"version": "0.15.2",
|
||||||
|
@ -6699,6 +6765,11 @@
|
||||||
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
|
||||||
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
|
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
|
||||||
},
|
},
|
||||||
|
"node_modules/seedrandom": {
|
||||||
|
"version": "3.0.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/seedrandom/-/seedrandom-3.0.5.tgz",
|
||||||
|
"integrity": "sha512-8OwmbklUNzwezjGInmZ+2clQmExQPvomqjL7LFqOYqtmuxRgQYqOD3mHaU+MvZn5FLUeVxVfQjwLZW/n/JFuqg=="
|
||||||
|
},
|
||||||
"node_modules/semver": {
|
"node_modules/semver": {
|
||||||
"version": "6.3.1",
|
"version": "6.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
|
||||||
|
@ -7108,6 +7179,11 @@
|
||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/tiny-emitter": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz",
|
||||||
|
"integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q=="
|
||||||
|
},
|
||||||
"node_modules/to-fast-properties": {
|
"node_modules/to-fast-properties": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
|
||||||
|
@ -7279,6 +7355,14 @@
|
||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/typed-function": {
|
||||||
|
"version": "4.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/typed-function/-/typed-function-4.1.1.tgz",
|
||||||
|
"integrity": "sha512-Pq1DVubcvibmm8bYcMowjVnnMwPVMeh0DIdA8ad8NZY2sJgapANJmiigSUwlt+EgXxpfIv8MWrQXTIzkfYZLYQ==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 14"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/unbox-primitive": {
|
"node_modules/unbox-primitive": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz",
|
||||||
|
@ -9315,7 +9399,6 @@
|
||||||
"version": "7.23.6",
|
"version": "7.23.6",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.6.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.6.tgz",
|
||||||
"integrity": "sha512-zHd0eUrf5GZoOWVCXp6koAKQTfZV07eit6bGPmJgnZdnSAvvZee6zniW2XMF7Cmc4ISOOnPy3QaSiIJGJkVEDQ==",
|
"integrity": "sha512-zHd0eUrf5GZoOWVCXp6koAKQTfZV07eit6bGPmJgnZdnSAvvZee6zniW2XMF7Cmc4ISOOnPy3QaSiIJGJkVEDQ==",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"regenerator-runtime": "^0.14.0"
|
"regenerator-runtime": "^0.14.0"
|
||||||
}
|
}
|
||||||
|
@ -10399,6 +10482,11 @@
|
||||||
"resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz",
|
||||||
"integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug=="
|
"integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug=="
|
||||||
},
|
},
|
||||||
|
"complex.js": {
|
||||||
|
"version": "2.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/complex.js/-/complex.js-2.1.1.tgz",
|
||||||
|
"integrity": "sha512-8njCHOTtFFLtegk6zQo0kkVX1rngygb/KQI6z1qZxlFI3scluC+LVTCFbrkWjBv4vvLlbQ9t88IPMC6k95VTTg=="
|
||||||
|
},
|
||||||
"component-emitter": {
|
"component-emitter": {
|
||||||
"version": "1.3.1",
|
"version": "1.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.1.tgz",
|
||||||
|
@ -10466,6 +10554,11 @@
|
||||||
"resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz",
|
||||||
"integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA=="
|
"integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA=="
|
||||||
},
|
},
|
||||||
|
"convert": {
|
||||||
|
"version": "4.14.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/convert/-/convert-4.14.1.tgz",
|
||||||
|
"integrity": "sha512-haeYUERJCdvILEfZC2OHZd8JIIvU6Kl93zfDrDCG3dvws4icuWC2D5O7jyaKh8vjECdfkWkVB6qDycQpGhWWSA=="
|
||||||
|
},
|
||||||
"convert-source-map": {
|
"convert-source-map": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
|
||||||
|
@ -10538,6 +10631,11 @@
|
||||||
"ms": "2.0.0"
|
"ms": "2.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"decimal.js": {
|
||||||
|
"version": "10.4.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz",
|
||||||
|
"integrity": "sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA=="
|
||||||
|
},
|
||||||
"deep-is": {
|
"deep-is": {
|
||||||
"version": "0.1.4",
|
"version": "0.1.4",
|
||||||
"resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
|
"resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
|
||||||
|
@ -10741,6 +10839,11 @@
|
||||||
"resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
|
||||||
"integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow=="
|
"integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow=="
|
||||||
},
|
},
|
||||||
|
"escape-latex": {
|
||||||
|
"version": "1.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/escape-latex/-/escape-latex-1.2.0.tgz",
|
||||||
|
"integrity": "sha512-nV5aVWW1K0wEiUIEdZ4erkGGH8mDxGyxSeqPzRNtWP7ataw+/olFObw7hujFWlVjNsaDFw5VZ5NzVSIqRgfTiw=="
|
||||||
|
},
|
||||||
"escape-string-regexp": {
|
"escape-string-regexp": {
|
||||||
"version": "1.0.5",
|
"version": "1.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
|
||||||
|
@ -11389,6 +11492,11 @@
|
||||||
"resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
|
||||||
"integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow=="
|
"integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow=="
|
||||||
},
|
},
|
||||||
|
"fraction.js": {
|
||||||
|
"version": "4.3.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.4.tgz",
|
||||||
|
"integrity": "sha512-pwiTgt0Q7t+GHZA4yaLjObx4vXmmdcS0iSJ19o8d/goUGgItX9UZWKWNnLHehxviD8wU2IWRsnR8cD5+yOJP2Q=="
|
||||||
|
},
|
||||||
"fresh": {
|
"fresh": {
|
||||||
"version": "0.5.2",
|
"version": "0.5.2",
|
||||||
"resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
|
"resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
|
||||||
|
@ -11844,6 +11952,11 @@
|
||||||
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
|
||||||
"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="
|
"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="
|
||||||
},
|
},
|
||||||
|
"javascript-natural-sort": {
|
||||||
|
"version": "0.7.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/javascript-natural-sort/-/javascript-natural-sort-0.7.1.tgz",
|
||||||
|
"integrity": "sha512-nO6jcEfZWQXDhOiBtG2KvKyEptz7RVbpGP4vTD2hLBdmNQSsCiicO2Ioinv6UI4y9ukqnBpy+XZ9H6uLNgJTlw=="
|
||||||
|
},
|
||||||
"js-tokens": {
|
"js-tokens": {
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
|
||||||
|
@ -12042,6 +12155,22 @@
|
||||||
"superagent": "5.1.0"
|
"superagent": "5.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"mathjs": {
|
||||||
|
"version": "12.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/mathjs/-/mathjs-12.2.1.tgz",
|
||||||
|
"integrity": "sha512-/uG/yMP0wUSfALCyJkKco0gYlrp0kHFt4yNT3E+ZCoiWpsT9GdtLqydxHp3gjDCQrR4GGBDXMnKOQtJbmIe9SQ==",
|
||||||
|
"requires": {
|
||||||
|
"@babel/runtime": "^7.23.6",
|
||||||
|
"complex.js": "^2.1.1",
|
||||||
|
"decimal.js": "^10.4.3",
|
||||||
|
"escape-latex": "^1.2.0",
|
||||||
|
"fraction.js": "4.3.4",
|
||||||
|
"javascript-natural-sort": "^0.7.1",
|
||||||
|
"seedrandom": "^3.0.5",
|
||||||
|
"tiny-emitter": "^2.1.0",
|
||||||
|
"typed-function": "^4.1.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"media-typer": {
|
"media-typer": {
|
||||||
"version": "0.3.0",
|
"version": "0.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
|
||||||
|
@ -12613,8 +12742,7 @@
|
||||||
"regenerator-runtime": {
|
"regenerator-runtime": {
|
||||||
"version": "0.14.1",
|
"version": "0.14.1",
|
||||||
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz",
|
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz",
|
||||||
"integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==",
|
"integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw=="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"regenerator-transform": {
|
"regenerator-transform": {
|
||||||
"version": "0.15.2",
|
"version": "0.15.2",
|
||||||
|
@ -12750,6 +12878,11 @@
|
||||||
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
|
||||||
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
|
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
|
||||||
},
|
},
|
||||||
|
"seedrandom": {
|
||||||
|
"version": "3.0.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/seedrandom/-/seedrandom-3.0.5.tgz",
|
||||||
|
"integrity": "sha512-8OwmbklUNzwezjGInmZ+2clQmExQPvomqjL7LFqOYqtmuxRgQYqOD3mHaU+MvZn5FLUeVxVfQjwLZW/n/JFuqg=="
|
||||||
|
},
|
||||||
"semver": {
|
"semver": {
|
||||||
"version": "6.3.1",
|
"version": "6.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
|
||||||
|
@ -13049,6 +13182,11 @@
|
||||||
"resolved": "https://registry.npmjs.org/tildify/-/tildify-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/tildify/-/tildify-2.0.0.tgz",
|
||||||
"integrity": "sha512-Cc+OraorugtXNfs50hU9KS369rFXCfgGLpfCfvlc+Ud5u6VWmUQsOAa9HbTvheQdYnrdJqqv1e5oIqXppMYnSw=="
|
"integrity": "sha512-Cc+OraorugtXNfs50hU9KS369rFXCfgGLpfCfvlc+Ud5u6VWmUQsOAa9HbTvheQdYnrdJqqv1e5oIqXppMYnSw=="
|
||||||
},
|
},
|
||||||
|
"tiny-emitter": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz",
|
||||||
|
"integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q=="
|
||||||
|
},
|
||||||
"to-fast-properties": {
|
"to-fast-properties": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
|
||||||
|
@ -13174,6 +13312,11 @@
|
||||||
"is-typed-array": "^1.1.9"
|
"is-typed-array": "^1.1.9"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"typed-function": {
|
||||||
|
"version": "4.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/typed-function/-/typed-function-4.1.1.tgz",
|
||||||
|
"integrity": "sha512-Pq1DVubcvibmm8bYcMowjVnnMwPVMeh0DIdA8ad8NZY2sJgapANJmiigSUwlt+EgXxpfIv8MWrQXTIzkfYZLYQ=="
|
||||||
|
},
|
||||||
"unbox-primitive": {
|
"unbox-primitive": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz",
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
"@vue/server-renderer": "^3.3.10",
|
"@vue/server-renderer": "^3.3.10",
|
||||||
"compression": "^1.7.4",
|
"compression": "^1.7.4",
|
||||||
"config": "^3.3.9",
|
"config": "^3.3.9",
|
||||||
|
"convert": "^4.14.1",
|
||||||
"cross-env": "^7.0.3",
|
"cross-env": "^7.0.3",
|
||||||
"date-fns": "^3.0.0",
|
"date-fns": "^3.0.0",
|
||||||
"error-stack-parser": "^2.1.4",
|
"error-stack-parser": "^2.1.4",
|
||||||
|
@ -23,6 +24,7 @@
|
||||||
"express-query-boolean": "^2.0.0",
|
"express-query-boolean": "^2.0.0",
|
||||||
"knex": "^3.1.0",
|
"knex": "^3.1.0",
|
||||||
"manticoresearch": "^4.0.0",
|
"manticoresearch": "^4.0.0",
|
||||||
|
"mathjs": "^12.2.1",
|
||||||
"mitt": "^3.0.1",
|
"mitt": "^3.0.1",
|
||||||
"nanoid": "^5.0.4",
|
"nanoid": "^5.0.4",
|
||||||
"path-to-regexp": "^6.2.1",
|
"path-to-regexp": "^6.2.1",
|
||||||
|
|
|
@ -1,23 +1,59 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="page">
|
<div class="actor">
|
||||||
<div class="bio">
|
<div class="actor-header">
|
||||||
<img
|
<h2 class="header-name">
|
||||||
v-if="actor.avatar"
|
<span v-if="actor.entity">{{ actor.name }} ({{ actor.entity.name }})</span>
|
||||||
:src="actor.avatar.isS3 ? `https://cdndev.traxxx.me/${actor.avatar.thumbnail}` : `/media/${actor.avatar.thumbnail}`"
|
<span v-else>{{ actor.name }}</span>
|
||||||
:style="{ 'background-image': actor.avatar.isS3 ? `url(https://cdndev.traxxx.me/${actor.avatar.lazy})` : `url(/media/${actor.avatar.lazy})` }"
|
|
||||||
class="avatar"
|
|
||||||
>
|
|
||||||
|
|
||||||
<h2 class="name">{{ actor.name }}</h2>
|
<Gender
|
||||||
|
:gender="actor.gender"
|
||||||
|
class="header-gender"
|
||||||
|
/>
|
||||||
|
</h2>
|
||||||
|
|
||||||
|
<li
|
||||||
|
v-if="actor.aliases?.length"
|
||||||
|
class="bio-item"
|
||||||
|
>
|
||||||
|
<dfn class="bio-label">Also known as</dfn>
|
||||||
|
<span class="bio-value">
|
||||||
|
<span
|
||||||
|
v-for="alias in actor.aliases"
|
||||||
|
:key="`alias-${alias.id}`"
|
||||||
|
class="alias"
|
||||||
|
>{{ alias.name }}</span>
|
||||||
|
</span>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
<Social
|
||||||
|
v-if="actor.social && actor.social.length > 0"
|
||||||
|
:actor="actor"
|
||||||
|
class="header-social"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<StashButton
|
||||||
|
:stashed-by="stashedBy"
|
||||||
|
class="actor-stash light"
|
||||||
|
@stash="(stash) => stashActor(stash)"
|
||||||
|
@unstash="(stash) => unstashActor(stash)"
|
||||||
|
/>
|
||||||
|
-->
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="content">
|
||||||
|
<Bio :actor="actor" />
|
||||||
|
|
||||||
<Scenes />
|
<Scenes />
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { inject } from 'vue';
|
import { inject } from 'vue';
|
||||||
|
|
||||||
|
import Bio from '#/components/actors/bio.vue';
|
||||||
|
import Gender from '#/components/actors/gender.vue';
|
||||||
import Scenes from '#/components/scenes/scenes.vue';
|
import Scenes from '#/components/scenes/scenes.vue';
|
||||||
|
|
||||||
const pageContext = inject('pageContext');
|
const pageContext = inject('pageContext');
|
||||||
|
@ -27,19 +63,45 @@ const { actor } = pageProps;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.bio {
|
.actor {
|
||||||
display: flex;
|
display: flex;
|
||||||
padding: 1rem;
|
flex-direction: column;
|
||||||
|
flex-grow: 1;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.actor-header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
color: var(--highlight-strong-30);
|
||||||
background: var(--grey-dark-40);
|
background: var(--grey-dark-40);
|
||||||
color: var(--text-light);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.name {
|
.header-name {
|
||||||
|
padding: .5rem 1rem;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
display: inline-flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.avatar {
|
.header-gender {
|
||||||
height: 10rem;
|
display: inline-block;
|
||||||
margin-right: 1rem;
|
margin: 0 0 0 .5rem;
|
||||||
|
transform: translate(0, .125rem);
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-social {
|
||||||
|
overflow: hidden;
|
||||||
|
white-space: nowrap;
|
||||||
|
margin: 0 1rem 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
flex-grow: 1;
|
||||||
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -168,7 +168,7 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { inject } from 'vue';
|
import { inject } from 'vue';
|
||||||
|
|
||||||
import { formatDate, formatDuration } from '#/src/format.js';
|
import { formatDate, formatDuration } from '#/utils/format.js';
|
||||||
|
|
||||||
import Icon from '../../components/icon/icon.vue';
|
import Icon from '../../components/icon/icon.vue';
|
||||||
import ActorTile from '../../components/actors/tile.vue';
|
import ActorTile from '../../components/actors/tile.vue';
|
||||||
|
@ -327,10 +327,10 @@ const { scene } = pageProps;
|
||||||
}
|
}
|
||||||
|
|
||||||
.actors {
|
.actors {
|
||||||
display: flex;
|
display: grid;
|
||||||
gap: .5rem;
|
flex-grow: 1;
|
||||||
overflow-x: auto;
|
grid-template-columns: repeat(auto-fill, minmax(10rem, 1fr));
|
||||||
flex-wrap: nowrap;
|
gap: .25rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tag {
|
.tag {
|
||||||
|
|
|
@ -1,9 +1,17 @@
|
||||||
// https://vike.dev/onRenderHtml
|
// https://vike.dev/onRenderHtml
|
||||||
|
import config from 'config';
|
||||||
import { renderToString as renderToString_ } from '@vue/server-renderer';
|
import { renderToString as renderToString_ } from '@vue/server-renderer';
|
||||||
import { escapeInject, dangerouslySkipEscape } from 'vike/server';
|
import { escapeInject, dangerouslySkipEscape } from 'vike/server'; /* eslint-disable-line import/extensions */
|
||||||
|
|
||||||
import { createApp } from './app.js';
|
import { createApp } from './app.js';
|
||||||
import getTitle from '../src/get-title.js';
|
|
||||||
|
function getTitle(location) {
|
||||||
|
if (!location) {
|
||||||
|
return config.title;
|
||||||
|
}
|
||||||
|
|
||||||
|
return `${config.title} - ${location.slice(0, 1).toUpperCase()}${location.slice(1)}`;
|
||||||
|
}
|
||||||
|
|
||||||
async function renderToString(app) {
|
async function renderToString(app) {
|
||||||
let err;
|
let err;
|
||||||
|
|
|
@ -41,6 +41,8 @@ onMounted(() => {
|
||||||
}
|
}
|
||||||
|
|
||||||
.content {
|
.content {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import { differenceInYears } from 'date-fns';
|
import { differenceInYears } from 'date-fns';
|
||||||
|
import { unit } from 'mathjs';
|
||||||
|
|
||||||
import knex from './knex.js';
|
import knex from './knex.js';
|
||||||
import { searchApi } from './manticore.js';
|
import { searchApi } from './manticore.js';
|
||||||
|
@ -15,14 +16,37 @@ export function curateActor(actor, context = {}) {
|
||||||
dateOfBirth: actor.date_of_birth,
|
dateOfBirth: actor.date_of_birth,
|
||||||
ageFromBirth: actor.date_of_birth && differenceInYears(Date.now(), actor.date_of_birth),
|
ageFromBirth: actor.date_of_birth && differenceInYears(Date.now(), actor.date_of_birth),
|
||||||
ageThen: context.sceneDate && actor.date_of_birth && differenceInYears(context.sceneDate, actor.date_of_birth),
|
ageThen: context.sceneDate && actor.date_of_birth && differenceInYears(context.sceneDate, actor.date_of_birth),
|
||||||
birthCountry: actor.birth_country_alpha2 && {
|
bust: actor.bust,
|
||||||
|
cup: actor.cup,
|
||||||
|
waist: actor.waist,
|
||||||
|
hip: actor.hip,
|
||||||
|
naturalBoobs: actor.naturalBoobs,
|
||||||
|
height: actor.height && {
|
||||||
|
metric: actor.height,
|
||||||
|
imperial: unit(actor.height, 'cm').splitUnit(['ft', 'in']).map((value) => Math.round(value.toNumber())),
|
||||||
|
},
|
||||||
|
weight: actor.weight && {
|
||||||
|
metric: actor.weight,
|
||||||
|
imperial: Math.round(unit(actor.weight, 'kg').toNumeric('lbs')),
|
||||||
|
},
|
||||||
|
eyes: actor.eyes,
|
||||||
|
hairColor: actor.hairColor,
|
||||||
|
hasTattoos: actor.has_tattoos,
|
||||||
|
tattoos: actor.tattoos,
|
||||||
|
hasPiercings: actor.has_piercings,
|
||||||
|
piercings: actor.piercings,
|
||||||
|
origin: {
|
||||||
|
country: actor.birth_country_alpha2 && {
|
||||||
alpha2: actor.birth_country_alpha2,
|
alpha2: actor.birth_country_alpha2,
|
||||||
name: actor.birth_country_name,
|
name: actor.birth_country_name,
|
||||||
},
|
},
|
||||||
residenceCountry: actor.residence_country_alpha2 && {
|
},
|
||||||
|
residence: {
|
||||||
|
country: actor.residence_country_alpha2 && {
|
||||||
alpha2: actor.residence_country_alpha2,
|
alpha2: actor.residence_country_alpha2,
|
||||||
name: actor.residence_country_name,
|
name: actor.residence_country_name,
|
||||||
},
|
},
|
||||||
|
},
|
||||||
avatar: actor.avatar && {
|
avatar: actor.avatar && {
|
||||||
id: actor.avatar.id,
|
id: actor.avatar.id,
|
||||||
path: actor.avatar.path,
|
path: actor.avatar.path,
|
||||||
|
@ -30,6 +54,8 @@ export function curateActor(actor, context = {}) {
|
||||||
lazy: actor.avatar.lazy,
|
lazy: actor.avatar.lazy,
|
||||||
isS3: actor.avatar.is_s3,
|
isS3: actor.avatar.is_s3,
|
||||||
},
|
},
|
||||||
|
createdAt: actor.created_at,
|
||||||
|
updatedAt: actor.updated_at,
|
||||||
likes: actor.stashed,
|
likes: actor.stashed,
|
||||||
...context.append?.[actor.id],
|
...context.append?.[actor.id],
|
||||||
};
|
};
|
||||||
|
@ -90,8 +116,6 @@ function curateOptions(options) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildQuery(filters) {
|
function buildQuery(filters) {
|
||||||
console.log('filters', filters);
|
|
||||||
|
|
||||||
const query = {
|
const query = {
|
||||||
bool: {
|
bool: {
|
||||||
must: [],
|
must: [],
|
||||||
|
@ -103,8 +127,6 @@ function buildQuery(filters) {
|
||||||
};
|
};
|
||||||
|
|
||||||
if (filters.query) {
|
if (filters.query) {
|
||||||
console.log(filters.query);
|
|
||||||
|
|
||||||
query.bool.must.push({
|
query.bool.must.push({
|
||||||
match: {
|
match: {
|
||||||
name: filters.query,
|
name: filters.query,
|
||||||
|
@ -224,8 +246,6 @@ export async function fetchActors(filters, rawOptions) {
|
||||||
const options = curateOptions(rawOptions);
|
const options = curateOptions(rawOptions);
|
||||||
const { query, expressions } = buildQuery(filters);
|
const { query, expressions } = buildQuery(filters);
|
||||||
|
|
||||||
console.log(options);
|
|
||||||
|
|
||||||
const result = await searchApi.search({
|
const result = await searchApi.search({
|
||||||
index: 'actors',
|
index: 'actors',
|
||||||
query,
|
query,
|
||||||
|
|
|
@ -80,25 +80,17 @@ export async function fetchScenesById(sceneIds) {
|
||||||
.groupBy('channels.id', 'networks.id'),
|
.groupBy('channels.id', 'networks.id'),
|
||||||
knex('releases_actors')
|
knex('releases_actors')
|
||||||
.select(
|
.select(
|
||||||
'actors.*',
|
'actors_meta.*',
|
||||||
'releases_actors.release_id',
|
'releases_actors.release_id',
|
||||||
'avatars.id as avatar_id',
|
|
||||||
'avatars.path as avatar_path',
|
|
||||||
'avatars.thumbnail as avatar_thumbnail',
|
|
||||||
'avatars.lazy as avatar_lazy',
|
|
||||||
'avatars.width as avatar_width',
|
|
||||||
'avatars.height as avatar_height',
|
|
||||||
'avatars.is_s3 as avatar_s3',
|
|
||||||
'birth_countries.alpha2 as birth_country_alpha2',
|
'birth_countries.alpha2 as birth_country_alpha2',
|
||||||
'birth_countries.name as birth_country_name',
|
'birth_countries.name as birth_country_name',
|
||||||
'residence_countries.alpha2 as residence_country_alpha2',
|
'residence_countries.alpha2 as residence_country_alpha2',
|
||||||
'residence_countries.name as residence_country_name',
|
'residence_countries.name as residence_country_name',
|
||||||
)
|
)
|
||||||
.whereIn('release_id', sceneIds)
|
.whereIn('release_id', sceneIds)
|
||||||
.leftJoin('actors', 'actors.id', 'releases_actors.actor_id')
|
.leftJoin('actors_meta', 'actors_meta.id', 'releases_actors.actor_id')
|
||||||
.leftJoin('media as avatars', 'avatars.id', 'actors.avatar_media_id')
|
.leftJoin('countries as birth_countries', 'birth_countries.alpha2', 'actors_meta.birth_country_alpha2')
|
||||||
.leftJoin('countries as birth_countries', 'birth_countries.alpha2', 'actors.birth_country_alpha2')
|
.leftJoin('countries as residence_countries', 'residence_countries.alpha2', 'actors_meta.residence_country_alpha2'),
|
||||||
.leftJoin('countries as residence_countries', 'residence_countries.alpha2', 'actors.residence_country_alpha2'),
|
|
||||||
knex('releases_directors')
|
knex('releases_directors')
|
||||||
.whereIn('release_id', sceneIds)
|
.whereIn('release_id', sceneIds)
|
||||||
.leftJoin('actors as directors', 'directors.id', 'releases_directors.director_id'),
|
.leftJoin('actors as directors', 'directors.id', 'releases_directors.director_id'),
|
||||||
|
@ -191,23 +183,26 @@ function buildQuery(filters = {}) {
|
||||||
sort = [{ created_at: 'desc' }, { effective_date: 'asc' }];
|
sort = [{ created_at: 'desc' }, { effective_date: 'asc' }];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (filters.actorIds) {
|
if (filters.tagIds) {
|
||||||
filters.actorIds.forEach((actorId) => {
|
filters.tagIds.forEach((tagId) => {
|
||||||
query.bool.must.push({
|
query.bool.must.push({ equals: { 'any(tag_ids)': tagId } });
|
||||||
equals: {
|
|
||||||
'any(actor_ids)': actorId,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (filters.tagIds) {
|
if (filters.entityId) {
|
||||||
filters.tagIds.forEach((tagId) => {
|
|
||||||
query.bool.must.push({
|
query.bool.must.push({
|
||||||
equals: {
|
bool: {
|
||||||
'any(tag_ids)': tagId,
|
should: [
|
||||||
|
{ equals: { channel_id: filters.entityId } },
|
||||||
|
{ equals: { network_id: filters.entityId } },
|
||||||
|
],
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (filters.actorIds) {
|
||||||
|
filters.actorIds.forEach((actorId) => {
|
||||||
|
query.bool.must.push({ equals: { 'any(actor_ids)': actorId } });
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -221,8 +216,6 @@ function buildQuery(filters = {}) {
|
||||||
],
|
],
|
||||||
*/
|
*/
|
||||||
|
|
||||||
console.log(query.bool.must);
|
|
||||||
|
|
||||||
return { query, sort };
|
return { query, sort };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -272,9 +265,6 @@ export async function fetchScenes(filters, rawOptions) {
|
||||||
const options = curateOptions(rawOptions);
|
const options = curateOptions(rawOptions);
|
||||||
const { query, sort } = buildQuery(filters);
|
const { query, sort } = buildQuery(filters);
|
||||||
|
|
||||||
console.log('filters', filters);
|
|
||||||
console.log('options', options);
|
|
||||||
|
|
||||||
const result = await searchApi.search({
|
const result = await searchApi.search({
|
||||||
index: 'scenes',
|
index: 'scenes',
|
||||||
query,
|
query,
|
||||||
|
|
|
@ -4,8 +4,8 @@ import { fetchScenes } from '../scenes.js';
|
||||||
import { parseActorIdentifier } from '../query.js';
|
import { parseActorIdentifier } from '../query.js';
|
||||||
import redis from '../redis.js';
|
import redis from '../redis.js';
|
||||||
|
|
||||||
async function getTagIdsBySlug(tagSlugs) {
|
async function getIdsBySlug(slugs, domain) {
|
||||||
const tagIds = await Promise.all(tagSlugs.map(async (slug) => {
|
const ids = await Promise.all(slugs.map(async (slug) => {
|
||||||
if (!slug) {
|
if (!slug) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -14,19 +14,20 @@ async function getTagIdsBySlug(tagSlugs) {
|
||||||
return Number(slug); // already an ID or missing
|
return Number(slug); // already an ID or missing
|
||||||
}
|
}
|
||||||
|
|
||||||
const tagId = await redis.hGet('traxxx:tags:id_by_slug', slug);
|
const id = await redis.hGet(`traxxx:${domain}:id_by_slug`, slug);
|
||||||
|
|
||||||
return Number(tagId);
|
return Number(id);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
return tagIds.filter(Boolean);
|
return ids.filter(Boolean);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function curateScenesQuery(query) {
|
export async function curateScenesQuery(query) {
|
||||||
return {
|
return {
|
||||||
scope: query.scope || 'latest',
|
scope: query.scope || 'latest',
|
||||||
actorIds: [query.actorId, ...(query.actors?.split(',') || []).map((identifier) => parseActorIdentifier(identifier)?.id)].filter(Boolean),
|
actorIds: [query.actorId, ...(query.actors?.split(',') || []).map((identifier) => parseActorIdentifier(identifier)?.id)].filter(Boolean),
|
||||||
tagIds: await getTagIdsBySlug([query.tagId, ...(query.tags?.split(',') || [])]),
|
tagIds: await getIdsBySlug([query.tagId, ...(query.tags?.split(',') || [])], 'tags'),
|
||||||
|
entityId: query.e ? await getIdsBySlug([query.e], 'entities').then(([id]) => id) : query.entityId,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,59 @@
|
||||||
|
const config = {
|
||||||
|
client: {
|
||||||
|
media: {
|
||||||
|
assetPath: '/img',
|
||||||
|
mediaPath: '/media',
|
||||||
|
s3Path: 'https://cdndev.traxxx.me',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
function getBasePath(media, type, options) {
|
||||||
|
/*
|
||||||
|
if (store.state.ui.sfw) {
|
||||||
|
return config.client.media.assetPath;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (media.isS3) {
|
||||||
|
return config.client.media.s3Path;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options?.local) {
|
||||||
|
return config.client.media.assetPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
return config.client.media.mediaPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getFilename(media, type, options) {
|
||||||
|
/*
|
||||||
|
if (store.state.ui.sfw && type && !options?.original) {
|
||||||
|
return media.sfw[type];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (store.state.ui.sfw) {
|
||||||
|
return media.sfw.path;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (type && !options?.original) {
|
||||||
|
return media[type];
|
||||||
|
}
|
||||||
|
|
||||||
|
return media.path;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getMediaPath(media, type, options) {
|
||||||
|
console.log('media', media);
|
||||||
|
if (!media) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const path = getBasePath(media, type, options);
|
||||||
|
const filename = getFilename(media, type, options);
|
||||||
|
|
||||||
|
console.log(path, filename);
|
||||||
|
|
||||||
|
return `${path}/${filename}`;
|
||||||
|
}
|
Loading…
Reference in New Issue