wraith/frontend/components/connections/GroupEditDialog.vue
Vantz Stockwell b93fe016ed feat: frontend — auth flow, connection manager UI, host tree
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-12 17:11:02 -04:00

104 lines
2.7 KiB
Vue

<script setup lang="ts">
import { Dialog, InputText, Select, Button } from 'primevue'
const props = defineProps<{
visible: boolean
group?: any | null
}>()
const emit = defineEmits<{
(e: 'update:visible', val: boolean): void
(e: 'saved'): void
}>()
const connections = useConnectionStore()
const form = ref({
name: '',
parentId: null as number | null,
})
const saving = ref(false)
const error = ref('')
const isEdit = computed(() => !!props.group?.id)
const title = computed(() => isEdit.value ? 'Edit Group' : 'New Group')
const parentOptions = computed(() => {
const options = [{ label: 'No Parent (top-level)', value: null }]
// Flatten groups for parent selection, excluding self if editing
const addGroups = (groups: any[], prefix = '') => {
for (const g of groups) {
if (isEdit.value && g.id === props.group?.id) continue
options.push({ label: prefix + g.name, value: g.id })
if (g.children?.length) addGroups(g.children, prefix + g.name + ' / ')
}
}
addGroups(connections.groups)
return options
})
watch(() => props.visible, (v) => {
if (v) {
form.value = {
name: props.group?.name || '',
parentId: props.group?.parentId ?? null,
}
error.value = ''
}
})
async function save() {
error.value = ''
saving.value = true
try {
if (isEdit.value) {
await connections.updateGroup(props.group.id, form.value)
} else {
await connections.createGroup(form.value)
}
emit('saved')
emit('update:visible', false)
} catch (e: any) {
error.value = e.data?.message || 'Failed to save group'
} finally {
saving.value = false
}
}
</script>
<template>
<Dialog
:visible="visible"
@update:visible="emit('update:visible', $event)"
:header="title"
:modal="true"
:closable="true"
:style="{ width: '380px' }"
>
<div class="space-y-4 pt-2">
<!-- Name -->
<div>
<label class="block text-sm text-gray-400 mb-1">Group Name *</label>
<InputText v-model="form.name" placeholder="Production Servers" class="w-full" autofocus />
</div>
<!-- Parent -->
<div>
<label class="block text-sm text-gray-400 mb-1">Parent Group</label>
<Select v-model="form.parentId" :options="parentOptions" optionLabel="label" optionValue="value" class="w-full" />
</div>
<!-- Error -->
<p v-if="error" class="text-red-400 text-sm">{{ error }}</p>
</div>
<template #footer>
<div class="flex justify-end gap-2">
<Button label="Cancel" severity="secondary" @click="emit('update:visible', false)" />
<Button :label="saving ? 'Saving...' : 'Save'" :disabled="saving || !form.name" @click="save" />
</div>
</template>
</Dialog>
</template>