mirror of
https://github.com/Drop-OSS/drop-api-autogen.git
synced 2026-07-20 23:45:56 -04:00
108 lines
4.6 KiB
Vue
108 lines
4.6 KiB
Vue
<template>
|
|
<div>
|
|
<div v-if="guidesNavigation">
|
|
<h1 class="font-display font-bold text-zinc-100">{{ guidesNavigation.title }}</h1>
|
|
<ul class="ml-3 mt-1 space-y-2">
|
|
<li v-for="guide in guidesNavigation.children">
|
|
<NuxtLink :href="guide.path" class="transition text-sm text-zinc-300 hover:text-zinc-100">
|
|
<span class="text-blue-400">+ {{ " " }}</span>{{ guide.title }}
|
|
</NuxtLink>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="mt-8">
|
|
<div class="grid grid-cols-1">
|
|
<input type="email" name="email" id="email"
|
|
class="col-start-1 row-start-1 block w-full rounded-md bg-zinc-950 py-1.5 pr-3 pl-10 text-base text-zinc-100 outline-1 -outline-offset-1 outline-zinc-700 placeholder:text-zinc-500 focus:outline-2 focus:-outline-offset-2 focus:outline-blue-600 sm:pl-9 sm:text-sm/6"
|
|
placeholder="/api/v1/..." v-model="query" />
|
|
<MagnifyingGlassIcon
|
|
class="pointer-events-none col-start-1 row-start-1 ml-3 size-5 self-center text-gray-400 sm:size-4"
|
|
aria-hidden="true" />
|
|
</div>
|
|
</div>
|
|
<ul class="mt-4 space-y-3">
|
|
<li v-for="[path, methods] in filteredCollapsedNav.entries()">
|
|
<span class="font-display text-zinc-100 font-semibold">{{ path }}</span>
|
|
<ul class="mt-1 space-y-1">
|
|
<li v-for="method in methods">
|
|
<NuxtLink
|
|
class="transition hover:bg-zinc-900 px-1 py-0.5 rounded ml-1 text-zinc-400 grid grid-cols-4 gap-x-2"
|
|
:href="method.path">
|
|
|
|
<span
|
|
:class="[apiMethodColours[method.method], 'text-center text-xs font-bold ring-1 rounded-full px-1 py-0.5']">{{
|
|
method.method }}</span>
|
|
<div class="col-span-3 text-sm relative whitespace-nowrap overflow-hidden"><span
|
|
class="absolute right-0">{{ method.methodlessName }}</span></div>
|
|
</NuxtLink>
|
|
</li>
|
|
</ul>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { MagnifyingGlassIcon } from '@heroicons/vue/16/solid'
|
|
import type { ContentNavigationItem } from '@nuxt/content';
|
|
|
|
const rawAPINav = await queryCollectionNavigation("docs");
|
|
const apiNavRoot = rawAPINav.at(0);
|
|
if (!apiNavRoot) throw createError({ statusCode: 500, statusMessage: "Failed to fetch API docs navigation", fatal: true });
|
|
|
|
const collapsedAPINav = ref<Map<string, Array<ContentNavigationItem & { method: string, methodlessName: string }>>>(new Map());
|
|
const apiMethods = ["GET", "POST", "DELETE", "PATCH"];
|
|
|
|
const apiMethodColours: { [key: string]: string } = {
|
|
"GET": "text-green-500 bg-green-500/10",
|
|
"POST": "text-orange-500 bg-orange-500/10",
|
|
"PATCH": "text-yellow-500 bg-yellow-500/10",
|
|
"DELETE": "text-red-500 bg-red-500/10",
|
|
"WS": "text-blue-500 bg-blue-500/10",
|
|
}
|
|
|
|
function recursivelyCollapseAPINav(nav: ContentNavigationItem, parent?: ContentNavigationItem) {
|
|
const potentialMethod = nav.title.split(" ").at(0);
|
|
if (!potentialMethod || !apiMethods.includes(potentialMethod.toUpperCase()) || !parent) {
|
|
if (nav.children) {
|
|
for (const child of nav.children)
|
|
recursivelyCollapseAPINav(child, nav);
|
|
}
|
|
return;
|
|
}
|
|
|
|
const methodlessName = nav.title.slice(potentialMethod.length).trim();
|
|
|
|
const newValue = collapsedAPINav.value.get(parent.path) ?? [];
|
|
newValue.push({ ...nav, method: potentialMethod, methodlessName })
|
|
collapsedAPINav.value.set(parent.path, newValue);
|
|
}
|
|
|
|
recursivelyCollapseAPINav(apiNavRoot)
|
|
|
|
collapsedAPINav.value = new Map([...collapsedAPINav.value].sort((a, b) => a[0].localeCompare(b[0])).map((v) => {
|
|
v[1].sort((a, b) => {
|
|
const methodSort = a.method.length - b.method.length;
|
|
if (methodSort == 0) return a.methodlessName.length - b.methodlessName.length;
|
|
return methodSort;
|
|
});
|
|
return v;
|
|
}))
|
|
|
|
const query = ref("");
|
|
|
|
const filteredCollapsedNav = computed(() => {
|
|
if(!query.value) return collapsedAPINav.value;
|
|
|
|
const raw = [...collapsedAPINav.value];
|
|
|
|
const filtered = raw.map((e) => [e[0], e[1].filter((v) => v.title.toLowerCase().includes(query.value.toLowerCase()))] as const);
|
|
const stripped = filtered.filter((e) => e[1].length > 0);
|
|
|
|
return new Map(stripped);
|
|
|
|
});
|
|
|
|
const guidesNavigation = (await queryCollectionNavigation("guides")).at(0);
|
|
|
|
</script> |