diff --git a/components/actors/tile.vue b/components/actors/tile.vue index bf8e603..6b6248c 100644 --- a/components/actors/tile.vue +++ b/components/actors/tile.vue @@ -66,7 +66,16 @@ - {{ actor.name }} + + {{ actor.name }} + + + @@ -119,9 +128,11 @@ const favorited = ref(props.actor.stashes.some((actorStash) => actorStash.id === } } -.name { +.label { + display: flex; + justify-content: space-between; + align-items: center; flex-shrink: 0; - padding: .35rem .5rem; font-weight: bold; font-size: .9rem; white-space: nowrap; @@ -130,6 +141,15 @@ const favorited = ref(props.actor.stashes.some((actorStash) => actorStash.id === user-select: all; } +.name { + padding: .35rem .25rem .35rem .5rem; +} + +.favicon { + height: 1rem; + padding: .35rem .5rem .35rem .25rem; +} + .avatar-container { position: relative; flex-grow: 1; diff --git a/pages/actors/@actorId/edit/+Page.vue b/pages/actors/@actorId/edit/+Page.vue index b998452..dbe2be2 100644 --- a/pages/actors/@actorId/edit/+Page.vue +++ b/pages/actors/@actorId/edit/+Page.vue @@ -68,7 +68,7 @@
{{ item.label || item.key }}
-
+
- +
- +
- Bust + Height - cm + - - + + ft + + in + +
+
+ + +
+ Weight + + + kg + + + + + + + +
@@ -210,20 +244,10 @@
- State + Place -
- -
- City - - @@ -560,27 +584,53 @@
Penis length - + + cm + + + + inch +
Penis girth - + + cm + + + + inch +
@@ -690,7 +740,7 @@ const user = pageContext.user; const countries = pageContext.pageProps.countries; const actor = ref(pageContext.pageProps.actor); -console.log(actor.value); +// console.log(actor.value); const topCountries = [ 'AU', @@ -705,26 +755,6 @@ const topCountries = [ const sortedCountries = countries.toSorted((countryA, countryB) => topCountries.indexOf(countryB.alpha2) - topCountries.indexOf(countryA.alpha2)); -/* -const cupSizes = [ - 'A', 'AA', - 'B', - 'C', - 'D', 'DD', 'DDD', - 'E', - 'F', 'FF', - 'G', 'GG', - 'H', 'HH', - 'J', 'JJ', - 'K', 'KK', - 'L', - 'M', - 'N', - 'O', - 'P', -]; -*/ - const cupSizes = { us: ['AA', 'A', 'B', 'C', 'D', ['DD', 'E'], ['DDD', 'F'], 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P'], // United States uk: ['AA', 'A', 'B', 'C', 'D', 'DD', 'E', 'F', 'FF', 'G', 'GG', 'H', 'HH', 'J', 'JJ', 'K', 'KK'], // United Kingdom @@ -778,28 +808,42 @@ const fields = computed(() => [ : null, inline: true, }, + { + key: 'ethnicity', + type: 'string', + value: actor.value.ethnicity, + suggestions: [ + 'Asian', + 'Black', + 'Indian', + 'Latina', + 'White', + ], + }, { key: 'origin', type: 'place', value: { - ...actor.value.origin, country: actor.value.origin?.country?.alpha2 || null, + place: [actor.value.origin?.city, actor.value.origin?.state].filter(Boolean).join(', '), }, }, { key: 'residence', type: 'place', value: { - ...actor.value.residence, country: actor.value.residence?.country?.alpha2 || null, + place: [actor.value.residence?.city, actor.value.residence?.state].filter(Boolean).join(', '), }, }, { key: 'size', type: 'size', value: { - height: actor.value.height?.metric, - weight: actor.value.weight?.metric, + metricHeight: actor.value.height?.metric, + metricWeight: actor.value.weight?.metric, + imperialHeight: actor.value.height?.imperial || [], + imperialWeight: actor.value.weight?.imperial, }, }, { @@ -900,8 +944,10 @@ const fields = computed(() => [ key: 'penis', type: 'penis', value: { - penisLength: actor.value.penisLength?.imperial, - penisGirth: actor.value.penisGirth?.imperial, + metricLength: actor.value.penisLength?.metric, + metricGirth: actor.value.penisGirth?.metric, + imperialLength: actor.value.penisLength?.imperial, + imperialGirth: actor.value.penisGirth?.imperial, isCircumcised: actor.value.isCircumcised, }, }, @@ -943,27 +989,49 @@ function setAvatar(avatarId) { const keyMap = { origin: { country: 'originCountry', - state: 'originState', - city: 'originCity', + place: 'originPlace', }, residence: { country: 'residenceCountry', - state: 'residenceState', - city: 'residenceCity', + place: 'residencePlace', }, }; +const groupMap = { + penisLength: 'penis', + penisGirth: 'penis', + height: 'size', + weight: 'size', +}; + async function submit() { try { await post('/revisions/actors', { actorId: actor.value.id, - edits: Object.fromEntries(Array.from(editing.value).flatMap((key) => { - if (edits.value[key] && typeof edits.value[key] === 'object') { - return Object.entries(edits.value[key]).map(([valueKey, value]) => [keyMap[key]?.[valueKey] || valueKey, value]); - } + edits: { + ...Object.fromEntries(Array.from(editing.value).flatMap((key) => { + if (edits.value[key] && typeof edits.value[key] === 'object') { + return Object.entries(edits.value[key]).map(([valueKey, value]) => [keyMap[key]?.[valueKey] || valueKey, value]); + } - return [[key, edits.value[key]]]; - })), + return [[key, edits.value[key]]]; + })), + ...Object.fromEntries(Object.entries({ + height: sizeUnits.value === 'imperial' ? edits.value.size.imperialHeight : edits.value.size.metricHeight, + weight: sizeUnits.value === 'imperial' ? edits.value.size.imperialWeight : edits.value.size.metricWeight, + 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, + }, + sizeUnits: sizeUnits.value, figureUnits: figureUnits.value, penisUnits: penisUnits.value, comment: comment.value, diff --git a/src/actors.js b/src/actors.js index 4c8afe9..4373bd7 100644 --- a/src/actors.js +++ b/src/actors.js @@ -59,6 +59,12 @@ export function curateActor(actor, context = {}) { name: actor.name, gender: actor.gender, age: actor.age, + ethnicity: actor.ethnicity, + entity: actor.entity && { + id: actor.entity.id, + slug: actor.entity.slug, + name: actor.entity.name, + }, ...Object.fromEntries(Object.entries(keyMap).map(([key, entryKey]) => [key, actor[entryKey]])), ageFromBirth: actor.date_of_birth && differenceInYears(Date.now(), actor.date_of_birth), ageThen: context.sceneDate && actor.date_of_birth && differenceInYears(context.sceneDate, actor.date_of_birth), @@ -166,11 +172,13 @@ export async function fetchActorsById(actorIds, options = {}, reqUser) { knex.raw('COALESCE(birth_countries.alias, birth_countries.name) as birth_country_name'), 'residence_countries.alpha2 as residence_country_alpha2', knex.raw('COALESCE(residence_countries.alias, residence_countries.name) as residence_country_name'), + knex.raw('row_to_json(entities) as entity'), ) .leftJoin('actors_meta', 'actors_meta.actor_id', 'actors.id') .leftJoin('countries as birth_countries', 'birth_countries.alpha2', 'actors.birth_country_alpha2') .leftJoin('countries as residence_countries', 'residence_countries.alpha2', 'actors.residence_country_alpha2') .leftJoin('media as avatars', 'avatars.id', 'actors.avatar_media_id') + .leftJoin('entities', 'entities.id', 'actors.entity_id') .whereIn('actors.id', actorIds) .modify((builder) => { if (options.order) { @@ -199,8 +207,8 @@ export async function fetchActorsById(actorIds, options = {}, reqUser) { ) .whereIn('actor_id', actorIds) .leftJoin('media', 'media.id', 'actors_avatars.media_id') - .groupBy('media.id', 'actors_avatars.actor_id', 'actors_avatars.created_at') - .orderBy('actors_avatars.created_at', 'desc'), + .groupBy('media.id', 'actors_avatars.actor_id') + .orderBy(knex.raw('max(actors_avatars.created_at)'), 'desc'), reqUser ? knex('stashes_actors') .leftJoin('stashes', 'stashes.id', 'stashes_actors.stash_id') @@ -549,34 +557,6 @@ async function fetchMainProfile(actorId, wasCreated = false) { return fetchMainProfile(actorId, true); } -/* -async function applyMainProfile(actorId) { - const [actorEntry, mainProfile] = await Promise.all([ - knex('actors') - .where('id', actorId) - .first(), - fetchMainProfile(actorId), - ]); - - if (!actorEntry) { - throw new HttpError('No actor profile found to apply main profile to', 404); - } - - const preservedKeys = ['id']; - - // we start iterating from the actor entry so we don't include keys that are not yet supported by the actors table - const mergedProfile = Object.fromEntries(Object.entries(actorEntry) - .filter(([key]) => Object.hasOwn(mainProfile, key)) - .map(([key, value]) => [key, mainProfile[key] === null || preservedKeys.includes(key) - ? value - : mainProfile[key]])); - - await knex('actors') - .where('id', actorId) - .update(mergedProfile); -} -*/ - async function applyActorRevision(revisionIds, reqUser) { const revisions = await knex('actors_revisions') .whereIn('id', revisionIds) @@ -600,6 +580,7 @@ async function applyActorRevision(revisionIds, reqUser) { 'residenceCountry', 'residenceState', 'residenceCity', + 'ethnicity', 'height', 'weight', 'bust', @@ -755,6 +736,27 @@ function convertFigure(domain = 'cup', rawValue, units) { return usValue; } +function convertHeight(height, units) { + if (units === 'metric' || !Array.isArray(height)) { + return Number(height) || null; + } + + if (height.length !== 2) { + return null; + } + + // 12 inches in a foot + return Math.round(((height[0] * 12) + height[1]) * 2.54); +} + +function convertWeight(weight, units) { + if (units === 'imperial') { + return Math.round(unit(weight, 'lbs').toNumeric('kg')); + } + + return Number(weight) || null; +} + export async function createActorRevision(actorId, { edits, comment, @@ -819,15 +821,9 @@ export async function createActorRevision(actorId, { return null; } - if (Array.isArray(value)) { - const valueSet = new Set(value); - const baseSet = new Set(baseActor[key]); - - if (valueSet.size === baseSet.size && baseActor[key].every((id) => valueSet.has(id))) { - return null; - } - - return { key, value: Array.from(valueSet) }; + if (['originPlace', 'residencePlay'].includes(key)) { + console.log(key, value); + throw new Error('must be converted first!'); } if (['cup', 'bust', 'waist', 'hip'].includes(key)) { @@ -844,9 +840,49 @@ export async function createActorRevision(actorId, { }; } + if (['height'].includes(key)) { + const convertedValue = convertHeight(value, options.sizeUnits); + + if (baseActor[key] === convertedValue) { + return null; + } + + const conversionComment = !value || convertedValue === value + ? null + : `${key} converted from ${value[0]} in ${value[1]} ft to ${convertedValue} cm`; + + return { + key, + value: convertedValue, + comment: conversionComment, + }; + } + + if (['weight'].includes(key)) { + const convertedValue = convertWeight(value, options.sizeUnits); + + if (baseActor[key] === convertedValue) { + return null; + } + + const conversionComment = !value || convertedValue === value + ? null + : `${key} converted from ${value} lbs to ${convertedValue} kg`; + + return { + key, + value: convertedValue, + comment: conversionComment, + }; + } + if (['penisLength', 'penisGirth'].includes(key) && options.penisUnits === 'imperial') { const convertedValue = Math.round(convert(value, 'inches').to('cm')); + if (baseActor[key] === convertedValue) { + return null; + } + return { key, value: convertedValue, @@ -854,6 +890,17 @@ export async function createActorRevision(actorId, { }; } + if (Array.isArray(value)) { + const valueSet = new Set(value); + const baseSet = new Set(baseActor[key]); + + if (valueSet.size === baseSet.size && baseActor[key].every((id) => valueSet.has(id))) { + return null; + } + + return { key, value: Array.from(valueSet) }; + } + return { key, value }; }).filter(Boolean);