Skip to content

Commit 6da9520

Browse files
committed
feat: Implement user deactivation functionality and improve dialog handling in DisableButton component
1 parent eedd713 commit 6da9520

File tree

2 files changed

+85
-28
lines changed

2 files changed

+85
-28
lines changed

custom/DisableButton.vue

Lines changed: 44 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
<template>
2-
<div class="flex items-end justify-start gap-2 cursor-pointer" @click="openDialog()">
3-
<p class="text-justify max-h-[18px] truncate max-w-[60vw] md:max-w-none">Deactivate user</p>
4-
</div>
2+
<div class="flex items-end justify-start gap-2 cursor-pointer" :class="{'opacity-50': checkboxes.length !== 1}">
3+
<p class="text-justify max-h-[18px] truncate max-w-[60vw] md:max-w-none">Deactivate user</p>
4+
</div>
55
<Dialog
66
ref="confirmDialog"
77
class="w-96"
88
header="Deactivate user"
99
:buttons="[
10-
{ label: 'Confirm', onclick: (dialog) => { console.log('Confirmed'); dialog.hide(); } },
10+
{ label: 'Confirm', onclick: (dialog) => { deactivateUser(); dialog.hide(); } },
1111
{ label: 'Cancel', onclick: (dialog) => dialog.hide() },
1212
]"
1313
>
@@ -18,14 +18,45 @@
1818
</template>
1919

2020
<script lang="ts" setup>
21-
import { Dialog } from '@/afcl';
22-
import { ref, watch } from 'vue';
21+
import { Dialog, Tooltip } from '@/afcl';
22+
import { ref } from 'vue';
2323
import { AdminUser, type AdminForthResourceCommon } from '@/types';
24+
import adminforth from "@/adminforth"
25+
import { callAdminForthApi } from '@/utils';
2426
2527
const confirmDialog = ref(null);
2628
2729
function openDialog() {
28-
confirmDialog.value.open()
30+
if ( props.checkboxes.length !== 1 ) {
31+
if (props.checkboxes.lenght > 1) {
32+
adminforth.alert({message: "Select only one account to deactivate", variant: "warning"})
33+
} else {
34+
adminforth.alert({message: "Select at least to deactivate", variant: "warning"})
35+
}
36+
} else {
37+
confirmDialog.value.open()
38+
}
39+
}
40+
41+
async function deactivateUser() {
42+
try {
43+
const res = await callAdminForthApi({
44+
path: `/plugin/${props.meta.pluginInstanceId}/deactivateUser`,
45+
method: 'POST',
46+
body: {
47+
record: props.checkboxes[0],
48+
},
49+
});
50+
if (!res || res.ok === false || res.error) {
51+
if ( res.error ) {
52+
throw new Error(res.error)
53+
}
54+
throw new Error("")
55+
}
56+
props.updateList();
57+
} catch (e) {
58+
adminforth.alert({message: `Error deactivating user. ${e}`, variant: "warning"});
59+
}
2960
}
3061
3162
const props = defineProps<{
@@ -42,11 +73,13 @@ const props = defineProps<{
4273
}
4374
}>();
4475
45-
46-
watch(props.checkboxes, (newVal) => {
47-
// Handle checkbox changes
48-
console.log("New checkboxes:", newVal)
76+
defineExpose({
77+
click
4978
});
5079
80+
function click() {
81+
openDialog();
82+
}
83+
5184
5285
</script>

index.ts

Lines changed: 41 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1-
import { AdminForthPlugin, AdminForthDataTypes, AdminForthResourcePages} from "adminforth";
1+
import { AdminForthPlugin, AdminForthDataTypes, AdminForthResourcePages, Filters} from "adminforth";
22
import type { IAdminForth, IHttpServer, AdminForthResourceColumn, AdminForthResource, IAdminForthHttpResponse, AdminUser, AdminForthComponentDeclaration } from "adminforth";
33
import type { PluginOptions } from './types.js';
4-
4+
55
export default class UserSoftDelete extends AdminForthPlugin {
66
options: PluginOptions;
7+
allowDisableFunc: Function | null | boolean = null;
78

89
constructor(options: PluginOptions) {
910
super(options, import.meta.url);
@@ -12,19 +13,14 @@ export default class UserSoftDelete extends AdminForthPlugin {
1213

1314
async modifyResourceConfig(adminforth: IAdminForth, resourceConfig: AdminForthResource) {
1415
super.modifyResourceConfig(adminforth, resourceConfig);
15-
let allowDisableFunc;
1616
if (this.options.canDeactivate) {
17-
//console.log('Using canDeactivate from plugin options');
18-
allowDisableFunc = this.options.canDeactivate;
17+
this.allowDisableFunc = this.options.canDeactivate;
1918
} else if (resourceConfig.options.allowedActions.delete && typeof resourceConfig.options.allowedActions.delete === 'function') {
20-
//console.log('Using existing delete permission function from resource config');
21-
allowDisableFunc = resourceConfig.options.allowedActions.delete;
19+
this.allowDisableFunc = resourceConfig.options.allowedActions.delete;
2220
} else if (resourceConfig.options.allowedActions.delete && typeof resourceConfig.options.allowedActions.delete === 'boolean') {
23-
//console.log('Using existing delete permission boolean from resource config:', resourceConfig.options.allowedActions.delete);
24-
allowDisableFunc = async () => resourceConfig.options.allowedActions.delete;
21+
this.allowDisableFunc = async () => resourceConfig.options.allowedActions.delete;
2522
} else {
26-
//console.log('No delete permission function found, defaulting to allow all');
27-
allowDisableFunc = async () => true;
23+
this.allowDisableFunc = async () => true;
2824
}
2925

3026
resourceConfig.options.allowedActions.delete = false;
@@ -72,7 +68,7 @@ export default class UserSoftDelete extends AdminForthPlugin {
7268
resourceConfig.options.pageInjections.list.threeDotsDropdownItems = [];
7369
}
7470
(resourceConfig.options.pageInjections.list.threeDotsDropdownItems as AdminForthComponentDeclaration[]).push(
75-
{ file: this.componentPath('DisableButton.vue') }
71+
{ file: this.componentPath('DisableButton.vue'), meta: { pluginInstanceId: this.pluginInstanceId } }
7672
);
7773

7874
// simply modify resourceConfig or adminforth.config. You can get access to plugin options via this.options;
@@ -85,16 +81,44 @@ export default class UserSoftDelete extends AdminForthPlugin {
8581
instanceUniqueRepresentation(pluginOptions: any) : string {
8682
// optional method to return unique string representation of plugin instance.
8783
// Needed if plugin can have multiple instances on one resource
88-
return `single`;
84+
return `user-soft-delete`;
8985
}
9086

9187
setupEndpoints(server: IHttpServer) {
9288
server.endpoint({
9389
method: 'POST',
94-
path: `/plugin/${this.pluginInstanceId}/example`,
95-
handler: async ({ body }) => {
96-
const { name } = body;
97-
return { hey: `Hello ${name}` };
90+
path: `/plugin/${this.pluginInstanceId}/deactivateUser`,
91+
handler: async ({ adminUser,body }) => {
92+
let isAllowedToDeactivate = false;
93+
if ( typeof this.allowDisableFunc === "function" ) {
94+
isAllowedToDeactivate = await this.allowDisableFunc(adminUser);
95+
} else if (typeof this.allowDisableFunc === "boolean") {
96+
isAllowedToDeactivate = this.allowDisableFunc;
97+
}
98+
if ( isAllowedToDeactivate === false ) {
99+
return {ok: false, error: "Not allowed to deactivate user"}
100+
}
101+
const id = body.record;
102+
const primaryKeyColumn = this.resourceConfig.columns.find((col) => col.primaryKey);
103+
104+
const oldUser = await this.adminforth
105+
.resource(this.resourceConfig.resourceId)
106+
.get([Filters.EQ(primaryKeyColumn.name, id)]);
107+
108+
if (!oldUser) {
109+
throw new Error(`User with id ${id} not found`);
110+
}
111+
112+
const newUser = { ...oldUser, [this.options.activeFieldName]: false };
113+
114+
await this.adminforth.updateResourceRecord({
115+
resource: this.resourceConfig,
116+
recordId: id,
117+
oldRecord: oldUser,
118+
record: newUser,
119+
adminUser: adminUser
120+
})
121+
return {ok: true}
98122
}
99123
});
100124
}

0 commit comments

Comments
 (0)