diff --git a/assets/components/album/album.vue b/assets/components/album/album.vue index 543e12c6..0a1310da 100644 --- a/assets/components/album/album.vue +++ b/assets/components/album/album.vue @@ -27,7 +27,7 @@ >
  • You are at least 18 years old, and legally permitted to view adult material in your jurisdiction.
  • -
  • You do not regard erotic, sexual and pornographic material as obscene or offensive.
  • +
  • You do not regard erotic and frankly pornographic media as obscene or offensive.
  • You understand that most sexual scenarios depicted on this website are fictional, performed by professional actors for the purpose of entertainment, and not representative of real-life interactions.
  • diff --git a/assets/components/releases/release.vue b/assets/components/releases/release.vue index 7a98c30e..220ace6c 100644 --- a/assets/components/releases/release.vue +++ b/assets/components/releases/release.vue @@ -55,14 +55,14 @@ v-show="me && isStashed" icon="heart7" class="stash stashed noselect" - @click="unstashRelease" + @click="unstashScene" /> @@ -251,8 +251,8 @@ async function fetchRelease(scroll = true) { } } -async function stashRelease() { - this.$store.dispatch(this.$route.name === 'movie' ? 'stashMovie' : 'stashRelease', { +async function stashScene() { + this.$store.dispatch(this.$route.name === 'movie' ? 'stashMovie' : 'stashScene', { sceneId: this.release.id, movieId: this.release.id, stashId: this.$store.getters.favorites.id, @@ -261,8 +261,8 @@ async function stashRelease() { this.fetchRelease(false); } -async function unstashRelease() { - this.$store.dispatch(this.$route.name === 'movie' ? 'unstashMovie' : 'unstashRelease', { +async function unstashScene() { + this.$store.dispatch(this.$route.name === 'movie' ? 'unstashMovie' : 'unstashScene', { sceneId: this.release.id, movieId: this.release.id, stashId: this.$store.getters.favorites.id, @@ -323,8 +323,8 @@ export default { mounted: fetchRelease, methods: { fetchRelease, - stashRelease, - unstashRelease, + stashScene, + unstashScene, }, }; diff --git a/assets/components/stashes/stash.vue b/assets/components/stashes/stash.vue new file mode 100644 index 00000000..0c173892 --- /dev/null +++ b/assets/components/stashes/stash.vue @@ -0,0 +1,115 @@ + + + + + diff --git a/assets/components/tags/photos.vue b/assets/components/tags/photos.vue index 12d91a0f..dbd1d1c7 100644 --- a/assets/components/tags/photos.vue +++ b/assets/components/tags/photos.vue @@ -11,7 +11,7 @@ > + +
    + + + +
    + + {{ actor.name }} +
    + + + + + diff --git a/assets/components/users/scene-preview.vue b/assets/components/users/scene-preview.vue new file mode 100644 index 00000000..0ea6adf8 --- /dev/null +++ b/assets/components/users/scene-preview.vue @@ -0,0 +1,108 @@ + + + + + diff --git a/assets/components/users/user.vue b/assets/components/users/user.vue index 22962bf9..5a5b2393 100644 --- a/assets/components/users/user.vue +++ b/assets/components/users/user.vue @@ -19,16 +19,28 @@ :key="stash.id" class="stash" > -

    {{ stash.name }}

    + +

    {{ stash.name }}

    +
    @@ -47,18 +66,22 @@ @@ -89,25 +115,34 @@ export default { margin: 0 0 1rem 0; } +.stashes { + display: grid; + grid-template-columns: 1fr 1fr; +} + .heading { color: var(--primary); } .stash { - width: 100%; + min-width: 0; background: var(--background); margin: 0 0 1rem 0; box-shadow: 0 0 3px var(--shadow-weak); } +.stash-link.stash-section { + display: block; + text-decoration: none; +} + .stash-name { color: var(--shadow-strong); - padding: 1rem .5rem 0 .5rem; margin: 0; } .stash-section { - padding: 1rem .5rem; + padding: .5rem; &:not(:last-child) { border-bottom: solid 1px var(--shadow-hint); @@ -116,17 +151,27 @@ export default { .stash-actors, .stash-scenes { - display: grid; - flex-grow: 1; - grid-gap: .5rem; - box-sizing: border-box; -} + display: flex; + overflow-x: auto; + scroll-behavior: smooth; + scrollbar-width: none; -.stash-actors { - grid-template-columns: repeat(auto-fill, minmax(10rem, 1fr)); + &::-webkit-scrollbar { + display: none; + } } .stash-scenes { - grid-template-columns: repeat(auto-fill, minmax(22rem, 1fr)); + height: 8rem; + grid-gap: .5rem; +} + +.stash-actors { + grid-gap: 1rem; +} + +.stash-actor, +.stash-scene { + flex-shrink: 0; } diff --git a/assets/js/main.js b/assets/js/main.js index 2c1f7636..7a8749ca 100644 --- a/assets/js/main.js +++ b/assets/js/main.js @@ -58,6 +58,10 @@ async function init() { } function getPath(media, type, options) { + if (!media) { + return null; + } + const path = getBasePath(media, type, options); const filename = getFilename(media, type, options); diff --git a/assets/js/router.js b/assets/js/router.js index 0c7d8a90..e1f3c8b4 100644 --- a/assets/js/router.js +++ b/assets/js/router.js @@ -12,6 +12,7 @@ import Actors from '../components/actors/actors.vue'; import Movies from '../components/releases/movies.vue'; import Tag from '../components/tags/tag.vue'; import Tags from '../components/tags/tags.vue'; +import Stash from '../components/stashes/stash.vue'; import Search from '../components/search/search.vue'; import Stats from '../components/stats/stats.vue'; import NotFound from '../components/errors/404.vue'; @@ -201,6 +202,11 @@ const routes = [ component: Tags, name: 'tags', }, + { + path: '/stash/:stashId/:stashSlug?', + component: Stash, + name: 'stash', + }, { path: '/search', component: Search, diff --git a/assets/js/stashes/actions.js b/assets/js/stashes/actions.js index 16ab1a60..7f28dd38 100644 --- a/assets/js/stashes/actions.js +++ b/assets/js/stashes/actions.js @@ -1,6 +1,62 @@ -import { post, del } from '../api'; +import { graphql, post, del } from '../api'; +import { releaseFields } from '../fragments'; +import { curateStash } from '../curate'; function initStashesActions(_store, _router) { + async function fetchStash(context, stashId) { + const { stash } = await graphql(` + query Stash( + $stashId: Int! + ) { + stash(id: $stashId) { + id + name + slug + public + user { + id + username + } + actors: stashesActors { + comment + actor { + id + name + slug + gender + age + ageFromBirth + dateOfBirth + birthCity + birthState + birthCountry: countryByBirthCountryAlpha2 { + alpha2 + name + alias + } + avatar: avatarMedia { + id + path + thumbnail + lazy + } + } + } + scenes: stashesScenes { + comment + scene { + ${releaseFields} + } + } + } + } + `, { + stashId: Number(stashId), + }); + + return curateStash(stash); + } + async function stashActor(context, { actorId, stashId }) { await post(`/stashes/${stashId}/actors`, { actorId }); } @@ -26,6 +82,7 @@ function initStashesActions(_store, _router) { } return { + fetchStash, stashActor, stashScene, stashMovie, diff --git a/assets/js/users/actions.js b/assets/js/users/actions.js index fa3a074e..1fd5ec64 100644 --- a/assets/js/users/actions.js +++ b/assets/js/users/actions.js @@ -42,7 +42,7 @@ function initUsersActions(_store, _router) { } } } - scenes: stashesScenes { + scenes: stashesScenes(first: 20) { comment scene { ${releaseFields} diff --git a/migrations/20190325001339_releases.js b/migrations/20190325001339_releases.js index 61f368f4..6903bbb5 100644 --- a/migrations/20190325001339_releases.js +++ b/migrations/20190325001339_releases.js @@ -1087,6 +1087,10 @@ exports.up = knex => Promise.resolve() table.unique(['stash_id', 'scene_id']); table.string('comment'); + + table.datetime('created_at') + .notNullable() + .defaultTo(knex.fn.now()); })) .then(() => knex.schema.createTable('stashes_movies', (table) => { table.integer('stash_id') @@ -1104,6 +1108,10 @@ exports.up = knex => Promise.resolve() table.unique(['stash_id', 'movie_id']); table.string('comment'); + + table.datetime('created_at') + .notNullable() + .defaultTo(knex.fn.now()); })) .then(() => knex.schema.createTable('stashes_actors', (table) => { table.integer('stash_id') @@ -1121,6 +1129,10 @@ exports.up = knex => Promise.resolve() table.unique(['stash_id', 'actor_id']); table.string('comment'); + + table.datetime('created_at') + .notNullable() + .defaultTo(knex.fn.now()); })) // SEARCH .then(() => { // eslint-disable-line arrow-body-style