Dashboard and error handling

This commit is contained in:
2025-07-15 13:22:11 +02:00
parent 5ac4c987d3
commit 6a5149fd4c
27 changed files with 572 additions and 204 deletions

View File

@ -7,7 +7,12 @@ import ClientDetailView from '@/views/clients/ClientDetailView.vue'
import { useRouter, useRoute } from 'vue-router'
import { useTreeState } from '@/store/useTreeState'
const props = defineProps<{ id: string | null; parentId: string | null }>()
interface Props {
id: string
parentId?: string
}
const props = defineProps<Props>()
const router = useRouter()
const clientId = toRef(() => props.id)
const parentId = toRef(() => props.parentId)

View File

@ -11,25 +11,30 @@
<script setup lang="ts">
import { ref, toRef, watch, onMounted } from 'vue'
import { assertSdkResponseOk } from '@/api/AssertSdkResponseOk'
import { ValidationError } from '@/api/errors'
import ClientSkeleton from '@/components/clients/ClientSkeleton.vue'
import ClientDetail from '@/components/clients/ClientDetail.vue'
import type { ClientCreate } from '@/client'
import { idKey } from '@/api/paths'
import { SshecretAdmin } from '@/client'
import { useTreeState } from '@/store/useTreeState'
import { useAlertsStore } from '@/store/useAlertsStore'
const props = defineProps<{ id: string | null; parentId: string | null }>()
interface Props {
id: string
parentId?: string
}
const props = defineProps<Props>()
const clientId = toRef(() => props.id)
const client = ref<Client>()
const treeState = useTreeState()
const emit = defineEmits<{ (e: 'clientDeleted', data: string): void }>()
const alerts = useAlertsStore()
const updateErrors = ref([])
async function loadClient() {
console.log('loadClient called: ', props.id)
if (!props.id) return
client.value = await treeState.getClient(props.id)
}
@ -46,12 +51,27 @@ async function deleteClient(deleteId: string) {
emit('clientDeleted', deleteId)
}
function clearUpdateErrors() {
updateErrors.value = []
}
async function updateClient(updated: ClientCreate) {
const response = await SshecretAdmin.updateClientApiV1ClientsIdPut({
path: { id: idKey(localClient.value.id) },
body: data,
})
client.value = response.data
try {
const responseData = assertSdkResponseOk(response)
client.value = responseData
clearUpdateErrors()
} catch (err) {
if (err instanceof ValidationError) {
updateErrors.value = err.errors
} else {
const errorMessage = err.message ?? 'Unknown error'
alerts.showAlert(`Error from backend: ${errorMessage}`, 'error')
}
}
}
onMounted(loadClient)

View File

@ -88,7 +88,13 @@
</div>
</div>
<sl-drawer label="Create Client" :open="createDrawerOpen" @sl-hide="createDrawerOpen = false">
<ClientForm @submit="createClient" @cancel="createDrawerOpen = false" :key="createFormKey" />
<ClientForm
@submit="createClient"
@cancel="createDrawerOpen = false"
@clearErrors="clearCreateErrors"
:key="createFormKey"
:errors="createErrors"
/>
</sl-drawer>
</template>
@ -101,6 +107,8 @@ import { usePagination } from '@/composables/usePagination'
import { SshecretAdmin } from '@/client/sdk.gen'
import type { Client, ClientCreate } from '@/client/types.gen'
import { ValidationError } from '@/api/errors'
import { assertSdkResponseOk } from '@/api/AssertSdkResponseOk'
import { useTreeState } from '@/store/useTreeState'
import { useRouter, useRoute } from 'vue-router'
@ -110,6 +118,7 @@ import ClientSecretTreeItem from '@/components/clients/ClientSecretTreeItem.vue'
import ClientForm from '@/components/clients/ClientForm.vue'
import PageNumbers from '@/components/common/PageNumbers.vue'
import TreeItemSkeleton from '@/components/common/TreeItemSkeleton.vue'
import { useAlertsStore } from '@/store/useAlertsStore'
import { useDebounce } from '@/composables/useDebounce'
const treeState = useTreeState()
@ -121,6 +130,8 @@ const clients = computed(() => treeState.clients.clients)
const selectedClient = ref<Client | null>(null)
const selectedSecret = ref<string | null>(null)
const createErrors = ref([])
const createFormKey = ref<number>(0)
const createDrawerOpen = ref<boolean>(false)
@ -135,6 +146,7 @@ const router = useRouter()
const clientQuery = toRef(() => props.loadClient)
const debouncedQuery = useDebounce(clientQuery, 300)
const alerts = useAlertsStore()
const { pageNum, offset, firstResult, lastResult, totalPages, nextPage, prevPage, goToPage } =
usePagination(totalClients, clientsPerPage)
@ -173,12 +185,28 @@ function itemSelected(event: Event) {
async function createClient(data: ClientCreate) {
const response = await SshecretAdmin.createClientApiV1ClientsPost({ body: data })
clients.value.unshift(response.data)
totalClients.value += 1
createDrawerOpen.value = false
createFormKey.value += 1
treeState.selectClient(response.data.id)
router.push({ name: 'Client', params: { id: response.data.id } })
try {
const responseData = assertSdkResponseOk(response)
clients.value.unshift(responseData)
totalClients.value += 1
createDrawerOpen.value = false
createFormKey.value += 1
treeState.selectClient(responseData.id)
router.push({ name: 'Client', params: { id: responseData.id } })
createErrors.value = []
} catch (err) {
if (err instanceof ValidationError) {
createErrors.value = err.errors
} else {
const errorMessage = err.message ?? 'Unknown error'
alerts.showAlert(`Error from backend: ${errorMessage}`, 'error')
}
}
}
function clearCreateErrors() {
// Clear any errors from the create form.
createErrors.value = []
}
async function clientDeleted(id: string) {