diff --git a/apps/web/src/components/navbar/AddDatabaseForm/newdatabaseform.tsx b/apps/web/src/components/navbar/AddDatabaseForm/newdatabaseform.tsx index dbaedc45820080dda2192681c8445ecbae7127a1..9c71e959fa76ee98f4cfa541439d317f8a8f90f1 100644 --- a/apps/web/src/components/navbar/AddDatabaseForm/newdatabaseform.tsx +++ b/apps/web/src/components/navbar/AddDatabaseForm/newdatabaseform.tsx @@ -237,12 +237,15 @@ export const NewDatabaseForm = (props: { onClose(): void; open: boolean }) => { <div className="card-actions w-full justify-center"> <button className={`btn btn-primary ${Object.values(hasError).some((e) => e === true) ? 'btn-disabled' : ''}`}>Submit</button> - <button className="btn btn-outline" onClick={() => props.onClose()}> + <button className="btn btn-outline" onClick={() => + props.onClose() + + }> Cancel </button> </div> - {/* - + {/* + <div className={styles.loginContainerButton}> {portValidation && portValidation == 'error' ? ( <Button disabled variant="contained" type="submit" color="success"> @@ -253,7 +256,7 @@ export const NewDatabaseForm = (props: { onClose(): void; open: boolean }) => { Submit </Button> )} - + <Button className={styles.cancelButton} variant="outlined" diff --git a/apps/web/src/components/navbar/DatabaseDashboard/dbDashboard.tsx b/apps/web/src/components/navbar/DatabaseDashboard/dbDashboard.tsx new file mode 100644 index 0000000000000000000000000000000000000000..bf73045e67572fb7509da76d263046d862e6b4f2 --- /dev/null +++ b/apps/web/src/components/navbar/DatabaseDashboard/dbDashboard.tsx @@ -0,0 +1,43 @@ +import React, { useEffect, useRef, useState } from 'react'; +import { + AddDatabaseRequest, + DatabaseType, + databaseNameMapping, + databaseProtocolMapping, + useDatabaseAPI, + useSchemaAPI, + useSessionCache, + } from '@graphpolaris/shared/lib/data-access'; +import { DbItem } from './dbItem'; +import { DbPullItems } from './dbPullItems'; +export const DbDashboard = (props:{onClose(): void; open: boolean;}) => { + const ref = useRef<HTMLDialogElement>(null); + useEffect(() => { + if (props.open) ref.current?.showModal(); + else ref.current?.close(); + }, [props.open]); + + return( + <dialog ref={ref} className='w-1/2'> + <form + className="card flex gap-4" + onSubmit={(event: React.FormEvent) => { + event.preventDefault(); + }} + > + <div className='flex flex-row'> + <span className='text-xl basis-4/5'>Database Options</span> + <button className='btn btn-outline basis-1/5'>Add</button> + </div> + + <DbPullItems /> + + <div className="card-actions w-full justify-center"> + <button className='btn btn-outline' onClick={() => props.onClose()}> + Cancel + </button> + </div> + </form> + </dialog> + ); +}; \ No newline at end of file diff --git a/apps/web/src/components/navbar/DatabaseDashboard/dbElements/dbAttributeDisplay.tsx b/apps/web/src/components/navbar/DatabaseDashboard/dbElements/dbAttributeDisplay.tsx new file mode 100644 index 0000000000000000000000000000000000000000..014487bc70596d909bfc29f3ee39ae422257cc6c --- /dev/null +++ b/apps/web/src/components/navbar/DatabaseDashboard/dbElements/dbAttributeDisplay.tsx @@ -0,0 +1,20 @@ +import React, { useEffect, useRef, useState } from 'react'; +import { + AddDatabaseRequest, + DatabaseType, + databaseNameMapping, + databaseProtocolMapping, + useDatabaseAPI, + useSchemaAPI, + } from '@graphpolaris/shared/lib/data-access'; +export const DbAttributeDisplay = (props:{ + Nodes:number, + Edges:number, + }) => { + return( + <div> + <p>Nodes #: {props.Nodes}</p> + <p>Edges #: {props.Edges}</p> + </div> + ); +}; diff --git a/apps/web/src/components/navbar/DatabaseDashboard/dbElements/dbNodeDisplay.tsx b/apps/web/src/components/navbar/DatabaseDashboard/dbElements/dbNodeDisplay.tsx new file mode 100644 index 0000000000000000000000000000000000000000..2da4861256d07f19831aa497828a2ad4d3d724ff --- /dev/null +++ b/apps/web/src/components/navbar/DatabaseDashboard/dbElements/dbNodeDisplay.tsx @@ -0,0 +1,40 @@ +import React, { useEffect, useRef, useState } from 'react'; +import { + AddDatabaseRequest, + DatabaseType, + databaseNameMapping, + databaseProtocolMapping, + useDatabaseAPI, + useSchemaAPI, + } from '@graphpolaris/shared/lib/data-access'; +import { SchemaReactflowNodeWithFunctions, SchemaReactflowRelationWithFunctions } from '@graphpolaris/shared/lib/schema/model/reactflow'; +import { Edge, Node } from 'reactflow'; +// Use Schema Data Information +// Total Nodes +// Schema Node Types +// Schema Node Type Counts +const Nodes = ["Cars","Bikes","Planes","Buses","Ducks","Horses"] +const NodeCounts = [32,25,15,20,44,80] +const NodeTotal = 216 +export const DbNodeDisplay = (props:{ + displayNodes:Node<SchemaReactflowNodeWithFunctions | SchemaReactflowRelationWithFunctions>[], + totalNodes:number + }) => { + + const Radials: any[] = []; + props.displayNodes.forEach(dnode => { + let NodePercentageValue = (dnode.data.nodeCount/props.totalNodes)*100 + const currentRadial = ( + <div className='w-full rounded-lg p-12 flex flex-col justify-center items-center'> + <div className="radial-progress text-primary" style={{"--value":NodePercentageValue}}>{dnode.data.nodeCount}</div> + <div className='text-center mb-2'>{dnode.data.name}</div> + </div> + ); + Radials.push(currentRadial); + }); + return( + <div className='grid grid-cols-4 gap-6'> + {Radials} + </div> + ) +}; diff --git a/apps/web/src/components/navbar/DatabaseDashboard/dbElements/dbRelationDescriptor.tsx b/apps/web/src/components/navbar/DatabaseDashboard/dbElements/dbRelationDescriptor.tsx new file mode 100644 index 0000000000000000000000000000000000000000..31e221b559e4e29f66867e67d343aa009fe78694 --- /dev/null +++ b/apps/web/src/components/navbar/DatabaseDashboard/dbElements/dbRelationDescriptor.tsx @@ -0,0 +1,48 @@ +import React, { useEffect, useRef, useState } from 'react'; +import { + AddDatabaseRequest, + DatabaseType, + databaseNameMapping, + databaseProtocolMapping, + useDatabaseAPI, + useSchemaAPI, + } from '@graphpolaris/shared/lib/data-access'; + import { Edge, Node } from 'reactflow'; +export const DbRelationDescriptor = (props:{ + Name:string, + RelationSource: string, + RelationTarget: string, + RelationType: number + }) => { + if (props.RelationType==1){ + return( + <tr> + <td>{props.Name}</td> + <td>{props.RelationSource}---{'>'}{props.RelationTarget}</td> + </tr> + ); + } + else if (props.RelationType==2){ + return( + <tr> + <td>{props.Name}</td> + <td>{props.RelationSource}{'<'}---{props.RelationTarget}</td> + </tr> + ); + } + else if (props.RelationType==3){ + return( + <tr> + <td>{props.Name}</td> + <td>{props.RelationSource}{'<'}------{'>'}{props.RelationTarget}</td> + </tr> + ); + } + + return( + <tr> + <td>{props.Name}</td> + <td>{"Test"}---{'>'}{"Tested"}</td> + </tr> + ); +}; diff --git a/apps/web/src/components/navbar/DatabaseDashboard/dbElements/dbRelations.tsx b/apps/web/src/components/navbar/DatabaseDashboard/dbElements/dbRelations.tsx new file mode 100644 index 0000000000000000000000000000000000000000..65242362521220b49b19475ed8423628f5e8e604 --- /dev/null +++ b/apps/web/src/components/navbar/DatabaseDashboard/dbElements/dbRelations.tsx @@ -0,0 +1,38 @@ +import React, { useEffect, useRef, useState } from 'react'; +import { + AddDatabaseRequest, + DatabaseType, + databaseNameMapping, + databaseProtocolMapping, + useDatabaseAPI, + useSchemaAPI, + } from '@graphpolaris/shared/lib/data-access'; +import { DbRelationDescriptor } from './dbRelationDescriptor'; +import { Edge, Node } from 'reactflow'; +import { RelationPosToToEntityPos } from '@graphpolaris/shared/lib/querybuilder'; +export const DbRelations = (props:{ + RelationNodes:Edge[] + }) => { + var Relations: any[] = [] + props.RelationNodes.forEach(rset => { + const currentRelation= ( + <DbRelationDescriptor Name='Test' RelationSource={rset.source} RelationTarget={rset.target} RelationType={1}/> + ); + Relations.push(currentRelation); + }); + return( + <div className='border border-base-300'> + <table className='table'> + <thead> + <tr> + <th>KBI</th> + <th>Description</th> + </tr> + </thead> + <tbody> + {Relations} + </tbody> + </table> + </div> + ); +}; diff --git a/apps/web/src/components/navbar/DatabaseDashboard/dbItem.tsx b/apps/web/src/components/navbar/DatabaseDashboard/dbItem.tsx new file mode 100644 index 0000000000000000000000000000000000000000..a738d18f0bc9181d04efccc3c1b7b25e6e359faf --- /dev/null +++ b/apps/web/src/components/navbar/DatabaseDashboard/dbItem.tsx @@ -0,0 +1,59 @@ +import { SchemaReactflowNodeWithFunctions, SchemaReactflowRelationWithFunctions } from '@graphpolaris/shared/lib/schema/model/reactflow'; +import { DbAttributeDisplay } from './dbElements/dbAttributeDisplay'; +import { DbNodeDisplay } from './dbElements/dbNodeDisplay'; +import { DbRelations } from './dbElements/dbRelations'; +import { Edge, Node } from 'reactflow'; +export const DbItem = (props:{ + Name:string, + EdgeSet:Edge[], + NodeSet:Node<SchemaReactflowNodeWithFunctions | SchemaReactflowRelationWithFunctions>[], + Count:number + }) => { + var NodeSet= {"One": {"Two":1,"Red":0,"Blue":2},"Two": {"One":2,"Red":3,"Blue":0},"Red": {"One":0, "Two":3, "Blue":0},"Blue": {"One":1,"Two":0,"Red":0}}; + var RelationNodes=["One","Two","Red","Blue"]; + return( + <div tabIndex={props.Count} className='collapse border border-base-300 collapse-arrow'> + <input type='checkbox' /> + <div className='collapse-title text-lg font-medium w-full flex flex-row'> + <div className='basis-4/5'> + <span>{props.Name}</span> + <span className='text-sm text-gray-700 ml-4'>Last Modified: Other Date</span> + </div> + <button className='btn btn-outline basis-1/5'>Select</button> + </div> + <div className='collapse-content'> + <div className='collapse collapse-arrow'> + <input type='checkbox' /> + <div className='collapse-title text-lg font-medium w-full flex flex-row collapse-arrow'> + Attributes + </div> + <div className='collapse-content'> + <DbAttributeDisplay Nodes={props.NodeSet.length} Edges={props.EdgeSet.length} /> + </div> + </div> + <div className='collapse collapse-arrow'> + <input type='checkbox' /> + <div className='collapse-title text-lg font-medium w-full flex flex-row collapse-arrow'> + Relations + </div> + <div className='collapse-content'> + <DbRelations RelationNodes={props.EdgeSet}/> + </div> + </div> + <div className='collapse collapse-arrow'> + <input type='checkbox' /> + <div className='collapse-title text-lg font-medium w-full flex flex-row collapse-arrow'> + Node Information + </div> + <div className='collapse-content'> + <p className='text-gray-700'> Total Nodes: {props.NodeSet.length}</p> + <div className='grid grid-cols-4 gap-6'> + <DbNodeDisplay displayNodes={props.NodeSet} totalNodes={props.NodeSet.length}/> + </div> + </div> + </div> + </div> + + </div> + ); +}; diff --git a/apps/web/src/components/navbar/DatabaseDashboard/dbPullItems.tsx b/apps/web/src/components/navbar/DatabaseDashboard/dbPullItems.tsx new file mode 100644 index 0000000000000000000000000000000000000000..617e461f4e7566b2045b6773c0237004e738697b --- /dev/null +++ b/apps/web/src/components/navbar/DatabaseDashboard/dbPullItems.tsx @@ -0,0 +1,61 @@ +import React, { useEffect, useRef, useState } from 'react'; +import { + AddDatabaseRequest, + DatabaseType, + databaseNameMapping, + databaseProtocolMapping, + readInSchemaFromBackend, + useAppDispatch, + useDatabaseAPI, + useGraphQueryResult, + useSchemaAPI, + useSchemaGraphology, + useSessionCache, + } from '@graphpolaris/shared/lib/data-access'; +import { SchemaUtils, schemaExpandRelation, schemaGraphology2Reactflow } from '@graphpolaris/shared/lib/schema/schema-utils'; +import ReactFlow, { + ControlButton, + Controls, + Node, + Edge, + ReactFlowProvider, + useNodesState, + useEdgesState, + ReactFlowInstance, + Background, + } from 'reactflow'; +import { DbItem } from './dbItem'; +import { DbSolo } from './dbSolo'; +import { SchemaFromBackend } from '@graphpolaris/shared/lib/schema'; +import Broker from '@graphpolaris/shared/lib/data-access/socket/broker'; +import { schemaGraphology } from '@graphpolaris/shared/lib/data-access/store/schemaSlice'; +export const DbPullItems = () => { + const session = useSessionCache(); + const schemaGraphology = useSchemaGraphology(); + const expandedSchema = schemaExpandRelation(schemaGraphology); + const schemaFlow = schemaGraphology2Reactflow(expandedSchema); + + // Fetch DB Information from Schema + // Fill in Simpler Data like Total Nodes and Edges + // Create a multidimensional array for Node types and counts + // Create a multidimensional array for Relations between Nodes and counts + if (session.databases.length > 1){ + return(session.databases.map((db: any) => ( + <DbItem EdgeSet={schemaFlow.edges} NodeSet={schemaFlow.nodes} Name={db} Count={0} + /> + )))}; + if (session.databases.length == 1){ + console.log(schemaFlow.nodes); + console.log(schemaFlow.edges); + return(session.databases.map((db: any) => ( + <DbSolo Name={db} EdgeSet={schemaFlow.edges} NodeSet={schemaFlow.nodes} + /> + )) + ) + } + return( + <div> + Database Not Found, Connect to a Database! + </div> + ) +}; diff --git a/apps/web/src/components/navbar/DatabaseDashboard/dbSolo.tsx b/apps/web/src/components/navbar/DatabaseDashboard/dbSolo.tsx new file mode 100644 index 0000000000000000000000000000000000000000..1c2a56d34c3d26f866aa863c02b834023426f9af --- /dev/null +++ b/apps/web/src/components/navbar/DatabaseDashboard/dbSolo.tsx @@ -0,0 +1,57 @@ +import { Edge, Node } from 'reactflow'; +import { DbAttributeDisplay } from './dbElements/dbAttributeDisplay'; +import { DbNodeDisplay } from './dbElements/dbNodeDisplay'; +import { DbRelations } from './dbElements/dbRelations'; +import { SchemaReactflowNodeWithFunctions, SchemaReactflowRelationWithFunctions } from '@graphpolaris/shared/lib/schema/model/reactflow'; +export const DbSolo= (props:{ + Name:string, + EdgeSet:Edge[], + NodeSet:Node<SchemaReactflowNodeWithFunctions | SchemaReactflowRelationWithFunctions>[], + }) => { + var NodeSet= {"One": {"Two":1,"Red":0,"Blue":2},"Two": {"One":2,"Red":3,"Blue":0},"Red": {"One":0, "Two":3, "Blue":0},"Blue": {"One":1,"Two":0,"Red":0}}; + var RelationNodes=["One","Two","Red","Blue"]; + console.log(props.NodeSet); + return( + <div> + <div > + <div className='basis-4/5'> + <span>{props.Name}</span> + <span className='text-sm text-gray-700 ml-4'>Last Modified: Other Date</span> + </div> + </div> + <div> + <div className='collapse collapse-arrow'> + <input type='checkbox' /> + <div className='collapse-title text-lg font-medium w-full flex flex-row collapse-arrow'> + Attributes + </div> + <div className='collapse-content'> + <DbAttributeDisplay Nodes={props.NodeSet.length} Edges={props.EdgeSet.length} /> + </div> + </div> + <div className='collapse collapse-arrow'> + <input type='checkbox' /> + <div className='collapse-title text-lg font-medium w-full flex flex-row collapse-arrow'> + Relations + </div> + <div className='collapse-content'> + <DbRelations RelationNodes={props.EdgeSet}/> + </div> + </div> + <div className='collapse collapse-arrow'> + <input type='checkbox' /> + <div className='collapse-title text-lg font-medium w-full flex flex-row collapse-arrow'> + Node Information + </div> + <div className='collapse-content'> + <p className='text-gray-700'> Total Nodes: {props.NodeSet.length}</p> + <div className='grid grid-cols-4 gap-6'> + <DbNodeDisplay displayNodes={props.NodeSet} totalNodes={props.NodeSet.length}/> + </div> + </div> + </div> + </div> + + </div> + ); +}; diff --git a/apps/web/src/components/navbar/navbar.tsx b/apps/web/src/components/navbar/navbar.tsx index 9ecb2378ab2e72496015d1ee76f1f6ae8fda906d..31dc145116ea382b8c0f4b9e3262d64cb989e8ac 100644 --- a/apps/web/src/components/navbar/navbar.tsx +++ b/apps/web/src/components/navbar/navbar.tsx @@ -25,6 +25,7 @@ import { } from '@graphpolaris/shared/lib/data-access'; import { DatabaseMenu } from './databasemenu'; import { NewDatabaseForm } from './AddDatabaseForm/newdatabaseform'; +import { DbDashboard } from './DatabaseDashboard/dbDashboard'; // import { changeTabs } from 'src/app/panels/Visualization'; import { visualization } from 'src/app/app.module.scss'; /** NavbarComponentProps is an interface containing the NavbarViewModel. */ @@ -64,6 +65,7 @@ export const Navbar = (props: NavbarComponentProps) => { const [menuOpen, setMenuOpen] = useState(false); const [subMenuOpen, setSubMenuOpen] = useState<string | undefined>(undefined); + const [dbDashboardOpen, setdbDashboardOpen] = useState(false); /** * Called when the user clicks on the 'submit' button of the add database form. */ @@ -78,6 +80,7 @@ export const Navbar = (props: NavbarComponentProps) => { return ( <div className="w-full h-auto px-5"> <NewDatabaseForm open={addDatabaseFormOpen} onClose={() => setAddDatabaseFormOpen(false)} /> + <DbDashboard open={dbDashboardOpen} onClose={() => setdbDashboardOpen(false)}/> <div title="GraphPolaris" className="navbar w-full"> <div className="w-8/12"> <a href="https://graphpolaris.com/" > @@ -104,6 +107,17 @@ export const Navbar = (props: NavbarComponentProps) => { <div className="dropdown"> <label tabIndex= {1} className="btn s-1">Data</label> <ul tabIndex={1} className="dropdown-content z-[1] menu p-2 shadow bg-base-100 rounded-box w-52"> + <li> + <button + onClick={() => { + setdbDashboardOpen(true); + setMenuOpen(false); + setSubMenuOpen(undefined); + }} + > + Databases + </button> + </li> <li> <button onClick={() => { diff --git a/apps/web/src/styles.css b/apps/web/src/styles.css index eae4343098ce499729772044bf9565c46bb98046..28f508dd26aea5e062c3eb845c7cd1950e81931b 100644 --- a/apps/web/src/styles.css +++ b/apps/web/src/styles.css @@ -17,3 +17,7 @@ @apply z-50; @apply content-[attr(data-tip)]; } + +.btn { + z-index: 1; +} \ No newline at end of file