Add Tag Edit Modal and UI

This commit is contained in:
Gregor Vostrak
2026-02-10 13:19:30 +01:00
parent 215957104f
commit 2c4af95ee3
7 changed files with 158 additions and 6 deletions

View File

@@ -0,0 +1,75 @@
<script setup lang="ts">
import TextInput from '@/packages/ui/src/Input/TextInput.vue';
import SecondaryButton from '@/packages/ui/src/Buttons/SecondaryButton.vue';
import DialogModal from '@/packages/ui/src/DialogModal.vue';
import { ref } from 'vue';
import PrimaryButton from '@/packages/ui/src/Buttons/PrimaryButton.vue';
import { useFocus } from '@vueuse/core';
import { useTagsStore } from '@/utils/useTags';
import type { Tag, UpdateTagBody } from '@/packages/api/src';
const { updateTag } = useTagsStore();
const show = defineModel('show', { default: false });
const saving = ref(false);
const props = defineProps<{
tag: Tag;
}>();
const tagBody = ref<UpdateTagBody>({
name: props.tag.name,
});
async function submit() {
saving.value = true;
try {
await updateTag({ tagId: props.tag.id, tagBody: tagBody.value });
show.value = false;
} finally {
saving.value = false;
}
}
const tagNameInput = ref<HTMLInputElement | null>(null);
useFocus(tagNameInput, { initialValue: true });
</script>
<template>
<DialogModal closeable :show="show" @close="show = false">
<template #title>
<div class="flex space-x-2">
<span> Update Tag </span>
</div>
</template>
<template #content>
<div class="flex items-center space-x-4">
<div class="col-span-6 sm:col-span-4 flex-1">
<TextInput
id="tagName"
ref="tagNameInput"
v-model="tagBody.name"
type="text"
placeholder="Tag Name"
class="mt-1 block w-full"
required
autocomplete="tagName"
@keydown.enter="submit()" />
</div>
</div>
</template>
<template #footer>
<SecondaryButton @click="show = false"> Cancel </SecondaryButton>
<PrimaryButton
class="ms-3"
:class="{ 'opacity-25': saving }"
:disabled="saving"
@click="submit">
Update Tag
</PrimaryButton>
</template>
</DialogModal>
</template>
<style scoped></style>

View File

@@ -1,5 +1,6 @@
<script setup lang="ts">
import { TrashIcon } from '@heroicons/vue/20/solid';
import { TrashIcon, PencilSquareIcon } from '@heroicons/vue/20/solid';
import { canDeleteTags, canUpdateTags } from '@/utils/permissions';
import type { Tag } from '@/packages/api/src';
import {
DropdownMenu,
@@ -9,6 +10,7 @@ import {
} from '@/Components/ui/dropdown-menu';
const emit = defineEmits<{
edit: [];
delete: [];
}>();
const props = defineProps<{
@@ -38,6 +40,16 @@ const props = defineProps<{
</DropdownMenuTrigger>
<DropdownMenuContent class="min-w-[150px]" align="end">
<DropdownMenuItem
v-if="canUpdateTags()"
:aria-label="'Edit Tag ' + props.tag.name"
data-testid="tag_edit"
class="flex items-center space-x-3 cursor-pointer"
@click="emit('edit')">
<PencilSquareIcon class="w-5 text-icon-active" />
<span>Edit</span>
</DropdownMenuItem>
<DropdownMenuItem
v-if="canDeleteTags()"
:aria-label="'Delete Tag ' + props.tag.name"
data-testid="tag_delete"
class="flex items-center space-x-3 cursor-pointer text-destructive focus:text-destructive"

View File

@@ -2,13 +2,17 @@
import type { Tag } from '@/packages/api/src';
import { useTagsStore } from '@/utils/useTags';
import TagMoreOptionsDropdown from '@/Components/Common/Tag/TagMoreOptionsDropdown.vue';
import TagEditModal from '@/Components/Common/Tag/TagEditModal.vue';
import TableRow from '@/Components/TableRow.vue';
import { canDeleteTags } from '@/utils/permissions';
import { canDeleteTags, canUpdateTags } from '@/utils/permissions';
import { ref } from 'vue';
const props = defineProps<{
tag: Tag;
}>();
const showTagEditModal = ref(false);
function deleteTag() {
useTagsStore().deleteTag(props.tag.id);
}
@@ -25,10 +29,12 @@ function deleteTag() {
<div
class="relative whitespace-nowrap flex items-center pl-3 text-right text-sm font-medium sm:pr-0 pr-4 sm:pr-6 lg:pr-8 3xl:pr-12">
<TagMoreOptionsDropdown
v-if="canDeleteTags()"
v-if="canDeleteTags() || canUpdateTags()"
:tag="tag"
@edit="showTagEditModal = true"
@delete="deleteTag"></TagMoreOptionsDropdown>
</div>
<TagEditModal v-model:show="showTagEditModal" :tag="tag"></TagEditModal>
</TableRow>
</template>