directory list context menu

This commit is contained in:
2025-07-15 16:20:47 +02:00
parent 5631158b72
commit 672cfbee11
7 changed files with 64 additions and 12 deletions

View File

@@ -18,11 +18,11 @@ const { entry, disabled } = defineProps<{
const deleting = ref(false);
async function submitDelete() {
async function submitDelete(force: boolean = false) {
deleting.value = true;
if (entry.fileType === 'directory') {
await deleteWarrenDirectory(warrenRoute.value, entry.name);
await deleteWarrenDirectory(warrenRoute.value, entry.name, force);
} else {
await deleteWarrenFile(warrenRoute.value, entry.name);
}
@@ -56,10 +56,20 @@ async function submitDelete() {
</NuxtLink>
</ContextMenuTrigger>
<ContextMenuContent>
<ContextMenuItem @select="submitDelete">
<ContextMenuItem @select="() => submitDelete(false)">
<Icon name="lucide:trash-2" />
Delete
</ContextMenuItem>
<ContextMenuItem
v-if="entry.fileType === 'directory'"
@select="() => submitDelete(true)"
>
<Icon
class="text-destructive-foreground"
name="lucide:trash-2"
/>
Force delete
</ContextMenuItem>
</ContextMenuContent>
</ContextMenu>
</template>

View File

@@ -0,0 +1,28 @@
<script setup lang="ts">
import {
ContextMenu,
ContextMenuTrigger,
ContextMenuContent,
ContextMenuItem,
} from '@/components/ui/context-menu';
const dialog = useCreateDirectoryDialog();
const props = defineProps<{
class?: string;
}>();
</script>
<template>
<ContextMenu>
<ContextMenuTrigger :class="props.class">
<slot />
</ContextMenuTrigger>
<ContextMenuContent>
<ContextMenuItem @select="dialog.openDialog">
<Icon name="lucide:folder-plus" />
Create directory
</ContextMenuItem>
</ContextMenuContent>
</ContextMenu>
</template>

View File

@@ -11,9 +11,9 @@ import {
import { createDirectory } from '~/lib/api/warrens';
const warrenRoute = useWarrenRoute();
const dialog = useCreateDirectoryDialog();
const creating = ref(false);
const open = ref(false);
const directoryName = ref('');
async function submit() {
@@ -28,13 +28,13 @@ async function submit() {
if (success) {
directoryName.value = '';
open.value = false;
dialog.open = false;
}
}
</script>
<template>
<Dialog v-model:open="open">
<Dialog v-model:open="dialog.open">
<DialogTrigger as-child>
<slot />
</DialogTrigger>

View File

@@ -20,7 +20,7 @@ const breadcrumbs = computed(() => getBreadcrumbs(route.path));
<template>
<SidebarProvider>
<AppSidebar />
<main class="w-full grow">
<main class="w-full grow overflow-hidden flex flex-col">
<header
class="h-16 flex items-center gap-2 transition-[width,height] ease-linear group-has-[[data-collapsible=icon]]/sidebar-wrapper:h-12"
>

View File

@@ -1,5 +1,5 @@
import { toast } from 'vue-sonner';
import type { DirectoryEntry, FileType } from '~/types';
import type { DirectoryEntry } from '~/types';
import type { ApiResponse } from '~/types/api';
import type { Warren } from '~/types/warrens';
@@ -104,7 +104,8 @@ export async function createDirectory(
export async function deleteWarrenDirectory(
path: string,
directoryName: string
directoryName: string,
force: boolean
): Promise<{ success: boolean }> {
// eslint-disable-next-line prefer-const
let [warrenId, rest] = splitOnce(path, '/');
@@ -125,7 +126,7 @@ export async function deleteWarrenDirectory(
body: JSON.stringify({
warrenId,
path: rest,
force: false,
force,
}),
});

View File

@@ -1,12 +1,14 @@
<script setup lang="ts">
import DirectoryListContextMenu from '~/components/DirectoryListContextMenu.vue';
import { getWarrenDirectory } from '~/lib/api/warrens';
const entries = useAsyncData('current-directory', () =>
getWarrenDirectory(useWarrenRoute().value)
).data;
</script>
<template>
<div>
<DirectoryListContextMenu class="w-full grow">
<DirectoryList v-if="entries != null" :entries="entries" />
</div>
</DirectoryListContextMenu>
</template>

View File

@@ -15,3 +15,14 @@ export const useWarrenStore = defineStore<
export const useWarrenRoute = () =>
computed(() => useRoute().path.split('/warrens/')[1]);
export const useCreateDirectoryDialog = defineStore('create_directory_dialog', {
state: () => ({
open: false,
}),
actions: {
openDialog() {
this.open = true;
},
},
});