Added actor creation page.
This commit is contained in:
@@ -1 +0,0 @@
|
||||
export default '/actor/edit/@actorId/*';
|
||||
@@ -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,
|
||||
34
pages/actors/edit/+onBeforeRender.js
Normal file
34
pages/actors/edit/+onBeforeRender.js
Normal file
@@ -0,0 +1,34 @@
|
||||
import { redirect } from 'vike/abort'; /* eslint-disable-line import/extensions */
|
||||
|
||||
import { fetchActorsById } from '#/src/actors.js';
|
||||
import { fetchCountries } from '#/src/countries.js';
|
||||
|
||||
export async function onBeforeRender(pageContext) {
|
||||
if (!pageContext.user) {
|
||||
throw redirect(`/login?r=${encodeURIComponent(pageContext.urlOriginal)}`);
|
||||
}
|
||||
|
||||
const [actor] = pageContext.routeParams.actorId
|
||||
? await fetchActorsById([Number(pageContext.routeParams.actorId)], {}, pageContext.user)
|
||||
: [];
|
||||
|
||||
const countries = await fetchCountries();
|
||||
|
||||
/*
|
||||
if (!actor) {
|
||||
throw render(404, `Cannot find actor '${pageContext.routeParams.actorId}'.`);
|
||||
}
|
||||
*/
|
||||
|
||||
return {
|
||||
pageContext: {
|
||||
title: actor
|
||||
? `Editing '${actor.name}'`
|
||||
: 'Adding actor',
|
||||
pageProps: {
|
||||
actor,
|
||||
countries,
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
20
pages/actors/edit/+route.js
Normal file
20
pages/actors/edit/+route.js
Normal file
@@ -0,0 +1,20 @@
|
||||
// export default '/actor/edit/@actorId/*';
|
||||
// import { redirect } from 'vike/abort'; /* eslint-disable-line import/extensions */
|
||||
import { match } from 'path-to-regexp';
|
||||
|
||||
const path = '/actor/(edit|new)/:actorId?/:actorSlug?';
|
||||
const urlMatch = match(path, { decode: decodeURIComponent });
|
||||
|
||||
export default (pageContext) => {
|
||||
const matched = urlMatch(pageContext.urlPathname);
|
||||
|
||||
if (matched) {
|
||||
return {
|
||||
routeParams: matched.params.actorId ? {
|
||||
actorId: matched.params.actorId,
|
||||
} : {},
|
||||
};
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
Reference in New Issue
Block a user