Skip to content

Commit 214a4cb

Browse files
committed
fix: add composite pk support
1 parent 184bf0d commit 214a4cb

4 files changed

Lines changed: 72 additions & 47 deletions

File tree

‎custom/RelatedLogsLink.vue‎

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import { computed } from 'vue';
2020
import { useRoute } from 'vue-router';
2121
import { IconClockSolid } from '@iconify-prerendered/vue-flowbite';
22+
import { encodeRecordId } from '@/utils/recordId';
2223
import { useRouter } from 'vue-router';
2324
2425
const router = useRouter();
@@ -50,10 +51,21 @@ const to = computed(() => {
5051
if (!resourceColumns) return null;
5152
5253
const pkName = props.meta?.pkName
54+
const pkNames = props.meta?.pkNames?.length ? props.meta.pkNames : [pkName];
5355
5456
const isShowPage = route.name === 'resource-show' || route.name === 'resource-edit';
5557
56-
let recordId = props.record?.[pkName];
58+
// for composite primary key record id is glued from all key columns, so build it the same way as backend does
59+
const pkResource = props.resource?.columns?.some((c: any) => c.primaryKey)
60+
? props.resource
61+
: { columns: pkNames.map((name: string) => ({ name, primaryKey: true })) };
62+
63+
let recordId: any = undefined;
64+
try {
65+
recordId = props.record ? encodeRecordId(pkResource as any, props.record) : undefined;
66+
} catch (e) {
67+
// record has no values of all key columns, fall back to record id from route below
68+
}
5769
5870
if (!recordId && isShowPage) {
5971
recordId = route.params.primaryKey || route.params.id;

‎index.ts‎

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import type {
77
import dayjs from 'dayjs'
88
import utc from 'dayjs/plugin/utc.js';
99

10-
import { AdminForthPlugin, AllowedActionsEnum, AdminForthSortDirections, AdminForthDataTypes, HttpExtra, ActionCheckSource, Filters, afLogger, } from "adminforth";
10+
import { AdminForthPlugin, AllowedActionsEnum, AdminForthSortDirections, AdminForthDataTypes, HttpExtra, ActionCheckSource, Filters, afLogger, encodeRecordId, isCompositePrimaryKey, primaryKeyColumnNames, } from "adminforth";
1111
import { PluginOptions } from "./types.js";
1212

1313
dayjs.extend(utc);
@@ -95,8 +95,8 @@ export default class AuditLogPlugin extends AdminForthPlugin {
9595
return { ok: true };
9696
}
9797

98-
const recordIdFieldName = resource.columns.find((c) => c.primaryKey === true)?.name;
99-
const recordId = data?.[recordIdFieldName] || oldRecord?.[recordIdFieldName];
98+
// record id is built from all primary key columns, so resources with composite primary key are supported
99+
const recordId = encodeRecordId(resource, { ...(oldRecord || {}), ...(data || {}) });
100100
const connector = this.adminforth.connectors[resource.dataSource];
101101

102102
const newRecord = action == AllowedActionsEnum.delete ? {} : (await connector.getRecordByPrimaryKey(resource, recordId)) || {};
@@ -266,6 +266,8 @@ export default class AuditLogPlugin extends AdminForthPlugin {
266266
auditLogResourceId: this.auditLogResource,
267267
resourceColumns: this.options.resourceColumns,
268268
pkName: resource.columns.find((c) => c.primaryKey)?.name || 'id',
269+
// all primary key columns, so component can build record id of composite primary key resource
270+
pkNames: primaryKeyColumnNames(resource),
269271
title: 'Edit History'
270272
}
271273
}
@@ -331,6 +333,8 @@ export default class AuditLogPlugin extends AdminForthPlugin {
331333
auditLogResourceId: this.auditLogResource,
332334
resourceColumns: this.options.resourceColumns,
333335
pkName: resource.columns.find((c) => c.primaryKey)?.name || 'id',
336+
// all primary key columns, so component can build record id of composite primary key resource
337+
pkNames: primaryKeyColumnNames(resource),
334338
title: 'Edit History'
335339
}
336340
});
@@ -353,6 +357,12 @@ export default class AuditLogPlugin extends AdminForthPlugin {
353357
const recordIdColumn = resourceConfig.columns.find((c) => c.name === this.options.resourceColumns.resourceRecordIdColumnName);
354358
if (!recordIdColumn.foreignResource) {
355359
for (const resource of existingResources) {
360+
// core does not support foreignResource pointing to resource with composite primary key yet,
361+
// so such resources are still logged, but their record id is not clickable
362+
const targetResource = this.adminforth.config.resources.find((r) => r.resourceId === resource.value);
363+
if (targetResource && isCompositePrimaryKey(targetResource)) {
364+
continue;
365+
}
356366
if(!recordIdColumn.foreignResource?.polymorphicResources) {
357367
recordIdColumn.foreignResource = {
358368
polymorphicResources: [],

‎package.json‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
"build": "tsc && rsync -av --exclude 'node_modules' custom dist/"
3535
},
3636
"peerDependencies": {
37-
"adminforth": "^3.7.1"
37+
"adminforth": "^3.20.0"
3838
},
3939
"release": {
4040
"plugins": [
@@ -63,7 +63,7 @@
6363
},
6464
"devDependencies": {
6565
"@types/node": "^22.10.7",
66-
"adminforth": "^3.7.1",
66+
"adminforth": "^3.20.0",
6767
"semantic-release": "^24.2.1",
6868
"semantic-release-slack-bot": "^4.0.2",
6969
"typescript": "^5.7.3"

‎pnpm-lock.yaml‎

Lines changed: 44 additions & 41 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)