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 }}
+
+ v-for="{ scene } in stash.scenes"
+ :key="scene.id"
+ class="stash-scene"
+ >
+
+
+ v-for="{ actor } in stash.actors"
+ :key="actor.id"
+ class="stash-actor"
+ >
+
+
@@ -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