diff --git a/apps/web/.env b/apps/web/.env
new file mode 100644
index 0000000000000000000000000000000000000000..2458b1b74f5e911e2f9928977a1930edc8b78914
--- /dev/null
+++ b/apps/web/.env
@@ -0,0 +1,24 @@
+GRAPHPOLARIS_VERSION=dev
+BACKEND_URL=http://localhost
+BACKEND_WSS_URL=ws://localhost:3001/ws
+STAGING=dev
+SKIP_LOGIN=true
+BACKEND_USER=:3001
+GRAPHPOLARIS_VERSION=dev
+
+SENTRY_ENABLED=false
+SENTRY_URL=
+
+GP_AUTH_URL=
+
+WIP_TABLEVIS=false
+WIP_NODELINKVIS=false
+WIP_RAWJSONVIS=false
+WIP_PAOHVIS=true
+WIP_MATRIXVIS=true
+WIP_SEMANTICSUBSTRATESVIS=true
+WIP_MAPVIS=true
+
+WIP_INSIGHT_SHARING=true
+WIP_VIEWER_PERMISSIONS=true
+WIP_SHARABLE_EXPLORATION=true
diff --git a/apps/web/src/components/navbar/navbar.tsx b/apps/web/src/components/navbar/navbar.tsx
index e5512cb2cf2959b5b6e2140364d68dfc8c24d96c..5aa6d09c612d408d3f016f17495534cb6d94c9b4 100644
--- a/apps/web/src/components/navbar/navbar.tsx
+++ b/apps/web/src/components/navbar/navbar.tsx
@@ -8,16 +8,14 @@
 /* The comment above was added so the code coverage wouldn't count this file towards code coverage.
  * We do not test components/renderfunctions/styling files.
  * See testing plan for more details.*/
-import React, { useState, useRef, useEffect, useCallback } from 'react';
+import React, { useState, useRef, useEffect } from 'react';
 import { useAuthCache, useAuthentication } from '@graphpolaris/shared/lib/data-access';
 import { DropdownItem } from '@graphpolaris/shared/lib/components/dropdowns';
 import GpLogo from './gp-logo';
 import { Popover, PopoverContent, PopoverTrigger } from '@graphpolaris/shared/lib/components/layout/Popover';
-import { useDispatch } from 'react-redux';
-import { showManagePermissions, showSharableExploration } from 'config';
-import { Button, Dialog, DialogContent, DialogTrigger, useActiveSaveStateAuthorization, useSessionCache } from '@graphpolaris/shared';
+import { showSharableExploration } from 'config';
+import { Button, useActiveSaveStateAuthorization } from '@graphpolaris/shared';
 import { ManagementTrigger, ManagementViews } from '@graphpolaris/shared/lib/management';
-import { Members } from '@graphpolaris/shared/lib/management/Members';
 
 export const Navbar = () => {
   const dropdownRef = useRef<HTMLDivElement>(null);
diff --git a/libs/shared/lib/components/tooltip/Tooltip.tsx b/libs/shared/lib/components/tooltip/Tooltip.tsx
index ac37a2506cccbfb9eae449e2e9627a165d88fd13..2dc2869aa23cc2e135f76f6cf2517b4e6b73307e 100644
--- a/libs/shared/lib/components/tooltip/Tooltip.tsx
+++ b/libs/shared/lib/components/tooltip/Tooltip.tsx
@@ -24,7 +24,7 @@ interface TooltipOptions {
   placement?: Placement;
   open?: boolean;
   onOpenChange?: (open: boolean) => void;
-  boundaryElement?: React.RefObject<HTMLElement> | null;
+  boundaryElement?: React.RefObject<HTMLElement> | HTMLElement | null;
   showArrow?: boolean;
   interactive?: boolean;
 }
@@ -60,14 +60,14 @@ export function useTooltip({
       flip({
         crossAxis: placement.includes('-'),
         fallbackAxisSideDirection: 'start',
-        padding: 5
+        padding: 5,
       }),
       shift({ padding: 5 }),
     ],
   };
 
   if (boundaryElement != null) {
-    const boundary = boundaryElement?.current ?? undefined;
+    const boundary = boundaryElement instanceof HTMLElement ? (boundaryElement ?? undefined) : (boundaryElement?.current ?? undefined);
     config.middleware.find((x) => x.name == 'flip')!.options[0].boundary = boundary;
     config.middleware.find((x) => x.name == 'shift')!.options[0].boundary = boundary;
     config.middleware.push(hide({ boundary }));
@@ -125,9 +125,7 @@ export function Tooltip({ children, ...options }: { children: React.ReactNode }
   // or other positioning options.
   const tooltip = useTooltip(options);
 
-  return <TooltipContext.Provider value={tooltip}>
-    {children}
-  </TooltipContext.Provider>;
+  return <TooltipContext.Provider value={tooltip}>{children}</TooltipContext.Provider>;
 }
 
 export const TooltipTrigger = React.forwardRef<HTMLElement, React.HTMLProps<HTMLElement> & { asChild?: boolean; x?: number; y?: number }>(
diff --git a/libs/shared/lib/data-access/api/eventBus.tsx b/libs/shared/lib/data-access/api/eventBus.tsx
index bc471755dc093378de92519c25eaabf783662afc..d48c70bc64eb36fd1cbfcf4a65533ebdf38b30f8 100644
--- a/libs/shared/lib/data-access/api/eventBus.tsx
+++ b/libs/shared/lib/data-access/api/eventBus.tsx
@@ -77,11 +77,13 @@ export const EventBus = (props: { onRunQuery: Function; onAuthorized: Function }
       console.debug('Setting state fetched from database', saveStateID, saveStates);
       const state = saveStates[saveStateID];
       if (state) {
-        dispatch(setQuerybuilderNodes(state.queryBuilder));
+        if (state.queries && state.queries.length > 0) {
+          dispatch(setQuerybuilderNodes(state.queries[0]));
+        }
         dispatch(
           setVisualizationState(
-            Object.keys(state.visualization).length !== 0 // should only occur in mock data
-              ? (state.visualization as VisState)
+            Object.keys(state.visualizations).length !== 0 // should only occur in mock data
+              ? (state.visualizations as VisState)
               : {
                   activeVisualizationIndex: -1,
                   openVisualizationArray: [],
@@ -189,7 +191,7 @@ export const EventBus = (props: { onRunQuery: Function; onAuthorized: Function }
       if (response && response.result) {
         dispatch(setQueryText(response));
       }
-    }, 'query_translation_result');
+    }, 'queryTranslation_result');
 
     login();
 
@@ -199,7 +201,7 @@ export const EventBus = (props: { onRunQuery: Function; onAuthorized: Function }
       unsubs.forEach((unsub) => {
         unsub();
       });
-      Broker.instance().unSubscribeAll('query_translation_result');
+      Broker.instance().unSubscribeAll('queryTranslation_result');
       Broker.instance().unSubscribeAll('schema_stats_result');
       Broker.instance().unSubscribeAll('schema_inference');
     };
@@ -208,9 +210,9 @@ export const EventBus = (props: { onRunQuery: Function; onAuthorized: Function }
   useEffect(() => {
     if (session.currentSaveState) {
       let state = { ...session.saveStates[session.currentSaveState] };
-      if (!isEqual(state.queryBuilder, queryBuilder) && state.queryBuilder?.graph?.nodes) {
-        console.debug('Updating queryBuilder state', state.queryBuilder, queryBuilder);
-        state.queryBuilder = { ...queryBuilder };
+      if (!isEqual(state.queries?.[0], queryBuilder)) {
+        console.debug('Updating queryBuilder state', state.queries, queryBuilder);
+        state.queries = [{ ...queryBuilder }];
         dispatch(updateSelectedSaveState(state));
         wsUpdateState(state);
       }
@@ -220,9 +222,9 @@ export const EventBus = (props: { onRunQuery: Function; onAuthorized: Function }
   useEffect(() => {
     if (session.currentSaveState) {
       let state = { ...session.saveStates[session.currentSaveState] };
-      if (!isEqual(state.visualization, visState)) {
+      if (!isEqual(state.visualizations, visState)) {
         console.debug('Updating visState state', visState);
-        state.visualization = { ...visState };
+        state.visualizations = { ...visState };
         dispatch(updateSelectedSaveState(state));
         wsUpdateState(state);
       }
diff --git a/libs/shared/lib/data-access/broker/broker.tsx b/libs/shared/lib/data-access/broker/broker.tsx
index ab9739aad520ef4d7c2341d20b0929ca98fb1d15..f915a2f241faec948ebecc2ecf8ff1bc788db470 100644
--- a/libs/shared/lib/data-access/broker/broker.tsx
+++ b/libs/shared/lib/data-access/broker/broker.tsx
@@ -12,7 +12,7 @@ import { ReceiveMessageI, SendMessageI, SendMessageWithSessionI } from './types'
  * It works with routingkeys, a listener can subscribe to messages from the backend with a specific routingkey.
  * Possible routingkeys:
  * - query_result:              Contains an object with nodes and edges or a numerical result.
- * - query_translation_result:  Contains the query translated to the database language.
+ * - queryTranslation_result:  Contains the query translated to the database language.
  * - schema_result:             Contains the schema of the users database.
  * - query_status_update:       Contains an update to if a query is being executed.
  * - query_database_error:      Contains the error received from the database.
diff --git a/libs/shared/lib/data-access/broker/wsQuery.ts b/libs/shared/lib/data-access/broker/wsQuery.ts
index ca1aac6fcc932db137c727450038875367024db0..6f8bc2c3a4b9e6775cd9d75cf134230a60e251e0 100644
--- a/libs/shared/lib/data-access/broker/wsQuery.ts
+++ b/libs/shared/lib/data-access/broker/wsQuery.ts
@@ -24,9 +24,9 @@ export function wsManualQueryRequest(query: string) {
 
 type QueryTranslationResponse = (data: QueryBuilderText) => void;
 export function wsQueryTranslationSubscription(callback: QueryTranslationResponse) {
-  const id = Broker.instance().subscribe(callback, 'query_translation_result');
+  const id = Broker.instance().subscribe(callback, 'queryTranslation_result');
   return () => {
-    Broker.instance().unSubscribe('query_translation_result', id);
+    Broker.instance().unSubscribe('queryTranslation_result', id);
   };
 }
 
diff --git a/libs/shared/lib/data-access/broker/wsState.tsx b/libs/shared/lib/data-access/broker/wsState.tsx
index d938c9f2a17d142fe2e8567ec95d576cd52b039e..24a87ed3f0b9459be7c2dd8e25e53433bb04565e 100644
--- a/libs/shared/lib/data-access/broker/wsState.tsx
+++ b/libs/shared/lib/data-access/broker/wsState.tsx
@@ -1,4 +1,4 @@
-import { QueryBuilderState } from '../store/querybuilderSlice';
+import { QueryBuilderState, SchemaState } from '../store/querybuilderSlice';
 import { URLParams, setParam } from '../api/url';
 import { Broker } from './broker';
 import { DateStringStatement } from '../../querybuilder/model/logic/general';
@@ -9,8 +9,8 @@ export const databaseNameMapping: string[] = ['arangodb', 'neo4j'];
 export const databaseProtocolMapping: string[] = ['neo4j://', 'neo4j+s://', 'bolt://', 'bolt+s://'];
 
 export enum DatabaseType {
-  ArangoDB = 0,
-  Neo4j = 1,
+  ArangoDB = 'arango',
+  Neo4j = 'neo4j',
 }
 
 export enum DatabaseStatus {
@@ -26,7 +26,7 @@ export type DatabaseInfo = {
   protocol: string;
   username: string;
   password: string;
-  type: number;
+  type: string;
 };
 
 export const SaveStateAuthorizationObjectsArray = ['database', 'visualization', 'query', 'schema'] as const;
@@ -42,13 +42,15 @@ export const nilUUID = '00000000-0000-0000-0000-000000000000';
 
 export type SaveStateI = {
   id: string;
-  user_id: string;
+  userId: string;
   name: string;
-  db: DatabaseInfo;
-  schema: any;
-  queryBuilder: QueryBuilderState;
-  visualization: VisState | {};
-  share_state: any;
+  dbConnections: DatabaseInfo[];
+  schemas: SchemaState[];
+  queries: QueryBuilderState[];
+  visualizations: VisState;
+  createdAt: string;
+  updatedAt: string;
+  shareState: any;
 };
 
 type GetStateResponse = (data: SaveStateI) => void;
@@ -169,6 +171,11 @@ export function wsUpdateState(request: SaveStateI, callback?: GetStateResponse)
 }
 
 export function wsTestDatabaseConnection(dbConnection: DatabaseInfo, callback?: TestSaveStateConnectionResponse) {
+  if (!dbConnection) {
+    console.warn('dbConnection is undefined on wsTestDatabaseConnection');
+    if (callback) callback({ status: 'fail', saveStateID: '' });
+    return;
+  }
   Broker.instance().sendMessage(
     {
       key: 'dbConnection',
diff --git a/libs/shared/lib/data-access/security/useAuthentication.tsx b/libs/shared/lib/data-access/security/useAuthentication.tsx
index f4718b51ca472c82b2a0323db6a396078a285cb7..fcb507b868c3effc43464d9049899e9ec33be6ce 100644
--- a/libs/shared/lib/data-access/security/useAuthentication.tsx
+++ b/libs/shared/lib/data-access/security/useAuthentication.tsx
@@ -20,10 +20,11 @@ export const useAuthentication = () => {
 
   const login = () => {
     fetch(`${domain}${userURI}/headers`, fetchSettings)
-      .then((res) =>
+      .then((res) => {
         res
           .json()
           .then((res: UserAuthenticationHeader) => {
+            console.log(res, 'headers');
             dispatch(
               authenticated({
                 username: res.username,
@@ -35,8 +36,8 @@ export const useAuthentication = () => {
               }),
             );
           })
-          .catch(handleError),
-      )
+          .catch(handleError);
+      })
       .catch(handleError);
   };
 
diff --git a/libs/shared/lib/data-access/store/querybuilderSlice.ts b/libs/shared/lib/data-access/store/querybuilderSlice.ts
index bfa417fdadb25406e594c4efe05662a1fc7ddf31..d6b771370819e30054cb45b74f8d73766a806fce 100644
--- a/libs/shared/lib/data-access/store/querybuilderSlice.ts
+++ b/libs/shared/lib/data-access/store/querybuilderSlice.ts
@@ -36,6 +36,10 @@ export type QueryBuilderState = {
   unionTypes: { [nodeId: string]: QueryUnionType };
 };
 
+export type SchemaState = {
+  settings: Record<string, any>;
+}
+
 // Define the initial state using that type
 export const initialState: QueryBuilderState = {
   graph: defaultGraph(),
@@ -65,6 +69,11 @@ export const querybuilderSlice = createSlice({
       state.graph = action.payload;
       state.ignoreReactivity = false;
     },
+    /**
+     * Sets the querybuilder nodes, settings, and attributes being shown,
+     * if the payload contains the required information.
+     * @param {QueryBuilderState} action.payload the payload with the new state
+     */
     setQuerybuilderNodes: (state: QueryBuilderState, action: PayloadAction<QueryBuilderState>) => {
       if (action.payload.graph?.nodes && action.payload.graph?.edges) {
         state.graph = action.payload.graph;
diff --git a/libs/shared/lib/data-access/store/visualizationSlice.ts b/libs/shared/lib/data-access/store/visualizationSlice.ts
index 1f206d93297a33b1420f3ae86ec75b7811562e70..1f9600963e814905a9ca85935d5fed0761946009 100644
--- a/libs/shared/lib/data-access/store/visualizationSlice.ts
+++ b/libs/shared/lib/data-access/store/visualizationSlice.ts
@@ -5,8 +5,8 @@ import { isEqual } from 'lodash-es';
 
 export type VisStateSettings = VisualizationSettingsType[];
 export type VisState = {
-  activeVisualizationIndex: number;
-  openVisualizationArray: VisStateSettings;
+  activeVisualizationIndex: number; // uses underscore_case to match data model from backend
+  openVisualizationArray: VisStateSettings; // uses underscore_case to match data model from backend
 };
 
 export const initialState: VisState = {
diff --git a/libs/shared/lib/inspector/ConnectionInspector.tsx b/libs/shared/lib/inspector/ConnectionInspector.tsx
index 16988b41ffdf72845bd5705fc3be7294d16291f2..0268472f10a3da825621a7f307f8be187501b9ba 100644
--- a/libs/shared/lib/inspector/ConnectionInspector.tsx
+++ b/libs/shared/lib/inspector/ConnectionInspector.tsx
@@ -12,13 +12,13 @@ export function ConnectionInspector() {
           <span className="text-xs font-semibold">Name</span>
           <span className="text-xs">{session.saveStates[session.currentSaveState].name}</span>
           <span className="text-xs font-semibold">Database</span>
-          <span className="text-xs">{session.saveStates[session.currentSaveState].db.internalDatabaseName}</span>
+          <span className="text-xs">{session.saveStates[session.currentSaveState].dbConnections?.[0]?.internalDatabaseName}</span>
           <span className="text-xs font-semibold">Protocol</span>
-          <span className="text-xs">{session.saveStates[session.currentSaveState].db.protocol}</span>
+          <span className="text-xs">{session.saveStates[session.currentSaveState].dbConnections?.[0]?.protocol}</span>
           <span className="text-xs font-semibold">Hostname</span>
-          <span className="text-xs">{session.saveStates[session.currentSaveState].db.url}</span>
+          <span className="text-xs">{session.saveStates[session.currentSaveState].dbConnections?.[0]?.url}</span>
           <span className="text-xs font-semibold">Port</span>
-          <span className="text-xs">{session.saveStates[session.currentSaveState].db.port}</span>
+          <span className="text-xs">{session.saveStates[session.currentSaveState].dbConnections?.[0]?.port}</span>
         </div>
       )}
     </div>
diff --git a/libs/shared/lib/inspector/InspectorPanel.tsx b/libs/shared/lib/inspector/InspectorPanel.tsx
index a803dd5cc4ad3125eeea16f0b678eeee7b7cf8ce..cbc35aefc3191b55141d062f965daacd8b25695d 100644
--- a/libs/shared/lib/inspector/InspectorPanel.tsx
+++ b/libs/shared/lib/inspector/InspectorPanel.tsx
@@ -15,7 +15,6 @@ export function InspectorPanel(props: { children?: React.ReactNode }) {
   const selection = useSelection();
   const focus = useFocus();
   const dispatch = useDispatch();
-  const { activeVisualizationIndex } = useVisualization();
 
   const inspector = useMemo(() => {
     if (selection) return <SelectionConfig />;
diff --git a/libs/shared/lib/management/database/DatabaseForm.tsx b/libs/shared/lib/management/database/DatabaseForm.tsx
index 1f49601f3daa4165eb5f0a6e635e0ab0bf2a3029..b4d8e3045f46973178c840840ab6e65931ad374d 100644
--- a/libs/shared/lib/management/database/DatabaseForm.tsx
+++ b/libs/shared/lib/management/database/DatabaseForm.tsx
@@ -6,20 +6,24 @@ import { databaseNameMapping, databaseProtocolMapping, DatabaseType, Input, nilU
 export const INITIAL_SAVE_STATE: SaveStateI = {
   id: nilUUID,
   name: 'Untitled',
-  db: {
-    username: 'neo4j',
-    password: 'DevOnlyPass',
-    url: 'localhost',
-    port: 7687,
-    protocol: 'neo4j://',
-    internalDatabaseName: 'neo4j',
-    type: DatabaseType.Neo4j,
-  },
-  schema: {},
-  queryBuilder: qbInitialState,
-  visualization: {},
-  share_state: {},
-  user_id: '',
+  dbConnections: [
+    {
+      username: 'neo4j',
+      password: 'DevOnlyPass',
+      url: 'localhost',
+      port: 7687,
+      protocol: 'neo4j://',
+      internalDatabaseName: 'neo4j',
+      type: DatabaseType.Neo4j,
+    },
+  ],
+  schemas: [{ settings: {} }],
+  queries: [qbInitialState],
+  visualizations: { activeVisualizationIndex: -1, openVisualizationArray: [] },
+  shareState: {},
+  createdAt: '',
+  updatedAt: '',
+  userId: '',
 };
 
 export const DatabaseForm = (props: { data: SaveStateI; onChange: (data: SaveStateI, error: boolean) => void }) => {
@@ -29,7 +33,7 @@ export const DatabaseForm = (props: { data: SaveStateI; onChange: (data: SaveSta
   function handlePortChanged(port: string): void {
     if (!isNaN(Number(port)))
       setFormData((draft) => {
-        draft.db.port = Number(port);
+        draft.dbConnections[0].port = Number(port);
         return draft;
       });
   }
@@ -54,7 +58,7 @@ export const DatabaseForm = (props: { data: SaveStateI; onChange: (data: SaveSta
       <Input
         type="text"
         label="Internal database name"
-        value={formData.db.internalDatabaseName}
+        value={formData.dbConnections[0].internalDatabaseName}
         placeholder="internalDatabaseName"
         required
         errorText="This field is required"
@@ -64,7 +68,7 @@ export const DatabaseForm = (props: { data: SaveStateI; onChange: (data: SaveSta
         }}
         onChange={(value: string) =>
           setFormData((draft) => {
-            draft.db.internalDatabaseName = value;
+            draft.dbConnections[0].internalDatabaseName = value;
           })
         }
       />
@@ -75,11 +79,11 @@ export const DatabaseForm = (props: { data: SaveStateI; onChange: (data: SaveSta
           className="w-full"
           label="Database Type"
           required
-          value={databaseNameMapping[formData.db.type]}
+          value={formData.dbConnections[0].type}
           options={databaseNameMapping}
           onChange={(value: string | number) => {
             setFormData((draft) => {
-              draft.db.type = databaseNameMapping.indexOf(value.toString());
+              draft.dbConnections[0].type = value.toString();
             });
           }}
         />
@@ -88,12 +92,12 @@ export const DatabaseForm = (props: { data: SaveStateI; onChange: (data: SaveSta
           type="dropdown"
           label="Database Protocol"
           required
-          value={formData.db.protocol}
+          value={formData.dbConnections[0].protocol}
           options={databaseProtocolMapping}
           info="Protocol via which the database connection will be established"
           onChange={(value: string | number) => {
             setFormData((draft) => {
-              draft.db.protocol = value.toString();
+              draft.dbConnections[0].protocol = value.toString();
             });
           }}
         />
@@ -103,7 +107,7 @@ export const DatabaseForm = (props: { data: SaveStateI; onChange: (data: SaveSta
         <Input
           type="text"
           label="Hostname/IP"
-          value={formData.db.url}
+          value={formData.dbConnections[0].url}
           placeholder="neo4j"
           required
           errorText="This field is required"
@@ -114,7 +118,7 @@ export const DatabaseForm = (props: { data: SaveStateI; onChange: (data: SaveSta
           }}
           onChange={(value: string) => {
             setFormData((draft) => {
-              draft.db.url = value;
+              draft.dbConnections[0].url = value;
             });
           }}
         />
@@ -122,7 +126,7 @@ export const DatabaseForm = (props: { data: SaveStateI; onChange: (data: SaveSta
         <Input
           type="text"
           label="Port"
-          value={formData.db.port.toString()}
+          value={formData.dbConnections[0].port.toString()}
           placeholder="neo4j"
           required
           errorText="Must be between 1 and 9999"
@@ -133,7 +137,7 @@ export const DatabaseForm = (props: { data: SaveStateI; onChange: (data: SaveSta
           }}
           onChange={(value: string) => {
             setFormData((draft) => {
-              draft.db.port = Number(value);
+              draft.dbConnections[0].port = Number(value);
             });
           }}
         />
@@ -143,7 +147,7 @@ export const DatabaseForm = (props: { data: SaveStateI; onChange: (data: SaveSta
         <Input
           type="text"
           label="Username"
-          value={formData.db.username}
+          value={formData.dbConnections[0].username}
           placeholder="username"
           required
           errorText="This field is required"
@@ -154,7 +158,7 @@ export const DatabaseForm = (props: { data: SaveStateI; onChange: (data: SaveSta
           }}
           onChange={(value: string) => {
             setFormData((draft) => {
-              draft.db.username = value;
+              draft.dbConnections[0].username = value;
             });
           }}
         />
@@ -163,7 +167,7 @@ export const DatabaseForm = (props: { data: SaveStateI; onChange: (data: SaveSta
           type="text"
           visible={false}
           label="Password"
-          value={formData.db.password}
+          value={formData.dbConnections[0].password}
           placeholder="password"
           required
           errorText="This field is required"
@@ -174,7 +178,7 @@ export const DatabaseForm = (props: { data: SaveStateI; onChange: (data: SaveSta
           }}
           onChange={(value: string) => {
             setFormData((draft) => {
-              draft.db.password = value;
+              draft.dbConnections[0].password = value;
             });
           }}
         />
diff --git a/libs/shared/lib/management/database/Databases.tsx b/libs/shared/lib/management/database/Databases.tsx
index a3c327212822834eab5802b8ac55d305f52513f2..786a8ab0971286caaa835972ab2513273711c6d4 100644
--- a/libs/shared/lib/management/database/Databases.tsx
+++ b/libs/shared/lib/management/database/Databases.tsx
@@ -66,7 +66,8 @@ export function Databases({ onClose, saveStates, changeActive, setSelectedSaveSt
           if (saveStates[a].name.toLowerCase() <= saveStates[b].name.toLowerCase()) return dir;
           else return -dir;
         } else {
-          if (saveStates[a].db[orderBy[0]].toLowerCase() <= saveStates[b].db[orderBy[0]].toLowerCase()) return dir;
+          if (saveStates[a].dbConnections?.[0][orderBy[0]].toLowerCase() <= saveStates[b].dbConnections?.[0][orderBy[0]].toLowerCase())
+            return dir;
           else return -dir;
         }
       }),
@@ -119,10 +120,10 @@ export function Databases({ onClose, saveStates, changeActive, setSelectedSaveSt
                   </Button>
                 </td>
                 <td className="text-left">
-                  <span className="font-light">{saveStates[key].db.protocol}</span>
+                  <span className="font-light">{saveStates[key].dbConnections?.[0]?.protocol}</span>
                 </td>
                 <td className="text-left">
-                  <span className="font-light">{saveStates[key].db.url}</span>
+                  <span className="font-light">{saveStates[key].dbConnections?.[0]?.url}</span>
                 </td>
                 <td className="text-right flex justify-end">
                   <Button
diff --git a/libs/shared/lib/management/database/MockSaveStates.tsx b/libs/shared/lib/management/database/MockSaveStates.tsx
index 7fdaa0a190642b8c44d62a30b82fc488cfa3ee5b..a23aba28d11b76cd531138c8d081000210db8890 100644
--- a/libs/shared/lib/management/database/MockSaveStates.tsx
+++ b/libs/shared/lib/management/database/MockSaveStates.tsx
@@ -13,120 +13,144 @@ export const sampleSaveStates: Array<SaveStateSampleI> = [
     name: 'Recommendations',
     subtitle: 'Hosted by Neo4j',
     description: 'Network of movies, actors, directors and reviews by people',
-    db: {
-      username: 'recommendations',
-      password: 'recommendations',
-      url: 'demo.neo4jlabs.com',
-      port: 7687,
-      protocol: 'neo4j+s://',
-      internalDatabaseName: 'recommendations',
-      type: DatabaseType.Neo4j,
-    },
-    schema: {},
-    queryBuilder: qbInitialState,
-    visualization: {},
-    share_state: {},
-    user_id: '',
+    dbConnections: [
+      {
+        username: 'recommendations',
+        password: 'recommendations',
+        url: 'demo.neo4jlabs.com',
+        port: 7687,
+        protocol: 'neo4j+s://',
+        internalDatabaseName: 'recommendations',
+        type: DatabaseType.Neo4j,
+      },
+    ],
+    schemas: [],
+    queries: [qbInitialState],
+    visualizations: { activeVisualizationIndex: -1, openVisualizationArray: [] },
+    shareState: {},
+    userId: '',
+    createdAt: '',
+    updatedAt: '',
   },
   {
     id: nilUUID,
     name: 'Movies',
     subtitle: 'Hosted by Neo4j',
     description: 'Movies and people related to those movies as actors, directors and producers',
-    db: {
-      username: 'movies',
-      password: 'movies',
-      url: 'demo.neo4jlabs.com',
-      port: 7687,
-      protocol: 'neo4j+s://',
-      internalDatabaseName: 'movies',
-      type: DatabaseType.Neo4j,
-    },
-    schema: {},
-    queryBuilder: qbInitialState,
-    visualization: {},
-    share_state: {},
-    user_id: '',
+    dbConnections: [
+      {
+        username: 'movies',
+        password: 'movies',
+        url: 'demo.neo4jlabs.com',
+        port: 7687,
+        protocol: 'neo4j+s://',
+        internalDatabaseName: 'movies',
+        type: DatabaseType.Neo4j,
+      },
+    ],
+    schemas: [],
+    queries: [qbInitialState],
+    visualizations: { activeVisualizationIndex: -1, openVisualizationArray: [] },
+    shareState: {},
+    userId: '',
+    createdAt: '',
+    updatedAt: '',
   },
   {
     id: nilUUID,
     name: 'Northwind',
     subtitle: 'Hosted by Neo4j',
     description: 'Retail-system with products, orders, customers, suppliers and employees',
-    db: {
-      username: 'northwind',
-      password: 'northwind',
-      url: 'demo.neo4jlabs.com',
-      port: 7687,
-      protocol: 'neo4j+s://',
-      internalDatabaseName: 'northwind',
-      type: DatabaseType.Neo4j,
-    },
-    schema: {},
-    queryBuilder: qbInitialState,
-    visualization: {},
-    share_state: {},
-    user_id: '',
+    dbConnections: [
+      {
+        username: 'northwind',
+        password: 'northwind',
+        url: 'demo.neo4jlabs.com',
+        port: 7687,
+        protocol: 'neo4j+s://',
+        internalDatabaseName: 'northwind',
+        type: DatabaseType.Neo4j,
+      },
+    ],
+    schemas: [],
+    queries: [qbInitialState],
+    visualizations: { activeVisualizationIndex: -1, openVisualizationArray: [] },
+    shareState: {},
+    userId: '',
+    createdAt: '',
+    updatedAt: '',
   },
   {
     id: nilUUID,
     name: 'Fincen',
     subtitle: 'Hosted by Neo4j',
     description: 'FinCEN files investigation for banks and countries',
-    db: {
-      username: 'fincen',
-      password: 'fincen',
-      url: 'demo.neo4jlabs.com',
-      port: 7687,
-      protocol: 'neo4j+s://',
-      internalDatabaseName: 'fincen',
-      type: DatabaseType.Neo4j,
-    },
-    schema: {},
-    queryBuilder: qbInitialState,
-    visualization: {},
-    share_state: {},
-    user_id: '',
+    dbConnections: [
+      {
+        username: 'fincen',
+        password: 'fincen',
+        url: 'demo.neo4jlabs.com',
+        port: 7687,
+        protocol: 'neo4j+s://',
+        internalDatabaseName: 'fincen',
+        type: DatabaseType.Neo4j,
+      },
+    ],
+    schemas: [],
+    queries: [qbInitialState],
+    visualizations: { activeVisualizationIndex: -1, openVisualizationArray: [] },
+    shareState: {},
+    userId: '',
+    createdAt: '',
+    updatedAt: '',
   },
   {
     id: nilUUID,
     name: 'Slack',
     subtitle: 'Hosted by Neo4j',
     description: 'Communication network consisting of several types of users and messages',
-    db: {
-      username: 'slack',
-      password: 'slack',
-      url: 'demo.neo4jlabs.com',
-      port: 7687,
-      protocol: 'neo4j+s://',
-      internalDatabaseName: 'slack',
-      type: DatabaseType.Neo4j,
-    },
-    schema: {},
-    queryBuilder: qbInitialState,
-    visualization: {},
-    share_state: {},
-    user_id: '',
+    dbConnections: [
+      {
+        username: 'slack',
+        password: 'slack',
+        url: 'demo.neo4jlabs.com',
+        port: 7687,
+        protocol: 'neo4j+s://',
+        internalDatabaseName: 'slack',
+        type: DatabaseType.Neo4j,
+      },
+    ],
+    schemas: [],
+    queries: [qbInitialState],
+    visualizations: { activeVisualizationIndex: -1, openVisualizationArray: [] },
+    shareState: {},
+    userId: '',
+    createdAt: '',
+    updatedAt: '',
   },
   {
     id: nilUUID,
     name: 'Game of Thrones',
     subtitle: 'Hosted by Neo4j',
     description: 'Character interactions and actors in the Game of Thrones movie',
-    db: {
-      username: 'gameofthrones',
-      password: 'gameofthrones',
-      url: 'demo.neo4jlabs.com',
-      port: 7687,
-      protocol: 'neo4j+s://',
-      internalDatabaseName: 'gameofthrones',
-      type: DatabaseType.Neo4j,
-    },
-    schema: {},
-    queryBuilder: qbInitialState,
-    visualization: {},
-    share_state: {},
-    user_id: '',
+    dbConnections: [
+      {
+        username: 'gameofthrones',
+        password: 'gameofthrones',
+        url: 'demo.neo4jlabs.com',
+        port: 7687,
+        protocol: 'neo4j+s://',
+        internalDatabaseName: 'gameofthrones',
+        type: DatabaseType.Neo4j,
+      },
+    ],
+    schemas: [],
+    queries: [qbInitialState],
+    visualizations: { activeVisualizationIndex: -1, openVisualizationArray: [] },
+    shareState: {},
+    userId: '',
+    createdAt: '',
+    updatedAt: '',
   },
 ];
 
diff --git a/libs/shared/lib/management/database/UpsertDatabase.tsx b/libs/shared/lib/management/database/UpsertDatabase.tsx
index 5c6fa1513fd16e61f8ddfd5231dcefaab0ad6e5b..a3c4fa773c18db244030915b48a1a29cdd0a37e9 100644
--- a/libs/shared/lib/management/database/UpsertDatabase.tsx
+++ b/libs/shared/lib/management/database/UpsertDatabase.tsx
@@ -16,10 +16,10 @@ export const UpsertDatabase = (props: {
   const databaseHandler = useHandleDatabase();
   const ref = useRef<HTMLDialogElement>(null);
   const authCache = useAuthCache();
-  const [formData, setFormData] = useImmer(
+  const [formData, setFormData] = useImmer<SaveStateI>(
     props.saveState && props.open === 'update'
       ? props.saveState
-      : { ...INITIAL_SAVE_STATE, user_id: authCache.authentication?.userID || '' },
+      : { ...INITIAL_SAVE_STATE, userId: authCache.authentication?.userID || '' },
   );
   const [hasError, setHasError] = useState(false);
   const [sampleDataPanel, setSampleDataPanel] = useState<boolean | null>(false);
@@ -42,7 +42,7 @@ export const UpsertDatabase = (props: {
   }
 
   function closeDialog(): void {
-    setFormData({ ...INITIAL_SAVE_STATE, user_id: authCache.authentication?.userID || '' });
+    setFormData({ ...INITIAL_SAVE_STATE, userId: authCache.authentication?.userID || '' });
     ref.current?.close();
     props.onClose();
   }
@@ -54,7 +54,7 @@ export const UpsertDatabase = (props: {
           <SampleDatabaseSelector
             onClick={(data) => {
               setHasError(false);
-              handleSubmit({ ...data, user_id: authCache.authentication?.userID || '' });
+              handleSubmit({ ...data, userId: authCache.authentication?.userID || '' });
             }}
           />
         ) : (
diff --git a/libs/shared/lib/management/database/useHandleDatabase.ts b/libs/shared/lib/management/database/useHandleDatabase.ts
index 2f03281c9b26f8ba8cf4034246000d0a2994a04e..8ee9639a5baf304fe6d35ac25339c5f940719146 100644
--- a/libs/shared/lib/management/database/useHandleDatabase.ts
+++ b/libs/shared/lib/management/database/useHandleDatabase.ts
@@ -32,20 +32,21 @@ export const useHandleDatabase = () => {
     forceAdd: boolean = false,
     concludedCallback: () => void,
   ): Promise<void> {
+    console.log('submitDatabaseChange', saveStateData);
     setConnectionStatus(() => ({
       updating: true,
       status: 'Testing database connection',
       verified: null,
     }));
 
-    wsTestDatabaseConnection(saveStateData.db, (data) => {
+    wsTestDatabaseConnection(saveStateData.dbConnections?.[0], (data) => {
       if (!saveStateData) {
         console.error('formData is null');
         return;
       }
-      if (saveStateData.user_id !== authCache.authentication?.userID && authCache.authentication?.userID) {
+      if (saveStateData.userId !== authCache.authentication?.userID && authCache.authentication?.userID) {
         console.error('user_id is not equal to auth.userID');
-        saveStateData.user_id = authCache.authentication.userID;
+        saveStateData.userId = authCache.authentication.userID;
       }
       if (data && data.status === 'success') {
         setConnectionStatus((prevState) => ({
diff --git a/libs/shared/lib/querybuilder/panel/ContextMenu.tsx b/libs/shared/lib/querybuilder/panel/ContextMenu.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..f13fb451a2bb0b8fb3ed54369304baac6291a3ce
--- /dev/null
+++ b/libs/shared/lib/querybuilder/panel/ContextMenu.tsx
@@ -0,0 +1,133 @@
+import { useEffect, useMemo, useState } from 'react';
+import { Tooltip, TooltipTrigger, TooltipContent, DropdownItem, TextInput, Icon } from '../../components';
+import { ReactFlowInstance, Node } from 'reactflow';
+import { NodeAttribute, SchemaReactflowEntityNode } from '../model';
+import {
+  useAppDispatch,
+  useQuerybuilderAttributesShown,
+  useQuerybuilderGraph,
+  useQuerybuilderHash,
+  useQuerybuilderUnionTypes,
+} from '../..';
+import { isEqual } from 'lodash-es';
+import {
+  attributeShownToggle,
+  QueryUnionType,
+  setQuerybuilderGraphology,
+  setQueryUnionType,
+  toQuerybuilderGraphology,
+} from '@graphpolaris/shared/lib/data-access/store/querybuilderSlice';
+import { getDataTypeIcon } from '../../components/DataTypeIcon';
+
+export const ContextMenu = (props: {
+  open: boolean;
+  position?: { x: number; y: number };
+  node?: Node;
+  reactFlowWrapper: React.RefObject<HTMLDivElement>;
+  reactFlow: ReactFlowInstance;
+  onClose: () => void;
+}) => {
+  const [filter, setFilter] = useState<string>('');
+  const dispatch = useAppDispatch();
+  const graph = useQuerybuilderGraph();
+  const qbHash = useQuerybuilderHash();
+
+  const graphologyGraph = useMemo(() => toQuerybuilderGraphology(graph), [graph, qbHash]);
+
+  const state = useMemo(() => {
+    const divPos = props.reactFlowWrapper.current?.getBoundingClientRect();
+    if (!divPos || !props.node) return;
+    let position = { x: 0, y: 0 };
+    if (props.position) {
+      position = props.position;
+    } else {
+      position = props.reactFlow.flowToScreenPosition({ x: props.node.data.x, y: props.node.data.y });
+    }
+
+    return {
+      open: props.open,
+      x: position.x - divPos.x,
+      y: position.y - divPos.y + 10,
+    };
+  }, [props.open, props.node]);
+
+  const filteredAttributes = useMemo<NodeAttribute[]>(() => {
+    if (props.node == null) return [];
+    if (filter == null || filter.length == 0) return props.node.data.attributes;
+
+    return (props.node.data.attributes as NodeAttribute[]).filter((attr) => {
+      return attr.handleData.attributeName?.toLocaleLowerCase().includes(filter.toLocaleLowerCase());
+    });
+  }, [filter, props.node]);
+
+  const attributesBeingShown = useQuerybuilderAttributesShown();
+  function isAttributeAdded(attribute: NodeAttribute): boolean {
+    return attributesBeingShown.some((x) => isEqual(x, attribute.handleData));
+  }
+
+  function addAttribute(attribute: NodeAttribute) {
+    dispatch(attributeShownToggle(attribute.handleData));
+  }
+
+  const unionType = useQuerybuilderUnionTypes();
+  function setUnionType(unionType: QueryUnionType) {
+    if (!props.node) return;
+    dispatch(setQueryUnionType({ nodeId: props.node.id, unionType: unionType }));
+  }
+  function removeNode() {
+    if (!props.node) return;
+    graphologyGraph.dropNode(props.node.id);
+    dispatch(setQuerybuilderGraphology(graphologyGraph));
+    props.onClose();
+  }
+
+  return (
+    <Tooltip open={props.open && state !== undefined} interactive={true} showArrow={false} placement="bottom-start">
+      <TooltipTrigger x={state ? state.x : 0} y={state ? state.y : 0} />
+      <TooltipContent>
+        <DropdownItem
+          value={'Add/remove attribute'}
+          onClick={(e) => {}}
+          submenu={[
+            <TextInput
+              type={'text'}
+              placeholder="Filter"
+              size="xs"
+              className="mb-1 min-w-40 rounded-sm"
+              value={filter}
+              onClick={(e) => e.stopPropagation()}
+              onChange={(v) => setFilter(v)}
+            />,
+
+            filteredAttributes.map((attr) => (
+              <DropdownItem
+                key={attr.handleData.attributeName + attr.handleData.nodeId}
+                value={attr.handleData.attributeName ?? ''}
+                selected={isAttributeAdded(attr)}
+                onClick={(_) => addAttribute(attr)}
+              >
+                <Icon component={getDataTypeIcon(attr?.handleData?.attributeType)} className="ms-2 float-end" size={16} />
+              </DropdownItem>
+            )),
+          ]}
+        />
+        <DropdownItem
+          value="Union type"
+          submenu={[
+            <DropdownItem
+              value="AND"
+              onClick={(_) => setUnionType(QueryUnionType.AND)}
+              selected={props.node ? unionType[props.node.id] != QueryUnionType.OR : false} // Also selected when null
+            />,
+            <DropdownItem
+              value="OR"
+              onClick={(_) => setUnionType(QueryUnionType.OR)}
+              selected={props.node ? unionType[props.node.id] == QueryUnionType.OR : false}
+            />,
+          ]}
+        />
+        <DropdownItem value="Remove" className="text-danger" onClick={(e) => removeNode()} />
+      </TooltipContent>
+    </Tooltip>
+  );
+};
diff --git a/libs/shared/lib/querybuilder/panel/QueryBuilder.tsx b/libs/shared/lib/querybuilder/panel/QueryBuilder.tsx
index 10579c53407d1c5b2efcbe4b90bd562610248460..ad0ff3253217ad1a312c997595086aae01f4ea48 100644
--- a/libs/shared/lib/querybuilder/panel/QueryBuilder.tsx
+++ b/libs/shared/lib/querybuilder/panel/QueryBuilder.tsx
@@ -9,7 +9,11 @@ import {
   useSchemaInference,
   useSearchResultQB,
 } from '@graphpolaris/shared/lib/data-access/store';
-import { setQuerybuilderGraphology, toQuerybuilderGraphology } from '@graphpolaris/shared/lib/data-access/store/querybuilderSlice';
+import {
+  QueryUnionType,
+  setQuerybuilderGraphology,
+  toQuerybuilderGraphology,
+} from '@graphpolaris/shared/lib/data-access/store/querybuilderSlice';
 import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
 import ReactFlow, {
   Background,
@@ -22,6 +26,7 @@ import ReactFlow, {
   OnConnectStartParams,
   ReactFlowInstance,
   ReactFlowProvider,
+  Viewport,
   isNode,
   useReactFlow,
 } from 'reactflow';
@@ -40,6 +45,7 @@ import { ConnectingNodeDataI } from './utils/connectorDrop';
 import { resultSetFocus } from '../../data-access/store/interactionSlice';
 import { QueryBuilderDispatcherContext } from './QueryBuilderDispatcher';
 import { QueryBuilderNav, QueryBuilderToggleSettings } from './QueryBuilderNav';
+import { ContextMenu } from './ContextMenu';
 
 export type QueryBuilderProps = {
   onRunQuery?: () => void;
@@ -82,6 +88,9 @@ export const QueryBuilderInner = (props: QueryBuilderProps) => {
   const searchResults = useSearchResultQB();
   const reactFlowInstanceRef = useRef<ReactFlowInstance | null>(null);
   const [allowZoom, setAllowZoom] = useState(true);
+  const [contextMenuOpen, setContextMenuOpen] = useState<{ open: boolean; node?: Node; position?: { x: number; y: number } }>({
+    open: false,
+  });
 
   useEffect(() => {
     const searchResultKeys = new Set([...searchResults.nodes.map((node) => node.key), ...searchResults.edges.map((edge) => edge.key)]);
@@ -472,6 +481,21 @@ export const QueryBuilderInner = (props: QueryBuilderProps) => {
     }
   };
 
+  const onNodeContextMenu = (event: React.MouseEvent, node: Node) => {
+    if (event.shiftKey) return;
+    event.preventDefault();
+    setContextMenuOpen({ open: true, node: node, position: { x: event.clientX, y: event.clientY } });
+  };
+
+  const onMove = useCallback(
+    (event: MouseEvent | TouchEvent, viewport: Viewport) => {
+      if (contextMenuOpen.open) {
+        setContextMenuOpen({ ...contextMenuOpen, open: false });
+      }
+    },
+    [contextMenuOpen],
+  );
+
   useEffect(() => {
     try {
       applyLayout();
@@ -502,6 +526,16 @@ export const QueryBuilderInner = (props: QueryBuilderProps) => {
         },
       }}
     >
+      <ContextMenu
+        open={contextMenuOpen.open}
+        node={contextMenuOpen.node}
+        position={contextMenuOpen.position}
+        reactFlowWrapper={reactFlowWrapper}
+        reactFlow={reactFlow}
+        onClose={() => {
+          setContextMenuOpen({ ...contextMenuOpen, open: false });
+        }}
+      />
       <div ref={reactFlowWrapper} className="h-full w-full flex flex-col">
         <QueryBuilderNav
           toggleSettings={toggleSettings}
@@ -582,6 +616,7 @@ export const QueryBuilderInner = (props: QueryBuilderProps) => {
             reactFlowInstanceRef.current = reactFlowInstance;
             onInit(reactFlowInstance);
           }}
+          onMove={onMove}
           onNodesChange={saveStateAuthorization.query.W ? onNodesChange : () => {}}
           onDragOver={saveStateAuthorization.query.W ? onDragOver : () => {}}
           onConnect={saveStateAuthorization.query.W ? onConnect : () => {}}
@@ -594,7 +629,7 @@ export const QueryBuilderInner = (props: QueryBuilderProps) => {
           onEdgeUpdateEnd={saveStateAuthorization.query.W ? onEdgeUpdateEnd : () => {}}
           onDrop={saveStateAuthorization.query.W ? onDrop : () => {}}
           // onContextMenu={onContextMenu}
-          // onNodeContextMenu={saveStateAuthorization.query.W ? onNodeContextMenu : () => {}}
+          onNodeContextMenu={saveStateAuthorization.query.W ? onNodeContextMenu : () => {}}
           // onNodesDelete={onNodesDelete}
           // onNodesChange={onNodesChange}
           deleteKeyCode="Backspace"
diff --git a/libs/shared/lib/querybuilder/pills/customFlowPills/entitypill/QueryEntityPill.tsx b/libs/shared/lib/querybuilder/pills/customFlowPills/entitypill/QueryEntityPill.tsx
index 97b5865fc3ac45f397ad9d26b734593ef20a3aee..84be53b8d9b4742eee037d845d5fd54d404cbd1a 100644
--- a/libs/shared/lib/querybuilder/pills/customFlowPills/entitypill/QueryEntityPill.tsx
+++ b/libs/shared/lib/querybuilder/pills/customFlowPills/entitypill/QueryEntityPill.tsx
@@ -43,116 +43,14 @@ export const QueryEntityPill = React.memo((node: SchemaReactflowEntityNode) => {
     [graph],
   );
 
-  const [openDropdown, setOpenDropdown] = useState(false);
-  const [filter, setFilter] = useState<string>('');
-  const resource = 'query';
-
-  const filteredAttributes = useMemo(() => {
-    if (filter == null || filter.length == 0) return data.attributes;
-
-    return data.attributes.filter((attr) => {
-      return attr.handleData.attributeName?.toLocaleLowerCase().includes(filter.toLocaleLowerCase());
-    });
-  }, [filter]);
-
-  const qbHash = useQuerybuilderHash();
-  const graphologyGraph = useMemo(() => toQuerybuilderGraphology(graph), [graph, qbHash]);
-  const dispatch = useDispatch();
-
-  function removeNode() {
-    graphologyGraph.dropNode(node.id);
-    dispatch(setQuerybuilderGraphology(graphologyGraph));
-  }
-
-  function addAttribute(attribute: NodeAttribute) {
-    dispatch(attributeShownToggle(attribute.handleData));
-  }
-
   const unionType = useQuerybuilderUnionTypes()[node.id];
 
-  function setUnionType(unionType: QueryUnionType) {
-    dispatch(setQueryUnionType({ nodeId: node.id, unionType: unionType }));
-  }
-
-  const attributesBeingShown = useQuerybuilderAttributesShown();
-  function isAttributeAdded(attribute: NodeAttribute): boolean {
-    return attributesBeingShown.some((x) => isEqual(x, attribute.handleData));
-  }
-
   return (
     <div className="w-fit h-fit nowheel" ref={ref} id="asd">
       <EntityPill
         title={
           <div className="flex flex-row justify-between items-center">
             <span>{data.name || ''}</span>
-
-            <DropdownContainer>
-              <DropdownTrigger size="md">
-                <Button
-                  variantType="secondary"
-                  variant="ghost"
-                  size="2xs"
-                  iconComponent={openDropdown ? 'icon-[ic--baseline-arrow-drop-up]' : 'icon-[ic--baseline-arrow-drop-down]'}
-                  className={openDropdown ? 'border-secondary-200' : ''}
-                />
-              </DropdownTrigger>
-
-              <DropdownItemContainer>
-                <PopoverContext.Consumer>
-                  {(popover) => [
-                    <DropdownItem
-                      value={'Add/remove attribute'}
-                      onClick={(e) => {
-                        popover?.setOpen(false);
-                        setOpenDropdown(false);
-                      }}
-                      submenu={[
-                        <TextInput
-                          type={'text'}
-                          placeholder="Filter"
-                          size="xs"
-                          className="mb-1 min-w-40 rounded-sm"
-                          value={filter}
-                          onClick={(e) => e.stopPropagation()}
-                          onChange={(v) => setFilter(v)}
-                        />,
-
-                        filteredAttributes.map((attr) => (
-                          <DropdownItem
-                            key={attr.handleData.attributeName + attr.handleData.nodeId}
-                            value={attr.handleData.attributeName ?? ''}
-                            selected={isAttributeAdded(attr)}
-                            onClick={(_) => addAttribute(attr)}
-                          >
-                            <Icon component={getDataTypeIcon(attr?.handleData?.attributeType)} className="ms-2 float-end" size={16} />
-                          </DropdownItem>
-                        )),
-                      ]}
-                    />,
-                    <DropdownItem
-                      value="Union type"
-                      onClick={(e) => {
-                        popover?.setOpen(false);
-                        setOpenDropdown(false);
-                      }}
-                      submenu={[
-                        <DropdownItem
-                          value="AND"
-                          onClick={(_) => setUnionType(QueryUnionType.AND)}
-                          selected={unionType != QueryUnionType.OR} // Also selected when null
-                        />,
-                        <DropdownItem
-                          value="OR"
-                          onClick={(_) => setUnionType(QueryUnionType.OR)}
-                          selected={unionType == QueryUnionType.OR}
-                        />,
-                      ]}
-                    />,
-                  ]}
-                </PopoverContext.Consumer>
-                <DropdownItem value="Remove" className="text-danger" onClick={(e) => removeNode()} />
-              </DropdownItemContainer>
-            </DropdownContainer>
           </div>
         }
         withHandles="horizontal"
diff --git a/libs/shared/lib/vis/components/config/VisualizationSettings.tsx b/libs/shared/lib/vis/components/config/VisualizationSettings.tsx
index ec24a2e73ace7e9b5853db7b0bb9c70cfb9b3c4f..37abf9bf1c183cb8811b39c54f57bdf5fb929ae9 100644
--- a/libs/shared/lib/vis/components/config/VisualizationSettings.tsx
+++ b/libs/shared/lib/vis/components/config/VisualizationSettings.tsx
@@ -1,21 +1,7 @@
 import React, { Suspense, useEffect, useMemo, useState } from 'react';
-import {
-  Button,
-  Input,
-  VISUALIZATION_TYPES,
-  Visualizations,
-  useAppDispatch,
-  useGraphQueryResultMeta,
-  useVisualization,
-  useActiveVisualization,
-} from '../../..';
+import { Button, Input, VISUALIZATION_TYPES, Visualizations, useAppDispatch, useGraphQueryResultMeta, useVisualization } from '../../..';
 import { SettingsHeader } from './components';
-import {
-  removeVisualization,
-  updateActiveVisualization,
-  updateVisualization,
-  updateActiveVisualizationAttributes,
-} from '@graphpolaris/shared/lib/data-access/store/visualizationSlice';
+import { removeVisualization, updateActiveVisualizationAttributes } from '@graphpolaris/shared/lib/data-access/store/visualizationSlice';
 import { VisualizationSettingsPropTypes, VisualizationSettingsType } from '../../common';
 
 type Props = {};