Added actor assignment to new actors module. Showing network icon on network-specific actors. Improved dark theme. Changed tag tile design. Added Digital Playground logos.
|
@ -11,11 +11,7 @@
|
|||
"no-console": 0,
|
||||
"indent": "off",
|
||||
"template-curly-spacing": "off",
|
||||
"max-len": [2, {
|
||||
"code": 300,
|
||||
"tabWidth": 4,
|
||||
"ignoreUrls": true
|
||||
}],
|
||||
"max-len": 0,
|
||||
"vue/no-v-html": 0,
|
||||
"vue/html-indent": ["error", 4],
|
||||
"vue/multiline-html-element-content-newline": 0,
|
||||
|
|
|
@ -7,7 +7,9 @@
|
|||
|
||||
<div class="actor-header">
|
||||
<h2 class="header-name">
|
||||
{{ actor.name }}
|
||||
<span v-if="actor.network">{{ actor.name }} ({{ actor.network.name }})</span>
|
||||
<span v-else="">{{ actor.name }}</span>
|
||||
|
||||
<Gender
|
||||
:gender="actor.gender"
|
||||
class="header-gender"
|
||||
|
|
|
@ -109,8 +109,20 @@ export default {
|
|||
<style lang="scss">
|
||||
@import 'theme';
|
||||
|
||||
.gender-link.selected .gender .icon {
|
||||
fill: var(--text-light);
|
||||
.gender-link {
|
||||
&.selected .gender .icon {
|
||||
fill: var(--text-light);
|
||||
filter: none;
|
||||
}
|
||||
|
||||
&:hover:not(.selected) .gender .icon {
|
||||
fill: var(--text-light);
|
||||
}
|
||||
|
||||
&:hover:not(.selected) .transsexual .icon {
|
||||
fill: var(--female);
|
||||
filter: drop-shadow(1px 0 0 var(--text-light)) drop-shadow(-1px 0 0 var(--text-light)) drop-shadow(0 1px 0 var(--text-light)) drop-shadow(0 -1px 0 var(--text-light)) drop-shadow(1px 0 0 var(--male)) drop-shadow(-1px 0 0 var(--male)) drop-shadow(0 1px 0 var(--male)) drop-shadow(0 -1px 0 var(--male)) drop-shadow(0 0 1px rgba(0, 0, 0, 0.5));
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
|
@ -159,7 +171,6 @@ export default {
|
|||
align-items: center;
|
||||
justify-content: center;
|
||||
box-sizing: border-box;
|
||||
padding: .2rem 0 0 0;
|
||||
margin: .25rem .5rem .25rem 0;
|
||||
color: var(--shadow);
|
||||
background: var(--background);
|
||||
|
@ -167,31 +178,29 @@ export default {
|
|||
text-decoration: none;
|
||||
box-shadow: 0 0 3px var(--darken-weak);
|
||||
|
||||
.male,
|
||||
.female,
|
||||
.transsexual {
|
||||
padding: .2rem 0 0 0;
|
||||
}
|
||||
|
||||
.icon {
|
||||
fill: var(--shadow);
|
||||
}
|
||||
|
||||
&:hover {
|
||||
color: var(--primary);
|
||||
color: var(--text-light);
|
||||
cursor: pointer;
|
||||
|
||||
.icon {
|
||||
fill: var(--text-light);
|
||||
}
|
||||
}
|
||||
|
||||
&.selected {
|
||||
background: var(--primary);
|
||||
color: var(--text-light);
|
||||
|
||||
&.male {
|
||||
background: var(--male);
|
||||
}
|
||||
|
||||
&.female {
|
||||
background: var(--female);
|
||||
}
|
||||
|
||||
&.transsexual {
|
||||
background: var(--text);
|
||||
}
|
||||
|
||||
&.other .icon {
|
||||
fill: var(--text-light);
|
||||
}
|
||||
|
|
|
@ -72,6 +72,7 @@ export default {
|
|||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
background: var(--background-dim);
|
||||
color: var(--text);
|
||||
}
|
||||
|
||||
.content {
|
||||
|
|
|
@ -246,6 +246,7 @@ async function mounted() {
|
|||
this.release = await this.$store.dispatch('fetchReleaseById', this.$route.params.releaseId);
|
||||
this.filename = format(config.filename.pattern, {
|
||||
...this.release,
|
||||
shootId: this.release.shootId || '',
|
||||
date: this.formatDate(this.release.date, config.filename.date),
|
||||
}, {
|
||||
spreadSeparator: config.filename.separator,
|
||||
|
@ -287,8 +288,8 @@ export default {
|
|||
|
||||
.info {
|
||||
padding: 1rem;
|
||||
border-left: solid 1px $shadow-hint;
|
||||
border-right: solid 1px $shadow-hint;
|
||||
border-left: solid 1px var(--shadow-hint);
|
||||
border-right: solid 1px var(--shadow-hint);
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
|
@ -304,15 +305,15 @@ export default {
|
|||
.icon {
|
||||
display: inline-block;
|
||||
width: 1rem;
|
||||
fill: $shadow-strong;
|
||||
fill: var(--shadow-strong);
|
||||
margin: 0 1rem 0 0;
|
||||
}
|
||||
}
|
||||
|
||||
.details {
|
||||
background: $profile;
|
||||
color: $text-contrast;
|
||||
box-shadow: 0 0 3px $shadow-weak;
|
||||
background: var(--profile);
|
||||
color: var(--text-light);
|
||||
box-shadow: 0 0 3px var(--shadow-weak);
|
||||
cursor: default;
|
||||
|
||||
.column {
|
||||
|
@ -322,7 +323,7 @@ export default {
|
|||
}
|
||||
|
||||
.link {
|
||||
color: $text-contrast;
|
||||
color: var(--text-light);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -331,11 +332,11 @@ export default {
|
|||
height: 100%;
|
||||
|
||||
&:not(:last-child) {
|
||||
border-right: solid 1px $highlight-hint;
|
||||
border-right: solid 1px var(--lighten-hint);
|
||||
}
|
||||
|
||||
.icon {
|
||||
fill: $highlight-weak;
|
||||
fill: var(--lighten-weak);
|
||||
margin: 0 .25rem 0 0;
|
||||
}
|
||||
|
||||
|
@ -359,7 +360,6 @@ export default {
|
|||
|
||||
.logo {
|
||||
display: inline-block;
|
||||
filter: $logo-highlight;
|
||||
}
|
||||
|
||||
.logo-site {
|
||||
|
@ -377,7 +377,7 @@ export default {
|
|||
}
|
||||
|
||||
.chain {
|
||||
color: $highlight;
|
||||
color: var(--lighten);
|
||||
padding: 0 .5rem;
|
||||
font-weight: bold;
|
||||
font-size: .8rem;
|
||||
|
@ -388,7 +388,7 @@ export default {
|
|||
}
|
||||
|
||||
.description {
|
||||
line-height: 1.25;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.duration {
|
||||
|
@ -416,34 +416,36 @@ export default {
|
|||
.filename {
|
||||
width: 100%;
|
||||
padding: .5rem;
|
||||
border: solid 1px $shadow-weak;
|
||||
color: var(--text);
|
||||
border: solid 1px var(--shadow-weak);
|
||||
background: var(--background);
|
||||
}
|
||||
|
||||
.link {
|
||||
display: inline-block;
|
||||
color: $link;
|
||||
color: var(--link);
|
||||
text-decoration: none;
|
||||
|
||||
&:hover {
|
||||
color: $primary;
|
||||
color: var(--primary);
|
||||
|
||||
.icon {
|
||||
fill: $primary;
|
||||
fill: var(--primary);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.tag .link {
|
||||
background: $background;
|
||||
background: var(--background);
|
||||
display: inline-block;
|
||||
padding: .5rem;
|
||||
margin: 0 .25rem .25rem 0;
|
||||
box-shadow: 0 0 2px $shadow-weak;
|
||||
box-shadow: 0 0 2px var(--shadow-weak);
|
||||
text-decoration: none;
|
||||
text-transform: capitalize;
|
||||
|
||||
&:hover {
|
||||
color: $primary;
|
||||
color: var(--primary);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -8,8 +8,21 @@
|
|||
class="link"
|
||||
>
|
||||
<span
|
||||
v-if="actor.network"
|
||||
v-tooltip.top="`${actor.name} (${actor.network.name})`"
|
||||
class="handle"
|
||||
>
|
||||
<img
|
||||
:src="`/img/logos/${actor.network.slug}/favicon.png`"
|
||||
class="favicon"
|
||||
>
|
||||
<span class="name">{{ actor.name }}</span>
|
||||
</span>
|
||||
|
||||
<span
|
||||
v-else
|
||||
v-tooltip.top="actor.name"
|
||||
class="name"
|
||||
class="handle name"
|
||||
>{{ actor.name }}</span>
|
||||
|
||||
<div class="avatar-container">
|
||||
|
@ -89,28 +102,54 @@ export default {
|
|||
|
||||
.actor {
|
||||
width: 100%;
|
||||
background: $background;
|
||||
display: inline-block;
|
||||
margin: 0 .5rem .5rem 0;
|
||||
box-shadow: 0 0 3px $shadow-weak;
|
||||
box-shadow: 0 0 3px var(--darken-weak);
|
||||
background: var(--profile);
|
||||
}
|
||||
|
||||
.link {
|
||||
color: $text;
|
||||
color: var(--text-light);
|
||||
text-decoration: none;
|
||||
|
||||
&:hover {
|
||||
color: $primary;
|
||||
color: var(--primary);
|
||||
}
|
||||
}
|
||||
|
||||
.handle {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: .5rem;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.favicon {
|
||||
width: 1rem;
|
||||
height: 1rem;
|
||||
margin: 0 .5rem 0 0;
|
||||
|
||||
& + .name {
|
||||
padding: 0 1rem 0 0;
|
||||
}
|
||||
}
|
||||
|
||||
.name {
|
||||
flex-grow: 1;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.avatar-container {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.avatar {
|
||||
color: $shadow-weak;
|
||||
background: $shadow-hint;
|
||||
color: var(--darken-weak);
|
||||
background: var(--darken-hint);
|
||||
height: 13rem;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
|
@ -123,12 +162,12 @@ export default {
|
|||
.avatar-fallback {
|
||||
max-height: 75%;
|
||||
max-width: 80%;
|
||||
opacity: .1;
|
||||
opacity: .5;
|
||||
}
|
||||
|
||||
.details {
|
||||
background: $shadow;
|
||||
color: $text-contrast;
|
||||
background: var(--darken);
|
||||
color: var(--text-light);
|
||||
width: 100%;
|
||||
height: 1.75rem;
|
||||
display: flex;
|
||||
|
@ -156,16 +195,6 @@ export default {
|
|||
}
|
||||
|
||||
.age-then {
|
||||
color: $highlight;
|
||||
}
|
||||
|
||||
.name {
|
||||
display: block;
|
||||
padding: .5rem;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
color: var(--lighten);
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -216,9 +216,8 @@ export default {
|
|||
object-fit: cover;
|
||||
background-position: center;
|
||||
background-size: cover;
|
||||
background-color: var(--shadow-hint);
|
||||
background-color: var(--darken-hint);
|
||||
color: var(--shadow);
|
||||
text-shadow: 1px 1px 0 var(--highlight);
|
||||
}
|
||||
|
||||
.row {
|
||||
|
|
|
@ -4,14 +4,14 @@
|
|||
:title="tag.name"
|
||||
class="tile"
|
||||
>
|
||||
<span class="title">{{ tag.name }}</span>
|
||||
|
||||
<img
|
||||
v-if="tag.poster"
|
||||
:src="sfw ? `/img/${tag.poster.sfw.thumbnail}` : `/img/${tag.poster.thumbnail}`"
|
||||
:alt="tag.name"
|
||||
class="poster"
|
||||
>
|
||||
|
||||
<span class="title">{{ tag.name }}</span>
|
||||
</router-link>
|
||||
</template>
|
||||
|
||||
|
@ -44,6 +44,7 @@ export default {
|
|||
align-items: left;
|
||||
justify-content: flex-end;
|
||||
box-sizing: border-box;
|
||||
position: relative;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
box-shadow: inset 0 0 3px var(--darken);
|
||||
|
@ -51,16 +52,23 @@ export default {
|
|||
|
||||
.poster {
|
||||
width: 100%;
|
||||
height: 14rem;
|
||||
height: 16rem;
|
||||
object-fit: cover;
|
||||
box-shadow: 0 0 3px var(--darken);
|
||||
object-position: 50% 100%;
|
||||
box-shadow: 0 0 1px var(--darken);
|
||||
}
|
||||
|
||||
.title {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
font-size: 1rem;
|
||||
box-sizing: border-box;
|
||||
padding: .5rem 1rem;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
background: var(--darken);
|
||||
font-size: 1rem;
|
||||
font-weight: bold;
|
||||
text-transform: capitalize;
|
||||
text-shadow: 0 0 3px var(--darken-strong);
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -9,7 +9,6 @@ body {
|
|||
}
|
||||
|
||||
body {
|
||||
color: var(--text);
|
||||
margin: 0;
|
||||
font-family: Arial, Helvetica, sans-serif;
|
||||
}
|
||||
|
|
|
@ -77,6 +77,11 @@ function initActorActions(store, _router) {
|
|||
tattoos
|
||||
piercings
|
||||
description
|
||||
network {
|
||||
id
|
||||
name
|
||||
slug
|
||||
}
|
||||
avatar: actorsAvatarByActorId {
|
||||
media {
|
||||
thumbnail
|
||||
|
@ -222,6 +227,11 @@ function initActorActions(store, _router) {
|
|||
age
|
||||
birthdate
|
||||
gender
|
||||
network {
|
||||
id
|
||||
name
|
||||
slug
|
||||
}
|
||||
avatar: actorsAvatarByActorId {
|
||||
media {
|
||||
thumbnail
|
||||
|
|
|
@ -37,6 +37,11 @@ const actorFields = `
|
|||
birthdate
|
||||
age
|
||||
gender
|
||||
network {
|
||||
id
|
||||
name
|
||||
slug
|
||||
}
|
||||
originCountry: countryByBirthCountryAlpha2 {
|
||||
alpha2
|
||||
name
|
||||
|
|
|
@ -247,7 +247,6 @@ exports.up = knex => Promise.resolve()
|
|||
table.increments('id', 12);
|
||||
|
||||
table.string('name')
|
||||
.unique()
|
||||
.notNullable();
|
||||
|
||||
table.string('slug', 32)
|
||||
|
@ -261,17 +260,6 @@ exports.up = knex => Promise.resolve()
|
|||
.references('id')
|
||||
.inTable('networks');
|
||||
|
||||
table.datetime('created_at')
|
||||
.defaultTo(knex.fn.now());
|
||||
}))
|
||||
.then(() => knex.schema.createTable('actors_profiles', (table) => {
|
||||
table.increments('id', 12);
|
||||
|
||||
table.integer('actor_id')
|
||||
.references('id')
|
||||
.inTable('actors')
|
||||
.notNullable();
|
||||
|
||||
table.date('birthdate');
|
||||
table.string('gender', 18);
|
||||
table.text('description');
|
||||
|
@ -307,6 +295,13 @@ exports.up = knex => Promise.resolve()
|
|||
|
||||
table.datetime('created_at')
|
||||
.defaultTo(knex.fn.now());
|
||||
}))
|
||||
.then(() => knex.raw('CREATE TABLE actors_profiles AS TABLE actors WITH NO DATA;'))
|
||||
.then(() => knex.schema.alterTable('actors_profiles', (table) => {
|
||||
table.integer('actor_id')
|
||||
.references('id')
|
||||
.inTable('actors')
|
||||
.notNullable();
|
||||
|
||||
table.datetime('scraped_at');
|
||||
table.boolean('scrape_success');
|
||||
|
@ -323,7 +318,9 @@ exports.up = knex => Promise.resolve()
|
|||
{ slug: 'face', name: 'face' },
|
||||
{ slug: 'scalp', name: 'scalp' },
|
||||
{ slug: 'forehead', name: 'forehead' },
|
||||
{ slug: 'temple', name: 'temple' },
|
||||
{ slug: 'cheek', name: 'cheek' },
|
||||
{ slug: 'jaw', name: 'jaw' },
|
||||
{ slug: 'chin', name: 'chin' },
|
||||
{ slug: 'neck', name: 'neck' },
|
||||
{ slug: 'throat', name: 'throat' },
|
||||
|
@ -337,6 +334,9 @@ exports.up = knex => Promise.resolve()
|
|||
{ slug: 'upper-lip', name: 'upper lip' },
|
||||
{ slug: 'lower-lip', name: 'lower lip' },
|
||||
{ slug: 'inner-lip', name: 'inner lip' },
|
||||
{ slug: 'inner-lower-lip', name: 'inner lower lip' },
|
||||
{ slug: 'inner-upper-lip', name: 'inner upper lip' },
|
||||
{ slug: 'philtrum', name: 'philtrum' },
|
||||
{ slug: 'above-lip', name: 'above lip' },
|
||||
{ slug: 'below-lip', name: 'below lip' },
|
||||
// nose
|
||||
|
@ -364,7 +364,7 @@ exports.up = knex => Promise.resolve()
|
|||
// hands
|
||||
{ slug: 'hand', name: 'hand' },
|
||||
{ slug: 'fingers', name: 'fingers' },
|
||||
{ slug: 'knuckles', name: 'knucles' },
|
||||
{ slug: 'knuckles', name: 'knuckles' },
|
||||
{ slug: 'thumb', name: 'thumb' },
|
||||
{ slug: 'index-finger', name: 'index finger' },
|
||||
{ slug: 'middle-finger', name: 'middle finger' },
|
||||
|
@ -378,11 +378,14 @@ exports.up = knex => Promise.resolve()
|
|||
{ slug: 'collarbone', name: 'collarbone' },
|
||||
{ slug: 'chest', name: 'chest' },
|
||||
{ slug: 'rib-cage', name: 'rib cage' },
|
||||
{ slug: 'breastbone', name: 'breastbone' },
|
||||
{ slug: 'underboob', name: 'underboob' },
|
||||
{ slug: 'sideboob', name: 'sideboob' },
|
||||
{ slug: 'boob', name: 'boob' },
|
||||
{ slug: 'nipple', name: 'nipple' },
|
||||
{ slug: 'abdomen', name: 'abdomen' },
|
||||
{ slug: 'lower-abdomen', name: 'lower abdomen' },
|
||||
{ slug: 'navel', name: 'navel' },
|
||||
{ slug: 'pelvis', name: 'pelvis' },
|
||||
// back
|
||||
{ slug: 'back', name: 'back' },
|
||||
{ slug: 'upper-back', name: 'upper back' },
|
||||
|
@ -392,9 +395,9 @@ exports.up = knex => Promise.resolve()
|
|||
// bottom
|
||||
{ slug: 'butt', name: 'butt' },
|
||||
{ slug: 'hip', name: 'hip' },
|
||||
{ slug: 'anus', name: 'anus' },
|
||||
// genitals
|
||||
{ slug: 'pubic-mound', name: 'pubic mound' },
|
||||
{ slug: 'anus', name: 'anus' },
|
||||
{ slug: 'vagina', name: 'vagina' },
|
||||
{ slug: 'outer-labia', name: 'outer labia' },
|
||||
{ slug: 'inner-labia', name: 'inner labia' },
|
||||
|
@ -748,8 +751,8 @@ exports.up = knex => Promise.resolve()
|
|||
COMMENT ON VIEW movie_actors IS E'@foreignKey (movie_id) references releases (id)\n@foreignKey (actor_id) references actors (id)';
|
||||
COMMENT ON VIEW movie_tags IS E'@foreignKey (movie_id) references releases (id)\n@foreignKey (tag_id) references tags (id)';
|
||||
|
||||
COMMENT ON COLUMN actors_profiles.height IS E'@omit read,update,create,delete,all,many';
|
||||
COMMENT ON COLUMN actors_profiles.weight IS E'@omit read,update,create,delete,all,many';
|
||||
COMMENT ON COLUMN actors.height IS E'@omit read,update,create,delete,all,many';
|
||||
COMMENT ON COLUMN actors.weight IS E'@omit read,update,create,delete,all,many';
|
||||
`));
|
||||
|
||||
exports.down = knex => knex.raw(`
|
||||
|
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 20 KiB |
After Width: | Height: | Size: 102 KiB |
After Width: | Height: | Size: 25 KiB |
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 2.6 KiB |
After Width: | Height: | Size: 46 KiB |
After Width: | Height: | Size: 36 KiB |
After Width: | Height: | Size: 258 KiB |
After Width: | Height: | Size: 25 KiB |
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 20 KiB |
After Width: | Height: | Size: 6.2 KiB |
|
@ -1,57 +1,74 @@
|
|||
'use strict';
|
||||
|
||||
const logger = require('./logger')(__filename);
|
||||
const knex = require('./knex');
|
||||
const slugify = require('./utils/slugify');
|
||||
const capitalize = require('./utils/capitalize');
|
||||
|
||||
function toBaseActors(actorsOrNames, release) {
|
||||
return actorsOrNames.map((actorOrName) => {
|
||||
const name = capitalize(actorOrName.name || actorOrName);
|
||||
const slug = slugify(name);
|
||||
|
||||
const baseActor = {
|
||||
name,
|
||||
slug,
|
||||
hasSingleName: name.split(/\s+/).length === 1,
|
||||
network: release.site.network,
|
||||
slugWithNetworkSlug: `${slug}-${release.site.network.slug}`,
|
||||
};
|
||||
|
||||
if (actorOrName.name) {
|
||||
return {
|
||||
...actorOrName,
|
||||
name: capitalize(actorOrName.name),
|
||||
slug: slugify(actorOrName.name),
|
||||
networkId: release.site.network.id,
|
||||
...baseActor,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
name: capitalize(actorOrName),
|
||||
slug: slugify(actorOrName),
|
||||
networkId: release.site.network.id,
|
||||
};
|
||||
return baseActor;
|
||||
});
|
||||
}
|
||||
|
||||
function curateActorEntry(baseActor) {
|
||||
const actorEntry = {
|
||||
if (baseActor.hasSingleName) {
|
||||
logger.warn(`Assigning single name actor '${baseActor.name}' to network '${baseActor.network.name}'`);
|
||||
|
||||
// attach network ID to allow separating actors with the same name
|
||||
return {
|
||||
name: baseActor.name,
|
||||
slug: baseActor.slugWithNetworkSlug,
|
||||
network_id: baseActor.network.id,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
name: baseActor.name,
|
||||
slug: baseActor.slug,
|
||||
};
|
||||
|
||||
if (baseActor.name.split(/\s+/).length === 1) {
|
||||
// attach network ID for single names, to reduce mismatches
|
||||
actorEntry.network_id = baseActor.networkId;
|
||||
}
|
||||
|
||||
return actorEntry;
|
||||
}
|
||||
|
||||
function curateActorEntries(baseActors) {
|
||||
return baseActors.map(baseActor => curateActorEntry(baseActor));
|
||||
}
|
||||
|
||||
async function getActors(baseActors) {
|
||||
async function getOrCreateActors(baseActors) {
|
||||
const existingActors = await knex('actors')
|
||||
.select('id', 'name', 'slug', 'network_id')
|
||||
.whereIn('slug', baseActors.map(baseActor => baseActor.slug))
|
||||
.orWhereIn('name', baseActors.map(baseActor => baseActor.slug));
|
||||
.whereNull('network_id')
|
||||
.orWhereIn(['slug', 'network_id'], baseActors.map(baseActor => [baseActor.slugWithNetworkSlug, baseActor.network.id]));
|
||||
|
||||
if (existingActors.length === 0) {
|
||||
// TODO: TESTING ONLY
|
||||
await knex('actors').insert(curateActorEntries(baseActors.slice(0, 3)));
|
||||
const existingActorSlugs = new Set(existingActors.map(actor => actor.slug));
|
||||
const uniqueBaseActors = baseActors.filter(baseActor => !existingActorSlugs.has(baseActor.slug) && !existingActorSlugs.has(baseActor.slugWithNetworkSlug));
|
||||
|
||||
const curatedActorEntries = curateActorEntries(uniqueBaseActors);
|
||||
const newActors = await knex('actors').insert(curatedActorEntries, ['id', 'name', 'slug', 'network_id']);
|
||||
|
||||
if (Array.isArray(newActors)) {
|
||||
return newActors.concat(existingActors);
|
||||
}
|
||||
|
||||
console.log(existingActors);
|
||||
return existingActors;
|
||||
}
|
||||
|
||||
async function associateActors(releases) {
|
||||
|
@ -67,9 +84,18 @@ async function associateActors(releases) {
|
|||
const baseActorsBySlug = baseActors.reduce((acc, baseActor) => ({ ...acc, [baseActor.slug]: baseActor }), {});
|
||||
const uniqueBaseActors = Object.values(baseActorsBySlug);
|
||||
|
||||
const actors = await getActors(uniqueBaseActors);
|
||||
const actors = await getOrCreateActors(uniqueBaseActors);
|
||||
const actorIdsBySlug = actors.reduce((acc, actor) => ({ ...acc, [actor.slug]: actor.id }), {});
|
||||
|
||||
console.log(actors);
|
||||
const releaseActorAssociations = Object.entries(baseActorsByReleaseId)
|
||||
.map(([releaseId, releaseActors]) => releaseActors
|
||||
.map(releaseActor => ({
|
||||
release_id: releaseId,
|
||||
actor_id: actorIdsBySlug[releaseActor.slug] || actorIdsBySlug[releaseActor.slugWithNetworkSlug],
|
||||
})))
|
||||
.flat();
|
||||
|
||||
await knex.raw(`${knex('releases_actors').insert(releaseActorAssociations).toString()} ON CONFLICT DO NOTHING;`);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
|
|
|
@ -11,14 +11,14 @@ const schemaExtender = makeExtendSchemaPlugin(_build => ({
|
|||
IMPERIAL
|
||||
}
|
||||
|
||||
extend type ActorProfile {
|
||||
extend type Actor {
|
||||
age: Int @requires(columns: ["birthdate"])
|
||||
height(units:Units): String @requires(columns: ["height"])
|
||||
weight(units:Units): String @requires(columns: ["weight"])
|
||||
}
|
||||
`,
|
||||
resolvers: {
|
||||
ActorProfile: {
|
||||
Actor: {
|
||||
age(parent, _args, _context, _info) {
|
||||
if (!parent.birthdate) return null;
|
||||
|
||||
|
|