Compare commits

..

No commits in common. "9de289a0fb25281aae44800874414cc8020ac7c7" and "f6b50cc732d8f016644fabeae1d9e5a33297ea24" have entirely different histories.

17 changed files with 33 additions and 130 deletions

4
package-lock.json generated
View File

@ -1,11 +1,11 @@
{ {
"name": "traxxx-web", "name": "traxxx-web",
"version": "0.15.1", "version": "0.15.0",
"lockfileVersion": 2, "lockfileVersion": 2,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"version": "0.15.1", "version": "0.15.0",
"dependencies": { "dependencies": {
"@brillout/json-serializer": "^0.5.8", "@brillout/json-serializer": "^0.5.8",
"@dicebear/collection": "^7.0.5", "@dicebear/collection": "^7.0.5",

View File

@ -71,5 +71,5 @@
"postcss-custom-media": "^10.0.2", "postcss-custom-media": "^10.0.2",
"postcss-nesting": "^12.0.2" "postcss-nesting": "^12.0.2"
}, },
"version": "0.15.1" "version": "0.15.0"
} }

View File

@ -1,16 +1,14 @@
<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>
</div> </div>
<div v-else> <div v-else>
<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>
@ -27,10 +25,3 @@ 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>

View File

@ -16,34 +16,18 @@
: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
v-if="stash.primary"
icon="heart7"
class="primary"
/>
</a>
<Icon <Icon
v-if="profile.id === user?.id && stash.public" v-if="stash.primary"
icon="eye" icon="heart7"
class="public noselect" class="primary"
@click="setStashPublic(stash, false)"
/> />
</a>
<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
@ -68,48 +52,14 @@
</template> </template>
<script setup> <script setup>
import { ref, inject } from 'vue'; import { 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 = ref(pageContext.pageProps.profile); const profile = 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>
@ -123,12 +73,11 @@ async function setStashPublic(stash, isPublic) {
.username { .username {
margin: 0; margin: 0;
font-size: 1.25rem;
} }
.avatar { .avatar {
width: 1.5rem; width: 2rem;
height: 1.5rem; height: 2rem;
border-radius: .25rem; border-radius: .25rem;
margin-right: 1rem; margin-right: 1rem;
} }
@ -150,30 +99,11 @@ async function setStashPublic(stash, isPublic) {
} }
} }
.stash-header {
display: flex;
align-items: stretch;
border-bottom: solid 1px var(--shadow-weak-30);
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 { .stash-name {
display: flex; display: flex;
flex-grow: 1;
padding: .5rem; padding: .5rem;
overflow: hidden; border-bottom: solid 1px var(--shadow-weak-30);
font-weight: bold;
.icon { .icon {
margin-left: .75rem; margin-left: .75rem;
@ -181,7 +111,6 @@ async function setStashPublic(stash, isPublic) {
.icon.primary { .icon.primary {
fill: var(--primary); fill: var(--primary);
transform: translateY(1px);
} }
} }

View File

@ -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, {}, pageContext.user); const profile = await fetchUser(pageContext.routeParams.username);
if (!profile) { if (!profile) {
throw render(404, `Cannot find user '${pageContext.routeParams.username}'.`); throw render(404, `Cannot find user '${pageContext.routeParams.username}'.`);

View File

@ -25,20 +25,20 @@ export function curateUser(user, assets = {}) {
} }
function whereUser(builder, userId, options = {}) { function whereUser(builder, userId, options = {}) {
if (Number.isNaN(Number(userId))) { if (typeof userId === 'number') {
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;
} }
builder.where('users.id', Number(userId));
} }
export async function fetchUser(userId, options = {}, reqUser) { export async function fetchUser(userId, options = {}) {
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,11 +52,6 @@ export async function fetchUser(userId, options = {}, reqUser) {
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) {

View File

@ -24,10 +24,6 @@ import {
signupApi, signupApi,
} from './auth.js'; } from './auth.js';
import {
fetchUserApi
} from './users.js';
import { import {
createStashApi, createStashApi,
removeStashApi, removeStashApi,
@ -100,7 +96,6 @@ 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

View File

@ -1,7 +0,0 @@
import { fetchUser } from '../users.js';
export async function fetchUserApi(req, res) {
const user = await fetchUser(req.params.userId, {}, req.user);
res.send(user);
}