From fda6a5c0313291e5f1eba3432e0c3785b0fcb828 Mon Sep 17 00:00:00 2001 From: Leonardo Christino <leomilho@gmail.com> Date: Mon, 17 Jul 2023 09:50:55 +0200 Subject: [PATCH] feat(query): enable backend connection --- apps/web/.env | 4 +- apps/web/.env.development | 7 ++ apps/web/.env.production | 9 +- apps/web/node.d.ts | 1 + apps/web/package.json | 96 +++++++++---------- apps/web/src/app/app.tsx | 14 +-- apps/web/src/components/navbar/navbar.tsx | 5 +- apps/web/src/environments/variables.ts | 3 +- apps/web/vite.config.ts | 3 +- libs/shared/.env | 3 - libs/shared/lib/data-access/api/database.ts | 10 +- libs/shared/lib/data-access/api/query.ts | 7 +- libs/shared/lib/data-access/api/schema.ts | 6 +- libs/shared/lib/data-access/api/user.ts | 5 +- .../lib/data-access/authorization/useAuth.jsx | 27 ++++-- .../WebSocketHandler.tsx | 2 +- .../shared/lib/data-access/store/authSlice.ts | 12 ++- .../panel/querybuilder.module.scss | 75 ++++++++------- .../lib/querybuilder/panel/querybuilder.tsx | 43 ++++++++- .../customFlowPills/entitypill/entitypill.tsx | 4 +- .../schema/pills/nodes/entity/entity-node.tsx | 16 ++-- libs/shared/node.d.ts | 12 +++ turbo.json | 40 ++++---- 23 files changed, 246 insertions(+), 158 deletions(-) create mode 100644 apps/web/.env.development delete mode 100644 libs/shared/.env create mode 100644 libs/shared/node.d.ts diff --git a/apps/web/.env b/apps/web/.env index f651adbd0..31d4bea3b 100644 --- a/apps/web/.env +++ b/apps/web/.env @@ -1,2 +1,2 @@ -VITE_BACKEND_URL=api.graphpolaris.com -VITE_STAGING=local +VITE_BACKEND_URL=https://api.graphpolaris.com +VITE_STAGING=local diff --git a/apps/web/.env.development b/apps/web/.env.development new file mode 100644 index 000000000..f6b68d9b0 --- /dev/null +++ b/apps/web/.env.development @@ -0,0 +1,7 @@ +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=:8080 +VITE_BACKEND_SCHEMA=:3002 \ No newline at end of file diff --git a/apps/web/.env.production b/apps/web/.env.production index 895239e15..cf5c3e8e8 100644 --- a/apps/web/.env.production +++ b/apps/web/.env.production @@ -1,2 +1,7 @@ -VITE_BACKEND_URL=api.graphpolaris.com -VITE_STAGING=prod \ No newline at end of file +VITE_BACKEND_URL=https://api.graphpolaris.com +VITE_BACKEND_WSS_URL=ws://api.graphpolaris.com/socket/ +VITE_STAGING=prod +VITE_SKIP_LOGIN=false +VITE_BACKEND_USER=/user +VITE_BACKEND_QUERY=:8080 +VITE_BACKEND_SCHEMA=/schema \ No newline at end of file diff --git a/apps/web/node.d.ts b/apps/web/node.d.ts index 515e679e7..34f3d984d 100644 --- a/apps/web/node.d.ts +++ b/apps/web/node.d.ts @@ -1,6 +1,7 @@ interface ImportMeta { env: { VITE_BACKEND_URL: string; + VITE_BACKEND_WSS_URL: string; VITE_STAGING: string; VITE_KEYCLOAK_URL: string; VITE_KEYCLOAK_REALM: string; diff --git a/apps/web/package.json b/apps/web/package.json index 9dc529d75..6de2cebe7 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -1,48 +1,48 @@ -{ - "name": "web", - "private": true, - "version": "0.0.0", - "type": "module", - "scripts": { - "dev": "vite --host local.graphpolaris.com --port 4200", - "dev2": "vite --host local.graphpolaris.com --port 4200", - "build": "tsc && vite build", - "preview": "vite preview", - "lint": "eslint *.ts*", - "test": "vitest run" - }, - "dependencies": { - "@graphpolaris/shared": "workspace:*", - "@mui/base": "5.0.0-alpha.118", - "@mui/icons-material": "^5.11.11", - "@mui/material": "^5.11.13", - "@reduxjs/toolkit": "^1.9.2", - "graphology": "^0.25.1", - "react": "^18.2.0", - "react-dom": "^18.2.0", - "react-grid-layout": "^1.3.4", - "react-redux": "^8.0.5", - "react-router-dom": "^6.8.1", - "reactflow": "11.4.0-next.1", - "styled-components": "^5.3.6" - }, - "devDependencies": { - "@storybook/react": "7.0.0-rc.5", - "@testing-library/react": "14.0.0", - "@types/react": "^18.0.28", - "@types/react-dom": "^18.0.11", - "@types/react-grid-layout": "^1.3.2", - "@types/styled-components": "^5.1.26", - "@vitejs/plugin-basic-ssl": "^1.0.1", - "@vitejs/plugin-react-swc": "^3.0.0", - "autoprefixer": "^10.4.14", - "graphology-types": "^0.24.7", - "postcss": "^8.4.21", - "react-is": "^18.2.0", - "tailwindcss": "^3.3.1", - "typescript": "^4.9.3", - "vite": "^4.2.0", - "vite-plugin-dts": "^2.1.0", - "vitest": "^0.29.2" - } -} +{ + "name": "web", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "dev2": "vite --host local.graphpolaris.com --port 4200", + "dev": "vite --port 4200", + "build": "tsc && vite build", + "preview": "vite preview", + "lint": "eslint *.ts*", + "test": "vitest run" + }, + "dependencies": { + "@graphpolaris/shared": "workspace:*", + "@mui/base": "5.0.0-alpha.118", + "@mui/icons-material": "^5.11.11", + "@mui/material": "^5.11.13", + "@reduxjs/toolkit": "^1.9.2", + "graphology": "^0.25.1", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "react-grid-layout": "^1.3.4", + "react-redux": "^8.0.5", + "react-router-dom": "^6.8.1", + "reactflow": "11.4.0-next.1", + "styled-components": "^5.3.6" + }, + "devDependencies": { + "@storybook/react": "7.0.0-rc.5", + "@testing-library/react": "14.0.0", + "@types/react": "^18.0.28", + "@types/react-dom": "^18.0.11", + "@types/react-grid-layout": "^1.3.2", + "@types/styled-components": "^5.1.26", + "@vitejs/plugin-basic-ssl": "^1.0.1", + "@vitejs/plugin-react-swc": "^3.0.0", + "autoprefixer": "^10.4.14", + "graphology-types": "^0.24.7", + "postcss": "^8.4.21", + "react-is": "^18.2.0", + "tailwindcss": "^3.3.1", + "typescript": "^4.9.3", + "vite": "^4.2.0", + "vite-plugin-dts": "^2.1.0", + "vitest": "^0.29.2" + } +} diff --git a/apps/web/src/app/app.tsx b/apps/web/src/app/app.tsx index 3e0c20dfa..97e18077a 100644 --- a/apps/web/src/app/app.tsx +++ b/apps/web/src/app/app.tsx @@ -18,7 +18,6 @@ import { Schema } from '@graphpolaris/shared/lib/schema/panel'; import { useEffect, useRef, useState } from 'react'; import { Navbar } from '../components/navbar/navbar'; import Panel from '../components/panels/panel'; -import { domain } from '../environments/variables'; import { VisualizationPanel } from './panels/Visualization'; import styles from './app.module.scss'; import { logout } from '@graphpolaris/shared/lib/data-access/store/authSlice'; @@ -31,14 +30,14 @@ export interface App { export function App(props: App) { const isLogin = useAuth(); const auth = useAuthorizationCache(); - const api = useDatabaseAPI(domain); - const api_schema = useSchemaAPI(domain); - const api_query = useQueryAPI(domain); + const api = useDatabaseAPI(); + const api_schema = useSchemaAPI(); + const api_query = useQueryAPI(); const dispatch = useAppDispatch(); const session = useSessionCache(); const query = useQuerybuilderGraph(); const queryHash = useQuerybuilderHash(); - const ws = useRef(new WebSocketHandler(domain)); + const ws = useRef(new WebSocketHandler(import.meta.env.VITE_BACKEND_WSS_URL)); const [authCheck, setAuthCheck] = useState(false); // for testing purposes @@ -69,14 +68,15 @@ export function App(props: App) { useEffect(() => { // Newly (un)authorized + console.log('Auth changed', auth.authorized, isLogin); if (auth.authorized) { console.info('App is authorized; Getting Databases', isLogin); api.GetAllDatabases({ updateSessionCache: true }); setAuthCheck(true); } else { - dispatch(logout()); + // dispatch(logout()); } - }, [isLogin]); + }, [auth]); useEffect(() => { // New query diff --git a/apps/web/src/components/navbar/navbar.tsx b/apps/web/src/components/navbar/navbar.tsx index ba1cae518..c5918591a 100644 --- a/apps/web/src/components/navbar/navbar.tsx +++ b/apps/web/src/components/navbar/navbar.tsx @@ -26,7 +26,6 @@ import { useSchemaAPI, useSessionCache, } from '@graphpolaris/shared/lib/data-access'; -import { domain } from '../../environments/variables'; /** NavbarComponentProps is an interface containing the NavbarViewModel. */ export interface NavbarComponentProps { @@ -54,8 +53,8 @@ export const Navbar = (props: NavbarComponentProps) => { const theme = useTheme(); const auth = useAuthorizationCache(); const session = useSessionCache(); - const api = useDatabaseAPI(domain); - const schemaApi = useSchemaAPI(domain); + const api = useDatabaseAPI(); + const schemaApi = useSchemaAPI(); const dispatch = useAppDispatch(); useEffect(() => { diff --git a/apps/web/src/environments/variables.ts b/apps/web/src/environments/variables.ts index 51edd0dc1..b8c2d6b48 100644 --- a/apps/web/src/environments/variables.ts +++ b/apps/web/src/environments/variables.ts @@ -1 +1,2 @@ -export const domain = import.meta.env.VITE_BACKEND_URL; +// export const domainPrefix = import.meta.env.VITE_STAGING === 'development' ? '' : 'https://'; +// export const domain = domainPrefix + import.meta.env.VITE_BACKEND_URL; diff --git a/apps/web/vite.config.ts b/apps/web/vite.config.ts index f4e7dada1..44c0c7d60 100644 --- a/apps/web/vite.config.ts +++ b/apps/web/vite.config.ts @@ -2,14 +2,13 @@ import { defineConfig } from 'vite'; import react from '@vitejs/plugin-react-swc'; import path from 'path'; -import basicSsl from '@vitejs/plugin-basic-ssl'; import dts from 'vite-plugin-dts'; // https://vitejs.dev/config/ export default defineConfig({ plugins: [ react(), - basicSsl(), + // basicSsl(), dts({ insertTypesEntry: true, }), diff --git a/libs/shared/.env b/libs/shared/.env deleted file mode 100644 index 25874d424..000000000 --- a/libs/shared/.env +++ /dev/null @@ -1,3 +0,0 @@ -VITE_KEYCLOAK_URL=https://login.graphpolaris.com/ -VITE_KEYCLOAK_REALM=graphpolaris -VITE_KEYCLOAK_CLIENT=web \ No newline at end of file diff --git a/libs/shared/lib/data-access/api/database.ts b/libs/shared/lib/data-access/api/database.ts index cfc2620ab..bb7390c02 100644 --- a/libs/shared/lib/data-access/api/database.ts +++ b/libs/shared/lib/data-access/api/database.ts @@ -33,15 +33,17 @@ export type DeleteDatabasesOptions = { updateSessionCache?: boolean; }; -export const useDatabaseAPI = (domain: string) => { +export const useDatabaseAPI = () => { const { accessToken } = useAuthorizationCache(); const cache = useSessionCache(); const dispatch = useAppDispatch(); + const domain = import.meta.env.VITE_BACKEND_URL; + const useruri = import.meta.env.VITE_BACKEND_USER; function AddDatabase(request: AddDatabaseRequest, options: AddDatabaseOptions = {}): Promise<void> { const { setAsCurrent = true, updateDatabaseCache = false } = options; return new Promise((resolve, reject) => { - fetch(`https://${domain}/user/database`, { + fetch(`${domain}${useruri}/database`, { method: 'POST', credentials: 'same-origin', headers: new Headers({ @@ -65,7 +67,7 @@ export const useDatabaseAPI = (domain: string) => { async function GetAllDatabases(options: GetDatabasesOptions = {}): Promise<Array<string>> { const { updateSessionCache: updateDatabaseCache = true } = options; // console.log(accessToken); - const response = await fetch(`https://${domain}/user/database`, { + const response = await fetch(`${domain}${useruri}/database`, { method: 'GET', credentials: 'same-origin', headers: new Headers({ @@ -88,7 +90,7 @@ export const useDatabaseAPI = (domain: string) => { function DeleteDatabase(name: string, options: DeleteDatabasesOptions = {}): Promise<void> { const { updateSessionCache: updateDatabaseCache = true } = options; return new Promise((resolve, reject) => { - fetch(`https://${domain}/user/database/` + name, { + fetch(`${domain}${useruri}/database/` + name, { method: 'DELETE', credentials: 'same-origin', headers: new Headers({ diff --git a/libs/shared/lib/data-access/api/query.ts b/libs/shared/lib/data-access/api/query.ts index ad8d5e0f7..8f5c9da66 100644 --- a/libs/shared/lib/data-access/api/query.ts +++ b/libs/shared/lib/data-access/api/query.ts @@ -3,12 +3,13 @@ import { BackendQueryFormat } from '../../querybuilder/model/BackendQueryFormat'; import { useAuthorizationCache, useSessionCache } from '../store'; -export const useQueryAPI = (domain: string) => { +export const useQueryAPI = () => { const cache = useSessionCache(); const { accessToken } = useAuthorizationCache(); + const domain = import.meta.env.VITE_BACKEND_URL; async function execute(query: BackendQueryFormat) { - const response = await fetch(`https://${domain}/query/execute/`, { + const response = await fetch(`${domain}/query/execute/`, { method: 'POST', credentials: 'same-origin', headers: new Headers({ @@ -28,7 +29,7 @@ export const useQueryAPI = (domain: string) => { async function retrieveCachedQuery(queryID: string) { // TODO: check if this method is needed! - // const response = await fetch(`https://${domain}/query/retrieve-cached/`, { + // const response = await fetch(`${domain}/query/retrieve-cached/`, { // method: 'POST', // credentials: 'same-origin', // headers: new Headers({ diff --git a/libs/shared/lib/data-access/api/schema.ts b/libs/shared/lib/data-access/api/schema.ts index 67d2be290..59a7b2ecf 100644 --- a/libs/shared/lib/data-access/api/schema.ts +++ b/libs/shared/lib/data-access/api/schema.ts @@ -2,9 +2,11 @@ import { useAuthorizationCache, useSessionCache } from '../store'; -export const useSchemaAPI = (domain: string) => { +export const useSchemaAPI = () => { const cache = useSessionCache(); const { accessToken } = useAuthorizationCache(); + const domain = import.meta.env.VITE_BACKEND_URL; + const schema = import.meta.env.VITE_BACKEND_SCHEMA; async function RequestSchema(databaseName?: string) { if (!databaseName) databaseName = cache.currentDatabase; @@ -17,7 +19,7 @@ export const useSchemaAPI = (domain: string) => { cached: true, }; - const response = await fetch(`https://${domain}/schema/`, { + const response = await fetch(`${domain}${schema}/`, { method: 'POST', credentials: 'same-origin', headers: new Headers({ diff --git a/libs/shared/lib/data-access/api/user.ts b/libs/shared/lib/data-access/api/user.ts index a4fb38603..5e4cd7e3d 100644 --- a/libs/shared/lib/data-access/api/user.ts +++ b/libs/shared/lib/data-access/api/user.ts @@ -8,12 +8,13 @@ export type User = { SignInProvider: number; }; -export const useUserAPI = (domain: string) => { +export const useUserAPI = () => { const { accessToken } = useAuthorizationCache(); + const domain = import.meta.env.VITE_BACKEND_URL; function GetUserInfo(): Promise<User> { return new Promise<User>((resolve, reject) => { - fetch(`https://${domain}/user/`, { + fetch(`${domain}/user/`, { method: 'GET', credentials: 'same-origin', headers: new Headers({ diff --git a/libs/shared/lib/data-access/authorization/useAuth.jsx b/libs/shared/lib/data-access/authorization/useAuth.jsx index 644abac87..ab8bb0a74 100644 --- a/libs/shared/lib/data-access/authorization/useAuth.jsx +++ b/libs/shared/lib/data-access/authorization/useAuth.jsx @@ -6,13 +6,9 @@ import { authorized } from '../store/authSlice'; export const useAuth = () => { const keycloak = new Keycloak({ - // url: import.meta.env.VITE_KEYCLOAK_URL, - // realm: import.meta.env.VITE_KEYCLOAK_REALM, - // clientId: import.meta.env.VITE_KEYCLOAK_CLIENT, - //TODO: remove this hardcode - url: 'https://keycloak.graphpolaris.com', - realm: 'graphpolaris', - clientId: 'web', + url: import.meta.env.VITE_KEYCLOAK_URL || 'https://keycloak.graphpolaris.com', + realm: import.meta.env.VITE_KEYCLOAK_REALM || 'graphpolaris', + clientId: import.meta.env.VITE_KEYCLOAK_CLIENT || 'web', }); const isRun = useRef(false); @@ -20,8 +16,21 @@ export const useAuth = () => { const dispatch = useAppDispatch(); useEffect(() => { - if (isRun.current) return; + if (import.meta.env.VITE_SKIP_LOGIN) { + console.log('skipping login'); + setLogin(true); + dispatch( + authorized({ + userID: 'userID', + sessionID: 'sessionID', + accessToken: 'accessToken', + authorized: true, + }) + ); + return; + } + if (isRun.current) return; isRun.current = true; keycloak .init({ @@ -32,11 +41,9 @@ export const useAuth = () => { .then(async (isAuthenticated) => { // console.log("useAuth useEffect", isAuthenticated, keycloak.idTokenParsed); setLogin(isAuthenticated); - // just for example here: // const profile = await getUserProfile(); // console.log("useAuth useEffect profile", profile); - await dispatch( authorized({ // Info from https://www.keycloak.org/docs/latest/securing_apps/ diff --git a/libs/shared/lib/data-access/socket/backend-message-receiver/WebSocketHandler.tsx b/libs/shared/lib/data-access/socket/backend-message-receiver/WebSocketHandler.tsx index ec7e4496e..bca2d0453 100644 --- a/libs/shared/lib/data-access/socket/backend-message-receiver/WebSocketHandler.tsx +++ b/libs/shared/lib/data-access/socket/backend-message-receiver/WebSocketHandler.tsx @@ -16,7 +16,7 @@ export class WebSocketHandler implements BackendMessageReceiver { /** @param domain The domain to make the websocket connection with. */ public constructor(domain: string) { - this.url = 'wss://' + domain + '/socket/'; + this.url = domain; this.connected = false; } diff --git a/libs/shared/lib/data-access/store/authSlice.ts b/libs/shared/lib/data-access/store/authSlice.ts index 088359644..9c892fc46 100644 --- a/libs/shared/lib/data-access/store/authSlice.ts +++ b/libs/shared/lib/data-access/store/authSlice.ts @@ -1,6 +1,12 @@ import { createSlice, PayloadAction } from '@reduxjs/toolkit'; import type { RootState } from './store'; -import { useIsAuthorizedState } from '../authorization'; + +type useIsAuthorizedState = { + authorized: boolean | undefined; + accessToken: string | undefined; + sessionID: string | undefined; + userID: string | undefined; +}; // Define the initial state using that type export const initialState: useIsAuthorizedState = { @@ -16,21 +22,25 @@ export const authSlice = createSlice({ initialState, reducers: { updateAccessToken(state, action: PayloadAction<string>) { + console.debug('Updating access token'); state.accessToken = action.payload; }, authorized(state, action: PayloadAction<useIsAuthorizedState>) { + console.debug('Authorized'); state.authorized = action.payload.authorized; state.accessToken = action.payload.accessToken; state.sessionID = action.payload.sessionID; state.userID = action.payload.userID; }, logout(state) { + console.debug('Logging out'); state.authorized = undefined; state.accessToken = undefined; state.sessionID = undefined; state.userID = undefined; }, unauthorized(state) { + console.debug('Unauthorized'); state.authorized = false; }, }, diff --git a/libs/shared/lib/querybuilder/panel/querybuilder.module.scss b/libs/shared/lib/querybuilder/panel/querybuilder.module.scss index 1806d4850..aa0cb3737 100644 --- a/libs/shared/lib/querybuilder/panel/querybuilder.module.scss +++ b/libs/shared/lib/querybuilder/panel/querybuilder.module.scss @@ -1,36 +1,39 @@ -.reactflow { - width: 100%; - // height: 500px; - - // :global(.react-flow__edges) { - // z-index: 4 !important; - // } -} - -//controls -.controls { - left: auto !important; - bottom: auto !important; - top: 10px; - right: 20px; - width: auto !important; -} -.buttons { - left: auto !important; - bottom: auto !important; - top: 10px; - right: 20px; - & svg { - transform: scale(1.4); - } -} - -.menuText { - font-size: small; - font-family: Poppins, sans-serif; -} - -.full { - height: 100%; - width: 100%; -} +.reactflow { + width: 100%; + // height: 500px; + + // :global(.react-flow__edges) { + // z-index: 4 !important; + // } +} + +//controls +.controls { + left: auto !important; + bottom: auto !important; + top: 10px; + right: 20px; + width: auto !important; +} +.buttons { + left: auto !important; + bottom: auto !important; + top: 10px; + right: 20px; + & svg { + transform: scale(1.4); + } +} + +.dndnode { +} + +.menuText { + font-size: small; + font-family: Poppins, sans-serif; +} + +.full { + height: 100%; + width: 100%; +} diff --git a/libs/shared/lib/querybuilder/panel/querybuilder.tsx b/libs/shared/lib/querybuilder/panel/querybuilder.tsx index fa3d2c51f..98d6cf335 100644 --- a/libs/shared/lib/querybuilder/panel/querybuilder.tsx +++ b/libs/shared/lib/querybuilder/panel/querybuilder.tsx @@ -30,7 +30,7 @@ import ReactFlow, { } from 'reactflow'; import styles from './querybuilder.module.scss'; -import React, { ReactComponentElement, useMemo, useRef, useEffect, useCallback, useState } from 'react'; +import React, { ReactComponentElement, useMemo, useRef, useEffect, useCallback, useState, DragEventHandler } from 'react'; import { AttributePill, ConnectionDragLine, ConnectionLine, EntityFlowElement, RelationPill } from '../pills'; import { dragPillStarted, dragPillStopped, movePillTo } from '../pills/dragging/dragPill'; import { Settings as SettingsIcon, Delete as DeleteIcon, ImportExport as ExportIcon } from '@mui/icons-material'; @@ -554,7 +554,6 @@ function PopupMenu(props: { ))} </Grid> ); - return ( <Dialog onClose={handleClose} open={props.open} PaperComponent={PaperComponent}> <DialogTitle>Add New Node</DialogTitle> @@ -570,14 +569,54 @@ function PopupMenu(props: { ); } +export const QueryBuilderPills = (props: { onClose: () => void; onClick: (value: AllLogicDescriptions, type: InputNodeType) => void }) => { + const onDragStart = (event: React.DragEvent, nodeType: InputNodeType) => { + console.log('drag start', nodeType); + + event.dataTransfer.setData('application/reactflow', nodeType); + event.dataTransfer.effectAllowed = 'move'; + }; + + const generateList = (list: AllLogicDescriptions[], type: InputNodeType) => ( + <List> + {list.map((f, i) => ( + <ListItem key={JSON.stringify(f) + type + i}> + {/* <ListItemAvatar> + <Avatar sx={{ bgcolor: blue[100], color: blue[600] }}> + <PersonIcon /> + </Avatar> + </ListItemAvatar> */} + + <ListItemText + draggable + primary={f.name} + secondary={f.description} + onDragStart={(event) => onDragStart(event, type)} + key={f + type} + /> + </ListItem> + ))} + </List> + ); + + return ( + <aside> + <div>{generateList(MathFunctions, 'string')}</div> + </aside> + ); +}; + export const QueryBuilder = () => { return ( <div style={{ width: '100%', height: '100%', + display: 'flex', + gap: '1rem', }} > + <QueryBuilderPills /> <ReactFlowProvider> <QueryBuilderInner /> </ReactFlowProvider> diff --git a/libs/shared/lib/querybuilder/pills/customFlowPills/entitypill/entitypill.tsx b/libs/shared/lib/querybuilder/pills/customFlowPills/entitypill/entitypill.tsx index 04e972f9c..fbac410a0 100644 --- a/libs/shared/lib/querybuilder/pills/customFlowPills/entitypill/entitypill.tsx +++ b/libs/shared/lib/querybuilder/pills/customFlowPills/entitypill/entitypill.tsx @@ -15,6 +15,7 @@ import { useQuerybuilderGraph } from '@graphpolaris/shared/lib/data-access'; export const EntityFlowElement = React.memo((node: SchemaReactflowEntityNode) => { const theme = useTheme(); const data = node.data; + const forceOpen: boolean = true; const graph = useQuerybuilderGraph(); const myEdges = graph.edges.filter( @@ -101,10 +102,11 @@ export const EntityFlowElement = React.memo((node: SchemaReactflowEntityNode) => <span className={styles.entitySpan}>{data.name}</span> </div> */} {data?.attributes && ( - <div className={styles.content + ' ' + (showingDropdown ? styles.content_display : '')}> + <div className={styles.content + ' ' + (showingDropdown || forceOpen ? styles.content_display : '')}> {data.attributes .filter( (attribute, i) => + forceOpen || hovered || handleBeingDragged === i || myEdges.some((edge) => edge?.attributes?.sourceHandle === getHandleIdFromReactflow(node, attribute)) diff --git a/libs/shared/lib/schema/pills/nodes/entity/entity-node.tsx b/libs/shared/lib/schema/pills/nodes/entity/entity-node.tsx index aad5bef4a..1bdbb7dba 100644 --- a/libs/shared/lib/schema/pills/nodes/entity/entity-node.tsx +++ b/libs/shared/lib/schema/pills/nodes/entity/entity-node.tsx @@ -111,56 +111,56 @@ export const EntityNode = React.memo(({ id, data }: NodeProps<SchemaReactflowNod id="entitySourceLeft" position={Position.Left} type="source" - hidden={Array.from(data.handles).includes('entitySourceLeft') ? false : true} + // hidden={Array.from(data.handles).includes('entitySourceLeft') ? false : true} ></Handle> <Handle style={{ pointerEvents: 'none' }} id="entityTargetLeft" position={Position.Left} type="target" - hidden={Array.from(data.handles).includes('entityTargetLeft') ? false : true} + // hidden={Array.from(data.handles).includes('entityTargetLeft') ? false : true} ></Handle> <Handle style={{ pointerEvents: 'none' }} id="entitySourceRight" position={Position.Right} type="source" - hidden={Array.from(data.handles).includes('entitySourceRight') ? false : true} + // hidden={Array.from(data.handles).includes('entitySourceRight') ? false : true} ></Handle> <Handle style={{ pointerEvents: 'none' }} id="entityTargetRight" position={Position.Right} type="target" - hidden={Array.from(data.handles).includes('entityTargetRight') ? false : true} + // hidden={Array.from(data.handles).includes('entityTargetRight') ? false : true} ></Handle> <Handle style={{ pointerEvents: 'none' }} id="entitySourceTop" position={Position.Top} type="source" - hidden={Array.from(data.handles).includes('entitySourceTop') ? false : true} + // hidden={Array.from(data.handles).includes('entitySourceTop') ? false : true} ></Handle> <Handle style={{ pointerEvents: 'none' }} id="entityTargetTop" position={Position.Top} type="target" - hidden={Array.from(data.handles).includes('entityTargetTop') ? false : true} + // hidden={Array.from(data.handles).includes('entityTargetTop') ? false : true} ></Handle> <Handle style={{ pointerEvents: 'none' }} id="entitySourceBottom" position={Position.Bottom} type="source" - hidden={Array.from(data.handles).includes('entitySourceBottom') ? false : true} + // hidden={Array.from(data.handles).includes('entitySourceBottom') ? false : true} ></Handle> <Handle style={{ pointerEvents: 'none' }} id="entityTargetBottom" position={Position.Bottom} type="target" - hidden={Array.from(data.handles).includes('entityTargetBottom') ? false : true} + // hidden={Array.from(data.handles).includes('entityTargetBottom') ? false : true} ></Handle> <div className={styles.nodeWrapper}> <span className={styles.nodeData} style={{ color: theme.palette.custom.elementText }}> diff --git a/libs/shared/node.d.ts b/libs/shared/node.d.ts new file mode 100644 index 000000000..0cb37864e --- /dev/null +++ b/libs/shared/node.d.ts @@ -0,0 +1,12 @@ +interface ImportMeta { + env: { + VITE_BACKEND_URL: string; + VITE_BACKEND_USER: string; + VITE_BACKEND_SCHEMA: string; + VITE_BACKEND_QUERY: string; + VITE_STAGING: string; + VITE_KEYCLOAK_URL: string; + VITE_KEYCLOAK_REALM: string; + VITE_KEYCLOAK_CLIENT: string; + }; +} diff --git a/turbo.json b/turbo.json index 4ce7ad057..131b3025a 100644 --- a/turbo.json +++ b/turbo.json @@ -1,20 +1,20 @@ -{ - "$schema": "https://turbo.build/schema.json", - "globalDependencies": ["**/.env.*local"], - "pipeline": { - "build": { - "dependsOn": ["^build"], - "outputs": ["dist/**", ".next/**"] - }, - "lint": { - "outputs": [] - }, - "test": {}, - "dev": { - "cache": false - }, - "sb": { - "outputs": ["storybook-static/**"] - } - } -} +{ + "$schema": "https://turbo.build/schema.json", + "globalDependencies": ["**/.env*"], + "pipeline": { + "build": { + "dependsOn": ["^build"], + "outputs": ["dist/**", ".next/**"] + }, + "lint": { + "outputs": [] + }, + "test": {}, + "dev": { + "cache": false + }, + "sb": { + "outputs": ["storybook-static/**"] + } + } +} -- GitLab