Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • graphpolaris/frontend-v2
  • rijkheere/frontend-v-2-reordering-paoh
2 results
Show changes
Commits on Source (5)
Showing
with 224 additions and 176 deletions
......@@ -24,6 +24,7 @@ yarn-error.log*
.pnpm-debug.log*
# local env files
.env
.env.local
.env.development.local
.env.test.local
......
......@@ -13,6 +13,8 @@ First run `pnpm i` on the root of the workspace to install all dependencies. It
If you need to install a new dependency or upgrade an existing one, do so in the respective package.json and rerun `pnpm i` in the root of the workspace. If you find any issues, feel free to delete the node_modules folder from the workspace root and from the app/lib which you are changing the dependency and rerun the `pnpm i` command from the root of the workspace. Most issues are solved by then.
Secondly, make sure you create a local `.env` file. For local development, you can simply copy the contents of the `.env.development` template in the `/apps/web` directory to a new `.env` file and you should be good to go.
### Running Storybook.js
To run the dev storybook (implementing visualizations) simply run `pnpm sb` and once it is running, ctrl-click the link what appears in the terminal. The url should be [http://localhost:6006].
......
GRAPHPOLARIS_VERSION=dev
BACKEND_URL=http://localhost
BACKEND_WSS_URL=ws://localhost:3001/
BACKEND_WSS_URL=ws://localhost:3001/ws
STAGING=dev
SKIP_LOGIN=true
BACKEND_USER=:3000
BACKEND_USER=:3001
GRAPHPOLARIS_VERSION=dev
SENTRY_ENABLED=false
......@@ -21,4 +21,4 @@ WIP_MAPVIS=true
WIP_INSIGHT_SHARING=true
WIP_VIEWER_PERMISSIONS=true
WIP_SHARABLE_EXPLORATION=true
\ No newline at end of file
WIP_SHARABLE_EXPLORATION=true
VITE_BACKEND_URL=http://localhost
VITE_BACKEND_WSS_URL=ws://localhost:3001/
VITE_STAGING=dev
VITE_SKIP_LOGIN=true
VITE_BACKEND_USER=:3000
VITE_BACKEND_QUERY=:3003
VITE_BACKEND_SCHEMA=:3002
GRAPHPOLARIS_VERSION=dev
BACKEND_URL=http://localhost
BACKEND_WSS_URL=ws://localhost:3001/
STAGING=dev
SKIP_LOGIN=true
BACKEND_USER=:3000
GRAPHPOLARIS_VERSION=dev
SENTRY_ENABLED=false
SENTRY_URL=
......
......@@ -3,7 +3,7 @@ VITE_BACKEND_WSS_URL=ws://api.graphpolaris.com/socket/
VITE_STAGING=prod
VITE_SKIP_LOGIN=false
VITE_BACKEND_USER=/user
VITE_BACKEND_USER=/socket
VITE_BACKEND_QUERY=/query
VITE_BACKEND_SCHEMA=/schema
......
......@@ -8,16 +8,16 @@
/* The comment above was added so the code coverage wouldn't count this file towards code coverage.
* We do not test components/renderfunctions/styling files.
* See testing plan for more details.*/
import React, { useState, useRef, useEffect, useCallback } from 'react';
import React, { useState, useRef, useEffect } from 'react';
import { useAuthCache, useAuthentication } from '@graphpolaris/shared/lib/data-access';
import { DropdownItem } from '@graphpolaris/shared/lib/components/dropdowns';
import GpLogo from './gp-logo';
import { Popover, PopoverContent, PopoverTrigger } from '@graphpolaris/shared/lib/components/layout/Popover';
import { useDispatch } from 'react-redux';
import { showManagePermissions, showSharableExploration } from 'config';
import { Button, Dialog, DialogContent, DialogTrigger, useActiveSaveStateAuthorization, useSessionCache } from '@graphpolaris/shared';
import { showSharableExploration } from 'config';
import { Button, useActiveSaveStateAuthorization } from '@graphpolaris/shared';
import { ManagementTrigger, ManagementViews } from '@graphpolaris/shared/lib/management';
import { Members } from '@graphpolaris/shared/lib/management/Members';
const AuthURL = import.meta.env.GP_AUTH_URL;
export const Navbar = () => {
const dropdownRef = useRef<HTMLDivElement>(null);
......@@ -88,7 +88,7 @@ export const Navbar = () => {
<DropdownItem
value="Log out"
onClick={() => {
location.replace(`${import.meta.env['GP_AUTH_URL']}/flows/-/default/invalidation/`);
location.replace(`${AuthURL}/outpost.goauthentik.io/sign_out`);
}}
/>
</>
......
......@@ -24,7 +24,7 @@ interface TooltipOptions {
placement?: Placement;
open?: boolean;
onOpenChange?: (open: boolean) => void;
boundaryElement?: React.RefObject<HTMLElement> | null;
boundaryElement?: React.RefObject<HTMLElement> | HTMLElement | null;
showArrow?: boolean;
interactive?: boolean;
}
......@@ -60,14 +60,14 @@ export function useTooltip({
flip({
crossAxis: placement.includes('-'),
fallbackAxisSideDirection: 'start',
padding: 5
padding: 5,
}),
shift({ padding: 5 }),
],
};
if (boundaryElement != null) {
const boundary = boundaryElement?.current ?? undefined;
const boundary = boundaryElement instanceof HTMLElement ? (boundaryElement ?? undefined) : (boundaryElement?.current ?? undefined);
config.middleware.find((x) => x.name == 'flip')!.options[0].boundary = boundary;
config.middleware.find((x) => x.name == 'shift')!.options[0].boundary = boundary;
config.middleware.push(hide({ boundary }));
......@@ -125,9 +125,7 @@ export function Tooltip({ children, ...options }: { children: React.ReactNode }
// or other positioning options.
const tooltip = useTooltip(options);
return <TooltipContext.Provider value={tooltip}>
{children}
</TooltipContext.Provider>;
return <TooltipContext.Provider value={tooltip}>{children}</TooltipContext.Provider>;
}
export const TooltipTrigger = React.forwardRef<HTMLElement, React.HTMLProps<HTMLElement> & { asChild?: boolean; x?: number; y?: number }>(
......
......@@ -77,11 +77,13 @@ export const EventBus = (props: { onRunQuery: Function; onAuthorized: Function }
console.debug('Setting state fetched from database', saveStateID, saveStates);
const state = saveStates[saveStateID];
if (state) {
dispatch(setQuerybuilderNodes(state.queryBuilder));
if (state.queries && state.queries.length > 0) {
dispatch(setQuerybuilderNodes(state.queries[0]));
}
dispatch(
setVisualizationState(
Object.keys(state.visualization).length !== 0 // should only occur in mock data
? (state.visualization as VisState)
Object.keys(state.visualizations).length !== 0 // should only occur in mock data
? (state.visualizations as VisState)
: {
activeVisualizationIndex: -1,
openVisualizationArray: [],
......@@ -189,7 +191,7 @@ export const EventBus = (props: { onRunQuery: Function; onAuthorized: Function }
if (response && response.result) {
dispatch(setQueryText(response));
}
}, 'query_translation_result');
}, 'queryTranslation_result');
login();
......@@ -199,7 +201,7 @@ export const EventBus = (props: { onRunQuery: Function; onAuthorized: Function }
unsubs.forEach((unsub) => {
unsub();
});
Broker.instance().unSubscribeAll('query_translation_result');
Broker.instance().unSubscribeAll('queryTranslation_result');
Broker.instance().unSubscribeAll('schema_stats_result');
Broker.instance().unSubscribeAll('schema_inference');
};
......@@ -208,9 +210,9 @@ export const EventBus = (props: { onRunQuery: Function; onAuthorized: Function }
useEffect(() => {
if (session.currentSaveState) {
let state = { ...session.saveStates[session.currentSaveState] };
if (!isEqual(state.queryBuilder, queryBuilder) && state.queryBuilder?.graph?.nodes) {
console.debug('Updating queryBuilder state', state.queryBuilder, queryBuilder);
state.queryBuilder = { ...queryBuilder };
if (!isEqual(state.queries?.[0], queryBuilder)) {
console.debug('Updating queryBuilder state', state.queries, queryBuilder);
state.queries = [{ ...queryBuilder }];
dispatch(updateSelectedSaveState(state));
wsUpdateState(state);
}
......@@ -220,9 +222,9 @@ export const EventBus = (props: { onRunQuery: Function; onAuthorized: Function }
useEffect(() => {
if (session.currentSaveState) {
let state = { ...session.saveStates[session.currentSaveState] };
if (!isEqual(state.visualization, visState)) {
if (!isEqual(state.visualizations, visState)) {
console.debug('Updating visState state', visState);
state.visualization = { ...visState };
state.visualizations = { ...visState };
dispatch(updateSelectedSaveState(state));
wsUpdateState(state);
}
......
......@@ -12,7 +12,7 @@ import { ReceiveMessageI, SendMessageI, SendMessageWithSessionI } from './types'
* It works with routingkeys, a listener can subscribe to messages from the backend with a specific routingkey.
* Possible routingkeys:
* - query_result: Contains an object with nodes and edges or a numerical result.
* - query_translation_result: Contains the query translated to the database language.
* - queryTranslation_result: Contains the query translated to the database language.
* - schema_result: Contains the schema of the users database.
* - query_status_update: Contains an update to if a query is being executed.
* - query_database_error: Contains the error received from the database.
......
......@@ -24,9 +24,9 @@ export function wsManualQueryRequest(query: string) {
type QueryTranslationResponse = (data: QueryBuilderText) => void;
export function wsQueryTranslationSubscription(callback: QueryTranslationResponse) {
const id = Broker.instance().subscribe(callback, 'query_translation_result');
const id = Broker.instance().subscribe(callback, 'queryTranslation_result');
return () => {
Broker.instance().unSubscribe('query_translation_result', id);
Broker.instance().unSubscribe('queryTranslation_result', id);
};
}
......
import { QueryBuilderState } from '../store/querybuilderSlice';
import { QueryBuilderState, SchemaState } from '../store/querybuilderSlice';
import { URLParams, setParam } from '../api/url';
import { Broker } from './broker';
import { DateStringStatement } from '../../querybuilder/model/logic/general';
......@@ -9,8 +9,8 @@ export const databaseNameMapping: string[] = ['arangodb', 'neo4j'];
export const databaseProtocolMapping: string[] = ['neo4j://', 'neo4j+s://', 'bolt://', 'bolt+s://'];
export enum DatabaseType {
ArangoDB = 0,
Neo4j = 1,
ArangoDB = 'arango',
Neo4j = 'neo4j',
}
export enum DatabaseStatus {
......@@ -26,7 +26,7 @@ export type DatabaseInfo = {
protocol: string;
username: string;
password: string;
type: number;
type: string;
};
export const SaveStateAuthorizationObjectsArray = ['database', 'visualization', 'query', 'schema'] as const;
......@@ -42,13 +42,15 @@ export const nilUUID = '00000000-0000-0000-0000-000000000000';
export type SaveStateI = {
id: string;
user_id: string;
userId: string;
name: string;
db: DatabaseInfo;
schema: any;
queryBuilder: QueryBuilderState;
visualization: VisState | {};
share_state: any;
dbConnections: DatabaseInfo[];
schemas: SchemaState[];
queries: QueryBuilderState[];
visualizations: VisState;
createdAt: string;
updatedAt: string;
shareState: any;
};
type GetStateResponse = (data: SaveStateI) => void;
......@@ -169,6 +171,11 @@ export function wsUpdateState(request: SaveStateI, callback?: GetStateResponse)
}
export function wsTestDatabaseConnection(dbConnection: DatabaseInfo, callback?: TestSaveStateConnectionResponse) {
if (!dbConnection) {
console.warn('dbConnection is undefined on wsTestDatabaseConnection');
if (callback) callback({ status: 'fail', saveStateID: '' });
return;
}
Broker.instance().sendMessage(
{
key: 'dbConnection',
......
......@@ -20,10 +20,11 @@ export const useAuthentication = () => {
const login = () => {
fetch(`${domain}${userURI}/headers`, fetchSettings)
.then((res) =>
.then((res) => {
res
.json()
.then((res: UserAuthenticationHeader) => {
console.log(res, 'headers');
dispatch(
authenticated({
username: res.username,
......@@ -35,8 +36,8 @@ export const useAuthentication = () => {
}),
);
})
.catch(handleError),
)
.catch(handleError);
})
.catch(handleError);
};
......
......@@ -36,6 +36,10 @@ export type QueryBuilderState = {
unionTypes: { [nodeId: string]: QueryUnionType };
};
export type SchemaState = {
settings: Record<string, any>;
}
// Define the initial state using that type
export const initialState: QueryBuilderState = {
graph: defaultGraph(),
......@@ -65,6 +69,11 @@ export const querybuilderSlice = createSlice({
state.graph = action.payload;
state.ignoreReactivity = false;
},
/**
* Sets the querybuilder nodes, settings, and attributes being shown,
* if the payload contains the required information.
* @param {QueryBuilderState} action.payload the payload with the new state
*/
setQuerybuilderNodes: (state: QueryBuilderState, action: PayloadAction<QueryBuilderState>) => {
if (action.payload.graph?.nodes && action.payload.graph?.edges) {
state.graph = action.payload.graph;
......
......@@ -5,8 +5,8 @@ import { isEqual } from 'lodash-es';
export type VisStateSettings = VisualizationSettingsType[];
export type VisState = {
activeVisualizationIndex: number;
openVisualizationArray: VisStateSettings;
activeVisualizationIndex: number; // uses underscore_case to match data model from backend
openVisualizationArray: VisStateSettings; // uses underscore_case to match data model from backend
};
export const initialState: VisState = {
......
......@@ -12,13 +12,13 @@ export function ConnectionInspector() {
<span className="text-xs font-semibold">Name</span>
<span className="text-xs">{session.saveStates[session.currentSaveState].name}</span>
<span className="text-xs font-semibold">Database</span>
<span className="text-xs">{session.saveStates[session.currentSaveState].db.internalDatabaseName}</span>
<span className="text-xs">{session.saveStates[session.currentSaveState].dbConnections?.[0]?.internalDatabaseName}</span>
<span className="text-xs font-semibold">Protocol</span>
<span className="text-xs">{session.saveStates[session.currentSaveState].db.protocol}</span>
<span className="text-xs">{session.saveStates[session.currentSaveState].dbConnections?.[0]?.protocol}</span>
<span className="text-xs font-semibold">Hostname</span>
<span className="text-xs">{session.saveStates[session.currentSaveState].db.url}</span>
<span className="text-xs">{session.saveStates[session.currentSaveState].dbConnections?.[0]?.url}</span>
<span className="text-xs font-semibold">Port</span>
<span className="text-xs">{session.saveStates[session.currentSaveState].db.port}</span>
<span className="text-xs">{session.saveStates[session.currentSaveState].dbConnections?.[0]?.port}</span>
</div>
)}
</div>
......
......@@ -15,7 +15,6 @@ export function InspectorPanel(props: { children?: React.ReactNode }) {
const selection = useSelection();
const focus = useFocus();
const dispatch = useDispatch();
const { activeVisualizationIndex } = useVisualization();
const inspector = useMemo(() => {
if (selection) return <SelectionConfig />;
......
......@@ -6,20 +6,24 @@ import { databaseNameMapping, databaseProtocolMapping, DatabaseType, Input, nilU
export const INITIAL_SAVE_STATE: SaveStateI = {
id: nilUUID,
name: 'Untitled',
db: {
username: 'neo4j',
password: 'DevOnlyPass',
url: 'localhost',
port: 7687,
protocol: 'neo4j://',
internalDatabaseName: 'neo4j',
type: DatabaseType.Neo4j,
},
schema: {},
queryBuilder: qbInitialState,
visualization: {},
share_state: {},
user_id: '',
dbConnections: [
{
username: 'neo4j',
password: 'DevOnlyPass',
url: 'localhost',
port: 7687,
protocol: 'neo4j://',
internalDatabaseName: 'neo4j',
type: DatabaseType.Neo4j,
},
],
schemas: [{ settings: {} }],
queries: [qbInitialState],
visualizations: { activeVisualizationIndex: -1, openVisualizationArray: [] },
shareState: {},
createdAt: '',
updatedAt: '',
userId: '',
};
export const DatabaseForm = (props: { data: SaveStateI; onChange: (data: SaveStateI, error: boolean) => void }) => {
......@@ -29,7 +33,7 @@ export const DatabaseForm = (props: { data: SaveStateI; onChange: (data: SaveSta
function handlePortChanged(port: string): void {
if (!isNaN(Number(port)))
setFormData((draft) => {
draft.db.port = Number(port);
draft.dbConnections[0].port = Number(port);
return draft;
});
}
......@@ -54,7 +58,7 @@ export const DatabaseForm = (props: { data: SaveStateI; onChange: (data: SaveSta
<Input
type="text"
label="Internal database name"
value={formData.db.internalDatabaseName}
value={formData.dbConnections[0].internalDatabaseName}
placeholder="internalDatabaseName"
required
errorText="This field is required"
......@@ -64,7 +68,7 @@ export const DatabaseForm = (props: { data: SaveStateI; onChange: (data: SaveSta
}}
onChange={(value: string) =>
setFormData((draft) => {
draft.db.internalDatabaseName = value;
draft.dbConnections[0].internalDatabaseName = value;
})
}
/>
......@@ -75,11 +79,11 @@ export const DatabaseForm = (props: { data: SaveStateI; onChange: (data: SaveSta
className="w-full"
label="Database Type"
required
value={databaseNameMapping[formData.db.type]}
value={formData.dbConnections[0].type}
options={databaseNameMapping}
onChange={(value: string | number) => {
setFormData((draft) => {
draft.db.type = databaseNameMapping.indexOf(value.toString());
draft.dbConnections[0].type = value.toString();
});
}}
/>
......@@ -88,12 +92,12 @@ export const DatabaseForm = (props: { data: SaveStateI; onChange: (data: SaveSta
type="dropdown"
label="Database Protocol"
required
value={formData.db.protocol}
value={formData.dbConnections[0].protocol}
options={databaseProtocolMapping}
info="Protocol via which the database connection will be established"
onChange={(value: string | number) => {
setFormData((draft) => {
draft.db.protocol = value.toString();
draft.dbConnections[0].protocol = value.toString();
});
}}
/>
......@@ -103,7 +107,7 @@ export const DatabaseForm = (props: { data: SaveStateI; onChange: (data: SaveSta
<Input
type="text"
label="Hostname/IP"
value={formData.db.url}
value={formData.dbConnections[0].url}
placeholder="neo4j"
required
errorText="This field is required"
......@@ -114,7 +118,7 @@ export const DatabaseForm = (props: { data: SaveStateI; onChange: (data: SaveSta
}}
onChange={(value: string) => {
setFormData((draft) => {
draft.db.url = value;
draft.dbConnections[0].url = value;
});
}}
/>
......@@ -122,7 +126,7 @@ export const DatabaseForm = (props: { data: SaveStateI; onChange: (data: SaveSta
<Input
type="text"
label="Port"
value={formData.db.port.toString()}
value={formData.dbConnections[0].port.toString()}
placeholder="neo4j"
required
errorText="Must be between 1 and 9999"
......@@ -133,7 +137,7 @@ export const DatabaseForm = (props: { data: SaveStateI; onChange: (data: SaveSta
}}
onChange={(value: string) => {
setFormData((draft) => {
draft.db.port = Number(value);
draft.dbConnections[0].port = Number(value);
});
}}
/>
......@@ -143,7 +147,7 @@ export const DatabaseForm = (props: { data: SaveStateI; onChange: (data: SaveSta
<Input
type="text"
label="Username"
value={formData.db.username}
value={formData.dbConnections[0].username}
placeholder="username"
required
errorText="This field is required"
......@@ -154,7 +158,7 @@ export const DatabaseForm = (props: { data: SaveStateI; onChange: (data: SaveSta
}}
onChange={(value: string) => {
setFormData((draft) => {
draft.db.username = value;
draft.dbConnections[0].username = value;
});
}}
/>
......@@ -163,7 +167,7 @@ export const DatabaseForm = (props: { data: SaveStateI; onChange: (data: SaveSta
type="text"
visible={false}
label="Password"
value={formData.db.password}
value={formData.dbConnections[0].password}
placeholder="password"
required
errorText="This field is required"
......@@ -174,7 +178,7 @@ export const DatabaseForm = (props: { data: SaveStateI; onChange: (data: SaveSta
}}
onChange={(value: string) => {
setFormData((draft) => {
draft.db.password = value;
draft.dbConnections[0].password = value;
});
}}
/>
......
......@@ -66,7 +66,8 @@ export function Databases({ onClose, saveStates, changeActive, setSelectedSaveSt
if (saveStates[a].name.toLowerCase() <= saveStates[b].name.toLowerCase()) return dir;
else return -dir;
} else {
if (saveStates[a].db[orderBy[0]].toLowerCase() <= saveStates[b].db[orderBy[0]].toLowerCase()) return dir;
if (saveStates[a].dbConnections?.[0][orderBy[0]].toLowerCase() <= saveStates[b].dbConnections?.[0][orderBy[0]].toLowerCase())
return dir;
else return -dir;
}
}),
......@@ -119,10 +120,10 @@ export function Databases({ onClose, saveStates, changeActive, setSelectedSaveSt
</Button>
</td>
<td className="text-left">
<span className="font-light">{saveStates[key].db.protocol}</span>
<span className="font-light">{saveStates[key].dbConnections?.[0]?.protocol}</span>
</td>
<td className="text-left">
<span className="font-light">{saveStates[key].db.url}</span>
<span className="font-light">{saveStates[key].dbConnections?.[0]?.url}</span>
</td>
<td className="text-right flex justify-end">
<Button
......
......@@ -13,120 +13,144 @@ export const sampleSaveStates: Array<SaveStateSampleI> = [
name: 'Recommendations',
subtitle: 'Hosted by Neo4j',
description: 'Network of movies, actors, directors and reviews by people',
db: {
username: 'recommendations',
password: 'recommendations',
url: 'demo.neo4jlabs.com',
port: 7687,
protocol: 'neo4j+s://',
internalDatabaseName: 'recommendations',
type: DatabaseType.Neo4j,
},
schema: {},
queryBuilder: qbInitialState,
visualization: {},
share_state: {},
user_id: '',
dbConnections: [
{
username: 'recommendations',
password: 'recommendations',
url: 'demo.neo4jlabs.com',
port: 7687,
protocol: 'neo4j+s://',
internalDatabaseName: 'recommendations',
type: DatabaseType.Neo4j,
},
],
schemas: [],
queries: [qbInitialState],
visualizations: { activeVisualizationIndex: -1, openVisualizationArray: [] },
shareState: {},
userId: '',
createdAt: '',
updatedAt: '',
},
{
id: nilUUID,
name: 'Movies',
subtitle: 'Hosted by Neo4j',
description: 'Movies and people related to those movies as actors, directors and producers',
db: {
username: 'movies',
password: 'movies',
url: 'demo.neo4jlabs.com',
port: 7687,
protocol: 'neo4j+s://',
internalDatabaseName: 'movies',
type: DatabaseType.Neo4j,
},
schema: {},
queryBuilder: qbInitialState,
visualization: {},
share_state: {},
user_id: '',
dbConnections: [
{
username: 'movies',
password: 'movies',
url: 'demo.neo4jlabs.com',
port: 7687,
protocol: 'neo4j+s://',
internalDatabaseName: 'movies',
type: DatabaseType.Neo4j,
},
],
schemas: [],
queries: [qbInitialState],
visualizations: { activeVisualizationIndex: -1, openVisualizationArray: [] },
shareState: {},
userId: '',
createdAt: '',
updatedAt: '',
},
{
id: nilUUID,
name: 'Northwind',
subtitle: 'Hosted by Neo4j',
description: 'Retail-system with products, orders, customers, suppliers and employees',
db: {
username: 'northwind',
password: 'northwind',
url: 'demo.neo4jlabs.com',
port: 7687,
protocol: 'neo4j+s://',
internalDatabaseName: 'northwind',
type: DatabaseType.Neo4j,
},
schema: {},
queryBuilder: qbInitialState,
visualization: {},
share_state: {},
user_id: '',
dbConnections: [
{
username: 'northwind',
password: 'northwind',
url: 'demo.neo4jlabs.com',
port: 7687,
protocol: 'neo4j+s://',
internalDatabaseName: 'northwind',
type: DatabaseType.Neo4j,
},
],
schemas: [],
queries: [qbInitialState],
visualizations: { activeVisualizationIndex: -1, openVisualizationArray: [] },
shareState: {},
userId: '',
createdAt: '',
updatedAt: '',
},
{
id: nilUUID,
name: 'Fincen',
subtitle: 'Hosted by Neo4j',
description: 'FinCEN files investigation for banks and countries',
db: {
username: 'fincen',
password: 'fincen',
url: 'demo.neo4jlabs.com',
port: 7687,
protocol: 'neo4j+s://',
internalDatabaseName: 'fincen',
type: DatabaseType.Neo4j,
},
schema: {},
queryBuilder: qbInitialState,
visualization: {},
share_state: {},
user_id: '',
dbConnections: [
{
username: 'fincen',
password: 'fincen',
url: 'demo.neo4jlabs.com',
port: 7687,
protocol: 'neo4j+s://',
internalDatabaseName: 'fincen',
type: DatabaseType.Neo4j,
},
],
schemas: [],
queries: [qbInitialState],
visualizations: { activeVisualizationIndex: -1, openVisualizationArray: [] },
shareState: {},
userId: '',
createdAt: '',
updatedAt: '',
},
{
id: nilUUID,
name: 'Slack',
subtitle: 'Hosted by Neo4j',
description: 'Communication network consisting of several types of users and messages',
db: {
username: 'slack',
password: 'slack',
url: 'demo.neo4jlabs.com',
port: 7687,
protocol: 'neo4j+s://',
internalDatabaseName: 'slack',
type: DatabaseType.Neo4j,
},
schema: {},
queryBuilder: qbInitialState,
visualization: {},
share_state: {},
user_id: '',
dbConnections: [
{
username: 'slack',
password: 'slack',
url: 'demo.neo4jlabs.com',
port: 7687,
protocol: 'neo4j+s://',
internalDatabaseName: 'slack',
type: DatabaseType.Neo4j,
},
],
schemas: [],
queries: [qbInitialState],
visualizations: { activeVisualizationIndex: -1, openVisualizationArray: [] },
shareState: {},
userId: '',
createdAt: '',
updatedAt: '',
},
{
id: nilUUID,
name: 'Game of Thrones',
subtitle: 'Hosted by Neo4j',
description: 'Character interactions and actors in the Game of Thrones movie',
db: {
username: 'gameofthrones',
password: 'gameofthrones',
url: 'demo.neo4jlabs.com',
port: 7687,
protocol: 'neo4j+s://',
internalDatabaseName: 'gameofthrones',
type: DatabaseType.Neo4j,
},
schema: {},
queryBuilder: qbInitialState,
visualization: {},
share_state: {},
user_id: '',
dbConnections: [
{
username: 'gameofthrones',
password: 'gameofthrones',
url: 'demo.neo4jlabs.com',
port: 7687,
protocol: 'neo4j+s://',
internalDatabaseName: 'gameofthrones',
type: DatabaseType.Neo4j,
},
],
schemas: [],
queries: [qbInitialState],
visualizations: { activeVisualizationIndex: -1, openVisualizationArray: [] },
shareState: {},
userId: '',
createdAt: '',
updatedAt: '',
},
];
......
......@@ -16,10 +16,10 @@ export const UpsertDatabase = (props: {
const databaseHandler = useHandleDatabase();
const ref = useRef<HTMLDialogElement>(null);
const authCache = useAuthCache();
const [formData, setFormData] = useImmer(
const [formData, setFormData] = useImmer<SaveStateI>(
props.saveState && props.open === 'update'
? props.saveState
: { ...INITIAL_SAVE_STATE, user_id: authCache.authentication?.userID || '' },
: { ...INITIAL_SAVE_STATE, userId: authCache.authentication?.userID || '' },
);
const [hasError, setHasError] = useState(false);
const [sampleDataPanel, setSampleDataPanel] = useState<boolean | null>(false);
......@@ -42,7 +42,7 @@ export const UpsertDatabase = (props: {
}
function closeDialog(): void {
setFormData({ ...INITIAL_SAVE_STATE, user_id: authCache.authentication?.userID || '' });
setFormData({ ...INITIAL_SAVE_STATE, userId: authCache.authentication?.userID || '' });
ref.current?.close();
props.onClose();
}
......@@ -54,7 +54,7 @@ export const UpsertDatabase = (props: {
<SampleDatabaseSelector
onClick={(data) => {
setHasError(false);
handleSubmit({ ...data, user_id: authCache.authentication?.userID || '' });
handleSubmit({ ...data, userId: authCache.authentication?.userID || '' });
}}
/>
) : (
......