mirror of
https://gitlab.com/PronounsPage/PronounsPage.git
synced 2025-09-27 23:13:01 -04:00

the #shared alias used by Nuxt cannot be easily disabled and to prevent breackage with jiti, we make use of it
86 lines
2.3 KiB
Vue
86 lines
2.3 KiB
Vue
<script setup lang="ts">
|
|
import { formatSize } from '#shared/helpers.ts';
|
|
import { adminStorageRefreshInjectionKey } from '#shared/injectionKeys.ts';
|
|
|
|
const props = defineProps<{
|
|
itemKey: string;
|
|
size: number;
|
|
}>();
|
|
|
|
const chunk = computed(() => props.itemKey.replace(/^.+:/, ''));
|
|
|
|
const isOpen = ref(false);
|
|
|
|
const contentUrl = computed(() => `/api/admin/storage/items/${props.itemKey}`);
|
|
|
|
const contentAsyncData = useFetch(contentUrl.value, {
|
|
immediate: false,
|
|
});
|
|
|
|
watch(isOpen, async () => {
|
|
if (isOpen.value) {
|
|
await contentAsyncData.execute();
|
|
}
|
|
});
|
|
|
|
const adminStorageRefresh = inject(adminStorageRefreshInjectionKey);
|
|
const dialogue = useDialogue();
|
|
const remove = async () => {
|
|
try {
|
|
await dialogue.confirm(`Are you sure you want to remove ${props.itemKey}?`, 'danger');
|
|
} catch (error) {
|
|
if (error === undefined) {
|
|
return;
|
|
}
|
|
throw error;
|
|
}
|
|
await $fetch(contentUrl.value, { method: 'DELETE' });
|
|
if (adminStorageRefresh) {
|
|
await adminStorageRefresh();
|
|
}
|
|
};
|
|
</script>
|
|
|
|
<template>
|
|
<details @toggle="isOpen = $event.newState === 'open'">
|
|
<summary>
|
|
<span class="py-1 d-inline-flex justify-content-between align-items-start">
|
|
<code>{{ chunk }}</code>
|
|
<span>
|
|
<span class="badge text-bg-info">{{ formatSize(size) }}</span>
|
|
<button type="button" class="btn btn-sm btn-outline-danger" @click="remove()">
|
|
<Icon v="trash" />
|
|
</button>
|
|
</span>
|
|
</span>
|
|
</summary>
|
|
<div v-if="isOpen" class="ps-3">
|
|
<template v-if="contentAsyncData.status.value === 'success'">
|
|
<img
|
|
v-if="itemKey.endsWith('.png')"
|
|
:src="contentUrl"
|
|
:alt="`Image content for storage key ${itemKey}`"
|
|
>
|
|
<pre v-else class="mb-0">{{ contentAsyncData.data }}</pre>
|
|
</template>
|
|
<Spinner v-else />
|
|
</div>
|
|
</details>
|
|
</template>
|
|
|
|
<style scoped lang="scss">
|
|
@import 'assets/variables';
|
|
|
|
summary > span {
|
|
width: calc(100% - #{$spacer});
|
|
}
|
|
|
|
img {
|
|
max-width: 100%;
|
|
}
|
|
|
|
pre {
|
|
max-height: 80vh;
|
|
}
|
|
</style>
|