adminforth 1.1.35 → 1.1.37

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 CHANGED
@@ -648,20 +648,24 @@ class AdminForth {
648
648
  if (process.env.HEAVY_DEBUG) {
649
649
  console.log('🪲Interpreting resource', resource.resourceId, source);
650
650
  }
651
+ const allowedActions = {};
651
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]) {
652
653
  if (process.env.HEAVY_DEBUG) {
653
654
  console.log('🪲checking for allowed call', key, 'value:', value, 'typeof', typeof value);
654
655
  }
655
656
  // if callable then call
656
657
  if (typeof value === 'function') {
657
- resource.options.allowedActions[key] = yield value({ adminUser, resource, meta, source });
658
+ allowedActions[key] = yield value({ adminUser, resource, meta, source });
659
+ }
660
+ else {
661
+ allowedActions[key] = value;
658
662
  }
659
663
  })));
664
+ return { allowedActions };
660
665
  });
661
666
  }
662
- function checkAccess(action, resource) {
663
- var _b;
664
- const allowed = (_b = resource.options) === null || _b === void 0 ? void 0 : _b.allowedActions[action];
667
+ function checkAccess(action, allowedActions) {
668
+ const allowed = allowedActions[action];
665
669
  if (allowed !== true) {
666
670
  return { error: typeof allowed === 'string' ? allowed : 'Action is not allowed', allowed: false };
667
671
  }
@@ -682,9 +686,11 @@ class AdminForth {
682
686
  if (!resource) {
683
687
  return { error: `Resource ${resourceId} not found` };
684
688
  }
685
- yield interpretResource(adminUser, resource, {}, ActionCheckSource.DisplayButtons);
689
+ const { allowedActions } = yield interpretResource(adminUser, resource, {}, ActionCheckSource.DisplayButtons);
686
690
  // exclude "plugins" key
687
- return { resource: Object.assign(Object.assign({}, resource), { plugins: undefined }) };
691
+ return {
692
+ resource: Object.assign(Object.assign({}, resource), { plugins: undefined, options: Object.assign(Object.assign({}, resource.options), { allowedActions }) })
693
+ };
688
694
  }),
689
695
  });
690
696
  server.endpoint({
@@ -706,8 +712,8 @@ class AdminForth {
706
712
  if (!resource) {
707
713
  return { error: `Resource ${resourceId} not found` };
708
714
  }
709
- yield interpretResource(adminUser, resource, { requestBody: body }, ActionCheckSource.DisplayButtons);
710
- const { allowed, error } = checkAccess(source, resource);
715
+ const { allowedActions } = yield interpretResource(adminUser, resource, { requestBody: body }, ActionCheckSource.DisplayButtons);
716
+ const { allowed, error } = checkAccess(source, allowedActions);
711
717
  if (!allowed) {
712
718
  return { error };
713
719
  }
@@ -905,8 +911,8 @@ class AdminForth {
905
911
  if (!resource) {
906
912
  return { error: `Resource '${body['resourceId']}' not found` };
907
913
  }
908
- yield interpretResource(adminUser, resource, { requestBody: body }, ActionCheckSource.CreateRequest);
909
- const { allowed, error } = checkAccess(AllowedActionsEnum.create, resource);
914
+ const { allowedActions } = yield interpretResource(adminUser, resource, { requestBody: body }, ActionCheckSource.CreateRequest);
915
+ const { allowed, error } = checkAccess(AllowedActionsEnum.create, allowedActions);
910
916
  if (!allowed) {
911
917
  return { error };
912
918
  }
@@ -985,8 +991,8 @@ class AdminForth {
985
991
  return { error: `Record with ${primaryKeyColumn.name} ${recordId} not found` };
986
992
  }
987
993
  const record = body['record'];
988
- yield interpretResource(adminUser, resource, { requestBody: body, record, oldRecord }, ActionCheckSource.EditRequest);
989
- const { allowed, error } = checkAccess(AllowedActionsEnum.edit, resource);
994
+ const { allowedActions } = yield interpretResource(adminUser, resource, { requestBody: body, record, oldRecord }, ActionCheckSource.EditRequest);
995
+ const { allowed, error } = checkAccess(AllowedActionsEnum.edit, allowedActions);
990
996
  if (!allowed) {
991
997
  return { error };
992
998
  }
@@ -1049,8 +1055,8 @@ class AdminForth {
1049
1055
  if (resource.options.allowedActions.delete === false) {
1050
1056
  return { error: `Resource '${resource.resourceId}' does not allow delete action` };
1051
1057
  }
1052
- yield interpretResource(adminUser, resource, { requestBody: body }, ActionCheckSource.DeleteRequest);
1053
- const { allowed, error } = checkAccess(AllowedActionsEnum.delete, resource);
1058
+ const { allowedActions } = yield interpretResource(adminUser, resource, { requestBody: body }, ActionCheckSource.DeleteRequest);
1059
+ const { allowed, error } = checkAccess(AllowedActionsEnum.delete, allowedActions);
1054
1060
  if (!allowed) {
1055
1061
  return { error };
1056
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"
121
+ <tr @click="onClick($event,row)" v-else v-for="(row, rowI) in rows" :key="row.id"
122
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">
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)"
@@ -134,6 +135,7 @@
134
135
  <td v-for="c in columnsListed" class="px-6 py-4">
135
136
  <!-- if c.name in listComponentsPerColumn, render it. If not, render ValueRenderer -->
136
137
  <component
138
+ @click="(e)=>{e.stopPropagation()}"
137
139
  :is="c?.components?.list ? getCustomComponent(c.components.list) : ValueRenderer"
138
140
  :meta="c?.components?.list.meta"
139
141
  :column="c"
@@ -142,7 +144,7 @@
142
144
  :resource="resource"
143
145
  />
144
146
  </td>
145
- <td class=" items-center px-6 py-4">
147
+ <td class=" items-center px-6 py-4" @click="(e)=>{e.stopPropagation()}">
146
148
  <div class="flex">
147
149
  <RouterLink
148
150
  v-if="resource.options?.allowedActions.show"
@@ -291,6 +293,7 @@ IconFilterOutline,
291
293
  IconPenSolid,
292
294
  IconTrashBinSolid
293
295
  } from '@iconify-prerendered/vue-flowbite';
296
+ import router from '@/router';
294
297
 
295
298
  const coreStore = useCoreStore();
296
299
 
@@ -385,6 +388,31 @@ function onSortButtonClick(field) {
385
388
  }
386
389
  }
387
390
 
391
+
392
+ const clickTarget = ref(null);
393
+ async function onClick(e,row) {
394
+ console.log(e,row)
395
+ if(clickTarget.value === e.target) return;
396
+ clickTarget.value = e.target;
397
+ await new Promise((resolve) => setTimeout(resolve, 500));
398
+ if (window.getSelection().toString()) return;
399
+ else {router.push({
400
+ name: 'resource-show',
401
+ params: {
402
+ resourceId: props.resource.resourceId,
403
+ primaryKey: row._primaryKeyValue,
404
+ },
405
+ })}
406
+ }
407
+
408
+
409
+
410
+
411
+
412
+
413
+
414
+
415
+
388
416
  async function deleteRecord(row) {
389
417
  const data = await window.adminforth.confirm({
390
418
  message: 'Are you sure you want to delete this item?',
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,10 +733,11 @@ class AdminForth implements AdminForthClass {
732
733
  },
733
734
  });
734
735
 
735
- async function interpretResource(adminUser: AdminUser, resource: AdminForthResource, meta: any, source: ActionCheckSource) {
736
+ async function interpretResource(adminUser: AdminUser, resource: AdminForthResource, meta: any, source: ActionCheckSource): Promise<{allowedActions: AllowedActions}> {
736
737
  if (process.env.HEAVY_DEBUG) {
737
738
  console.log('🪲Interpreting resource', resource.resourceId, source);
738
739
  }
740
+ const allowedActions = {};
739
741
 
740
742
  await Promise.all(
741
743
  Object.entries(resource.options?.allowedActions || {}).map(
@@ -746,14 +748,18 @@ class AdminForth implements AdminForthClass {
746
748
 
747
749
  // if callable then call
748
750
  if (typeof value === 'function') {
749
- resource.options.allowedActions[key] = await value({ adminUser, resource, meta, source });
751
+ allowedActions[key] = await value({ adminUser, resource, meta, source });
752
+ } else {
753
+ allowedActions[key] = value;
750
754
  }
751
755
  })
752
756
  );
757
+
758
+ return { allowedActions };
753
759
  }
754
760
 
755
- function checkAccess(action: AllowedActionsEnum, resource: AdminForthResource): { allowed: boolean, error?: string } {
756
- const allowed = (resource.options?.allowedActions[action] as boolean | string | undefined);
761
+ function checkAccess(action: AllowedActionsEnum, allowedActions: AllowedActions): { allowed: boolean, error?: string } {
762
+ const allowed = (allowedActions[action] as boolean | string | undefined);
757
763
  if (allowed !== true) {
758
764
  return { error: typeof allowed === 'string' ? allowed : 'Action is not allowed', allowed: false };
759
765
  }
@@ -777,10 +783,19 @@ class AdminForth implements AdminForthClass {
777
783
  return { error: `Resource ${resourceId} not found` };
778
784
  }
779
785
 
780
- await interpretResource(adminUser, resource, {}, ActionCheckSource.DisplayButtons);
786
+ const { allowedActions } = await interpretResource(adminUser, resource, {}, ActionCheckSource.DisplayButtons);
781
787
 
782
788
  // exclude "plugins" key
783
- return { resource: { ...resource, plugins: undefined } };
789
+ return {
790
+ resource: {
791
+ ...resource,
792
+ plugins: undefined,
793
+ options: {
794
+ ...resource.options,
795
+ allowedActions,
796
+ }
797
+ }
798
+ };
784
799
  },
785
800
  });
786
801
  server.endpoint({
@@ -802,9 +817,9 @@ class AdminForth implements AdminForthClass {
802
817
  return { error: `Resource ${resourceId} not found` };
803
818
  }
804
819
 
805
- await interpretResource(adminUser, resource, { requestBody: body }, ActionCheckSource.DisplayButtons);
820
+ const { allowedActions } = await interpretResource(adminUser, resource, { requestBody: body }, ActionCheckSource.DisplayButtons);
806
821
 
807
- const { allowed, error } = checkAccess(source as AllowedActionsEnum, resource);
822
+ const { allowed, error } = checkAccess(source as AllowedActionsEnum, allowedActions);
808
823
  if (!allowed) {
809
824
  return { error };
810
825
  }
@@ -1026,9 +1041,9 @@ class AdminForth implements AdminForthClass {
1026
1041
  if (!resource) {
1027
1042
  return { error: `Resource '${body['resourceId']}' not found` };
1028
1043
  }
1029
- await interpretResource(adminUser, resource, { requestBody: body}, ActionCheckSource.CreateRequest);
1044
+ const { allowedActions } = await interpretResource(adminUser, resource, { requestBody: body}, ActionCheckSource.CreateRequest);
1030
1045
 
1031
- const { allowed, error } = checkAccess(AllowedActionsEnum.create, resource);
1046
+ const { allowed, error } = checkAccess(AllowedActionsEnum.create, allowedActions);
1032
1047
  if (!allowed) {
1033
1048
  return { error };
1034
1049
  }
@@ -1117,9 +1132,9 @@ class AdminForth implements AdminForthClass {
1117
1132
  }
1118
1133
  const record = body['record'];
1119
1134
 
1120
- await interpretResource(adminUser, resource, { requestBody: body, record, oldRecord}, ActionCheckSource.EditRequest);
1135
+ const { allowedActions } = await interpretResource(adminUser, resource, { requestBody: body, record, oldRecord}, ActionCheckSource.EditRequest);
1121
1136
 
1122
- const { allowed, error } = checkAccess(AllowedActionsEnum.edit, resource);
1137
+ const { allowed, error } = checkAccess(AllowedActionsEnum.edit, allowedActions);
1123
1138
  if (!allowed) {
1124
1139
  return { error };
1125
1140
  }
@@ -1188,9 +1203,9 @@ class AdminForth implements AdminForthClass {
1188
1203
  return { error: `Resource '${resource.resourceId}' does not allow delete action` };
1189
1204
  }
1190
1205
 
1191
- await interpretResource(adminUser, resource, { requestBody: body }, ActionCheckSource.DeleteRequest);
1206
+ const { allowedActions } = await interpretResource(adminUser, resource, { requestBody: body }, ActionCheckSource.DeleteRequest);
1192
1207
 
1193
- const { allowed, error } = checkAccess(AllowedActionsEnum.delete, resource);
1208
+ const { allowed, error } = checkAccess(AllowedActionsEnum.delete, allowedActions);
1194
1209
  if (!allowed) {
1195
1210
  return { error };
1196
1211
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "adminforth",
3
- "version": "1.1.35",
3
+ "version": "1.1.37",
4
4
  "description": "OpenSource Vue3 powered forth-generation admin panel",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -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"
121
+ <tr @click="onClick($event,row)" v-else v-for="(row, rowI) in rows" :key="row.id"
122
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">
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)"
@@ -134,6 +135,7 @@
134
135
  <td v-for="c in columnsListed" class="px-6 py-4">
135
136
  <!-- if c.name in listComponentsPerColumn, render it. If not, render ValueRenderer -->
136
137
  <component
138
+ @click="(e)=>{e.stopPropagation()}"
137
139
  :is="c?.components?.list ? getCustomComponent(c.components.list) : ValueRenderer"
138
140
  :meta="c?.components?.list.meta"
139
141
  :column="c"
@@ -142,7 +144,7 @@
142
144
  :resource="resource"
143
145
  />
144
146
  </td>
145
- <td class=" items-center px-6 py-4">
147
+ <td class=" items-center px-6 py-4" @click="(e)=>{e.stopPropagation()}">
146
148
  <div class="flex">
147
149
  <RouterLink
148
150
  v-if="resource.options?.allowedActions.show"
@@ -291,6 +293,7 @@ IconFilterOutline,
291
293
  IconPenSolid,
292
294
  IconTrashBinSolid
293
295
  } from '@iconify-prerendered/vue-flowbite';
296
+ import router from '@/router';
294
297
 
295
298
  const coreStore = useCoreStore();
296
299
 
@@ -385,6 +388,31 @@ function onSortButtonClick(field) {
385
388
  }
386
389
  }
387
390
 
391
+
392
+ const clickTarget = ref(null);
393
+ async function onClick(e,row) {
394
+ console.log(e,row)
395
+ if(clickTarget.value === e.target) return;
396
+ clickTarget.value = e.target;
397
+ await new Promise((resolve) => setTimeout(resolve, 500));
398
+ if (window.getSelection().toString()) return;
399
+ else {router.push({
400
+ name: 'resource-show',
401
+ params: {
402
+ resourceId: props.resource.resourceId,
403
+ primaryKey: row._primaryKeyValue,
404
+ },
405
+ })}
406
+ }
407
+
408
+
409
+
410
+
411
+
412
+
413
+
414
+
415
+
388
416
  async function deleteRecord(row) {
389
417
  const data = await window.adminforth.confirm({
390
418
  message: 'Are you sure you want to delete this item?',