|
|
|
@@ -7,12 +7,12 @@
|
|
|
|
|
<template v-if="apply">Your revision has been submitted. Thank you for your contribution!</template>
|
|
|
|
|
<template v-else>Your revision has been submitted for review. Thank you for your contribution!</template>
|
|
|
|
|
|
|
|
|
|
<ul>
|
|
|
|
|
<ul v-if="actor">
|
|
|
|
|
<li>
|
|
|
|
|
<a
|
|
|
|
|
:href="`/actor/${actor.id}/${actor.slug}`"
|
|
|
|
|
class="link"
|
|
|
|
|
>Return to actor</a>
|
|
|
|
|
>{{ creating ? 'Go' : 'Return' }} to actor</a>
|
|
|
|
|
</li>
|
|
|
|
|
|
|
|
|
|
<li>
|
|
|
|
@@ -22,21 +22,21 @@
|
|
|
|
|
>Make another edit</a>
|
|
|
|
|
</li>
|
|
|
|
|
|
|
|
|
|
<li>
|
|
|
|
|
<li v-if="!creating">
|
|
|
|
|
<a
|
|
|
|
|
:href="`/actor/revs/${actor.id}/${actor.slug}`"
|
|
|
|
|
class="link"
|
|
|
|
|
>Go to actor revisions</a>
|
|
|
|
|
</li>
|
|
|
|
|
|
|
|
|
|
<li>
|
|
|
|
|
<li v-if="!creating">
|
|
|
|
|
<a
|
|
|
|
|
:href="`/user/${user.username}/revisions/actors`"
|
|
|
|
|
class="link"
|
|
|
|
|
>Go to user revisions</a>
|
|
|
|
|
</li>
|
|
|
|
|
|
|
|
|
|
<li v-if="user.role !== 'user'">
|
|
|
|
|
<li v-if="user.role !== 'user' && !creating">
|
|
|
|
|
<a
|
|
|
|
|
href="/admin/revisions/actors"
|
|
|
|
|
class="link"
|
|
|
|
@@ -49,7 +49,10 @@
|
|
|
|
|
v-else
|
|
|
|
|
@submit.prevent
|
|
|
|
|
>
|
|
|
|
|
<div class="editor-header">
|
|
|
|
|
<div
|
|
|
|
|
v-if="actor"
|
|
|
|
|
class="editor-header"
|
|
|
|
|
>
|
|
|
|
|
<h2 class="heading ellipsis">Edit actor #{{ actor.id }} - {{ actor.name }}</h2>
|
|
|
|
|
|
|
|
|
|
<a
|
|
|
|
@@ -59,6 +62,13 @@
|
|
|
|
|
>Go to actor</a>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div
|
|
|
|
|
v-else
|
|
|
|
|
class="editor-header"
|
|
|
|
|
>
|
|
|
|
|
<h2 class="heading ellipsis">Add actor</h2>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<ul class="nolist">
|
|
|
|
|
<li
|
|
|
|
|
v-for="item in fields"
|
|
|
|
@@ -281,6 +291,7 @@
|
|
|
|
|
</select>
|
|
|
|
|
|
|
|
|
|
<input
|
|
|
|
|
v-if="item.hasDescription !== false"
|
|
|
|
|
v-model="edits[item.key].description"
|
|
|
|
|
class="description input"
|
|
|
|
|
placeholder="Description"
|
|
|
|
@@ -317,7 +328,7 @@
|
|
|
|
|
|
|
|
|
|
<div class="editor-actions">
|
|
|
|
|
<Checkbox
|
|
|
|
|
v-if="user.role !== 'user'"
|
|
|
|
|
v-if="user.role !== 'user' && actor"
|
|
|
|
|
label="Approve and apply immediately"
|
|
|
|
|
:checked="apply"
|
|
|
|
|
:disabled="editing.size === 0"
|
|
|
|
@@ -346,6 +357,7 @@
|
|
|
|
|
<script setup>
|
|
|
|
|
import { ref, computed, inject } from 'vue';
|
|
|
|
|
import { format } from 'date-fns';
|
|
|
|
|
import omit from 'object.omit';
|
|
|
|
|
|
|
|
|
|
import EditSocials from '#/components/edit/socials.vue';
|
|
|
|
|
import EditPlace from '#/components/edit/place.vue';
|
|
|
|
@@ -361,13 +373,15 @@ import {
|
|
|
|
|
post,
|
|
|
|
|
} from '#/src/api.js';
|
|
|
|
|
|
|
|
|
|
import events from '#/src/events.js';
|
|
|
|
|
|
|
|
|
|
const pageContext = inject('pageContext');
|
|
|
|
|
|
|
|
|
|
const user = pageContext.user;
|
|
|
|
|
const actor = ref(pageContext.pageProps.actor);
|
|
|
|
|
const actor = ref(pageContext.pageProps.actor || null);
|
|
|
|
|
|
|
|
|
|
const fields = computed(() => [
|
|
|
|
|
...(actor.value.photos.length > 0 ? [{
|
|
|
|
|
...(actor.value?.photos.length > 0 ? [{
|
|
|
|
|
key: 'avatar',
|
|
|
|
|
type: 'avatar',
|
|
|
|
|
value: actor.value.avatar?.id,
|
|
|
|
@@ -377,13 +391,13 @@ const fields = computed(() => [
|
|
|
|
|
? [{
|
|
|
|
|
key: 'name',
|
|
|
|
|
type: 'string',
|
|
|
|
|
value: actor.value.name,
|
|
|
|
|
value: actor.value?.name,
|
|
|
|
|
}]
|
|
|
|
|
: []),
|
|
|
|
|
{
|
|
|
|
|
key: 'gender',
|
|
|
|
|
type: 'select',
|
|
|
|
|
value: actor.value.gender,
|
|
|
|
|
value: actor.value?.gender || null,
|
|
|
|
|
options: [null, 'female', 'male', 'transsexual', 'other'],
|
|
|
|
|
inline: true,
|
|
|
|
|
},
|
|
|
|
@@ -391,7 +405,7 @@ const fields = computed(() => [
|
|
|
|
|
key: 'dateOfBirth',
|
|
|
|
|
label: 'date of birth',
|
|
|
|
|
type: 'date',
|
|
|
|
|
value: actor.value.dateOfBirth
|
|
|
|
|
value: actor.value?.dateOfBirth
|
|
|
|
|
? format(actor.value.dateOfBirth, 'yyyy-MM-dd')
|
|
|
|
|
: null,
|
|
|
|
|
inline: true,
|
|
|
|
@@ -399,28 +413,28 @@ const fields = computed(() => [
|
|
|
|
|
{
|
|
|
|
|
key: 'socials',
|
|
|
|
|
type: 'socials',
|
|
|
|
|
value: actor.value.socials,
|
|
|
|
|
value: actor.value?.socials || [],
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
key: 'origin',
|
|
|
|
|
type: 'place',
|
|
|
|
|
value: {
|
|
|
|
|
country: actor.value.origin?.country?.alpha2 || null,
|
|
|
|
|
place: [actor.value.origin?.city, actor.value.origin?.state].filter(Boolean).join(', '),
|
|
|
|
|
country: actor.value?.origin?.country?.alpha2 || null,
|
|
|
|
|
place: [actor.value?.origin?.city, actor.value?.origin?.state].filter(Boolean).join(', '),
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
key: 'residence',
|
|
|
|
|
type: 'place',
|
|
|
|
|
value: {
|
|
|
|
|
country: actor.value.residence?.country?.alpha2 || null,
|
|
|
|
|
place: [actor.value.residence?.city, actor.value.residence?.state].filter(Boolean).join(', '),
|
|
|
|
|
country: actor.value?.residence?.country?.alpha2 || null,
|
|
|
|
|
place: [actor.value?.residence?.city, actor.value?.residence?.state].filter(Boolean).join(', '),
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
key: 'ethnicity',
|
|
|
|
|
type: 'string',
|
|
|
|
|
value: actor.value.ethnicity,
|
|
|
|
|
value: actor.value?.ethnicity || null,
|
|
|
|
|
suggestions: [
|
|
|
|
|
'Asian',
|
|
|
|
|
'Black',
|
|
|
|
@@ -433,20 +447,20 @@ const fields = computed(() => [
|
|
|
|
|
key: 'size',
|
|
|
|
|
type: 'size',
|
|
|
|
|
value: {
|
|
|
|
|
metricHeight: actor.value.height?.metric,
|
|
|
|
|
metricWeight: actor.value.weight?.metric,
|
|
|
|
|
imperialHeight: actor.value.height?.imperial || [],
|
|
|
|
|
imperialWeight: actor.value.weight?.imperial,
|
|
|
|
|
metricHeight: actor.value?.height?.metric || null,
|
|
|
|
|
metricWeight: actor.value?.weight?.metric || null,
|
|
|
|
|
imperialHeight: actor.value?.height?.imperial || [],
|
|
|
|
|
imperialWeight: actor.value?.weight?.imperial || null,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
key: 'figure',
|
|
|
|
|
type: 'figure',
|
|
|
|
|
value: {
|
|
|
|
|
bust: actor.value.bust,
|
|
|
|
|
cup: actor.value.cup,
|
|
|
|
|
waist: actor.value.waist,
|
|
|
|
|
hip: actor.value.hip,
|
|
|
|
|
bust: actor.value?.bust || null,
|
|
|
|
|
cup: actor.value?.cup || null,
|
|
|
|
|
waist: actor.value?.waist || null,
|
|
|
|
|
hip: actor.value?.hip || null,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
@@ -454,25 +468,25 @@ const fields = computed(() => [
|
|
|
|
|
type: 'augmentation',
|
|
|
|
|
note: 'Provide explicit evidence, such as social media posts, visible scarring, or before/after. Avoid "it\'s obvious".',
|
|
|
|
|
value: {
|
|
|
|
|
naturalBoobs: actor.value.naturalBoobs,
|
|
|
|
|
boobsVolume: actor.value.boobsVolume,
|
|
|
|
|
boobsImplant: actor.value.boobsImplant,
|
|
|
|
|
boobsPlacement: actor.value.boobsPlacement,
|
|
|
|
|
boobsIncision: actor.value.boobsIncision,
|
|
|
|
|
boobsSurgeon: actor.value.boobsSurgeon,
|
|
|
|
|
naturalButt: actor.value.naturalButt,
|
|
|
|
|
buttVolume: actor.value.buttVolume,
|
|
|
|
|
buttImplant: actor.value.buttImplant,
|
|
|
|
|
naturalLips: actor.value.naturalLips,
|
|
|
|
|
lipsVolume: actor.value.lipsVolume,
|
|
|
|
|
naturalLabia: actor.value.naturalLabia,
|
|
|
|
|
naturalBoobs: actor.value?.naturalBoobs || null,
|
|
|
|
|
boobsVolume: actor.value?.boobsVolume || null,
|
|
|
|
|
boobsImplant: actor.value?.boobsImplant || null,
|
|
|
|
|
boobsPlacement: actor.value?.boobsPlacement || null,
|
|
|
|
|
boobsIncision: actor.value?.boobsIncision || null,
|
|
|
|
|
boobsSurgeon: actor.value?.boobsSurgeon || null,
|
|
|
|
|
naturalButt: actor.value?.naturalButt || null,
|
|
|
|
|
buttVolume: actor.value?.buttVolume || null,
|
|
|
|
|
buttImplant: actor.value?.buttImplant || null,
|
|
|
|
|
naturalLips: actor.value?.naturalLips || null,
|
|
|
|
|
lipsVolume: actor.value?.lipsVolume || null,
|
|
|
|
|
naturalLabia: actor.value?.naturalLabia || null,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
key: 'hairColor',
|
|
|
|
|
label: 'hair color',
|
|
|
|
|
type: 'select',
|
|
|
|
|
value: actor.value.hairColor,
|
|
|
|
|
value: actor.value?.hairColor || null,
|
|
|
|
|
options: [
|
|
|
|
|
null,
|
|
|
|
|
'black',
|
|
|
|
@@ -491,7 +505,7 @@ const fields = computed(() => [
|
|
|
|
|
key: 'eyes',
|
|
|
|
|
label: 'eye color',
|
|
|
|
|
type: 'select',
|
|
|
|
|
value: actor.value.eyes,
|
|
|
|
|
value: actor.value?.eyes || null,
|
|
|
|
|
options: [
|
|
|
|
|
null,
|
|
|
|
|
'blue',
|
|
|
|
@@ -506,8 +520,8 @@ const fields = computed(() => [
|
|
|
|
|
key: 'tattoos',
|
|
|
|
|
type: 'has',
|
|
|
|
|
value: {
|
|
|
|
|
has: actor.value.hasTattoos,
|
|
|
|
|
description: actor.value.tattoos,
|
|
|
|
|
has: actor.value?.hasTattoos || null,
|
|
|
|
|
description: actor.value?.tattoos || null,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
@@ -515,14 +529,14 @@ const fields = computed(() => [
|
|
|
|
|
type: 'has',
|
|
|
|
|
note: 'Excludes earrings',
|
|
|
|
|
value: {
|
|
|
|
|
has: actor.value.hasPiercings,
|
|
|
|
|
description: actor.value.piercings,
|
|
|
|
|
has: actor.value?.hasPiercings || null,
|
|
|
|
|
description: actor.value?.piercings || null,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
key: 'agency',
|
|
|
|
|
type: 'string',
|
|
|
|
|
value: actor.value.agency,
|
|
|
|
|
value: actor.value?.agency || null,
|
|
|
|
|
suggestions: [
|
|
|
|
|
'101 Modeling',
|
|
|
|
|
'Adult Talent Managers (ATMLA)',
|
|
|
|
@@ -540,25 +554,41 @@ const fields = computed(() => [
|
|
|
|
|
key: 'penis',
|
|
|
|
|
type: 'penis',
|
|
|
|
|
value: {
|
|
|
|
|
metricLength: actor.value.penisLength?.metric,
|
|
|
|
|
metricGirth: actor.value.penisGirth?.metric,
|
|
|
|
|
imperialLength: actor.value.penisLength?.imperial,
|
|
|
|
|
imperialGirth: actor.value.penisGirth?.imperial,
|
|
|
|
|
isCircumcised: actor.value.isCircumcised,
|
|
|
|
|
metricLength: actor.value?.penisLength?.metric || null,
|
|
|
|
|
metricGirth: actor.value?.penisGirth?.metric || null,
|
|
|
|
|
imperialLength: actor.value?.penisLength?.imperial || null,
|
|
|
|
|
imperialGirth: actor.value?.penisGirth?.imperial || null,
|
|
|
|
|
isCircumcised: actor.value?.isCircumcised || null,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
key: 'dateOfDeath',
|
|
|
|
|
label: 'date of death',
|
|
|
|
|
type: 'date',
|
|
|
|
|
value: actor.value.dateOfDeath
|
|
|
|
|
value: actor.value?.dateOfDeath
|
|
|
|
|
? format(actor.value.dateOfDeath, 'yyyy-MM-dd')
|
|
|
|
|
: null,
|
|
|
|
|
},
|
|
|
|
|
]);
|
|
|
|
|
{
|
|
|
|
|
key: 'allowGlobalMatch',
|
|
|
|
|
label: 'global match',
|
|
|
|
|
type: 'has',
|
|
|
|
|
note: 'Allow this actor to be assigned to scenes automatically, overriding single-name protections.',
|
|
|
|
|
hasDescription: false,
|
|
|
|
|
value: {
|
|
|
|
|
has: actor.value?.isGlobal || null,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
]
|
|
|
|
|
.filter((field) => (actor.value ? true : ['name', 'gender'].includes(field.key)))
|
|
|
|
|
.map((field) => ({
|
|
|
|
|
...field,
|
|
|
|
|
forced: true,
|
|
|
|
|
})));
|
|
|
|
|
|
|
|
|
|
const editing = ref(new Set());
|
|
|
|
|
const editing = ref(new Set(actor.value ? [] : ['name', 'gender']));
|
|
|
|
|
const edits = ref(Object.fromEntries(fields.value.map((field) => [field.key, field.value])));
|
|
|
|
|
const creating = !actor.value;
|
|
|
|
|
const comment = ref(null);
|
|
|
|
|
const apply = ref(user.role !== 'user');
|
|
|
|
|
const submitting = ref(false);
|
|
|
|
@@ -609,13 +639,54 @@ const groupMap = {
|
|
|
|
|
weight: 'size',
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
async function submitCreate() {
|
|
|
|
|
submitting.value = true;
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
const newActor = {
|
|
|
|
|
actor: Object.fromEntries(Array.from(['name', 'gender']).flatMap((key) => {
|
|
|
|
|
if (!edits.value[key]) {
|
|
|
|
|
throw new Error(`Missing ${key}`);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (edits.value[key] && typeof edits.value[key] === 'object' && !Array.isArray(edits.value[key])) {
|
|
|
|
|
return Object.entries(edits.value[key]).map(([valueKey, value]) => [keyMap[key]?.[valueKey] || valueKey, value]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return [[key, edits.value[key]]];
|
|
|
|
|
})),
|
|
|
|
|
comment: comment.value,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const { actor: createdActor } = await post('/actors', newActor, {
|
|
|
|
|
successFeedback: 'Actor has been added.',
|
|
|
|
|
appendErrorMessage: true,
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
actor.value = createdActor;
|
|
|
|
|
} catch (error) {
|
|
|
|
|
events.emit('feedback', {
|
|
|
|
|
type: 'error',
|
|
|
|
|
message: error.message,
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
submitting.value = false;
|
|
|
|
|
submitted.value = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function submit() {
|
|
|
|
|
if (!actor.value) {
|
|
|
|
|
submitCreate();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
submitting.value = true;
|
|
|
|
|
|
|
|
|
|
await post('/revisions/actors', {
|
|
|
|
|
actorId: actor.value.id,
|
|
|
|
|
edits: {
|
|
|
|
|
edits: omit({
|
|
|
|
|
...Object.fromEntries(Array.from(editing.value).flatMap((key) => {
|
|
|
|
|
if (edits.value[key] && typeof edits.value[key] === 'object' && !Array.isArray(edits.value[key])) {
|
|
|
|
|
return Object.entries(edits.value[key]).map(([valueKey, value]) => [keyMap[key]?.[valueKey] || valueKey, value]);
|
|
|
|
@@ -629,15 +700,16 @@ async function submit() {
|
|
|
|
|
penisLength: penisUnits.value === 'imperial' ? edits.value.penis.imperialLength : edits.value.penis.metricLength,
|
|
|
|
|
penisGirth: penisUnits.value === 'imperial' ? edits.value.penis.imperialGirth : edits.value.penis.metricGirth,
|
|
|
|
|
}).filter(([key]) => editing.value.has(groupMap[key] || key))),
|
|
|
|
|
metricHeight: undefined,
|
|
|
|
|
metricWeight: undefined,
|
|
|
|
|
imperialHeight: undefined,
|
|
|
|
|
imperialWeight: undefined,
|
|
|
|
|
metricLength: undefined,
|
|
|
|
|
metricGirth: undefined,
|
|
|
|
|
imperialLength: undefined,
|
|
|
|
|
imperialGirth: undefined,
|
|
|
|
|
},
|
|
|
|
|
}, [
|
|
|
|
|
'metricHeight',
|
|
|
|
|
'metricWeight',
|
|
|
|
|
'imperialHeight',
|
|
|
|
|
'imperialWeight',
|
|
|
|
|
'metricLength',
|
|
|
|
|
'metricGirth',
|
|
|
|
|
'imperialLength',
|
|
|
|
|
'imperialGirth',
|
|
|
|
|
]),
|
|
|
|
|
sizeUnits: sizeUnits.value,
|
|
|
|
|
figureUnits: figureUnits.value,
|
|
|
|
|
penisUnits: penisUnits.value,
|