mirror of https://github.com/wg-easy/wg-easy
Browse Source
* get ip and hostnames * use heroicons * add host field * get private info * unstyled prototype * styled select * add to setup * fix typespull/1740/head
committed by
GitHub
39 changed files with 450 additions and 302 deletions
@ -7,5 +7,5 @@ |
|||
"docs:preview": "docker run --rm -it -p 8080:8080 -v ./docs:/docs squidfunk/mkdocs-material serve -a 0.0.0.0:8080", |
|||
"scripts:version": "bash scripts/version.sh" |
|||
}, |
|||
"packageManager": "[email protected].2" |
|||
"packageManager": "[email protected].3" |
|||
} |
|||
|
@ -0,0 +1,40 @@ |
|||
<template> |
|||
<BaseDialog :trigger-class="triggerClass"> |
|||
<template #trigger><slot /></template> |
|||
<template #title>{{ $t('admin.config.suggest') }}</template> |
|||
<template #description> |
|||
<p v-if="!values"> |
|||
{{ $t('general.loading') }} |
|||
</p> |
|||
<div v-else class="flex flex-col items-start gap-2"> |
|||
<p>{{ $t('admin.config.suggestDesc') }}</p> |
|||
<BaseSelect v-model="selected" :options="values" /> |
|||
</div> |
|||
</template> |
|||
<template #actions> |
|||
<DialogClose as-child> |
|||
<BaseButton>{{ $t('dialog.cancel') }}</BaseButton> |
|||
</DialogClose> |
|||
<DialogClose as-child> |
|||
<BaseButton @click="$emit('change', selected)"> |
|||
{{ $t('dialog.change') }} |
|||
</BaseButton> |
|||
</DialogClose> |
|||
</template> |
|||
</BaseDialog> |
|||
</template> |
|||
|
|||
<script lang="ts" setup> |
|||
defineEmits(['change']); |
|||
const props = defineProps<{ |
|||
triggerClass?: string; |
|||
url: '/api/admin/ip-info' | '/api/setup/4'; |
|||
}>(); |
|||
|
|||
const { data } = await useFetch(props.url, { |
|||
method: 'get', |
|||
}); |
|||
|
|||
const selected = ref<string>(); |
|||
const values = toRef(data.value); |
|||
</script> |
@ -0,0 +1,37 @@ |
|||
<template> |
|||
<SelectRoot v-model="selected"> |
|||
<SelectTrigger |
|||
class="inline-flex h-8 items-center justify-around gap-2 rounded bg-gray-200 px-3 text-sm leading-none dark:bg-neutral-500 dark:text-neutral-200" |
|||
aria-label="Choose option" |
|||
> |
|||
<SelectValue placeholder="Select..." /> |
|||
<IconsArrowDown class="size-3" /> |
|||
</SelectTrigger> |
|||
|
|||
<SelectPortal> |
|||
<SelectContent |
|||
class="z-[100] min-w-28 rounded bg-gray-300 dark:bg-neutral-500" |
|||
> |
|||
<SelectViewport class="p-2"> |
|||
<SelectItem |
|||
v-for="(option, index) in options" |
|||
:key="index" |
|||
:value="option.value" |
|||
class="relative flex h-6 items-center rounded px-3 text-sm leading-none outline-none hover:bg-red-800 hover:text-white dark:text-white" |
|||
> |
|||
<SelectItemText> |
|||
{{ option.value }} - {{ option.label }} |
|||
</SelectItemText> |
|||
</SelectItem> |
|||
</SelectViewport> |
|||
</SelectContent> |
|||
</SelectPortal> |
|||
</SelectRoot> |
|||
</template> |
|||
|
|||
<script lang="ts" setup> |
|||
defineProps<{ |
|||
options: { label: string; value: string }[]; |
|||
}>(); |
|||
const selected = defineModel<string>(); |
|||
</script> |
@ -0,0 +1,48 @@ |
|||
<template> |
|||
<div class="flex items-center"> |
|||
<FormLabel :for="id"> |
|||
{{ label }} |
|||
</FormLabel> |
|||
<BaseTooltip v-if="description" :text="description"> |
|||
<IconsInfo class="size-4" /> |
|||
</BaseTooltip> |
|||
</div> |
|||
<div class="flex"> |
|||
<BaseInput |
|||
:id="id" |
|||
v-model.trim="data" |
|||
:name="id" |
|||
type="text" |
|||
class="w-full" |
|||
:placeholder="placeholder" |
|||
/> |
|||
<AdminSuggestDialog :url="url" @change="data = $event"> |
|||
<BaseButton as="span"> |
|||
<div class="flex items-center gap-3"> |
|||
<IconsSparkles class="w-4" /> |
|||
<span>{{ $t('admin.config.suggest') }}</span> |
|||
</div> |
|||
</BaseButton> |
|||
</AdminSuggestDialog> |
|||
</div> |
|||
</template> |
|||
|
|||
<script lang="ts" setup> |
|||
defineProps<{ |
|||
id: string; |
|||
label: string; |
|||
description?: string; |
|||
placeholder?: string; |
|||
url: '/api/admin/ip-info' | '/api/setup/4'; |
|||
}>(); |
|||
|
|||
const data = defineModel<string | null>({ |
|||
set(value) { |
|||
const temp = value?.trim() ?? null; |
|||
if (temp === '') { |
|||
return null; |
|||
} |
|||
return temp; |
|||
}, |
|||
}); |
|||
</script> |
@ -1,13 +1,7 @@ |
|||
<template> |
|||
<svg |
|||
xmlns="http://www.w3.org/2000/svg" |
|||
viewBox="0 0 20 20" |
|||
fill="currentColor" |
|||
> |
|||
<path |
|||
fill-rule="evenodd" |
|||
d="M16.707 10.293a1 1 0 010 1.414l-6 6a1 1 0 01-1.414 0l-6-6a1 1 0 111.414-1.414L9 14.586V3a1 1 0 012 0v11.586l4.293-4.293a1 1 0 011.414 0z" |
|||
clip-rule="evenodd" |
|||
/> |
|||
</svg> |
|||
<ArrowDownIcon /> |
|||
</template> |
|||
|
|||
<script lang="ts" setup> |
|||
import ArrowDownIcon from '@heroicons/vue/24/outline/esm/ArrowDownIcon'; |
|||
</script> |
|||
|
@ -1,16 +1,7 @@ |
|||
<template> |
|||
<svg |
|||
inline |
|||
xmlns="http://www.w3.org/2000/svg" |
|||
fill="none" |
|||
viewBox="0 0 24 24" |
|||
stroke-width="1.5" |
|||
stroke="currentColor" |
|||
> |
|||
<path |
|||
stroke-linecap="round" |
|||
stroke-linejoin="round" |
|||
d="M16.023 9.348h4.992v-.001M2.985 19.644v-4.992m0 0h4.992m-4.993 0 3.181 3.183a8.25 8.25 0 0 0 13.803-3.7M4.031 9.865a8.25 8.25 0 0 1 13.803-3.7l3.181 3.182m0-4.991v4.99" |
|||
/> |
|||
</svg> |
|||
<ArrowPathIcon /> |
|||
</template> |
|||
|
|||
<script lang="ts" setup> |
|||
import ArrowPathIcon from '@heroicons/vue/24/outline/esm/ArrowPathIcon'; |
|||
</script> |
|||
|
@ -1,15 +1,7 @@ |
|||
<template> |
|||
<svg |
|||
xmlns="http://www.w3.org/2000/svg" |
|||
fill="none" |
|||
viewBox="0 0 24 24" |
|||
stroke-width="1.5" |
|||
stroke="currentColor" |
|||
> |
|||
<path |
|||
stroke-linecap="round" |
|||
stroke-linejoin="round" |
|||
d="m11.25 9-3 3m0 0 3 3m-3-3h7.5M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z" |
|||
/> |
|||
</svg> |
|||
<ArrowLeftCircleIcon /> |
|||
</template> |
|||
|
|||
<script lang="ts" setup> |
|||
import ArrowLeftCircleIcon from '@heroicons/vue/24/outline/esm/ArrowLeftCircleIcon'; |
|||
</script> |
|||
|
@ -1,15 +1,7 @@ |
|||
<template> |
|||
<svg |
|||
xmlns="http://www.w3.org/2000/svg" |
|||
fill="none" |
|||
viewBox="0 0 24 24" |
|||
stroke-width="1.5" |
|||
stroke="currentColor" |
|||
> |
|||
<path |
|||
stroke-linecap="round" |
|||
stroke-linejoin="round" |
|||
d="m12.75 15 3-3m0 0-3-3m3 3h-7.5M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z" |
|||
/> |
|||
</svg> |
|||
<ArrowRightCircleIcon /> |
|||
</template> |
|||
|
|||
<script lang="ts" setup> |
|||
import ArrowRightCircleIcon from '@heroicons/vue/24/outline/esm/ArrowLeftCircleIcon'; |
|||
</script> |
|||
|
@ -1,13 +1,7 @@ |
|||
<template> |
|||
<svg |
|||
xmlns="http://www.w3.org/2000/svg" |
|||
viewBox="0 0 20 20" |
|||
fill="currentColor" |
|||
> |
|||
<path |
|||
fill-rule="evenodd" |
|||
d="M3.293 9.707a1 1 0 010-1.414l6-6a1 1 0 011.414 0l6 6a1 1 0 01-1.414 1.414L11 5.414V17a1 1 0 11-2 0V5.414L4.707 9.707a1 1 0 01-1.414 0z" |
|||
clip-rule="evenodd" |
|||
/> |
|||
</svg> |
|||
<ArrowUpIcon /> |
|||
</template> |
|||
|
|||
<script lang="ts" setup> |
|||
import ArrowUpIcon from '@heroicons/vue/24/outline/esm/ArrowUpIcon'; |
|||
</script> |
|||
|
@ -1,12 +1,7 @@ |
|||
<template> |
|||
<svg |
|||
xmlns="http://www.w3.org/2000/svg" |
|||
viewBox="0 0 24 24" |
|||
stroke-width="1.5" |
|||
fill="currentColor" |
|||
> |
|||
<path |
|||
d="M18.375 2.25c-1.035 0-1.875.84-1.875 1.875v15.75c0 1.035.84 1.875 1.875 1.875h.75c1.035 0 1.875-.84 1.875-1.875V4.125c0-1.036-.84-1.875-1.875-1.875h-.75ZM9.75 8.625c0-1.036.84-1.875 1.875-1.875h.75c1.036 0 1.875.84 1.875 1.875v11.25c0 1.035-.84 1.875-1.875 1.875h-.75a1.875 1.875 0 0 1-1.875-1.875V8.625ZM3 13.125c0-1.036.84-1.875 1.875-1.875h.75c1.036 0 1.875.84 1.875 1.875v6.75c0 1.035-.84 1.875-1.875 1.875h-.75A1.875 1.875 0 0 1 3 19.875v-6.75Z" |
|||
/> |
|||
</svg> |
|||
<ChartBarIcon /> |
|||
</template> |
|||
|
|||
<script lang="ts" setup> |
|||
import ChartBarIcon from '@heroicons/vue/24/outline/esm/ChartBarIcon'; |
|||
</script> |
|||
|
@ -1,15 +1,7 @@ |
|||
<template> |
|||
<svg |
|||
xmlns="http://www.w3.org/2000/svg" |
|||
fill="none" |
|||
viewBox="0 0 24 24" |
|||
stroke-width="1.5" |
|||
stroke="currentColor" |
|||
> |
|||
<path |
|||
stroke-linecap="round" |
|||
stroke-linejoin="round" |
|||
d="M9 12.75 11.25 15 15 9.75M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z" |
|||
/> |
|||
</svg> |
|||
<CheckCircleIcon /> |
|||
</template> |
|||
|
|||
<script lang="ts" setup> |
|||
import CheckCircleIcon from '@heroicons/vue/24/outline/esm/CheckCircleIcon'; |
|||
</script> |
|||
|
@ -1,15 +1,7 @@ |
|||
<template> |
|||
<svg |
|||
xmlns="http://www.w3.org/2000/svg" |
|||
fill="none" |
|||
viewBox="0 0 24 24" |
|||
stroke="currentColor" |
|||
> |
|||
<path |
|||
stroke-linecap="round" |
|||
stroke-linejoin="round" |
|||
stroke-width="2" |
|||
d="M6 18L18 6M6 6l12 12" |
|||
/> |
|||
</svg> |
|||
<XMarkIcon /> |
|||
</template> |
|||
|
|||
<script lang="ts" setup> |
|||
import XMarkIcon from '@heroicons/vue/24/outline/esm/XMarkIcon'; |
|||
</script> |
|||
|
@ -1,13 +1,7 @@ |
|||
<template> |
|||
<svg |
|||
xmlns="http://www.w3.org/2000/svg" |
|||
viewBox="0 0 20 20" |
|||
fill="currentColor" |
|||
> |
|||
<path |
|||
fill-rule="evenodd" |
|||
d="M9 2a1 1 0 00-.894.553L7.382 4H4a1 1 0 000 2v10a2 2 0 002 2h8a2 2 0 002-2V6a1 1 0 100-2h-3.382l-.724-1.447A1 1 0 0011 2H9zM7 8a1 1 0 012 0v6a1 1 0 11-2 0V8zm5-1a1 1 0 00-1 1v6a1 1 0 102 0V8a1 1 0 00-1-1z" |
|||
clip-rule="evenodd" |
|||
/> |
|||
</svg> |
|||
<TrashIcon /> |
|||
</template> |
|||
|
|||
<script lang="ts" setup> |
|||
import TrashIcon from '@heroicons/vue/24/outline/esm/TrashIcon'; |
|||
</script> |
|||
|
@ -1,15 +1,7 @@ |
|||
<template> |
|||
<svg |
|||
xmlns="http://www.w3.org/2000/svg" |
|||
fill="none" |
|||
viewBox="0 0 24 24" |
|||
stroke="currentColor" |
|||
> |
|||
<path |
|||
stroke-linecap="round" |
|||
stroke-linejoin="round" |
|||
stroke-width="2" |
|||
d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4" |
|||
/> |
|||
</svg> |
|||
<ArrowDownTrayIcon /> |
|||
</template> |
|||
|
|||
<script lang="ts" setup> |
|||
import ArrowDownTrayIcon from '@heroicons/vue/24/outline/esm/ArrowDownTrayIcon'; |
|||
</script> |
|||
|
@ -1,15 +1,7 @@ |
|||
<template> |
|||
<svg |
|||
xmlns="http://www.w3.org/2000/svg" |
|||
fill="none" |
|||
viewBox="0 0 24 24" |
|||
stroke="currentColor" |
|||
> |
|||
<path |
|||
stroke-linecap="round" |
|||
stroke-linejoin="round" |
|||
stroke-width="2" |
|||
d="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z" |
|||
/> |
|||
</svg> |
|||
<PencilSquareIcon /> |
|||
</template> |
|||
|
|||
<script lang="ts" setup> |
|||
import PencilSquareIcon from '@heroicons/vue/24/outline/esm/PencilSquareIcon'; |
|||
</script> |
|||
|
@ -1,15 +1,7 @@ |
|||
<template> |
|||
<svg |
|||
xmlns="http://www.w3.org/2000/svg" |
|||
fill="none" |
|||
viewBox="0 0 24 24" |
|||
stroke-width="1.5" |
|||
stroke="currentColor" |
|||
> |
|||
<path |
|||
stroke-linecap="round" |
|||
stroke-linejoin="round" |
|||
d="m11.25 11.25.041-.02a.75.75 0 0 1 1.063.852l-.708 2.836a.75.75 0 0 0 1.063.853l.041-.021M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9-3.75h.008v.008H12V8.25Z" |
|||
/> |
|||
</svg> |
|||
<InformationCircleIcon /> |
|||
</template> |
|||
|
|||
<script lang="ts" setup> |
|||
import InformationCircleIcon from '@heroicons/vue/24/outline/esm/InformationCircleIcon'; |
|||
</script> |
|||
|
@ -1,15 +1,7 @@ |
|||
<template> |
|||
<svg |
|||
xmlns="http://www.w3.org/2000/svg" |
|||
fill="none" |
|||
viewBox="0 0 24 24" |
|||
stroke-width="1.5" |
|||
stroke="currentColor" |
|||
> |
|||
<path |
|||
stroke-linecap="round" |
|||
stroke-linejoin="round" |
|||
d="m10.5 21 5.25-11.25L21 21m-9-3h7.5M3 5.621a48.474 48.474 0 0 1 6-.371m0 0c1.12 0 2.233.038 3.334.114M9 5.25V3m3.334 2.364C11.176 10.658 7.69 15.08 3 17.502m9.334-12.138c.896.061 1.785.147 2.666.257m-4.589 8.495a18.023 18.023 0 0 1-3.827-5.802" |
|||
/> |
|||
</svg> |
|||
<LanguageIcon /> |
|||
</template> |
|||
|
|||
<script lang="ts" setup> |
|||
import LanguageIcon from '@heroicons/vue/24/outline/esm/LanguageIcon'; |
|||
</script> |
|||
|
@ -1,15 +1,7 @@ |
|||
<template> |
|||
<svg |
|||
xmlns="http://www.w3.org/2000/svg" |
|||
fill="none" |
|||
viewBox="0 0 24 24" |
|||
stroke="currentColor" |
|||
> |
|||
<path |
|||
stroke-linecap="round" |
|||
stroke-linejoin="round" |
|||
stroke-width="2" |
|||
d="M13.213 9.787a3.391 3.391 0 0 0-4.795 0l-3.425 3.426a3.39 3.39 0 0 0 4.795 4.794l.321-.304m-.321-4.49a3.39 3.39 0 0 0 4.795 0l3.424-3.426a3.39 3.39 0 0 0-4.794-4.795l-1.028.961" |
|||
/> |
|||
</svg> |
|||
<LinkIcon /> |
|||
</template> |
|||
|
|||
<script lang="ts" setup> |
|||
import LinkIcon from '@heroicons/vue/24/outline/esm/LinkIcon'; |
|||
</script> |
|||
|
@ -1,15 +1,7 @@ |
|||
<template> |
|||
<svg |
|||
xmlns="http://www.w3.org/2000/svg" |
|||
fill="none" |
|||
viewBox="0 0 24 24" |
|||
stroke="currentColor" |
|||
> |
|||
<path |
|||
stroke-linecap="round" |
|||
stroke-linejoin="round" |
|||
stroke-width="2" |
|||
d="M17 16l4-4m0 0l-4-4m4 4H7m6 4v1a3 3 0 01-3 3H6a3 3 0 01-3-3V7a3 3 0 013-3h4a3 3 0 013 3v1" |
|||
/> |
|||
</svg> |
|||
<ArrowRightStartOnRectangleIcon /> |
|||
</template> |
|||
|
|||
<script lang="ts" setup> |
|||
import ArrowRightStartOnRectangleIcon from '@heroicons/vue/24/outline/esm/ArrowRightStartOnRectangleIcon'; |
|||
</script> |
|||
|
@ -1,15 +1,7 @@ |
|||
<template> |
|||
<svg |
|||
xmlns="http://www.w3.org/2000/svg" |
|||
fill="none" |
|||
viewBox="0 0 24 24" |
|||
stroke-width="1.5" |
|||
stroke="currentColor" |
|||
> |
|||
<path |
|||
stroke-linecap="round" |
|||
stroke-linejoin="round" |
|||
d="M21.752 15.002A9.72 9.72 0 0 1 18 15.75c-5.385 0-9.75-4.365-9.75-9.75 0-1.33.266-2.597.748-3.752A9.753 9.753 0 0 0 3 11.25C3 16.635 7.365 21 12.75 21a9.753 9.753 0 0 0 9.002-5.998Z" |
|||
/> |
|||
</svg> |
|||
<MoonIcon /> |
|||
</template> |
|||
|
|||
<script lang="ts" setup> |
|||
import MoonIcon from '@heroicons/vue/24/outline/esm/MoonIcon'; |
|||
</script> |
|||
|
@ -1,16 +1,7 @@ |
|||
<template> |
|||
<svg |
|||
inline |
|||
xmlns="http://www.w3.org/2000/svg" |
|||
fill="none" |
|||
viewBox="0 0 24 24" |
|||
stroke="currentColor" |
|||
> |
|||
<path |
|||
stroke-linecap="round" |
|||
stroke-linejoin="round" |
|||
stroke-width="2" |
|||
d="M12 6v6m0 0v6m0-6h6m-6 0H6" |
|||
/> |
|||
</svg> |
|||
<PlusIcon /> |
|||
</template> |
|||
|
|||
<script lang="ts" setup> |
|||
import PlusIcon from '@heroicons/vue/24/outline/esm/PlusIcon'; |
|||
</script> |
|||
|
@ -1,15 +1,7 @@ |
|||
<template> |
|||
<svg |
|||
xmlns="http://www.w3.org/2000/svg" |
|||
fill="none" |
|||
viewBox="0 0 24 24" |
|||
stroke="currentColor" |
|||
> |
|||
<path |
|||
stroke-linecap="round" |
|||
stroke-linejoin="round" |
|||
stroke-width="2" |
|||
d="M12 4v1m6 11h2m-6 0h-2v4m0-11v3m0 0h.01M12 12h4.01M16 20h4M4 12h4m12 0h.01M5 8h2a1 1 0 001-1V5a1 1 0 00-1-1H5a1 1 0 00-1 1v2a1 1 0 001 1zm12 0h2a1 1 0 001-1V5a1 1 0 00-1-1h-2a1 1 0 00-1 1v2a1 1 0 001 1zM5 20h2a1 1 0 001-1v-2a1 1 0 00-1-1H5a1 1 0 00-1 1v2a1 1 0 001 1z" |
|||
/> |
|||
</svg> |
|||
<QrCodeIcon /> |
|||
</template> |
|||
|
|||
<script lang="ts" setup> |
|||
import QrCodeIcon from '@heroicons/vue/24/outline/esm/QrCodeIcon'; |
|||
</script> |
|||
|
@ -0,0 +1,7 @@ |
|||
<template> |
|||
<SparklesIcon /> |
|||
</template> |
|||
|
|||
<script lang="ts" setup> |
|||
import SparklesIcon from '@heroicons/vue/24/outline/esm/SparklesIcon'; |
|||
</script> |
@ -1,16 +1,7 @@ |
|||
<template> |
|||
<svg |
|||
inline |
|||
xmlns="http://www.w3.org/2000/svg" |
|||
fill="none" |
|||
viewBox="0 0 24 24" |
|||
stroke-width="1.5" |
|||
stroke="currentColor" |
|||
> |
|||
<path |
|||
stroke-linecap="round" |
|||
stroke-linejoin="round" |
|||
d="M5.25 14.25h13.5m-13.5 0a3 3 0 0 1-3-3m3 3a3 3 0 1 0 0 6h13.5a3 3 0 1 0 0-6m-16.5-3a3 3 0 0 1 3-3h13.5a3 3 0 0 1 3 3m-19.5 0a4.5 4.5 0 0 1 .9-2.7L5.737 5.1a3.375 3.375 0 0 1 2.7-1.35h7.126c1.062 0 2.062.5 2.7 1.35l2.587 3.45a4.5 4.5 0 0 1 .9 2.7m0 0a3 3 0 0 1-3 3m0 3h.008v.008h-.008v-.008Zm0-6h.008v.008h-.008v-.008Zm-3 6h.008v.008h-.008v-.008Zm0-6h.008v.008h-.008v-.008Z" |
|||
/> |
|||
</svg> |
|||
<ServerStackIcon /> |
|||
</template> |
|||
|
|||
<script lang="ts" setup> |
|||
import ServerStackIcon from '@heroicons/vue/24/outline/esm/ServerStackIcon'; |
|||
</script> |
|||
|
@ -1,15 +1,7 @@ |
|||
<template> |
|||
<svg |
|||
xmlns="http://www.w3.org/2000/svg" |
|||
fill="none" |
|||
viewBox="0 0 24 24" |
|||
stroke-width="1.5" |
|||
stroke="currentColor" |
|||
> |
|||
<path |
|||
stroke-linecap="round" |
|||
stroke-linejoin="round" |
|||
d="M12 3v2.25m6.364.386-1.591 1.591M21 12h-2.25m-.386 6.364-1.591-1.591M12 18.75V21m-4.773-4.227-1.591 1.591M5.25 12H3m4.227-4.773L5.636 5.636M15.75 12a3.75 3.75 0 1 1-7.5 0 3.75 3.75 0 0 1 7.5 0Z" |
|||
/> |
|||
</svg> |
|||
<SunIcon /> |
|||
</template> |
|||
|
|||
<script lang="ts" setup> |
|||
import SunIcon from '@heroicons/vue/24/outline/esm/SunIcon'; |
|||
</script> |
|||
|
@ -1,17 +1,7 @@ |
|||
<template> |
|||
<!-- Heroicon name: outline/exclamation --> |
|||
<svg |
|||
xmlns="http://www.w3.org/2000/svg" |
|||
fill="none" |
|||
viewBox="0 0 24 24" |
|||
stroke="currentColor" |
|||
aria-hidden="true" |
|||
> |
|||
<path |
|||
stroke-linecap="round" |
|||
stroke-linejoin="round" |
|||
stroke-width="2" |
|||
d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z" |
|||
/> |
|||
</svg> |
|||
<ExclamationTriangleIcon /> |
|||
</template> |
|||
|
|||
<script lang="ts" setup> |
|||
import ExclamationTriangleIcon from '@heroicons/vue/24/outline/esm/ExclamationTriangleIcon'; |
|||
</script> |
|||
|
@ -19,6 +19,7 @@ |
|||
}, |
|||
"dependencies": { |
|||
"@eschricht/nuxt-color-mode": "^1.1.5", |
|||
"@heroicons/vue": "^2.2.0", |
|||
"@libsql/client": "^0.14.0", |
|||
"@nuxtjs/i18n": "^9.3.1", |
|||
"@nuxtjs/tailwindcss": "^6.13.2", |
|||
@ -60,5 +61,5 @@ |
|||
"typescript": "^5.8.2", |
|||
"vue-tsc": "^2.2.8" |
|||
}, |
|||
"packageManager": "[email protected].2" |
|||
"packageManager": "[email protected].3" |
|||
} |
|||
|
@ -11,6 +11,9 @@ importers: |
|||
'@eschricht/nuxt-color-mode': |
|||
specifier: ^1.1.5 |
|||
version: 1.1.5([email protected]) |
|||
'@heroicons/vue': |
|||
specifier: ^2.2.0 |
|||
version: 2.2.0([email protected]([email protected])) |
|||
'@libsql/client': |
|||
specifier: ^0.14.0 |
|||
version: 0.14.0 |
|||
@ -791,6 +794,11 @@ packages: |
|||
'@floating-ui/[email protected]': |
|||
resolution: {integrity: sha512-XFlUzGHGv12zbgHNk5FN2mUB7ROul3oG2ENdTpWdE+qMFxyNxWSRmsoyhiEnpmabNm6WnUvR1OvJfUfN4ojC1A==} |
|||
|
|||
'@heroicons/[email protected]': |
|||
resolution: {integrity: sha512-G3dbSxoeEKqbi/DFalhRxJU4mTXJn7GwZ7ae8NuEQzd1bqdd0jAbdaBZlHPcvPD2xI1iGzNVB4k20Un2AguYPw==} |
|||
peerDependencies: |
|||
vue: '>= 3' |
|||
|
|||
'@humanfs/[email protected]': |
|||
resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==} |
|||
engines: {node: '>=18.18.0'} |
|||
@ -3403,7 +3411,6 @@ packages: |
|||
|
|||
[email protected]: |
|||
resolution: {integrity: sha512-T9eIRCs6b0J1SHKYIvD8+KCJMcWZ900iZyxdnSCdqxN12Z1ijzT+jY5nrk72Jw4B0HGzms2NgpryArlJqvc3Lw==} |
|||
cpu: [x64, arm64, wasm32] |
|||
os: [darwin, linux, win32] |
|||
|
|||
[email protected]: |
|||
@ -5761,6 +5768,10 @@ snapshots: |
|||
- '@vue/composition-api' |
|||
- vue |
|||
|
|||
'@heroicons/[email protected]([email protected]([email protected]))': |
|||
dependencies: |
|||
vue: 3.5.13([email protected]) |
|||
|
|||
'@humanfs/[email protected]': {} |
|||
|
|||
'@humanfs/[email protected]': |
|||
|
@ -0,0 +1,4 @@ |
|||
export default definePermissionEventHandler('admin', 'any', async () => { |
|||
const result = await cachedGetIpInformation(); |
|||
return result; |
|||
}); |
@ -0,0 +1,4 @@ |
|||
export default defineSetupEventHandler(4, async () => { |
|||
const result = await cachedGetIpInformation(); |
|||
return result; |
|||
}); |
@ -0,0 +1,29 @@ |
|||
type Opts = { |
|||
/** |
|||
* Expiry time in milliseconds |
|||
*/ |
|||
expiry: number; |
|||
}; |
|||
|
|||
/** |
|||
* Cache function for 1 hour |
|||
*/ |
|||
export function cacheFunction<T>(fn: () => T, { expiry }: Opts): () => T { |
|||
let cache: { value: T; expiry: number } | null = null; |
|||
|
|||
return (): T => { |
|||
const now = Date.now(); |
|||
|
|||
if (cache && cache.expiry > now) { |
|||
return cache.value; |
|||
} |
|||
|
|||
const result = fn(); |
|||
cache = { |
|||
value: result, |
|||
expiry: now + expiry, |
|||
}; |
|||
|
|||
return result; |
|||
}; |
|||
} |
Loading…
Reference in new issue