adminforth 1.1.36 → 1.1.38
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +36 -32
- package/dist/spa/spa/src/components/ResourceListTable.vue +31 -4
- package/dist/spa/spa/src/components/ValueRenderer.vue +1 -1
- package/index.ts +45 -32
- package/package.json +1 -1
- package/spa/src/components/ResourceListTable.vue +31 -4
- package/spa/src/components/ValueRenderer.vue +1 -1
package/dist/index.js
CHANGED
|
@@ -645,25 +645,27 @@ class AdminForth {
|
|
|
645
645
|
function interpretResource(adminUser, resource, meta, source) {
|
|
646
646
|
return __awaiter(this, void 0, void 0, function* () {
|
|
647
647
|
var _b;
|
|
648
|
-
const newResource = JSON.parse(JSON.stringify(resource));
|
|
649
648
|
if (process.env.HEAVY_DEBUG) {
|
|
650
649
|
console.log('🪲Interpreting resource', resource.resourceId, source);
|
|
651
650
|
}
|
|
651
|
+
const allowedActions = {};
|
|
652
652
|
yield Promise.all(Object.entries(((_b = resource.options) === null || _b === void 0 ? void 0 : _b.allowedActions) || {}).map((_c) => __awaiter(this, [_c], void 0, function* ([key, value]) {
|
|
653
653
|
if (process.env.HEAVY_DEBUG) {
|
|
654
654
|
console.log('🪲checking for allowed call', key, 'value:', value, 'typeof', typeof value);
|
|
655
655
|
}
|
|
656
656
|
// if callable then call
|
|
657
657
|
if (typeof value === 'function') {
|
|
658
|
-
|
|
658
|
+
allowedActions[key] = yield value({ adminUser, resource, meta, source });
|
|
659
|
+
}
|
|
660
|
+
else {
|
|
661
|
+
allowedActions[key] = value;
|
|
659
662
|
}
|
|
660
663
|
})));
|
|
661
|
-
return
|
|
664
|
+
return { allowedActions };
|
|
662
665
|
});
|
|
663
666
|
}
|
|
664
|
-
function checkAccess(action,
|
|
665
|
-
|
|
666
|
-
const allowed = (_b = resource.options) === null || _b === void 0 ? void 0 : _b.allowedActions[action];
|
|
667
|
+
function checkAccess(action, allowedActions) {
|
|
668
|
+
const allowed = allowedActions[action];
|
|
667
669
|
if (allowed !== true) {
|
|
668
670
|
return { error: typeof allowed === 'string' ? allowed : 'Action is not allowed', allowed: false };
|
|
669
671
|
}
|
|
@@ -680,13 +682,15 @@ class AdminForth {
|
|
|
680
682
|
if (this.statuses.dbDiscover !== 'done') {
|
|
681
683
|
return { error: 'Database discovery is still in progress, please try later' };
|
|
682
684
|
}
|
|
683
|
-
const
|
|
684
|
-
if (!
|
|
685
|
+
const resource = this.config.resources.find((res) => res.resourceId == resourceId);
|
|
686
|
+
if (!resource) {
|
|
685
687
|
return { error: `Resource ${resourceId} not found` };
|
|
686
688
|
}
|
|
687
|
-
const
|
|
689
|
+
const { allowedActions } = yield interpretResource(adminUser, resource, {}, ActionCheckSource.DisplayButtons);
|
|
688
690
|
// exclude "plugins" key
|
|
689
|
-
return {
|
|
691
|
+
return {
|
|
692
|
+
resource: Object.assign(Object.assign({}, resource), { plugins: undefined, options: Object.assign(Object.assign({}, resource.options), { allowedActions }) })
|
|
693
|
+
};
|
|
690
694
|
}),
|
|
691
695
|
});
|
|
692
696
|
server.endpoint({
|
|
@@ -704,12 +708,12 @@ class AdminForth {
|
|
|
704
708
|
if (this.statuses.dbDiscover !== 'done') {
|
|
705
709
|
return { error: 'Database discovery is still in progress, please try later' };
|
|
706
710
|
}
|
|
707
|
-
const
|
|
708
|
-
if (!
|
|
711
|
+
const resource = this.config.resources.find((res) => res.resourceId == resourceId);
|
|
712
|
+
if (!resource) {
|
|
709
713
|
return { error: `Resource ${resourceId} not found` };
|
|
710
714
|
}
|
|
711
|
-
const
|
|
712
|
-
const { allowed, error } = checkAccess(source,
|
|
715
|
+
const { allowedActions } = yield interpretResource(adminUser, resource, { requestBody: body }, ActionCheckSource.DisplayButtons);
|
|
716
|
+
const { allowed, error } = checkAccess(source, allowedActions);
|
|
713
717
|
if (!allowed) {
|
|
714
718
|
return { error };
|
|
715
719
|
}
|
|
@@ -903,12 +907,12 @@ class AdminForth {
|
|
|
903
907
|
path: '/create_record',
|
|
904
908
|
handler: (_y) => __awaiter(this, [_y], void 0, function* ({ body, adminUser }) {
|
|
905
909
|
var _z, _0, _1, _2, _3;
|
|
906
|
-
const
|
|
907
|
-
if (!
|
|
910
|
+
const resource = this.config.resources.find((res) => res.resourceId == body['resourceId']);
|
|
911
|
+
if (!resource) {
|
|
908
912
|
return { error: `Resource '${body['resourceId']}' not found` };
|
|
909
913
|
}
|
|
910
|
-
const
|
|
911
|
-
const { allowed, error } = checkAccess(AllowedActionsEnum.create,
|
|
914
|
+
const { allowedActions } = yield interpretResource(adminUser, resource, { requestBody: body }, ActionCheckSource.CreateRequest);
|
|
915
|
+
const { allowed, error } = checkAccess(AllowedActionsEnum.create, allowedActions);
|
|
912
916
|
if (!allowed) {
|
|
913
917
|
return { error };
|
|
914
918
|
}
|
|
@@ -975,20 +979,20 @@ class AdminForth {
|
|
|
975
979
|
path: '/update_record',
|
|
976
980
|
handler: (_4) => __awaiter(this, [_4], void 0, function* ({ body, adminUser }) {
|
|
977
981
|
var _5, _6, _7, _8;
|
|
978
|
-
const
|
|
979
|
-
if (!
|
|
982
|
+
const resource = this.config.resources.find((res) => res.resourceId == body['resourceId']);
|
|
983
|
+
if (!resource) {
|
|
980
984
|
return { error: `Resource '${body['resourceId']}' not found` };
|
|
981
985
|
}
|
|
982
986
|
const recordId = body['recordId'];
|
|
983
|
-
const connector = this.connectors[
|
|
984
|
-
const oldRecord = yield connector.getRecordByPrimaryKey(
|
|
987
|
+
const connector = this.connectors[resource.dataSource];
|
|
988
|
+
const oldRecord = yield connector.getRecordByPrimaryKey(resource, recordId);
|
|
985
989
|
if (!oldRecord) {
|
|
986
|
-
const primaryKeyColumn =
|
|
990
|
+
const primaryKeyColumn = resource.columns.find((col) => col.primaryKey);
|
|
987
991
|
return { error: `Record with ${primaryKeyColumn.name} ${recordId} not found` };
|
|
988
992
|
}
|
|
989
993
|
const record = body['record'];
|
|
990
|
-
const
|
|
991
|
-
const { allowed, error } = checkAccess(AllowedActionsEnum.edit,
|
|
994
|
+
const { allowedActions } = yield interpretResource(adminUser, resource, { requestBody: body, record, oldRecord }, ActionCheckSource.EditRequest);
|
|
995
|
+
const { allowed, error } = checkAccess(AllowedActionsEnum.edit, allowedActions);
|
|
992
996
|
if (!allowed) {
|
|
993
997
|
return { error };
|
|
994
998
|
}
|
|
@@ -1040,19 +1044,19 @@ class AdminForth {
|
|
|
1040
1044
|
path: '/delete_record',
|
|
1041
1045
|
handler: (_9) => __awaiter(this, [_9], void 0, function* ({ body, adminUser }) {
|
|
1042
1046
|
var _10, _11, _12, _13;
|
|
1043
|
-
const
|
|
1044
|
-
const record = yield this.connectors[
|
|
1045
|
-
if (!
|
|
1047
|
+
const resource = this.config.resources.find((res) => res.resourceId == body['resourceId']);
|
|
1048
|
+
const record = yield this.connectors[resource.dataSource].getRecordByPrimaryKey(resource, body['primaryKey']);
|
|
1049
|
+
if (!resource) {
|
|
1046
1050
|
return { error: `Resource '${body['resourceId']}' not found` };
|
|
1047
1051
|
}
|
|
1048
1052
|
if (!record) {
|
|
1049
1053
|
return { error: `Record with ${body['primaryKey']} not found` };
|
|
1050
1054
|
}
|
|
1051
|
-
if (
|
|
1052
|
-
return { error: `Resource '${
|
|
1055
|
+
if (resource.options.allowedActions.delete === false) {
|
|
1056
|
+
return { error: `Resource '${resource.resourceId}' does not allow delete action` };
|
|
1053
1057
|
}
|
|
1054
|
-
const
|
|
1055
|
-
const { allowed, error } = checkAccess(AllowedActionsEnum.delete,
|
|
1058
|
+
const { allowedActions } = yield interpretResource(adminUser, resource, { requestBody: body }, ActionCheckSource.DeleteRequest);
|
|
1059
|
+
const { allowed, error } = checkAccess(AllowedActionsEnum.delete, allowedActions);
|
|
1056
1060
|
if (!allowed) {
|
|
1057
1061
|
return { error };
|
|
1058
1062
|
}
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
<tr>
|
|
29
29
|
<th scope="col" class="p-4">
|
|
30
30
|
<div v-if="rows && rows.length" class="flex items-center">
|
|
31
|
-
<input id="checkbox-all-search" type="checkbox" :checked="allFromThisPageChecked" @change="selectAll()"
|
|
31
|
+
<input id="checkbox-all-search" type="checkbox" :checked="allFromThisPageChecked" @change="selectAll()"
|
|
32
32
|
class="w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 dark:focus:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600">
|
|
33
33
|
<label for="checkbox-all-search" class="sr-only">checkbox</label>
|
|
34
34
|
</div>
|
|
@@ -118,11 +118,12 @@
|
|
|
118
118
|
</td>
|
|
119
119
|
</tr>
|
|
120
120
|
|
|
121
|
-
<tr v-else v-for="(row, rowI) in rows" :key="row.id"
|
|
122
|
-
class="bg-list-view-table-bg border-b dark:bg-gray-800 border-list-view-border-color dark:border-gray-700 hover:bg-list-view-table-row-hover dark:hover:bg-gray-600">
|
|
121
|
+
<tr @click="onClick($event,row)" v-else v-for="(row, rowI) in rows" :key="row.id"
|
|
122
|
+
class="bg-list-view-table-bg border-b dark:bg-gray-800 border-list-view-border-color dark:border-gray-700 hover:bg-list-view-table-row-hover dark:hover:bg-gray-600 cursor-pointer">
|
|
123
123
|
<td class="w-4 p-4">
|
|
124
124
|
<div class="flex items center">
|
|
125
125
|
<input
|
|
126
|
+
@click="(e)=>{e.stopPropagation()}"
|
|
126
127
|
id="checkbox-table-search-1"
|
|
127
128
|
type="checkbox"
|
|
128
129
|
:checked="checkboxesInternal.includes(row.id)"
|
|
@@ -142,7 +143,7 @@
|
|
|
142
143
|
:resource="resource"
|
|
143
144
|
/>
|
|
144
145
|
</td>
|
|
145
|
-
<td class=" items-center px-6 py-4">
|
|
146
|
+
<td class=" items-center px-6 py-4" @click="(e)=>{e.stopPropagation()}">
|
|
146
147
|
<div class="flex">
|
|
147
148
|
<RouterLink
|
|
148
149
|
v-if="resource.options?.allowedActions.show"
|
|
@@ -291,6 +292,7 @@ IconFilterOutline,
|
|
|
291
292
|
IconPenSolid,
|
|
292
293
|
IconTrashBinSolid
|
|
293
294
|
} from '@iconify-prerendered/vue-flowbite';
|
|
295
|
+
import router from '@/router';
|
|
294
296
|
|
|
295
297
|
const coreStore = useCoreStore();
|
|
296
298
|
|
|
@@ -385,6 +387,31 @@ function onSortButtonClick(field) {
|
|
|
385
387
|
}
|
|
386
388
|
}
|
|
387
389
|
|
|
390
|
+
|
|
391
|
+
const clickTarget = ref(null);
|
|
392
|
+
async function onClick(e,row) {
|
|
393
|
+
console.log(e,row)
|
|
394
|
+
if(clickTarget.value === e.target) return;
|
|
395
|
+
clickTarget.value = e.target;
|
|
396
|
+
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
397
|
+
if (window.getSelection().toString()) return;
|
|
398
|
+
else {router.push({
|
|
399
|
+
name: 'resource-show',
|
|
400
|
+
params: {
|
|
401
|
+
resourceId: props.resource.resourceId,
|
|
402
|
+
primaryKey: row._primaryKeyValue,
|
|
403
|
+
},
|
|
404
|
+
})}
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
|
|
408
|
+
|
|
409
|
+
|
|
410
|
+
|
|
411
|
+
|
|
412
|
+
|
|
413
|
+
|
|
414
|
+
|
|
388
415
|
async function deleteRecord(row) {
|
|
389
416
|
const data = await window.adminforth.confirm({
|
|
390
417
|
message: 'Are you sure you want to delete this item?',
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div>
|
|
3
3
|
|
|
4
|
-
<span v-if="column.foreignResource">
|
|
4
|
+
<span @click="(e)=>{e.stopPropagation()}" v-if="column.foreignResource">
|
|
5
5
|
<RouterLink v-if="record[column.name]" class="font-medium text-blue-600 dark:text-blue-500 hover:brightness-110"
|
|
6
6
|
:to="{ name: 'resource-show', params: { resourceId: column.foreignResource.resourceId, primaryKey: record[column.name].pk } }">
|
|
7
7
|
{{ record[column.name].label }}
|
package/index.ts
CHANGED
|
@@ -17,6 +17,7 @@ import { AdminForthConfig, AdminForthClass, AdminForthComponentDeclaration, Admi
|
|
|
17
17
|
AfterDataSourceResponseFunction, AllowedActionValue, AdminUser,
|
|
18
18
|
AdminForthResource,
|
|
19
19
|
AllowedActionsEnum,
|
|
20
|
+
AllowedActions,
|
|
20
21
|
ActionCheckSource
|
|
21
22
|
} from './types/AdminForthConfig.js';
|
|
22
23
|
import path from 'path';
|
|
@@ -732,11 +733,11 @@ class AdminForth implements AdminForthClass {
|
|
|
732
733
|
},
|
|
733
734
|
});
|
|
734
735
|
|
|
735
|
-
async function interpretResource(adminUser: AdminUser, resource: AdminForthResource, meta: any, source: ActionCheckSource): Promise<
|
|
736
|
-
const newResource = JSON.parse(JSON.stringify(resource));
|
|
736
|
+
async function interpretResource(adminUser: AdminUser, resource: AdminForthResource, meta: any, source: ActionCheckSource): Promise<{allowedActions: AllowedActions}> {
|
|
737
737
|
if (process.env.HEAVY_DEBUG) {
|
|
738
738
|
console.log('🪲Interpreting resource', resource.resourceId, source);
|
|
739
739
|
}
|
|
740
|
+
const allowedActions = {};
|
|
740
741
|
|
|
741
742
|
await Promise.all(
|
|
742
743
|
Object.entries(resource.options?.allowedActions || {}).map(
|
|
@@ -747,15 +748,18 @@ class AdminForth implements AdminForthClass {
|
|
|
747
748
|
|
|
748
749
|
// if callable then call
|
|
749
750
|
if (typeof value === 'function') {
|
|
750
|
-
|
|
751
|
+
allowedActions[key] = await value({ adminUser, resource, meta, source });
|
|
752
|
+
} else {
|
|
753
|
+
allowedActions[key] = value;
|
|
751
754
|
}
|
|
752
755
|
})
|
|
753
756
|
);
|
|
754
|
-
|
|
757
|
+
|
|
758
|
+
return { allowedActions };
|
|
755
759
|
}
|
|
756
760
|
|
|
757
|
-
function checkAccess(action: AllowedActionsEnum,
|
|
758
|
-
const allowed = (
|
|
761
|
+
function checkAccess(action: AllowedActionsEnum, allowedActions: AllowedActions): { allowed: boolean, error?: string } {
|
|
762
|
+
const allowed = (allowedActions[action] as boolean | string | undefined);
|
|
759
763
|
if (allowed !== true) {
|
|
760
764
|
return { error: typeof allowed === 'string' ? allowed : 'Action is not allowed', allowed: false };
|
|
761
765
|
}
|
|
@@ -774,15 +778,24 @@ class AdminForth implements AdminForthClass {
|
|
|
774
778
|
if (this.statuses.dbDiscover !== 'done') {
|
|
775
779
|
return { error : 'Database discovery is still in progress, please try later' };
|
|
776
780
|
}
|
|
777
|
-
const
|
|
778
|
-
if (!
|
|
781
|
+
const resource = this.config.resources.find((res) => res.resourceId == resourceId);
|
|
782
|
+
if (!resource) {
|
|
779
783
|
return { error: `Resource ${resourceId} not found` };
|
|
780
784
|
}
|
|
781
785
|
|
|
782
|
-
const
|
|
786
|
+
const { allowedActions } = await interpretResource(adminUser, resource, {}, ActionCheckSource.DisplayButtons);
|
|
783
787
|
|
|
784
788
|
// exclude "plugins" key
|
|
785
|
-
return {
|
|
789
|
+
return {
|
|
790
|
+
resource: {
|
|
791
|
+
...resource,
|
|
792
|
+
plugins: undefined,
|
|
793
|
+
options: {
|
|
794
|
+
...resource.options,
|
|
795
|
+
allowedActions,
|
|
796
|
+
}
|
|
797
|
+
}
|
|
798
|
+
};
|
|
786
799
|
},
|
|
787
800
|
});
|
|
788
801
|
server.endpoint({
|
|
@@ -799,14 +812,14 @@ class AdminForth implements AdminForthClass {
|
|
|
799
812
|
if (this.statuses.dbDiscover !== 'done') {
|
|
800
813
|
return { error : 'Database discovery is still in progress, please try later' };
|
|
801
814
|
}
|
|
802
|
-
const
|
|
803
|
-
if (!
|
|
815
|
+
const resource = this.config.resources.find((res) => res.resourceId == resourceId);
|
|
816
|
+
if (!resource) {
|
|
804
817
|
return { error: `Resource ${resourceId} not found` };
|
|
805
818
|
}
|
|
806
819
|
|
|
807
|
-
const
|
|
820
|
+
const { allowedActions } = await interpretResource(adminUser, resource, { requestBody: body }, ActionCheckSource.DisplayButtons);
|
|
808
821
|
|
|
809
|
-
const { allowed, error } = checkAccess(source as AllowedActionsEnum,
|
|
822
|
+
const { allowed, error } = checkAccess(source as AllowedActionsEnum, allowedActions);
|
|
810
823
|
if (!allowed) {
|
|
811
824
|
return { error };
|
|
812
825
|
}
|
|
@@ -1024,13 +1037,13 @@ class AdminForth implements AdminForthClass {
|
|
|
1024
1037
|
method: 'POST',
|
|
1025
1038
|
path: '/create_record',
|
|
1026
1039
|
handler: async ({ body, adminUser }) => {
|
|
1027
|
-
const
|
|
1028
|
-
if (!
|
|
1040
|
+
const resource = this.config.resources.find((res) => res.resourceId == body['resourceId']);
|
|
1041
|
+
if (!resource) {
|
|
1029
1042
|
return { error: `Resource '${body['resourceId']}' not found` };
|
|
1030
1043
|
}
|
|
1031
|
-
const
|
|
1044
|
+
const { allowedActions } = await interpretResource(adminUser, resource, { requestBody: body}, ActionCheckSource.CreateRequest);
|
|
1032
1045
|
|
|
1033
|
-
const { allowed, error } = checkAccess(AllowedActionsEnum.create,
|
|
1046
|
+
const { allowed, error } = checkAccess(AllowedActionsEnum.create, allowedActions);
|
|
1034
1047
|
if (!allowed) {
|
|
1035
1048
|
return { error };
|
|
1036
1049
|
}
|
|
@@ -1105,23 +1118,23 @@ class AdminForth implements AdminForthClass {
|
|
|
1105
1118
|
method: 'POST',
|
|
1106
1119
|
path: '/update_record',
|
|
1107
1120
|
handler: async ({ body, adminUser }) => {
|
|
1108
|
-
const
|
|
1109
|
-
if (!
|
|
1121
|
+
const resource = this.config.resources.find((res) => res.resourceId == body['resourceId']);
|
|
1122
|
+
if (!resource) {
|
|
1110
1123
|
return { error: `Resource '${body['resourceId']}' not found` };
|
|
1111
1124
|
}
|
|
1112
1125
|
|
|
1113
1126
|
const recordId = body['recordId'];
|
|
1114
|
-
const connector = this.connectors[
|
|
1115
|
-
const oldRecord = await connector.getRecordByPrimaryKey(
|
|
1127
|
+
const connector = this.connectors[resource.dataSource];
|
|
1128
|
+
const oldRecord = await connector.getRecordByPrimaryKey(resource, recordId)
|
|
1116
1129
|
if (!oldRecord) {
|
|
1117
|
-
const primaryKeyColumn =
|
|
1130
|
+
const primaryKeyColumn = resource.columns.find((col) => col.primaryKey);
|
|
1118
1131
|
return { error: `Record with ${primaryKeyColumn.name} ${recordId} not found` };
|
|
1119
1132
|
}
|
|
1120
1133
|
const record = body['record'];
|
|
1121
1134
|
|
|
1122
|
-
const
|
|
1135
|
+
const { allowedActions } = await interpretResource(adminUser, resource, { requestBody: body, record, oldRecord}, ActionCheckSource.EditRequest);
|
|
1123
1136
|
|
|
1124
|
-
const { allowed, error } = checkAccess(AllowedActionsEnum.edit,
|
|
1137
|
+
const { allowed, error } = checkAccess(AllowedActionsEnum.edit, allowedActions);
|
|
1125
1138
|
if (!allowed) {
|
|
1126
1139
|
return { error };
|
|
1127
1140
|
}
|
|
@@ -1178,21 +1191,21 @@ class AdminForth implements AdminForthClass {
|
|
|
1178
1191
|
method: 'POST',
|
|
1179
1192
|
path: '/delete_record',
|
|
1180
1193
|
handler: async ({ body, adminUser }) => {
|
|
1181
|
-
const
|
|
1182
|
-
const record = await this.connectors[
|
|
1183
|
-
if (!
|
|
1194
|
+
const resource = this.config.resources.find((res) => res.resourceId == body['resourceId']);
|
|
1195
|
+
const record = await this.connectors[resource.dataSource].getRecordByPrimaryKey(resource, body['primaryKey']);
|
|
1196
|
+
if (!resource) {
|
|
1184
1197
|
return { error: `Resource '${body['resourceId']}' not found` };
|
|
1185
1198
|
}
|
|
1186
1199
|
if (!record){
|
|
1187
1200
|
return { error: `Record with ${body['primaryKey']} not found` };
|
|
1188
1201
|
}
|
|
1189
|
-
if (
|
|
1190
|
-
return { error: `Resource '${
|
|
1202
|
+
if (resource.options.allowedActions.delete === false) {
|
|
1203
|
+
return { error: `Resource '${resource.resourceId}' does not allow delete action` };
|
|
1191
1204
|
}
|
|
1192
1205
|
|
|
1193
|
-
const
|
|
1206
|
+
const { allowedActions } = await interpretResource(adminUser, resource, { requestBody: body }, ActionCheckSource.DeleteRequest);
|
|
1194
1207
|
|
|
1195
|
-
const { allowed, error } = checkAccess(AllowedActionsEnum.delete,
|
|
1208
|
+
const { allowed, error } = checkAccess(AllowedActionsEnum.delete, allowedActions);
|
|
1196
1209
|
if (!allowed) {
|
|
1197
1210
|
return { error };
|
|
1198
1211
|
}
|
package/package.json
CHANGED
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
<tr>
|
|
29
29
|
<th scope="col" class="p-4">
|
|
30
30
|
<div v-if="rows && rows.length" class="flex items-center">
|
|
31
|
-
<input id="checkbox-all-search" type="checkbox" :checked="allFromThisPageChecked" @change="selectAll()"
|
|
31
|
+
<input id="checkbox-all-search" type="checkbox" :checked="allFromThisPageChecked" @change="selectAll()"
|
|
32
32
|
class="w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 dark:focus:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600">
|
|
33
33
|
<label for="checkbox-all-search" class="sr-only">checkbox</label>
|
|
34
34
|
</div>
|
|
@@ -118,11 +118,12 @@
|
|
|
118
118
|
</td>
|
|
119
119
|
</tr>
|
|
120
120
|
|
|
121
|
-
<tr v-else v-for="(row, rowI) in rows" :key="row.id"
|
|
122
|
-
class="bg-list-view-table-bg border-b dark:bg-gray-800 border-list-view-border-color dark:border-gray-700 hover:bg-list-view-table-row-hover dark:hover:bg-gray-600">
|
|
121
|
+
<tr @click="onClick($event,row)" v-else v-for="(row, rowI) in rows" :key="row.id"
|
|
122
|
+
class="bg-list-view-table-bg border-b dark:bg-gray-800 border-list-view-border-color dark:border-gray-700 hover:bg-list-view-table-row-hover dark:hover:bg-gray-600 cursor-pointer">
|
|
123
123
|
<td class="w-4 p-4">
|
|
124
124
|
<div class="flex items center">
|
|
125
125
|
<input
|
|
126
|
+
@click="(e)=>{e.stopPropagation()}"
|
|
126
127
|
id="checkbox-table-search-1"
|
|
127
128
|
type="checkbox"
|
|
128
129
|
:checked="checkboxesInternal.includes(row.id)"
|
|
@@ -142,7 +143,7 @@
|
|
|
142
143
|
:resource="resource"
|
|
143
144
|
/>
|
|
144
145
|
</td>
|
|
145
|
-
<td class=" items-center px-6 py-4">
|
|
146
|
+
<td class=" items-center px-6 py-4" @click="(e)=>{e.stopPropagation()}">
|
|
146
147
|
<div class="flex">
|
|
147
148
|
<RouterLink
|
|
148
149
|
v-if="resource.options?.allowedActions.show"
|
|
@@ -291,6 +292,7 @@ IconFilterOutline,
|
|
|
291
292
|
IconPenSolid,
|
|
292
293
|
IconTrashBinSolid
|
|
293
294
|
} from '@iconify-prerendered/vue-flowbite';
|
|
295
|
+
import router from '@/router';
|
|
294
296
|
|
|
295
297
|
const coreStore = useCoreStore();
|
|
296
298
|
|
|
@@ -385,6 +387,31 @@ function onSortButtonClick(field) {
|
|
|
385
387
|
}
|
|
386
388
|
}
|
|
387
389
|
|
|
390
|
+
|
|
391
|
+
const clickTarget = ref(null);
|
|
392
|
+
async function onClick(e,row) {
|
|
393
|
+
console.log(e,row)
|
|
394
|
+
if(clickTarget.value === e.target) return;
|
|
395
|
+
clickTarget.value = e.target;
|
|
396
|
+
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
397
|
+
if (window.getSelection().toString()) return;
|
|
398
|
+
else {router.push({
|
|
399
|
+
name: 'resource-show',
|
|
400
|
+
params: {
|
|
401
|
+
resourceId: props.resource.resourceId,
|
|
402
|
+
primaryKey: row._primaryKeyValue,
|
|
403
|
+
},
|
|
404
|
+
})}
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
|
|
408
|
+
|
|
409
|
+
|
|
410
|
+
|
|
411
|
+
|
|
412
|
+
|
|
413
|
+
|
|
414
|
+
|
|
388
415
|
async function deleteRecord(row) {
|
|
389
416
|
const data = await window.adminforth.confirm({
|
|
390
417
|
message: 'Are you sure you want to delete this item?',
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div>
|
|
3
3
|
|
|
4
|
-
<span v-if="column.foreignResource">
|
|
4
|
+
<span @click="(e)=>{e.stopPropagation()}" v-if="column.foreignResource">
|
|
5
5
|
<RouterLink v-if="record[column.name]" class="font-medium text-blue-600 dark:text-blue-500 hover:brightness-110"
|
|
6
6
|
:to="{ name: 'resource-show', params: { resourceId: column.foreignResource.resourceId, primaryKey: record[column.name].pk } }">
|
|
7
7
|
{{ record[column.name].label }}
|