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