mirror of
https://github.com/BillyOutlast/drop.git
synced 2026-02-04 00:31:17 +01:00
Small fixes (#141)
* fix: save task as Json rather than string * fix: pull objects before creating game in database * fix: strips relative dirs from version information * fix: #132 * fix: lint * fix: news object ids and small tweaks * fix: notification styling errors * fix: lint
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="flex grow flex-col gap-y-5 overflow-y-auto px-6 py-4">
|
<div class="flex grow flex-col gap-y-5 overflow-y-auto px-6 py-4">
|
||||||
<span class="inline-flex items-center gap-x-2 font-semibold text-zinc-100">
|
<span class="inline-flex items-center gap-x-2 font-semibold text-zinc-100">
|
||||||
<UserIcon class="size-5" /> {{ $t("account.settings") }}
|
<UserIcon class="size-5" /> {{ $t("account.title") }}
|
||||||
</span>
|
</span>
|
||||||
<nav class="flex flex-1 flex-col">
|
<nav class="flex flex-1 flex-col">
|
||||||
<ul role="list" class="flex flex-1 flex-col gap-y-7">
|
<ul role="list" class="flex flex-1 flex-col gap-y-7">
|
||||||
@@ -74,7 +74,7 @@ const navigation: (NavigationItem & { icon: Component; count?: number })[] = [
|
|||||||
count: notifications.value.length,
|
count: notifications.value.length,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t("settings"),
|
label: t("account.settings"),
|
||||||
route: "/account/settings",
|
route: "/account/settings",
|
||||||
prefix: "/account/settings",
|
prefix: "/account/settings",
|
||||||
icon: WrenchScrewdriverIcon,
|
icon: WrenchScrewdriverIcon,
|
||||||
|
|||||||
@@ -91,9 +91,7 @@
|
|||||||
:src="useObject(article.imageObjectId)"
|
:src="useObject(article.imageObjectId)"
|
||||||
class="absolute blur-sm inset-0 w-full h-full object-cover transition-all duration-200 group-hover:scale-110"
|
class="absolute blur-sm inset-0 w-full h-full object-cover transition-all duration-200 group-hover:scale-110"
|
||||||
/>
|
/>
|
||||||
<div
|
<div class="absolute inset-0 bg-zinc-900/50" />
|
||||||
class="absolute inset-0 bg-gradient-to-b from-transparent to-zinc-800 transition-all duration-200"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h3 class="relative text-sm font-medium text-zinc-100">
|
<h3 class="relative text-sm font-medium text-zinc-100">
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="relative inline-block group">
|
<div class="relative inline-block group/relative-time">
|
||||||
<!-- Visible relative time -->
|
<!-- Visible relative time -->
|
||||||
<time :datetime="isoDate" class="text-sm text-muted-foreground">
|
<time :datetime="isoDate" class="text-sm text-muted-foreground">
|
||||||
{{ DateTime.fromJSDate(date).toRelative({ locale: $i18n.locale }) }}
|
{{ DateTime.fromJSDate(date).toRelative({ locale: $i18n.locale }) }}
|
||||||
@@ -8,7 +8,7 @@
|
|||||||
<!-- Custom tooltip that shows on hover -->
|
<!-- Custom tooltip that shows on hover -->
|
||||||
<div
|
<div
|
||||||
role="tooltip"
|
role="tooltip"
|
||||||
class="absolute bottom-full left-1/2 -translate-x-1/2 mb-1 px-2 py-1 rounded bg-zinc-900 text-white text-xs whitespace-nowrap shadow z-10 opacity-0 group-hover:opacity-100 transition-opacity pointer-events-none"
|
class="absolute bottom-full left-1/2 -translate-x-1/2 mb-1 px-2 py-1 rounded bg-zinc-900 text-white text-xs whitespace-nowrap shadow z-10 opacity-0 group-hover/relative-time:opacity-100 transition-opacity pointer-events-none"
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
>
|
>
|
||||||
{{ $d(date, "long") }}
|
{{ $d(date, "long") }}
|
||||||
|
|||||||
@@ -19,8 +19,8 @@
|
|||||||
"title": "Notifications",
|
"title": "Notifications",
|
||||||
"unread": "Unread Notifications"
|
"unread": "Unread Notifications"
|
||||||
},
|
},
|
||||||
"settings": "Account Settings",
|
"settings": "Settings",
|
||||||
"title": "Account"
|
"title": "Account Settings"
|
||||||
},
|
},
|
||||||
"actions": "Actions",
|
"actions": "Actions",
|
||||||
"adminTitle": "Admin Dashboard | Drop",
|
"adminTitle": "Admin Dashboard | Drop",
|
||||||
|
|||||||
@@ -40,14 +40,16 @@
|
|||||||
{{ notification.description }}
|
{{ notification.description }}
|
||||||
</p>
|
</p>
|
||||||
<div class="mt-4 flex flex-wrap gap-2">
|
<div class="mt-4 flex flex-wrap gap-2">
|
||||||
<a
|
<NuxtLink
|
||||||
v-for="action in notification.actions"
|
v-for="[name, href] in notification.actions.map((v) =>
|
||||||
:key="action"
|
v.split('|'),
|
||||||
:href="action.split('|')[1]"
|
)"
|
||||||
|
:key="href"
|
||||||
|
:href="href"
|
||||||
class="inline-flex items-center rounded-md bg-blue-400/10 px-2 py-1 text-xs font-medium text-blue-400 ring-1 ring-inset ring-blue-400/20 transition-all duration-200 hover:bg-blue-400/20 hover:scale-105 active:scale-95"
|
class="inline-flex items-center rounded-md bg-blue-400/10 px-2 py-1 text-xs font-medium text-blue-400 ring-1 ring-inset ring-blue-400/20 transition-all duration-200 hover:bg-blue-400/20 hover:scale-105 active:scale-95"
|
||||||
>
|
>
|
||||||
{{ action.split("|")[0] }}
|
{{ name }}
|
||||||
</a>
|
</NuxtLink>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="ml-4 flex flex-shrink-0 items-center gap-x-2">
|
<div class="ml-4 flex flex-shrink-0 items-center gap-x-2">
|
||||||
@@ -57,7 +59,7 @@
|
|||||||
<button
|
<button
|
||||||
v-if="!notification.read"
|
v-if="!notification.read"
|
||||||
type="button"
|
type="button"
|
||||||
class="inline-flex items-center rounded-md bg-zinc-400/10 px-2 py-1 text-xs font-medium text-zinc-400 ring-1 ring-inset ring-zinc-400/20 transition-all duration-200 hover:bg-zinc-400/20 hover:scale-105 active:scale-95"
|
class="inline-flex gap-x-1 items-center rounded-md bg-zinc-400/10 px-2 py-1 text-xs font-medium text-zinc-400 ring-1 ring-inset ring-zinc-400/20 transition-all duration-200 hover:bg-zinc-400/20 hover:scale-105 active:scale-95"
|
||||||
@click="markAsRead(notification.id)"
|
@click="markAsRead(notification.id)"
|
||||||
>
|
>
|
||||||
<CheckIcon class="size-3" />
|
<CheckIcon class="size-3" />
|
||||||
@@ -65,7 +67,7 @@
|
|||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
class="inline-flex items-center rounded-md bg-red-400/10 px-2 py-1 text-xs font-medium text-red-400 ring-1 ring-inset ring-red-400/20 transition-all duration-200 hover:bg-red-400/20 hover:scale-105 active:scale-95"
|
class="inline-flex gap-x-1 items-center rounded-md bg-red-400/10 px-2 py-1 text-xs font-medium text-red-400 ring-1 ring-inset ring-red-400/20 transition-all duration-200 hover:bg-red-400/20 hover:scale-105 active:scale-95"
|
||||||
@click="deleteNotification(notification.id)"
|
@click="deleteNotification(notification.id)"
|
||||||
>
|
>
|
||||||
<TrashIcon class="size-3" />
|
<TrashIcon class="size-3" />
|
||||||
|
|||||||
@@ -86,7 +86,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="px-4 py-10 sm:px-6 lg:px-8 lg:py-6 grow">
|
<div class="px-4 py-10 sm:px-6 lg:px-8 lg:py-6 grow">
|
||||||
<NuxtPage />
|
<NuxtPage :articles="news" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -1,12 +1,16 @@
|
|||||||
<!-- eslint-disable vue/no-v-html -->
|
<!-- eslint-disable vue/no-v-html -->
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<div v-if="article" class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
<div v-if="article" class="px-4 sm:px-6 lg:px-8">
|
||||||
<!-- Banner header with blurred background -->
|
<!-- Banner header with blurred background -->
|
||||||
<div class="relative w-full h-[300px] mb-8 rounded-lg overflow-hidden">
|
<div class="relative w-full h-[300px] mb-8 rounded-lg overflow-hidden">
|
||||||
<div v-if="article.imageObjectId" class="absolute inset-0">
|
<div class="absolute inset-0">
|
||||||
<img
|
<img
|
||||||
:src="useObject(article.imageObjectId)"
|
:src="
|
||||||
|
article.imageObjectId
|
||||||
|
? useObject(article.imageObjectId)
|
||||||
|
: '/wallpapers/news-placeholder.jpg'
|
||||||
|
"
|
||||||
alt=""
|
alt=""
|
||||||
class="w-full h-full object-cover blur-sm scale-110"
|
class="w-full h-full object-cover blur-sm scale-110"
|
||||||
/>
|
/>
|
||||||
@@ -14,12 +18,6 @@
|
|||||||
class="absolute inset-0 bg-gradient-to-b from-transparent to-zinc-950"
|
class="absolute inset-0 bg-gradient-to-b from-transparent to-zinc-950"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div v-else>
|
|
||||||
<!-- Fallback gradient background when no image -->
|
|
||||||
<div
|
|
||||||
class="absolute inset-0 bg-gradient-to-b from-zinc-800 to-zinc-900"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="relative h-full flex flex-col justify-end p-8">
|
<div class="relative h-full flex flex-col justify-end p-8">
|
||||||
<div class="flex items-center gap-x-3 mb-6">
|
<div class="flex items-center gap-x-3 mb-6">
|
||||||
@@ -73,7 +71,7 @@
|
|||||||
|
|
||||||
<!-- Article content - markdown -->
|
<!-- Article content - markdown -->
|
||||||
<div
|
<div
|
||||||
class="mx-auto prose prose-invert prose-lg"
|
class="mx-auto prose prose-blue prose-invert prose-lg"
|
||||||
v-html="renderedContent"
|
v-html="renderedContent"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="flex flex-col max-w-4xl mx-auto">
|
<div class="flex flex-col px-8">
|
||||||
<div class="mb-8">
|
<div class="mb-8">
|
||||||
<div class="flex flex-col gap-y-4">
|
<div class="flex flex-col gap-y-4">
|
||||||
<div>
|
<div>
|
||||||
@@ -14,7 +14,11 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Articles list -->
|
<!-- Articles list -->
|
||||||
<TransitionGroup name="article-list" tag="div" class="space-y-6">
|
<TransitionGroup
|
||||||
|
name="article-list"
|
||||||
|
tag="div"
|
||||||
|
class="gap-6 grid sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-5"
|
||||||
|
>
|
||||||
<NuxtLink
|
<NuxtLink
|
||||||
v-for="article in articles"
|
v-for="article in articles"
|
||||||
:key="article.id"
|
:key="article.id"
|
||||||
@@ -26,8 +30,11 @@
|
|||||||
>
|
>
|
||||||
<div class="relative h-48 w-full overflow-hidden">
|
<div class="relative h-48 w-full overflow-hidden">
|
||||||
<img
|
<img
|
||||||
v-if="article.imageObjectId"
|
:src="
|
||||||
:src="useObject(article.imageObjectId)"
|
article.imageObjectId
|
||||||
|
? useObject(article.imageObjectId)
|
||||||
|
: '/wallpapers/news-placeholder.jpg'
|
||||||
|
"
|
||||||
alt=""
|
alt=""
|
||||||
class="h-full w-full object-cover object-center transition-all duration-500 group-hover:scale-110 scale-105"
|
class="h-full w-full object-cover object-center transition-all duration-500 group-hover:scale-110 scale-105"
|
||||||
/>
|
/>
|
||||||
|
|||||||
BIN
public/wallpapers/news-placeholder.jpg
Normal file
BIN
public/wallpapers/news-placeholder.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.9 MiB |
@@ -51,7 +51,7 @@ export default defineEventHandler(async (h3) => {
|
|||||||
|
|
||||||
tags: parsedTags,
|
tags: parsedTags,
|
||||||
|
|
||||||
...(imageId && { image: imageId }),
|
...(imageId && { imageObjectId: imageId }),
|
||||||
authorId: "system",
|
authorId: "system",
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -147,14 +147,14 @@ class LibraryManager {
|
|||||||
}> = [];
|
}> = [];
|
||||||
|
|
||||||
const files = await library.versionReaddir(game.libraryPath, versionName);
|
const files = await library.versionReaddir(game.libraryPath, versionName);
|
||||||
for (const file of files) {
|
for (const filename of files) {
|
||||||
const filename = path.basename(file);
|
const basename = path.basename(filename);
|
||||||
const dotLocation = file.lastIndexOf(".");
|
const dotLocation = filename.lastIndexOf(".");
|
||||||
const ext = dotLocation == -1 ? "" : file.slice(dotLocation);
|
const ext = dotLocation == -1 ? "" : filename.slice(dotLocation);
|
||||||
for (const [platform, checkExts] of Object.entries(fileExts)) {
|
for (const [platform, checkExts] of Object.entries(fileExts)) {
|
||||||
for (const checkExt of checkExts) {
|
for (const checkExt of checkExts) {
|
||||||
if (checkExt != ext) continue;
|
if (checkExt != ext) continue;
|
||||||
const fuzzyValue = fuzzy(filename, game.mName);
|
const fuzzyValue = fuzzy(basename, game.mName);
|
||||||
options.push({
|
options.push({
|
||||||
filename,
|
filename,
|
||||||
platform,
|
platform,
|
||||||
|
|||||||
@@ -197,8 +197,8 @@ export class MetadataHandler {
|
|||||||
{},
|
{},
|
||||||
["internal:read"],
|
["internal:read"],
|
||||||
wrapTaskContext(context, {
|
wrapTaskContext(context, {
|
||||||
min: 63,
|
min: 60,
|
||||||
max: 100,
|
max: 95,
|
||||||
prefix: "[object import] ",
|
prefix: "[object import] ",
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
@@ -227,6 +227,13 @@ export class MetadataHandler {
|
|||||||
|
|
||||||
context?.progress(60);
|
context?.progress(60);
|
||||||
|
|
||||||
|
logger.info(`Successfully fetched all metadata.`);
|
||||||
|
logger.info(`Importing objects...`);
|
||||||
|
|
||||||
|
await pullObjects();
|
||||||
|
|
||||||
|
progress(95);
|
||||||
|
|
||||||
await prisma.game.create({
|
await prisma.game.create({
|
||||||
data: {
|
data: {
|
||||||
id: gameId,
|
id: gameId,
|
||||||
@@ -262,12 +269,6 @@ export class MetadataHandler {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
progress(63);
|
|
||||||
logger.info(`Successfully fetched all metadata.`);
|
|
||||||
logger.info(`Importing objects...`);
|
|
||||||
|
|
||||||
await pullObjects();
|
|
||||||
|
|
||||||
logger.info(`Finished game import.`);
|
logger.info(`Finished game import.`);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ class NewsManager {
|
|||||||
description: string;
|
description: string;
|
||||||
tags: string[];
|
tags: string[];
|
||||||
authorId: string;
|
authorId: string;
|
||||||
image?: string;
|
imageObjectId?: string;
|
||||||
}) {
|
}) {
|
||||||
return await prisma.article.create({
|
return await prisma.article.create({
|
||||||
data: {
|
data: {
|
||||||
@@ -23,7 +23,7 @@ class NewsManager {
|
|||||||
})),
|
})),
|
||||||
},
|
},
|
||||||
|
|
||||||
...(data.image && { image: data.image }),
|
...(data.imageObjectId && { imageObjectId: data.imageObjectId }),
|
||||||
author: {
|
author: {
|
||||||
connect: {
|
connect: {
|
||||||
id: data.authorId,
|
id: data.authorId,
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ class TaskHandler {
|
|||||||
this.taskCreators.set(task.taskGroup, task.build);
|
this.taskCreators.set(task.taskGroup, task.build);
|
||||||
}
|
}
|
||||||
|
|
||||||
create(task: Task) {
|
async create(task: Task) {
|
||||||
let updateCollectTimeout: NodeJS.Timeout | undefined;
|
let updateCollectTimeout: NodeJS.Timeout | undefined;
|
||||||
let updateCollectResolves: Array<(value: unknown) => void> = [];
|
let updateCollectResolves: Array<(value: unknown) => void> = [];
|
||||||
let logOffset: number = 0;
|
let logOffset: number = 0;
|
||||||
@@ -131,44 +131,6 @@ class TaskHandler {
|
|||||||
|
|
||||||
const taskPool = this.taskPool;
|
const taskPool = this.taskPool;
|
||||||
|
|
||||||
// Create a pino transport that replicates the old log function behavior
|
|
||||||
// const taskLogger = pino({
|
|
||||||
// hooks: {
|
|
||||||
// logMethod(args, method) {
|
|
||||||
// // Combine all arguments into a single string message
|
|
||||||
// const message = args.map(String).join(" ");
|
|
||||||
// const now = new Date();
|
|
||||||
|
|
||||||
// const pad = (n: number, width = 2) =>
|
|
||||||
// n.toString().padStart(width, "0");
|
|
||||||
|
|
||||||
// const year = now.getUTCFullYear();
|
|
||||||
// const month = pad(now.getUTCMonth() + 1);
|
|
||||||
// const day = pad(now.getUTCDate());
|
|
||||||
|
|
||||||
// const hours = pad(now.getUTCHours());
|
|
||||||
// const minutes = pad(now.getUTCMinutes());
|
|
||||||
// const seconds = pad(now.getUTCSeconds());
|
|
||||||
// const milliseconds = pad(now.getUTCMilliseconds(), 3);
|
|
||||||
|
|
||||||
// const logObj = {
|
|
||||||
// timestamp: `${year}-${month}-${day} ${hours}:${minutes}:${seconds}.${milliseconds} UTC`,
|
|
||||||
// message,
|
|
||||||
// };
|
|
||||||
|
|
||||||
// // Push the formatted log string to the task's log array
|
|
||||||
// const taskEntry = taskPool.get(task.id);
|
|
||||||
// if (taskEntry) {
|
|
||||||
// taskEntry.log.push(JSON.stringify(logObj));
|
|
||||||
// updateAllClients();
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // Optionally, still call the original method if you want logs elsewhere
|
|
||||||
// method.apply(this, args);
|
|
||||||
// },
|
|
||||||
// },
|
|
||||||
// });
|
|
||||||
|
|
||||||
// Custom writable stream to capture logs
|
// Custom writable stream to capture logs
|
||||||
const logStream = new Writable({
|
const logStream = new Writable({
|
||||||
objectMode: true,
|
objectMode: true,
|
||||||
@@ -227,7 +189,7 @@ class TaskHandler {
|
|||||||
endTime: undefined,
|
endTime: undefined,
|
||||||
});
|
});
|
||||||
|
|
||||||
updateAllClients(true);
|
await updateAllClients(true);
|
||||||
|
|
||||||
droplet.callAltThreadFunc(async () => {
|
droplet.callAltThreadFunc(async () => {
|
||||||
const taskEntry = this.taskPool.get(task.id);
|
const taskEntry = this.taskPool.get(task.id);
|
||||||
@@ -267,9 +229,7 @@ class TaskHandler {
|
|||||||
|
|
||||||
acls: taskEntry.acls,
|
acls: taskEntry.acls,
|
||||||
|
|
||||||
...(taskEntry.error
|
...(taskEntry.error ? { error: taskEntry.error } : undefined),
|
||||||
? { error: JSON.stringify(taskEntry.error) }
|
|
||||||
: undefined),
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user