diff --git a/custom/InlineList.vue b/custom/InlineList.vue index 2de8e79..b4c2b93 100644 --- a/custom/InlineList.vue +++ b/custom/InlineList.vue @@ -364,9 +364,11 @@ onMounted( async () => { } const foreighResourceId = props.meta.foreignResourceId; listResource.value = (await callAdminForthApi({ - path: `/plugin/${props.meta.pluginInstanceId}/get_resource`, + path: `/get_resource`, method: 'POST', - body: {}, + body: { + resourceId: foreighResourceId, + }, })).resource; if (listResource.value?.options?.allowedActions?.create && listResourceRefColumn.value && !listResourceRefColumn.value.showIn.create) { diff --git a/index.ts b/index.ts index f6197c6..6a873a0 100644 --- a/index.ts +++ b/index.ts @@ -11,9 +11,12 @@ import { interpretResource, ActionCheckSource } from "adminforth"; export default class ForeignInlineListPlugin extends AdminForthPlugin { foreignResource: AdminForthResource; + copyOfForeignResource: AdminForthResource; options: PluginOptions; adminforth: IAdminForth; + activationOrder: number = -10000000; + constructor(options: PluginOptions) { super(options, import.meta.url); this.options = options; @@ -24,81 +27,6 @@ export default class ForeignInlineListPlugin extends AdminForthPlugin { } setupEndpoints(server: IHttpServer) { - process.env.HEAVY_DEBUG && console.log(`🪲 ForeignInlineListPlugin.setupEndpoints, registering: '/plugin/${this.pluginInstanceId}/get_resource'`); - server.endpoint({ - method: 'POST', - path: `/plugin/${this.pluginInstanceId}/get_resource`, - handler: async ({ body, adminUser }) => { - const resource = this.adminforth.config.resources.find((res) => this.options.foreignResourceId === res.resourceId); - if (!resource) { - return { error: `Resource ${this.options.foreignResourceId} not found` }; - } - // exclude "plugins" key - const resourceCopy = clone({ ...resource, plugins: undefined }); - - if (this.options.modifyTableResourceConfig) { - this.options.modifyTableResourceConfig(resourceCopy); - } - - const { allowedActions } = await interpretResource(adminUser, resourceCopy, {}, ActionCheckSource.DisplayButtons, this.adminforth); - - return { - resource: { - ...resourceCopy, - options: { - ...resourceCopy.options, - allowedActions, - }, - } - }; - } - }); - server.endpoint({ - method: 'POST', - path: `/plugin/${this.pluginInstanceId}/start_bulk_action`, - handler: async ({ body, adminUser, tr }) => { - const { resourceId, actionId, recordIds } = body; - const resource = this.adminforth.config.resources.find((res) => res.resourceId == resourceId); - if (!resource) { - return { error: await tr(`Resource {resourceId} not found`, 'errors', { resourceId }) }; - } - - const resourceCopy = JSON.parse(JSON.stringify({ ...resource, plugins: undefined })); - - - if (this.options.modifyTableResourceConfig) { - this.options.modifyTableResourceConfig(resourceCopy); - } - - const { allowedActions } = await interpretResource( - adminUser, - resourceCopy, - { requestBody: body }, - ActionCheckSource.BulkActionRequest, - this.adminforth - ); - - const action = resourceCopy.options.bulkActions.find((act) => act.id == actionId); - if (!action) { - return { error: await tr(`Action {actionId} not found`, 'errors', { actionId }) }; - } - - if (action.allowed) { - const execAllowed = await action.allowed({ adminUser, resourceCopy, selectedIds: recordIds, allowedActions }); - if (!execAllowed) { - return { error: await tr(`Action "{actionId}" not allowed`, 'errors', { actionId: action.label }) }; - } - } - const response = await action.action({selectedIds: recordIds, adminUser, resourceCopy, tr}); - - return { - actionId, - recordIds, - resourceId, - ...response - } - } - }) server.endpoint({ method: 'POST', path: `/plugin/${this.pluginInstanceId}/get_default_filters`, @@ -119,19 +47,19 @@ export default class ForeignInlineListPlugin extends AdminForthPlugin { }) } - async modifyResourceConfig(adminforth: IAdminForth, resourceConfig: AdminForthResource) { + async modifyResourceConfig(adminforth: IAdminForth, resourceConfig: AdminForthResource, allPluginInstances?: {pi: AdminForthPlugin, resource: AdminForthResource}[]) { super.modifyResourceConfig(adminforth, resourceConfig); - this.adminforth = adminforth; - // get resource with foreignResourceId + this.adminforth = adminforth; this.foreignResource = adminforth.config.resources.find((resource) => resource.resourceId === this.options.foreignResourceId); + if (!this.foreignResource) { const similar = suggestIfTypo(adminforth.config.resources.map((res) => res.resourceId), this.options.foreignResourceId); throw new Error(`ForeignInlineListPlugin: Resource with ID "${this.options.foreignResourceId}" not found. ${similar ? `Did you mean "${similar}"?` : ''}`); } + const idOfNewCopy = `${this.foreignResource.resourceId}_inline_list__from_${this.resourceConfig.resourceId}__`; - const defaultSort = this.foreignResource.options?.defaultSort; const newColumn = { name: `foreignInlineList_${this.foreignResource.resourceId}`, label: 'Foreign Inline List', @@ -151,15 +79,7 @@ export default class ForeignInlineListPlugin extends AdminForthPlugin { ...this.options, pluginInstanceId: this.pluginInstanceId, disableForeignListResourceRefColumn: this.options.disableForeignListResourceRefColumn, - ...(defaultSort - ? { - defaultSort: { - field: defaultSort.columnName, - direction: defaultSort.direction, - } - } - : {} - ) + foreignResourceId: idOfNewCopy } } }, @@ -202,5 +122,72 @@ export default class ForeignInlineListPlugin extends AdminForthPlugin { } else { resourceConfig.columns.push(newColumn); } + + // get resource with foreignResourceId + this.copyOfForeignResource = clone({ ...this.foreignResource, plugins: [] }); + + // if we install on plugin which is already a copy, adjust foreignResource references + if (this.resourceConfig.resourceId.includes('_inline_list__from_')) { + const originalResourceIdPart = this.resourceConfig.resourceId.split('_inline_list__from_')[0]; + // find column in copied resource which is foreignResource.resourceId equal to originalResourceIdPart + // and change it to point to this.resourceConfig.resourceId + const foreignRefColumn = this.copyOfForeignResource.columns.find(col => col.foreignResource?.resourceId === originalResourceIdPart); + if (foreignRefColumn) { + foreignRefColumn.foreignResource.resourceId = this.resourceConfig.resourceId; + } + } + + // if foreignInlineList_ column already created, remove it + this.copyOfForeignResource.columns = this.copyOfForeignResource.columns.filter(col => !col.name.startsWith('foreignInlineList_')); + // we should not cate about modifications made by other plugins, while activationOrder of this plugin is very low (negative) + + this.copyOfForeignResource.resourceId = idOfNewCopy; + adminforth.config.resources.push(this.copyOfForeignResource); + + if (this.options.modifyTableResourceConfig) { + this.options.modifyTableResourceConfig(this.copyOfForeignResource); + } + + let shouldRefColumnBeUpdated = false; + // now we need to create a copy of all plugins of foreignResource, + for (const plugin of this.foreignResource.plugins || []) { + const options = plugin.pluginOptions; + // call constructor + if ( plugin.constructor.name === 'ForeignInlineListPlugin' ) { + + if (plugin.pluginOptions.foreignResourceId === this.foreignResource.resourceId && !this.resourceConfig.resourceId.includes('_inline_list__from_')) { + // TODO delete copyOfForeignResource from adminforth.config.resources, because we are don't use this copy anymore + plugin.pluginOptions.foreignResourceId = idOfNewCopy; + const pluginCopy = new (plugin.constructor as any)(options); + this.copyOfForeignResource.plugins.push(pluginCopy); + const currentResourceForeignRefColumn = this.resourceConfig.columns.find(col => col.foreignResource?.resourceId === this.resourceConfig.resourceId); + if (currentResourceForeignRefColumn) { + currentResourceForeignRefColumn.foreignResource.resourceId = idOfNewCopy; + } + shouldRefColumnBeUpdated = true; + } else if (!plugin.pluginOptions.foreignResourceId.includes('_inline_list__from_')) { + const pluginCopy = new (plugin.constructor as any)(options); + this.copyOfForeignResource.plugins.push(pluginCopy); + } + } else { + const pluginCopy = new (plugin.constructor as any)(options); + this.copyOfForeignResource.plugins.push(pluginCopy); + } + } + + // activate plugins for the copyOfForeignResource + for (const plugin of this.copyOfForeignResource.plugins.sort((a, b) => a.activationOrder - b.activationOrder)) { + // if there already is a plugin with same instanceUniqueRepresentation, skip + process.env.HEAVY_DEBUG && console.log('Activating plugin for foreign inline list copy:', plugin.constructor.name); + allPluginInstances.push({pi: plugin, resource: this.copyOfForeignResource}); + } + + const currentResourceForeignRefColumnWithComponent = this.copyOfForeignResource.columns.find(col => col.name === 'foreignInlineList_' + idOfNewCopy); + if (currentResourceForeignRefColumnWithComponent && shouldRefColumnBeUpdated) { + // if we are creating a copy for resource, which is refferes to itself, we need to update foreignResourceId in component meta + //@ts-ignore + currentResourceForeignRefColumnWithComponent.components.showRow.meta.foreignResourceId = this.resourceConfig.resourceId; + } + } } \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index b34a572..1740f96 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,7 +18,7 @@ "typescript": "^5.7.3" }, "peerDependencies": { - "adminforth": "^2.13.0-next.51" + "adminforth": "^2.16.1-next.4" } }, "../..": { @@ -1076,9 +1076,9 @@ } }, "node_modules/adminforth": { - "version": "2.13.0-next.51", - "resolved": "https://registry.npmjs.org/adminforth/-/adminforth-2.13.0-next.51.tgz", - "integrity": "sha512-hNWloIvFNNEwaWAfDaUJsF3MZZBKZKAF14LHkXG6cd2wBO/kbWrvdbw1t2WK/U18/hVUJ7QlI0/e+8P8TXGcSg==", + "version": "2.16.1-next.4", + "resolved": "https://registry.npmjs.org/adminforth/-/adminforth-2.16.1-next.4.tgz", + "integrity": "sha512-1E4FElDFO/423V7uJ4zqUk7TFQnUaErqgV2UtXqsJXqqD/4LVurMC1rXDpl6Ni+bUucbnvFHpKSGaRxe6Lj8rA==", "hasInstallScript": true, "license": "ISC", "peer": true, diff --git a/package.json b/package.json index 466ec9f..344cb3c 100644 --- a/package.json +++ b/package.json @@ -57,6 +57,6 @@ "clone": "^2.1.2" }, "peerDependencies": { - "adminforth": "^2.13.0-next.51" + "adminforth": "^2.16.1-next.4" } }