From b11f32c1ece2d4b8fbd14a6eeeacc441e1da8b3d Mon Sep 17 00:00:00 2001
From: Sjoerd <svink@graphpolaris.com>
Date: Sat, 12 Oct 2024 09:34:27 +0000
Subject: [PATCH] feat: rework of project management and permissions screen

---
 .../dbConnectionSelector.tsx                  | 258 ------------------
 .../DatabaseManagement/forms/settings.tsx     | 212 --------------
 apps/web/src/components/navbar/gp-logo.tsx    |  19 +-
 apps/web/src/components/navbar/navbar.tsx     |  84 ++----
 libs/shared/lib/components/buttons/Button.tsx |  21 +-
 libs/shared/lib/components/icon/index.tsx     |   4 +-
 libs/shared/lib/components/layout/Dialog.tsx  |  12 +-
 .../UserManagementContent.tsx                 |  96 -------
 .../shared/lib/components/tableUI/TableUI.tsx |   3 -
 libs/shared/lib/components/tabs/Tab.tsx       |  57 +++-
 .../plugins/InsertVariablesPlugin.tsx         |  66 ++---
 libs/shared/lib/data-access/api/eventBus.tsx  |   5 +-
 .../shared/lib/data-access/broker/wsSchema.ts |  19 +-
 libs/shared/lib/data-access/store/hooks.ts    |   3 +
 .../lib/data-access/store/schemaSlice.ts      |  13 +-
 libs/shared/lib/management/Explorations.tsx   |  45 +++
 .../lib/management/ManagementDialog.tsx       |  95 +++++++
 .../lib/management/ManagementTrigger.tsx      |  88 ++++++
 libs/shared/lib/management/Members.tsx        |  74 +++++
 libs/shared/lib/management/Overview.tsx       |  35 +++
 libs/shared/lib/management/Settings.tsx       |  28 ++
 libs/shared/lib/management/Workspace.tsx      |  39 +++
 .../lib/management/database/DatabaseForm.tsx  |   5 +-
 .../lib/management/database/Databases.tsx     | 203 ++++++++++++++
 .../management/database/MockSaveStates.tsx    |   8 +-
 .../management/database/UpsertDatabase.tsx    | 134 +++++++++
 libs/shared/lib/management/database/index.ts  |   2 +
 .../management/database/useHandleDatabase.ts  |  91 ++++++
 libs/shared/lib/management/index.ts           |   2 +
 libs/shared/lib/schema/panel/Schema.tsx       |  18 +-
 .../lib/vis/components/VisualizationPanel.tsx |   2 +-
 .../vis/components/VisualizationTabBar.tsx    |   4 +-
 32 files changed, 1024 insertions(+), 721 deletions(-)
 delete mode 100644 apps/web/src/components/navbar/DatabaseManagement/dbConnectionSelector.tsx
 delete mode 100644 apps/web/src/components/navbar/DatabaseManagement/forms/settings.tsx
 delete mode 100644 libs/shared/lib/components/panels/userManagementContent/UserManagementContent.tsx
 create mode 100644 libs/shared/lib/management/Explorations.tsx
 create mode 100644 libs/shared/lib/management/ManagementDialog.tsx
 create mode 100644 libs/shared/lib/management/ManagementTrigger.tsx
 create mode 100644 libs/shared/lib/management/Members.tsx
 create mode 100644 libs/shared/lib/management/Overview.tsx
 create mode 100644 libs/shared/lib/management/Settings.tsx
 create mode 100644 libs/shared/lib/management/Workspace.tsx
 rename apps/web/src/components/navbar/DatabaseManagement/forms/databaseForm.tsx => libs/shared/lib/management/database/DatabaseForm.tsx (94%)
 create mode 100644 libs/shared/lib/management/database/Databases.tsx
 rename apps/web/src/components/navbar/DatabaseManagement/forms/mockSaveStates.tsx => libs/shared/lib/management/database/MockSaveStates.tsx (93%)
 create mode 100644 libs/shared/lib/management/database/UpsertDatabase.tsx
 create mode 100644 libs/shared/lib/management/database/index.ts
 create mode 100644 libs/shared/lib/management/database/useHandleDatabase.ts
 create mode 100644 libs/shared/lib/management/index.ts

diff --git a/apps/web/src/components/navbar/DatabaseManagement/dbConnectionSelector.tsx b/apps/web/src/components/navbar/DatabaseManagement/dbConnectionSelector.tsx
deleted file mode 100644
index fabd61ac9..000000000
--- a/apps/web/src/components/navbar/DatabaseManagement/dbConnectionSelector.tsx
+++ /dev/null
@@ -1,258 +0,0 @@
-import React, { useEffect, useState, useCallback } from 'react';
-import { useAppDispatch, useSchemaGraph, useSessionCache, useAuthCache } from '@graphpolaris/shared/lib/data-access';
-import { deleteSaveState, selectSaveState } from '@graphpolaris/shared/lib/data-access/store/sessionSlice';
-import { SettingsForm } from './forms/settings';
-import { LoadingSpinner } from '@graphpolaris/shared/lib/components/LoadingSpinner';
-import { addError } from '@graphpolaris/shared/lib/data-access/store/configSlice';
-import { DropdownTrigger, DropdownContainer, DropdownItemContainer } from '@graphpolaris/shared/lib/components/dropdowns';
-import { clearQB } from '@graphpolaris/shared/lib/data-access/store/querybuilderSlice';
-import { clearSchema } from '@graphpolaris/shared/lib/data-access/store/schemaSlice';
-import { DatabaseStatus, SaveStateI, nilUUID, wsDeleteState } from '@graphpolaris/shared/lib/data-access/broker';
-import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@graphpolaris/shared/lib/components/tooltip';
-import { Icon } from '@graphpolaris/shared';
-
-export default function DatabaseSelector({}) {
-  const dispatch = useAppDispatch();
-  const session = useSessionCache();
-  const schemaGraph = useSchemaGraph();
-  const authCache = useAuthCache();
-  const [hovered, setHovered] = useState<string | null>(null);
-  const [connecting, setConnecting] = useState<boolean>(false);
-  const [dbSelectionMenuOpen, setDbSelectionMenuOpen] = useState<boolean>(false);
-  const [settingsMenuOpen, setSettingsMenuOpen] = useState<'add' | 'update' | undefined>(undefined);
-  const [selectedSaveState, setSelectedSaveState] = useState<SaveStateI | null>(null);
-
-  useEffect(() => {
-    if (
-      (!session.fetchingSaveStates &&
-        session.saveStates &&
-        Object.keys(session.saveStates).length === 0 &&
-        settingsMenuOpen === undefined) ||
-      session.currentSaveState === nilUUID
-    ) {
-      setSettingsMenuOpen('add');
-    }
-  }, [session, settingsMenuOpen]);
-
-  useEffect(() => {
-    setConnecting(false);
-  }, [schemaGraph]);
-
-  useEffect(() => {
-    let timeoutId: ReturnType<typeof setTimeout>;
-    if (connecting) {
-      timeoutId = setTimeout(() => {
-        dispatch(addError("Couldn't establish connection"));
-        setConnecting(false);
-        dispatch(selectSaveState(undefined));
-        dispatch(clearQB());
-        dispatch(clearSchema());
-      }, 10000);
-    }
-
-    return () => {
-      if (timeoutId) clearTimeout(timeoutId);
-    };
-  }, [connecting]);
-
-  return (
-    <div className="menu-walkthrough">
-      <TooltipProvider delayDuration={1000}>
-        {settingsMenuOpen !== undefined && authCache.authorization.savestate.W && (
-          <SettingsForm
-            open={settingsMenuOpen}
-            saveState={settingsMenuOpen === 'update' ? selectedSaveState : null}
-            disableCancel={
-              (session.saveStates && Object.keys(session.saveStates).length === 0) ||
-              session.currentSaveState === '00000000-0000-0000-0000-000000000000'
-            }
-            onClose={() => {
-              setSettingsMenuOpen(undefined);
-            }}
-          />
-        )}
-        <DropdownContainer
-          open={dbSelectionMenuOpen}
-          onOpenChange={(ret) => {
-            if (!ret) {
-              if (session.saveStates && Object.keys(session.saveStates).length === 0) setSettingsMenuOpen('add');
-              else setDbSelectionMenuOpen(!dbSelectionMenuOpen);
-            } else {
-              setDbSelectionMenuOpen(true);
-            }
-          }}
-        >
-          <DropdownTrigger
-            onClick={() => {
-              if (
-                connecting ||
-                authCache.authentication?.authenticated === false ||
-                !!authCache.authentication?.roomID ||
-                authCache.authorization.savestate.W
-              ) {
-                setDbSelectionMenuOpen(!dbSelectionMenuOpen);
-              }
-            }}
-            className="w-[18rem]"
-            size="md"
-            noDropdownArrow={
-              connecting ||
-              authCache.authentication?.authenticated === false ||
-              !!authCache.authentication?.roomID ||
-              !authCache.authorization.savestate.W
-            }
-            title={
-              <div className="flex items-center">
-                {connecting && session.currentSaveState && session.currentSaveState in session.saveStates ? (
-                  <>
-                    <LoadingSpinner />
-                    <p className="ml-2 truncate">Connecting to {session.saveStates[session.currentSaveState].name}</p>
-                  </>
-                ) : session.currentSaveState && session.currentSaveState in session.saveStates && session.currentSaveState !== nilUUID ? (
-                  <div className="flex">
-                    <Icon component="icon-[ic--outline-storage]" size={20} className=" self-center" />
-                    <span className="relative">
-                      <span
-                        className={`absolute bottom-0.5 right-3 h-2 w-2 border border-light  rounded-full ${session.testedSaveState[session.currentSaveState] === DatabaseStatus.tested ? 'bg-success-500' : 'bg-danger-500'}`}
-                      />
-                    </span>
-                    <p className="ml-2 truncate">{session.saveStates[session.currentSaveState].name}</p>
-                  </div>
-                ) : session.saveStates === undefined ? (
-                  <>
-                    <LoadingSpinner />
-                    <p className="ml-2">Retrieving databases</p>
-                  </>
-                ) : Object.keys(session.saveStates).length === 0 || session.currentSaveState === nilUUID ? (
-                  <>
-                    <p className="ml-2">Add your first Database</p>
-                  </>
-                ) : (
-                  <>
-                    <div className="h-2 w-2 rounded-full bg-secondary-500" />
-                    <p className="ml-2">Select a database</p>
-                  </>
-                )}
-              </div>
-            }
-          />
-
-          {session.saveStates !== undefined && (
-            <DropdownItemContainer>
-              <li
-                className="flex items-center p-2 hover:bg-secondary-50 cursor-pointer"
-                onClick={(e) => {
-                  e.preventDefault();
-                  setDbSelectionMenuOpen(false);
-                  setConnecting(false);
-                  setSettingsMenuOpen('add');
-                }}
-              >
-                {session.saveStates && Object.keys(session.saveStates).length === 0 ? (
-                  <>
-                    <Icon component="icon-[ic--baseline-add]" size={24} />
-                    <p className="ml-2">Add your first database</p>
-                  </>
-                ) : (
-                  <>
-                    <Icon component="icon-[ic--baseline-add]" size={24} />
-                    <p className="ml-2">Add database</p>
-                  </>
-                )}
-              </li>
-              {Object.values(session.saveStates)
-                .filter((save) => save.id !== nilUUID)
-                .map((save) => (
-                  <li
-                    key={save.id}
-                    className="flex justify-between items-center px-4 py-2 hover:bg-primary-100 gap-2 cursor-pointer"
-                    onClick={(e) => {
-                      if (save.id !== session.currentSaveState) {
-                        e.preventDefault();
-                        setDbSelectionMenuOpen(false);
-                        setConnecting(true);
-                        dispatch(selectSaveState(save.id));
-                        dispatch(clearQB());
-                        dispatch(clearSchema());
-                      } else {
-                        setDbSelectionMenuOpen(false);
-                      }
-                    }}
-                    onMouseEnter={() => setHovered(save.id)}
-                    onMouseLeave={() => setHovered(null)}
-                  >
-                    <Tooltip placement={'left'}>
-                      <TooltipTrigger>
-                        <div
-                          className={`h-[8px] w-[8px] rounded-full shrink-0 ${
-                            session.testedSaveState[save.id] === DatabaseStatus.tested ? 'bg-success-500' : 'bg-danger-500'
-                          }`}
-                        />
-                      </TooltipTrigger>
-                      <TooltipContent>
-                        <p>
-                          {session.testedSaveState[save.id] === DatabaseStatus.tested
-                            ? 'Database connection tested'
-                            : 'Something went wrong when trying to connect'}
-                        </p>
-                      </TooltipContent>
-                    </Tooltip>
-                    <div className="w-full shrink min-w-0 flex flex-col">
-                      <p className="truncate w-full shrink-0 min-w-0">{save.name}</p>
-                      <p className="bg-light text-2xs text-secondary-500 truncate w-fit shrink-0 min-w-0 max-w-full h-full border border-secondary-200 rounded-sm p-0.5">
-                        {save.db.protocol}
-                        {save.db.url}
-                      </p>
-                    </div>
-                    <div className={`flex items-center ml-2 ${hovered === save.id ? 'display' : 'invisible'}`}>
-                      <div
-                        className="text-secondary-700 hover:text-secondary-400 transition-colors duration-300"
-                        onClick={(e) => {
-                          e.preventDefault();
-                          e.stopPropagation();
-                          setSettingsMenuOpen('update');
-                          setSelectedSaveState(save);
-                        }}
-                      >
-                        <Tooltip>
-                          <TooltipTrigger>
-                            <Icon component="icon-[ic--baseline-settings]" size={24} />
-                          </TooltipTrigger>
-                          <TooltipContent>
-                            <p>Change the connection details</p>
-                          </TooltipContent>
-                        </Tooltip>
-                      </div>
-                      <div
-                        className="text-secondary-700 hover:text-secondary-400 transition-colors duration-300"
-                        onClick={(e) => {
-                          e.preventDefault();
-                          e.stopPropagation();
-                          setDbSelectionMenuOpen(false);
-                          if (session.currentSaveState === save.id) {
-                            dispatch(clearQB());
-                            dispatch(clearSchema());
-                          }
-                          wsDeleteState(save.id);
-                          dispatch(deleteSaveState(save.id));
-                        }}
-                      >
-                        <Tooltip>
-                          <TooltipTrigger>
-                            <Icon component="icon-[ic--baseline-delete]" size={24} />
-                          </TooltipTrigger>
-                          <TooltipContent>
-                            <p>Delete the database</p>
-                          </TooltipContent>
-                        </Tooltip>
-                      </div>
-                    </div>
-                  </li>
-                ))}
-            </DropdownItemContainer>
-          )}
-        </DropdownContainer>
-      </TooltipProvider>
-    </div>
-  );
-}
diff --git a/apps/web/src/components/navbar/DatabaseManagement/forms/settings.tsx b/apps/web/src/components/navbar/DatabaseManagement/forms/settings.tsx
deleted file mode 100644
index 1877544da..000000000
--- a/apps/web/src/components/navbar/DatabaseManagement/forms/settings.tsx
+++ /dev/null
@@ -1,212 +0,0 @@
-import React, { useEffect, useRef, useState } from 'react';
-import {
-  useAppDispatch,
-  SaveStateI,
-  wsUpdateState,
-  wsTestDatabaseConnection,
-  wsCreateState,
-  useAuthCache,
-  nilUUID,
-} from '@graphpolaris/shared/lib/data-access';
-import { Dialog, DialogContent } from '@graphpolaris/shared/lib/components/layout';
-import { Button } from '@graphpolaris/shared/lib/components/buttons';
-import { useImmer } from 'use-immer';
-import { addSaveState, testedSaveState } from '@graphpolaris/shared/lib/data-access/store/sessionSlice';
-import { DatabaseForm, INITIAL_SAVE_STATE } from './databaseForm';
-import { SampleDatabaseSelector } from './mockSaveStates';
-import { Icon } from '@graphpolaris/shared';
-
-type Connection = {
-  updating: boolean;
-  status: null | string;
-  verified: boolean | null;
-};
-
-export const SettingsForm = (props: { onClose(): void; open: 'add' | 'update'; saveState: SaveStateI | null; disableCancel?: boolean }) => {
-  const dispatch = useAppDispatch();
-  const ref = useRef<HTMLDialogElement>(null);
-  const auth = useAuthCache();
-  const [formData, setFormData] = useImmer(
-    props.saveState && props.open === 'update' ? props.saveState : { ...INITIAL_SAVE_STATE, user_id: auth.authentication?.userID || '' },
-  );
-  const [hasError, setHasError] = useState(false);
-  const [sampleDataPanel, setSampleDataPanel] = useState<boolean | null>(false);
-  const [connection, setConnection] = useState<Connection>({
-    updating: false,
-    status: null,
-    verified: null,
-  });
-  const formTitle = props.open === 'add' ? 'Add' : 'Update';
-
-  useEffect(() => {
-    if (props.saveState && props.open === 'update') {
-      setFormData(props.saveState);
-      setSampleDataPanel(null);
-    } else {
-      setSampleDataPanel(false);
-    }
-  }, [props.saveState]);
-
-  async function handleSubmit(saveStateData?: SaveStateI, forceAdd: boolean = false): Promise<void> {
-    if (!saveStateData) saveStateData = formData;
-    setConnection(() => ({
-      updating: true,
-      status: 'Testing database connection',
-      verified: null,
-    }));
-
-    wsTestDatabaseConnection(saveStateData.db, (data) => {
-      if (!saveStateData) {
-        console.error('formData is null');
-        return;
-      }
-      if (!auth.authentication) {
-        console.error('auth is null');
-        return;
-      }
-      if (saveStateData.user_id !== auth.authentication.userID && auth.authentication.userID) {
-        console.error('user_id is not equal to auth.userID');
-        saveStateData.user_id = auth.authentication.userID;
-      }
-      if (data && data.status === 'success') {
-        setConnection((prevState) => ({
-          updating: false,
-          status: 'Database connection verified',
-          verified: true,
-        }));
-        if (props.open === 'add' || forceAdd) {
-          wsCreateState(saveStateData, (_data) => {
-            dispatch(addSaveState(_data));
-            dispatch(testedSaveState(_data.id));
-            closeDialog();
-          });
-        } else {
-          dispatch(testedSaveState(data.saveStateID));
-          wsUpdateState(saveStateData, (_data) => {
-            dispatch(addSaveState(_data));
-            closeDialog();
-          });
-        }
-      } else {
-        setConnection((prevState) => ({
-          updating: false,
-          status: 'Database connection test failed',
-          verified: false,
-        }));
-      }
-    });
-  }
-
-  function handlePortChanged(port: string): void {
-    if (!isNaN(Number(port)))
-      setFormData((draft) => {
-        draft.db.port = Number(port);
-        return draft;
-      });
-  }
-
-  function closeDialog(): void {
-    setConnection({
-      updating: false,
-      status: null,
-      verified: null,
-    });
-    setFormData({ ...INITIAL_SAVE_STATE, user_id: auth.authentication?.userID || '' });
-    ref.current?.close();
-    props.onClose();
-  }
-
-  return (
-    <Dialog
-      open={!!props.open}
-      onOpenChange={(ret) => {
-        if (!ret) props.onClose;
-      }}
-    >
-      <DialogContent className="lg:min-w-[50rem]">
-        <div className="flex justify-between align-center m-2">
-          <h2 className="text-xl font-bold">{formTitle} Database Connection</h2>
-          <div>
-            {sampleDataPanel === true ? (
-              <Button variant="outline" label="Go back" onClick={() => setSampleDataPanel(false)} />
-            ) : sampleDataPanel === false ? (
-              <>
-                <h1 className="font-light text-xs">No data?</h1>
-                <p className="font-light text-sm cursor-pointer underline" onClick={() => setSampleDataPanel(true)}>
-                  Try sample data
-                </p>
-              </>
-            ) : (
-              ''
-            )}
-          </div>
-        </div>
-
-        <>
-          {sampleDataPanel === true ? (
-            <SampleDatabaseSelector
-              onClick={(data) => {
-                setHasError(false);
-                handleSubmit({ ...data, user_id: auth.authentication?.userID || '' });
-              }}
-            />
-          ) : (
-            <DatabaseForm
-              data={formData}
-              onChange={(data: SaveStateI, error: boolean) => {
-                setFormData({ ...data, id: formData.id });
-                setHasError(error);
-              }}
-            />
-          )}
-
-          {!(connection.status === null) && (
-            <div className={`flex flex-col justify-center items-center`}>
-              <div className="flex justify-center items-center">
-                {connection.verified === false && <Icon component="icon-[ic--baseline-error-outline]" className="text-secondary-400" />}
-                <p className="font-light text-sm	text-secondary-400	">{connection.status}</p>
-              </div>
-              {connection.verified === null && <progress className="progress w-56"></progress>}
-            </div>
-          )}
-
-          <div
-            className={`pt-4 flex flex-row gap-3 card-actions w-full justify-stretch items-center ${sampleDataPanel === true && 'hidden'}`}
-          >
-            <Button
-              variantType="primary"
-              className="flex-grow"
-              label={connection.updating ? (formTitle === 'Add' ? formTitle + 'ing...' : formTitle.slice(0, -1) + 'ing...') : formTitle}
-              onClick={(event) => {
-                event.preventDefault();
-                handleSubmit();
-              }}
-              disabled={connection.updating || hasError}
-            />
-            {props.open === 'update' && (
-              <Button
-                variantType="secondary"
-                className="flex-grow"
-                label={'Clone'}
-                onClick={(event) => {
-                  handleSubmit({ ...formData, name: formData.name + ' (copy)', id: nilUUID }, true);
-                }}
-                disabled={connection.updating || hasError}
-              />
-            )}
-            <Button
-              variant="outline"
-              className="flex-grow"
-              label="Cancel"
-              disabled={props.disableCancel}
-              onClick={(event) => {
-                event.preventDefault();
-                closeDialog();
-              }}
-            />
-          </div>
-        </>
-      </DialogContent>
-    </Dialog>
-  );
-};
diff --git a/apps/web/src/components/navbar/gp-logo.tsx b/apps/web/src/components/navbar/gp-logo.tsx
index a63b23ae1..b8b975a51 100644
--- a/apps/web/src/components/navbar/gp-logo.tsx
+++ b/apps/web/src/components/navbar/gp-logo.tsx
@@ -2,13 +2,14 @@ import React from 'react';
 
 type GpLogoProps = {
   className?: string; // `className` is optional and is of type string
+  includeText?: boolean;
 };
-const GpLogo: React.FC<GpLogoProps> = ({ className = '' }) => {
+const GpLogo: React.FC<GpLogoProps> = ({ className = '', includeText = true }) => {
   return (
     <>
       <svg
         xmlns="http://www.w3.org/2000/svg"
-        viewBox="0 0 444 80"
+        viewBox={`0 0 ${includeText ? '444' : '80'} 80`}
         fill="none"
         preserveAspectRatio="xMidYMid meet"
         className={`gp-logo ${className}`}
@@ -38,12 +39,14 @@ const GpLogo: React.FC<GpLogoProps> = ({ className = '' }) => {
         <path fill="#E29B27" d="m46.8153 55.6051 7.80257-7.80257 7.80257 7.80257-7.80257 7.80257z" />
         <path fill="#EAAE2C" d="m39.0128 63.4077 7.80257-7.80257 7.80257 7.80257-7.80257 7.80257z" />
         <path fill="#E9BE31" d="m31.2102 71.2102 7.80257-7.80257 7.80257 7.80257-7.80257 7.80257z" />
-        <path
-          fill="currentColor"
-          fillRule="evenodd"
-          d="M400.22 23.8855c.639.6389 1.42.9584 2.343.9584.887 0 1.632-.3195 2.236-.9584.639-.6389.958-1.4197.958-2.3426 0-.9228-.319-1.7037-.958-2.3426-.604-.6389-1.349-.9584-2.236-.9584-.923 0-1.704.3195-2.343.9584s-.958 1.4198-.958 2.3426c0 .9229.319 1.7037.958 2.3426Zm4.685 34.8731V29.5824h-4.845v29.1762h4.845Zm12.57-.6388c1.775.7453 3.78 1.118 6.016 1.118 2.095 0 3.94-.3549 5.538-1.0648 1.632-.7454 2.892-1.757 3.78-3.0348.887-1.2778 1.331-2.7153 1.331-4.3125-.036-1.7747-.533-3.2122-1.491-4.3126-.923-1.1003-2.041-1.9167-3.354-2.4491-1.314-.5679-3.017-1.1358-5.111-1.7037-1.669-.4614-2.982-.8696-3.94-1.2245-.923-.3905-1.704-.8874-2.343-1.4908-.603-.6389-.905-1.4375-.905-2.3959 0-1.2068.515-2.1829 1.544-2.9282 1.029-.7454 2.414-1.1181 4.153-1.1181 1.881 0 3.372.4614 4.472 1.3843 1.136.9228 1.757 2.1474 1.864 3.6736h4.844c-.141-2.8395-1.206-5.0757-3.194-6.7084-1.988-1.6327-4.596-2.4491-7.826-2.4491-2.095 0-3.958.3727-5.591 1.1181-1.633.7099-2.893 1.686-3.78 2.9283-.887 1.2423-1.331 2.6088-1.331 4.0995 0 1.8812.479 3.4075 1.438 4.5788.993 1.1358 2.165 2.0054 3.513 2.6088 1.385.5679 3.159 1.1358 5.325 1.7038 2.378.6034 4.135 1.2245 5.271 1.8634 1.135.6034 1.703 1.544 1.703 2.8218 0 1.2423-.532 2.2716-1.597 3.088-1.065.8164-2.52 1.2245-4.366 1.2245-1.987 0-3.602-.4614-4.845-1.3842-1.207-.9229-1.881-2.1119-2.023-3.5672h-5.005c.107 1.7747.675 3.3542 1.704 4.7385 1.029 1.3488 2.431 2.4136 4.206 3.1945Zm-32.431-23.799c.852-1.6683 2.058-2.9638 3.62-3.8867 1.597-.9228 3.532-1.3842 5.803-1.3842v5.0047h-1.277c-5.431 0-8.146 2.946-8.146 8.838v15.866h-4.845V29.5823h4.845v4.7385Zm-40.825 1.9168c-1.207 2.2361-1.81 4.8449-1.81 7.8264 0 2.9461.603 5.5726 1.81 7.8798 1.207 2.3071 2.857 4.0995 4.952 5.3773 2.094 1.2778 4.436 1.9167 7.027 1.9167 2.521 0 4.721-.5501 6.602-1.6505 1.917-1.1358 3.355-2.5555 4.313-4.2593v5.4307h4.898V29.5824h-4.898v5.3241c-.923-1.6682-2.325-3.0525-4.206-4.1528-1.881-1.1003-4.1-1.6505-6.655-1.6505-2.591 0-4.952.6212-7.081 1.8635-2.095 1.2423-3.745 2.9992-4.952 5.2709Zm21.563 2.1296c.887 1.6327 1.331 3.5494 1.331 5.7501 0 2.2006-.444 4.1351-1.331 5.8033-.887 1.6327-2.094 2.8928-3.62 3.7801-1.491.8519-3.142 1.2778-4.952 1.2778s-3.461-.4259-4.951-1.2778c-1.491-.8873-2.68-2.1474-3.568-3.7801-.887-1.6682-1.331-3.6204-1.331-5.8566 0-2.2006.444-4.1173 1.331-5.75.888-1.6328 2.077-2.8751 3.568-3.7269 1.49-.8519 3.141-1.2778 4.951-1.2778 1.81 0 3.461.4437 4.952 1.331 1.526.8519 2.733 2.0942 3.62 3.7269Zm-29.82-19.0073v39.3987h-4.845V19.3599h4.845Zm-33.63 38.0145c2.236 1.2423 4.721 1.8634 7.454 1.8634 2.768 0 5.288-.6211 7.56-1.8634 2.272-1.2423 4.064-2.9993 5.377-5.2709 1.349-2.3071 2.024-4.9692 2.024-7.9862 0-3.017-.657-5.6614-1.97-7.933-1.278-2.2716-3.035-4.0108-5.271-5.2176-2.236-1.2423-4.739-1.8635-7.507-1.8635-2.769 0-5.271.6212-7.507 1.8635-2.236 1.2068-4.011 2.9637-5.324 5.2709-1.278 2.2716-1.917 4.8982-1.917 7.8797 0 3.017.621 5.6791 1.863 7.9862 1.278 2.2716 3.017 4.0286 5.218 5.2709Zm12.352-3.6204c-1.526.8163-3.159 1.2245-4.898 1.2245-1.739 0-3.337-.3904-4.792-1.1713-1.455-.8164-2.627-2.0409-3.514-3.6736-.852-1.6328-1.278-3.6382-1.278-6.0163 0-2.3426.444-4.3303 1.331-5.9631.888-1.6327 2.059-2.8395 3.514-3.6204 1.491-.8163 3.124-1.2245 4.898-1.2245 1.74 0 3.355.4082 4.845 1.2245 1.491.7809 2.698 1.9877 3.621 3.6204.923 1.6328 1.384 3.6205 1.384 5.9631s-.479 4.3303-1.437 5.963c-.923 1.6327-2.148 2.8573-3.674 3.6737Zm-23.645-21.2435c0 3.088-1.064 5.6613-3.194 7.72-2.094 2.0232-5.307 3.0348-9.637 3.0348h-7.134v15.4932h-4.845V21.6493h11.979c4.189 0 7.365 1.0116 9.53 3.0347 2.201 2.0232 3.301 4.632 3.301 7.8265Zm-12.831 6.7617c2.698 0 4.685-.5857 5.963-1.757 1.278-1.1713 1.917-2.8395 1.917-5.0047 0-4.5787-2.627-6.8681-7.88-6.8681h-7.134v13.6298h7.134Zm-25.03-8.9445c-1.74-.9939-3.727-1.4908-5.963-1.4908-1.953 0-3.727.3727-5.324 1.1181-1.598.7099-2.876 1.7037-3.834 2.9815V19.3599h-7.454v39.3987h7.454V42.4667c0-2.3426.586-4.1351 1.757-5.3774 1.207-1.2778 2.84-1.9167 4.898-1.9167 2.023 0 3.621.6389 4.792 1.9167 1.171 1.2423 1.757 3.0348 1.757 5.3774v16.2919h7.454V41.4551c0-2.6621-.497-4.9337-1.491-6.8149-.958-1.9167-2.307-3.3542-4.046-4.3125Zm-51.204 3.1945c.958-1.3488 2.271-2.4669 3.939-3.3542 1.704-.9229 3.639-1.3843 5.804-1.3843 2.52 0 4.792.6212 6.815 1.8634 2.058 1.2423 3.673 3.0171 4.845 5.3242 1.206 2.2716 1.81 4.9159 1.81 7.933 0 3.017-.604 5.6968-1.81 8.0394-1.172 2.3071-2.787 4.0996-4.845 5.3774-2.023 1.2778-4.295 1.9167-6.815 1.9167-2.165 0-4.082-.4437-5.75-1.3311-1.633-.8873-2.964-2.0054-3.993-3.3542v18.2618h-7.454V29.2629h7.454v4.2593Zm15.599 10.3821c0-1.7748-.372-3.301-1.118-4.5788-.71-1.3133-1.668-2.3071-2.875-2.9815-1.171-.6744-2.449-1.0116-3.833-1.0116-1.349 0-2.627.3549-3.834 1.0648-1.171.6744-2.129 1.6682-2.875 2.9815-.709 1.3133-1.064 2.8573-1.064 4.632 0 1.7747.355 3.3187 1.064 4.632.746 1.3133 1.704 2.3249 2.875 3.0348 1.207.6744 2.485 1.0116 3.834 1.0116 1.384 0 2.662-.355 3.833-1.0648 1.207-.7099 2.165-1.7215 2.875-3.0348.746-1.3133 1.118-2.875 1.118-4.6852Zm-59.296-7.933c-1.172 2.3071-1.757 4.9514-1.757 7.933 0 3.017.585 5.6968 1.757 8.0394 1.206 2.3071 2.821 4.0996 4.845 5.3774 2.058 1.2778 4.33 1.9167 6.815 1.9167 2.2 0 4.135-.4437 5.803-1.3311 1.704-.9228 3.035-2.0764 3.993-3.4607v4.3126h7.507V29.2629h-7.507v4.206c-.994-1.3487-2.325-2.4668-3.993-3.3542-1.633-.8873-3.55-1.331-5.75-1.331-2.52 0-4.81.6212-6.868 1.8634-2.024 1.2423-3.639 3.0171-4.845 5.3242Zm20.391 3.4074c.71 1.2778 1.065 2.8218 1.065 4.632 0 1.8102-.355 3.372-1.065 4.6853-.71 1.2778-1.668 2.2716-2.875 2.9815-1.207.6744-2.502 1.0116-3.887 1.0116-1.348 0-2.626-.355-3.833-1.0648-1.171-.7099-2.13-1.7215-2.875-3.0348-.71-1.3488-1.065-2.9105-1.065-4.6852 0-1.7748.355-3.301 1.065-4.5788.745-1.3133 1.704-2.3071 2.875-2.9815 1.171-.6744 2.449-1.0116 3.833-1.0116 1.385 0 2.68.3549 3.887 1.0648 1.207.6744 2.165 1.6682 2.875 2.9815Zm-34.303-5.537c.958-1.5617 2.2-2.7863 3.727-3.6736 1.561-.8874 3.336-1.3311 5.324-1.3311v7.8265h-1.97c-2.343 0-4.117.5502-5.324 1.6505-1.172 1.1003-1.757 3.017-1.757 5.7501v14.6946h-7.454V29.263h7.454v4.5787Zm-25.96-4.6321c1.491.8164 2.663 2.0055 3.514 3.5672h8.572c-1.171-3.6914-3.301-6.5487-6.389-8.5719-3.088-2.0586-6.726-3.088-10.914-3.088-3.55 0-6.78.8164-9.69 2.4491-2.875 1.5973-5.1468 3.8512-6.815 6.7617-1.6328 2.875-2.4491 6.1405-2.4491 9.7964s.8163 6.9214 2.4491 9.7964c1.6682 2.8751 3.94 5.129 6.815 6.7617 2.91 1.5972 6.158 2.3958 9.743 2.3958 3.195 0 6.07-.6566 8.625-1.9699 2.591-1.3488 4.703-3.1235 6.336-5.3241 1.633-2.2007 2.697-4.5965 3.194-7.1876v-6.4955h-20.125v5.6969h12.778c-.568 2.6975-1.757 4.8094-3.567 6.3357-1.81 1.4908-4.135 2.2361-6.975 2.2361-2.307 0-4.33-.4969-6.069-1.4907-1.739-.9939-3.106-2.4136-4.1-4.2593-.958-1.8457-1.437-4.0109-1.437-6.4955 0-2.4136.479-4.5432 1.437-6.389.958-1.8456 2.29-3.2654 3.993-4.2593 1.704-.9938 3.656-1.4907 5.857-1.4907 1.987 0 3.727.4082 5.217 1.2245Z"
-          clipRule="evenodd"
-        />
+        {includeText && (
+          <path
+            fill="currentColor"
+            fillRule="evenodd"
+            d="M400.22 23.8855c.639.6389 1.42.9584 2.343.9584.887 0 1.632-.3195 2.236-.9584.639-.6389.958-1.4197.958-2.3426 0-.9228-.319-1.7037-.958-2.3426-.604-.6389-1.349-.9584-2.236-.9584-.923 0-1.704.3195-2.343.9584s-.958 1.4198-.958 2.3426c0 .9229.319 1.7037.958 2.3426Zm4.685 34.8731V29.5824h-4.845v29.1762h4.845Zm12.57-.6388c1.775.7453 3.78 1.118 6.016 1.118 2.095 0 3.94-.3549 5.538-1.0648 1.632-.7454 2.892-1.757 3.78-3.0348.887-1.2778 1.331-2.7153 1.331-4.3125-.036-1.7747-.533-3.2122-1.491-4.3126-.923-1.1003-2.041-1.9167-3.354-2.4491-1.314-.5679-3.017-1.1358-5.111-1.7037-1.669-.4614-2.982-.8696-3.94-1.2245-.923-.3905-1.704-.8874-2.343-1.4908-.603-.6389-.905-1.4375-.905-2.3959 0-1.2068.515-2.1829 1.544-2.9282 1.029-.7454 2.414-1.1181 4.153-1.1181 1.881 0 3.372.4614 4.472 1.3843 1.136.9228 1.757 2.1474 1.864 3.6736h4.844c-.141-2.8395-1.206-5.0757-3.194-6.7084-1.988-1.6327-4.596-2.4491-7.826-2.4491-2.095 0-3.958.3727-5.591 1.1181-1.633.7099-2.893 1.686-3.78 2.9283-.887 1.2423-1.331 2.6088-1.331 4.0995 0 1.8812.479 3.4075 1.438 4.5788.993 1.1358 2.165 2.0054 3.513 2.6088 1.385.5679 3.159 1.1358 5.325 1.7038 2.378.6034 4.135 1.2245 5.271 1.8634 1.135.6034 1.703 1.544 1.703 2.8218 0 1.2423-.532 2.2716-1.597 3.088-1.065.8164-2.52 1.2245-4.366 1.2245-1.987 0-3.602-.4614-4.845-1.3842-1.207-.9229-1.881-2.1119-2.023-3.5672h-5.005c.107 1.7747.675 3.3542 1.704 4.7385 1.029 1.3488 2.431 2.4136 4.206 3.1945Zm-32.431-23.799c.852-1.6683 2.058-2.9638 3.62-3.8867 1.597-.9228 3.532-1.3842 5.803-1.3842v5.0047h-1.277c-5.431 0-8.146 2.946-8.146 8.838v15.866h-4.845V29.5823h4.845v4.7385Zm-40.825 1.9168c-1.207 2.2361-1.81 4.8449-1.81 7.8264 0 2.9461.603 5.5726 1.81 7.8798 1.207 2.3071 2.857 4.0995 4.952 5.3773 2.094 1.2778 4.436 1.9167 7.027 1.9167 2.521 0 4.721-.5501 6.602-1.6505 1.917-1.1358 3.355-2.5555 4.313-4.2593v5.4307h4.898V29.5824h-4.898v5.3241c-.923-1.6682-2.325-3.0525-4.206-4.1528-1.881-1.1003-4.1-1.6505-6.655-1.6505-2.591 0-4.952.6212-7.081 1.8635-2.095 1.2423-3.745 2.9992-4.952 5.2709Zm21.563 2.1296c.887 1.6327 1.331 3.5494 1.331 5.7501 0 2.2006-.444 4.1351-1.331 5.8033-.887 1.6327-2.094 2.8928-3.62 3.7801-1.491.8519-3.142 1.2778-4.952 1.2778s-3.461-.4259-4.951-1.2778c-1.491-.8873-2.68-2.1474-3.568-3.7801-.887-1.6682-1.331-3.6204-1.331-5.8566 0-2.2006.444-4.1173 1.331-5.75.888-1.6328 2.077-2.8751 3.568-3.7269 1.49-.8519 3.141-1.2778 4.951-1.2778 1.81 0 3.461.4437 4.952 1.331 1.526.8519 2.733 2.0942 3.62 3.7269Zm-29.82-19.0073v39.3987h-4.845V19.3599h4.845Zm-33.63 38.0145c2.236 1.2423 4.721 1.8634 7.454 1.8634 2.768 0 5.288-.6211 7.56-1.8634 2.272-1.2423 4.064-2.9993 5.377-5.2709 1.349-2.3071 2.024-4.9692 2.024-7.9862 0-3.017-.657-5.6614-1.97-7.933-1.278-2.2716-3.035-4.0108-5.271-5.2176-2.236-1.2423-4.739-1.8635-7.507-1.8635-2.769 0-5.271.6212-7.507 1.8635-2.236 1.2068-4.011 2.9637-5.324 5.2709-1.278 2.2716-1.917 4.8982-1.917 7.8797 0 3.017.621 5.6791 1.863 7.9862 1.278 2.2716 3.017 4.0286 5.218 5.2709Zm12.352-3.6204c-1.526.8163-3.159 1.2245-4.898 1.2245-1.739 0-3.337-.3904-4.792-1.1713-1.455-.8164-2.627-2.0409-3.514-3.6736-.852-1.6328-1.278-3.6382-1.278-6.0163 0-2.3426.444-4.3303 1.331-5.9631.888-1.6327 2.059-2.8395 3.514-3.6204 1.491-.8163 3.124-1.2245 4.898-1.2245 1.74 0 3.355.4082 4.845 1.2245 1.491.7809 2.698 1.9877 3.621 3.6204.923 1.6328 1.384 3.6205 1.384 5.9631s-.479 4.3303-1.437 5.963c-.923 1.6327-2.148 2.8573-3.674 3.6737Zm-23.645-21.2435c0 3.088-1.064 5.6613-3.194 7.72-2.094 2.0232-5.307 3.0348-9.637 3.0348h-7.134v15.4932h-4.845V21.6493h11.979c4.189 0 7.365 1.0116 9.53 3.0347 2.201 2.0232 3.301 4.632 3.301 7.8265Zm-12.831 6.7617c2.698 0 4.685-.5857 5.963-1.757 1.278-1.1713 1.917-2.8395 1.917-5.0047 0-4.5787-2.627-6.8681-7.88-6.8681h-7.134v13.6298h7.134Zm-25.03-8.9445c-1.74-.9939-3.727-1.4908-5.963-1.4908-1.953 0-3.727.3727-5.324 1.1181-1.598.7099-2.876 1.7037-3.834 2.9815V19.3599h-7.454v39.3987h7.454V42.4667c0-2.3426.586-4.1351 1.757-5.3774 1.207-1.2778 2.84-1.9167 4.898-1.9167 2.023 0 3.621.6389 4.792 1.9167 1.171 1.2423 1.757 3.0348 1.757 5.3774v16.2919h7.454V41.4551c0-2.6621-.497-4.9337-1.491-6.8149-.958-1.9167-2.307-3.3542-4.046-4.3125Zm-51.204 3.1945c.958-1.3488 2.271-2.4669 3.939-3.3542 1.704-.9229 3.639-1.3843 5.804-1.3843 2.52 0 4.792.6212 6.815 1.8634 2.058 1.2423 3.673 3.0171 4.845 5.3242 1.206 2.2716 1.81 4.9159 1.81 7.933 0 3.017-.604 5.6968-1.81 8.0394-1.172 2.3071-2.787 4.0996-4.845 5.3774-2.023 1.2778-4.295 1.9167-6.815 1.9167-2.165 0-4.082-.4437-5.75-1.3311-1.633-.8873-2.964-2.0054-3.993-3.3542v18.2618h-7.454V29.2629h7.454v4.2593Zm15.599 10.3821c0-1.7748-.372-3.301-1.118-4.5788-.71-1.3133-1.668-2.3071-2.875-2.9815-1.171-.6744-2.449-1.0116-3.833-1.0116-1.349 0-2.627.3549-3.834 1.0648-1.171.6744-2.129 1.6682-2.875 2.9815-.709 1.3133-1.064 2.8573-1.064 4.632 0 1.7747.355 3.3187 1.064 4.632.746 1.3133 1.704 2.3249 2.875 3.0348 1.207.6744 2.485 1.0116 3.834 1.0116 1.384 0 2.662-.355 3.833-1.0648 1.207-.7099 2.165-1.7215 2.875-3.0348.746-1.3133 1.118-2.875 1.118-4.6852Zm-59.296-7.933c-1.172 2.3071-1.757 4.9514-1.757 7.933 0 3.017.585 5.6968 1.757 8.0394 1.206 2.3071 2.821 4.0996 4.845 5.3774 2.058 1.2778 4.33 1.9167 6.815 1.9167 2.2 0 4.135-.4437 5.803-1.3311 1.704-.9228 3.035-2.0764 3.993-3.4607v4.3126h7.507V29.2629h-7.507v4.206c-.994-1.3487-2.325-2.4668-3.993-3.3542-1.633-.8873-3.55-1.331-5.75-1.331-2.52 0-4.81.6212-6.868 1.8634-2.024 1.2423-3.639 3.0171-4.845 5.3242Zm20.391 3.4074c.71 1.2778 1.065 2.8218 1.065 4.632 0 1.8102-.355 3.372-1.065 4.6853-.71 1.2778-1.668 2.2716-2.875 2.9815-1.207.6744-2.502 1.0116-3.887 1.0116-1.348 0-2.626-.355-3.833-1.0648-1.171-.7099-2.13-1.7215-2.875-3.0348-.71-1.3488-1.065-2.9105-1.065-4.6852 0-1.7748.355-3.301 1.065-4.5788.745-1.3133 1.704-2.3071 2.875-2.9815 1.171-.6744 2.449-1.0116 3.833-1.0116 1.385 0 2.68.3549 3.887 1.0648 1.207.6744 2.165 1.6682 2.875 2.9815Zm-34.303-5.537c.958-1.5617 2.2-2.7863 3.727-3.6736 1.561-.8874 3.336-1.3311 5.324-1.3311v7.8265h-1.97c-2.343 0-4.117.5502-5.324 1.6505-1.172 1.1003-1.757 3.017-1.757 5.7501v14.6946h-7.454V29.263h7.454v4.5787Zm-25.96-4.6321c1.491.8164 2.663 2.0055 3.514 3.5672h8.572c-1.171-3.6914-3.301-6.5487-6.389-8.5719-3.088-2.0586-6.726-3.088-10.914-3.088-3.55 0-6.78.8164-9.69 2.4491-2.875 1.5973-5.1468 3.8512-6.815 6.7617-1.6328 2.875-2.4491 6.1405-2.4491 9.7964s.8163 6.9214 2.4491 9.7964c1.6682 2.8751 3.94 5.129 6.815 6.7617 2.91 1.5972 6.158 2.3958 9.743 2.3958 3.195 0 6.07-.6566 8.625-1.9699 2.591-1.3488 4.703-3.1235 6.336-5.3241 1.633-2.2007 2.697-4.5965 3.194-7.1876v-6.4955h-20.125v5.6969h12.778c-.568 2.6975-1.757 4.8094-3.567 6.3357-1.81 1.4908-4.135 2.2361-6.975 2.2361-2.307 0-4.33-.4969-6.069-1.4907-1.739-.9939-3.106-2.4136-4.1-4.2593-.958-1.8457-1.437-4.0109-1.437-6.4955 0-2.4136.479-4.5432 1.437-6.389.958-1.8456 2.29-3.2654 3.993-4.2593 1.704-.9938 3.656-1.4907 5.857-1.4907 1.987 0 3.727.4082 5.217 1.2245Z"
+            clipRule="evenodd"
+          />
+        )}
       </svg>
     </>
   );
diff --git a/apps/web/src/components/navbar/navbar.tsx b/apps/web/src/components/navbar/navbar.tsx
index 435a06eca..e5512cb2c 100644
--- a/apps/web/src/components/navbar/navbar.tsx
+++ b/apps/web/src/components/navbar/navbar.tsx
@@ -10,23 +10,24 @@
  * See testing plan for more details.*/
 import React, { useState, useRef, useEffect, useCallback } from 'react';
 import { useAuthCache, useAuthentication } from '@graphpolaris/shared/lib/data-access';
-import DatabaseSelector from './DatabaseManagement/dbConnectionSelector';
 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 { Dialog, DialogContent, DialogTrigger } from '@graphpolaris/shared/lib/components/layout/Dialog';
-import { UserManagementContent } from '@graphpolaris/shared/lib/components/panels/userManagementContent/UserManagementContent';
-import { addInfo } from '@graphpolaris/shared/lib/data-access/store/configSlice';
 import { showManagePermissions, showSharableExploration } from 'config';
+import { Button, Dialog, DialogContent, DialogTrigger, useActiveSaveStateAuthorization, useSessionCache } 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);
   const auth = useAuthentication();
   const authCache = useAuthCache();
+  const authorization = useActiveSaveStateAuthorization();
   const [menuOpen, setMenuOpen] = useState(false);
-  const dispatch = useDispatch();
   const buildInfo = import.meta.env.GRAPHPOLARIS_VERSION;
+  const [managementOpen, setManagementOpen] = useState<boolean>(false);
+  const [current, setCurrent] = useState<ManagementViews>('overview');
 
   useEffect(() => {
     const handleClickOutside = (event: MouseEvent) => {
@@ -40,43 +41,12 @@ export const Navbar = () => {
     };
   }, [menuOpen]);
 
-  // const { canRead, canWrite } = useCheckPermissionPolicy();
-  const [readAllowed, setReadAllowed] = useState(false);
-  const [writeAllowed, setWriteAllowed] = useState(false);
-  // const resource = 'policy';
-
-  // const checkReadPermission = useCallback(async () => {
-  //   const result = await canRead(resource);
-  //   setReadAllowed(result);
-  // }, [canRead]);
-
-  // const checkWritePermission = useCallback(async () => {
-  //   const result = await canWrite(resource);
-  //   setWriteAllowed(result);
-  // }, [canWrite]);
-
-  // useEffect(() => {
-  //   checkReadPermission();
-  // }, [checkReadPermission]);
-
-  // useEffect(() => {
-  //   checkWritePermission();
-  // }, [checkWritePermission]);
-
-  const handleConfirmUsers = (users: { name: string; email: string; type: string }[]) => {
-    //TODO !FIXME: when the user clicks on confirm, users state is ready to be sent to backend
-  };
-
-  const handleClickShareLink = () => {
-    //TODO !FIXME: add copy link to clipoard functionality
-    dispatch(addInfo('Link copied to clipboard'));
-  };
   return (
-    <nav className="w-full px-4 h-12 flex flex-row items-center gap-2 md:gap-3 lg:gap-4">
-      <a href="https://graphpolaris.com/" target="_blank" className="shrink-0 text-dark">
-        <GpLogo className="h-7" />
-      </a>
-      <DatabaseSelector />
+    <nav className="w-full px-2 h-12 flex flex-row items-center gap-2 md:gap-3 lg:gap-4">
+      <GpLogo className="h-7" includeText={false} />
+      <ManagementTrigger managementOpen={managementOpen} setManagementOpen={setManagementOpen} current={current} setCurrent={setCurrent} />
+
+      <Button label="Share" variantType="primary" size="sm" onClick={() => auth.newShareRoom()} />
       <div className="ml-auto">
         <div className="w-fit" ref={dropdownRef}>
           <Popover>
@@ -105,10 +75,22 @@ export const Navbar = () => {
                       }}
                     />
                   )}
+                  {authCache.authorization?.savestate?.W && authorization.database.W && (
+                    <DropdownItem
+                      value="Viewer Permissions"
+                      onClick={() => {
+                        setManagementOpen(true);
+                        setCurrent('members');
+                      }}
+                    />
+                  )}
                   <DropdownItem value="Settings" onClick={() => {}} />
-                  <DropdownItem value="Log out" onClick={() => {
-                    location.replace(`${import.meta.env['GP_AUTH_URL']}/flows/-/default/invalidation/`)
-                  }} />
+                  <DropdownItem
+                    value="Log out"
+                    onClick={() => {
+                      location.replace(`${import.meta.env['GP_AUTH_URL']}/flows/-/default/invalidation/`);
+                    }}
+                  />
                 </>
               ) : (
                 <>
@@ -123,20 +105,6 @@ export const Navbar = () => {
               <div className="p-2 border-t">
                 <h3 className="text-xs">Version: {buildInfo}</h3>
               </div>
-              {showManagePermissions() && writeAllowed && (
-                <>
-                  <Dialog>
-                    <DialogTrigger className="ml-2 text-sm hover:bg-secondary-200">Manage Viewers Permission</DialogTrigger>
-                    <DialogContent>
-                      <UserManagementContent
-                        sessionId={authCache.authentication?.sessionID ?? ''}
-                        onConfirm={handleConfirmUsers}
-                        onClickShareLink={handleClickShareLink}
-                      />
-                    </DialogContent>
-                  </Dialog>
-                </>
-              )}
             </PopoverContent>
           </Popover>
         </div>
diff --git a/libs/shared/lib/components/buttons/Button.tsx b/libs/shared/lib/components/buttons/Button.tsx
index 639e7f9c6..3d7df746c 100644
--- a/libs/shared/lib/components/buttons/Button.tsx
+++ b/libs/shared/lib/components/buttons/Button.tsx
@@ -3,7 +3,7 @@ import styles from './buttons.module.scss';
 import { Icon } from '../icon';
 import { Tooltip, TooltipContent, TooltipTrigger } from '../tooltip';
 
-type ButtonProps = {
+export type ButtonProps = {
   as?: 'button' | 'a' | 'div';
   variantType?: 'primary' | 'secondary' | 'danger';
   variant?: 'solid' | 'outline' | 'ghost';
@@ -33,6 +33,25 @@ type ButtonProps = {
   onMouseLeaveCapture?: (e: any) => void;
   onMouseOverCapture?: (e: any) => void;
   onMouseOutCapture?: (e: any) => void;
+
+  // Drag and Drop
+  onDragStart?: (e: any) => void;
+  onDrag?: (e: any) => void;
+  onDragEnd?: (e: any) => void;
+  onDragEnter?: (e: any) => void;
+  onDragExit?: (e: any) => void;
+  onDragLeave?: (e: any) => void;
+  onDragOver?: (e: any) => void;
+  onDragStartCapture?: (e: any) => void;
+  onDragCapture?: (e: any) => void;
+  onDragEndCapture?: (e: any) => void;
+  onDragEnterCapture?: (e: any) => void;
+  onDragExitCapture?: (e: any) => void;
+  onDragLeaveCapture?: (e: any) => void;
+  onDragOverCapture?: (e: any) => void;
+  onDrop?: (e: any) => void;
+  onDropCapture?: (e: any) => void;
+  draggable?: boolean;
 };
 
 export const Button = React.forwardRef<HTMLButtonElement | HTMLAnchorElement | HTMLDivElement, ButtonProps>(
diff --git a/libs/shared/lib/components/icon/index.tsx b/libs/shared/lib/components/icon/index.tsx
index 67b824fcc..f208efb30 100644
--- a/libs/shared/lib/components/icon/index.tsx
+++ b/libs/shared/lib/components/icon/index.tsx
@@ -2,8 +2,8 @@ import React, { ReactElement, ReactNode } from 'react';
 import { SVGProps } from 'react';
 
 // Define Sizes and IconProps types
-export type Sizes = 8 | 10 | 12 | 14 | 16 | 20 | 24 | 28 | 32 | 36 | 40;
-export const sizesArray: Sizes[] = [8, 10, 12, 14, 16, 20, 24, 28, 32, 36, 40];
+export const sizesArray = [8, 10, 12, 14, 16, 20, 24, 28, 32, 36, 40, 48, 56] as const;
+export type Sizes = (typeof sizesArray)[number];
 
 export type IconProps = SVGProps<SVGSVGElement> & {
   component?: ReactNode | ReactElement<any> | string;
diff --git a/libs/shared/lib/components/layout/Dialog.tsx b/libs/shared/lib/components/layout/Dialog.tsx
index 1f6bb731e..f18234621 100644
--- a/libs/shared/lib/components/layout/Dialog.tsx
+++ b/libs/shared/lib/components/layout/Dialog.tsx
@@ -11,7 +11,7 @@ import {
   FloatingOverlay,
   useId,
 } from '@floating-ui/react';
-import { Button } from '../buttons';
+import { Button, ButtonProps } from '../buttons';
 
 interface DialogOptions {
   initialOpen?: boolean;
@@ -200,9 +200,7 @@ export const DialogDescription = React.forwardRef<HTMLParagraphElement, React.HT
   );
 });
 
-export const DialogClose = React.forwardRef<HTMLButtonElement, React.ButtonHTMLAttributes<HTMLButtonElement>>(
-  function DialogClose(props, ref) {
-    const { setOpen } = useDialogContext();
-    return <Button variant="solid" className="w-full" {...props} ref={ref} onClick={() => setOpen(false)} />;
-  },
-);
+export const DialogClose = React.forwardRef<HTMLButtonElement, ButtonProps>(function DialogClose(props, ref) {
+  const { setOpen } = useDialogContext();
+  return <Button variant="solid" className="w-full" {...props} ref={ref} onClick={() => setOpen(false)} />;
+});
diff --git a/libs/shared/lib/components/panels/userManagementContent/UserManagementContent.tsx b/libs/shared/lib/components/panels/userManagementContent/UserManagementContent.tsx
deleted file mode 100644
index 7357f76f1..000000000
--- a/libs/shared/lib/components/panels/userManagementContent/UserManagementContent.tsx
+++ /dev/null
@@ -1,96 +0,0 @@
-import React, { useState } from 'react';
-import { Button } from '@graphpolaris/shared/lib/components/buttons';
-import { useDialogContext } from '@graphpolaris/shared/lib/components/layout/Dialog';
-import { Input } from '@graphpolaris/shared/lib/components/inputs';
-import { TableUI } from '@graphpolaris/shared/lib/components/tableUI/TableUI';
-import { useUsersPolicy } from '@graphpolaris/shared/lib/data-access/store';
-import { useDispatch } from 'react-redux';
-import { setUsersPolicy, UserPolicy } from '@graphpolaris/shared/lib/data-access/store/authorizationUsersSlice';
-interface UserManagementContentProps {
-  sessionId: string;
-  onConfirm: (users: { name: string; email: string; type: string }[]) => void;
-  onClickShareLink: () => void;
-}
-
-interface FieldConfig<T> {
-  key: keyof T;
-  label: string;
-  type: 'text' | 'dropdown';
-  required?: boolean;
-}
-
-export const UserManagementContent: React.FC<UserManagementContentProps> = ({ sessionId, onConfirm, onClickShareLink }) => {
-  const { setOpen } = useDialogContext();
-  const dispatch = useDispatch();
-
-  // !FIXME: This should definited at high level
-  const optionsTypeUser = ['', 'Creator', 'Viewer'];
-  const [copiedAccessOption, setCopiedAccessOption] = useState<string>(optionsTypeUser[2]);
-
-  const usersPolicy = useUsersPolicy();
-  // !FIXME: This should be populated from the store
-  const userFields = [
-    { key: 'name', label: 'Name', type: 'text', required: true },
-    { key: 'email', label: 'Email', type: 'text', required: true },
-    { key: 'type', label: 'Type', type: 'dropdown', required: true },
-  ] as FieldConfig<UserPolicy>[];
-
-  const options = {
-    type: optionsTypeUser,
-  };
-
-  const handleUserChange = (newUsers: UserPolicy[]) => {
-    dispatch(setUsersPolicy({ users: newUsers }));
-  };
-
-  const handleCancel = () => {
-    setOpen(false);
-  };
-
-  const handleClickShare = () => {
-    setOpen(false);
-    onClickShareLink();
-  };
-
-  return (
-    <div className="flex flex-col w-[50rem] h-[40rem]">
-      <div className="flex-grow justify-center p-2 text-sm overflow-hidden text-ellipsis whitespace-nowrap">
-        <h1 className="flex justify-center font-bold gap-x-1">
-          <span>Manage Users Sharing of</span> <span className="text-secondary-500">{sessionId}</span>
-        </h1>
-      </div>
-
-      <div className="flex flex-row items-center justify-center gap-2 mt-4 w-full">
-        <span>By sharing this link recipient will have </span>
-        <div>
-          <Input
-            type="dropdown"
-            label=""
-            value={copiedAccessOption}
-            options={optionsTypeUser}
-            onChange={(value) => setCopiedAccessOption(value.toString())}
-          />
-        </div>
-        <span>access</span>
-        <Button variant="solid" size="md" label="Copy link" onClick={handleClickShare} />
-      </div>
-
-      <div className="flex items-center my-4">
-        <hr className="flex-grow border-t border-gray-300" />
-        <span className="mx-4 text-gray-500">or</span>
-        <hr className="flex-grow border-t border-gray-300" />
-      </div>
-
-      <div className="flex flex-col items-center flex-grow mt-4">
-        <TableUI data={usersPolicy.users} fieldConfigs={userFields} dropdownOptions={options} onDataChange={handleUserChange} />
-      </div>
-
-      <div className="flex justify-center p-2 mt-auto">
-        <div className="flex space-x-4">
-          <Button variant="outline" size="md" label="Cancel" onClick={handleCancel} />
-          <Button variantType="primary" size="md" label="Confirm" onClick={() => onConfirm(usersPolicy.users)} />
-        </div>
-      </div>
-    </div>
-  );
-};
diff --git a/libs/shared/lib/components/tableUI/TableUI.tsx b/libs/shared/lib/components/tableUI/TableUI.tsx
index 8138d147c..02a1d4c8d 100644
--- a/libs/shared/lib/components/tableUI/TableUI.tsx
+++ b/libs/shared/lib/components/tableUI/TableUI.tsx
@@ -64,9 +64,6 @@ export const TableUI = <T extends Record<string, any>>({ data, fieldConfigs, dro
 
   return (
     <div className="mt-2 w-full overflow-x-auto">
-      <div className="flex justify-end mb-4">
-        <Button variant="solid" size="md" label="Add Row" onClick={handleAddRow} />
-      </div>
       <table className="min-w-full bg-white border border-gray-300 rounded-md">
         <thead>
           <tr className="bg-gray-100 border-b">
diff --git a/libs/shared/lib/components/tabs/Tab.tsx b/libs/shared/lib/components/tabs/Tab.tsx
index d007b5c26..49a66667f 100644
--- a/libs/shared/lib/components/tabs/Tab.tsx
+++ b/libs/shared/lib/components/tabs/Tab.tsx
@@ -1,29 +1,62 @@
 import React from 'react';
+import { Button, ButtonProps } from '../buttons';
 
-export const Tabs = (props: { children: React.ReactNode }) => {
+type TabTypes = 'inline' | 'rounded' | 'simple';
+
+type ContextType = {
+  tabType: TabTypes;
+};
+const TabContext = React.createContext<ContextType>({
+  tabType: 'inline',
+});
+
+export const Tabs = (props: { children: React.ReactNode; tabType?: TabTypes }) => {
+  const tabType = props.tabType || 'inline';
+  let className = '';
+  if (tabType === 'inline') {
+    className = 'flex items-stretch divide-x divide-secondary-200 border-x border-secondary-200 overflow-x-auto -my-px';
+  } else if (tabType === 'rounded') {
+    className = 'flex gap-x-1  border-b border-secondary-300 mb-5';
+  } else if (tabType === 'simple') {
+    className = 'flex gap-x-1';
+  }
   return (
-    <div className="flex items-stretch divide-x divide-secondary-200 border-x border-secondary-200 overflow-x-auto -my-px">
-      {props.children}
-    </div>
+    <TabContext.Provider value={{ tabType: tabType }}>
+      <div className={className}>{props.children}</div>
+    </TabContext.Provider>
   );
 };
 
 export const Tab = ({
   activeTab,
   text,
+  variant = 'ghost',
+  className = '',
   ...props
-}: React.ButtonHTMLAttributes<HTMLDivElement> & {
+}: ButtonProps & {
   activeTab: boolean;
-  children: React.ReactNode;
+  children?: React.ReactNode;
   text: string;
 }) => {
+  const context = React.useContext(TabContext);
+
+  if (context.tabType === 'inline') {
+    className += ` pl-2 pr-1 gap-1 relative h-full text-secondary-500 border-secondary-200 before:content-[''] 
+    before:absolute before:left-0 before:bottom-0 before:h-[2px] before:w-full
+    ${activeTab ? 'before:bg-primary-500' : 'before:bg-transparent hover:before:bg-secondary-300 hover:bg-secondary-200'}`;
+  } else if (context.tabType === 'rounded') {
+    className += ` -mb-px py-4 px-4 text-sm  text-secondary-500 text-center border rounded-t-lg rounded-b-none 
+    ${activeTab ? 'active text-secondary-950 border-l-secondary-300 border-r-secondary-300 border-t-secondary-300 border-b-white' : ''} 
+    before:bg-transparent hover:before:bg-secondary-300 hover:bg-secondary-200`;
+  } else if (context.tabType === 'simple') {
+    className += ` ${activeTab ? 'active bg-secondary-200 hover:bg-secondary-300' : 'hover:bg-secondary-100'}`;
+  }
+
   return (
-    <div
-      className={`flex items-center pl-2 pr-1 gap-1 cursor-pointer relative border-secondary-200 before:content-[''] before:absolute before:left-0 before:bottom-0 before:h-[2px] before:w-full ${activeTab ? 'before:bg-primary-500' : 'before:bg-transparent hover:before:bg-secondary-300 hover:bg-secondary-200'}`}
-      {...props}
-    >
-      <p className={`text-xs text-secondary-500 font-semibold ${activeTab && 'text-secondary-950'}`}>{text}</p>
+    <Button className={className} label={text} variant={variant} size="xs" {...props}>
+      {/* <p className={`text-xs font-semibold ${activeTab && 'text-secondary-950'}`}>{text}</p> */}
+
       {props.children}
-    </div>
+    </Button>
   );
 };
diff --git a/libs/shared/lib/components/textEditor/plugins/InsertVariablesPlugin.tsx b/libs/shared/lib/components/textEditor/plugins/InsertVariablesPlugin.tsx
index 8e1488014..eebd254d9 100644
--- a/libs/shared/lib/components/textEditor/plugins/InsertVariablesPlugin.tsx
+++ b/libs/shared/lib/components/textEditor/plugins/InsertVariablesPlugin.tsx
@@ -1,32 +1,21 @@
-import { useLexicalComposerContext } from "@lexical/react/LexicalComposerContext";
-import {
-  $copyNode,
-  $getRoot,
-  $isParagraphNode,
-  $isElementNode,
-  $getNodeByKey,
-  $getSelection,
-  type BaseSelection,
-  $parseSerializedNode
-} from "lexical";
+import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';
+import { $getSelection, type BaseSelection } from 'lexical';
 import { Input } from '@graphpolaris/shared/lib/components/inputs';
 import { VariableNode, VariableType } from '../VariableNode';
-import { useState } from 'react';
 import { useGraphQueryResult, useVisualization } from '@graphpolaris/shared/lib/data-access';
 
 export const InsertVariablesPlugin = () => {
   const [editor] = useLexicalComposerContext();
   const { openVisualizationArray } = useVisualization();
 
-  const visualizationOptions = openVisualizationArray
-    .map(x => x.name);
+  const visualizationOptions = openVisualizationArray.map((x) => x.name);
 
   const onChange = (value: string | number, type: VariableType) => {
     editor.update(() => {
       const selection = $getSelection() as BaseSelection;
-      
+
       const node = new VariableNode(String(value), type);
-      
+
       selection.insertNodes([node]);
 
       // TODO: enable drag and dropping nodes
@@ -37,34 +26,39 @@ export const InsertVariablesPlugin = () => {
 
   const nodeTypes = Object.keys(result.metaData?.nodes.types || {});
   function optionsForType(type: string) {
-    const typeObj = result.metaData?.nodes.types[type] ?? {attributes: null};
-    
+    const typeObj = result.metaData?.nodes.types[type] ?? { attributes: null };
+
     if (!('attributes' in typeObj) || typeObj.attributes == null) {
       return [];
     }
-    
 
-    return Object.entries(typeObj.attributes).map(([k,v]) => Object.keys(v).map(x => `${k}_${x}`)).flat();
+    return Object.entries(typeObj.attributes)
+      .map(([k, v]) => Object.keys(v).map((x) => `${k}_${x}`))
+      .flat();
   }
 
-  return <>
-    { nodeTypes.map((nodeType) => 
-      <Input
-            type="dropdown"
-            label={`${nodeType} variable`}
-            value=""
-            options={optionsForType(nodeType)}
-            onChange={(v) => onChange(v, VariableType.statistic)}
-            />
-        )
-    }
-    { (visualizationOptions.length > 0) ? <Input
+  return (
+    <>
+      {nodeTypes.map((nodeType) => (
+        <Input
+          type="dropdown"
+          label={`${nodeType} variable`}
+          value=""
+          options={optionsForType(nodeType)}
+          onChange={(v) => onChange(v, VariableType.statistic)}
+        />
+      ))}
+      {visualizationOptions.length > 0 ? (
+        <Input
           type="dropdown"
           label={`Visualization`}
           value=""
           options={visualizationOptions}
           onChange={(v) => onChange(v, VariableType.visualization)}
-          /> : ''
-    }
-  </>;
-};
\ No newline at end of file
+        />
+      ) : (
+        ''
+      )}
+    </>
+  );
+};
diff --git a/libs/shared/lib/data-access/api/eventBus.tsx b/libs/shared/lib/data-access/api/eventBus.tsx
index 283f07dd8..d783b723d 100644
--- a/libs/shared/lib/data-access/api/eventBus.tsx
+++ b/libs/shared/lib/data-access/api/eventBus.tsx
@@ -46,7 +46,7 @@ import {
 import { URLParams, getParam, deleteParam } from './url';
 import { VisState, setVisualizationState } from '../store/visualizationSlice';
 import { isEqual } from 'lodash-es';
-import { setSchemaAttributeDimensions, setSchemaAttributeInformation } from '../store/schemaSlice';
+import { setSchemaAttributeDimensions, setSchemaAttributeInformation, setSchemaLoading } from '../store/schemaSlice';
 import { addError } from '@graphpolaris/shared/lib/data-access/store/configSlice';
 import { unSelect } from '../store/interactionSlice';
 import { SchemaGraphStats } from '../../schema';
@@ -90,6 +90,7 @@ export const EventBus = (props: { onRunQuery: Function; onAuthorized: Function }
 
     unsubs.push(
       wsSchemaSubscription((data) => {
+        dispatch(setSchemaLoading(false));
         dispatch(readInSchemaFromBackend(data));
         dispatch(addInfo('Schema graph updated'));
       }),
@@ -151,6 +152,7 @@ export const EventBus = (props: { onRunQuery: Function; onAuthorized: Function }
     unsubs.push(
       wsGetStateSubscription((data) => {
         if (data.id !== nilUUID) {
+          console.debug('Save State updated', data);
           dispatch(addSaveState(data));
           dispatch(selectSaveState(data.id));
           loadSaveState(data.id, session.saveStates);
@@ -223,6 +225,7 @@ export const EventBus = (props: { onRunQuery: Function; onAuthorized: Function }
   useEffect(() => {
     // New active database
     if (session.currentSaveState && session.currentSaveState !== nilUUID) {
+      dispatch(setSchemaLoading(true));
       wsSchemaRequest(session.currentSaveState);
       wsSchemaStatsRequest(session.currentSaveState);
       wsSelectState(session.currentSaveState);
diff --git a/libs/shared/lib/data-access/broker/wsSchema.ts b/libs/shared/lib/data-access/broker/wsSchema.ts
index 09a81f21a..bfbb2e5eb 100644
--- a/libs/shared/lib/data-access/broker/wsSchema.ts
+++ b/libs/shared/lib/data-access/broker/wsSchema.ts
@@ -3,15 +3,18 @@
 import { SchemaFromBackend, SchemaStatsFromBackend } from '../../schema';
 import { Broker } from './broker';
 
-export function wsSchemaRequest(saveStateID: string) {
-  Broker.instance().sendMessage({
-    key: 'schema',
-    subKey: 'get',
-    body: {
-      cached: false,
-      saveStateID: saveStateID,
+export function wsSchemaRequest(saveStateID: string, callback?: Function) {
+  Broker.instance().sendMessage(
+    {
+      key: 'schema',
+      subKey: 'get',
+      body: {
+        cached: false,
+        saveStateID: saveStateID,
+      },
     },
-  });
+    callback,
+  );
 }
 
 type SchemaResponse = (data: SchemaFromBackend) => void;
diff --git a/libs/shared/lib/data-access/store/hooks.ts b/libs/shared/lib/data-access/store/hooks.ts
index 2c57d5045..d55cbb791 100644
--- a/libs/shared/lib/data-access/store/hooks.ts
+++ b/libs/shared/lib/data-access/store/hooks.ts
@@ -7,6 +7,8 @@ import {
   SchemaSettings,
   schemaStatsState,
   schemaInferenceState,
+  SchemaSliceI,
+  schema,
 } from './schemaSlice';
 import type { RootState, AppDispatch } from './store';
 import { ConfigStateI, configState } from '@graphpolaris/shared/lib/data-access/store/configSlice';
@@ -52,6 +54,7 @@ export const useGraphQueryResult: () => GraphQueryResult = () => useAppSelector(
 export const useGraphQueryResultMeta: () => GraphMetadata | undefined = () => useAppSelector(selectGraphQueryResultMetaData);
 
 // Gives the schema
+export const useSchema: () => SchemaSliceI = () => useAppSelector(schema);
 export const useSchemaGraph: () => SchemaGraph = () => useAppSelector(schemaGraph);
 export const useSchemaSettings: () => SchemaSettings = () => useAppSelector(schemaSettingsState);
 export const useSchemaStats: () => SchemaGraphStats = () => useAppSelector(schemaStatsState);
diff --git a/libs/shared/lib/data-access/store/schemaSlice.ts b/libs/shared/lib/data-access/store/schemaSlice.ts
index 479cfe24e..5c79edddf 100644
--- a/libs/shared/lib/data-access/store/schemaSlice.ts
+++ b/libs/shared/lib/data-access/store/schemaSlice.ts
@@ -17,15 +17,16 @@ export type SchemaSettings = {
   schemaViewState: SchemaViewState;
 };
 
-type schemaSliceI = {
+export type SchemaSliceI = {
   graph: SchemaGraph;
   graphInference: SchemaGraphInference;
   graphStats: SchemaGraphStats;
+  loading: boolean;
   settings: SchemaSettings;
 };
 
 // Define the initial state using that type
-export const initialState: schemaSliceI = {
+export const initialState: SchemaSliceI = {
   graph: new SchemaGraphology().export(),
   graphInference: {
     nodes: {},
@@ -41,6 +42,7 @@ export const initialState: schemaSliceI = {
       stats: {},
     },
   },
+  loading: true,
   // layoutName: 'Cytoscape_fcose',
   settings: {
     connectionType: 'connection',
@@ -79,6 +81,11 @@ export const schemaSlice = createSlice({
     setSchemaAttributeInformation: (state, action: PayloadAction<SchemaGraphStats>) => {
       state.graphStats = action.payload;
     },
+
+    setSchemaLoading: (state, action: PayloadAction<boolean>) => {
+      state.loading = action.payload;
+      if (!action.payload) state.graph = new SchemaGraphology().export();
+    },
   },
 });
 export const {
@@ -88,8 +95,10 @@ export const {
   clearSchema,
   setSchemaAttributeDimensions,
   setSchemaAttributeInformation,
+  setSchemaLoading,
 } = schemaSlice.actions;
 
+export const schema = (state: RootState) => state.schema;
 export const schemaSettingsState = (state: RootState) => state.schema.settings;
 export const schemaInferenceState = (state: RootState) => state.schema.graphInference;
 export const schemaStatsState = (state: RootState) => state.schema.graphStats;
diff --git a/libs/shared/lib/management/Explorations.tsx b/libs/shared/lib/management/Explorations.tsx
new file mode 100644
index 000000000..deadcebd0
--- /dev/null
+++ b/libs/shared/lib/management/Explorations.tsx
@@ -0,0 +1,45 @@
+import React from 'react';
+import { Button } from '../components';
+
+type Props = {
+  changeActive: (val: 'add' | 'update') => void;
+};
+
+export function Explorations({ changeActive }: Props) {
+  return (
+    <div>
+      <div className="flex gap-x-4 mb-4">
+        <Button
+          label="Project"
+          variantType="primary"
+          iconComponent="icon-[ic--baseline-add]"
+          iconPosition="leading"
+          onClick={() => changeActive('add')}
+        />
+        <Button
+          label="Learn how to use"
+          variant="ghost"
+          iconComponent="icon-[mdi--play]"
+          iconPosition="leading"
+          onClick={() => window.open('https://graphpolaris.com/', '_blank')}
+        />
+      </div>
+      <table className="w-full">
+        <thead>
+          <tr>
+            <th scope="col" className="text-left">
+              Name
+            </th>
+            <th scope="col" className="text-left">
+              Last modified
+            </th>
+            <th scope="col" className="text-left">
+              Created
+            </th>
+            <th scope="col"></th>
+          </tr>
+        </thead>
+      </table>
+    </div>
+  );
+}
diff --git a/libs/shared/lib/management/ManagementDialog.tsx b/libs/shared/lib/management/ManagementDialog.tsx
new file mode 100644
index 000000000..c0f57f042
--- /dev/null
+++ b/libs/shared/lib/management/ManagementDialog.tsx
@@ -0,0 +1,95 @@
+import React, { useState } from 'react';
+import { Settings } from './Settings';
+import { Overview } from './Overview';
+import { Members } from './Members';
+import { UpsertDatabase } from './database';
+import { Button, Dialog, DialogContent, SaveStateI, useAppDispatch, useAuthCache, useSessionCache } from '..';
+import { addInfo } from '../data-access/store/configSlice';
+
+type Props = {
+  open: boolean;
+  onClose: () => void;
+  current: ManagementViews;
+  setCurrent: (val: ManagementViews) => void;
+};
+
+export type ManagementViews = 'overview' | 'settings' | 'members' | 'add' | 'update';
+
+export function ManagementDialog(props: Props) {
+  const dispatch = useAppDispatch();
+  const session = useSessionCache();
+  const authCache = useAuthCache();
+  const [selectedSaveState, setSelectedSaveState] = useState<SaveStateI | null>(null);
+
+  const dialogMessage = (() => {
+    switch (props.current) {
+      case 'add':
+        return 'Add Database';
+      case 'update':
+        return 'Updating Database Connection';
+      case 'members':
+        return 'Manage Members';
+      default:
+        return '';
+    }
+  })();
+
+  const handleClose = () => {
+    props.onClose();
+    props.setCurrent('overview');
+  };
+
+  const handleConfirmUsers = (users: { name: string; email: string; type: string }[]) => {
+    //TODO !FIXME: when the user clicks on confirm, users state is ready to be sent to backend
+  };
+
+  const handleClickShareLink = () => {
+    //TODO !FIXME: add copy link to clipboard functionality
+    dispatch(addInfo('Link copied to clipboard'));
+  };
+
+  return (
+    <Dialog
+      open={props.open}
+      onOpenChange={(ret) => {
+        if (!ret) handleClose();
+      }}
+    >
+      <DialogContent className="border bg-light w-8/12 flex-grow mx-auto px-0 py-0">
+        {props.current === 'overview' ? (
+          <Overview onViewChange={props.setCurrent} setSelectedSaveState={setSelectedSaveState} onClose={() => handleClose()} />
+        ) : (
+          <div>
+            <div className="flex justify-between items-center border-b p-4">
+              <span className="text-secondary font-semibold">{dialogMessage}</span>
+              <Button iconComponent="icon-[ic--outline-close]" variant="ghost" onClick={() => handleClose()} />
+            </div>
+            {props.current === 'settings' ? (
+              <Settings />
+            ) : props.current === 'members' ? (
+              <Members
+                onConfirm={handleConfirmUsers}
+                onClickShareLink={handleClickShareLink}
+                onClose={() => {
+                  handleClose();
+                }}
+              />
+            ) : (
+              <UpsertDatabase
+                open={props.current}
+                saveState={props.current === 'update' ? selectedSaveState : null}
+                disableCancel={
+                  (session.saveStates && Object.keys(session.saveStates).length === 0) ||
+                  session.currentSaveState === '00000000-0000-0000-0000-000000000000'
+                }
+                onClose={() => {
+                  handleClose();
+                }}
+              />
+            )}
+          </div>
+        )}
+      </DialogContent>
+    </Dialog>
+  );
+}
diff --git a/libs/shared/lib/management/ManagementTrigger.tsx b/libs/shared/lib/management/ManagementTrigger.tsx
new file mode 100644
index 000000000..ace73c3c3
--- /dev/null
+++ b/libs/shared/lib/management/ManagementTrigger.tsx
@@ -0,0 +1,88 @@
+import React, { useState, useEffect, useCallback } from 'react';
+import { addError } from '../data-access/store/configSlice';
+import { selectSaveState } from '../data-access/store/sessionSlice';
+import { clearQB } from '../data-access/store/querybuilderSlice';
+import { clearSchema } from '../data-access/store/schemaSlice';
+import { ManagementDialog, ManagementViews } from './ManagementDialog';
+import { DatabaseStatus, Icon, LoadingSpinner, nilUUID, useAppDispatch, useSchemaGraph, useSessionCache } from '..';
+
+type Props = {
+  managementOpen: boolean;
+  setManagementOpen: (val: boolean) => void;
+  current: ManagementViews;
+  setCurrent: (val: ManagementViews) => void;
+};
+
+export function ManagementTrigger({ managementOpen, setManagementOpen, current, setCurrent }: Props) {
+  const dispatch = useAppDispatch();
+  const session = useSessionCache();
+  const schemaGraph = useSchemaGraph();
+  const [connecting, setConnecting] = useState<boolean>(false);
+
+  useEffect(() => {
+    setConnecting(false);
+  }, [schemaGraph]);
+
+  useEffect(() => {
+    let timeoutId: ReturnType<typeof setTimeout>;
+    if (connecting) {
+      timeoutId = setTimeout(() => {
+        dispatch(addError("Couldn't establish connection"));
+        setConnecting(false);
+        dispatch(selectSaveState(undefined));
+        dispatch(clearQB());
+        dispatch(clearSchema());
+      }, 10000);
+    }
+
+    return () => {
+      if (timeoutId) clearTimeout(timeoutId);
+    };
+  }, [connecting]);
+
+  return (
+    <div>
+      <ManagementDialog
+        open={managementOpen}
+        onClose={() => setManagementOpen(!managementOpen)}
+        current={current}
+        setCurrent={setCurrent}
+      />
+      <div
+        className="flex items-center cursor-pointer border rounded hover:bg-secondary-100 transition-colors duration-300 py-1 px-2"
+        onClick={() => setManagementOpen(true)}
+      >
+        {connecting && session.currentSaveState && session.currentSaveState in session.saveStates ? (
+          <>
+            <LoadingSpinner />
+            <p className="ml-2 truncate">Connecting to {session.saveStates[session.currentSaveState].name}</p>
+          </>
+        ) : session.currentSaveState && session.currentSaveState in session.saveStates && session.currentSaveState !== nilUUID ? (
+          <div className="flex">
+            <Icon component="icon-[mdi--database-outline]" size={20} className="self-center text-secondary-700" />
+            <span className="relative">
+              <span
+                className={`absolute bottom-0.5 right-3 h-2 w-2 border border-light  rounded-full ${session.testedSaveState[session.currentSaveState] === DatabaseStatus.tested ? 'bg-success-500' : 'bg-danger-500'}`}
+              />
+            </span>
+            <p className="ml-1 truncate">{session.saveStates[session.currentSaveState].name}</p>
+          </div>
+        ) : session.saveStates === undefined ? (
+          <>
+            <LoadingSpinner />
+            <p className="ml-2">Retrieving databases</p>
+          </>
+        ) : Object.keys(session.saveStates).length === 0 || session.currentSaveState === nilUUID ? (
+          <>
+            <p className="ml-2">Add your first Database</p>
+          </>
+        ) : (
+          <>
+            <div className="h-2 w-2 rounded-full bg-secondary-500" />
+            <p className="ml-2">Select a database</p>
+          </>
+        )}
+      </div>
+    </div>
+  );
+}
diff --git a/libs/shared/lib/management/Members.tsx b/libs/shared/lib/management/Members.tsx
new file mode 100644
index 000000000..64122c68e
--- /dev/null
+++ b/libs/shared/lib/management/Members.tsx
@@ -0,0 +1,74 @@
+import React, { useState } from 'react';
+import { Button } from '../components/buttons';
+import { useDialogContext } from '../components/layout/Dialog';
+import { Input } from '../components/inputs';
+import { useUsersPolicy } from '../data-access/store';
+import { useDispatch } from 'react-redux';
+import { Icon } from '..';
+import { setUsersPolicy, UserPolicy } from '../data-access/store/authorizationUsersSlice';
+import { TableUI } from '../components/tableUI/TableUI';
+
+interface UserManagementContentProps {
+  onConfirm?: (users: { name: string; email: string; type: string }[]) => void;
+  onClickShareLink?: () => void;
+  onClose?: () => void;
+}
+
+interface FieldConfig<T> {
+  key: keyof T;
+  label: string;
+  type: 'text' | 'dropdown';
+  required?: boolean;
+}
+
+export const Members: React.FC<UserManagementContentProps> = ({ onConfirm, onClickShareLink, onClose }) => {
+  const { setOpen } = useDialogContext();
+  const dispatch = useDispatch();
+
+  // !FIXME: This should definited at high level
+  const optionsTypeUser = ['', 'Creator', 'Viewer'];
+
+  const usersPolicy = useUsersPolicy();
+  // !FIXME: This should be populated from the store
+  const userFields = [
+    { key: 'name', label: 'Name', type: 'text', required: true },
+    { key: 'email', label: 'Email', type: 'text', required: true },
+    { key: 'type', label: 'Type', type: 'dropdown', required: true },
+  ] as FieldConfig<UserPolicy>[];
+
+  const options = {
+    type: optionsTypeUser,
+  };
+
+  const handleUserChange = (newUsers: UserPolicy[]) => {
+    dispatch(setUsersPolicy({ users: newUsers }));
+  };
+
+  return (
+    <div className="flex flex-col p-4">
+      <div className="bg-primary-50 flex items-center px-2 gap-x-2 my-2">
+        <Icon component="icon-[ic--outline-info]" size={14} />
+        <span className="font-light text-sm">These members have access to all projects within your company</span>
+      </div>
+
+      <div className="flex flex-col items-center flex-grow">
+        <TableUI data={usersPolicy.users} fieldConfigs={userFields} dropdownOptions={options} onDataChange={handleUserChange} />
+      </div>
+
+      <div className="flex justify-center p-2 mt-auto">
+        <div className="flex space-x-4">
+          <Button variant="outline" size="md" label="Add row" onClick={() => {}} />
+          <Button
+            variantType="primary"
+            size="md"
+            label="Save"
+            onClick={() => {
+              if (onConfirm) onConfirm(usersPolicy.users);
+              if (onClose) onClose();
+            }}
+          />
+        </div>
+      </div>
+    </div>
+  );
+};
diff --git a/libs/shared/lib/management/Overview.tsx b/libs/shared/lib/management/Overview.tsx
new file mode 100644
index 000000000..59f6f13e3
--- /dev/null
+++ b/libs/shared/lib/management/Overview.tsx
@@ -0,0 +1,35 @@
+import React, { useState } from 'react';
+import { SaveStateI, useAppDispatch, useSessionCache } from '..';
+import { ManagementViews } from './ManagementDialog';
+import { Tabs, Tab } from '../components/tabs';
+import { Workspace } from './Workspace';
+import { Members } from './Members';
+
+type Props = {
+  onClose: () => void;
+  onViewChange: (val: ManagementViews) => void;
+  setSelectedSaveState: (val: SaveStateI) => void;
+};
+
+export function Overview({ onClose, onViewChange, setSelectedSaveState }: Props) {
+  const [activeTab, setActiveTab] = useState<'workspace' | 'company' | 'settings' | 'members' | 'admin'>('workspace');
+
+  return (
+    <div className="flex flex-col h-[calc(100vh-20rem)] max-w-[calc(100vw-20rem)] overflow-y-auto overflow-x-hidden p-8 gap-4">
+      <h1 className="text-4xl font-semibold">{/* <img className="w-52" src="" /> */}Company name</h1>
+      <Tabs tabType="simple">
+        <Tab text="Workspace" activeTab={activeTab === 'workspace'} onClick={() => setActiveTab('workspace')}></Tab>
+        <Tab text="Company" activeTab={activeTab === 'company'} onClick={() => setActiveTab('company')}></Tab>
+        {/* TODO investigate how to best integrate <Tab text="Members" activeTab={activeTab === 'members'} onClick={() => setActiveTab('members')}></Tab> */}
+        <Tab text="Admin Only" activeTab={activeTab === 'admin'} onClick={() => setActiveTab('admin')} variant="outline"></Tab>
+      </Tabs>
+
+      <div>
+        {activeTab === 'workspace' && (
+          <Workspace onClose={onClose} onViewChange={onViewChange} setSelectedSaveState={setSelectedSaveState} />
+        )}
+        {/* {activeTab === 'members' && <Members />} */}
+      </div>
+    </div>
+  );
+}
diff --git a/libs/shared/lib/management/Settings.tsx b/libs/shared/lib/management/Settings.tsx
new file mode 100644
index 000000000..02987b9e6
--- /dev/null
+++ b/libs/shared/lib/management/Settings.tsx
@@ -0,0 +1,28 @@
+import React from 'react';
+
+export function Settings() {
+  return (
+    <div className="flex items-start w-full h-full p-6">
+      <div className="w-1/3 flex flex-col items-center">
+        <img src="" />
+        <span className="text-primary font-semibold">Change logo</span>
+      </div>
+      <div className="w-2/3 flex flex-col gap-y-4">
+        <div className="flex flex-col">
+          <span className="font-bold">Company name</span>
+          <div className="flex gap-x-4">
+            <span>Stichting VbV</span>
+            <span className="text-primary font-semibold">Change name</span>
+          </div>
+        </div>
+        <div className="flex flex-col">
+          <span className="font-bold">Plan and Billing</span>
+          <div className="flex gap-x-4">
+            <span>Standard</span>
+            <span className="text-primary font-semibold">Go to billing</span>
+          </div>
+        </div>
+      </div>
+    </div>
+  );
+}
diff --git a/libs/shared/lib/management/Workspace.tsx b/libs/shared/lib/management/Workspace.tsx
new file mode 100644
index 000000000..38645964d
--- /dev/null
+++ b/libs/shared/lib/management/Workspace.tsx
@@ -0,0 +1,39 @@
+import React, { useState } from 'react';
+import { Button, SaveStateI, useAppDispatch, useSessionCache } from '..';
+import { Databases } from './database';
+import { ManagementViews } from './ManagementDialog';
+import { Tabs, Tab } from '../components/tabs';
+
+type Props = {
+  onClose: () => void;
+  onViewChange: (val: ManagementViews) => void;
+  setSelectedSaveState: (val: SaveStateI) => void;
+};
+
+export function Workspace({ onClose, onViewChange, setSelectedSaveState }: Props) {
+  const session = useSessionCache();
+  const [activeTab, setActiveTab] = useState('databases');
+
+  return (
+    <div>
+      <Tabs tabType="rounded">
+        {/* TODO <Tab text="Projects" activeTab={activeTab === 'projects'} onClick={() => setActiveTab('projects')}></Tab> */}
+        <Tab text="Databases" activeTab={activeTab === 'databases'} onClick={() => setActiveTab('databases')}></Tab>
+        {/* TODO <Tab text="Explorations" activeTab={activeTab === 'explorations'} onClick={() => setActiveTab('explorations')}></Tab> */}
+      </Tabs>
+
+      <div>
+        {/* TODO {activeTab === 'projects' && 'Not Implemented Yet'} */}
+        {activeTab === 'databases' && (
+          <Databases
+            saveStates={session.saveStates}
+            changeActive={(val) => onViewChange(val)}
+            setSelectedSaveState={setSelectedSaveState}
+            onClose={onClose}
+          />
+        )}
+        {/* TODO {activeTab === 'explorations' && <Explorations changeActive={(val: 'add' | 'update') => onViewChange(val)} />} */}
+      </div>
+    </div>
+  );
+}
diff --git a/apps/web/src/components/navbar/DatabaseManagement/forms/databaseForm.tsx b/libs/shared/lib/management/database/DatabaseForm.tsx
similarity index 94%
rename from apps/web/src/components/navbar/DatabaseManagement/forms/databaseForm.tsx
rename to libs/shared/lib/management/database/DatabaseForm.tsx
index 942d65c94..1f49601f3 100644
--- a/apps/web/src/components/navbar/DatabaseManagement/forms/databaseForm.tsx
+++ b/libs/shared/lib/management/database/DatabaseForm.tsx
@@ -1,8 +1,7 @@
 import React, { useEffect, useState } from 'react';
-import { DatabaseType, SaveStateI, databaseNameMapping, databaseProtocolMapping, nilUUID } from '@graphpolaris/shared/lib/data-access';
-import { Input } from '@graphpolaris/shared/lib/components/inputs';
 import { useImmer } from 'use-immer';
-import { initialState as qbInitialState } from '@graphpolaris/shared/lib/data-access/store/querybuilderSlice';
+import { initialState as qbInitialState } from '../../data-access/store/querybuilderSlice';
+import { databaseNameMapping, databaseProtocolMapping, DatabaseType, Input, nilUUID, SaveStateI } from '../..';
 
 export const INITIAL_SAVE_STATE: SaveStateI = {
   id: nilUUID,
diff --git a/libs/shared/lib/management/database/Databases.tsx b/libs/shared/lib/management/database/Databases.tsx
new file mode 100644
index 000000000..a3c327212
--- /dev/null
+++ b/libs/shared/lib/management/database/Databases.tsx
@@ -0,0 +1,203 @@
+import React, { useMemo, useState } from 'react';
+import {
+  Button,
+  DropdownItem,
+  Icon,
+  nilUUID,
+  SaveStateI,
+  useAppDispatch,
+  useAuthCache,
+  useAuthentication,
+  useSessionCache,
+  wsDeleteState,
+} from '../..';
+import { deleteSaveState, selectSaveState } from '../../data-access/store/sessionSlice';
+import { clearQB } from '../../data-access/store/querybuilderSlice';
+import { clearSchema } from '../../data-access/store/schemaSlice';
+import { Popover, PopoverContent, PopoverTrigger } from '../../components/layout/Popover';
+import { useHandleDatabase } from './useHandleDatabase';
+
+type Props = {
+  onClose: () => void;
+  saveStates: { [id: string]: SaveStateI };
+  changeActive: (val: 'add' | 'update') => void;
+  setSelectedSaveState: (val: SaveStateI) => void;
+};
+
+type DatabaseTableHeaderTypes = 'name' | 'protocol' | 'url';
+
+const DataTableHeader = ({
+  name,
+  orderBy,
+  setOrderBy,
+}: {
+  name: DatabaseTableHeaderTypes;
+  orderBy: [DatabaseTableHeaderTypes, 'asc' | 'desc'];
+  setOrderBy: (val: [DatabaseTableHeaderTypes, 'asc' | 'desc']) => void;
+}) => {
+  return (
+    <th
+      scope="col"
+      className="text-left hover:underline cursor-pointer"
+      onClick={() => setOrderBy([name, orderBy[1] === 'desc' && orderBy[0] === name ? 'asc' : 'desc'])}
+    >
+      <span className="flex items-center gap-0">
+        {name}
+        {orderBy[0] !== name && <div className="min-w-6 min-h-4 " />}
+        {orderBy[0] === name && orderBy[1] === 'asc' && <Icon component="icon-[ic--baseline-arrow-drop-up]" />}
+        {orderBy[0] === name && orderBy[1] === 'desc' && <Icon component="icon-[ic--baseline-arrow-drop-down]" />}
+      </span>
+    </th>
+  );
+};
+
+export function Databases({ onClose, saveStates, changeActive, setSelectedSaveState }: Props) {
+  const dispatch = useAppDispatch();
+  const auth = useAuthentication();
+  const session = useSessionCache();
+  const databaseHandler = useHandleDatabase();
+  const [orderBy, setOrderBy] = useState<[DatabaseTableHeaderTypes, 'asc' | 'desc']>(['name', 'desc']);
+
+  const orderedSaveStates = useMemo(
+    () =>
+      Object.keys(saveStates).sort((a, b) => {
+        const dir = orderBy[1] === 'asc' ? 1 : -1;
+        if (orderBy[0] === 'name') {
+          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;
+          else return -dir;
+        }
+      }),
+    [saveStates, orderBy],
+  );
+
+  return (
+    <div className="flex flex-col gap-4">
+      <div className="flex gap-x-4">
+        <Button
+          label="Database"
+          variantType="primary"
+          iconComponent="icon-[ic--baseline-add]"
+          iconPosition="leading"
+          onClick={() => changeActive('add')}
+        />
+        <Button
+          label="Learn how to use"
+          variant="ghost"
+          iconComponent="icon-[mdi--play]"
+          iconPosition="leading"
+          onClick={() => window.open('https://graphpolaris.com/', '_blank')}
+        />
+      </div>
+      {orderedSaveStates.length > 0 && (
+        <table className="w-full">
+          <thead>
+            <tr>
+              <DataTableHeader name="name" orderBy={orderBy} setOrderBy={setOrderBy} />
+              <DataTableHeader name="protocol" orderBy={orderBy} setOrderBy={setOrderBy} />
+              <DataTableHeader name="url" orderBy={orderBy} setOrderBy={setOrderBy} />
+            </tr>
+          </thead>
+          <tbody className="divide-y divide-white overflow-auto table-fixed">
+            {orderedSaveStates.map((key) => (
+              <tr key={key}>
+                <td>
+                  <Button
+                    variant={session.currentSaveState === key ? 'outline' : 'ghost'}
+                    onClick={() => {
+                      if (key !== session.currentSaveState) {
+                        dispatch(selectSaveState(key));
+                        dispatch(clearQB());
+                        dispatch(clearSchema());
+                        onClose();
+                      }
+                    }}
+                  >
+                    {saveStates[key].name}
+                  </Button>
+                </td>
+                <td className="text-left">
+                  <span className="font-light">{saveStates[key].db.protocol}</span>
+                </td>
+                <td className="text-left">
+                  <span className="font-light">{saveStates[key].db.url}</span>
+                </td>
+                <td className="text-right flex justify-end">
+                  <Button
+                    iconComponent="icon-[mdi--trash-outline]"
+                    variant="ghost"
+                    onClick={() => {
+                      if (session.currentSaveState === key) {
+                        dispatch(clearQB());
+                        dispatch(clearSchema());
+                      }
+                      wsDeleteState(key);
+                      dispatch(deleteSaveState(key));
+                    }}
+                  />
+                  <Popover>
+                    <PopoverTrigger>
+                      <Button iconComponent="icon-[mi--options-vertical]" variant="ghost" />
+                    </PopoverTrigger>
+                    <PopoverContent className="w-56 z-50 bg-light rounded-sm border-[1px] outline-none">
+                      <DropdownItem
+                        value="Open"
+                        onClick={() => {
+                          if (key !== session.currentSaveState) {
+                            dispatch(selectSaveState(key));
+                            dispatch(clearQB());
+                            dispatch(clearSchema());
+                          }
+                          onClose();
+                        }}
+                      />
+                      <DropdownItem
+                        value="Update"
+                        onClick={() => {
+                          changeActive('update');
+                          setSelectedSaveState(saveStates[key]);
+                        }}
+                      />
+                      <DropdownItem
+                        value="Clone"
+                        onClick={() => {
+                          databaseHandler.submitDatabaseChange(
+                            { ...saveStates[key], name: saveStates[key].name + ' (copy)', id: nilUUID },
+                            'add',
+                            true,
+                            () => {},
+                          );
+                          setSelectedSaveState(saveStates[key]);
+                        }}
+                      />
+                      <DropdownItem
+                        value="Share"
+                        onClick={() => {
+                          auth.newShareRoom();
+                        }}
+                      />
+                      <DropdownItem
+                        value="Delete"
+                        onClick={() => {
+                          if (session.currentSaveState === key) {
+                            dispatch(clearQB());
+                            dispatch(clearSchema());
+                          }
+                          wsDeleteState(key);
+                          dispatch(deleteSaveState(key));
+                        }}
+                        className="text-danger"
+                      />
+                    </PopoverContent>
+                  </Popover>
+                </td>
+              </tr>
+            ))}
+          </tbody>
+        </table>
+      )}
+    </div>
+  );
+}
diff --git a/apps/web/src/components/navbar/DatabaseManagement/forms/mockSaveStates.tsx b/libs/shared/lib/management/database/MockSaveStates.tsx
similarity index 93%
rename from apps/web/src/components/navbar/DatabaseManagement/forms/mockSaveStates.tsx
rename to libs/shared/lib/management/database/MockSaveStates.tsx
index 25ccd998c..7fdaa0a19 100644
--- a/apps/web/src/components/navbar/DatabaseManagement/forms/mockSaveStates.tsx
+++ b/libs/shared/lib/management/database/MockSaveStates.tsx
@@ -1,6 +1,6 @@
 import React from 'react';
-import { DatabaseType, SaveStateI, nilUUID } from '@graphpolaris/shared/lib/data-access/broker';
-import { initialState as qbInitialState } from '@graphpolaris/shared/lib/data-access/store/querybuilderSlice';
+import { DatabaseType, SaveStateI, nilUUID } from '../../data-access/broker';
+import { initialState as qbInitialState } from '../../data-access/store/querybuilderSlice';
 
 export type SaveStateSampleI = SaveStateI & {
   subtitle: string;
@@ -132,11 +132,11 @@ export const sampleSaveStates: Array<SaveStateSampleI> = [
 
 export const SampleDatabaseSelector = (props: { onClick: (data: SaveStateI) => void }) => {
   return (
-    <div className="grid grid-cols-2 lg:grid-cols-3 gap-2">
+    <div className="flex flex-wrap gap-2">
       {sampleSaveStates.map((sample) => (
         <div
           key={sample.name}
-          className="card hover:bg-secondary-100 cursor-pointer mb-2 border w-[15rem]"
+          className="card hover:bg-secondary-100 cursor-pointer mb-2 border w-[15rem] flex-grow "
           onClick={() => props.onClick(sample as SaveStateI)}
         >
           <div className="card-body">
diff --git a/libs/shared/lib/management/database/UpsertDatabase.tsx b/libs/shared/lib/management/database/UpsertDatabase.tsx
new file mode 100644
index 000000000..5c6fa1513
--- /dev/null
+++ b/libs/shared/lib/management/database/UpsertDatabase.tsx
@@ -0,0 +1,134 @@
+import React, { useEffect, useRef, useState } from 'react';
+import { SaveStateI, useAuthCache, nilUUID } from '../../data-access';
+import { Button } from '../../components/buttons';
+import { useImmer } from 'use-immer';
+import { DatabaseForm, INITIAL_SAVE_STATE } from './DatabaseForm';
+import { SampleDatabaseSelector } from './MockSaveStates';
+import { Icon } from '../..';
+import { useHandleDatabase } from './useHandleDatabase';
+
+export const UpsertDatabase = (props: {
+  onClose(): void;
+  open: 'add' | 'update';
+  saveState: SaveStateI | null;
+  disableCancel?: boolean;
+}) => {
+  const databaseHandler = useHandleDatabase();
+  const ref = useRef<HTMLDialogElement>(null);
+  const authCache = useAuthCache();
+  const [formData, setFormData] = useImmer(
+    props.saveState && props.open === 'update'
+      ? props.saveState
+      : { ...INITIAL_SAVE_STATE, user_id: authCache.authentication?.userID || '' },
+  );
+  const [hasError, setHasError] = useState(false);
+  const [sampleDataPanel, setSampleDataPanel] = useState<boolean | null>(false);
+  const formTitle = props.open === 'add' ? 'Add' : 'Update';
+
+  useEffect(() => {
+    if (props.saveState && props.open === 'update') {
+      setFormData(props.saveState);
+      setSampleDataPanel(null);
+    } else {
+      setSampleDataPanel(false);
+    }
+  }, [props.saveState]);
+
+  async function handleSubmit(saveStateData?: SaveStateI, forceAdd: boolean = false): Promise<void> {
+    if (!saveStateData) saveStateData = formData;
+    databaseHandler.submitDatabaseChange(saveStateData, props.open, forceAdd, () => {
+      closeDialog();
+    });
+  }
+
+  function closeDialog(): void {
+    setFormData({ ...INITIAL_SAVE_STATE, user_id: authCache.authentication?.userID || '' });
+    ref.current?.close();
+    props.onClose();
+  }
+
+  return (
+    <div className="lg:min-w-[50rem] p-6">
+      <>
+        {sampleDataPanel === true ? (
+          <SampleDatabaseSelector
+            onClick={(data) => {
+              setHasError(false);
+              handleSubmit({ ...data, user_id: authCache.authentication?.userID || '' });
+            }}
+          />
+        ) : (
+          <DatabaseForm
+            data={formData}
+            onChange={(data: SaveStateI, error: boolean) => {
+              setFormData({ ...data, id: formData.id });
+              setHasError(error);
+            }}
+          />
+        )}
+
+        {!(databaseHandler.connectionStatus.status === null) && (
+          <div className={`flex flex-col justify-center items-center`}>
+            <div className="flex justify-center items-center">
+              {databaseHandler.connectionStatus.verified === false && (
+                <Icon component="icon-[ic--baseline-error-outline]" className="text-secondary-400" />
+              )}
+              <p className="font-light text-sm	text-secondary-400	">{databaseHandler.connectionStatus.status}</p>
+            </div>
+            {databaseHandler.connectionStatus.verified === null && <progress className="progress w-56"></progress>}
+          </div>
+        )}
+
+        <div
+          className={`pt-4 flex flex-row gap-3 card-actions w-full justify-between items-center ${sampleDataPanel === true && 'hidden'}`}
+        >
+          <div className="flex justify-between items-center">
+            <Button
+              variantType="primary"
+              className="flex-grow"
+              label={
+                databaseHandler.connectionStatus.updating
+                  ? formTitle === 'Add'
+                    ? formTitle + 'ing...'
+                    : formTitle.slice(0, -1) + 'ing...'
+                  : formTitle
+              }
+              onClick={(event) => {
+                event.preventDefault();
+                handleSubmit();
+              }}
+              disabled={databaseHandler.connectionStatus.updating || hasError}
+            />
+            {props.open === 'update' && (
+              <Button
+                variantType="secondary"
+                className="flex-grow"
+                label={'Clone'}
+                onClick={(event) => {
+                  handleSubmit({ ...formData, name: formData.name + ' (copy)', id: nilUUID }, true);
+                }}
+                disabled={databaseHandler.connectionStatus.updating || hasError}
+              />
+            )}
+          </div>
+          <div className="flex justify-end align-center mx-2">
+            <div>
+              {sampleDataPanel === true ? (
+                <Button variant="outline" label="Go back" onClick={() => setSampleDataPanel(false)} />
+              ) : sampleDataPanel === false ? (
+                <>
+                  <h1 className="font-light text-xs">No data?</h1>
+                  <p className="font-light text-sm cursor-pointer underline" onClick={() => setSampleDataPanel(true)}>
+                    Try sample data
+                  </p>
+                </>
+              ) : (
+                ''
+              )}
+            </div>
+          </div>
+        </div>
+      </>
+    </div>
+  );
+};
diff --git a/libs/shared/lib/management/database/index.ts b/libs/shared/lib/management/database/index.ts
new file mode 100644
index 000000000..f723a67e6
--- /dev/null
+++ b/libs/shared/lib/management/database/index.ts
@@ -0,0 +1,2 @@
+export * from './Databases';
+export * from './UpsertDatabase';
diff --git a/libs/shared/lib/management/database/useHandleDatabase.ts b/libs/shared/lib/management/database/useHandleDatabase.ts
new file mode 100644
index 000000000..2f03281c9
--- /dev/null
+++ b/libs/shared/lib/management/database/useHandleDatabase.ts
@@ -0,0 +1,91 @@
+import {
+  SaveStateI,
+  wsTestDatabaseConnection,
+  wsCreateState,
+  wsUpdateState,
+  useAuthCache,
+  useAppDispatch,
+} from '../../data-access';
+import { useState } from 'react';
+import { addSaveState, selectSaveState, testedSaveState } from '../../data-access/store/sessionSlice';
+import { setSchemaLoading } from '../../data-access/store/schemaSlice';
+
+export type ConnectionStatus = {
+  updating: boolean;
+  status: null | string;
+  verified: boolean | null;
+};
+
+export const useHandleDatabase = () => {
+  const dispatch = useAppDispatch();
+  const [connectionStatus, setConnectionStatus] = useState<ConnectionStatus>({
+    updating: false,
+    status: null,
+    verified: null,
+  });
+
+  const authCache = useAuthCache();
+
+  async function submitDatabaseChange(
+    saveStateData: SaveStateI,
+    type: 'add' | 'update',
+    forceAdd: boolean = false,
+    concludedCallback: () => void,
+  ): Promise<void> {
+    setConnectionStatus(() => ({
+      updating: true,
+      status: 'Testing database connection',
+      verified: null,
+    }));
+
+    wsTestDatabaseConnection(saveStateData.db, (data) => {
+      if (!saveStateData) {
+        console.error('formData is null');
+        return;
+      }
+      if (saveStateData.user_id !== authCache.authentication?.userID && authCache.authentication?.userID) {
+        console.error('user_id is not equal to auth.userID');
+        saveStateData.user_id = authCache.authentication.userID;
+      }
+      if (data && data.status === 'success') {
+        setConnectionStatus((prevState) => ({
+          updating: false,
+          status: 'Database connection verified',
+          verified: true,
+        }));
+        dispatch(setSchemaLoading(true));
+        dispatch(selectSaveState(undefined));
+        if (type === 'add' || forceAdd) {
+          wsCreateState(saveStateData, (newSaveState) => {
+            dispatch(addSaveState(newSaveState));
+            dispatch(testedSaveState(newSaveState.id));
+            setConnectionStatus({
+              updating: false,
+              status: null,
+              verified: null,
+            });
+            concludedCallback();
+          });
+        } else {
+          dispatch(testedSaveState(data.saveStateID));
+          wsUpdateState(saveStateData, (updatedSaveState) => {
+            dispatch(addSaveState(updatedSaveState));
+            setConnectionStatus({
+              updating: false,
+              status: null,
+              verified: null,
+            });
+            concludedCallback();
+          });
+        }
+      } else {
+        setConnectionStatus((prevState) => ({
+          updating: false,
+          status: 'Database connection test failed',
+          verified: false,
+        }));
+      }
+    });
+  }
+  return { submitDatabaseChange, connectionStatus };
+};
diff --git a/libs/shared/lib/management/index.ts b/libs/shared/lib/management/index.ts
new file mode 100644
index 000000000..90a09e7d3
--- /dev/null
+++ b/libs/shared/lib/management/index.ts
@@ -0,0 +1,2 @@
+export * from './ManagementTrigger';
+export * from './ManagementDialog';
diff --git a/libs/shared/lib/schema/panel/Schema.tsx b/libs/shared/lib/schema/panel/Schema.tsx
index ef704b8f9..fce8bad96 100644
--- a/libs/shared/lib/schema/panel/Schema.tsx
+++ b/libs/shared/lib/schema/panel/Schema.tsx
@@ -3,11 +3,11 @@ import React, { useEffect, useMemo, useRef, useState } from 'react';
 import { useDispatch } from 'react-redux';
 import ReactFlow, { Edge, MiniMap, Node, ReactFlowInstance, ReactFlowProvider, useEdgesState, useNodesState } from 'reactflow';
 import 'reactflow/dist/style.css';
-import { Panel } from '../../components';
+import { Icon, Panel } from '../../components';
 import { Button } from '../../components/buttons';
 import { Popover, PopoverContent, PopoverTrigger } from '../../components/layout/Popover';
 import { Tooltip, TooltipContent, TooltipTrigger } from '../../components/tooltip/Tooltip';
-import { useSchemaGraph, useSchemaSettings, useSearchResultSchema } from '../../data-access';
+import { useSchema, useSchemaGraph, useSchemaSettings, useSearchResultSchema } from '../../data-access';
 import { resultSetFocus } from '../../data-access/store/interactionSlice';
 import { toSchemaGraphology } from '../../data-access/store/schemaSlice';
 import { AlgorithmToLayoutProvider, AllLayoutAlgorithms, LayoutFactory } from '../../graph-layout';
@@ -81,8 +81,8 @@ export const Schema = (props: Props) => {
   const reactFlowRef = useRef<HTMLDivElement>(null);
 
   // In case the schema is updated
-  const schemaGraph = useSchemaGraph();
-  const schemaGraphology = useMemo(() => toSchemaGraphology(schemaGraph), [schemaGraph]);
+  const schema = useSchema();
+  const schemaGraphology = useMemo(() => toSchemaGraphology(schema.graph), [schema.graph]);
   const layout = useRef<AlgorithmToLayoutProvider<AllLayoutAlgorithms>>();
 
   const [viewSelected, setViewState] = useState<SchemaViewState>(SchemaViewState.SchemaListS);
@@ -226,7 +226,7 @@ export const Schema = (props: Props) => {
     } else {
       layoutList();
     }
-  }, [schemaGraph, settings]);
+  }, [schema.graph, settings]);
 
   useEffect(() => {
     setNodes((nds) =>
@@ -303,7 +303,7 @@ export const Schema = (props: Props) => {
                 iconComponent="icon-[ic--baseline-content-copy]"
                 onClick={() => {
                   // Copy the schema to the clipboard
-                  navigator.clipboard.writeText(JSON.stringify(schemaGraph, null, 2));
+                  navigator.clipboard.writeText(JSON.stringify(schema.graph, null, 2));
                 }}
               />
             </TooltipTrigger>
@@ -352,7 +352,11 @@ export const Schema = (props: Props) => {
       }
     >
       <div className="schema-panel w-full h-full flex flex-col justify-between" ref={reactFlowRef}>
-        {nodes.length === 0 ? (
+        {schema.loading ? (
+          <div className="h-full flex flex-col items-center justify-center">
+            <Icon component="icon-[mingcute--loading-line]" size={56} className="w-15 h-15 animate-spin " />
+          </div>
+        ) : nodes.length === 0 ? (
           <p className="m-3 text-xl font-bold">No Elements</p>
         ) : (
           <ReactFlowProvider>
diff --git a/libs/shared/lib/vis/components/VisualizationPanel.tsx b/libs/shared/lib/vis/components/VisualizationPanel.tsx
index e705499e9..16e539086 100644
--- a/libs/shared/lib/vis/components/VisualizationPanel.tsx
+++ b/libs/shared/lib/vis/components/VisualizationPanel.tsx
@@ -31,7 +31,7 @@ export const Visualizations: Record<string, PromiseFunc> = {
   }),
   ...(isVisualizationReleased('MapVis') && { MapVis: () => import('../visualizations/mapvis/mapvis') }),
   ...(isVisualizationReleased('Vis0D') && { Vis0D: () => import('../visualizations/Vis0D/Vis0D') }),
-  ...(isVisualizationReleased('Vis1D') && { Vis0D: () => import('../visualizations/vis1D/Vis1D') }),
+  ...(isVisualizationReleased('Vis1D') && { Vis1D: () => import('../visualizations/vis1D/Vis1D') }),
 };
 
 export const VISUALIZATION_TYPES: string[] = Object.keys(Visualizations);
diff --git a/libs/shared/lib/vis/components/VisualizationTabBar.tsx b/libs/shared/lib/vis/components/VisualizationTabBar.tsx
index 9d229a1a1..b186aebf8 100644
--- a/libs/shared/lib/vis/components/VisualizationTabBar.tsx
+++ b/libs/shared/lib/vis/components/VisualizationTabBar.tsx
@@ -17,11 +17,11 @@ export default function VisualizationTabBar(props: { fullSize: () => void; expor
     e.dataTransfer.setData('text/plain', i.toString());
   };
 
-  const handleDragOver = (e: React.DragEvent<HTMLDivElement>) => {
+  const handleDragOver = (e: React.DragEvent<HTMLButtonElement>) => {
     e.preventDefault();
   };
 
-  const handleDrop = (e: React.DragEvent<HTMLDivElement>, i: number) => {
+  const handleDrop = (e: React.DragEvent<HTMLButtonElement>, i: number) => {
     e.preventDefault();
     const draggedVisIndex = e.dataTransfer.getData('text/plain');
     dispatch(reorderVisState({ id: Number(draggedVisIndex), newPosition: i }));
-- 
GitLab