diff --git a/ui/src/views/UserListView.vue b/ui/src/views/UserListView.vue index 6bb84b0..03e9081 100644 --- a/ui/src/views/UserListView.vue +++ b/ui/src/views/UserListView.vue @@ -51,12 +51,34 @@ mdi-lock-open-variant @@ -85,6 +107,21 @@ + + + + + {{ t('user.' + actionType) }} + {{ t('user.' + actionType + 'Confirm', { id: actionTarget?.id }) }} + + + {{ t('common.cancel') }} + {{ t('common.confirm') }} + + + @@ -120,6 +157,12 @@ const deleteTarget = ref(null) const deleting = ref(false) const bulkDeleteDialog = ref(false) +// Row gear-menu action state (lock/unlock, isolate/restore, reset). +const actionDialog = ref(false) +const actionType = ref('') +const actionTarget = ref(null) +const actionLoading = ref(false) + const headers = computed(() => [ { title: t('user.login'), key: 'id', sortable: true }, { title: t('user.firstName'), key: 'firstName', sortable: true }, @@ -180,6 +223,36 @@ async function confirmBulkDelete() { dt.load({ page: 1, itemsPerPage: itemsPerPage.value }) } +function startUserAction(item, type) { + actionTarget.value = item + actionType.value = type + actionDialog.value = true +} + +async function confirmUserAction() { + if (dt.demoMode.value) { + errorStore.push({ message: t('user.demoAction'), status: 0 }) + actionDialog.value = false + return + } + actionLoading.value = true + const id = actionTarget.value.id + const actions = { + lock: () => api.del(`rest/service/id/user/${id}/lock`), + unlock: () => api.put(`rest/service/id/user/${id}/unlock`), + isolate: () => api.del(`rest/service/id/user/${id}/isolate`), + restore: () => api.put(`rest/service/id/user/${id}/restore`), + resetPassword: () => api.put(`rest/service/id/user/${id}/reset`), + } + await actions[actionType.value]() + actionLoading.value = false + actionDialog.value = false + actionTarget.value = null + // Reload the current page so the status icon and the contextual + // lock/isolate menu labels reflect the new state. + dt.load(lastOptions) +} + onMounted(() => { appStore.setBreadcrumbs( [