Added visibility toggle to stash tile. Collapsed stash page directory structure.
This commit is contained in:
parent
f6b50cc732
commit
ce4b9e7d40
|
@ -1,6 +1,7 @@
|
||||||
<template>
|
<template>
|
||||||
|
<div class="page">
|
||||||
<div v-if="is404">
|
<div v-if="is404">
|
||||||
<h1>404 Page Not Found</h1>
|
<h1>404 Not Found</h1>
|
||||||
|
|
||||||
<p v-if="abortReason">{{ abortReason }}</p>
|
<p v-if="abortReason">{{ abortReason }}</p>
|
||||||
<p v-else>This page could not be found.</p>
|
<p v-else>This page could not be found.</p>
|
||||||
|
@ -10,6 +11,7 @@
|
||||||
<h1>500 Internal Error</h1>
|
<h1>500 Internal Error</h1>
|
||||||
<p>Something went wrong.</p>
|
<p>Something went wrong.</p>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
|
@ -25,3 +27,10 @@ defineProps({
|
||||||
const pageContext = inject('pageContext');
|
const pageContext = inject('pageContext');
|
||||||
const { abortReason } = pageContext;
|
const { abortReason } = pageContext;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.page {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
|
@ -16,11 +16,12 @@
|
||||||
:key="`stash-${stash.id}`"
|
:key="`stash-${stash.id}`"
|
||||||
>
|
>
|
||||||
<div class="stash">
|
<div class="stash">
|
||||||
|
<div class="stash-header">
|
||||||
<a
|
<a
|
||||||
:href="`/stash/${profile.username}/${stash.slug}`"
|
:href="`/stash/${profile.username}/${stash.slug}`"
|
||||||
class="stash-name nolink"
|
class="stash-name ellipsis nolink"
|
||||||
>
|
>
|
||||||
{{ stash.name }}
|
<span class="ellipsis">{{ stash.name }}</span>
|
||||||
|
|
||||||
<Icon
|
<Icon
|
||||||
v-if="stash.primary"
|
v-if="stash.primary"
|
||||||
|
@ -29,6 +30,21 @@
|
||||||
/>
|
/>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
|
<Icon
|
||||||
|
v-if="profile.id === user?.id && stash.public"
|
||||||
|
icon="eye"
|
||||||
|
class="public noselect"
|
||||||
|
@click="setStashPublic(stash, false)"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Icon
|
||||||
|
v-else-if="profile.id === user?.id"
|
||||||
|
icon="eye-blocked"
|
||||||
|
class="public noselect"
|
||||||
|
@click="setStashPublic(stash, true)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="stash-counts">
|
<div class="stash-counts">
|
||||||
<a
|
<a
|
||||||
:href="`/stash/${profile.username}/${stash.slug}/scenes`"
|
:href="`/stash/${profile.username}/${stash.slug}/scenes`"
|
||||||
|
@ -52,14 +68,48 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { inject } from 'vue';
|
import { ref, inject } from 'vue';
|
||||||
|
|
||||||
|
import { get, patch } from '#/src/api.js';
|
||||||
|
import events from '#/src/events.js';
|
||||||
|
|
||||||
const pageContext = inject('pageContext');
|
const pageContext = inject('pageContext');
|
||||||
const profile = pageContext.pageProps.profile;
|
const profile = ref(pageContext.pageProps.profile);
|
||||||
|
const user = pageContext.user;
|
||||||
|
const done = ref(true);
|
||||||
|
|
||||||
function abbreviateNumber(number) {
|
function abbreviateNumber(number) {
|
||||||
return number?.toLocaleString('en-US', { notation: 'compact' }) || 0;
|
return number?.toLocaleString('en-US', { notation: 'compact' }) || 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function setStashPublic(stash, isPublic) {
|
||||||
|
if (done.value === false) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
done.value = false;
|
||||||
|
|
||||||
|
await patch(`/stashes/${stash.id}`, { public: isPublic });
|
||||||
|
profile.value = await get(`/users/${profile.value.id}`);
|
||||||
|
|
||||||
|
events.emit('feedback', {
|
||||||
|
type: isPublic ? 'success' : 'remove',
|
||||||
|
message: isPublic
|
||||||
|
? `Stash '${stash.name}' is public`
|
||||||
|
: `Stash '${stash.name}' is private`,
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
|
||||||
|
events.emit('feedback', {
|
||||||
|
type: 'error',
|
||||||
|
message: 'Failed to update stash',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
done.value = true;
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
@ -73,11 +123,12 @@ function abbreviateNumber(number) {
|
||||||
|
|
||||||
.username {
|
.username {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
font-size: 1.25rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.avatar {
|
.avatar {
|
||||||
width: 2rem;
|
width: 1.5rem;
|
||||||
height: 2rem;
|
height: 1.5rem;
|
||||||
border-radius: .25rem;
|
border-radius: .25rem;
|
||||||
margin-right: 1rem;
|
margin-right: 1rem;
|
||||||
}
|
}
|
||||||
|
@ -99,11 +150,30 @@ function abbreviateNumber(number) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.stash-name {
|
.stash-header {
|
||||||
display: flex;
|
display: flex;
|
||||||
padding: .5rem;
|
align-items: stretch;
|
||||||
border-bottom: solid 1px var(--shadow-weak-30);
|
border-bottom: solid 1px var(--shadow-weak-30);
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon.public {
|
||||||
|
display: flex;
|
||||||
|
height: auto;
|
||||||
|
padding: 0 .75rem;
|
||||||
|
fill: var(--shadow);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
cursor: pointer;
|
||||||
|
fill: var(--shadow-strong-30);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.stash-name {
|
||||||
|
display: flex;
|
||||||
|
flex-grow: 1;
|
||||||
|
padding: .5rem;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
.icon {
|
.icon {
|
||||||
margin-left: .75rem;
|
margin-left: .75rem;
|
||||||
|
@ -111,6 +181,7 @@ function abbreviateNumber(number) {
|
||||||
|
|
||||||
.icon.primary {
|
.icon.primary {
|
||||||
fill: var(--primary);
|
fill: var(--primary);
|
||||||
|
transform: translateY(1px);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@ import { render } from 'vike/abort'; /* eslint-disable-line import/extensions */
|
||||||
import { fetchUser } from '#/src/users.js';
|
import { fetchUser } from '#/src/users.js';
|
||||||
|
|
||||||
export async function onBeforeRender(pageContext) {
|
export async function onBeforeRender(pageContext) {
|
||||||
const profile = await fetchUser(pageContext.routeParams.username);
|
const profile = await fetchUser(pageContext.routeParams.username, {}, pageContext.user);
|
||||||
|
|
||||||
if (!profile) {
|
if (!profile) {
|
||||||
throw render(404, `Cannot find user '${pageContext.routeParams.username}'.`);
|
throw render(404, `Cannot find user '${pageContext.routeParams.username}'.`);
|
||||||
|
|
19
src/users.js
19
src/users.js
|
@ -25,20 +25,20 @@ export function curateUser(user, assets = {}) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function whereUser(builder, userId, options = {}) {
|
function whereUser(builder, userId, options = {}) {
|
||||||
if (typeof userId === 'number') {
|
if (Number.isNaN(Number(userId))) {
|
||||||
builder.where('users.id', userId);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof userId === 'string') {
|
|
||||||
builder.where(knex.raw('lower(users.username)'), userId.toLowerCase());
|
builder.where(knex.raw('lower(users.username)'), userId.toLowerCase());
|
||||||
|
|
||||||
if (options.email) {
|
if (options.email) {
|
||||||
builder.orWhere(knex.raw('lower(users.email)'), userId.toLowerCase());
|
builder.orWhere(knex.raw('lower(users.email)'), userId.toLowerCase());
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function fetchUser(userId, options = {}) {
|
builder.where('users.id', Number(userId));
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function fetchUser(userId, options = {}, reqUser) {
|
||||||
const user = await knex('users')
|
const user = await knex('users')
|
||||||
.select(knex.raw('users.*, users_roles.abilities as role_abilities'))
|
.select(knex.raw('users.*, users_roles.abilities as role_abilities'))
|
||||||
.modify((builder) => whereUser(builder, userId, options))
|
.modify((builder) => whereUser(builder, userId, options))
|
||||||
|
@ -52,6 +52,11 @@ export async function fetchUser(userId, options = {}) {
|
||||||
|
|
||||||
const stashes = await knex('stashes')
|
const stashes = await knex('stashes')
|
||||||
.where('user_id', user.id)
|
.where('user_id', user.id)
|
||||||
|
.modify((builder) => {
|
||||||
|
if (reqUser?.id !== user.id) {
|
||||||
|
builder.where('public', true);
|
||||||
|
}
|
||||||
|
})
|
||||||
.leftJoin('stashes_meta', 'stashes_meta.stash_id', 'stashes.id');
|
.leftJoin('stashes_meta', 'stashes_meta.stash_id', 'stashes.id');
|
||||||
|
|
||||||
if (options.raw) {
|
if (options.raw) {
|
||||||
|
|
|
@ -24,6 +24,10 @@ import {
|
||||||
signupApi,
|
signupApi,
|
||||||
} from './auth.js';
|
} from './auth.js';
|
||||||
|
|
||||||
|
import {
|
||||||
|
fetchUserApi
|
||||||
|
} from './users.js';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
createStashApi,
|
createStashApi,
|
||||||
removeStashApi,
|
removeStashApi,
|
||||||
|
@ -96,6 +100,7 @@ export default async function initServer() {
|
||||||
router.delete('/api/session', logoutApi);
|
router.delete('/api/session', logoutApi);
|
||||||
|
|
||||||
// USERS
|
// USERS
|
||||||
|
router.get('/api/users/:userId', fetchUserApi);
|
||||||
router.post('/api/users', signupApi);
|
router.post('/api/users', signupApi);
|
||||||
|
|
||||||
// STASHES
|
// STASHES
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
import { fetchUser } from '../users.js';
|
||||||
|
|
||||||
|
export async function fetchUserApi(req, res) {
|
||||||
|
const user = await fetchUser(req.params.userId, {}, req.user);
|
||||||
|
|
||||||
|
res.send(user);
|
||||||
|
}
|
Loading…
Reference in New Issue