Separated user page stash component.

This commit is contained in:
DebaucheryLibrarian 2021-03-20 02:49:17 +01:00
parent 5577e4fee5
commit e88cf4e3f4
7 changed files with 218 additions and 145 deletions

View File

@ -24,8 +24,6 @@
<script> <script>
async function unstashActor(actorId, stashId) { async function unstashActor(actorId, stashId) {
await this.$store.dispatch('unstashActor', { actorId, stashId }); await this.$store.dispatch('unstashActor', { actorId, stashId });
this.$emit('unstash');
} }
export default { export default {

View File

@ -0,0 +1,169 @@
<template>
<div class="stash">
<div class="stash-section stash-header">
<router-link
:to="{ name: 'stash', params: { stashId: stash.id, stashSlug: stash.slug } }"
class="stash-link nolink"
>
<h4 class="stash-name">{{ stash.name }}</h4>
</router-link>
<label
v-if="isMe"
v-tooltip="'Public'"
:class="{ public: stash.public }"
class="stash-public"
>
<Icon
v-show="stash.public"
icon="eye"
/>
<Icon
v-show="!stash.public"
icon="eye-blocked"
/>
<Toggle
:checked="stash.public"
@change="checked => publishStash(stash, checked)"
/>
</label>
</div>
<ul
v-if="stash.scenes?.length > 0"
class="stash-section stash-scenes nolist"
>
<li
v-for="{ scene } in stash.scenes"
:key="scene.id"
class="stash-scene"
>
<ScenePreview
:scene="scene"
:stash="stash"
/>
</li>
</ul>
<ul
v-if="stash.actors?.length > 0"
class="stash-section stash-actors nolist"
>
<li
v-for="{ actor } in stash.actors"
:key="actor.id"
class="stash-actor"
>
<ActorPreview
:actor="actor"
:stash="stash"
/>
</li>
</ul>
</div>
</template>
<script>
import ActorPreview from './actor-preview.vue';
import ScenePreview from './scene-preview.vue';
import Toggle from '../form/toggle.vue';
async function publishStash(stash, isPublic) {
await this.$store.dispatch('updateStash', {
stashId: stash.id,
stash: { public: isPublic },
});
this.$emit('publish', isPublic);
}
export default {
components: {
ActorPreview,
ScenePreview,
Toggle,
},
props: {
stash: {
type: Object,
default: null,
},
isMe: {
type: Boolean,
default: false,
},
},
emits: ['publish'],
methods: {
publishStash,
},
};
</script>
<style lang="scss" scoped>
.stash-section {
display: flex;
align-items: center;
padding: .5rem;
&:not(:last-child) {
border-bottom: solid 1px var(--shadow-hint);
}
}
.stash-header {
justify-content: space-between;
padding: 0;
}
.stash-link {
flex-grow: 1;
display: inline-block;
text-decoration: none;
}
.stash-public {
display: flex;
align-items: center;
padding: .5rem;
cursor: pointer;
.icon {
fill: var(--shadow-strong);
margin: 0 .5rem 0 0;
}
}
.stash-name {
padding: .5rem;
margin: 0;
color: var(--shadow-strong);
}
.stash-actors,
.stash-scenes {
display: flex;
overflow-x: auto;
grid-gap: .5rem;
scroll-behavior: smooth;
scrollbar-width: none;
&::-webkit-scrollbar {
display: none;
}
}
.stash-scenes {
height: 8rem;
}
.stash-actor,
.stash-scene {
height: 100%;
flex-shrink: 0;
font-size: 0;
}
</style>

View File

@ -19,80 +19,19 @@
:key="stash.id" :key="stash.id"
class="stash" class="stash"
> >
<div class="stash-section stash-header"> <Stash
<router-link
:to="{ name: 'stash', params: { stashId: stash.id, stashSlug: stash.slug } }"
class="stash-link nolink"
>
<h4 class="stash-name">{{ stash.name }}</h4>
</router-link>
<label
v-if="isMe"
v-tooltip="'Public'"
:class="{ public: stash.public }"
class="stash-public"
>
<Icon
v-show="stash.public"
icon="eye"
/>
<Icon
v-show="!stash.public"
icon="eye-blocked"
/>
<Toggle
:checked="stash.public"
@change="checked => publishStash(stash, checked)"
/>
</label>
</div>
<ul
v-if="stash.scenes?.length > 0"
class="stash-section stash-scenes nolist"
>
<li
v-for="{ scene } in stash.scenes"
:key="scene.id"
class="stash-scene"
>
<ScenePreview
:scene="scene"
:stash="stash" :stash="stash"
@unstash="fetchUser" :is-me="isMe"
@publish="() => fetchUser()"
/> />
</li> </li>
</ul> </ul>
<ul
v-if="stash.actors?.length > 0"
class="stash-section stash-actors nolist"
>
<li
v-for="{ actor } in stash.actors"
:key="actor.id"
class="stash-actor"
>
<ActorPreview
:actor="actor"
:stash="stash"
@unstash="fetchUser"
/>
</li>
</ul>
</li>
</ul>
</section> </section>
</div> </div>
</template> </template>
<script> <script>
import ActorPreview from './actor-preview.vue'; import Stash from './stash.vue';
import ScenePreview from './scene-preview.vue';
import Toggle from '../form/toggle.vue';
async function fetchUser() { async function fetchUser() {
this.user = await this.$store.dispatch('fetchUser', this.$route.params.username); this.user = await this.$store.dispatch('fetchUser', this.$route.params.username);
@ -101,24 +40,13 @@ async function fetchUser() {
this.pageTitle = this.user?.username; this.pageTitle = this.user?.username;
} }
async function publishStash(stash, isPublic) {
await this.$store.dispatch('updateStash', {
stashId: stash.id,
stash: { public: isPublic },
});
this.fetchUser();
}
async function mounted() { async function mounted() {
await this.fetchUser(); await this.fetchUser();
} }
export default { export default {
components: { components: {
ActorPreview, Stash,
ScenePreview,
Toggle,
}, },
data() { data() {
return { return {
@ -132,7 +60,6 @@ export default {
mounted, mounted,
methods: { methods: {
fetchUser, fetchUser,
publishStash,
}, },
}; };
</script> </script>
@ -172,69 +99,6 @@ export default {
box-shadow: 0 0 3px var(--shadow-weak); box-shadow: 0 0 3px var(--shadow-weak);
} }
.stash-section {
display: flex;
align-items: center;
padding: .5rem;
&:not(:last-child) {
border-bottom: solid 1px var(--shadow-hint);
}
}
.stash-header {
justify-content: space-between;
padding: 0;
}
.stash-link {
flex-grow: 1;
display: inline-block;
text-decoration: none;
}
.stash-public {
display: flex;
align-items: center;
padding: .5rem;
cursor: pointer;
.icon {
fill: var(--shadow-strong);
margin: 0 .5rem 0 0;
}
}
.stash-name {
padding: .5rem;
margin: 0;
color: var(--shadow-strong);
}
.stash-actors,
.stash-scenes {
display: flex;
overflow-x: auto;
grid-gap: .5rem;
scroll-behavior: smooth;
scrollbar-width: none;
&::-webkit-scrollbar {
display: none;
}
}
.stash-scenes {
height: 8rem;
}
.stash-actor,
.stash-scene {
height: 100%;
flex-shrink: 0;
font-size: 0;
}
@media(max-width: $breakpoint-kilo) { @media(max-width: $breakpoint-kilo) {
.stashes { .stashes {
grid-template-columns: 1fr; grid-template-columns: 1fr;

View File

@ -67,6 +67,12 @@ function initStashesActions(store, _router) {
return curateStash(stash); return curateStash(stash);
} }
async function createStash(context, stash) {
const newStash = await post('/stashes', stash);
return newStash;
}
async function updateStash(context, { stashId, stash }) { async function updateStash(context, { stashId, stash }) {
const newStash = await patch(`/stashes/${stashId}`, stash); const newStash = await patch(`/stashes/${stashId}`, stash);
@ -98,6 +104,7 @@ function initStashesActions(store, _router) {
} }
return { return {
createStash,
fetchStash, fetchStash,
stashActor, stashActor,
stashScene, stashScene,

View File

@ -2,6 +2,7 @@
const knex = require('./knex'); const knex = require('./knex');
const { HttpError } = require('./errors'); const { HttpError } = require('./errors');
const slugify = require('./utils/slugify');
function curateStash(stash) { function curateStash(stash) {
if (!stash) { if (!stash) {
@ -17,6 +18,17 @@ function curateStash(stash) {
return curatedStash; return curatedStash;
} }
function curateStashEntry(stash, user) {
const curatedStashEntry = {
user_id: user.id,
name: stash.name,
slug: slugify(stash.name),
public: false,
};
return curatedStashEntry;
}
async function fetchStash(stashId, sessionUser) { async function fetchStash(stashId, sessionUser) {
if (!sessionUser) { if (!sessionUser) {
throw new HttpError('You are not authenthicated', 401); throw new HttpError('You are not authenthicated', 401);
@ -36,6 +48,18 @@ async function fetchStash(stashId, sessionUser) {
return curateStash(stash); return curateStash(stash);
} }
async function createStash(newStash, sessionUser) {
if (!sessionUser) {
throw new HttpError('You are not authenthicated', 401);
}
const stash = await knex('stashes')
.insert(curateStashEntry(newStash, sessionUser))
.returning('*');
return curateStash(stash);
}
async function updateStash(stashId, newStash, sessionUser) { async function updateStash(stashId, newStash, sessionUser) {
if (!sessionUser) { if (!sessionUser) {
throw new HttpError('You are not authenthicated', 401); throw new HttpError('You are not authenthicated', 401);
@ -123,6 +147,7 @@ async function unstashMovie(movieId, stashId, sessionUser) {
} }
module.exports = { module.exports = {
createStash,
curateStash, curateStash,
stashActor, stashActor,
stashScene, stashScene,

View File

@ -44,6 +44,7 @@ const {
} = require('./tags'); } = require('./tags');
const { const {
createStash,
stashActor, stashActor,
stashScene, stashScene,
stashMovie, stashMovie,
@ -84,6 +85,7 @@ async function initServer() {
router.post('/api/users', signup); router.post('/api/users', signup);
router.post('/api/stashes', createStash);
router.patch('/api/stashes/:stashId', updateStash); router.patch('/api/stashes/:stashId', updateStash);
router.post('/api/stashes/:stashId/actors', stashActor); router.post('/api/stashes/:stashId/actors', stashActor);

View File

@ -1,6 +1,7 @@
'use strict'; 'use strict';
const { const {
createStash,
stashActor, stashActor,
stashScene, stashScene,
stashMovie, stashMovie,
@ -10,6 +11,12 @@ const {
updateStash, updateStash,
} = require('../stashes'); } = require('../stashes');
async function createStashApi(req, res) {
const stash = await createStash(req.body, req.session.user);
res.send(stash);
}
async function updateStashApi(req, res) { async function updateStashApi(req, res) {
const stash = await updateStash(req.params.stashId, req.body, req.session.user); const stash = await updateStash(req.params.stashId, req.body, req.session.user);
@ -53,6 +60,7 @@ async function unstashMovieApi(req, res) {
} }
module.exports = { module.exports = {
createStash: createStashApi,
stashActor: stashActorApi, stashActor: stashActorApi,
stashScene: stashSceneApi, stashScene: stashSceneApi,
stashMovie: stashMovieApi, stashMovie: stashMovieApi,