Added actor revision overviews to actor and user pages.
This commit is contained in:
parent
d0cf9bf5d0
commit
05bd7b703d
2
common
2
common
|
@ -1 +1 @@
|
||||||
Subproject commit 40011a62dae9da8deda71e9f8daf39665a8b7958
|
Subproject commit e55818ab448d463c4765c3394a6049280799ec33
|
|
@ -12,6 +12,11 @@
|
||||||
:title="actor.avatar.credit && `© ${actor.avatar.credit}`"
|
:title="actor.avatar.credit && `© ${actor.avatar.credit}`"
|
||||||
class="avatar"
|
class="avatar"
|
||||||
>
|
>
|
||||||
|
|
||||||
|
<span
|
||||||
|
v-if="actor.avatar?.credit"
|
||||||
|
class="avatar-credit"
|
||||||
|
>{{ actor.avatar.credit }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<ul class="bio nolist">
|
<ul class="bio nolist">
|
||||||
|
@ -140,14 +145,14 @@
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li
|
<li
|
||||||
v-if="!actor.naturalBoobs || !actor.naturalButt"
|
v-if="actor.naturalBoobs === false || actor.naturalButt === false"
|
||||||
class="bio-item augmentations"
|
class="bio-item augmentations"
|
||||||
>
|
>
|
||||||
<dfn class="bio-label"><Icon icon="magic-wand2" />Augmentations</dfn>
|
<dfn class="bio-label"><Icon icon="magic-wand2" />Enhanced</dfn>
|
||||||
|
|
||||||
<span class="bio-value">
|
<span class="bio-value">
|
||||||
<div
|
<div
|
||||||
v-if="!actor.naturalBoobs"
|
v-if="actor.naturalBoobs === false"
|
||||||
:title="[actor.boobsVolume, augmentationMap[actor.boobsPlacement] || actor.boobsPlacement, augmentationMap[actor.boobsImplant] || actor.boobsImplant].filter(Boolean).join(' ')"
|
:title="[actor.boobsVolume, augmentationMap[actor.boobsPlacement] || actor.boobsPlacement, augmentationMap[actor.boobsImplant] || actor.boobsImplant].filter(Boolean).join(' ')"
|
||||||
class="augmentations-section"
|
class="augmentations-section"
|
||||||
>Boobs<template v-if="actor.boobsVolume || actor.boobsImplant">: </template>
|
>Boobs<template v-if="actor.boobsVolume || actor.boobsImplant">: </template>
|
||||||
|
@ -156,7 +161,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
v-if="!actor.naturalButt"
|
v-if="actor.naturalButt === false"
|
||||||
class="augmentations-section"
|
class="augmentations-section"
|
||||||
>Butt<template v-if="actor.buttVolume || actor.buttImplant">: </template>
|
>Butt<template v-if="actor.buttVolume || actor.buttImplant">: </template>
|
||||||
<template v-if="actor.buttVolume">{{ actor.buttVolume }}cc</template>
|
<template v-if="actor.buttVolume">{{ actor.buttVolume }}cc</template>
|
||||||
|
@ -258,21 +263,38 @@
|
||||||
<span v-else>Yes</span>
|
<span v-else>Yes</span>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li class="bio-item updated hideable">Updated {{ formatDate(actor.updatedAt, 'yyyy-MM-dd hh:mm') }}, ID: {{ actor.id }}</li>
|
<li
|
||||||
|
v-if="actor.agency"
|
||||||
|
class="bio-item"
|
||||||
|
>
|
||||||
|
<dfn class="bio-label"><Icon icon="user-tie" />Agency</dfn>
|
||||||
|
|
||||||
<li class="bio-item actor-actions">
|
<span
|
||||||
<a
|
:title="actor.agency"
|
||||||
v-if="user && user.role !== 'user'"
|
class="bio-value"
|
||||||
:href="`/actor/edit/${actor.id}/${actor.slug}`"
|
>{{ actor.agency }}</span>
|
||||||
target="_blank"
|
</li>
|
||||||
class="link"
|
|
||||||
>Edit bio</a>
|
|
||||||
|
|
||||||
<a
|
<li class="bio-item updated hideable">
|
||||||
:href="`/actor/revisions/${actor.id}/${actor.slug}`"
|
<span
|
||||||
target="_blank"
|
class="ellipsis"
|
||||||
class="link"
|
:title="`#${actor.id} Updated ${formatDate(actor.updatedAt, 'yyyy-MM-dd hh:mm')}`"
|
||||||
>Revisions</a>
|
>#{{ actor.id }} Updated {{ formatDate(actor.updatedAt, 'yyyy-MM-dd') }}</span>
|
||||||
|
|
||||||
|
<div class="actor-actions">
|
||||||
|
<a
|
||||||
|
v-if="user && user.role !== 'user'"
|
||||||
|
:href="`/actor/edit/${actor.id}/${actor.slug}`"
|
||||||
|
target="_blank"
|
||||||
|
class="link"
|
||||||
|
>Edit bio</a>
|
||||||
|
|
||||||
|
<a
|
||||||
|
:href="`/actor/revs/${actor.id}/${actor.slug}`"
|
||||||
|
target="_blank"
|
||||||
|
class="link"
|
||||||
|
>Revisions</a>
|
||||||
|
</div>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
@ -413,17 +435,32 @@ const descriptions = Object.values(Object.fromEntries(props.actor.profiles
|
||||||
}
|
}
|
||||||
|
|
||||||
.avatar-container {
|
.avatar-container {
|
||||||
padding: 0 0 1rem 1rem;
|
position: relative;
|
||||||
|
margin: 0 .5rem 1rem 1rem;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
|
font-size: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.avatar {
|
.avatar {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
border: solid 3px var(--highlight-hint);
|
border: solid 3px var(--highlight-weak-30);
|
||||||
margin: 0 .5rem 0 0;
|
border-radius: .5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.avatar-credit {
|
||||||
|
width: 100%;
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
bottom: 0;
|
||||||
|
z-index: 1;
|
||||||
|
box-sizing: border-box;
|
||||||
|
padding: 0 .5rem;
|
||||||
|
color: var(--text-light);
|
||||||
|
font-size: .75rem;
|
||||||
|
text-shadow: 1px 1px 0 var(--shadow-strong-20);
|
||||||
|
}
|
||||||
|
|
||||||
&.expanded {
|
&.expanded {
|
||||||
padding-bottom: 1.5rem;
|
padding-bottom: 1.5rem;
|
||||||
margin-bottom: .75rem;
|
margin-bottom: .75rem;
|
||||||
|
@ -573,10 +610,22 @@ const descriptions = Object.values(Object.fromEntries(props.actor.profiles
|
||||||
}
|
}
|
||||||
|
|
||||||
.updated {
|
.updated {
|
||||||
color: var(--highlight-weak-20);
|
color: var(--highlight-weak-10);
|
||||||
font-size: .8rem;
|
font-size: .8rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.actor-actions {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-start;
|
||||||
|
gap: 1rem;
|
||||||
|
margin-right: .5rem;
|
||||||
|
|
||||||
|
.link {
|
||||||
|
color: inherit;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.descriptions-container {
|
.descriptions-container {
|
||||||
max-width: 30rem;
|
max-width: 30rem;
|
||||||
max-height: 100%;
|
max-height: 100%;
|
||||||
|
@ -691,16 +740,6 @@ const descriptions = Object.values(Object.fromEntries(props.actor.profiles
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.actor-actions {
|
|
||||||
justify-content: flex-start;
|
|
||||||
gap: 1rem;
|
|
||||||
font-weight: normal;
|
|
||||||
|
|
||||||
.link {
|
|
||||||
color: var(--highlight-strong-20);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media(--big) {
|
@media(--big) {
|
||||||
.descriptions-container {
|
.descriptions-container {
|
||||||
display: none;
|
display: none;
|
||||||
|
|
|
@ -45,6 +45,7 @@ const pageContext = inject('pageContext');
|
||||||
padding: 1rem 1rem .75rem 1rem;
|
padding: 1rem 1rem .75rem 1rem;
|
||||||
border-bottom: solid 1px var(--shadow-weak-30);
|
border-bottom: solid 1px var(--shadow-weak-30);
|
||||||
margin-bottom: .25rem;
|
margin-bottom: .25rem;
|
||||||
|
overflow-x: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.nav-items {
|
.nav-items {
|
||||||
|
@ -54,6 +55,7 @@ const pageContext = inject('pageContext');
|
||||||
|
|
||||||
.nav-item {
|
.nav-item {
|
||||||
display: block;
|
display: block;
|
||||||
|
flex-shrink: 0;
|
||||||
background: var(--background-dark-20);
|
background: var(--background-dark-20);
|
||||||
border-radius: 1rem;
|
border-radius: 1rem;
|
||||||
color: var(--glass-strong-20);
|
color: var(--glass-strong-20);
|
||||||
|
|
|
@ -0,0 +1,110 @@
|
||||||
|
<template>
|
||||||
|
<div class="avatar noshrink">
|
||||||
|
<img
|
||||||
|
:src="getPath(avatar, 'thumbnail')"
|
||||||
|
class="avatar-image"
|
||||||
|
>
|
||||||
|
|
||||||
|
<span
|
||||||
|
class="avatar-credit"
|
||||||
|
title="Credit"
|
||||||
|
>{{ avatar.credit }}</span>
|
||||||
|
|
||||||
|
<span class="avatar-meta">
|
||||||
|
<span title="Dimensions">{{ avatar.width }}x{{ avatar.height }}</span>
|
||||||
|
<span title="Sharpness">{{ avatar.sharpness.toFixed(2) }}</span>
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<a
|
||||||
|
:href="getPath(avatar)"
|
||||||
|
target="_blank"
|
||||||
|
class="avatar-zoom"
|
||||||
|
>
|
||||||
|
<Icon
|
||||||
|
icon="search"
|
||||||
|
/>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import getPath from '#/src/get-path.js';
|
||||||
|
|
||||||
|
defineProps({
|
||||||
|
avatar: {
|
||||||
|
type: Object,
|
||||||
|
default: null,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.avatar {
|
||||||
|
display: inline-block;
|
||||||
|
position: relative;
|
||||||
|
border: solid 2px transparent;
|
||||||
|
border-radius: .35rem;
|
||||||
|
box-shadow: 0 0 3px var(--shadow-weak-10);
|
||||||
|
margin: 2px; /* clear outline */
|
||||||
|
font-size: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
&.selected {
|
||||||
|
border: solid 2px var(--primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
/*
|
||||||
|
.avatar-meta,
|
||||||
|
.avatar-credit {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
fill: var(--text-light);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.avatar-image {
|
||||||
|
height: 10rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.avatar-zoom {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
z-index: 10;
|
||||||
|
padding: .25rem;
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
fill: var(--highlight);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.avatar-meta,
|
||||||
|
.avatar-credit {
|
||||||
|
position: absolute;
|
||||||
|
z-index: 10;
|
||||||
|
box-sizing: border-box;
|
||||||
|
padding: .15rem .25rem;
|
||||||
|
font-size: .7rem;
|
||||||
|
color: var(--text-light);
|
||||||
|
text-shadow: 1px 1px 0 var(--shadow-strong-30);
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
|
||||||
|
.avatar-meta {
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.avatar-credit {
|
||||||
|
bottom: .75rem;
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -116,6 +116,12 @@
|
||||||
>{{ item.name || item.id || item }}</li> ]
|
>{{ item.name || item.id || item }}</li> ]
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
<Avatar
|
||||||
|
v-else-if="delta.key === 'avatar'"
|
||||||
|
:avatar="avatarsById[rev.base[delta.key]]"
|
||||||
|
class="delta-avatar"
|
||||||
|
/>
|
||||||
|
|
||||||
<template v-else-if="rev.base[delta.key] instanceof Date">{{ format(rev.base[delta.key], 'yyyy-MM-dd hh:mm') }}</template>
|
<template v-else-if="rev.base[delta.key] instanceof Date">{{ format(rev.base[delta.key], 'yyyy-MM-dd hh:mm') }}</template>
|
||||||
<template v-else>{{ rev.base[delta.key] }}</template>
|
<template v-else>{{ rev.base[delta.key] }}</template>
|
||||||
</span>
|
</span>
|
||||||
|
@ -135,6 +141,12 @@
|
||||||
>{{ item.name || item.id || item }}</li> ]
|
>{{ item.name || item.id || item }}</li> ]
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
<Avatar
|
||||||
|
v-else-if="delta.key === 'avatar'"
|
||||||
|
:avatar="avatarsById[delta.value]"
|
||||||
|
class="delta-avatar"
|
||||||
|
/>
|
||||||
|
|
||||||
<template v-else-if="delta.value instanceof Date">{{ format(delta.value, 'yyyy-MM-dd hh:mm') }}</template>
|
<template v-else-if="delta.value instanceof Date">{{ format(delta.value, 'yyyy-MM-dd hh:mm') }}</template>
|
||||||
<template v-else>{{ delta.value }}</template>
|
<template v-else>{{ delta.value }}</template>
|
||||||
</span>
|
</span>
|
||||||
|
@ -156,7 +168,7 @@
|
||||||
@click="expanded.add(rev.id)"
|
@click="expanded.add(rev.id)"
|
||||||
>
|
>
|
||||||
|
|
||||||
<span class="rev-scene nolink noshrink"><template v-if="context !== 'scene'">{{ rev.sceneId }}</template>@{{ rev.hash.slice(0, 6) }}</span>
|
<span class="rev-scene nolink noshrink"><template v-if="context !== 'scene' && context !== 'actor'">{{ rev.sceneId || rev.actorId }}</template>@{{ rev.hash.slice(0, 6) }}</span>
|
||||||
|
|
||||||
<span
|
<span
|
||||||
v-if="context !== 'scene'"
|
v-if="context !== 'scene'"
|
||||||
|
@ -205,6 +217,7 @@
|
||||||
import { ref, computed, inject } from 'vue';
|
import { ref, computed, inject } from 'vue';
|
||||||
import { format } from 'date-fns';
|
import { format } from 'date-fns';
|
||||||
|
|
||||||
|
import Avatar from '#/components/edit/avatar.vue';
|
||||||
import Checkbox from '#/components/form/checkbox.vue';
|
import Checkbox from '#/components/form/checkbox.vue';
|
||||||
|
|
||||||
import { get, post } from '#/src/api.js';
|
import { get, post } from '#/src/api.js';
|
||||||
|
@ -224,10 +237,12 @@ const domain = pageContext.routeParams.domain;
|
||||||
const actors = ref(pageContext.pageProps.actors);
|
const actors = ref(pageContext.pageProps.actors);
|
||||||
const tags = ref(pageContext.pageProps.tags);
|
const tags = ref(pageContext.pageProps.tags);
|
||||||
const movies = ref(pageContext.pageProps.movies);
|
const movies = ref(pageContext.pageProps.movies);
|
||||||
|
const avatars = ref(pageContext.pageProps.avatars);
|
||||||
|
|
||||||
const actorsById = computed(() => Object.fromEntries(actors.value.map((actor) => [actor.id, actor])));
|
const actorsById = computed(() => Object.fromEntries(actors.value.map((actor) => [actor.id, actor])));
|
||||||
const tagsById = computed(() => Object.fromEntries(tags.value.map((tag) => [tag.id, tag])));
|
const tagsById = computed(() => Object.fromEntries(tags.value.map((tag) => [tag.id, tag])));
|
||||||
const moviesById = computed(() => Object.fromEntries(movies.value.map((movie) => [movie.id, movie])));
|
const moviesById = computed(() => Object.fromEntries(movies.value.map((movie) => [movie.id, movie])));
|
||||||
|
const avatarsById = computed(() => Object.fromEntries(avatars.value.map((avatar) => [avatar.id, avatar])));
|
||||||
|
|
||||||
const feedbacks = ref({});
|
const feedbacks = ref({});
|
||||||
const showReviewed = ref(false);
|
const showReviewed = ref(false);
|
||||||
|
@ -318,6 +333,7 @@ async function reloadRevisions() {
|
||||||
actors.value = updatedRevisions.actors;
|
actors.value = updatedRevisions.actors;
|
||||||
tags.value = updatedRevisions.tags;
|
tags.value = updatedRevisions.tags;
|
||||||
movies.value = updatedRevisions.movies;
|
movies.value = updatedRevisions.movies;
|
||||||
|
avatars.value = updatedRevisions.avatars;
|
||||||
revisions.value = updatedRevisions.revisions;
|
revisions.value = updatedRevisions.revisions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -39,18 +39,27 @@
|
||||||
class="photos nobar"
|
class="photos nobar"
|
||||||
:class="{ 'has-avatar': actor.avatar, 'has-photos': actor.avatar ? photos.length > 1 : photos.length > 0 }"
|
:class="{ 'has-avatar': actor.avatar, 'has-photos': actor.avatar ? photos.length > 1 : photos.length > 0 }"
|
||||||
>
|
>
|
||||||
<img
|
<div
|
||||||
v-for="photo in photos"
|
v-for="photo in photos"
|
||||||
:key="`photo-${photo.id}`"
|
:key="`photo-${photo.id}`"
|
||||||
:src="getPath(photo, 'thumbnail')"
|
class="photo-container"
|
||||||
:width="photo.width"
|
|
||||||
:height="photo.height"
|
|
||||||
:style="{ 'background-image': `url('${getPath(photo, 'lazy')}')` }"
|
|
||||||
:title="photo.credit && `© ${photo.credit}`"
|
|
||||||
loading="lazy"
|
|
||||||
class="photo"
|
|
||||||
:class="{ avatar: photo.isAvatar }"
|
:class="{ avatar: photo.isAvatar }"
|
||||||
>
|
>
|
||||||
|
<img
|
||||||
|
:src="getPath(photo, 'thumbnail')"
|
||||||
|
:width="photo.width"
|
||||||
|
:height="photo.height"
|
||||||
|
:style="{ 'background-image': `url('${getPath(photo, 'lazy')}')` }"
|
||||||
|
:title="photo.credit && `© ${photo.credit}`"
|
||||||
|
loading="lazy"
|
||||||
|
class="photo"
|
||||||
|
>
|
||||||
|
|
||||||
|
<span
|
||||||
|
v-if="photo.credit"
|
||||||
|
class="photo-credit"
|
||||||
|
>{{ photo.credit }}</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Domains
|
<Domains
|
||||||
|
@ -150,18 +159,37 @@ const photos = Object.values(Object.fromEntries(actor.profiles
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.photo-container {
|
||||||
|
position: relative;
|
||||||
|
font-size: 0;
|
||||||
|
|
||||||
|
&.avatar {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.photo {
|
.photo {
|
||||||
height: 14rem;
|
height: 14rem;
|
||||||
width: auto;
|
width: auto;
|
||||||
object-fit: cover;
|
object-fit: cover;
|
||||||
object-position: 50% 0;
|
object-position: 50% 0;
|
||||||
|
border-radius: .25rem;
|
||||||
background-size: cover;
|
background-size: cover;
|
||||||
background-position: center;
|
background-position: center;
|
||||||
box-shadow: 0 0px 3px var(--shadow-weak-30);
|
box-shadow: 0 0px 3px var(--shadow-weak-30);
|
||||||
|
}
|
||||||
|
|
||||||
&.avatar {
|
.photo-credit {
|
||||||
display: none;
|
width: 100%;
|
||||||
}
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
bottom: 0;
|
||||||
|
z-index: 1;
|
||||||
|
box-sizing: border-box;
|
||||||
|
padding: .15rem .2rem;
|
||||||
|
color: var(--text-light);
|
||||||
|
font-size: .75rem;
|
||||||
|
text-shadow: 1px 1px 0 var(--shadow-strong-20);
|
||||||
}
|
}
|
||||||
|
|
||||||
.domains-bar {
|
.domains-bar {
|
||||||
|
@ -174,7 +202,7 @@ const photos = Object.values(Object.fromEntries(actor.profiles
|
||||||
display: flex;
|
display: flex;
|
||||||
}
|
}
|
||||||
|
|
||||||
.photo.avatar {
|
.photo-container.avatar {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
|
|
||||||
<li>
|
<li>
|
||||||
<a
|
<a
|
||||||
:href="`/actor/revisions/${actor.id}/${actor.slug}`"
|
:href="`/actor/revs/${actor.id}/${actor.slug}`"
|
||||||
class="link"
|
class="link"
|
||||||
>Go to actor revisions</a>
|
>Go to actor revisions</a>
|
||||||
</li>
|
</li>
|
||||||
|
@ -86,9 +86,20 @@
|
||||||
v-if="item.type === 'string'"
|
v-if="item.type === 'string'"
|
||||||
v-model="edits[item.key]"
|
v-model="edits[item.key]"
|
||||||
class="string input"
|
class="string input"
|
||||||
|
:list="item.suggestions && `suggestions-${item.key}`"
|
||||||
:disabled="!editing.has(item.key)"
|
:disabled="!editing.has(item.key)"
|
||||||
>
|
>
|
||||||
|
|
||||||
|
<datalist
|
||||||
|
v-if="item.suggestions"
|
||||||
|
:id="`suggestions-${item.key}`"
|
||||||
|
>
|
||||||
|
<option
|
||||||
|
v-for="(suggestion, index) in item.suggestions"
|
||||||
|
:key="`suggestion-${item.key}-${index}`"
|
||||||
|
>{{ suggestion }}</option>
|
||||||
|
</datalist>
|
||||||
|
|
||||||
<textarea
|
<textarea
|
||||||
v-if="item.type === 'text'"
|
v-if="item.type === 'text'"
|
||||||
v-model="edits[item.key]"
|
v-model="edits[item.key]"
|
||||||
|
@ -485,38 +496,13 @@
|
||||||
class="avatars"
|
class="avatars"
|
||||||
:class="{ disabled: !editing.has(item.key) }"
|
:class="{ disabled: !editing.has(item.key) }"
|
||||||
>
|
>
|
||||||
<div
|
<Avatar
|
||||||
v-for="avatar in item.options"
|
v-for="avatar in item.options"
|
||||||
:key="`avatar-${avatar.id}`"
|
:key="`avatar-${avatar.id}`"
|
||||||
class="avatar noshrink"
|
:avatar="avatar"
|
||||||
:class="{ selected: edits[item.key] === avatar.id }"
|
:class="{ selected: edits[item.key] === avatar.id }"
|
||||||
@click="setAvatar(avatar.id)"
|
@click="setAvatar(avatar.id)"
|
||||||
>
|
/>
|
||||||
<img
|
|
||||||
:src="getPath(avatar, 'thumbnail')"
|
|
||||||
class="avatar-image"
|
|
||||||
>
|
|
||||||
|
|
||||||
<span
|
|
||||||
class="avatar-credit"
|
|
||||||
title="Credit"
|
|
||||||
>{{ avatar.credit }}</span>
|
|
||||||
|
|
||||||
<span class="avatar-meta">
|
|
||||||
<span title="Dimensions">{{ avatar.width }}x{{ avatar.height }}</span>
|
|
||||||
<span title="Sharpness">{{ avatar.sharpness.toFixed(2) }}</span>
|
|
||||||
</span>
|
|
||||||
|
|
||||||
<a
|
|
||||||
:href="getPath(avatar)"
|
|
||||||
target="_blank"
|
|
||||||
class="avatar-zoom"
|
|
||||||
>
|
|
||||||
<Icon
|
|
||||||
icon="search"
|
|
||||||
/>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
|
@ -561,8 +547,7 @@
|
||||||
import { ref, computed, inject } from 'vue';
|
import { ref, computed, inject } from 'vue';
|
||||||
import { format } from 'date-fns';
|
import { format } from 'date-fns';
|
||||||
|
|
||||||
import getPath from '#/src/get-path.js';
|
import Avatar from '#/components/edit/avatar.vue';
|
||||||
|
|
||||||
import Checkbox from '#/components/form/checkbox.vue';
|
import Checkbox from '#/components/form/checkbox.vue';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
@ -576,8 +561,6 @@ const user = pageContext.user;
|
||||||
const countries = pageContext.pageProps.countries;
|
const countries = pageContext.pageProps.countries;
|
||||||
const actor = ref(pageContext.pageProps.actor);
|
const actor = ref(pageContext.pageProps.actor);
|
||||||
|
|
||||||
console.log(actor.value);
|
|
||||||
|
|
||||||
const topCountries = [
|
const topCountries = [
|
||||||
'AU',
|
'AU',
|
||||||
'BR',
|
'BR',
|
||||||
|
@ -658,14 +641,14 @@ const fields = computed(() => [
|
||||||
{
|
{
|
||||||
key: 'height',
|
key: 'height',
|
||||||
type: 'number',
|
type: 'number',
|
||||||
value: actor.value.height.metric,
|
value: actor.value.height?.metric,
|
||||||
unit: 'cm',
|
unit: 'cm',
|
||||||
inline: true,
|
inline: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'weight',
|
key: 'weight',
|
||||||
type: 'number',
|
type: 'number',
|
||||||
value: actor.value.weight.metric,
|
value: actor.value.weight?.metric,
|
||||||
unit: 'kg',
|
unit: 'kg',
|
||||||
inline: true,
|
inline: true,
|
||||||
},
|
},
|
||||||
|
@ -743,6 +726,22 @@ const fields = computed(() => [
|
||||||
description: actor.value.piercings,
|
description: actor.value.piercings,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
key: 'agency',
|
||||||
|
type: 'string',
|
||||||
|
value: actor.value.agency,
|
||||||
|
suggestions: [
|
||||||
|
'101 Modeling',
|
||||||
|
'Adult Talent Managers (ATMLA)',
|
||||||
|
'The Bakery Talent',
|
||||||
|
'Coxxx Models',
|
||||||
|
'East Coast Talent (ECT)',
|
||||||
|
'Hussie Models',
|
||||||
|
'Invision Models',
|
||||||
|
'OC Modeling',
|
||||||
|
'Spiegler Girls',
|
||||||
|
],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
key: 'penis',
|
key: 'penis',
|
||||||
type: 'penis',
|
type: 'penis',
|
||||||
|
@ -780,30 +779,8 @@ function toggleField(item) {
|
||||||
}
|
}
|
||||||
|
|
||||||
editing.value.add(item.key);
|
editing.value.add(item.key);
|
||||||
|
|
||||||
/*
|
|
||||||
if (Array.isArray(item.value)) {
|
|
||||||
edits.value[item.key] = item.value.map((value) => value.hash || value.id);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
edits.value[item.key] = item.value;
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
function setValue(item, event) {
|
|
||||||
console.log(item, event.target.value);
|
|
||||||
|
|
||||||
if (item.type === 'number') {
|
|
||||||
edits.value[item.key] = Number(event.target.value);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
edits.value[item.key] = event.target.value;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
function setAvatar(avatarId) {
|
function setAvatar(avatarId) {
|
||||||
edits.value.avatar = avatarId;
|
edits.value.avatar = avatarId;
|
||||||
}
|
}
|
||||||
|
@ -822,8 +799,6 @@ const keyMap = {
|
||||||
};
|
};
|
||||||
|
|
||||||
async function submit() {
|
async function submit() {
|
||||||
console.log('SUBMIT', Array.from(editing.value), edits.value);
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await post('/revisions/actors', {
|
await post('/revisions/actors', {
|
||||||
actorId: actor.value.id,
|
actorId: actor.value.id,
|
||||||
|
@ -1014,75 +989,6 @@ async function submit() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.avatar {
|
|
||||||
display: inline-block;
|
|
||||||
position: relative;
|
|
||||||
border: solid 2px transparent;
|
|
||||||
border-radius: .35rem;
|
|
||||||
box-shadow: 0 0 3px var(--shadow-weak-10);
|
|
||||||
margin: 2px; /* clear outline */
|
|
||||||
font-size: 0;
|
|
||||||
overflow: hidden;
|
|
||||||
|
|
||||||
&.selected {
|
|
||||||
border: solid 2px var(--primary);
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
/*
|
|
||||||
.avatar-meta,
|
|
||||||
.avatar-credit {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
.icon {
|
|
||||||
fill: var(--text-light);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.avatar-image {
|
|
||||||
height: 10rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.avatar-zoom {
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
right: 0;
|
|
||||||
z-index: 10;
|
|
||||||
padding: .25rem;
|
|
||||||
|
|
||||||
.icon {
|
|
||||||
fill: var(--highlight);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.avatar-meta,
|
|
||||||
.avatar-credit {
|
|
||||||
position: absolute;
|
|
||||||
z-index: 10;
|
|
||||||
box-sizing: border-box;
|
|
||||||
padding: .15rem .25rem;
|
|
||||||
font-size: .7rem;
|
|
||||||
color: var(--text-light);
|
|
||||||
text-shadow: 1px 1px 0 var(--shadow-strong-30);
|
|
||||||
cursor: default;
|
|
||||||
}
|
|
||||||
|
|
||||||
.avatar-meta {
|
|
||||||
width: 100%;
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
bottom: 0;
|
|
||||||
left: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.avatar-credit {
|
|
||||||
bottom: .75rem;
|
|
||||||
left: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.item-actions {
|
.item-actions {
|
||||||
.icon {
|
.icon {
|
||||||
padding: .25rem 1rem;
|
padding: .25rem 1rem;
|
||||||
|
|
|
@ -1,23 +1,23 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<div class="revs-header">
|
<div class="revs-header">
|
||||||
<h2 class="heading">Revisions for "{{ scene.title }}"</h2>
|
<h2 class="heading">Revisions for "{{ actor.name }}"</h2>
|
||||||
|
|
||||||
<div class="revs-actions">
|
<div class="revs-actions">
|
||||||
<a
|
<a
|
||||||
:href="`/scene/edit/${scene.id}/${scene.slug}`"
|
:href="`/actor/edit/${actor.id}/${actor.slug}`"
|
||||||
class="link"
|
class="link"
|
||||||
>Edit scene</a>
|
>Edit actor</a>
|
||||||
|
|
||||||
<a
|
<a
|
||||||
:href="`/scene/${scene.id}/${scene.slug}`"
|
:href="`/actor/${actor.id}/${actor.slug}`"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
class="link"
|
class="link"
|
||||||
>Go to scene</a>
|
>Go to actor</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Revisions context="scene" />
|
<Revisions context="actor" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@ import { inject } from 'vue';
|
||||||
import Revisions from '#/components/edit/revisions.vue';
|
import Revisions from '#/components/edit/revisions.vue';
|
||||||
|
|
||||||
const pageContext = inject('pageContext');
|
const pageContext = inject('pageContext');
|
||||||
const scene = pageContext.pageProps.scene;
|
const actor = pageContext.pageProps.actor;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
|
|
@ -1,23 +1,24 @@
|
||||||
import { fetchActorsById } from '#/src/actors.js';
|
import { fetchActorsById, fetchActorRevisions } from '#/src/actors.js';
|
||||||
import { fetchSceneRevisions } from '#/src/scenes.js';
|
|
||||||
|
|
||||||
export async function onBeforeRender(pageContext) {
|
export async function onBeforeRender(pageContext) {
|
||||||
const [actor] = await fetchActorsById([Number(pageContext.routeParams.actorId)], {}, pageContext.user);
|
const [actor] = await fetchActorsById([Number(pageContext.routeParams.actorId)], {}, pageContext.user);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
revisions,
|
revisions,
|
||||||
} = await fetchSceneRevisions(null, {
|
avatars,
|
||||||
sceneId: actor.id,
|
} = await fetchActorRevisions(null, {
|
||||||
|
actorId: actor.id,
|
||||||
isFinalized: true,
|
isFinalized: true,
|
||||||
limit: 100,
|
limit: 100,
|
||||||
}, pageContext.user);
|
}, pageContext.user);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
pageContext: {
|
pageContext: {
|
||||||
title: `Revisions for '${actor.name}'`,
|
title: `Revs for '${actor.name}'`,
|
||||||
pageProps: {
|
pageProps: {
|
||||||
actor,
|
actor,
|
||||||
revisions,
|
revisions,
|
||||||
|
avatars,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -1 +1,19 @@
|
||||||
export default '/actor/revisions/@actorId/*';
|
import { match } from 'path-to-regexp';
|
||||||
|
|
||||||
|
const path = '/actor/revs/:actorId/:slug?';
|
||||||
|
const urlMatch = match(path, { decode: decodeURIComponent });
|
||||||
|
|
||||||
|
export default (pageContext) => {
|
||||||
|
const matched = urlMatch(pageContext.urlPathname);
|
||||||
|
|
||||||
|
if (matched) {
|
||||||
|
return {
|
||||||
|
routeParams: {
|
||||||
|
actorId: matched.params.actorId,
|
||||||
|
domain: 'actors',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
|
@ -1,9 +1,36 @@
|
||||||
<template>
|
<template>
|
||||||
<Admin>
|
<Admin>
|
||||||
<h2 class="heading">Admin Panel</h2>
|
<h2 class="heading">Admin Panel</h2>
|
||||||
|
|
||||||
|
<ul class="menu">
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
href="/admin/revisions/scenes"
|
||||||
|
class="link"
|
||||||
|
>Scene Revisions</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
href="/admin/revisions/actors"
|
||||||
|
class="link"
|
||||||
|
>Actor Revisions</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
</Admin>
|
</Admin>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import Admin from '#/components/admin/admin.vue';
|
import Admin from '#/components/admin/admin.vue';
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.menu {
|
||||||
|
margin: 0;
|
||||||
|
|
||||||
|
.link {
|
||||||
|
display: block;
|
||||||
|
padding: .25rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
|
@ -8,6 +8,7 @@ export async function onBeforeRender(pageContext) {
|
||||||
|
|
||||||
const {
|
const {
|
||||||
revisions,
|
revisions,
|
||||||
|
avatars,
|
||||||
} = await fetchActorRevisions(null, {
|
} = await fetchActorRevisions(null, {
|
||||||
isFinalized: false,
|
isFinalized: false,
|
||||||
limit: 50,
|
limit: 50,
|
||||||
|
@ -18,6 +19,7 @@ export async function onBeforeRender(pageContext) {
|
||||||
title: pageContext.routeParams.section,
|
title: pageContext.routeParams.section,
|
||||||
pageProps: {
|
pageProps: {
|
||||||
revisions,
|
revisions,
|
||||||
|
avatars,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -345,7 +345,7 @@
|
||||||
>Edit scene</a>
|
>Edit scene</a>
|
||||||
|
|
||||||
<a
|
<a
|
||||||
:href="`/scene/revisions/${scene.id}/${scene.slug}`"
|
:href="`/scene/revs/${scene.id}/${scene.slug}`"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
class="link"
|
class="link"
|
||||||
>Revisions</a>
|
>Revisions</a>
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
|
|
||||||
<li>
|
<li>
|
||||||
<a
|
<a
|
||||||
:href="`/scene/revisions/${scene.id}/${scene.slug}`"
|
:href="`/scene/revs/${scene.id}/${scene.slug}`"
|
||||||
class="link"
|
class="link"
|
||||||
>Go to scene revisions</a>
|
>Go to scene revisions</a>
|
||||||
</li>
|
</li>
|
||||||
|
@ -320,7 +320,7 @@ function setDuration(unit, event) {
|
||||||
|
|
||||||
async function submit() {
|
async function submit() {
|
||||||
try {
|
try {
|
||||||
await post('/revisions', {
|
await post('/revisions/scenes', {
|
||||||
sceneId: scene.value.id,
|
sceneId: scene.value.id,
|
||||||
edits: {
|
edits: {
|
||||||
...edits.value,
|
...edits.value,
|
||||||
|
|
|
@ -21,7 +21,7 @@ export async function onBeforeRender(pageContext) {
|
||||||
|
|
||||||
return {
|
return {
|
||||||
pageContext: {
|
pageContext: {
|
||||||
title: `Revisions for '${scene.title}'`,
|
title: `Revs for '${scene.title}'`,
|
||||||
pageProps: {
|
pageProps: {
|
||||||
scene,
|
scene,
|
||||||
revisions,
|
revisions,
|
||||||
|
|
|
@ -1 +1,19 @@
|
||||||
export default '/scene/revisions/@sceneId/*';
|
import { match } from 'path-to-regexp';
|
||||||
|
|
||||||
|
const path = '/scene/revs/:sceneId/:slug?';
|
||||||
|
const urlMatch = match(path, { decode: decodeURIComponent });
|
||||||
|
|
||||||
|
export default (pageContext) => {
|
||||||
|
const matched = urlMatch(pageContext.urlPathname);
|
||||||
|
|
||||||
|
if (matched) {
|
||||||
|
return {
|
||||||
|
routeParams: {
|
||||||
|
sceneId: matched.params.sceneId,
|
||||||
|
domain: 'scenes',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
|
@ -22,42 +22,48 @@
|
||||||
<a
|
<a
|
||||||
:href="`/user/${profile.username}/stashes`"
|
:href="`/user/${profile.username}/stashes`"
|
||||||
class="domain nolink"
|
class="domain nolink"
|
||||||
:class="{ active: domain === 'stashes' }"
|
:class="{ active: section === 'stashes' }"
|
||||||
>Stashes</a>
|
>Stashes</a>
|
||||||
|
|
||||||
<a
|
<a
|
||||||
:href="`/user/${profile.username}/alerts`"
|
:href="`/user/${profile.username}/alerts`"
|
||||||
class="domain nolink"
|
class="domain nolink"
|
||||||
:class="{ active: domain === 'alerts' }"
|
:class="{ active: section === 'alerts' }"
|
||||||
>Alerts</a>
|
>Alerts</a>
|
||||||
|
|
||||||
<a
|
<a
|
||||||
:href="`/user/${profile.username}/templates`"
|
:href="`/user/${profile.username}/templates`"
|
||||||
class="domain nolink"
|
class="domain nolink"
|
||||||
:class="{ active: domain === 'templates' }"
|
:class="{ active: section === 'templates' }"
|
||||||
>Templates</a>
|
>Templates</a>
|
||||||
|
|
||||||
<a
|
<a
|
||||||
:href="`/user/${profile.username}/revisions`"
|
:href="`/user/${profile.username}/revisions/scenes`"
|
||||||
class="domain nolink"
|
class="domain nolink"
|
||||||
:class="{ active: domain === 'revisions' }"
|
:class="{ active: section === 'revisions' && domain === 'scenes' }"
|
||||||
>Revisions</a>
|
>Scene Revisions</a>
|
||||||
|
|
||||||
|
<a
|
||||||
|
:href="`/user/${profile.username}/revisions/actors`"
|
||||||
|
class="domain nolink"
|
||||||
|
:class="{ active: section === 'revisions' && domain === 'actors' }"
|
||||||
|
>Actor Revisions</a>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<Stashes v-if="domain === 'stashes'" />
|
<Stashes v-if="section === 'stashes'" />
|
||||||
<Alerts v-if="domain === 'alerts' && profile.id === user?.id" />
|
<Alerts v-if="section === 'alerts' && profile.id === user?.id" />
|
||||||
|
|
||||||
<Summaries
|
<Summaries
|
||||||
v-if="domain === 'templates' && profile.id === user?.id"
|
v-if="section === 'templates' && profile.id === user?.id"
|
||||||
:release="mockupRelease"
|
:release="mockupRelease"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
v-if="domain === 'revisions' && profile.id === user?.id"
|
v-if="section === 'revisions' && profile.id === user?.id"
|
||||||
class="profile-section revisions"
|
class="profile-section revisions"
|
||||||
>
|
>
|
||||||
<h3 class="section-header heading">Revisions</h3>
|
<h3 class="section-header heading">{{ domain.slice(0, -1) }} Revisions</h3>
|
||||||
<Revisions context="user" />
|
<Revisions context="user" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -73,7 +79,10 @@ import Summaries from '#/components/scenes/summaries.vue';
|
||||||
import Revisions from '#/components/edit/revisions.vue';
|
import Revisions from '#/components/edit/revisions.vue';
|
||||||
|
|
||||||
const pageContext = inject('pageContext');
|
const pageContext = inject('pageContext');
|
||||||
|
|
||||||
|
const section = pageContext.routeParams.section;
|
||||||
const domain = pageContext.routeParams.domain;
|
const domain = pageContext.routeParams.domain;
|
||||||
|
|
||||||
const user = pageContext.user;
|
const user = pageContext.user;
|
||||||
const profile = ref(pageContext.pageProps.profile);
|
const profile = ref(pageContext.pageProps.profile);
|
||||||
|
|
||||||
|
@ -117,6 +126,7 @@ const mockupRelease = {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
padding: .5rem 1rem;
|
padding: .5rem 1rem;
|
||||||
|
text-transform: capitalize;
|
||||||
|
|
||||||
.button {
|
.button {
|
||||||
margin-left: 1rem;
|
margin-left: 1rem;
|
||||||
|
@ -222,6 +232,11 @@ const mockupRelease = {
|
||||||
padding: 0 1rem;
|
padding: 0 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.revisions-nav {
|
||||||
|
display: flex;
|
||||||
|
gap: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
@media(--compact) {
|
@media(--compact) {
|
||||||
.domains {
|
.domains {
|
||||||
padding: .5rem 1rem;
|
padding: .5rem 1rem;
|
||||||
|
|
|
@ -4,19 +4,37 @@ import { fetchUser } from '#/src/users.js';
|
||||||
import { fetchUserStashes } from '#/src/stashes.js';
|
import { fetchUserStashes } from '#/src/stashes.js';
|
||||||
import { fetchAlerts } from '#/src/alerts.js';
|
import { fetchAlerts } from '#/src/alerts.js';
|
||||||
import { fetchSceneRevisions } from '#/src/scenes.js';
|
import { fetchSceneRevisions } from '#/src/scenes.js';
|
||||||
|
import { fetchActorRevisions } from '#/src/actors.js';
|
||||||
|
|
||||||
|
async function fetchRevisions(pageContext) {
|
||||||
|
if (pageContext.routeParams.username !== pageContext.user?.username) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pageContext.routeParams.section === 'revisions' && pageContext.routeParams.domain === 'scenes') {
|
||||||
|
return fetchSceneRevisions(null, {
|
||||||
|
userId: pageContext.user.id,
|
||||||
|
limit: 100,
|
||||||
|
}, pageContext.user);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pageContext.routeParams.section === 'revisions' && pageContext.routeParams.domain === 'actors') {
|
||||||
|
return fetchActorRevisions(null, {
|
||||||
|
userId: pageContext.user.id,
|
||||||
|
limit: 100,
|
||||||
|
}, pageContext.user);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
export async function onBeforeRender(pageContext) {
|
export async function onBeforeRender(pageContext) {
|
||||||
const [profile, alerts, userRevisions] = await Promise.all([
|
const [profile, alerts, userRevisions] = await Promise.all([
|
||||||
fetchUser(pageContext.routeParams.username, {}, pageContext.user),
|
fetchUser(pageContext.routeParams.username, {}, pageContext.user),
|
||||||
pageContext.routeParams.domain === 'stashes' && pageContext.routeParams.username === pageContext.user?.username
|
pageContext.routeParams.section === 'alerts' && pageContext.routeParams.username === pageContext.user?.username
|
||||||
? fetchAlerts(pageContext.user)
|
? fetchAlerts(pageContext.user)
|
||||||
: [],
|
: [],
|
||||||
pageContext.routeParams.domain === 'revisions' && pageContext.routeParams.username === pageContext.user?.username
|
fetchRevisions(pageContext),
|
||||||
? fetchSceneRevisions(null, {
|
|
||||||
userId: pageContext.user.id,
|
|
||||||
limit: 100,
|
|
||||||
}, pageContext.user)
|
|
||||||
: {},
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
if (!profile) {
|
if (!profile) {
|
||||||
|
@ -28,8 +46,11 @@ export async function onBeforeRender(pageContext) {
|
||||||
actors,
|
actors,
|
||||||
tags,
|
tags,
|
||||||
movies,
|
movies,
|
||||||
|
avatars,
|
||||||
} = userRevisions;
|
} = userRevisions;
|
||||||
|
|
||||||
|
console.log(userRevisions);
|
||||||
|
|
||||||
const stashes = await fetchUserStashes(profile.id, pageContext.user);
|
const stashes = await fetchUserStashes(profile.id, pageContext.user);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -43,6 +64,7 @@ export async function onBeforeRender(pageContext) {
|
||||||
actors,
|
actors,
|
||||||
tags,
|
tags,
|
||||||
movies,
|
movies,
|
||||||
|
avatars,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { redirect } from 'vike/abort'; /* eslint-disable-line import/extensions */
|
import { redirect } from 'vike/abort'; /* eslint-disable-line import/extensions */
|
||||||
import { match } from 'path-to-regexp';
|
import { match } from 'path-to-regexp';
|
||||||
|
|
||||||
const path = '/user/:username/:domain?';
|
const path = '/user/:username/:section?/:domain?';
|
||||||
const urlMatch = match(path, { decode: decodeURIComponent });
|
const urlMatch = match(path, { decode: decodeURIComponent });
|
||||||
|
|
||||||
export default (pageContext) => {
|
export default (pageContext) => {
|
||||||
|
@ -15,7 +15,8 @@ export default (pageContext) => {
|
||||||
return {
|
return {
|
||||||
routeParams: {
|
routeParams: {
|
||||||
username: matched.params.username,
|
username: matched.params.username,
|
||||||
domain: matched.params.domain || 'stashes',
|
section: matched.params.section || 'stashes',
|
||||||
|
domain: matched.params.domain || 'scenes',
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "traxxx",
|
"name": "traxxx",
|
||||||
"short_name": "traxxx",
|
"short_name": "traxxx",
|
||||||
|
"scope": "/",
|
||||||
"icons": [
|
"icons": [
|
||||||
{
|
{
|
||||||
"src": "/img/favicon/android-chrome-192x192.png",
|
"src": "/img/favicon/android-chrome-192x192.png",
|
||||||
|
|
|
@ -79,6 +79,7 @@ export function curateActor(actor, context = {}) {
|
||||||
city: actor.residence_city,
|
city: actor.residence_city,
|
||||||
state: actor.residence_state,
|
state: actor.residence_state,
|
||||||
},
|
},
|
||||||
|
agency: actor.agency,
|
||||||
avatar: curateMedia(actor.avatar),
|
avatar: curateMedia(actor.avatar),
|
||||||
profiles: context.profiles?.map((profile) => ({
|
profiles: context.profiles?.map((profile) => ({
|
||||||
id: profile.id,
|
id: profile.id,
|
||||||
|
@ -159,8 +160,6 @@ export async function fetchActorsById(actorIds, options = {}, reqUser) {
|
||||||
: [],
|
: [],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
console.log(actors);
|
|
||||||
|
|
||||||
if (options.order) {
|
if (options.order) {
|
||||||
return actors.map((actorEntry) => curateActor(actorEntry, {
|
return actors.map((actorEntry) => curateActor(actorEntry, {
|
||||||
stashes: stashes.filter((stash) => stash.actor_id === actorEntry.id),
|
stashes: stashes.filter((stash) => stash.actor_id === actorEntry.id),
|
||||||
|
@ -183,8 +182,6 @@ export async function fetchActorsById(actorIds, options = {}, reqUser) {
|
||||||
});
|
});
|
||||||
}).filter(Boolean);
|
}).filter(Boolean);
|
||||||
|
|
||||||
console.log(curatedActors);
|
|
||||||
|
|
||||||
return curatedActors;
|
return curatedActors;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -448,11 +445,16 @@ export async function fetchActorRevisions(revisionId, filters = {}, reqUser) {
|
||||||
.limit(limit)
|
.limit(limit)
|
||||||
.offset((page - 1) * limit);
|
.offset((page - 1) * limit);
|
||||||
|
|
||||||
|
const avatarIds = Array.from(new Set(revisions.flatMap((revision) => [revision.base.avatar, revision.deltas.find((delta) => delta.key === 'avatar')?.value]))).filter(Boolean);
|
||||||
|
const avatarEntries = await knex('media').whereIn('id', avatarIds);
|
||||||
|
const avatars = avatarEntries.map((avatar) => curateMedia(avatar));
|
||||||
|
|
||||||
const curatedRevisions = revisions.map((revision) => curateRevision(revision));
|
const curatedRevisions = revisions.map((revision) => curateRevision(revision));
|
||||||
|
|
||||||
return {
|
return {
|
||||||
revisions: curatedRevisions,
|
revisions: curatedRevisions,
|
||||||
revision: revisionId && curatedRevisions.find((revision) => revision.id === revisionId),
|
revision: revisionId && curatedRevisions.find((revision) => revision.id === revisionId),
|
||||||
|
avatars,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -483,8 +485,6 @@ const keyMap = {
|
||||||
};
|
};
|
||||||
|
|
||||||
async function applyActorValueDelta(profileId, delta, trx) {
|
async function applyActorValueDelta(profileId, delta, trx) {
|
||||||
console.log('value delta', profileId, delta, keyMap[delta.key], delta.value);
|
|
||||||
|
|
||||||
return knex('actors_profiles')
|
return knex('actors_profiles')
|
||||||
.where('id', profileId)
|
.where('id', profileId)
|
||||||
.update(keyMap[delta.key] || delta.key, delta.value)
|
.update(keyMap[delta.key] || delta.key, delta.value)
|
||||||
|
@ -492,8 +492,6 @@ async function applyActorValueDelta(profileId, delta, trx) {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function applyActorDirectDelta(actorId, delta, trx) {
|
async function applyActorDirectDelta(actorId, delta, trx) {
|
||||||
console.log('value delta', delta);
|
|
||||||
|
|
||||||
return knex('actors')
|
return knex('actors')
|
||||||
.where('id', actorId)
|
.where('id', actorId)
|
||||||
.update(keyMap[delta.key] || delta.key, delta.value)
|
.update(keyMap[delta.key] || delta.key, delta.value)
|
||||||
|
@ -601,6 +599,7 @@ async function applyActorRevision(revisionIds, reqUser) {
|
||||||
'tattoos',
|
'tattoos',
|
||||||
'hasPiercings',
|
'hasPiercings',
|
||||||
'piercings',
|
'piercings',
|
||||||
|
'agency',
|
||||||
].includes(delta.key)) {
|
].includes(delta.key)) {
|
||||||
return applyActorValueDelta(mainProfile.id, delta, trx);
|
return applyActorValueDelta(mainProfile.id, delta, trx);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue