mirror of
https://github.com/Drop-OSS/drop.git
synced 2026-06-22 04:11:32 +10:00
fix: more eslint issues
This commit is contained in:
@@ -18,8 +18,8 @@ const carousel = inject(injectCarousel)!;
|
||||
|
||||
const amount = carousel.maxSlide - carousel.minSlide + 1;
|
||||
|
||||
function slideTo(index: number) {
|
||||
const offsetIndex = index + carousel.minSlide;
|
||||
carousel.nav.slideTo(offsetIndex);
|
||||
}
|
||||
// function slideTo(index: number) {
|
||||
// const offsetIndex = index + carousel.minSlide;
|
||||
// carousel.nav.slideTo(offsetIndex);
|
||||
// }
|
||||
</script>
|
||||
|
||||
@@ -58,7 +58,7 @@ const emit = defineEmits<{
|
||||
created: [collectionId: string];
|
||||
}>();
|
||||
|
||||
const open: Ref<boolean> = defineModel<boolean>();
|
||||
const open = defineModel<boolean>({ required: true });
|
||||
|
||||
const collectionName = ref("");
|
||||
const createCollectionLoading = ref(false);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="flex flex-row items-center gap-x-2">
|
||||
<img :src="game.icon" class="w-12 h-12 rounded-sm object-cover" >
|
||||
<img :src="game.icon" class="w-12 h-12 rounded-sm object-cover" />
|
||||
<div class="flex flex-col items-left">
|
||||
<h1 class="font-semibold font-display text-lg text-zinc-100">
|
||||
{{ game.name }}
|
||||
@@ -18,7 +18,7 @@
|
||||
<script setup lang="ts">
|
||||
import type { GameMetadataSearchResult } from "~/server/internal/metadata/types";
|
||||
|
||||
const props = defineProps<{
|
||||
const { game } = defineProps<{
|
||||
game: GameMetadataSearchResult & { sourceName?: string };
|
||||
}>();
|
||||
</script>
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
autocomplete="off"
|
||||
class="block w-full rounded-md bg-zinc-900 py-2 pl-9 pr-2 text-sm text-zinc-100 outline outline-1 -outline-offset-1 outline-zinc-700 placeholder:text-gray-400 focus:outline focus:outline-2 focus:-outline-offset-2 focus:outline-blue-600"
|
||||
placeholder="Search library..."
|
||||
>
|
||||
/>
|
||||
<MagnifyingGlassIcon
|
||||
class="pointer-events-none absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-zinc-400"
|
||||
aria-hidden="true"
|
||||
@@ -37,9 +37,11 @@
|
||||
:src="useObject(game.mCoverId)"
|
||||
class="h-9 w-9 flex-shrink-0 rounded transition-all duration-300 group-hover:scale-105 hover:rotate-[-2deg] hover:shadow-lg"
|
||||
alt=""
|
||||
>
|
||||
/>
|
||||
<div class="min-w-0 flex-1 pl-2.5">
|
||||
<p class="text-sm font-semibold text-display text-zinc-200 truncate text-left">
|
||||
<p
|
||||
class="text-sm font-semibold text-display text-zinc-200 truncate text-left"
|
||||
>
|
||||
{{ game.mName }}
|
||||
</p>
|
||||
</div>
|
||||
@@ -57,7 +59,6 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { HomeIcon } from "@heroicons/vue/24/outline";
|
||||
import { Bars3Icon, MagnifyingGlassIcon } from "@heroicons/vue/24/solid";
|
||||
|
||||
const library = await useLibrary();
|
||||
@@ -68,7 +69,7 @@ const filteredLibrary = computed(() =>
|
||||
library.value.entries
|
||||
.map((e) => e.game)
|
||||
.filter((e) =>
|
||||
e.mName.toLowerCase().includes(searchQuery.value.toLowerCase())
|
||||
)
|
||||
e.mName.toLowerCase().includes(searchQuery.value.toLowerCase()),
|
||||
),
|
||||
);
|
||||
</script>
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
autocomplete="off"
|
||||
class="mt-1 block w-full rounded-md bg-zinc-900 border-zinc-700 text-zinc-100 shadow-sm focus:border-primary-500 focus:ring-primary-500"
|
||||
required
|
||||
>
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
@@ -42,7 +42,7 @@
|
||||
type="text"
|
||||
class="mt-1 block w-full rounded-md bg-zinc-900 border-zinc-700 text-zinc-100 shadow-sm focus:border-primary-500 focus:ring-primary-500"
|
||||
required
|
||||
>
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
@@ -124,8 +124,8 @@
|
||||
accept="image/*"
|
||||
class="hidden"
|
||||
type="file"
|
||||
@change="(e) => file = (e.target as any)?.files"
|
||||
>
|
||||
@change="(e) => (file = (e.target as any)?.files)"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
@@ -155,7 +155,7 @@
|
||||
placeholder="Add a tag..."
|
||||
class="mt-1 block w-full rounded-md bg-zinc-900 border-zinc-700 text-zinc-100 shadow-sm focus:border-primary-500 focus:ring-primary-500"
|
||||
@keydown.enter.prevent="addTag"
|
||||
>
|
||||
/>
|
||||
<button
|
||||
type="button"
|
||||
class="mt-1 px-3 py-2 rounded-md bg-zinc-800 text-zinc-100 hover:bg-zinc-700"
|
||||
@@ -207,12 +207,10 @@ import {
|
||||
XCircleIcon,
|
||||
XMarkIcon,
|
||||
} from "@heroicons/vue/24/solid";
|
||||
import type { Article } from "@prisma/client";
|
||||
import { micromark } from "micromark";
|
||||
import type { SerializeObject } from "nitropack/types";
|
||||
|
||||
const news = useNews();
|
||||
if(!news.value){
|
||||
if (!news.value) {
|
||||
news.value = await fetchNews();
|
||||
}
|
||||
|
||||
@@ -230,6 +228,8 @@ const newArticle = ref({
|
||||
});
|
||||
|
||||
const markdownPreview = computed(() => {
|
||||
// TODO: maybe?? add https://github.com/cure53/DOMPurify
|
||||
// micromark says its safe, but this is straight html we are injecting
|
||||
return micromark(newArticle.value.content);
|
||||
});
|
||||
|
||||
@@ -302,7 +302,7 @@ function addTag() {
|
||||
|
||||
function removeTag(tagToRemove: string) {
|
||||
newArticle.value.tags = newArticle.value.tags.filter(
|
||||
(tag) => tag !== tagToRemove
|
||||
(tag) => tag !== tagToRemove,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -367,7 +367,8 @@ async function createArticle() {
|
||||
|
||||
modalOpen.value = false;
|
||||
} catch (e) {
|
||||
error.value = (e as any)?.statusMessage ?? "An unknown error occured.";
|
||||
// @ts-expect-error attempt to get statusMessage on error
|
||||
error.value = e?.statusMessage ?? "An unknown error occured.";
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
type="text"
|
||||
class="block w-full rounded-md border-0 bg-zinc-800 py-2.5 pl-10 pr-3 text-zinc-100 placeholder:text-zinc-400 focus:ring-2 focus:ring-inset focus:ring-blue-500 sm:text-sm sm:leading-6"
|
||||
placeholder="Search articles..."
|
||||
>
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -85,7 +85,7 @@
|
||||
<img
|
||||
:src="useObject(article.image)"
|
||||
class="absolute blur-sm inset-0 w-full h-full object-cover transition-all duration-200 group-hover:scale-110"
|
||||
>
|
||||
/>
|
||||
<div
|
||||
class="absolute inset-0 bg-gradient-to-b from-transparent to-zinc-800 transition-all duration-200"
|
||||
/>
|
||||
@@ -117,7 +117,7 @@ import { MagnifyingGlassIcon } from "@heroicons/vue/24/solid";
|
||||
import { micromark } from "micromark";
|
||||
|
||||
const news = useNews();
|
||||
if(!news.value){
|
||||
if (!news.value) {
|
||||
news.value = await fetchNews();
|
||||
}
|
||||
|
||||
@@ -154,6 +154,7 @@ const formatDate = (date: string) => {
|
||||
};
|
||||
|
||||
const formatExcerpt = (excerpt: string) => {
|
||||
// TODO: same as one in NewsArticleCreateButton
|
||||
// Convert markdown to HTML
|
||||
const html = micromark(excerpt);
|
||||
// Strip HTML tags using regex
|
||||
@@ -175,28 +176,32 @@ const filteredArticles = computed(() => {
|
||||
const now = new Date();
|
||||
let matchesDate = true;
|
||||
|
||||
switch (dateFilter.value) {
|
||||
case "today":
|
||||
switch (dateFilter.value.toLowerCase()) {
|
||||
case "today": {
|
||||
matchesDate = articleDate.toDateString() === now.toDateString();
|
||||
break;
|
||||
case "week":
|
||||
}
|
||||
case "week": {
|
||||
const weekAgo = new Date(now.setDate(now.getDate() - 7));
|
||||
matchesDate = articleDate >= weekAgo;
|
||||
break;
|
||||
case "month":
|
||||
}
|
||||
case "month": {
|
||||
matchesDate =
|
||||
articleDate.getMonth() === now.getMonth() &&
|
||||
articleDate.getFullYear() === now.getFullYear();
|
||||
break;
|
||||
case "year":
|
||||
}
|
||||
case "year": {
|
||||
matchesDate = articleDate.getFullYear() === now.getFullYear();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const matchesTags =
|
||||
selectedTags.value.length === 0 ||
|
||||
selectedTags.value.every((tag) =>
|
||||
article.tags.find((e) => e.name == tag)
|
||||
article.tags.find((e) => e.name == tag),
|
||||
);
|
||||
|
||||
return matchesSearch && matchesDate && matchesTags;
|
||||
|
||||
@@ -60,8 +60,8 @@
|
||||
:accept="props.accept"
|
||||
class="hidden"
|
||||
type="file"
|
||||
@change="(e) => file = (e.target as any)?.files"
|
||||
>
|
||||
@change="(e) => (file = (e.target as any)?.files)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -112,14 +112,15 @@ import { ref } from "vue";
|
||||
import {
|
||||
Dialog,
|
||||
DialogPanel,
|
||||
DialogTitle,
|
||||
TransitionChild,
|
||||
TransitionRoot,
|
||||
} from "@headlessui/vue";
|
||||
import { ArrowUpTrayIcon } from "@heroicons/vue/20/solid";
|
||||
import { XCircleIcon } from "@heroicons/vue/24/solid";
|
||||
|
||||
const open: Ref<boolean> = defineModel<boolean>() as any;
|
||||
const open = defineModel<boolean>({
|
||||
required: true,
|
||||
});
|
||||
|
||||
const file = ref<FileList | undefined>();
|
||||
const currentFile = computed(() => file.value?.item(0));
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<img
|
||||
:src="useObject(user.profilePicture)"
|
||||
class="w-5 h-5 rounded-sm"
|
||||
>
|
||||
/>
|
||||
<span class="ml-2 text-sm font-bold">{{ user.displayName }}</span>
|
||||
<ChevronDownIcon class="ml-3 h-4" />
|
||||
</div>
|
||||
@@ -33,7 +33,7 @@
|
||||
<img
|
||||
:src="useObject(user.profilePicture)"
|
||||
class="w-5 h-5 rounded-sm"
|
||||
>
|
||||
/>
|
||||
<span class="ml-2 text-sm font-bold">{{ user.displayName }}</span>
|
||||
</div>
|
||||
</NuxtLink>
|
||||
@@ -45,6 +45,7 @@
|
||||
v-slot="{ active, close }"
|
||||
hydrate-on-visible
|
||||
>
|
||||
<!-- TODO: think this would work better as a NuxtLink instead of a button -->
|
||||
<button
|
||||
:href="nav.route"
|
||||
:class="[
|
||||
@@ -92,9 +93,4 @@ const navigation: NavigationItem[] = [
|
||||
].filter((e) => e !== undefined);
|
||||
|
||||
const router = useRouter();
|
||||
|
||||
function navigateLink(href: string, closeFn: () => any) {
|
||||
closeFn();
|
||||
router.push(href);
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -6,7 +6,7 @@ type FullCollection = Collection & {
|
||||
};
|
||||
|
||||
export const useCollections = async () => {
|
||||
// @ts-expect-error
|
||||
// @ts-expect-error undefined is used to tell if value has been fetched or not
|
||||
const state = useState<FullCollection[]>("collections", () => undefined);
|
||||
if (state.value === undefined) {
|
||||
state.value = await $dropFetch<FullCollection[]>("/api/v1/collection");
|
||||
@@ -17,7 +17,9 @@ export const useCollections = async () => {
|
||||
|
||||
export async function refreshCollection(id: string) {
|
||||
const state = useState<FullCollection[]>("collections");
|
||||
const collection = await $dropFetch<FullCollection>(`/api/v1/collection/${id}`);
|
||||
const collection = await $dropFetch<FullCollection>(
|
||||
`/api/v1/collection/${id}`,
|
||||
);
|
||||
const index = state.value.findIndex((e) => e.id == id);
|
||||
if (index == -1) {
|
||||
state.value.push(collection);
|
||||
@@ -27,7 +29,7 @@ export async function refreshCollection(id: string) {
|
||||
}
|
||||
|
||||
export const useLibrary = async () => {
|
||||
// @ts-expect-error
|
||||
// @ts-expect-error undefined is used to tell if value has been fetched or not
|
||||
const state = useState<FullCollection>("library", () => undefined);
|
||||
if (state.value === undefined) {
|
||||
await refreshLibrary();
|
||||
|
||||
+1
-1
@@ -31,7 +31,7 @@ export const fetchNews = async (options?: {
|
||||
|
||||
const news = useNews();
|
||||
|
||||
// @ts-ignore
|
||||
// @ts-ignore forget why this ignor exists
|
||||
const newValue = await $dropFetch(`/api/v1/news?${query.toString()}`);
|
||||
|
||||
news.value = newValue;
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import type {
|
||||
$Fetch,
|
||||
ExtractedRouteMethod,
|
||||
NitroFetchOptions,
|
||||
NitroFetchRequest,
|
||||
@@ -8,15 +7,15 @@ import type {
|
||||
|
||||
interface DropFetch<
|
||||
DefaultT = unknown,
|
||||
DefaultR extends NitroFetchRequest = NitroFetchRequest
|
||||
DefaultR extends NitroFetchRequest = NitroFetchRequest,
|
||||
> {
|
||||
<
|
||||
T = DefaultT,
|
||||
R extends NitroFetchRequest = DefaultR,
|
||||
O extends NitroFetchOptions<R> = NitroFetchOptions<R>
|
||||
O extends NitroFetchOptions<R> = NitroFetchOptions<R>,
|
||||
>(
|
||||
request: R,
|
||||
opts?: O
|
||||
opts?: O,
|
||||
): Promise<
|
||||
// @ts-ignore
|
||||
TypedInternalResponse<
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
autocomplete="username"
|
||||
required
|
||||
class="block w-full rounded-md border-0 py-1.5 px-3 shadow-sm bg-zinc-950/20 text-zinc-300 ring-1 ring-inset ring-zinc-800 placeholder:text-zinc-400 focus:ring-2 focus:ring-inset focus:ring-blue-600 sm:text-sm sm:leading-6"
|
||||
>
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -53,7 +53,7 @@
|
||||
autocomplete="current-password"
|
||||
required
|
||||
class="block w-full rounded-md border-0 py-1.5 px-3 shadow-sm bg-zinc-950/20 text-zinc-300 ring-1 ring-inset ring-zinc-800 placeholder:text-zinc-400 focus:ring-2 focus:ring-inset focus:ring-blue-600 sm:text-sm sm:leading-6"
|
||||
>
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -65,7 +65,7 @@
|
||||
name="remember-me"
|
||||
type="checkbox"
|
||||
class="h-4 w-4 rounded bg-zinc-800 border-zinc-700 text-blue-600 focus:ring-blue-600"
|
||||
>
|
||||
/>
|
||||
<label
|
||||
for="remember-me"
|
||||
class="ml-3 block text-sm leading-6 text-zinc-400"
|
||||
@@ -113,7 +113,7 @@
|
||||
src="/wallpapers/signin.jpg"
|
||||
class="absolute inset-0 h-full w-full object-cover"
|
||||
alt=""
|
||||
>
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -121,7 +121,7 @@
|
||||
<script setup lang="ts">
|
||||
import { XCircleIcon } from "@heroicons/vue/20/solid";
|
||||
import type { User } from "@prisma/client";
|
||||
import Logo from "~/components/Logo.vue";
|
||||
import Logo from "~/components/DropLogo.vue";
|
||||
|
||||
const username = ref("");
|
||||
const password = ref("");
|
||||
|
||||
@@ -22,13 +22,13 @@
|
||||
src="/wallpapers/signin.jpg"
|
||||
class="absolute inset-0 h-full w-full object-cover"
|
||||
alt=""
|
||||
>
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import Logo from "~/components/Logo.vue";
|
||||
import Logo from "~/components/DropLogo.vue";
|
||||
const router = useRouter();
|
||||
|
||||
// Clear the user state
|
||||
|
||||
@@ -70,9 +70,9 @@
|
||||
class="whitespace-nowrap inline-flex gap-x-4 px-3 py-4 text-sm text-zinc-400"
|
||||
>
|
||||
<component
|
||||
:is="PLATFORM_ICONS[platform]"
|
||||
v-for="platform in platforms"
|
||||
:key="platform"
|
||||
:is="PLATFORM_ICONS[platform]"
|
||||
class="text-blue-600 w-6 h-6"
|
||||
/>
|
||||
<span
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { APITokenMode } from "@prisma/client";
|
||||
import { DateTime } from "luxon";
|
||||
import { UserACL } from "~/server/internal/acls";
|
||||
import type { UserACL } from "~/server/internal/acls";
|
||||
import { defineClientEventHandler } from "~/server/internal/clients/event-handler";
|
||||
import prisma from "~/server/internal/db/database";
|
||||
|
||||
|
||||
Reference in New Issue
Block a user