rename directory entries

This commit is contained in:
2025-07-16 06:23:24 +02:00
parent b121c27b37
commit a2cb58867c
16 changed files with 389 additions and 21 deletions

View File

@@ -4,13 +4,14 @@ import {
ContextMenuTrigger,
ContextMenuContent,
ContextMenuItem,
ContextMenuSeparator,
} from '@/components/ui/context-menu';
import { deleteWarrenDirectory, deleteWarrenFile } from '~/lib/api/warrens';
import type { DirectoryEntry } from '~/types';
import { buttonVariants } from '@/components/ui/button';
const route = useRoute();
const warrenRoute = useWarrenRoute();
const renameDialog = useRenameDirectoryDialog();
const { entry, disabled } = defineProps<{
entry: DirectoryEntry;
@@ -30,6 +31,10 @@ async function submitDelete(force: boolean = false) {
deleting.value = false;
}
async function openRenameDialog() {
renameDialog.openDialog(entry);
}
</script>
<template>
@@ -62,6 +67,13 @@ async function submitDelete(force: boolean = false) {
</NuxtLink>
</ContextMenuTrigger>
<ContextMenuContent>
<ContextMenuItem @select="openRenameDialog">
<Icon name="lucide:pencil" />
Rename
</ContextMenuItem>
<ContextMenuSeparator />
<ContextMenuItem @select="() => submitDelete(false)">
<Icon name="lucide:trash-2" />
Delete

View File

@@ -14,24 +14,17 @@ const warrenRoute = useWarrenRoute();
const dialog = useCreateDirectoryDialog();
const creating = ref(false);
const directoryName = ref('');
const directoryNameValid = computed(
() => directoryName.value.trim().length > 0
);
const directoryNameValid = computed(() => dialog.value.trim().length > 0);
async function submit() {
creating.value = true;
const { success } = await createDirectory(
warrenRoute.value,
directoryName.value
);
const { success } = await createDirectory(warrenRoute.value, dialog.value);
creating.value = false;
if (success) {
directoryName.value = '';
dialog.open = false;
dialog.reset();
}
}
</script>
@@ -50,7 +43,7 @@ async function submit() {
</DialogHeader>
<Input
v-model="directoryName"
v-model="dialog.value"
type="text"
name="directory-name"
placeholder="my-awesome-directory"

View File

@@ -0,0 +1,68 @@
<script setup lang="ts">
import {
Dialog,
DialogContent,
DialogHeader,
DialogTitle,
DialogDescription,
DialogFooter,
} from '@/components/ui/dialog';
import { renameWarrenEntry } from '~/lib/api/warrens';
const warrenRoute = useWarrenRoute();
const dialog = useRenameDirectoryDialog();
const renaming = ref(false);
const directoryNameValid = computed(() => dialog.value.trim().length > 0);
async function submit() {
if (dialog.entry == null) {
return;
}
renaming.value = true;
const { success } = await renameWarrenEntry(
warrenRoute.value,
dialog.entry.name,
dialog.value
);
renaming.value = false;
if (success) {
dialog.reset();
}
}
</script>
<template>
<Dialog v-model:open="dialog.open">
<DialogContent>
<DialogHeader>
<DialogTitle>Rename your directory</DialogTitle>
<DialogDescription
>Give your directory a new memorable name</DialogDescription
>
</DialogHeader>
<Input
v-model="dialog.value"
type="text"
name="directory-name"
placeholder="my-awesome-directory"
aria-required="true"
autocomplete="off"
required
/>
<DialogFooter>
<Button
:disabled="!directoryNameValid || renaming"
@click="submit"
>Rename</Button
>
</DialogFooter>
</DialogContent>
</Dialog>
</template>

View File

@@ -256,3 +256,49 @@ export async function uploadToWarren(
return { success: true };
}
export async function renameWarrenEntry(
path: string,
currentName: string,
newName: string
): Promise<{ success: boolean }> {
// eslint-disable-next-line prefer-const
let [warrenId, rest] = splitOnce(path, '/');
if (rest == null) {
rest = '/';
} else {
rest = '/' + rest + '/';
}
rest += currentName;
const { status } = await useFetch(getApiUrl(`warrens/files/rename`), {
method: 'PATCH',
headers: {
'content-type': 'application/json',
},
body: JSON.stringify({
warrenId,
path: rest,
newName,
}),
});
if (status.value !== 'success') {
toast.error('Rename', {
id: 'RENAME_FILE_TOAST',
description: `Failed to rename ${currentName}`,
});
return { success: false };
}
await refreshNuxtData('current-directory');
toast.success('Rename', {
id: 'RENAME_FILE_TOAST',
description: `Successfully renamed ${currentName} to ${newName}`,
});
return { success: true };
}

View File

@@ -1,5 +1,6 @@
<script setup lang="ts">
import DirectoryListContextMenu from '~/components/DirectoryListContextMenu.vue';
import RenameEntryDialog from '~/components/actions/RenameEntryDialog.vue';
import { getWarrenDirectory } from '~/lib/api/warrens';
const entries = useAsyncData('current-directory', () =>
@@ -8,7 +9,10 @@ const entries = useAsyncData('current-directory', () =>
</script>
<template>
<DirectoryListContextMenu class="w-full grow">
<DirectoryList v-if="entries != null" :entries="entries" />
</DirectoryListContextMenu>
<div>
<DirectoryListContextMenu class="w-full grow">
<DirectoryList v-if="entries != null" :entries="entries" />
</DirectoryListContextMenu>
<RenameEntryDialog />
</div>
</template>

View File

@@ -1,4 +1,5 @@
import { defineStore } from 'pinia';
import type { DirectoryEntry } from '~/types';
import type { Warren } from '~/types/warrens';
export const useWarrenStore = defineStore<
@@ -19,10 +20,35 @@ export const useWarrenRoute = () =>
export const useCreateDirectoryDialog = defineStore('create_directory_dialog', {
state: () => ({
open: false,
value: '',
}),
actions: {
openDialog() {
this.open = true;
},
reset() {
this.open = false;
this.value = '';
},
},
});
export const useRenameDirectoryDialog = defineStore('rename_directory_dialog', {
state: () => ({
open: false,
entry: null as DirectoryEntry | null,
value: '',
}),
actions: {
openDialog(entry: DirectoryEntry) {
this.entry = entry;
this.value = entry.name;
this.open = true;
},
reset() {
this.open = false;
this.entry = null;
this.value = '';
},
},
});