@@ -597,4 +597,150 @@ handler: async (a) => {
597597 const resp = await this .options .adapter .complete (content , [' .' ], this .options .expert ?.maxTokens || 50 );
598598 ...
599599}
600- ` ` `
600+ ` ` `
601+ ## Providing a frontend API
602+ If a plugin needs to provide an external frontend API so user code or other plugins can interact with it, you can create a .ts file or a global Pinia store (if you want to have some global variables or use plugin modals) and then re-use it in your frontend logic. For example:
603+
604+ 1) Create new ` ./ custom / useChatGptApi .ts ` and ` ./ custom / customModal ` files
605+ ` ` ` text
606+ af - plugin - chatgpt /
607+ ├── custom
608+ │ └── tsconfig .json
609+ | └── completionInput .vue
610+ // diff-add
611+ | └── useChatGptApi .ts
612+ // diff-add
613+ | └── customModal .vue
614+ ├── index .ts
615+ ├── package .json
616+ ├── tsconfig .json
617+ └── types .ts
618+ ` ` `
619+
620+ 2) Write your custom logic:
621+
622+ ` ` ` ts title= " ./custom/useChatGptApi.ts"
623+ import { ref } from ' vue' ;
624+ import { callAdminForthApi } from ' @/utils' ;
625+ import { defineStore } from ' pinia'
626+
627+ export const useChatGptApi = defineStore (' chatGptApi' , () => {
628+ const isCustomModalOpened = ref (false );
629+ const customModalData = ref ({})
630+
631+ function openCustomModal(modalData ) {
632+ customModalData .value = modalData ;
633+ isCustomModalOpened .value = true ;
634+ }
635+
636+ function closeCustomModal() {
637+ isCustomModalOpened .value = false ;
638+ }
639+
640+ async function doComplete(pluginInstanceId , record , columnName , textBeforeCursor ) {
641+ const res = await callAdminForthApi ({
642+ path: ` /plugin/${pluginInstanceId }/doComplete ` ,
643+ method: ' POST' ,
644+ body: {
645+ record: { ... record , [columnName ]: textBeforeCursor },
646+ },
647+ });
648+
649+ return res .completion ;
650+ }
651+
652+ return {
653+ isCustomModalOpened ,
654+ customModalData ,
655+ openCustomModal ,
656+ closeCustomModal ,
657+ doComplete
658+ }
659+ ` ` `
660+
661+ 3) If you want your plugin to have its own modal API, then first of all you'll need to inject this component somewhere so you can open it:
662+
663+ ` ` ` ts title = " ./index.ts"
664+
665+ async modifyResourceConfig (adminforth : IAdminForth , resourceConfig : AdminForthResource ) {
666+
667+ ...
668+
669+ // Global API injection: exposes openCustomModal(...) to open chatGptModal from anywhere
670+ (adminforth .config .customization .globalInjections .header ).push ({
671+ file: this .componentPath (' customModal.vue' ),
672+ meta: {
673+ pluginInstanceId: this .pluginInstanceId ,
674+ }
675+ });
676+
677+ ...
678+
679+ }
680+
681+ ` ` `
682+
683+
684+ and:
685+
686+ ` ` ` html title = " customModal.vue"
687+ <template >
688+ < ! -- Hidden component that registers a global function to open job info modal -->
689+ <Modal
690+ ref = " dialogRef"
691+ removeFromDomOnClose
692+ class = " p-4"
693+ : beforeCloseFunction = " () => { chatGpt.closeCustomModal(); }"
694+ >
695+ <div >
696+ *** Modal content***
697+ {{ chatGpt .customModalData }}
698+ < / div
699+ < / Modal >
700+ < / template >
701+
702+ < script setup lang = " ts" >
703+ import { ref , onMounted , onBeforeUnmount , watch } from ' vue' ;
704+ import { Modal } from ' @/afcl' ;
705+ import { useChatGptApi } from ' ./useChatGptApi' ;
706+
707+ const chatGpt = useChatGptApi ();
708+ const dialogRef = ref <any >(null );
709+
710+ const props = defineProps <{
711+ meta: {
712+ pluginInstanceId: string ;
713+ }
714+ }>();
715+
716+ watch (() => chatGpt .isCustomModalOpened , (newVal ) => {
717+ if (newVal ) {
718+ dialogRef .value ?.open ?.();
719+ } else {
720+ dialogRef .value ?.close ?.();
721+ }
722+ });
723+ < / script >
724+
725+
726+ ` ` `
727+
728+ 4) Re-use this api in your component:
729+
730+ ` ` ` html
731+ <template >
732+ ...
733+ < / template >
734+
735+ < script setup >
736+ // diff-add
737+ import { useChatGptApi } from ' @/custom/plugins/ChatGptPlugin/useChatGptApi' ;
738+ ...
739+ < / script >
740+ ` ` `
741+
742+ ### How to get the plugin file path from a custom component
743+
744+ ` ChatGptPlugin ` is the class name that is defined inside ` index .ts ` .
745+ So if we want to access plugin files from a custom component, we should use the path:
746+ > ` @/ custom / plugins /* Plugin class name*/ * File name * `
0 commit comments