adminforth 1.1.67 → 1.1.68

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.
@@ -34,8 +34,8 @@ class MongoConnector implements AdminForthDataSourceConnector {
34
34
  };
35
35
 
36
36
  SortDirectionsMap = {
37
- [AdminForthSortDirections.ASC]: 1,
38
- [AdminForthSortDirections.DESC]: -1,
37
+ [AdminForthSortDirections.asc]: 1,
38
+ [AdminForthSortDirections.desc]: -1,
39
39
  };
40
40
 
41
41
  async discoverFields(resource) {
@@ -68,13 +68,13 @@ class MongoConnector implements AdminForthDataSourceConnector {
68
68
  if (!value) {
69
69
  return null;
70
70
  }
71
- return dayjs.unix(value).toISOString();
71
+ return dayjs(Date.parse(value)).toISOString();
72
72
 
73
73
  } else if (field.type == AdminForthDataTypes.DATE) {
74
74
  if (!value) {
75
75
  return null;
76
76
  }
77
- return dayjs(value).toISOString().split('T')[0];
77
+ return dayjs(Date.parse(value)).toISOString().split('T')[0];
78
78
 
79
79
  } else if (field.type == AdminForthDataTypes.BOOLEAN) {
80
80
  return !!value;
@@ -37,8 +37,8 @@ class PostgresConnector implements AdminForthDataSourceConnector {
37
37
  };
38
38
 
39
39
  SortDirectionsMap = {
40
- [AdminForthSortDirections.ASC]: 'ASC',
41
- [AdminForthSortDirections.DESC]: 'DESC',
40
+ [AdminForthSortDirections.asc]: 'ASC',
41
+ [AdminForthSortDirections.desc]: 'DESC',
42
42
  };
43
43
 
44
44
  async discoverFields(resource) {
@@ -141,8 +141,8 @@ class SQLiteConnector implements AdminForthDataSourceConnector {
141
141
  };
142
142
 
143
143
  SortDirectionsMap = {
144
- [AdminForthSortDirections.ASC]: 'ASC',
145
- [AdminForthSortDirections.DESC]: 'DESC',
144
+ [AdminForthSortDirections.asc]: 'ASC',
145
+ [AdminForthSortDirections.desc]: 'DESC',
146
146
  };
147
147
 
148
148
 
@@ -25,8 +25,8 @@ class MongoConnector {
25
25
  [AdminForthFilterOperators.NIN]: (value) => ({ $nin: value }),
26
26
  };
27
27
  this.SortDirectionsMap = {
28
- [AdminForthSortDirections.ASC]: 1,
29
- [AdminForthSortDirections.DESC]: -1,
28
+ [AdminForthSortDirections.asc]: 1,
29
+ [AdminForthSortDirections.desc]: -1,
30
30
  };
31
31
  this.db = new MongoClient(url);
32
32
  (() => __awaiter(this, void 0, void 0, function* () {
@@ -71,13 +71,13 @@ class MongoConnector {
71
71
  if (!value) {
72
72
  return null;
73
73
  }
74
- return dayjs.unix(value).toISOString();
74
+ return dayjs(Date.parse(value)).toISOString();
75
75
  }
76
76
  else if (field.type == AdminForthDataTypes.DATE) {
77
77
  if (!value) {
78
78
  return null;
79
79
  }
80
- return dayjs(value).toISOString().split('T')[0];
80
+ return dayjs(Date.parse(value)).toISOString().split('T')[0];
81
81
  }
82
82
  else if (field.type == AdminForthDataTypes.BOOLEAN) {
83
83
  return !!value;
@@ -26,8 +26,8 @@ class PostgresConnector {
26
26
  [AdminForthFilterOperators.NIN]: 'NOT IN',
27
27
  };
28
28
  this.SortDirectionsMap = {
29
- [AdminForthSortDirections.ASC]: 'ASC',
30
- [AdminForthSortDirections.DESC]: 'DESC',
29
+ [AdminForthSortDirections.asc]: 'ASC',
30
+ [AdminForthSortDirections.desc]: 'DESC',
31
31
  };
32
32
  this.db = new Client({
33
33
  connectionString: url
@@ -26,8 +26,8 @@ class SQLiteConnector {
26
26
  [AdminForthFilterOperators.NIN]: 'NOT IN',
27
27
  };
28
28
  this.SortDirectionsMap = {
29
- [AdminForthSortDirections.ASC]: 'ASC',
30
- [AdminForthSortDirections.DESC]: 'DESC',
29
+ [AdminForthSortDirections.asc]: 'ASC',
30
+ [AdminForthSortDirections.desc]: 'DESC',
31
31
  };
32
32
  this.db = betterSqlite3(url.replace('sqlite://', ''));
33
33
  }
@@ -7,6 +7,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
7
7
  step((generator = generator.apply(thisArg, _arguments || [])).next());
8
8
  });
9
9
  };
10
+ import { AllowedActionsEnum, AdminForthSortDirections } from "../../types/AdminForthConfig.js";
10
11
  import AdminForthPlugin from "../base.js";
11
12
  class AuditLogPlugin extends AdminForthPlugin {
12
13
  constructor(options) {
@@ -16,15 +17,41 @@ class AuditLogPlugin extends AdminForthPlugin {
16
17
  const recordIdFieldName = (_a = resource.columns.find((c) => c.primaryKey === true)) === null || _a === void 0 ? void 0 : _a.name;
17
18
  const recordId = (data === null || data === void 0 ? void 0 : data[recordIdFieldName]) || (oldRecord === null || oldRecord === void 0 ? void 0 : oldRecord[recordIdFieldName]);
18
19
  const connector = this.adminforth.connectors[resource.dataSource];
19
- const newRecord = yield connector.getRecordByPrimaryKey(resource, recordId);
20
- let newData = {
21
- 'oldRecord': oldRecord || {},
22
- 'newRecord': newRecord
23
- };
20
+ const newRecord = action == AllowedActionsEnum.delete ? {} : (yield connector.getRecordByPrimaryKey(resource, recordId)) || {};
21
+ if (action !== AllowedActionsEnum.delete) {
22
+ oldRecord = oldRecord ? JSON.parse(JSON.stringify(oldRecord)) : {};
23
+ }
24
+ else {
25
+ oldRecord = data;
26
+ }
27
+ if (action !== AllowedActionsEnum.delete) {
28
+ const columnsNamesList = resource.columns.map((c) => c.name);
29
+ columnsNamesList.forEach((key) => {
30
+ if (JSON.stringify(oldRecord[key]) == JSON.stringify(newRecord[key])) {
31
+ delete oldRecord[key];
32
+ delete newRecord[key];
33
+ }
34
+ });
35
+ }
36
+ const backendOnlyColumns = resource.columns.filter((c) => c.backendOnly);
37
+ backendOnlyColumns.forEach((c) => {
38
+ if (JSON.stringify(oldRecord[c.name]) != JSON.stringify(newRecord[c.name])) {
39
+ if (action !== AllowedActionsEnum.delete) {
40
+ newRecord[c.name] = '<hidden value after>';
41
+ }
42
+ if (action !== AllowedActionsEnum.create) {
43
+ oldRecord[c.name] = '<hidden value before>';
44
+ }
45
+ }
46
+ else {
47
+ delete oldRecord[c.name];
48
+ delete newRecord[c.name];
49
+ }
50
+ });
24
51
  const record = {
25
52
  [this.options.resourceColumns.resourceIdColumnName]: resource.resourceId,
26
53
  [this.options.resourceColumns.resourceActionColumnName]: action,
27
- [this.options.resourceColumns.resourceDataColumnName]: newData,
54
+ [this.options.resourceColumns.resourceDataColumnName]: { 'oldRecord': oldRecord || {}, 'newRecord': newRecord },
28
55
  [this.options.resourceColumns.resourceUserIdColumnName]: user.pk,
29
56
  [this.options.resourceColumns.resourceRecordIdColumnName]: recordId,
30
57
  [this.options.resourceColumns.resourceCreatedColumnName]: new Date()
@@ -53,18 +80,23 @@ class AuditLogPlugin extends AdminForthPlugin {
53
80
  // type: AdminForthDataTypes.STRING
54
81
  };
55
82
  }
83
+ diffColumn.showIn = ['show'];
56
84
  diffColumn.components = {
57
85
  show: {
58
86
  file: this.componentPath('AuditLogView.vue'),
59
87
  meta: Object.assign(Object.assign({}, this.options), { pluginInstanceId: this.pluginInstanceId })
60
88
  }
61
89
  };
90
+ resource.options.defaultSort = {
91
+ columnName: this.options.resourceColumns.resourceCreatedColumnName,
92
+ direction: AdminForthSortDirections.desc
93
+ };
62
94
  return;
63
95
  }
64
96
  const defaultHooks = {
65
97
  create: { afterSave: [] },
66
98
  edit: { afterSave: [] },
67
- delete: { afterSave: [] }
99
+ delete: { beforeSave: [] }
68
100
  };
69
101
  if (!resource.hooks) {
70
102
  resource.hooks = defaultHooks;
@@ -73,10 +105,11 @@ class AuditLogPlugin extends AdminForthPlugin {
73
105
  resource.hooks = Object.assign(Object.assign({}, defaultHooks), resource.hooks);
74
106
  }
75
107
  Object.keys(resource.hooks).forEach((hook) => {
76
- if (!Array.isArray(resource.hooks[hook].afterSave)) {
77
- resource.hooks[hook].afterSave = [resource.hooks[hook].afterSave];
108
+ const hookToUse = hook == AllowedActionsEnum.delete ? 'beforeSave' : 'afterSave';
109
+ if (!Array.isArray(resource.hooks[hook][hookToUse])) {
110
+ resource.hooks[hook][hookToUse] = [resource.hooks[hook][hookToUse]];
78
111
  }
79
- resource.hooks[hook].afterSave.push((_a) => __awaiter(this, [_a], void 0, function* ({ resource, record, adminUser, oldRecord }) {
112
+ resource.hooks[hook][hookToUse].push((_a) => __awaiter(this, [_a], void 0, function* ({ resource, record, adminUser, oldRecord }) {
80
113
  return yield this.createLogRecord(resource, hook, record, adminUser, oldRecord);
81
114
  }));
82
115
  });
@@ -252,7 +252,8 @@ const props = defineProps([
252
252
  'rows',
253
253
  'totalRows',
254
254
  'pageSize',
255
- 'checkboxes'
255
+ 'checkboxes',
256
+ 'sort'
256
257
  ])
257
258
 
258
259
  // emits, update page
@@ -288,6 +289,10 @@ watch(() => props.checkboxes, (newCheckboxes) => {
288
289
  checkboxesInternal.value = newCheckboxes;
289
290
  });
290
291
 
292
+ watch(() => props.sort, (newSort) => {
293
+ sort.value = newSort;
294
+ });
295
+
291
296
  function addToCheckedValues(id) {
292
297
  if (checkboxesInternal.value.includes(id)) {
293
298
  checkboxesInternal.value = checkboxesInternal.value.filter((item) => item !== id);
@@ -89,6 +89,7 @@
89
89
  @update:sort="sort = $event"
90
90
  @update:checkboxes="checkboxes = $event"
91
91
  @update:records="getList"
92
+ :sort="sort"
92
93
  :pageSize="pageSize"
93
94
  :totalRows="totalRows"
94
95
  :checkboxes="checkboxes"
@@ -229,6 +230,15 @@ async function init() {
229
230
  resourceId: route.params.resourceId
230
231
  });
231
232
 
233
+ if (coreStore.resource.options?.defaultSort) {
234
+ sort.value = [{
235
+ field: coreStore.resource.options.defaultSort.columnName,
236
+ direction: coreStore.resource.options.defaultSort.direction
237
+ }];
238
+ } else {
239
+ sort.value = [];
240
+ }
241
+
232
242
  await getList();
233
243
  columnsMinMax.value = await callAdminForthApi({
234
244
  path: '/get_min_max_for_columns',
@@ -250,7 +260,6 @@ onMounted(async () => {
250
260
  watch(() => route.params.resourceId, async () => {
251
261
  filtersStore.setFilters([]);
252
262
  checkboxes.value = [];
253
- sort.value = [];
254
263
  await init();
255
264
  });
256
265
 
@@ -99,7 +99,7 @@ export var AdminForthFilterOperators;
99
99
  ;
100
100
  export var AdminForthSortDirections;
101
101
  (function (AdminForthSortDirections) {
102
- AdminForthSortDirections["ASC"] = "asc";
103
- AdminForthSortDirections["DESC"] = "desc";
102
+ AdminForthSortDirections["asc"] = "asc";
103
+ AdminForthSortDirections["desc"] = "desc";
104
104
  })(AdminForthSortDirections || (AdminForthSortDirections = {}));
105
105
  ;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "adminforth",
3
- "version": "1.1.67",
3
+ "version": "1.1.68",
4
4
  "description": "OpenSource Vue3 powered forth-generation admin panel",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -6,7 +6,8 @@ import {
6
6
  AdminUser,
7
7
  AdminForthDataTypes,
8
8
  AdminForthResourcePages,
9
- AdminForthFilterOperators
9
+ AdminForthFilterOperators,
10
+ AdminForthSortDirections
10
11
  } from "../../types/AdminForthConfig.js";
11
12
  import AdminForthPlugin from "../base.js";
12
13
  import { PluginOptions } from "./types.js";
@@ -30,16 +31,43 @@ export default class AuditLogPlugin extends AdminForthPlugin {
30
31
  const recordIdFieldName = resource.columns.find((c) => c.primaryKey === true)?.name;
31
32
  const recordId = data?.[recordIdFieldName] || oldRecord?.[recordIdFieldName];
32
33
  const connector = this.adminforth.connectors[resource.dataSource];
33
- const newRecord = await connector.getRecordByPrimaryKey(resource, recordId);
34
34
 
35
- let newData = {
36
- 'oldRecord': oldRecord || {},
37
- 'newRecord': newRecord
35
+ const newRecord = action == AllowedActionsEnum.delete ? {} : (await connector.getRecordByPrimaryKey(resource, recordId)) || {};
36
+ if (action !== AllowedActionsEnum.delete) {
37
+ oldRecord = oldRecord ? JSON.parse(JSON.stringify(oldRecord)) : {};
38
+ } else {
39
+ oldRecord = data
38
40
  }
41
+
42
+ if (action !== AllowedActionsEnum.delete) {
43
+ const columnsNamesList = resource.columns.map((c) => c.name);
44
+ columnsNamesList.forEach((key) => {
45
+ if (JSON.stringify(oldRecord[key]) == JSON.stringify(newRecord[key])) {
46
+ delete oldRecord[key];
47
+ delete newRecord[key];
48
+ }
49
+ });
50
+ }
51
+
52
+ const backendOnlyColumns = resource.columns.filter((c) => c.backendOnly);
53
+ backendOnlyColumns.forEach((c) => {
54
+ if (JSON.stringify(oldRecord[c.name]) != JSON.stringify(newRecord[c.name])) {
55
+ if (action !== AllowedActionsEnum.delete) {
56
+ newRecord[c.name] = '<hidden value after>'
57
+ }
58
+ if (action !== AllowedActionsEnum.create) {
59
+ oldRecord[c.name] = '<hidden value before>'
60
+ }
61
+ } else {
62
+ delete oldRecord[c.name];
63
+ delete newRecord[c.name];
64
+ }
65
+ });
66
+
39
67
  const record = {
40
68
  [this.options.resourceColumns.resourceIdColumnName]: resource.resourceId,
41
69
  [this.options.resourceColumns.resourceActionColumnName]: action,
42
- [this.options.resourceColumns.resourceDataColumnName]: newData,
70
+ [this.options.resourceColumns.resourceDataColumnName]: { 'oldRecord': oldRecord || {}, 'newRecord': newRecord },
43
71
  [this.options.resourceColumns.resourceUserIdColumnName]: user.pk,
44
72
  [this.options.resourceColumns.resourceRecordIdColumnName]: recordId,
45
73
  [this.options.resourceColumns.resourceCreatedColumnName]: new Date()
@@ -68,7 +96,8 @@ export default class AuditLogPlugin extends AdminForthPlugin {
68
96
  // type: AdminForthDataTypes.STRING
69
97
  }
70
98
  }
71
-
99
+
100
+ diffColumn.showIn = ['show']
72
101
  diffColumn.components = {
73
102
  show: {
74
103
  file: this.componentPath('AuditLogView.vue'),
@@ -78,13 +107,17 @@ export default class AuditLogPlugin extends AdminForthPlugin {
78
107
  }
79
108
  }
80
109
  }
110
+ resource.options.defaultSort = {
111
+ columnName: this.options.resourceColumns.resourceCreatedColumnName,
112
+ direction: AdminForthSortDirections.desc
113
+ }
81
114
  return;
82
115
  }
83
116
 
84
117
  const defaultHooks = {
85
118
  create: { afterSave: [] },
86
119
  edit: { afterSave: [] },
87
- delete: { afterSave: [] }
120
+ delete: { beforeSave: [] }
88
121
  }
89
122
 
90
123
  if ( !resource.hooks ) {
@@ -94,10 +127,11 @@ export default class AuditLogPlugin extends AdminForthPlugin {
94
127
  }
95
128
 
96
129
  Object.keys(resource.hooks).forEach((hook) => {
97
- if(!Array.isArray(resource.hooks[hook].afterSave)){
98
- resource.hooks[hook].afterSave = [resource.hooks[hook].afterSave]
130
+ const hookToUse = hook == AllowedActionsEnum.delete ? 'beforeSave' : 'afterSave';
131
+ if(!Array.isArray(resource.hooks[hook][hookToUse])){
132
+ resource.hooks[hook][hookToUse] = [resource.hooks[hook][hookToUse]]
99
133
  }
100
- resource.hooks[hook].afterSave.push(async ({resource, record, adminUser, oldRecord}) => {
134
+ resource.hooks[hook][hookToUse].push(async ({resource, record, adminUser, oldRecord}) => {
101
135
  return await this.createLogRecord(resource, hook as AllowedActionsEnum, record, adminUser, oldRecord)
102
136
  })
103
137
  })
@@ -252,7 +252,8 @@ const props = defineProps([
252
252
  'rows',
253
253
  'totalRows',
254
254
  'pageSize',
255
- 'checkboxes'
255
+ 'checkboxes',
256
+ 'sort'
256
257
  ])
257
258
 
258
259
  // emits, update page
@@ -288,6 +289,10 @@ watch(() => props.checkboxes, (newCheckboxes) => {
288
289
  checkboxesInternal.value = newCheckboxes;
289
290
  });
290
291
 
292
+ watch(() => props.sort, (newSort) => {
293
+ sort.value = newSort;
294
+ });
295
+
291
296
  function addToCheckedValues(id) {
292
297
  if (checkboxesInternal.value.includes(id)) {
293
298
  checkboxesInternal.value = checkboxesInternal.value.filter((item) => item !== id);
@@ -89,6 +89,7 @@
89
89
  @update:sort="sort = $event"
90
90
  @update:checkboxes="checkboxes = $event"
91
91
  @update:records="getList"
92
+ :sort="sort"
92
93
  :pageSize="pageSize"
93
94
  :totalRows="totalRows"
94
95
  :checkboxes="checkboxes"
@@ -229,6 +230,15 @@ async function init() {
229
230
  resourceId: route.params.resourceId
230
231
  });
231
232
 
233
+ if (coreStore.resource.options?.defaultSort) {
234
+ sort.value = [{
235
+ field: coreStore.resource.options.defaultSort.columnName,
236
+ direction: coreStore.resource.options.defaultSort.direction
237
+ }];
238
+ } else {
239
+ sort.value = [];
240
+ }
241
+
232
242
  await getList();
233
243
  columnsMinMax.value = await callAdminForthApi({
234
244
  path: '/get_min_max_for_columns',
@@ -250,7 +260,6 @@ onMounted(async () => {
250
260
  watch(() => route.params.resourceId, async () => {
251
261
  filtersStore.setFilters([]);
252
262
  checkboxes.value = [];
253
- sort.value = [];
254
263
  await init();
255
264
  });
256
265
 
@@ -545,6 +545,10 @@ export type AdminForthResource = {
545
545
  },
546
546
  },
547
547
  options?: {
548
+ defaultSort?: {
549
+ columnName: string,
550
+ direction: AdminForthSortDirections | string,
551
+ }
548
552
  bulkActions?: Array<{
549
553
  id?: string,
550
554
  label: string,
@@ -1073,8 +1077,8 @@ export enum AdminForthFilterOperators {
1073
1077
  };
1074
1078
 
1075
1079
  export enum AdminForthSortDirections {
1076
- ASC = 'asc',
1077
- DESC = 'desc',
1080
+ asc = 'asc',
1081
+ desc = 'desc',
1078
1082
  };
1079
1083
 
1080
1084