Upgraded dependencies, bumped to Node 24.
This commit is contained in:
@@ -1,13 +1,13 @@
|
||||
<script setup>
|
||||
import Actors from '#/components/actors/actors.vue';
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="page">
|
||||
<Actors />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import Actors from '#/components/actors/actors.vue';
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.page {
|
||||
display: flex;
|
||||
|
||||
@@ -1,3 +1,28 @@
|
||||
<script setup>
|
||||
import { inject, useId } from 'vue';
|
||||
|
||||
import Bio from '#/components/actors/bio.vue';
|
||||
|
||||
import Gender from '#/components/actors/gender.vue';
|
||||
import Domains from '#/components/domains/domains.vue';
|
||||
import Movies from '#/components/movies/movies.vue';
|
||||
import Scenes from '#/components/scenes/scenes.vue';
|
||||
import Heart from '#/components/stashes/heart.vue';
|
||||
import getPath from '#/src/get-path.js';
|
||||
|
||||
const pageContext = inject('pageContext');
|
||||
const { pageProps, routeParams } = pageContext;
|
||||
const { actor } = pageProps;
|
||||
|
||||
const domain = routeParams.domain;
|
||||
|
||||
const badCredits = ['Pierre Woodman']; // consistently horrible photos
|
||||
const photos = actor.photos.filter((photo) => photo.entropy > 5.5 && !badCredits.includes(photo.credit));
|
||||
const aliasTooltipId = useId();
|
||||
|
||||
console.log(actor);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="actor">
|
||||
<div class="actor-header">
|
||||
@@ -5,6 +30,17 @@
|
||||
<span v-if="actor.entity">{{ actor.name }} ({{ actor.entity.name }})</span>
|
||||
<span v-else>{{ actor.name }}</span>
|
||||
|
||||
<a
|
||||
v-if="actor.alias"
|
||||
v-tooltip="{ content: `Alias for ${actor.alias.name} (#${actor.alias.id})`, ariaId: aliasTooltipId }"
|
||||
:href="`/actor/${actor.alias.id}/${actor.alias.slug}`"
|
||||
>
|
||||
<Icon
|
||||
icon="at-sign"
|
||||
class="header-alias"
|
||||
/>
|
||||
</a>
|
||||
|
||||
<Gender
|
||||
:gender="actor.gender"
|
||||
class="header-gender"
|
||||
@@ -61,28 +97,6 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { inject } from 'vue';
|
||||
|
||||
import getPath from '#/src/get-path.js';
|
||||
|
||||
import Bio from '#/components/actors/bio.vue';
|
||||
import Gender from '#/components/actors/gender.vue';
|
||||
import Scenes from '#/components/scenes/scenes.vue';
|
||||
import Movies from '#/components/movies/movies.vue';
|
||||
import Heart from '#/components/stashes/heart.vue';
|
||||
import Domains from '#/components/domains/domains.vue';
|
||||
|
||||
const pageContext = inject('pageContext');
|
||||
const { pageProps, routeParams } = pageContext;
|
||||
const { actor } = pageProps;
|
||||
|
||||
const domain = routeParams.domain;
|
||||
|
||||
const badCredits = ['Pierre Woodman']; // consistently horrible photos
|
||||
const photos = actor.photos.filter((photo) => photo.entropy > 5.5 && !badCredits.includes(photo.credit));
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.actor {
|
||||
display: flex;
|
||||
@@ -111,6 +125,14 @@ const photos = actor.photos.filter((photo) => photo.entropy > 5.5 && !badCredits
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.header-alias.icon {
|
||||
height: 1.75rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0 1rem;
|
||||
fill: var(--primary);
|
||||
}
|
||||
|
||||
.header-social {
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import { redirect, render } from 'vike/abort'; /* eslint-disable-line import/extensions */
|
||||
import { redirect, render } from 'vike/abort';
|
||||
|
||||
import { fetchActorsById } from '#/src/actors.js';
|
||||
import { fetchScenes } from '#/src/scenes.js';
|
||||
import { fetchMovies } from '#/src/movies.js';
|
||||
import { curateScenesQuery } from '#/src/web/scenes.js';
|
||||
import { curateMoviesQuery } from '#/src/web/movies.js';
|
||||
import { getCampaignIndex, getRandomCampaigns } from '#/src/campaigns.js';
|
||||
import { fetchCountries } from '#/src/countries.js';
|
||||
import { getRandomCampaigns, getCampaignIndex } from '#/src/campaigns.js';
|
||||
import { fetchMovies } from '#/src/movies.js';
|
||||
import { fetchScenes } from '#/src/scenes.js';
|
||||
import { curateMoviesQuery } from '#/src/web/movies.js';
|
||||
import { curateScenesQuery } from '#/src/web/scenes.js';
|
||||
|
||||
async function fetchReleases(pageContext) {
|
||||
if (pageContext.routeParams.domain === 'movies') {
|
||||
@@ -47,10 +47,6 @@ export async function onBeforeRender(pageContext) {
|
||||
throw render(404, `Cannot find actor '${pageContext.routeParams.actorId}'.`);
|
||||
}
|
||||
|
||||
if (actor.alias && !Object.hasOwn(pageContext.urlParsed.search, 'inspect')) {
|
||||
throw redirect(`/actor/${actor.alias.id}/${actor.alias.slug}`);
|
||||
}
|
||||
|
||||
const [actorReleases, campaigns, countries] = await Promise.all([
|
||||
fetchReleases(pageContext),
|
||||
getRandomCampaigns([
|
||||
@@ -63,6 +59,10 @@ export async function onBeforeRender(pageContext) {
|
||||
isEditing && fetchCountries(),
|
||||
]);
|
||||
|
||||
if (actor.alias && actorReleases.length === 0 && !Object.hasOwn(pageContext.urlParsed.search, 'inspect')) {
|
||||
throw redirect(`/actor/${actor.alias.id}/${actor.alias.slug}`);
|
||||
}
|
||||
|
||||
const campaignIndex = getCampaignIndex(actorReleases.limit);
|
||||
const [paginationCampaign, sceneCampaign] = campaigns;
|
||||
|
||||
|
||||
@@ -1,3 +1,12 @@
|
||||
<script setup>
|
||||
import { inject } from 'vue';
|
||||
|
||||
import Revisions from '#/components/edit/revisions.vue';
|
||||
|
||||
const pageContext = inject('pageContext');
|
||||
const actor = pageContext.pageProps.actor;
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="content">
|
||||
<div class="revs-header">
|
||||
@@ -21,15 +30,6 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { inject } from 'vue';
|
||||
|
||||
import Revisions from '#/components/edit/revisions.vue';
|
||||
|
||||
const pageContext = inject('pageContext');
|
||||
const actor = pageContext.pageProps.actor;
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.content {
|
||||
padding: 1rem;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { fetchActorsById, fetchActorRevisions } from '#/src/actors.js';
|
||||
import { fetchActorRevisions, fetchActorsById } from '#/src/actors.js';
|
||||
|
||||
export async function onBeforeRender(pageContext) {
|
||||
const [actor] = await fetchActorsById([Number(pageContext.routeParams.actorId)], {}, pageContext.user);
|
||||
|
||||
@@ -1,388 +1,17 @@
|
||||
<template>
|
||||
<div class="editor">
|
||||
<p
|
||||
v-if="submitted"
|
||||
class="submitted"
|
||||
>
|
||||
<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 v-if="actor">
|
||||
<li>
|
||||
<a
|
||||
:href="`/actor/${actor.id}/${actor.slug}`"
|
||||
class="link"
|
||||
>{{ creating ? 'Go' : 'Return' }} to actor</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a
|
||||
:href="`/actor/edit/${actor.id}`"
|
||||
class="link"
|
||||
>Make another edit</a>
|
||||
</li>
|
||||
|
||||
<li v-if="!creating">
|
||||
<a
|
||||
:href="`/actor/revs/${actor.id}/${actor.slug}`"
|
||||
class="link"
|
||||
>Go to actor revisions</a>
|
||||
</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' && !creating">
|
||||
<a
|
||||
href="/admin/revisions/actors"
|
||||
class="link"
|
||||
>Go to revisions admin</a>
|
||||
</li>
|
||||
</ul>
|
||||
</p>
|
||||
|
||||
<form
|
||||
v-else
|
||||
@submit.prevent
|
||||
>
|
||||
<div
|
||||
v-if="actor"
|
||||
class="editor-header"
|
||||
>
|
||||
<h2 class="heading ellipsis">Edit actor #{{ actor.id }} - {{ actor.name }}</h2>
|
||||
|
||||
<span class="header-actions">
|
||||
<span
|
||||
v-if="verifyAbility(user, 'actor', 'merge')"
|
||||
target="_blank"
|
||||
class="link noshrink"
|
||||
@click="showMergeDialog = true"
|
||||
>Merge</span>
|
||||
|
||||
<Merge
|
||||
v-if="showMergeDialog"
|
||||
:actors="[actor]"
|
||||
@close="showMergeDialog = false"
|
||||
/>
|
||||
|
||||
<a
|
||||
:href="`/actor/${actor.id}/${actor.slug}`"
|
||||
target="_blank"
|
||||
class="link noshrink"
|
||||
>Go to actor</a>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-else
|
||||
class="editor-header"
|
||||
>
|
||||
<h2 class="heading ellipsis">Add actor</h2>
|
||||
</div>
|
||||
|
||||
<ul class="nolist">
|
||||
<li
|
||||
v-for="item in fields"
|
||||
:key="`item-${item.key}`"
|
||||
class="row"
|
||||
>
|
||||
<div class="item-header">
|
||||
<div class="key">
|
||||
{{ item.label || item.key }}
|
||||
|
||||
<Icon
|
||||
v-if="item.note"
|
||||
v-tooltip="item.note"
|
||||
icon="info2"
|
||||
class="item-note"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="item-actions noselect">
|
||||
<Icon
|
||||
v-if="!item.forced"
|
||||
icon="pencil5"
|
||||
:class="{ active: editing.has(item.key) }"
|
||||
@click="toggleField(item)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="value"
|
||||
:class="{ disabled: !editing.has(item.key) }"
|
||||
>
|
||||
<input
|
||||
v-if="item.type === 'string'"
|
||||
v-model="edits[item.key]"
|
||||
class="string input"
|
||||
:list="item.suggestions && `suggestions-${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
|
||||
v-if="item.type === 'text'"
|
||||
v-model="edits[item.key]"
|
||||
:placeholder="item.placeholder"
|
||||
rows="3"
|
||||
class="text input"
|
||||
:disabled="!editing.has(item.key)"
|
||||
/>
|
||||
|
||||
<template v-if="item.type === 'number'">
|
||||
<input
|
||||
v-model="edits[item.key]"
|
||||
type="number"
|
||||
:max="item.max"
|
||||
:min="item.min"
|
||||
class="number input"
|
||||
:disabled="!editing.has(item.key)"
|
||||
>{{ item.unit }}
|
||||
</template>
|
||||
|
||||
<input
|
||||
v-if="item.type === 'date'"
|
||||
v-model="edits[item.key]"
|
||||
type="date"
|
||||
class="date input"
|
||||
:disabled="!editing.has(item.key)"
|
||||
>
|
||||
|
||||
<select
|
||||
v-if="item.type === 'select'"
|
||||
v-model="edits[item.key]"
|
||||
class="select input"
|
||||
:disabled="!editing.has(item.key)"
|
||||
>
|
||||
<option
|
||||
v-for="option in item.options"
|
||||
:key="`${item.key}-option-${option}`"
|
||||
:value="typeof option?.value === 'undefined' ? option : option.value"
|
||||
>{{ option?.label || option }}</option>
|
||||
</select>
|
||||
|
||||
<div
|
||||
v-if="item.type === 'size'"
|
||||
class="figure size"
|
||||
>
|
||||
<div class="value-section">
|
||||
<span class="value-label">Units</span>
|
||||
|
||||
<select
|
||||
v-model="sizeUnits"
|
||||
class="input"
|
||||
:disabled="!editing.has(item.key)"
|
||||
>
|
||||
<option value="metric">Metric</option>
|
||||
<option value="imperial">Imperial</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<span class="figure-height">
|
||||
<div class="value-section">
|
||||
<span class="value-label">Height</span>
|
||||
|
||||
<span v-if="sizeUnits === 'metric'">
|
||||
<input
|
||||
v-model="edits[item.key].metricHeight"
|
||||
type="number"
|
||||
class="input"
|
||||
:disabled="!editing.has(item.key)"
|
||||
> cm
|
||||
</span>
|
||||
|
||||
<span v-if="sizeUnits === 'imperial'">
|
||||
<input
|
||||
v-model="edits[item.key].imperialHeight[0]"
|
||||
type="number"
|
||||
class="input"
|
||||
:disabled="!editing.has(item.key)"
|
||||
> ft
|
||||
|
||||
<input
|
||||
v-model="edits[item.key].imperialHeight[1]"
|
||||
type="number"
|
||||
class="input"
|
||||
:disabled="!editing.has(item.key)"
|
||||
> in
|
||||
</span>
|
||||
</div>
|
||||
</span>
|
||||
|
||||
<span class="figure-weight">
|
||||
<div class="value-section">
|
||||
<span class="value-label">Weight</span>
|
||||
|
||||
<span v-if="sizeUnits === 'metric'">
|
||||
<input
|
||||
v-model="edits[item.key].metricWeight"
|
||||
type="number"
|
||||
class="input"
|
||||
:disabled="!editing.has(item.key)"
|
||||
> kg
|
||||
</span>
|
||||
|
||||
<span v-if="sizeUnits === 'imperial'">
|
||||
<input
|
||||
v-model="edits[item.key].imperialWeight"
|
||||
type="number"
|
||||
class="input"
|
||||
:disabled="!editing.has(item.key)"
|
||||
>
|
||||
|
||||
<template v-if="sizeUnits === 'imperial'"> lbs</template>
|
||||
<template v-else> kg</template>
|
||||
</span>
|
||||
</div>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<EditSocials
|
||||
v-if="item.type === 'socials'"
|
||||
:edits="edits"
|
||||
:editing="editing"
|
||||
@socials="(socials) => edits.socials = socials"
|
||||
/>
|
||||
|
||||
<EditPlace
|
||||
v-if="item.type === 'place'"
|
||||
:item="item"
|
||||
:edits="edits"
|
||||
:editing="editing"
|
||||
@place="(place) => edits[item.key] = place"
|
||||
/>
|
||||
|
||||
<EditFigure
|
||||
v-if="item.type === 'figure'"
|
||||
:edits="edits"
|
||||
:editing="editing"
|
||||
:units="figureUnits"
|
||||
@figure="(figure) => edits.figure = figure"
|
||||
@units="(units) => figureUnits = units"
|
||||
/>
|
||||
|
||||
<EditAugmentation
|
||||
v-if="item.type === 'augmentation'"
|
||||
:edits="edits"
|
||||
:editing="editing"
|
||||
@augmentation="(augmentation) => edits.augmentation = augmentation"
|
||||
/>
|
||||
|
||||
<EditPenis
|
||||
v-if="item.type === 'penis'"
|
||||
:edits="edits"
|
||||
:editing="editing"
|
||||
:units="penisUnits"
|
||||
@penis="(penis) => edits.penis = penis"
|
||||
@units="(units) => penisUnits = units"
|
||||
/>
|
||||
|
||||
<div
|
||||
v-if="item.type === 'has'"
|
||||
class="has"
|
||||
>
|
||||
<select
|
||||
v-model="edits[item.key].has"
|
||||
class="select input"
|
||||
:disabled="!editing.has(item.key)"
|
||||
>
|
||||
<option :value="null" />
|
||||
<option :value="true">Yes</option>
|
||||
<option :value="false">No</option>
|
||||
</select>
|
||||
|
||||
<input
|
||||
v-if="item.hasDescription !== false"
|
||||
v-model="edits[item.key].description"
|
||||
class="description input"
|
||||
placeholder="Description"
|
||||
:disabled="!editing.has(item.key)"
|
||||
>
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-if="item.type === 'avatar'"
|
||||
class="avatars"
|
||||
:class="{ disabled: !editing.has(item.key) }"
|
||||
>
|
||||
<Avatar
|
||||
v-for="avatar in item.options"
|
||||
:key="`avatar-${avatar.id}`"
|
||||
:avatar="avatar"
|
||||
:class="{ selected: edits[item.key] === avatar.id }"
|
||||
@click="setAvatar(avatar.id)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div class="editor-footer">
|
||||
<div class="comment">
|
||||
<textarea
|
||||
v-model="comment"
|
||||
rows="3"
|
||||
placeholder="Please provide verifiable information and sources supporting your edits."
|
||||
class="text input noshrink"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="editor-actions">
|
||||
<Checkbox
|
||||
v-if="user.role !== 'user' && actor"
|
||||
label="Approve and apply immediately"
|
||||
:checked="apply"
|
||||
:disabled="editing.size === 0"
|
||||
@change="(checked) => apply = checked"
|
||||
/>
|
||||
|
||||
<Ellipsis v-if="submitting" />
|
||||
|
||||
<!-- we don't want the return key to submit the form -->
|
||||
<button
|
||||
v-else
|
||||
class="button button-primary"
|
||||
type="button"
|
||||
:disabled="editing.size === 0"
|
||||
@click="submit"
|
||||
>
|
||||
<template v-if="apply">Submit</template>
|
||||
<template v-else>Submit for review</template>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, computed, inject } from 'vue';
|
||||
import { format } from 'date-fns';
|
||||
import omit from 'object.omit';
|
||||
import { computed, inject, ref } from 'vue';
|
||||
|
||||
import EditSocials from '#/components/edit/socials.vue';
|
||||
import EditPlace from '#/components/edit/place.vue';
|
||||
import EditFigure from '#/components/edit/figure.vue';
|
||||
import Merge from '#/components/actors/merge.vue';
|
||||
import EditAugmentation from '#/components/edit/augmentation.vue';
|
||||
import EditPenis from '#/components/edit/penis.vue';
|
||||
import Avatar from '#/components/edit/avatar.vue';
|
||||
import EditFigure from '#/components/edit/figure.vue';
|
||||
import EditPenis from '#/components/edit/penis.vue';
|
||||
import EditPlace from '#/components/edit/place.vue';
|
||||
import EditSocials from '#/components/edit/socials.vue';
|
||||
import Checkbox from '#/components/form/checkbox.vue';
|
||||
import Ellipsis from '#/components/loading/ellipsis.vue';
|
||||
import Merge from '#/components/actors/merge.vue';
|
||||
|
||||
import {
|
||||
// get,
|
||||
@@ -397,18 +26,20 @@ const user = pageContext.user;
|
||||
const actor = ref(pageContext.pageProps.actor || null);
|
||||
|
||||
const fields = computed(() => [
|
||||
...(actor.value?.photos.length > 0 ? [{
|
||||
key: 'avatar',
|
||||
type: 'avatar',
|
||||
value: actor.value.avatar?.id,
|
||||
options: actor.value.photos,
|
||||
}] : []),
|
||||
...(actor.value?.photos.length > 0
|
||||
? [{
|
||||
key: 'avatar',
|
||||
type: 'avatar',
|
||||
value: actor.value.avatar?.id,
|
||||
options: actor.value.photos,
|
||||
}]
|
||||
: []),
|
||||
...(user.role === 'admin'
|
||||
? [{
|
||||
key: 'name',
|
||||
type: 'string',
|
||||
value: actor.value?.name,
|
||||
}]
|
||||
key: 'name',
|
||||
type: 'string',
|
||||
value: actor.value?.name,
|
||||
}]
|
||||
: []),
|
||||
{
|
||||
key: 'gender',
|
||||
@@ -707,12 +338,384 @@ async function submit() {
|
||||
submitted.value = true;
|
||||
|
||||
// actor.value = await get(`/actors/${actor.value.id}`);
|
||||
} catch (error) {
|
||||
}
|
||||
catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="editor">
|
||||
<p
|
||||
v-if="submitted"
|
||||
class="submitted"
|
||||
>
|
||||
<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 v-if="actor">
|
||||
<li>
|
||||
<a
|
||||
:href="`/actor/${actor.id}/${actor.slug}`"
|
||||
class="link"
|
||||
>{{ creating ? 'Go' : 'Return' }} to actor</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a
|
||||
:href="`/actor/edit/${actor.id}`"
|
||||
class="link"
|
||||
>Make another edit</a>
|
||||
</li>
|
||||
|
||||
<li v-if="!creating">
|
||||
<a
|
||||
:href="`/actor/revs/${actor.id}/${actor.slug}`"
|
||||
class="link"
|
||||
>Go to actor revisions</a>
|
||||
</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' && !creating">
|
||||
<a
|
||||
href="/admin/revisions/actors"
|
||||
class="link"
|
||||
>Go to revisions admin</a>
|
||||
</li>
|
||||
</ul>
|
||||
</p>
|
||||
|
||||
<form
|
||||
v-else
|
||||
@submit.prevent
|
||||
>
|
||||
<div
|
||||
v-if="actor"
|
||||
class="editor-header"
|
||||
>
|
||||
<h2 class="heading ellipsis">Edit actor #{{ actor.id }} - {{ actor.name }}</h2>
|
||||
|
||||
<span class="header-actions">
|
||||
<span
|
||||
v-if="verifyAbility(user, 'actor', 'merge')"
|
||||
target="_blank"
|
||||
class="link noshrink"
|
||||
@click="showMergeDialog = true"
|
||||
>Merge</span>
|
||||
|
||||
<Merge
|
||||
v-if="showMergeDialog"
|
||||
:actors="[actor]"
|
||||
@close="showMergeDialog = false"
|
||||
/>
|
||||
|
||||
<a
|
||||
:href="`/actor/${actor.id}/${actor.slug}`"
|
||||
target="_blank"
|
||||
class="link noshrink"
|
||||
>Go to actor</a>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-else
|
||||
class="editor-header"
|
||||
>
|
||||
<h2 class="heading ellipsis">Add actor</h2>
|
||||
</div>
|
||||
|
||||
<ul class="nolist">
|
||||
<li
|
||||
v-for="item in fields"
|
||||
:key="`item-${item.key}`"
|
||||
class="row"
|
||||
>
|
||||
<div class="item-header">
|
||||
<div class="key">
|
||||
{{ item.label || item.key }}
|
||||
|
||||
<Icon
|
||||
v-if="item.note"
|
||||
v-tooltip="{ content: item.note, ariaId: `field-note-${item.key}` }"
|
||||
icon="info2"
|
||||
class="item-note"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="item-actions noselect">
|
||||
<Icon
|
||||
v-if="!item.forced"
|
||||
icon="pencil5"
|
||||
:class="{ active: editing.has(item.key) }"
|
||||
@click="toggleField(item)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="value"
|
||||
:class="{ disabled: !editing.has(item.key) }"
|
||||
>
|
||||
<input
|
||||
v-if="item.type === 'string'"
|
||||
v-model="edits[item.key]"
|
||||
class="string input"
|
||||
:list="item.suggestions && `suggestions-${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
|
||||
v-if="item.type === 'text'"
|
||||
v-model="edits[item.key]"
|
||||
:placeholder="item.placeholder"
|
||||
rows="3"
|
||||
class="text input"
|
||||
:disabled="!editing.has(item.key)"
|
||||
/>
|
||||
|
||||
<template v-if="item.type === 'number'">
|
||||
<input
|
||||
v-model="edits[item.key]"
|
||||
type="number"
|
||||
:max="item.max"
|
||||
:min="item.min"
|
||||
class="number input"
|
||||
:disabled="!editing.has(item.key)"
|
||||
>{{ item.unit }}
|
||||
</template>
|
||||
|
||||
<input
|
||||
v-if="item.type === 'date'"
|
||||
v-model="edits[item.key]"
|
||||
type="date"
|
||||
class="date input"
|
||||
:disabled="!editing.has(item.key)"
|
||||
>
|
||||
|
||||
<select
|
||||
v-if="item.type === 'select'"
|
||||
v-model="edits[item.key]"
|
||||
class="select input"
|
||||
:disabled="!editing.has(item.key)"
|
||||
>
|
||||
<option
|
||||
v-for="option in item.options"
|
||||
:key="`${item.key}-option-${option}`"
|
||||
:value="typeof option?.value === 'undefined' ? option : option.value"
|
||||
>{{ option?.label || option }}</option>
|
||||
</select>
|
||||
|
||||
<div
|
||||
v-if="item.type === 'size'"
|
||||
class="figure size"
|
||||
>
|
||||
<div class="value-section">
|
||||
<span class="value-label">Units</span>
|
||||
|
||||
<select
|
||||
v-model="sizeUnits"
|
||||
class="input"
|
||||
:disabled="!editing.has(item.key)"
|
||||
>
|
||||
<option value="metric">Metric</option>
|
||||
<option value="imperial">Imperial</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<span class="figure-height">
|
||||
<div class="value-section">
|
||||
<span class="value-label">Height</span>
|
||||
|
||||
<span v-if="sizeUnits === 'metric'">
|
||||
<input
|
||||
v-model="edits[item.key].metricHeight"
|
||||
type="number"
|
||||
class="input"
|
||||
:disabled="!editing.has(item.key)"
|
||||
> cm
|
||||
</span>
|
||||
|
||||
<span v-if="sizeUnits === 'imperial'">
|
||||
<input
|
||||
v-model="edits[item.key].imperialHeight[0]"
|
||||
type="number"
|
||||
class="input"
|
||||
:disabled="!editing.has(item.key)"
|
||||
> ft
|
||||
|
||||
<input
|
||||
v-model="edits[item.key].imperialHeight[1]"
|
||||
type="number"
|
||||
class="input"
|
||||
:disabled="!editing.has(item.key)"
|
||||
> in
|
||||
</span>
|
||||
</div>
|
||||
</span>
|
||||
|
||||
<span class="figure-weight">
|
||||
<div class="value-section">
|
||||
<span class="value-label">Weight</span>
|
||||
|
||||
<span v-if="sizeUnits === 'metric'">
|
||||
<input
|
||||
v-model="edits[item.key].metricWeight"
|
||||
type="number"
|
||||
class="input"
|
||||
:disabled="!editing.has(item.key)"
|
||||
> kg
|
||||
</span>
|
||||
|
||||
<span v-if="sizeUnits === 'imperial'">
|
||||
<input
|
||||
v-model="edits[item.key].imperialWeight"
|
||||
type="number"
|
||||
class="input"
|
||||
:disabled="!editing.has(item.key)"
|
||||
>
|
||||
|
||||
<template v-if="sizeUnits === 'imperial'"> lbs</template>
|
||||
<template v-else> kg</template>
|
||||
</span>
|
||||
</div>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<EditSocials
|
||||
v-if="item.type === 'socials'"
|
||||
:edits="edits"
|
||||
:editing="editing"
|
||||
@socials="(socials) => edits.socials = socials"
|
||||
/>
|
||||
|
||||
<EditPlace
|
||||
v-if="item.type === 'place'"
|
||||
:item="item"
|
||||
:edits="edits"
|
||||
:editing="editing"
|
||||
@place="(place) => edits[item.key] = place"
|
||||
/>
|
||||
|
||||
<EditFigure
|
||||
v-if="item.type === 'figure'"
|
||||
:edits="edits"
|
||||
:editing="editing"
|
||||
:units="figureUnits"
|
||||
@figure="(figure) => edits.figure = figure"
|
||||
@units="(units) => figureUnits = units"
|
||||
/>
|
||||
|
||||
<EditAugmentation
|
||||
v-if="item.type === 'augmentation'"
|
||||
:edits="edits"
|
||||
:editing="editing"
|
||||
@augmentation="(augmentation) => edits.augmentation = augmentation"
|
||||
/>
|
||||
|
||||
<EditPenis
|
||||
v-if="item.type === 'penis'"
|
||||
:edits="edits"
|
||||
:editing="editing"
|
||||
:units="penisUnits"
|
||||
@penis="(penis) => edits.penis = penis"
|
||||
@units="(units) => penisUnits = units"
|
||||
/>
|
||||
|
||||
<div
|
||||
v-if="item.type === 'has'"
|
||||
class="has"
|
||||
>
|
||||
<select
|
||||
v-model="edits[item.key].has"
|
||||
class="select input"
|
||||
:disabled="!editing.has(item.key)"
|
||||
>
|
||||
<option :value="null" />
|
||||
<option :value="true">Yes</option>
|
||||
<option :value="false">No</option>
|
||||
</select>
|
||||
|
||||
<input
|
||||
v-if="item.hasDescription !== false"
|
||||
v-model="edits[item.key].description"
|
||||
class="description input"
|
||||
placeholder="Description"
|
||||
:disabled="!editing.has(item.key)"
|
||||
>
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-if="item.type === 'avatar'"
|
||||
class="avatars"
|
||||
:class="{ disabled: !editing.has(item.key) }"
|
||||
>
|
||||
<Avatar
|
||||
v-for="avatar in item.options"
|
||||
:key="`avatar-${avatar.id}`"
|
||||
:avatar="avatar"
|
||||
:class="{ selected: edits[item.key] === avatar.id }"
|
||||
@click="setAvatar(avatar.id)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div class="editor-footer">
|
||||
<div class="comment">
|
||||
<textarea
|
||||
v-model="comment"
|
||||
rows="3"
|
||||
placeholder="Please provide verifiable information and sources supporting your edits."
|
||||
class="text input noshrink"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="editor-actions">
|
||||
<Checkbox
|
||||
v-if="user.role !== 'user' && actor"
|
||||
label="Approve and apply immediately"
|
||||
:checked="apply"
|
||||
:disabled="editing.size === 0"
|
||||
@change="(checked) => apply = checked"
|
||||
/>
|
||||
|
||||
<Ellipsis v-if="submitting" />
|
||||
|
||||
<!-- we don't want the return key to submit the form -->
|
||||
<button
|
||||
v-else
|
||||
class="button button-primary"
|
||||
type="button"
|
||||
:disabled="editing.size === 0"
|
||||
@click="submit"
|
||||
>
|
||||
<template v-if="apply">Submit</template>
|
||||
<template v-else>Submit for review</template>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
.editor {
|
||||
flex-grow: 1;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { redirect } from 'vike/abort'; /* eslint-disable-line import/extensions */
|
||||
import { redirect } from 'vike/abort';
|
||||
|
||||
import { fetchActorsById } from '#/src/actors.js';
|
||||
import { fetchCountries } from '#/src/countries.js';
|
||||
|
||||
@@ -10,9 +10,11 @@ export default (pageContext) => {
|
||||
|
||||
if (matched) {
|
||||
return {
|
||||
routeParams: matched.params.actorId ? {
|
||||
actorId: matched.params.actorId,
|
||||
} : {},
|
||||
routeParams: matched.params.actorId
|
||||
? {
|
||||
actorId: matched.params.actorId,
|
||||
}
|
||||
: {},
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user