From 7e2791acda2780b7d95521bab81dd532481092ff Mon Sep 17 00:00:00 2001
From: Piotr Gawron <p.gawron@atcomp.pl>
Date: Thu, 31 Oct 2024 10:27:36 +0100
Subject: [PATCH] allow to load plugin with panel

---
 CHANGELOG                                     |  1 +
 docs/plugins/plugins.md                       | 12 ++++++-----
 index.d.ts                                    |  4 +---
 src/redux/plugins/plugins.reducers.test.ts    |  8 +++++++-
 src/redux/plugins/plugins.thunks.ts           | 16 ++++++++++++---
 src/services/pluginsManager/pluginsManager.ts | 20 ++++++++++++-------
 .../pluginsManager/pluginsManager.types.ts    |  5 +++--
 src/types/models.ts                           |  2 +-
 8 files changed, 46 insertions(+), 22 deletions(-)

diff --git a/CHANGELOG b/CHANGELOG
index 6edee4e1..38c549d2 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,5 +1,6 @@
 minerva-front (19.0.0~alpha.0) stable; urgency=medium
   * Feature: support for matomo (#289)
+  * Feature: allow plugin to not have a panel (#306)
 
  -- Piotr Gawron <piotr.gawron@uni.lu>  Fri, 18 Oct 2024 13:00:00 +0200
 
diff --git a/docs/plugins/plugins.md b/docs/plugins/plugins.md
index 1636f258..6613bb03 100644
--- a/docs/plugins/plugins.md
+++ b/docs/plugins/plugins.md
@@ -11,6 +11,7 @@ Your plugin should utilize the `window.minerva.plugins.registerPlugin` method fo
   pluginName: string;
   pluginVersion: string;
   pluginUrl: string;
+  withoutPanel: boolean | undefined;
 }
 ```
 
@@ -21,6 +22,7 @@ window.minerva.plugins.registerPlugin({
   pluginName: 'Your Plugin Name',
   pluginVersion: '1.8.3',
   pluginUrl: 'https://example.com/plugins/plugin.js',
+  withoutPanel: false,
 });
 ```
 
@@ -28,17 +30,17 @@ window.minerva.plugins.registerPlugin({
 
 The `window.minerva.plugins.registerPlugin` method returns object with `element` property which is a DOM element, allowing your plugin to append its HTML content to the DOM. Use this element to create and modify the HTML structure of your plugin.
 
-```
+```javascript
 // Plugin registration
 const { element } = window.minerva.plugins.registerPlugin({
-  pluginName: "Your Plugin Name",
-  pluginVersion: "1.0.0",
-  pluginUrl: "your-plugin-url",
+  pluginName: 'Your Plugin Name',
+  pluginVersion: '1.0.0',
+  pluginUrl: 'your-plugin-url',
 });
 
 // Modify plugin's HTML structure
 const yourContent = document.createElement('div');
-yourContent.textContent = "Your Plugin Content";
+yourContent.textContent = 'Your Plugin Content';
 element.appendChild(yourContent);
 ```
 
diff --git a/index.d.ts b/index.d.ts
index a18511ed..2e109d80 100644
--- a/index.d.ts
+++ b/index.d.ts
@@ -3,15 +3,12 @@ import { fitBounds } from '@/services/pluginsManager/map/fitBounds';
 import { getOpenMapId } from '@/services/pluginsManager/map/getOpenMapId';
 import { triggerSearch } from '@/services/pluginsManager/map/triggerSearch';
 import { MinervaConfiguration } from '@/services/pluginsManager/pluginsManager';
-import { MapInstance } from '@/types/map';
 import { getModels } from '@/services/pluginsManager/map/models/getModels';
 import { openMap } from '@/services/pluginsManager/map/openMap';
 import { getCenter } from '@/services/pluginsManager/map/position/getCenter';
 import { setCenter } from '@/services/pluginsManager/map/position/setCenter';
-import { triggerSearch } from '@/services/pluginsManager/map/triggerSearch';
 import { getZoom } from '@/services/pluginsManager/map/zoom/getZoom';
 import { setZoom } from '@/services/pluginsManager/map/zoom/setZoom';
-import { MinervaConfiguration } from '@/services/pluginsManager/pluginsManager';
 import { getDisease } from '@/services/pluginsManager/project/data/getDisease';
 import { getName } from '@/services/pluginsManager/project/data/getName';
 import { getOrganism } from '@/services/pluginsManager/project/data/getOrganism';
@@ -29,6 +26,7 @@ type Plugin = {
   pluginName: string;
   pluginVersion: string;
   pluginUrl: string;
+  withoutPanel: boolean | undefined;
 };
 
 type RegisterPlugin = ({ pluginName, pluginVersion, pluginUrl }: Plugin) => {
diff --git a/src/redux/plugins/plugins.reducers.test.ts b/src/redux/plugins/plugins.reducers.test.ts
index d5a7f010..0d282876 100644
--- a/src/redux/plugins/plugins.reducers.test.ts
+++ b/src/redux/plugins/plugins.reducers.test.ts
@@ -47,13 +47,14 @@ describe('plugins reducer', () => {
         pluginUrl: pluginFixture.urls[0],
         pluginVersion: pluginFixture.version,
         extendedPluginName: pluginFixture.name,
+        withoutPanel: false,
       }),
     );
 
     expect(type).toBe('plugins/registerPlugin/fulfilled');
     const { data, pluginsId } = store.getState().plugins.activePlugins;
 
-    expect(data[pluginFixture.hash]).toEqual(pluginFixture);
+    expect(data[pluginFixture.hash]).toEqual({ ...pluginFixture, withoutPanel: false });
     expect(pluginsId).toContain(pluginFixture.hash);
   });
 
@@ -68,6 +69,7 @@ describe('plugins reducer', () => {
         pluginUrl: pluginFixture.urls[0],
         pluginVersion: pluginFixture.version,
         extendedPluginName: pluginFixture.name,
+        withoutPanel: false,
       }),
     );
 
@@ -93,6 +95,7 @@ describe('plugins reducer', () => {
         pluginUrl: pluginFixture.urls[0],
         pluginVersion: pluginFixture.version,
         extendedPluginName: pluginFixture.name,
+        withoutPanel: false,
       }),
     );
 
@@ -113,6 +116,7 @@ describe('plugins reducer', () => {
         pluginUrl: pluginFixture.urls[0],
         pluginVersion: pluginFixture.version,
         extendedPluginName,
+        withoutPanel: false,
       }),
     );
 
@@ -122,6 +126,7 @@ describe('plugins reducer', () => {
       [pluginFixture.hash]: {
         ...pluginFixture,
         name: extendedPluginName,
+        withoutPanel: false,
       },
     });
   });
@@ -136,6 +141,7 @@ describe('plugins reducer', () => {
         pluginUrl: pluginFixture.urls[0],
         pluginVersion: pluginFixture.version,
         extendedPluginName: pluginFixture.name,
+        withoutPanel: false,
       }),
     );
 
diff --git a/src/redux/plugins/plugins.thunks.ts b/src/redux/plugins/plugins.thunks.ts
index 9a8e2888..8a33022e 100644
--- a/src/redux/plugins/plugins.thunks.ts
+++ b/src/redux/plugins/plugins.thunks.ts
@@ -23,6 +23,7 @@ type RegisterPlugin = {
   pluginVersion: string;
   isPublic: boolean;
   extendedPluginName: string;
+  withoutPanel: boolean | undefined;
 };
 
 export const registerPlugin = createAsyncThunk<
@@ -31,12 +32,20 @@ export const registerPlugin = createAsyncThunk<
   ThunkConfig
 >(
   'plugins/registerPlugin',
-  async ({ hash, isPublic, pluginName, pluginUrl, pluginVersion, extendedPluginName }) => {
+  async ({
+    hash,
+    isPublic,
+    pluginName,
+    pluginUrl,
+    pluginVersion,
+    extendedPluginName,
+    withoutPanel,
+  }) => {
     try {
-      const hashWihtoutPrefix = getPluginHashWithoutPrefix(hash);
+      const hashWithoutPrefix = getPluginHashWithoutPrefix(hash);
 
       const payload = {
-        hash: hashWihtoutPrefix,
+        hash: hashWithoutPrefix,
         url: pluginUrl,
         name: pluginName,
         version: pluginVersion,
@@ -58,6 +67,7 @@ export const registerPlugin = createAsyncThunk<
           ...response.data,
           hash,
           name: extendedPluginName,
+          withoutPanel,
         };
       }
 
diff --git a/src/services/pluginsManager/pluginsManager.ts b/src/services/pluginsManager/pluginsManager.ts
index 5653cd02..78f09d96 100644
--- a/src/services/pluginsManager/pluginsManager.ts
+++ b/src/services/pluginsManager/pluginsManager.ts
@@ -161,7 +161,7 @@ export const PluginsManager: PluginsManagerType = {
       PluginsManager.pluginsOccurrences[hash] = ZERO;
     }
   },
-  registerPlugin({ pluginName, pluginVersion, pluginUrl }) {
+  registerPlugin({ pluginName, pluginVersion, pluginUrl, withoutPanel }) {
     const hash = PluginsManager.hashedPlugins[pluginUrl];
 
     const extendedHash = PluginsManager.getExtendedPluginHash(hash);
@@ -182,12 +182,16 @@ export const PluginsManager: PluginsManagerType = {
         pluginName,
         pluginUrl,
         pluginVersion,
+        withoutPanel,
       }),
     );
 
-    const element = PluginsManager.createAndGetPluginContent({
-      hash: extendedHash,
-    });
+    const element = PluginsManager.createAndGetPluginContent(
+      {
+        hash: extendedHash,
+      },
+      !!withoutPanel,
+    );
 
     return {
       element,
@@ -202,12 +206,14 @@ export const PluginsManager: PluginsManagerType = {
       },
     };
   },
-  createAndGetPluginContent({ hash }) {
+  createAndGetPluginContent({ hash }, detached) {
     const element = document.createElement('div');
     element.setAttribute(PLUGINS_CONTENT_ELEMENT_ATTR_NAME, hash);
 
-    const wrapper = document.querySelector(`#${PLUGINS_CONTENT_ELEMENT_ID}`);
-    wrapper?.append(element);
+    if (!detached) {
+      const wrapper = document.querySelector(`#${PLUGINS_CONTENT_ELEMENT_ID}`);
+      wrapper?.append(element);
+    }
 
     return element;
   },
diff --git a/src/services/pluginsManager/pluginsManager.types.ts b/src/services/pluginsManager/pluginsManager.types.ts
index 2d959cf2..1da8b315 100644
--- a/src/services/pluginsManager/pluginsManager.types.ts
+++ b/src/services/pluginsManager/pluginsManager.types.ts
@@ -6,6 +6,7 @@ export type RegisterPlugin = {
   pluginName: string;
   pluginVersion: string;
   pluginUrl: string;
+  withoutPanel?: boolean | undefined;
 };
 
 export type MinervaConfiguration = ReturnType<typeof configurationMapper>;
@@ -16,10 +17,10 @@ export type PluginsManagerType = {
   };
   setHashedPlugin({ pluginUrl, pluginScript }: { pluginUrl: string; pluginScript: string }): string;
   init(): Unsubscribe;
-  registerPlugin({ pluginName, pluginVersion, pluginUrl }: RegisterPlugin): {
+  registerPlugin({ pluginName, pluginVersion, pluginUrl, withoutPanel }: RegisterPlugin): {
     element: HTMLDivElement;
   };
-  createAndGetPluginContent(plugin: Pick<MinervaPlugin, 'hash'>): HTMLDivElement;
+  createAndGetPluginContent(plugin: Pick<MinervaPlugin, 'hash'>, detached: boolean): HTMLDivElement;
   removePluginContent(plugin: Pick<MinervaPlugin, 'hash'>): void;
   activePlugins: {
     [pluginId: string]: string[];
diff --git a/src/types/models.ts b/src/types/models.ts
index e06cbbfb..1b09b1d9 100644
--- a/src/types/models.ts
+++ b/src/types/models.ts
@@ -143,7 +143,7 @@ export type PublicationsResponse = z.infer<typeof publicationsResponseSchema>;
 export type Publication = z.infer<typeof publicationSchema>;
 export type ExportNetwork = z.infer<typeof exportNetworkchema>;
 export type ExportElements = z.infer<typeof exportElementsSchema>;
-export type MinervaPlugin = z.infer<typeof pluginSchema>; // Plugin type interfers with global Plugin type
+export type MinervaPlugin = z.infer<typeof pluginSchema>; // Plugin type interferes with global Plugin type
 export type GeneVariant = z.infer<typeof geneVariant>;
 export type TargetSearchNameResult = z.infer<typeof targetSearchNameResult>;
 export type TargetElement = z.infer<typeof targetElementSchema>;
-- 
GitLab