From b05f2bc78e031b5dba283a6464a68401636177f1 Mon Sep 17 00:00:00 2001 From: svamel00 Date: Fri, 10 Feb 2023 11:04:07 +0100 Subject: [PATCH 01/60] Radiobutton-selection between SQL, Cypher, and MQL and fitting view of the leftsidebar --- package-lock.json | 1 + .../graphical-querying.component.html | 255 +++++++++++++++--- .../graphical-querying.component.ts | 123 +++++++-- 3 files changed, 308 insertions(+), 71 deletions(-) diff --git a/package-lock.json b/package-lock.json index 34450b74..84238692 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5,6 +5,7 @@ "requires": true, "packages": { "": { + "name": "Polypheny-UI", "version": "1.0.0", "license": "MIT", "dependencies": { diff --git a/src/app/views/querying/graphical-querying/graphical-querying.component.html b/src/app/views/querying/graphical-querying/graphical-querying.component.html index 4ed44f6f..5e48b9c4 100644 --- a/src/app/views/querying/graphical-querying/graphical-querying.component.html +++ b/src/app/views/querying/graphical-querying/graphical-querying.component.html @@ -2,62 +2,233 @@
Graphical Querying
-

Select columns from the left sidebar to get started. If needed, you can edit the generated SQL code.

-
-
- select -
-
+ + +

Select your query language:

+
+ + +
-
-
- from + +
+

Select columns from the left sidebar to get started. If needed, you can edit the generated SQL code.

+ +
+
+ select +
+
-
- {{t.key}} + +
+
+ from +
+
+ {{t.key}} +
-
-
-
- join
conditions
+
+
+ join
conditions
+
+
+ +
+
+
-
- -
-
+ +
Generated query
+

Edit your code if needed. Your changes will be overwritten, as soon as you add or remove a column in the select box or change any join condition.

+
+
-
+
-
Generated query
-

Edit your code if needed. Your changes will be overwritten, as soon as you add or remove a column in the select box or change any join condition.

-
- -
-
+ + - + + +
+
+
Query Result
+
+ +
- - +
+ {{resultSet.generatedQuery}} + + {{resultSet.affectedRows}} + ! + +
-
-
-
Query Result
+
+
+ Error: +

{{resultSet.error}}

+
+ +
+

+ Successfully executed +

+
+ +
+
+ +
+
+
+
-
+ + +
+

Select columns from the left sidebar to get started. If needed, you can edit the generated SQL code.

+ + +
+
+
+
+
+
+ {{detail.id}} +
+
+ {{label}} +
+
+

{{entry.key}}: {{entry.value}}

+
+
+ +
+
+
+ + +
+
+
+
+
+ +
+ +
+ +
+
+ Insert data +
+
    +
  • + + +
  • +
  • + + + + +
  • +
+
+ +
+ + +
+
+ match +
+
+
+ +
+
+ where +
+
+ {{t.key}} +
+
+ +
+
+ return +
+
+ +
+
+
+
+ +
Generated query
+

Edit your code if needed. Your changes will be overwritten, as soon as you add or remove a column in the select box or change any join condition.

+
+ +
+
+ + + + + + + + +
+
+
Query Result
+
+ +
{{resultSet.generatedQuery}} - {{resultSet.affectedRows}} - ! - + {{resultSet.affectedRows}} + ! +
@@ -68,24 +239,22 @@
Query Result

- Successfully executed + Successfully executed

- +
+
-
+
-
- - - +
diff --git a/src/app/views/querying/graphical-querying/graphical-querying.component.ts b/src/app/views/querying/graphical-querying/graphical-querying.component.ts index 47ba6dd3..3acba43e 100644 --- a/src/app/views/querying/graphical-querying/graphical-querying.component.ts +++ b/src/app/views/querying/graphical-querying/graphical-querying.component.ts @@ -61,14 +61,18 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest this.initWebSocket(); } + selectedLanguage: number; + ngOnInit() { + this._leftSidebar.close(); + this.subscriptions.unsubscribe(); this._leftSidebar.open(); - this.initSchema(); + this.initSchema(this.selectedLanguage); this.initGraphicalQuerying(); const sub = this._crud.onReconnection().subscribe( b => { if (b) { - this.initSchema(); + this.initSchema(this.selectedLanguage); } } ); @@ -99,35 +103,98 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest ); } - initSchema() { - this._crud.getSchema(new SchemaRequest('views/graphical-querying/', true, 3, false, false, [DataModels.RELATIONAL])).subscribe( - res => { - const nodeAction = (tree, node, $event) => { - if (!node.isActive && node.isLeaf) { - this.addCol(node.data); - node.setIsActive(true, true); - } else if (node.isActive && node.isLeaf) { - node.setIsActive(false, true); - this.removeCol(node.data.id); - - //deletes the selection if nothing is choosen - if (this.selectedColumn['column'].toString() === node.data.id) { - this.selectedCol([]); + initSchema(selectedLanguage:number) { + console.log(selectedLanguage); + if (selectedLanguage == 2) { + this._crud.getSchema(new SchemaRequest('views/graphical-querying/', true, 3, false, false, [DataModels.RELATIONAL])).subscribe( + res => { + const nodeAction = (tree, node, $event) => { + if (!node.isActive && node.isLeaf) { + this.addCol(node.data); + node.setIsActive(true, true); + } else if (node.isActive && node.isLeaf) { + node.setIsActive(false, true); + this.removeCol(node.data.id); + + //deletes the selection if nothing is choosen + if (this.selectedColumn['column'].toString() === node.data.id) { + this.selectedCol([]); + } + } + }; + + const schemaTemp = res; + const schema = []; + for (const s of schemaTemp) { + const node = SidebarNode.fromJson(s, {allowRouting: false, autoActive: false, action: nodeAction}); + schema.push(node); } + + this._leftSidebar.setNodes(schema); + this._leftSidebar.open(); } - }; + ); + } + else if (selectedLanguage == 1) { + this._crud.getSchema(new SchemaRequest('views/graphical-querying/', true, 3, false, false, [DataModels.GRAPH])).subscribe( + res => { + const nodeAction = (tree, node, $event) => { + if (!node.isActive && node.isLeaf) { + this.addCol(node.data); + node.setIsActive(true, true); + } else if (node.isActive && node.isLeaf) { + node.setIsActive(false, true); + this.removeCol(node.data.id); + + //deletes the selection if nothing is choosen + if (this.selectedColumn['column'].toString() === node.data.id) { + this.selectedCol([]); + } + } + }; - const schemaTemp = res; - const schema = []; - for (const s of schemaTemp) { - const node = SidebarNode.fromJson(s, {allowRouting: false, autoActive: false, action: nodeAction}); - schema.push(node); - } + const schemaTemp = res; + const schema = []; + for (const s of schemaTemp) { + const node = SidebarNode.fromJson(s, {allowRouting: false, autoActive: false, action: nodeAction}); + schema.push(node); + } - this._leftSidebar.setNodes(schema); - this._leftSidebar.open(); - } - ); + this._leftSidebar.setNodes(schema); + this._leftSidebar.open(); + } + ); + } + else if (selectedLanguage == 3) { + this._crud.getSchema(new SchemaRequest('views/graphical-querying/', true, 3, false, false, [DataModels.DOCUMENT])).subscribe( + res => { + const nodeAction = (tree, node, $event) => { + if (!node.isActive && node.isLeaf) { + this.addCol(node.data); + node.setIsActive(true, true); + } else if (node.isActive && node.isLeaf) { + node.setIsActive(false, true); + this.removeCol(node.data.id); + + //deletes the selection if nothing is choosen + if (this.selectedColumn['column'].toString() === node.data.id) { + this.selectedCol([]); + } + } + }; + + const schemaTemp = res; + const schema = []; + for (const s of schemaTemp) { + const node = SidebarNode.fromJson(s, {allowRouting: false, autoActive: false, action: nodeAction}); + schema.push(node); + } + + this._leftSidebar.setNodes(schema); + this._leftSidebar.open(); + } + ); + } } initGraphicalQuerying() { @@ -336,7 +403,7 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest let filteredInfos = ''; if (this.columns.size === 0) { - this.editorGenerated.setCode(''); + //this.editorGenerated.setCode(''); return; } From f4e1389e8b095654d51ceed05cf4637d8c3fb445 Mon Sep 17 00:00:00 2001 From: svamel00 Date: Wed, 15 Feb 2023 20:20:54 +0100 Subject: [PATCH 02/60] added input fields + fitting generated query to cypher. Active Namespace should be changed if chosen in the sidebar. --- src/app/components/components.module.ts | 3 +- .../graphical-querying.component.html | 146 ++++++------------ .../graphical-querying.component.ts | 67 ++++++-- 3 files changed, 100 insertions(+), 116 deletions(-) diff --git a/src/app/components/components.module.ts b/src/app/components/components.module.ts index ca012418..f4f496c9 100644 --- a/src/app/components/components.module.ts +++ b/src/app/components/components.module.ts @@ -100,7 +100,8 @@ import {DatesPipeModule} from './data-view/shared-module'; InputComponent, JsonEditorComponent, EditorComponent, - DeleteConfirmComponent + DeleteConfirmComponent, + DataGraphComponent ] }) export class ComponentsModule { diff --git a/src/app/views/querying/graphical-querying/graphical-querying.component.html b/src/app/views/querying/graphical-querying/graphical-querying.component.html index 46fd123b..4763a3e8 100644 --- a/src/app/views/querying/graphical-querying/graphical-querying.component.html +++ b/src/app/views/querying/graphical-querying/graphical-querying.component.html @@ -19,7 +19,7 @@
Graphical Querying
-
+

Select columns from the left sidebar to get started. If needed, you can edit the generated SQL code.

@@ -100,118 +100,62 @@
Query Result
- +
-

Select columns from the left sidebar to get started. If needed, you can edit the generated SQL code.

- - -
-
-
-
-
-
- {{detail.id}} -
-
- {{label}} -
-
-

{{entry.key}}: {{entry.value}}

+

Select your namespace from the left sidebar.

+ + + + + +
+
+
-
- + +
-
-
- - -
-
-
-
-
-
- -
- -
-
- Insert data -
-
    -
  • - - -
  • -
  • - - - - -
  • -
-
- -
- +
+
+ +
+ +
-
-
- match -
-
-
+
+
+ +
+ +
-
-
- where -
-
- {{t.key}} -
-
+ -
-
- return -
-
- -
-
-
-
Generated query
-

Edit your code if needed. Your changes will be overwritten, as soon as you add or remove a column in the select box or change any join condition.

+

Edit your code if needed.

-
- - - - diff --git a/src/app/views/querying/graphical-querying/graphical-querying.component.ts b/src/app/views/querying/graphical-querying/graphical-querying.component.ts index 8d0135e8..ce01eaba 100644 --- a/src/app/views/querying/graphical-querying/graphical-querying.component.ts +++ b/src/app/views/querying/graphical-querying/graphical-querying.component.ts @@ -1,4 +1,13 @@ -import {AfterViewInit, Component, OnDestroy, OnInit, TemplateRef, ViewChild, ViewEncapsulation} from '@angular/core'; +import { + AfterViewInit, + Component, + Input, + OnDestroy, + OnInit, + TemplateRef, + ViewChild, + ViewEncapsulation +} from '@angular/core'; import * as $ from 'jquery'; import 'jquery-ui/ui/widget'; import 'jquery-ui/ui/widgets/sortable'; @@ -10,12 +19,16 @@ import {ToastService} from '../../../components/toast/toast.service'; import {DataModels, EditTableRequest, QueryRequest, SchemaRequest} from '../../../models/ui-request.model'; import {SidebarNode} from '../../../models/sidebar-node.model'; import {ForeignKey, Uml} from '../../uml/uml.model'; -import {Router} from '@angular/router'; +import {ActivatedRoute, Router} from '@angular/router'; import {Subscription} from 'rxjs'; import {WebuiSettingsService} from '../../../services/webui-settings.service'; import {WebSocket} from '../../../services/webSocket'; import {BsModalRef, BsModalService} from 'ngx-bootstrap/modal'; import {ViewInformation} from '../../../components/data-view/data-view.component'; +// new import added to extent graph +import {DataGraphComponent} from '../../../components/data-view/data-graph/data-graph.component'; +import {DbmsTypesService} from '../../../services/dbms-types.service'; +import {TableConfig} from '../../../components/data-view/data-table/table-config'; @Component({ selector: 'app-graphical-querying', @@ -61,8 +74,19 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest this.initWebSocket(); } + // new additions by me: selectedLanguage: number; + tableId: string; + config: TableConfig; + + inputMatch = ''; + inputWhere = ''; + inputReturn = ''; + + activeNamespace: string; // same usage as console.components.ts + private readonly LOCAL_STORAGE_NAMESPACE_KEY = 'polypheny-namespace'; // same usage as console.components.ts + ngOnInit() { this._leftSidebar.close(); this.subscriptions.unsubscribe(); @@ -105,7 +129,7 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest initSchema(selectedLanguage:number) { console.log(selectedLanguage); - if (selectedLanguage == 2) { + if (selectedLanguage == 1) { this._crud.getSchema(new SchemaRequest('views/graphical-querying/', true, 3, false, false, [DataModels.RELATIONAL])).subscribe( res => { const nodeAction = (tree, node, $event) => { @@ -135,22 +159,23 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest } ); } - else if (selectedLanguage == 1) { + else if (selectedLanguage == 2) { this._crud.getSchema(new SchemaRequest('views/graphical-querying/', true, 3, false, false, [DataModels.GRAPH])).subscribe( res => { const nodeAction = (tree, node, $event) => { - if (!node.isActive && node.isLeaf) { - this.addCol(node.data); - node.setIsActive(true, true); + console.log(node.id); + this.setDefaultDB(node.id); //changes the activeNamespace to the one chosen on the leftside + /* + if (!node.isActive && node.isLeaf) { + //node.setIsActive(true, true); + console.log('activated'); + // here code to show graph + } else if (node.isActive && node.isLeaf) { node.setIsActive(false, true); - this.removeCol(node.data.id); - - //deletes the selection if nothing is choosen - if (this.selectedColumn['column'].toString() === node.data.id) { - this.selectedCol([]); - } - } + console.log('deactivated'); + // here code to let graph disappear + }*/ }; const schemaTemp = res; @@ -396,6 +421,19 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest return '"' + k.split('.').join('"."') + '"'; } + // inspired by the same function in console.component.ts + private setDefaultDB(name: string) { + name = name.trim(); + this.activeNamespace = name; + localStorage.setItem(this.LOCAL_STORAGE_NAMESPACE_KEY, name); + } + + async generateCypher() { + let cypher = ''; //TO DO: dynamic namespace + cypher += 'MATCH ' + this.inputMatch + '\nWHERE ' + this.inputWhere + '\nRETURN ' + this.inputReturn + ';'; + this.editorGenerated.setCode(cypher); + } + async generateSQL() { this.whereCounter = 0; this.andCounter = 0; @@ -582,3 +620,4 @@ class JoinCondition { this.active = !this.active; } } + From cea361a6431a9d117ec0bec50c39c8b7e269f6c5 Mon Sep 17 00:00:00 2001 From: svamel00 Date: Wed, 15 Feb 2023 22:38:28 +0100 Subject: [PATCH 03/60] changed selectedLanguage to lang and modified executeQuery() --- .../querying/console/console.component.ts | 1 + .../graphical-querying.component.html | 10 +++++----- .../graphical-querying.component.ts | 19 ++++++++++--------- 3 files changed, 16 insertions(+), 14 deletions(-) diff --git a/src/app/views/querying/console/console.component.ts b/src/app/views/querying/console/console.component.ts index e62a47be..a4bc19e7 100644 --- a/src/app/views/querying/console/console.component.ts +++ b/src/app/views/querying/console/console.component.ts @@ -183,6 +183,7 @@ export class ConsoleComponent implements OnInit, OnDestroy { this.queryAnalysis = null; this.loading = true; + console.log(code); if (!this._crud.anyQuery(this.websocket, new QueryRequest(code, this.analyzeQuery, this.useCache, this.lang, this.activeNamespace))) { this.loading = false; this.resultSets = [new ResultSet('Could not establish a connection with the server.', code)]; diff --git a/src/app/views/querying/graphical-querying/graphical-querying.component.html b/src/app/views/querying/graphical-querying/graphical-querying.component.html index 4763a3e8..05e2e763 100644 --- a/src/app/views/querying/graphical-querying/graphical-querying.component.html +++ b/src/app/views/querying/graphical-querying/graphical-querying.component.html @@ -8,18 +8,18 @@
Graphical Querying

Select your query language:

-
+

Select columns from the left sidebar to get started. If needed, you can edit the generated SQL code.

@@ -101,7 +101,7 @@
Query Result
-
+

Select your namespace from the left sidebar.

diff --git a/src/app/views/querying/graphical-querying/graphical-querying.component.ts b/src/app/views/querying/graphical-querying/graphical-querying.component.ts index ce01eaba..e1a773ca 100644 --- a/src/app/views/querying/graphical-querying/graphical-querying.component.ts +++ b/src/app/views/querying/graphical-querying/graphical-querying.component.ts @@ -75,7 +75,7 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest } // new additions by me: - selectedLanguage: number; + lang: string; // usage as lang in console.component.hmtl 'sql', 'cypher', 'mql' tableId: string; config: TableConfig; @@ -91,12 +91,12 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest this._leftSidebar.close(); this.subscriptions.unsubscribe(); this._leftSidebar.open(); - this.initSchema(this.selectedLanguage); + this.initSchema(this.lang); this.initGraphicalQuerying(); const sub = this._crud.onReconnection().subscribe( b => { if (b) { - this.initSchema(this.selectedLanguage); + this.initSchema(this.lang); } } ); @@ -127,9 +127,9 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest ); } - initSchema(selectedLanguage:number) { - console.log(selectedLanguage); - if (selectedLanguage == 1) { + initSchema(lang:string) { + console.log(lang); + if (lang === 'sql') { this._crud.getSchema(new SchemaRequest('views/graphical-querying/', true, 3, false, false, [DataModels.RELATIONAL])).subscribe( res => { const nodeAction = (tree, node, $event) => { @@ -159,7 +159,7 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest } ); } - else if (selectedLanguage == 2) { + else if (lang === 'cypher') { this._crud.getSchema(new SchemaRequest('views/graphical-querying/', true, 3, false, false, [DataModels.GRAPH])).subscribe( res => { const nodeAction = (tree, node, $event) => { @@ -190,7 +190,7 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest } ); } - else if (selectedLanguage == 3) { + else if (lang === 'mql') { this._crud.getSchema(new SchemaRequest('views/graphical-querying/', true, 3, false, false, [DataModels.DOCUMENT])).subscribe( res => { const nodeAction = (tree, node, $event) => { @@ -533,7 +533,8 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest executeQuery() { this.loading = true; const code = this.editorGenerated.getCode(); - if (!this._crud.anyQuery(this.webSocket, new QueryRequest(code, false, true, 'sql', null))) { + console.log(code); + if (!this._crud.anyQuery(this.webSocket, new QueryRequest(code, false, true, this.lang, null))) { this.loading = false; this.resultSet = new ResultSet('Could not establish a connection with the server.', code); } From 4a8af471bc88c7023e1d32fd59e750f2c0571b5f Mon Sep 17 00:00:00 2001 From: svamel00 Date: Fri, 17 Feb 2023 21:43:55 +0100 Subject: [PATCH 04/60] first buggy prototype for MQL graphyical querying --- .../querying/console/console.component.ts | 1 + .../graphical-querying.component.html | 123 +++++++++++++++--- .../graphical-querying.component.ts | 61 ++++++--- 3 files changed, 144 insertions(+), 41 deletions(-) diff --git a/src/app/views/querying/console/console.component.ts b/src/app/views/querying/console/console.component.ts index a4bc19e7..eb0dec49 100644 --- a/src/app/views/querying/console/console.component.ts +++ b/src/app/views/querying/console/console.component.ts @@ -184,6 +184,7 @@ export class ConsoleComponent implements OnInit, OnDestroy { this.loading = true; console.log(code); + console.log(this.activeNamespace); if (!this._crud.anyQuery(this.websocket, new QueryRequest(code, this.analyzeQuery, this.useCache, this.lang, this.activeNamespace))) { this.loading = false; this.resultSets = [new ResultSet('Could not establish a connection with the server.', code)]; diff --git a/src/app/views/querying/graphical-querying/graphical-querying.component.html b/src/app/views/querying/graphical-querying/graphical-querying.component.html index 05e2e763..943b65d1 100644 --- a/src/app/views/querying/graphical-querying/graphical-querying.component.html +++ b/src/app/views/querying/graphical-querying/graphical-querying.component.html @@ -5,6 +5,7 @@
Graphical Querying
+

Select your query language:

-

Select your namespace from the left sidebar.

@@ -117,7 +117,7 @@
Query Result
-
@@ -126,7 +126,7 @@
Query Result
-
@@ -134,26 +134,13 @@
Query Result
-
- - -
Generated query

Edit your code if needed.

-
+
@@ -165,7 +152,7 @@
Generated query
Query Result
-
+
{{resultSet.generatedQuery}} @@ -197,7 +184,103 @@
Query Result
-
+ + +
+

1. Choose what you would like to find.

+
+
+ +
+ +
+

2. Select the elements from the left sidebar.

+ +
+

3. Fill in the details.

+
+ + +
+
+
+
+
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+
+ + +
Generated query
+

Edit your code if needed.

+
+ +
+ + + + +
+
+
Query Result
+
+ +
+ +
+ {{resultSet.generatedQuery}} + + {{resultSet.affectedRows}} + ! + +
+ +
+
+ Error: +

{{resultSet.error}}

+
+ +
+

+ Successfully executed +

+
+ +
+
+ +
+
+
+
+ +
+ + + +
diff --git a/src/app/views/querying/graphical-querying/graphical-querying.component.ts b/src/app/views/querying/graphical-querying/graphical-querying.component.ts index e1a773ca..5cdf365e 100644 --- a/src/app/views/querying/graphical-querying/graphical-querying.component.ts +++ b/src/app/views/querying/graphical-querying/graphical-querying.component.ts @@ -80,16 +80,18 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest tableId: string; config: TableConfig; + inputMatch = ''; inputWhere = ''; inputReturn = ''; - + colList: string[] = []; + inputMatchMQL = ''; + inputDropdownMQL: string[] = []; + inputTextMQL: string[] = []; activeNamespace: string; // same usage as console.components.ts private readonly LOCAL_STORAGE_NAMESPACE_KEY = 'polypheny-namespace'; // same usage as console.components.ts ngOnInit() { - this._leftSidebar.close(); - this.subscriptions.unsubscribe(); this._leftSidebar.open(); this.initSchema(this.lang); this.initGraphicalQuerying(); @@ -164,18 +166,7 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest res => { const nodeAction = (tree, node, $event) => { console.log(node.id); - this.setDefaultDB(node.id); //changes the activeNamespace to the one chosen on the leftside - /* - if (!node.isActive && node.isLeaf) { - //node.setIsActive(true, true); - console.log('activated'); - // here code to show graph - - } else if (node.isActive && node.isLeaf) { - node.setIsActive(false, true); - console.log('deactivated'); - // here code to let graph disappear - }*/ + this.setDefaultDB(node.id); //changes the activeNamespace to the one chosen on the left side }; const schemaTemp = res; @@ -193,13 +184,14 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest else if (lang === 'mql') { this._crud.getSchema(new SchemaRequest('views/graphical-querying/', true, 3, false, false, [DataModels.DOCUMENT])).subscribe( res => { - const nodeAction = (tree, node, $event) => { + const nodeAction = (tree, node, $event) => { // TO DO: it only shows columns _id_ and _data_ but not correct ones. if (!node.isActive && node.isLeaf) { - this.addCol(node.data); - node.setIsActive(true, true); + console.log(node.data.name); + this.colList.push(node.data.id); + node.setIsActive(true, true); // TO DO: Find out what this does? } else if (node.isActive && node.isLeaf) { - node.setIsActive(false, true); - this.removeCol(node.data.id); + this.colList = this.colList.filter(col => col !== node.data.id); // removing specific column from the array by deselecting it in left sidebar + node.setIsActive(false, true); // TO DO: Find out what this does? //deletes the selection if nothing is choosen if (this.selectedColumn['column'].toString() === node.data.id) { @@ -434,6 +426,32 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest this.editorGenerated.setCode(cypher); } + async generateMQL() { + let mql = ''; + switch (this.inputMatchMQL) { + case 'mql-and': + mql += 'db.getCollection("' + 'collection_name' + '").find({'; + break; + case 'mql-or': + mql += 'db.getCollection("' + 'collection_name' + '").find({"$or" : [{'; + break; + case 'mql-nor': + mql += 'db.getCollection("' + 'collection_name' + '").find({"$nor" : [{'; + break; + } + for (let i = 0; i < this.inputDropdownMQL.length; i++) { + mql += this.inputDropdownMQL[i] + this.inputTextMQL[i]; + if (i+1 !== this.inputDropdownMQL.length) { + mql += ', '; + } + } + // TO DO: if and + mql += '});'; + // TO DO: if or + // TO DO: if nor + this.editorGenerated.setCode(mql); + } + async generateSQL() { this.whereCounter = 0; this.andCounter = 0; @@ -534,7 +552,8 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest this.loading = true; const code = this.editorGenerated.getCode(); console.log(code); - if (!this._crud.anyQuery(this.webSocket, new QueryRequest(code, false, true, this.lang, null))) { + console.log(this.activeNamespace); + if (!this._crud.anyQuery(this.webSocket, new QueryRequest(code, false, true, this.lang, this.activeNamespace))) { this.loading = false; this.resultSet = new ResultSet('Could not establish a connection with the server.', code); } From 1406f7347e772565386e470a1db72f37d1466189 Mon Sep 17 00:00:00 2001 From: svamel00 Date: Sat, 18 Feb 2023 00:22:34 +0100 Subject: [PATCH 05/60] new prototype idea for mql --- .../graphical-querying.component.html | 162 ++++++++++-------- .../graphical-querying.component.ts | 45 ++--- 2 files changed, 119 insertions(+), 88 deletions(-) diff --git a/src/app/views/querying/graphical-querying/graphical-querying.component.html b/src/app/views/querying/graphical-querying/graphical-querying.component.html index 943b65d1..22e95060 100644 --- a/src/app/views/querying/graphical-querying/graphical-querying.component.html +++ b/src/app/views/querying/graphical-querying/graphical-querying.component.html @@ -187,93 +187,119 @@
Query Result
-

1. Choose what you would like to find.

-
-
- -
- -
-

2. Select the elements from the left sidebar.

+

1. Select your collection from the left sidebar.

-
-

3. Fill in the details.

-
+
+

2. Choose how you want to find the elements.

+
+
+ +
+ +
- -
-
-
-
-
- +
+

3. Fill in the details.

+ + +
+
+
+
+
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+
+ +
- +
-
-
-
- -
- + + +
+
+
-
-
-
Generated query
-

Edit your code if needed.

-
- -
+
Generated query
+

Edit your code if needed.

+
+ +
- - + + -
-
-
Query Result
-
+
+
+
Query Result
+
-
+
-
- {{resultSet.generatedQuery}} - - {{resultSet.affectedRows}} - ! - -
+
+ {{resultSet.generatedQuery}} + + {{resultSet.affectedRows}} + ! + +
-
-
- Error: -

{{resultSet.error}}

-
+
+
+ Error: +

{{resultSet.error}}

+
-
-

- Successfully executed -

-
+
+

+ Successfully executed +

+
-
-
- +
+
+ +
+
+
diff --git a/src/app/views/querying/graphical-querying/graphical-querying.component.ts b/src/app/views/querying/graphical-querying/graphical-querying.component.ts index 5cdf365e..2a51bfa1 100644 --- a/src/app/views/querying/graphical-querying/graphical-querying.component.ts +++ b/src/app/views/querying/graphical-querying/graphical-querying.component.ts @@ -84,11 +84,14 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest inputMatch = ''; inputWhere = ''; inputReturn = ''; - colList: string[] = []; + colList: string[] = ['1']; inputMatchMQL = ''; inputDropdownMQL: string[] = []; - inputTextMQL: string[] = []; + inputTextMQL1: string[] = []; + inputTextMQL2: string[] = []; activeNamespace: string; // same usage as console.components.ts + collectionName: string; + fieldCounter = 1; private readonly LOCAL_STORAGE_NAMESPACE_KEY = 'polypheny-namespace'; // same usage as console.components.ts ngOnInit() { @@ -162,7 +165,7 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest ); } else if (lang === 'cypher') { - this._crud.getSchema(new SchemaRequest('views/graphical-querying/', true, 3, false, false, [DataModels.GRAPH])).subscribe( + this._crud.getSchema(new SchemaRequest('views/graphical-querying/', true, 1, false, false, [DataModels.GRAPH])).subscribe( res => { const nodeAction = (tree, node, $event) => { console.log(node.id); @@ -182,21 +185,14 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest ); } else if (lang === 'mql') { - this._crud.getSchema(new SchemaRequest('views/graphical-querying/', true, 3, false, false, [DataModels.DOCUMENT])).subscribe( + this._crud.getSchema(new SchemaRequest('views/graphical-querying/', true, 2, false, false, [DataModels.DOCUMENT])).subscribe( res => { const nodeAction = (tree, node, $event) => { // TO DO: it only shows columns _id_ and _data_ but not correct ones. if (!node.isActive && node.isLeaf) { - console.log(node.data.name); - this.colList.push(node.data.id); - node.setIsActive(true, true); // TO DO: Find out what this does? - } else if (node.isActive && node.isLeaf) { - this.colList = this.colList.filter(col => col !== node.data.id); // removing specific column from the array by deselecting it in left sidebar - node.setIsActive(false, true); // TO DO: Find out what this does? - - //deletes the selection if nothing is choosen - if (this.selectedColumn['column'].toString() === node.data.id) { - this.selectedCol([]); - } + console.log(node.parent.id); + this.setDefaultDB(node.parent.id); + console.log(node.displayField); + this.collectionName = node.displayField; } }; @@ -420,6 +416,15 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest localStorage.setItem(this.LOCAL_STORAGE_NAMESPACE_KEY, name); } + addMQLField() { + this.fieldCounter += 1; + this.colList.push(String(this.fieldCounter)); + } + + deleteMQLField(name:string) { + this.colList = this.colList.filter(col => col !== name); + } + async generateCypher() { let cypher = ''; //TO DO: dynamic namespace cypher += 'MATCH ' + this.inputMatch + '\nWHERE ' + this.inputWhere + '\nRETURN ' + this.inputReturn + ';'; @@ -430,23 +435,23 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest let mql = ''; switch (this.inputMatchMQL) { case 'mql-and': - mql += 'db.getCollection("' + 'collection_name' + '").find({'; + mql += 'db.getCollection("' + this.collectionName + '").find({'; break; case 'mql-or': - mql += 'db.getCollection("' + 'collection_name' + '").find({"$or" : [{'; + mql += 'db.getCollection("' + this.collectionName + '").find({"$or" : [{'; break; case 'mql-nor': - mql += 'db.getCollection("' + 'collection_name' + '").find({"$nor" : [{'; + mql += 'db.getCollection("' + this.collectionName + '").find({"$nor" : [{'; break; } for (let i = 0; i < this.inputDropdownMQL.length; i++) { - mql += this.inputDropdownMQL[i] + this.inputTextMQL[i]; + mql += this.inputTextMQL1[i] + this.inputDropdownMQL[i] + this.inputTextMQL2[i]; if (i+1 !== this.inputDropdownMQL.length) { mql += ', '; } } // TO DO: if and - mql += '});'; + mql += '})'; // TO DO: if or // TO DO: if nor this.editorGenerated.setCode(mql); From 11f6d936417881a55fe32fab0adee73b5f42b364 Mon Sep 17 00:00:00 2001 From: svamel00 Date: Sat, 18 Feb 2023 01:31:11 +0100 Subject: [PATCH 06/60] implemented or & nor, equal and not equal for mql --- .../graphical-querying.component.html | 22 ++++----- .../graphical-querying.component.ts | 49 +++++++++++++------ 2 files changed, 42 insertions(+), 29 deletions(-) diff --git a/src/app/views/querying/graphical-querying/graphical-querying.component.html b/src/app/views/querying/graphical-querying/graphical-querying.component.html index 22e95060..cbb1a03f 100644 --- a/src/app/views/querying/graphical-querying/graphical-querying.component.html +++ b/src/app/views/querying/graphical-querying/graphical-querying.component.html @@ -220,11 +220,11 @@
Query Result
- +
@@ -234,26 +234,22 @@
Query Result
+ [(ngModel)]="inputTextMQL2[i]" (keyup)="generateMQL()" placeholder="value">
-
-
- -
-
-
-
-
+
+
+
+ +
-
Generated query

Edit your code if needed.

diff --git a/src/app/views/querying/graphical-querying/graphical-querying.component.ts b/src/app/views/querying/graphical-querying/graphical-querying.component.ts index 2a51bfa1..4a8bdc59 100644 --- a/src/app/views/querying/graphical-querying/graphical-querying.component.ts +++ b/src/app/views/querying/graphical-querying/graphical-querying.component.ts @@ -418,12 +418,12 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest addMQLField() { this.fieldCounter += 1; - this.colList.push(String(this.fieldCounter)); + this.colList.push(String(this.fieldCounter += 1)); } - deleteMQLField(name:string) { + /*deleteMQLField(name:string) { this.colList = this.colList.filter(col => col !== name); - } + }*/ async generateCypher() { let cypher = ''; //TO DO: dynamic namespace @@ -436,24 +436,41 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest switch (this.inputMatchMQL) { case 'mql-and': mql += 'db.getCollection("' + this.collectionName + '").find({'; + for (let i = 0; i < this.inputDropdownMQL.length; i++) { + if (this.inputDropdownMQL[i] === 'equal') { + mql += this.inputTextMQL1[i] + ' : ' + this.inputTextMQL2[i]; + } + else if (this.inputDropdownMQL[i] === 'notequal') { + mql += this.inputTextMQL1[i] + ': {"$ne" : ' + this.inputTextMQL2[i] + '}'; + } + if (i+1 !== this.inputDropdownMQL.length) { + mql += ', '; + } + } + mql += '})'; break; case 'mql-or': - mql += 'db.getCollection("' + this.collectionName + '").find({"$or" : [{'; - break; case 'mql-nor': - mql += 'db.getCollection("' + this.collectionName + '").find({"$nor" : [{'; + if (this.inputMatchMQL === 'mql-or') { + mql += 'db.getCollection("' + this.collectionName + '").find({"$or" : ['; + } + else if (this.inputMatchMQL === 'mql-nor') { + mql += 'db.getCollection("' + this.collectionName + '").find({"$nor" : ['; + } + for (let i = 0; i < this.inputDropdownMQL.length; i++) { + if (this.inputDropdownMQL[i] === 'equal') { + mql += '{' + this.inputTextMQL1[i] + ' : ' + this.inputTextMQL2[i] + '}'; + } + else if (this.inputDropdownMQL[i] === 'notequal') { + mql += '{' + this.inputTextMQL1[i] + ': {"$ne" : ' + this.inputTextMQL2[i] + '}}'; + } + if (i+1 !== this.inputDropdownMQL.length) { + mql += ', '; + } + } + mql += ']})'; break; } - for (let i = 0; i < this.inputDropdownMQL.length; i++) { - mql += this.inputTextMQL1[i] + this.inputDropdownMQL[i] + this.inputTextMQL2[i]; - if (i+1 !== this.inputDropdownMQL.length) { - mql += ', '; - } - } - // TO DO: if and - mql += '})'; - // TO DO: if or - // TO DO: if nor this.editorGenerated.setCode(mql); } From 90ae085377ee16701ec7e6b57d3bde6ac4edf898 Mon Sep 17 00:00:00 2001 From: svamel00 Date: Sun, 19 Feb 2023 22:16:20 +0100 Subject: [PATCH 07/60] extended cypher prototyp with additional input fields. Fixxed multiple smaller bugs. --- .../graphical-querying.component.html | 326 +++++++++--------- .../graphical-querying.component.ts | 80 ++++- 2 files changed, 240 insertions(+), 166 deletions(-) diff --git a/src/app/views/querying/graphical-querying/graphical-querying.component.html b/src/app/views/querying/graphical-querying/graphical-querying.component.html index cbb1a03f..d24a2f20 100644 --- a/src/app/views/querying/graphical-querying/graphical-querying.component.html +++ b/src/app/views/querying/graphical-querying/graphical-querying.component.html @@ -1,26 +1,26 @@
-
Graphical Querying
+
Graphical Querying
- - - -

Select your query language:

-
+ + + +

Select your query language:

+
- -
+ +

Select columns from the left sidebar to get started. If needed, you can edit the generated SQL code.

@@ -100,10 +100,10 @@
Query Result
- -
-

Select your namespace from the left sidebar.

- + +
+

1. Select your graph from the left sidebar: {{ graphName !== undefined ? ' ' + graphName : '' }}

+
-
-
- -
- - -
- -
-
- -
- -
- -
-
- -
- -
- -
Generated query
-

Edit your code if needed.

-
- -
- - - - -
-
-
Query Result
-
- -
- -
- {{resultSet.generatedQuery}} - - {{resultSet.affectedRows}} - ! - -
- -
-
- Error: -

{{resultSet.error}}

-
- -
-

- Successfully executed -

-
- -
-
- -
-
-
-
- -
- - -
-

1. Select your collection from the left sidebar.

- -
-

2. Choose how you want to find the elements.

-
-
- -
- -
- -
-

3. Fill in the details.

- - -
-
-
-
-
- -
- +

2. Fill in the details.

+
+
+
+
+
+
-
-
-
- -
- +
+
+
+
+
+
-
-
-
- -
- +
+
+
+
+
+
- -
-
- +
+
+
-
- + +
+ +
+
+
+
Generated query
-

Edit your code if needed.

-
+

Edit your code if needed.

+
-
+
- - + + -
-
-
Query Result
-
+
+
+
Query Result
+
-
+
{{resultSet.generatedQuery}} @@ -283,28 +193,136 @@
Query Result

- Successfully executed + Successfully executed

- +
-
-
+ +
+

1. Select your collection from the left sidebar: {{ collectionName !== undefined ? ' ' + collectionName : '' }}

+
+

2. Choose how you want to find the elements.

+
+
+ +
+ +
+
+

3. Fill in the details.

+ + +
+
+
+
+
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+
+ +
+
+ +
+
+ +
+
+ +
Generated query
+

Edit your code if needed.

+
+ +
+ + + + +
+
+
Query Result
+
+ +
+ +
+ {{resultSet.generatedQuery}} + + {{resultSet.affectedRows}} + ! + +
+ +
+
+ Error: +

{{resultSet.error}}

+
+ +
+

+ Successfully executed +

+
+ +
+
+ +
+
+
+
+
+ +
+
+
-
diff --git a/src/app/views/querying/graphical-querying/graphical-querying.component.ts b/src/app/views/querying/graphical-querying/graphical-querying.component.ts index 4a8bdc59..1cf06409 100644 --- a/src/app/views/querying/graphical-querying/graphical-querying.component.ts +++ b/src/app/views/querying/graphical-querying/graphical-querying.component.ts @@ -76,22 +76,22 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest // new additions by me: lang: string; // usage as lang in console.component.hmtl 'sql', 'cypher', 'mql' - tableId: string; config: TableConfig; - - - inputMatch = ''; + // cypher input fields + inputMatch: string[] = ['','','']; // three input fields for match inputWhere = ''; inputReturn = ''; - colList: string[] = ['1']; + colList: string[] = ['1']; // each newly created input field in mql gets another value + // mql input fields inputMatchMQL = ''; inputDropdownMQL: string[] = []; inputTextMQL1: string[] = []; inputTextMQL2: string[] = []; activeNamespace: string; // same usage as console.components.ts collectionName: string; - fieldCounter = 1; + graphName: string; + fieldCounter = 0; private readonly LOCAL_STORAGE_NAMESPACE_KEY = 'polypheny-namespace'; // same usage as console.components.ts ngOnInit() { @@ -169,6 +169,7 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest res => { const nodeAction = (tree, node, $event) => { console.log(node.id); + this.graphName = node.id; this.setDefaultDB(node.id); //changes the activeNamespace to the one chosen on the left side }; @@ -409,6 +410,43 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest return '"' + k.split('.').join('"."') + '"'; } + setDefaultState(inputlang: string) { //sets the field values to zero if the user switches languages + switch (inputlang) { + case 'sql': + this.collectionName = undefined; + this.graphName = undefined; + this.inputMatchMQL = ''; + this.inputDropdownMQL = []; + this.inputTextMQL1 = []; + this.inputTextMQL2 = []; + this.fieldCounter = 1; + document.getElementById('mql-type').onclick = () => { + this.inputMatchMQL = null; + }; + this.inputMatch = ['','','']; // three input fields for match + this.inputWhere = ''; + this.inputReturn = ''; + break; + case 'cypher': + this.collectionName = undefined; + this.inputMatchMQL = ''; + this.inputDropdownMQL = []; + this.inputTextMQL1 = []; + this.inputTextMQL2 = []; + this.fieldCounter = 1; + document.getElementById('mql-type').onclick = () => { + this.inputMatchMQL = null; + }; + break; + case 'mql': + this.graphName = undefined; + this.inputMatch = ['','','']; // three input fields for match + this.inputWhere = ''; + this.inputReturn = ''; + break; + } + } + // inspired by the same function in console.component.ts private setDefaultDB(name: string) { name = name.trim(); @@ -418,16 +456,34 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest addMQLField() { this.fieldCounter += 1; - this.colList.push(String(this.fieldCounter += 1)); + this.colList.push(String(this.fieldCounter)); } - /*deleteMQLField(name:string) { - this.colList = this.colList.filter(col => col !== name); - }*/ + deleteMQLField() { + //this.colList = this.colList.filter(col => col !== name); + this.colList.pop(); + this.inputDropdownMQL[this.fieldCounter] = ''; + this.inputTextMQL1[this.fieldCounter] = ''; + this.inputTextMQL2[this.fieldCounter] = ''; + if (this.fieldCounter > -1) { // fixes bug if delete icon is clicked if there are no fields left + this.fieldCounter -= 1; + } + this.generateMQL(); + } async generateCypher() { let cypher = ''; //TO DO: dynamic namespace - cypher += 'MATCH ' + this.inputMatch + '\nWHERE ' + this.inputWhere + '\nRETURN ' + this.inputReturn + ';'; + cypher += 'MATCH '; + if (this.inputMatch[1] === '') { + cypher += '(' + this.inputMatch[0] + ')'; + } + else { + cypher += '(' + this.inputMatch[0] + ')-[' + this.inputMatch[1] + ']->(' + this.inputMatch[2] + ')'; + } + if (this.inputWhere !== '') { + cypher += '\nWHERE ' + this.inputWhere; + } + cypher += '\nRETURN ' + this.inputReturn + ';'; this.editorGenerated.setCode(cypher); } @@ -443,7 +499,7 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest else if (this.inputDropdownMQL[i] === 'notequal') { mql += this.inputTextMQL1[i] + ': {"$ne" : ' + this.inputTextMQL2[i] + '}'; } - if (i+1 !== this.inputDropdownMQL.length) { + if (i+1 <= this.inputDropdownMQL.length - 1 && this.inputDropdownMQL[i+1] !== '') { mql += ', '; } } From 6a35c66b65b44f1d799e8cbe1157daec03ee7e91 Mon Sep 17 00:00:00 2001 From: svamel00 Date: Tue, 21 Feb 2023 10:26:38 +0100 Subject: [PATCH 08/60] extended mql querying with greater and lesser --- .../graphical-querying.component.html | 4 ++ .../graphical-querying.component.ts | 55 ++++++++++++++----- 2 files changed, 46 insertions(+), 13 deletions(-) diff --git a/src/app/views/querying/graphical-querying/graphical-querying.component.html b/src/app/views/querying/graphical-querying/graphical-querying.component.html index d24a2f20..e75ac4b5 100644 --- a/src/app/views/querying/graphical-querying/graphical-querying.component.html +++ b/src/app/views/querying/graphical-querying/graphical-querying.component.html @@ -247,6 +247,10 @@
Query Result
diff --git a/src/app/views/querying/graphical-querying/graphical-querying.component.ts b/src/app/views/querying/graphical-querying/graphical-querying.component.ts index 1cf06409..08c69994 100644 --- a/src/app/views/querying/graphical-querying/graphical-querying.component.ts +++ b/src/app/views/querying/graphical-querying/graphical-querying.component.ts @@ -489,15 +489,30 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest async generateMQL() { let mql = ''; + //BUG: Special case if they are the same key, they have to get in the same bracket switch (this.inputMatchMQL) { case 'mql-and': mql += 'db.getCollection("' + this.collectionName + '").find({'; for (let i = 0; i < this.inputDropdownMQL.length; i++) { - if (this.inputDropdownMQL[i] === 'equal') { - mql += this.inputTextMQL1[i] + ' : ' + this.inputTextMQL2[i]; - } - else if (this.inputDropdownMQL[i] === 'notequal') { - mql += this.inputTextMQL1[i] + ': {"$ne" : ' + this.inputTextMQL2[i] + '}'; + switch (this.inputDropdownMQL[i]) { + case 'equal': + mql += this.inputTextMQL1[i] + ' : ' + this.inputTextMQL2[i]; + break; + case 'notequal': + mql += this.inputTextMQL1[i] + ': {"$ne" : ' + this.inputTextMQL2[i] + '}'; + break; + case 'greater': + mql += this.inputTextMQL1[i] + ': {"$gt" : ' + this.inputTextMQL2[i] + '}'; + break; + case 'lesser': + mql += this.inputTextMQL1[i] + ': {"$lt" : ' + this.inputTextMQL2[i] + '}'; + break; + //case 'contains': + // mql += this.inputTextMQL1[i] + ' : /.*' + this.inputTextMQL2[i] + '.*/i'; + // break; + //case 'notcontains': + // mql += this.inputTextMQL1[i] + ': {"$not" : /.*' + this.inputTextMQL2[i] + '.*/i}'; + // break;*// } if (i+1 <= this.inputDropdownMQL.length - 1 && this.inputDropdownMQL[i+1] !== '') { mql += ', '; @@ -508,19 +523,33 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest case 'mql-or': case 'mql-nor': if (this.inputMatchMQL === 'mql-or') { - mql += 'db.getCollection("' + this.collectionName + '").find({"$or" : ['; + mql += 'db.getCollection("' + this.collectionName + '").find({"$or" : ['; } else if (this.inputMatchMQL === 'mql-nor') { - mql += 'db.getCollection("' + this.collectionName + '").find({"$nor" : ['; + mql += 'db.getCollection("' + this.collectionName + '").find({"$nor" : ['; } for (let i = 0; i < this.inputDropdownMQL.length; i++) { - if (this.inputDropdownMQL[i] === 'equal') { - mql += '{' + this.inputTextMQL1[i] + ' : ' + this.inputTextMQL2[i] + '}'; - } - else if (this.inputDropdownMQL[i] === 'notequal') { - mql += '{' + this.inputTextMQL1[i] + ': {"$ne" : ' + this.inputTextMQL2[i] + '}}'; + switch (this.inputDropdownMQL[i]) { + case 'equal': + mql += '{' + this.inputTextMQL1[i] + ' : ' + this.inputTextMQL2[i] + '}'; + break; + case 'notequal': + mql += '{' + this.inputTextMQL1[i] + ': {"$ne" : ' + this.inputTextMQL2[i] + '}}'; + break; + case 'greater': + mql += '{' + this.inputTextMQL1[i] + ': {"$gt" : ' + this.inputTextMQL2[i] + '}}'; + break; + case 'lesser': + mql += '{' + this.inputTextMQL1[i] + ': {"$lt" : ' + this.inputTextMQL2[i] + '}}'; + break; + //case 'contains': + // mql += this.inputTextMQL1[i] + ' : /.*' + this.inputTextMQL2[i] + '.*/i'; + // break; + //case 'notcontains': + // mql += this.inputTextMQL1[i] + ': {"$not" : /.*' + this.inputTextMQL2[i] + '.*/i}'; + // break;*// } - if (i+1 !== this.inputDropdownMQL.length) { + if (i+1 <= this.inputDropdownMQL.length - 1 && this.inputDropdownMQL[i+1] !== '') { mql += ', '; } } From a50de2fe70c27fc5f82f6fd1f13576505e857d35 Mon Sep 17 00:00:00 2001 From: svamel00 Date: Tue, 21 Feb 2023 12:16:12 +0100 Subject: [PATCH 09/60] added extra fields for relationship types in cypher --- .../graphical-querying.component.html | 88 +++++++++++++++---- .../graphical-querying.component.ts | 30 ++++--- 2 files changed, 91 insertions(+), 27 deletions(-) diff --git a/src/app/views/querying/graphical-querying/graphical-querying.component.html b/src/app/views/querying/graphical-querying/graphical-querying.component.html index e75ac4b5..5e8bca60 100644 --- a/src/app/views/querying/graphical-querying/graphical-querying.component.html +++ b/src/app/views/querying/graphical-querying/graphical-querying.component.html @@ -114,50 +114,104 @@
Query Result
-->

2. Fill in the details.

+
+
+ +
+ +
+
-
+
- + +
+ +
+
+ +
+
+
+
+ +
+ +
+
+
+
+
+ +
+
-
-
-
- +
+
+
+ +
+
-
+
+
+
+
-
-
- +
+
+
+ +
+ +
+
+
+
+
+
+
+ +
+
-
+
+ [(ngModel)]="inputWhere" (keyup)="generateCypher()">
- +
+ [(ngModel)]="inputReturn" (keyup)="generateCypher()">
Generated query
diff --git a/src/app/views/querying/graphical-querying/graphical-querying.component.ts b/src/app/views/querying/graphical-querying/graphical-querying.component.ts index 08c69994..6058022b 100644 --- a/src/app/views/querying/graphical-querying/graphical-querying.component.ts +++ b/src/app/views/querying/graphical-querying/graphical-querying.component.ts @@ -79,9 +79,12 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest tableId: string; config: TableConfig; // cypher input fields - inputMatch: string[] = ['','','']; // three input fields for match + inputMatch = ''; inputWhere = ''; inputReturn = ''; + inputDropdownCypher: string; + + inputRelationship: string[] = ['','','','']; // [0] = Relationship, [1] = Node, [2] = 2.Relationship, [3] = 2.Node colList: string[] = ['1']; // each newly created input field in mql gets another value // mql input fields inputMatchMQL = ''; @@ -423,9 +426,10 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest document.getElementById('mql-type').onclick = () => { this.inputMatchMQL = null; }; - this.inputMatch = ['','','']; // three input fields for match + this.inputMatch = ''; // three input fields for match this.inputWhere = ''; this.inputReturn = ''; + this.inputRelationship = ['','','','']; break; case 'cypher': this.collectionName = undefined; @@ -440,9 +444,10 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest break; case 'mql': this.graphName = undefined; - this.inputMatch = ['','','']; // three input fields for match + this.inputMatch = ''; // three input fields for match this.inputWhere = ''; this.inputReturn = ''; + this.inputRelationship = ['','','','']; break; } } @@ -472,13 +477,18 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest } async generateCypher() { - let cypher = ''; //TO DO: dynamic namespace - cypher += 'MATCH '; - if (this.inputMatch[1] === '') { - cypher += '(' + this.inputMatch[0] + ')'; - } - else { - cypher += '(' + this.inputMatch[0] + ')-[' + this.inputMatch[1] + ']->(' + this.inputMatch[2] + ')'; + let cypher = ''; + cypher += 'MATCH ' + '(' + this.inputMatch + ')'; + switch (this.inputDropdownCypher) { + case 'cypher-outgoing': + cypher += '-->(' + this.inputRelationship[1] + ')'; + break; + case 'cypher-directed': + cypher += '-[' + this.inputRelationship[0] + ']->(' + this.inputRelationship[1] + ')'; + break; + case 'cypher-multiple': + cypher += '-[' + this.inputRelationship[0] + ']->(' + this.inputRelationship[1] + ')<-[' + this.inputRelationship[2] + ']-(' + this.inputRelationship[3] + ')'; + break; } if (this.inputWhere !== '') { cypher += '\nWHERE ' + this.inputWhere; From 399bb4633b6ece7d5c0fbdd92ba3dc3396bdc350 Mon Sep 17 00:00:00 2001 From: svamel00 Date: Wed, 22 Feb 2023 15:38:59 +0100 Subject: [PATCH 10/60] added delete button for every new row in mql --- .../graphical-querying.component.html | 101 ++++++----- .../graphical-querying.component.ts | 157 +++++++++--------- 2 files changed, 130 insertions(+), 128 deletions(-) diff --git a/src/app/views/querying/graphical-querying/graphical-querying.component.html b/src/app/views/querying/graphical-querying/graphical-querying.component.html index 5e8bca60..e486188f 100644 --- a/src/app/views/querying/graphical-querying/graphical-querying.component.html +++ b/src/app/views/querying/graphical-querying/graphical-querying.component.html @@ -106,12 +106,8 @@
Query Result
-

2. Fill in the details.

@@ -119,7 +115,7 @@
Query Result
+ [(ngModel)]="cypherMatch" (keyup)="generateCypher()" placeholder="Node">
@@ -128,7 +124,7 @@
Query Result
- @@ -139,33 +135,33 @@
Query Result
-
+
+ [(ngModel)]="cypherRelationship[1]" (keyup)="generateCypher()" placeholder="Node">
-
+
+ [(ngModel)]="cypherRelationship[0]" (keyup)="generateCypher()" placeholder="Relationship">
-
+
+ [(ngModel)]="cypherRelationship[1]" (keyup)="generateCypher()" placeholder="Node">
@@ -174,24 +170,24 @@
Query Result
-
+
+ [(ngModel)]="cypherRelationship[2]" (keyup)="generateCypher()" placeholder="2. Relationship">
-
+
+ [(ngModel)]="cypherRelationship[3]" (keyup)="generateCypher()" placeholder="2. Node">
@@ -203,7 +199,7 @@
Query Result
+ [(ngModel)]="cypherWhere" (keyup)="generateCypher()">
@@ -211,7 +207,7 @@
Query Result
+ [(ngModel)]="cypherReturn" (keyup)="generateCypher()">
Generated query
@@ -271,50 +267,56 @@
Query Result
-
-
+

3. Fill in the details.

-
-
-
-
-
- +
+
+
+
+
+
+ +
+
-
-
-
-
-
- +
+
+
+ +
+
-
-
-
-
-
- +
+
+
+ +
+
- +
+
+ +
@@ -325,9 +327,6 @@
Query Result
-
- -
Generated query
diff --git a/src/app/views/querying/graphical-querying/graphical-querying.component.ts b/src/app/views/querying/graphical-querying/graphical-querying.component.ts index 6058022b..84cbd7e6 100644 --- a/src/app/views/querying/graphical-querying/graphical-querying.component.ts +++ b/src/app/views/querying/graphical-querying/graphical-querying.component.ts @@ -79,18 +79,18 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest tableId: string; config: TableConfig; // cypher input fields - inputMatch = ''; - inputWhere = ''; - inputReturn = ''; - inputDropdownCypher: string; + cypherMatch = ''; + cypherWhere = ''; + cypherReturn = ''; + cypherDropdown: string; - inputRelationship: string[] = ['','','','']; // [0] = Relationship, [1] = Node, [2] = 2.Relationship, [3] = 2.Node - colList: string[] = ['1']; // each newly created input field in mql gets another value + cypherRelationship: string[] = ['','','','']; // [0] = Relationship, [1] = Node, [2] = 2.Relationship, [3] = 2.Node + fieldList: string[] = ['0']; // each newly created input field in mql gets another value // mql input fields - inputMatchMQL = ''; - inputDropdownMQL: string[] = []; - inputTextMQL1: string[] = []; - inputTextMQL2: string[] = []; + mqlMatch = ''; + mqlDropdown: string[] = []; + mqlText1: string[] = []; + mqlTest2: string[] = []; activeNamespace: string; // same usage as console.components.ts collectionName: string; graphName: string; @@ -418,36 +418,38 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest case 'sql': this.collectionName = undefined; this.graphName = undefined; - this.inputMatchMQL = ''; - this.inputDropdownMQL = []; - this.inputTextMQL1 = []; - this.inputTextMQL2 = []; - this.fieldCounter = 1; + this.mqlMatch = ''; + this.mqlDropdown = []; + this.mqlText1 = []; + this.mqlTest2 = []; + this.fieldCounter = 0; + this.fieldList = ['0']; document.getElementById('mql-type').onclick = () => { - this.inputMatchMQL = null; + this.mqlMatch = null; }; - this.inputMatch = ''; // three input fields for match - this.inputWhere = ''; - this.inputReturn = ''; - this.inputRelationship = ['','','','']; + this.cypherMatch = ''; // three input fields for match + this.cypherWhere = ''; + this.cypherReturn = ''; + this.cypherRelationship = ['','','','']; break; case 'cypher': this.collectionName = undefined; - this.inputMatchMQL = ''; - this.inputDropdownMQL = []; - this.inputTextMQL1 = []; - this.inputTextMQL2 = []; - this.fieldCounter = 1; + this.mqlMatch = ''; + this.mqlDropdown = []; + this.mqlText1 = []; + this.mqlTest2 = []; + this.fieldCounter = 0; document.getElementById('mql-type').onclick = () => { - this.inputMatchMQL = null; + this.mqlMatch = null; }; + this.fieldList = ['0']; break; case 'mql': this.graphName = undefined; - this.inputMatch = ''; // three input fields for match - this.inputWhere = ''; - this.inputReturn = ''; - this.inputRelationship = ['','','','']; + this.cypherMatch = ''; // three input fields for match + this.cypherWhere = ''; + this.cypherReturn = ''; + this.cypherRelationship = ['','','','']; break; } } @@ -461,70 +463,71 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest addMQLField() { this.fieldCounter += 1; - this.colList.push(String(this.fieldCounter)); + this.fieldList.push(String(this.fieldCounter)); } - deleteMQLField() { - //this.colList = this.colList.filter(col => col !== name); - this.colList.pop(); - this.inputDropdownMQL[this.fieldCounter] = ''; - this.inputTextMQL1[this.fieldCounter] = ''; - this.inputTextMQL2[this.fieldCounter] = ''; - if (this.fieldCounter > -1) { // fixes bug if delete icon is clicked if there are no fields left - this.fieldCounter -= 1; - } + deleteMQLField(field:string) { + const x = Number(field); + this.mqlDropdown[x] = ''; + this.mqlText1[x] = ''; + this.mqlTest2[x] = ''; + this.fieldList[x] = ''; this.generateMQL(); } async generateCypher() { let cypher = ''; - cypher += 'MATCH ' + '(' + this.inputMatch + ')'; - switch (this.inputDropdownCypher) { + cypher += 'MATCH ' + '(' + this.cypherMatch + ')'; + switch (this.cypherDropdown) { case 'cypher-outgoing': - cypher += '-->(' + this.inputRelationship[1] + ')'; + cypher += '-->(' + this.cypherRelationship[1] + ')'; break; case 'cypher-directed': - cypher += '-[' + this.inputRelationship[0] + ']->(' + this.inputRelationship[1] + ')'; + cypher += '-[' + this.cypherRelationship[0] + ']->(' + this.cypherRelationship[1] + ')'; break; case 'cypher-multiple': - cypher += '-[' + this.inputRelationship[0] + ']->(' + this.inputRelationship[1] + ')<-[' + this.inputRelationship[2] + ']-(' + this.inputRelationship[3] + ')'; + cypher += '-[' + this.cypherRelationship[0] + ']->(' + this.cypherRelationship[1] + ')<-[' + this.cypherRelationship[2] + ']-(' + this.cypherRelationship[3] + ')'; break; } - if (this.inputWhere !== '') { - cypher += '\nWHERE ' + this.inputWhere; + if (this.cypherWhere !== '') { + cypher += '\nWHERE ' + this.cypherWhere; } - cypher += '\nRETURN ' + this.inputReturn + ';'; + cypher += '\nRETURN ' + this.cypherReturn + ';'; this.editorGenerated.setCode(cypher); } async generateMQL() { let mql = ''; //BUG: Special case if they are the same key, they have to get in the same bracket - switch (this.inputMatchMQL) { + // Filter empty fields + const mqlDropdownf = this.mqlDropdown.filter((el) => el !== ''); + const mqlText1f = this.mqlText1.filter((_, idx) => mqlDropdownf[idx]); + const mqlText2f = this.mqlTest2.filter((_, idx) => mqlDropdownf[idx]); + switch (this.mqlMatch) { case 'mql-and': mql += 'db.getCollection("' + this.collectionName + '").find({'; - for (let i = 0; i < this.inputDropdownMQL.length; i++) { - switch (this.inputDropdownMQL[i]) { + for (let i = 0; i < mqlDropdownf.length; i++) { + switch (mqlDropdownf[i]) { case 'equal': - mql += this.inputTextMQL1[i] + ' : ' + this.inputTextMQL2[i]; + mql += mqlText1f[i] + ' : ' + mqlText2f[i]; break; case 'notequal': - mql += this.inputTextMQL1[i] + ': {"$ne" : ' + this.inputTextMQL2[i] + '}'; + mql += mqlText1f[i] + ': {"$ne" : ' + mqlText2f[i] + '}'; break; case 'greater': - mql += this.inputTextMQL1[i] + ': {"$gt" : ' + this.inputTextMQL2[i] + '}'; + mql += mqlText1f[i] + ': {"$gt" : ' + mqlText2f[i] + '}'; break; case 'lesser': - mql += this.inputTextMQL1[i] + ': {"$lt" : ' + this.inputTextMQL2[i] + '}'; + mql += mqlText1f[i] + ': {"$lt" : ' + mqlText2f[i] + '}'; + break; + case 'contains': + mql += mqlText1f[i] + ' : {$regex: \'/.*' + mqlText2f[i] + '.*/i\'}'; + break; + case 'notcontains': + mql += mqlText1f[i] + ': {"$not" : /.*' + mqlText2f[i] + '.*/i}'; break; - //case 'contains': - // mql += this.inputTextMQL1[i] + ' : /.*' + this.inputTextMQL2[i] + '.*/i'; - // break; - //case 'notcontains': - // mql += this.inputTextMQL1[i] + ': {"$not" : /.*' + this.inputTextMQL2[i] + '.*/i}'; - // break;*// } - if (i+1 <= this.inputDropdownMQL.length - 1 && this.inputDropdownMQL[i+1] !== '') { + if (i+1 <= mqlDropdownf.length - 1 && mqlDropdownf[i+1] !== '') { mql += ', '; } } @@ -532,34 +535,34 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest break; case 'mql-or': case 'mql-nor': - if (this.inputMatchMQL === 'mql-or') { + if (this.mqlMatch === 'mql-or') { mql += 'db.getCollection("' + this.collectionName + '").find({"$or" : ['; } - else if (this.inputMatchMQL === 'mql-nor') { + else if (this.mqlMatch === 'mql-nor') { mql += 'db.getCollection("' + this.collectionName + '").find({"$nor" : ['; } - for (let i = 0; i < this.inputDropdownMQL.length; i++) { - switch (this.inputDropdownMQL[i]) { + for (let i = 0; i < mqlDropdownf.length; i++) { + switch (mqlDropdownf[i]) { case 'equal': - mql += '{' + this.inputTextMQL1[i] + ' : ' + this.inputTextMQL2[i] + '}'; + mql += '{' + mqlText1f[i] + ' : ' + mqlText2f[i] + '}'; break; case 'notequal': - mql += '{' + this.inputTextMQL1[i] + ': {"$ne" : ' + this.inputTextMQL2[i] + '}}'; + mql += '{' + mqlText1f[i] + ': {"$ne" : ' + mqlText2f[i] + '}}'; break; case 'greater': - mql += '{' + this.inputTextMQL1[i] + ': {"$gt" : ' + this.inputTextMQL2[i] + '}}'; + mql += '{' + mqlText1f[i] + ': {"$gt" : ' + mqlText2f[i] + '}}'; break; case 'lesser': - mql += '{' + this.inputTextMQL1[i] + ': {"$lt" : ' + this.inputTextMQL2[i] + '}}'; + mql += '{' + mqlText1f[i] + ': {"$lt" : ' + mqlText2f[i] + '}}'; + break; + case 'contains': + mql += mqlText1f[i] + ' : /.*' + mqlText2f[i] + '.*/i'; + break; + case 'notcontains': + mql += mqlText1f[i] + ': {"$not" : /.*' + mqlText2f[i] + '.*/i}'; break; - //case 'contains': - // mql += this.inputTextMQL1[i] + ' : /.*' + this.inputTextMQL2[i] + '.*/i'; - // break; - //case 'notcontains': - // mql += this.inputTextMQL1[i] + ': {"$not" : /.*' + this.inputTextMQL2[i] + '.*/i}'; - // break;*// } - if (i+1 <= this.inputDropdownMQL.length - 1 && this.inputDropdownMQL[i+1] !== '') { + if (i+1 <= mqlDropdownf.length - 1 && mqlDropdownf[i+1] !== '') { mql += ', '; } } From 4430b440676cddf2545a6c93e7b130e0083ed321 Mon Sep 17 00:00:00 2001 From: svamel00 Date: Thu, 23 Feb 2023 00:06:16 +0100 Subject: [PATCH 11/60] added dropdown for mql button --- .../graphical-querying.component.html | 22 +++++++++++++-- .../graphical-querying.component.scss | 14 ++++++++++ .../graphical-querying.component.ts | 28 +++++++++++++++++++ 3 files changed, 61 insertions(+), 3 deletions(-) diff --git a/src/app/views/querying/graphical-querying/graphical-querying.component.html b/src/app/views/querying/graphical-querying/graphical-querying.component.html index e486188f..5849b946 100644 --- a/src/app/views/querying/graphical-querying/graphical-querying.component.html +++ b/src/app/views/querying/graphical-querying/graphical-querying.component.html @@ -290,7 +290,7 @@
Query Result
[(ngModel)]="mqlText1[i]" (keyup)="generateMQL()" placeholder="key">
-
+
@@ -322,12 +322,28 @@
Query Result
- +
+
+ + +
+
+ + +
Generated query

Edit your code if needed.

diff --git a/src/app/views/querying/graphical-querying/graphical-querying.component.scss b/src/app/views/querying/graphical-querying/graphical-querying.component.scss index eb077a81..ef9f586b 100644 --- a/src/app/views/querying/graphical-querying/graphical-querying.component.scss +++ b/src/app/views/querying/graphical-querying/graphical-querying.component.scss @@ -56,3 +56,17 @@ padding-right: 0; } +//Dropdown +.json-dropdown { + display: block; + // center block + margin: 0 auto; + position: absolute; + left: 50%; + transform: translateX(-50%); +} + +.show-error { + display: block !important; +} + diff --git a/src/app/views/querying/graphical-querying/graphical-querying.component.ts b/src/app/views/querying/graphical-querying/graphical-querying.component.ts index 84cbd7e6..c8c3d373 100644 --- a/src/app/views/querying/graphical-querying/graphical-querying.component.ts +++ b/src/app/views/querying/graphical-querying/graphical-querying.component.ts @@ -97,6 +97,12 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest fieldCounter = 0; private readonly LOCAL_STORAGE_NAMESPACE_KEY = 'polypheny-namespace'; // same usage as console.components.ts + show = false; + private debounce: any; + private debounceDelay = 200; + showError: boolean; + + ngOnInit() { this._leftSidebar.open(); this.initSchema(this.lang); @@ -461,6 +467,28 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest localStorage.setItem(this.LOCAL_STORAGE_NAMESPACE_KEY, name); } + //taken from json-editor.component.ts + setMenuShow(doShow: boolean, instant = false) { + if (instant) { + this.show = doShow; + return; + } + if (!doShow) { + this.debounce = setTimeout(() => { + this.show = false; + }, this.debounceDelay); + } else { + this.show = true; + } + } + + //taken from json-editor.component.ts + menuEnter() { + if (this.show) { + clearTimeout(this.debounce); + } + } + addMQLField() { this.fieldCounter += 1; this.fieldList.push(String(this.fieldCounter)); From f71d37a8d61590fe600a1ce8c032d87c02f324b4 Mon Sep 17 00:00:00 2001 From: svamel00 Date: Fri, 24 Feb 2023 23:19:18 +0100 Subject: [PATCH 12/60] added first buggy prototype for mql for its properties. Bugs to fix: switching languages and delete button --- .../graphical-querying.component.html | 49 ++++++++------ .../graphical-querying.component.ts | 64 +++++++++++++++---- 2 files changed, 82 insertions(+), 31 deletions(-) diff --git a/src/app/views/querying/graphical-querying/graphical-querying.component.html b/src/app/views/querying/graphical-querying/graphical-querying.component.html index 5849b946..bb97475d 100644 --- a/src/app/views/querying/graphical-querying/graphical-querying.component.html +++ b/src/app/views/querying/graphical-querying/graphical-querying.component.html @@ -280,38 +280,42 @@
Query Result
-
+
+ [(ngModel)]="mqlTextX[i]" (keyup)="prependKeyObject(this.fieldDepth[i], i); generateMQL()" placeholder="key">
-
-
- +
+
+
+ +
+
-
-
-
- +
+
+
+ +
+
-
@@ -328,10 +332,15 @@
Query Result
class="fa fa-plus">
diff --git a/src/app/views/querying/graphical-querying/graphical-querying.component.ts b/src/app/views/querying/graphical-querying/graphical-querying.component.ts index c8c3d373..0753f442 100644 --- a/src/app/views/querying/graphical-querying/graphical-querying.component.ts +++ b/src/app/views/querying/graphical-querying/graphical-querying.component.ts @@ -86,23 +86,26 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest cypherRelationship: string[] = ['','','','']; // [0] = Relationship, [1] = Node, [2] = 2.Relationship, [3] = 2.Node fieldList: string[] = ['0']; // each newly created input field in mql gets another value + fieldDepth: number[] = [0]; + fieldDepthCounter = 0; // mql input fields mqlMatch = ''; mqlDropdown: string[] = []; + mqlTextX: string[] =[]; mqlText1: string[] = []; - mqlTest2: string[] = []; + mqlText2: string[] = []; activeNamespace: string; // same usage as console.components.ts collectionName: string; graphName: string; fieldCounter = 0; private readonly LOCAL_STORAGE_NAMESPACE_KEY = 'polypheny-namespace'; // same usage as console.components.ts + // Dropdown show = false; private debounce: any; private debounceDelay = 200; showError: boolean; - ngOnInit() { this._leftSidebar.open(); this.initSchema(this.lang); @@ -426,10 +429,13 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest this.graphName = undefined; this.mqlMatch = ''; this.mqlDropdown = []; + this.mqlTextX = []; this.mqlText1 = []; - this.mqlTest2 = []; + this.mqlText2 = []; this.fieldCounter = 0; this.fieldList = ['0']; + this.fieldDepth = []; + this.fieldDepthCounter = 0; document.getElementById('mql-type').onclick = () => { this.mqlMatch = null; }; @@ -442,13 +448,16 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest this.collectionName = undefined; this.mqlMatch = ''; this.mqlDropdown = []; + this.mqlTextX = []; this.mqlText1 = []; - this.mqlTest2 = []; + this.mqlText2 = []; this.fieldCounter = 0; document.getElementById('mql-type').onclick = () => { this.mqlMatch = null; }; this.fieldList = ['0']; + this.fieldDepth = []; + this.fieldDepthCounter = 0; break; case 'mql': this.graphName = undefined; @@ -489,16 +498,49 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest } } - addMQLField() { + addMQLField() { // 'normal new Field' this.fieldCounter += 1; this.fieldList.push(String(this.fieldCounter)); + this.fieldDepthCounter = 0; + this.fieldDepth.push(this.fieldDepthCounter); + } + + addMQLFieldKeyObject() { // adding a property + this.fieldCounter += 1; + this.fieldList.push(String(this.fieldCounter)); //adding addition marker to fieldList + this.fieldDepthCounter += 1; + this.fieldDepth.push(this.fieldDepthCounter); + } + + addMQLFieldKeyObject2() { // staying on the same 'level' of property + this.fieldCounter += 1; + this.fieldList.push(String(this.fieldCounter)); //adding addition marker to fieldList + this.fieldDepth.push(this.fieldDepthCounter); + } + + prependKeyObject(depth: number, index: number) { //creating the dot notation for objects + let prependText = ''; + if (depth !== 0) { + prependText = '"'; + for (let i = this.mqlText1.length - 1; i >= 0; i--) { //searches elements in array with lower depth to append for dot-notation + if (this.fieldDepth[i] < depth) { + prependText += this.mqlText1[i] + '.'; + break; + } + } + } + this.mqlText1[index] = prependText + this.mqlTextX[index]; + if (depth !==0) { + this.mqlText1[index] += '"'; + } + console.log(this.fieldDepth[index]); } deleteMQLField(field:string) { const x = Number(field); this.mqlDropdown[x] = ''; this.mqlText1[x] = ''; - this.mqlTest2[x] = ''; + this.mqlText2[x] = ''; this.fieldList[x] = ''; this.generateMQL(); } @@ -528,9 +570,9 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest let mql = ''; //BUG: Special case if they are the same key, they have to get in the same bracket // Filter empty fields - const mqlDropdownf = this.mqlDropdown.filter((el) => el !== ''); - const mqlText1f = this.mqlText1.filter((_, idx) => mqlDropdownf[idx]); - const mqlText2f = this.mqlTest2.filter((_, idx) => mqlDropdownf[idx]); + const mqlDropdownf = this.mqlDropdown; //.filter((el) => el !== ''); + const mqlText1f = this.mqlText1; //.filter((_, idx) => mqlDropdownf[idx]); + const mqlText2f = this.mqlText2; //.filter((_, idx) => mqlDropdownf[idx]); switch (this.mqlMatch) { case 'mql-and': mql += 'db.getCollection("' + this.collectionName + '").find({'; @@ -555,7 +597,7 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest mql += mqlText1f[i] + ': {"$not" : /.*' + mqlText2f[i] + '.*/i}'; break; } - if (i+1 <= mqlDropdownf.length - 1 && mqlDropdownf[i+1] !== '') { + if (i+1 <= mqlDropdownf.length - 1 && mqlDropdownf[i] !== undefined) { mql += ', '; } } @@ -590,7 +632,7 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest mql += mqlText1f[i] + ': {"$not" : /.*' + mqlText2f[i] + '.*/i}'; break; } - if (i+1 <= mqlDropdownf.length - 1 && mqlDropdownf[i+1] !== '') { + if (i+1 <= mqlDropdownf.length - 1 && mqlDropdownf[i] !== undefined) { mql += ', '; } } From f1a958278a4c06b1eb48a0a204f1105b5703f329 Mon Sep 17 00:00:00 2001 From: svamel00 Date: Sat, 25 Feb 2023 15:19:29 +0100 Subject: [PATCH 13/60] fixed smaller bugs for new prototype mql --- .../graphical-querying.component.ts | 22 +++++++++++-------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/src/app/views/querying/graphical-querying/graphical-querying.component.ts b/src/app/views/querying/graphical-querying/graphical-querying.component.ts index 0753f442..dd7b3f45 100644 --- a/src/app/views/querying/graphical-querying/graphical-querying.component.ts +++ b/src/app/views/querying/graphical-querying/graphical-querying.component.ts @@ -91,7 +91,7 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest // mql input fields mqlMatch = ''; mqlDropdown: string[] = []; - mqlTextX: string[] =[]; + mqlTextX: string[] = []; mqlText1: string[] = []; mqlText2: string[] = []; activeNamespace: string; // same usage as console.components.ts @@ -434,7 +434,7 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest this.mqlText2 = []; this.fieldCounter = 0; this.fieldList = ['0']; - this.fieldDepth = []; + this.fieldDepth = [0]; this.fieldDepthCounter = 0; document.getElementById('mql-type').onclick = () => { this.mqlMatch = null; @@ -456,7 +456,7 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest this.mqlMatch = null; }; this.fieldList = ['0']; - this.fieldDepth = []; + this.fieldDepth = [0]; this.fieldDepthCounter = 0; break; case 'mql': @@ -538,10 +538,11 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest deleteMQLField(field:string) { const x = Number(field); - this.mqlDropdown[x] = ''; + this.mqlDropdown[x] = undefined; this.mqlText1[x] = ''; this.mqlText2[x] = ''; this.fieldList[x] = ''; + this.mqlTextX[x] = ''; this.generateMQL(); } @@ -570,9 +571,9 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest let mql = ''; //BUG: Special case if they are the same key, they have to get in the same bracket // Filter empty fields - const mqlDropdownf = this.mqlDropdown; //.filter((el) => el !== ''); - const mqlText1f = this.mqlText1; //.filter((_, idx) => mqlDropdownf[idx]); - const mqlText2f = this.mqlText2; //.filter((_, idx) => mqlDropdownf[idx]); + const mqlDropdownf = this.mqlDropdown.filter((el) => el !== '' && el !== undefined); + const mqlText2f = this.mqlText2.filter((_, idx) => this.mqlDropdown[idx]); + const mqlText1f = this.mqlText1.filter((_, idx) => this.mqlDropdown[idx]); switch (this.mqlMatch) { case 'mql-and': mql += 'db.getCollection("' + this.collectionName + '").find({'; @@ -597,7 +598,7 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest mql += mqlText1f[i] + ': {"$not" : /.*' + mqlText2f[i] + '.*/i}'; break; } - if (i+1 <= mqlDropdownf.length - 1 && mqlDropdownf[i] !== undefined) { + if (i+1 <= mqlDropdownf.length - 1) { mql += ', '; } } @@ -632,7 +633,7 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest mql += mqlText1f[i] + ': {"$not" : /.*' + mqlText2f[i] + '.*/i}'; break; } - if (i+1 <= mqlDropdownf.length - 1 && mqlDropdownf[i] !== undefined) { + if (i+1 <= mqlDropdownf.length - 1) { mql += ', '; } } @@ -640,6 +641,9 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest break; } this.editorGenerated.setCode(mql); + console.log(mqlDropdownf); + console.log(mqlText1f); + console.log(mqlText2f); } async generateSQL() { From 189f1f441960c1db4697c9f66eb6baaf5e17f52f Mon Sep 17 00:00:00 2001 From: svamel00 Date: Sat, 25 Feb 2023 16:48:23 +0100 Subject: [PATCH 14/60] now deleting through splice instead of leaving the indices values empty in mql --- .../graphical-querying.component.html | 68 +++++++++---------- .../graphical-querying.component.ts | 18 +++-- 2 files changed, 45 insertions(+), 41 deletions(-) diff --git a/src/app/views/querying/graphical-querying/graphical-querying.component.html b/src/app/views/querying/graphical-querying/graphical-querying.component.html index bb97475d..40dc17a0 100644 --- a/src/app/views/querying/graphical-querying/graphical-querying.component.html +++ b/src/app/views/querying/graphical-querying/graphical-querying.component.html @@ -279,49 +279,47 @@
Query Result
-
-
-
-
-
- -
- +
+
+
+
+
+
-
-
-
-
- -
- +
+
+
+
+
+
+
-
-
-
-
- -
- +
+
+
+
+
+
+
-
- - -
+
+
+ +
diff --git a/src/app/views/querying/graphical-querying/graphical-querying.component.ts b/src/app/views/querying/graphical-querying/graphical-querying.component.ts index dd7b3f45..3fe91e2d 100644 --- a/src/app/views/querying/graphical-querying/graphical-querying.component.ts +++ b/src/app/views/querying/graphical-querying/graphical-querying.component.ts @@ -510,6 +510,7 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest this.fieldList.push(String(this.fieldCounter)); //adding addition marker to fieldList this.fieldDepthCounter += 1; this.fieldDepth.push(this.fieldDepthCounter); + //this.mqlDropdown[] = undefined;// deleting equal from field before } addMQLFieldKeyObject2() { // staying on the same 'level' of property @@ -538,11 +539,16 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest deleteMQLField(field:string) { const x = Number(field); - this.mqlDropdown[x] = undefined; - this.mqlText1[x] = ''; - this.mqlText2[x] = ''; - this.fieldList[x] = ''; - this.mqlTextX[x] = ''; + this.mqlDropdown.splice(x, 1); + this.mqlText1.splice(x, 1); + this.mqlText2.splice(x, 1); + this.fieldList.pop(); + this.mqlTextX.splice(x, 1); + if (x === this.mqlText1.length - 1 && x !== 0) { //if last row of rows, we have to adapt fieldDepthCounter + this.fieldDepthCounter = this.fieldDepth[x - 1]; + } + this.fieldDepth.splice(x, 1); + this.fieldCounter -= 1; this.generateMQL(); } @@ -571,7 +577,7 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest let mql = ''; //BUG: Special case if they are the same key, they have to get in the same bracket // Filter empty fields - const mqlDropdownf = this.mqlDropdown.filter((el) => el !== '' && el !== undefined); + const mqlDropdownf = this.mqlDropdown.filter((el) => el !== ''); const mqlText2f = this.mqlText2.filter((_, idx) => this.mqlDropdown[idx]); const mqlText1f = this.mqlText1.filter((_, idx) => this.mqlDropdown[idx]); switch (this.mqlMatch) { From 97be967a0344e24060a852d95863da2836f60b6c Mon Sep 17 00:00:00 2001 From: svamel00 Date: Sat, 25 Feb 2023 17:34:56 +0100 Subject: [PATCH 15/60] fixxing small bug for properties --- .../graphical-querying.component.ts | 31 ++++++++----------- 1 file changed, 13 insertions(+), 18 deletions(-) diff --git a/src/app/views/querying/graphical-querying/graphical-querying.component.ts b/src/app/views/querying/graphical-querying/graphical-querying.component.ts index 3fe91e2d..34eac861 100644 --- a/src/app/views/querying/graphical-querying/graphical-querying.component.ts +++ b/src/app/views/querying/graphical-querying/graphical-querying.component.ts @@ -521,8 +521,7 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest prependKeyObject(depth: number, index: number) { //creating the dot notation for objects let prependText = ''; - if (depth !== 0) { - prependText = '"'; + if (depth !== 0) { //does not have to iterarate through this if depth 0 for (let i = this.mqlText1.length - 1; i >= 0; i--) { //searches elements in array with lower depth to append for dot-notation if (this.fieldDepth[i] < depth) { prependText += this.mqlText1[i] + '.'; @@ -531,10 +530,6 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest } } this.mqlText1[index] = prependText + this.mqlTextX[index]; - if (depth !==0) { - this.mqlText1[index] += '"'; - } - console.log(this.fieldDepth[index]); } deleteMQLField(field:string) { @@ -586,22 +581,22 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest for (let i = 0; i < mqlDropdownf.length; i++) { switch (mqlDropdownf[i]) { case 'equal': - mql += mqlText1f[i] + ' : ' + mqlText2f[i]; + mql += '"' + mqlText1f[i] + '" : ' + mqlText2f[i]; break; case 'notequal': - mql += mqlText1f[i] + ': {"$ne" : ' + mqlText2f[i] + '}'; + mql += '"' + mqlText1f[i] + '" : {"$ne" : ' + mqlText2f[i] + '}'; break; case 'greater': - mql += mqlText1f[i] + ': {"$gt" : ' + mqlText2f[i] + '}'; + mql += '"' + mqlText1f[i] + '" : {"$gt" : ' + mqlText2f[i] + '}'; break; case 'lesser': - mql += mqlText1f[i] + ': {"$lt" : ' + mqlText2f[i] + '}'; + mql += '"' + mqlText1f[i] + '" : {"$lt" : ' + mqlText2f[i] + '}'; break; case 'contains': - mql += mqlText1f[i] + ' : {$regex: \'/.*' + mqlText2f[i] + '.*/i\'}'; + mql += '"' + mqlText1f[i] + '" : {$regex: \'/.*' + mqlText2f[i] + '.*/i\'}'; break; case 'notcontains': - mql += mqlText1f[i] + ': {"$not" : /.*' + mqlText2f[i] + '.*/i}'; + mql += '"' + mqlText1f[i] + '" : {"$not" : /.*' + mqlText2f[i] + '.*/i}'; break; } if (i+1 <= mqlDropdownf.length - 1) { @@ -621,22 +616,22 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest for (let i = 0; i < mqlDropdownf.length; i++) { switch (mqlDropdownf[i]) { case 'equal': - mql += '{' + mqlText1f[i] + ' : ' + mqlText2f[i] + '}'; + mql += '{"' + mqlText1f[i] + '" : ' + mqlText2f[i] + '}'; break; case 'notequal': - mql += '{' + mqlText1f[i] + ': {"$ne" : ' + mqlText2f[i] + '}}'; + mql += '{"' + mqlText1f[i] + '" : {"$ne" : ' + mqlText2f[i] + '}}'; break; case 'greater': - mql += '{' + mqlText1f[i] + ': {"$gt" : ' + mqlText2f[i] + '}}'; + mql += '{"' + mqlText1f[i] + '" : {"$gt" : ' + mqlText2f[i] + '}}'; break; case 'lesser': - mql += '{' + mqlText1f[i] + ': {"$lt" : ' + mqlText2f[i] + '}}'; + mql += '{"' + mqlText1f[i] + '" : {"$lt" : ' + mqlText2f[i] + '}}'; break; case 'contains': - mql += mqlText1f[i] + ' : /.*' + mqlText2f[i] + '.*/i'; + mql += '"' + mqlText1f[i] + '" : /.*' + mqlText2f[i] + '.*/i'; break; case 'notcontains': - mql += mqlText1f[i] + ': {"$not" : /.*' + mqlText2f[i] + '.*/i}'; + mql += '"' + mqlText1f[i] + '" : {"$not" : /.*' + mqlText2f[i] + '.*/i}'; break; } if (i+1 <= mqlDropdownf.length - 1) { From 293de5ced4fe67eff2bd2af5cfaa4b0443be102e Mon Sep 17 00:00:00 2001 From: svamel00 Date: Sun, 5 Mar 2023 16:04:59 +0100 Subject: [PATCH 16/60] added and & or operators. TO DO: Fix new delete button bugs --- .../graphical-querying.component.html | 183 ++++++++++-------- .../graphical-querying.component.ts | 183 ++++++++++-------- 2 files changed, 204 insertions(+), 162 deletions(-) diff --git a/src/app/views/querying/graphical-querying/graphical-querying.component.html b/src/app/views/querying/graphical-querying/graphical-querying.component.html index 40dc17a0..76b92aee 100644 --- a/src/app/views/querying/graphical-querying/graphical-querying.component.html +++ b/src/app/views/querying/graphical-querying/graphical-querying.component.html @@ -122,7 +122,7 @@
Query Result
- +
- - - - -
-
-

3. Fill in the details.

+

Fill in the details:

-
+
+
+
+ AND +
+
+
+
+ OR +
+
+
+
+ END +
+
+
- +
- +
- +
- +
@@ -310,95 +315,109 @@
Query Result
- +
- +
- +
+
-
-
- - +
+ +
+
  • + +
  • +
    +
    +
    + +
    - +
    -
    Generated query
    -

    Edit your code if needed.

    -
    - -
    +
    Generated query
    +

    Edit your code if needed.

    +
    + +
    - - + + -
    -
    -
    Query Result
    -
    +
    +
    +
    Query Result
    +
    -
    +
    -
    - {{resultSet.generatedQuery}} - - {{resultSet.affectedRows}} - ! - -
    +
    + {{resultSet.generatedQuery}} + + {{resultSet.affectedRows}} + ! + +
    -
    -
    - Error: -

    {{resultSet.error}}

    -
    +
    +
    + Error: +

    {{resultSet.error}}

    +
    -
    -

    - Successfully executed -

    -
    +
    +

    + Successfully executed +

    +
    -
    -
    - -
    +
    +
    +
    -
    +
    diff --git a/src/app/views/querying/graphical-querying/graphical-querying.component.ts b/src/app/views/querying/graphical-querying/graphical-querying.component.ts index 34eac861..2f5708d2 100644 --- a/src/app/views/querying/graphical-querying/graphical-querying.component.ts +++ b/src/app/views/querying/graphical-querying/graphical-querying.component.ts @@ -88,8 +88,9 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest fieldList: string[] = ['0']; // each newly created input field in mql gets another value fieldDepth: number[] = [0]; fieldDepthCounter = 0; + logicalDepth: number[] = [0]; + logicalDepthCounter = 0; // mql input fields - mqlMatch = ''; mqlDropdown: string[] = []; mqlTextX: string[] = []; mqlText1: string[] = []; @@ -97,14 +98,17 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest activeNamespace: string; // same usage as console.components.ts collectionName: string; graphName: string; + + logicalOperatorStack: string[] = []; fieldCounter = 0; private readonly LOCAL_STORAGE_NAMESPACE_KEY = 'polypheny-namespace'; // same usage as console.components.ts // Dropdown show = false; + + show2 = false; private debounce: any; private debounceDelay = 200; - showError: boolean; ngOnInit() { this._leftSidebar.open(); @@ -427,37 +431,33 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest case 'sql': this.collectionName = undefined; this.graphName = undefined; - this.mqlMatch = ''; this.mqlDropdown = []; this.mqlTextX = []; this.mqlText1 = []; this.mqlText2 = []; this.fieldCounter = 0; + this.logicalDepth = [0]; this.fieldList = ['0']; this.fieldDepth = [0]; this.fieldDepthCounter = 0; - document.getElementById('mql-type').onclick = () => { - this.mqlMatch = null; - }; this.cypherMatch = ''; // three input fields for match this.cypherWhere = ''; this.cypherReturn = ''; this.cypherRelationship = ['','','','']; + this.logicalDepthCounter = 0; break; case 'cypher': this.collectionName = undefined; - this.mqlMatch = ''; this.mqlDropdown = []; this.mqlTextX = []; this.mqlText1 = []; this.mqlText2 = []; this.fieldCounter = 0; - document.getElementById('mql-type').onclick = () => { - this.mqlMatch = null; - }; this.fieldList = ['0']; this.fieldDepth = [0]; this.fieldDepthCounter = 0; + this.logicalDepth = [0]; + this.logicalDepthCounter = 0; break; case 'mql': this.graphName = undefined; @@ -498,11 +498,33 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest } } + setMenuShow2(doShow2: boolean, instant = false) { + if (instant) { + this.show2 = doShow2; + return; + } + if (!doShow2) { + this.debounce = setTimeout(() => { + this.show2 = false; + }, this.debounceDelay); + } else { + this.show2 = true; + } + } + + //taken from json-editor.component.ts + menuEnter2() { + if (this.show2) { + clearTimeout(this.debounce); + } + } + addMQLField() { // 'normal new Field' this.fieldCounter += 1; this.fieldList.push(String(this.fieldCounter)); this.fieldDepthCounter = 0; this.fieldDepth.push(this.fieldDepthCounter); + this.logicalDepth.push(this.logicalDepthCounter); } addMQLFieldKeyObject() { // adding a property @@ -510,6 +532,7 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest this.fieldList.push(String(this.fieldCounter)); //adding addition marker to fieldList this.fieldDepthCounter += 1; this.fieldDepth.push(this.fieldDepthCounter); + this.logicalDepth.push(this.logicalDepthCounter); //this.mqlDropdown[] = undefined;// deleting equal from field before } @@ -517,6 +540,25 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest this.fieldCounter += 1; this.fieldList.push(String(this.fieldCounter)); //adding addition marker to fieldList this.fieldDepth.push(this.fieldDepthCounter); + this.logicalDepth.push(this.logicalDepthCounter); + } + + addLogicalOperator(logical: string) { // adding Logical Operator AND or OR + this.fieldCounter += 1; + this.fieldList.push(logical); //adding addition marker to fieldList + this.fieldDepth.push(this.fieldDepthCounter); + this.logicalDepthCounter += 1; + this.logicalDepth.push(this.logicalDepthCounter); + this.logicalOperatorStack.push(logical); + } + + endLogicalOperator() { // ending Logical Operator AND or OR + this.fieldCounter += 1; + this.fieldList.push('END'); //adding addition marker to fieldList + this.fieldDepth.push(this.fieldDepthCounter); + this.logicalDepthCounter -= 1; + this.logicalDepth.push(this.logicalDepthCounter); + this.logicalOperatorStack.pop(); } prependKeyObject(depth: number, index: number) { //creating the dot notation for objects @@ -532,12 +574,11 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest this.mqlText1[index] = prependText + this.mqlTextX[index]; } - deleteMQLField(field:string) { - const x = Number(field); + deleteMQLField(x:number) { this.mqlDropdown.splice(x, 1); this.mqlText1.splice(x, 1); this.mqlText2.splice(x, 1); - this.fieldList.pop(); + this.fieldList.splice(x, 1); this.mqlTextX.splice(x, 1); if (x === this.mqlText1.length - 1 && x !== 0) { //if last row of rows, we have to adapt fieldDepthCounter this.fieldDepthCounter = this.fieldDepth[x - 1]; @@ -572,79 +613,61 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest let mql = ''; //BUG: Special case if they are the same key, they have to get in the same bracket // Filter empty fields - const mqlDropdownf = this.mqlDropdown.filter((el) => el !== ''); - const mqlText2f = this.mqlText2.filter((_, idx) => this.mqlDropdown[idx]); - const mqlText1f = this.mqlText1.filter((_, idx) => this.mqlDropdown[idx]); - switch (this.mqlMatch) { - case 'mql-and': - mql += 'db.getCollection("' + this.collectionName + '").find({'; - for (let i = 0; i < mqlDropdownf.length; i++) { - switch (mqlDropdownf[i]) { - case 'equal': - mql += '"' + mqlText1f[i] + '" : ' + mqlText2f[i]; - break; - case 'notequal': - mql += '"' + mqlText1f[i] + '" : {"$ne" : ' + mqlText2f[i] + '}'; - break; - case 'greater': - mql += '"' + mqlText1f[i] + '" : {"$gt" : ' + mqlText2f[i] + '}'; - break; - case 'lesser': - mql += '"' + mqlText1f[i] + '" : {"$lt" : ' + mqlText2f[i] + '}'; - break; - case 'contains': - mql += '"' + mqlText1f[i] + '" : {$regex: \'/.*' + mqlText2f[i] + '.*/i\'}'; - break; - case 'notcontains': - mql += '"' + mqlText1f[i] + '" : {"$not" : /.*' + mqlText2f[i] + '.*/i}'; - break; - } - if (i+1 <= mqlDropdownf.length - 1) { - mql += ', '; - } + //const mqlDropdownf = this.mqlDropdown.filter((el) => el !== ''); + //const mqlText2f = this.mqlText2.filter((_, idx) => this.mqlDropdown[idx]); + //const mqlText1f = this.mqlText1.filter((_, idx) => this.mqlDropdown[idx]); + const isInsideLogicalCondition = []; + mql += 'db.getCollection("' + this.collectionName + '").find({'; + for (let i = 0; i < this.fieldList.length; i++) { + if (this.fieldList[i] === 'AND') { + mql += '$and: ['; + isInsideLogicalCondition.push('AND'); + } + if (this.fieldList[i] === 'OR') { + mql += '$or: ['; + isInsideLogicalCondition.push('OR'); + } + if (this.fieldList[i] !== 'AND' && this.fieldList[i] !== 'OR' && this.fieldList[i] !== 'END') { + if (isInsideLogicalCondition.length !== 0){ + mql += '{'; } - mql += '})'; - break; - case 'mql-or': - case 'mql-nor': - if (this.mqlMatch === 'mql-or') { - mql += 'db.getCollection("' + this.collectionName + '").find({"$or" : ['; + switch (this.mqlDropdown[i]) { + case 'equal': + mql += '"' + this.mqlText1[i] + '" : ' + this.mqlText2[i]; + break; + case 'notequal': + mql += '"' + this.mqlText1[i] + '" : {"$ne" : ' + this.mqlText2[i] + '}'; + break; + case 'greater': + mql += '"' + this.mqlText1[i] + '" : {"$gt" : ' + this.mqlText2[i] + '}'; + break; + case 'lesser': + mql += '"' + this.mqlText1[i] + '" : {"$lt" : ' + this.mqlText2[i] + '}'; + break; + case 'contains': + mql += '"' + this.mqlText1[i] + '" : {$regex: \'/.*' + this.mqlText2[i] + '.*/i\'}'; + break; + case 'notcontains': + mql += '"' + this.mqlText1[i] + '" : {"$not" : /.*' + this.mqlText2[i] + '.*/i}'; + break; + case 'type': + mql += '"' + this.mqlText1[i] + '" : {"$type:" : ' + this.mqlText2[i] + '}'; + break; } - else if (this.mqlMatch === 'mql-nor') { - mql += 'db.getCollection("' + this.collectionName + '").find({"$nor" : ['; + if (isInsideLogicalCondition.length !== 0){ + mql += '}'; } - for (let i = 0; i < mqlDropdownf.length; i++) { - switch (mqlDropdownf[i]) { - case 'equal': - mql += '{"' + mqlText1f[i] + '" : ' + mqlText2f[i] + '}'; - break; - case 'notequal': - mql += '{"' + mqlText1f[i] + '" : {"$ne" : ' + mqlText2f[i] + '}}'; - break; - case 'greater': - mql += '{"' + mqlText1f[i] + '" : {"$gt" : ' + mqlText2f[i] + '}}'; - break; - case 'lesser': - mql += '{"' + mqlText1f[i] + '" : {"$lt" : ' + mqlText2f[i] + '}}'; - break; - case 'contains': - mql += '"' + mqlText1f[i] + '" : /.*' + mqlText2f[i] + '.*/i'; - break; - case 'notcontains': - mql += '"' + mqlText1f[i] + '" : {"$not" : /.*' + mqlText2f[i] + '.*/i}'; - break; - } - if (i+1 <= mqlDropdownf.length - 1) { - mql += ', '; - } + if (i + 1 <= this.mqlDropdown.length - 1) { + mql += ', '; } - mql += ']})'; - break; + } + if (this.fieldList[i] === 'END') { + mql += ']'; + isInsideLogicalCondition.pop(); + } } + mql += '})'; this.editorGenerated.setCode(mql); - console.log(mqlDropdownf); - console.log(mqlText1f); - console.log(mqlText2f); } async generateSQL() { From 49a075e746ae3aafb55807ff754e28c66c3a3a4b Mon Sep 17 00:00:00 2001 From: svamel00 Date: Sun, 5 Mar 2023 17:14:45 +0100 Subject: [PATCH 17/60] fixxed delete button for Logical Operators --- .../graphical-querying.component.html | 20 ++++++++--- .../graphical-querying.component.ts | 36 +++++++++++++------ 2 files changed, 41 insertions(+), 15 deletions(-) diff --git a/src/app/views/querying/graphical-querying/graphical-querying.component.html b/src/app/views/querying/graphical-querying/graphical-querying.component.html index 76b92aee..ac415331 100644 --- a/src/app/views/querying/graphical-querying/graphical-querying.component.html +++ b/src/app/views/querying/graphical-querying/graphical-querying.component.html @@ -269,17 +269,29 @@
    Query Result
    - AND +
    + AND +
    +
    + +
    - OR +
    + OR +
    +
    + +
    -
    - END +
    +
    + END +
    diff --git a/src/app/views/querying/graphical-querying/graphical-querying.component.ts b/src/app/views/querying/graphical-querying/graphical-querying.component.ts index 2f5708d2..d0f599ec 100644 --- a/src/app/views/querying/graphical-querying/graphical-querying.component.ts +++ b/src/app/views/querying/graphical-querying/graphical-querying.component.ts @@ -88,7 +88,7 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest fieldList: string[] = ['0']; // each newly created input field in mql gets another value fieldDepth: number[] = [0]; fieldDepthCounter = 0; - logicalDepth: number[] = [0]; + logicalDepth: number[] = [-1]; logicalDepthCounter = 0; // mql input fields mqlDropdown: string[] = []; @@ -524,7 +524,7 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest this.fieldList.push(String(this.fieldCounter)); this.fieldDepthCounter = 0; this.fieldDepth.push(this.fieldDepthCounter); - this.logicalDepth.push(this.logicalDepthCounter); + this.logicalDepth.push(-1); } addMQLFieldKeyObject() { // adding a property @@ -532,7 +532,7 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest this.fieldList.push(String(this.fieldCounter)); //adding addition marker to fieldList this.fieldDepthCounter += 1; this.fieldDepth.push(this.fieldDepthCounter); - this.logicalDepth.push(this.logicalDepthCounter); + this.logicalDepth.push(-1); //this.mqlDropdown[] = undefined;// deleting equal from field before } @@ -540,15 +540,15 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest this.fieldCounter += 1; this.fieldList.push(String(this.fieldCounter)); //adding addition marker to fieldList this.fieldDepth.push(this.fieldDepthCounter); - this.logicalDepth.push(this.logicalDepthCounter); + this.logicalDepth.push(-1); } addLogicalOperator(logical: string) { // adding Logical Operator AND or OR this.fieldCounter += 1; this.fieldList.push(logical); //adding addition marker to fieldList this.fieldDepth.push(this.fieldDepthCounter); - this.logicalDepthCounter += 1; this.logicalDepth.push(this.logicalDepthCounter); + this.logicalDepthCounter += 1; this.logicalOperatorStack.push(logical); } @@ -578,13 +578,32 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest this.mqlDropdown.splice(x, 1); this.mqlText1.splice(x, 1); this.mqlText2.splice(x, 1); - this.fieldList.splice(x, 1); this.mqlTextX.splice(x, 1); if (x === this.mqlText1.length - 1 && x !== 0) { //if last row of rows, we have to adapt fieldDepthCounter this.fieldDepthCounter = this.fieldDepth[x - 1]; } this.fieldDepth.splice(x, 1); this.fieldCounter -= 1; + if (this.fieldList[x] === 'AND' || this.fieldList[x] === 'OR' || this.fieldList[x] === 'END') { //Deleting logical Operator and its END + const indicesToRemove: number[] = []; + for (let i = x; i < this.fieldList.length; i++) { + if (this.logicalDepth[i] === this.logicalDepth[x]) { //should only delete the next element of logical Operator + indicesToRemove.push(i); + if (indicesToRemove.length === 2) { + break; + } + } + } + this.fieldList = this.fieldList.filter((_, index) => !indicesToRemove.includes(index)); + this.logicalDepth = this.logicalDepth.filter((_, index) => !indicesToRemove.includes(index)); + if (indicesToRemove.length === 1) { // there is no END, so the logical depth counter has to be substracted + this.logicalDepthCounter -= 1; + } + } + else { + this.fieldList.splice(x, 1); + this.logicalDepth.splice(x, 1); + } this.generateMQL(); } @@ -611,11 +630,6 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest async generateMQL() { let mql = ''; - //BUG: Special case if they are the same key, they have to get in the same bracket - // Filter empty fields - //const mqlDropdownf = this.mqlDropdown.filter((el) => el !== ''); - //const mqlText2f = this.mqlText2.filter((_, idx) => this.mqlDropdown[idx]); - //const mqlText1f = this.mqlText1.filter((_, idx) => this.mqlDropdown[idx]); const isInsideLogicalCondition = []; mql += 'db.getCollection("' + this.collectionName + '").find({'; for (let i = 0; i < this.fieldList.length; i++) { From bc0d65c979d2afdc68360d5e11cbd621ee2dc163 Mon Sep 17 00:00:00 2001 From: svamel00 Date: Sun, 5 Mar 2023 17:18:40 +0100 Subject: [PATCH 18/60] fixed small mistake for type in mql --- .../querying/graphical-querying/graphical-querying.component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/views/querying/graphical-querying/graphical-querying.component.ts b/src/app/views/querying/graphical-querying/graphical-querying.component.ts index d0f599ec..f63bda64 100644 --- a/src/app/views/querying/graphical-querying/graphical-querying.component.ts +++ b/src/app/views/querying/graphical-querying/graphical-querying.component.ts @@ -665,7 +665,7 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest mql += '"' + this.mqlText1[i] + '" : {"$not" : /.*' + this.mqlText2[i] + '.*/i}'; break; case 'type': - mql += '"' + this.mqlText1[i] + '" : {"$type:" : ' + this.mqlText2[i] + '}'; + mql += '"' + this.mqlText1[i] + '" : {"$type" : ' + this.mqlText2[i] + '}'; break; } if (isInsideLogicalCondition.length !== 0){ From 53ba280b7c182aa8782de435998931a1b3df5f8a Mon Sep 17 00:00:00 2001 From: svamel00 Date: Mon, 6 Mar 2023 20:12:45 +0100 Subject: [PATCH 19/60] corrected the delete button function specifically for the logical operators --- .../graphical-querying.component.ts | 54 +++++++++++++++---- 1 file changed, 43 insertions(+), 11 deletions(-) diff --git a/src/app/views/querying/graphical-querying/graphical-querying.component.ts b/src/app/views/querying/graphical-querying/graphical-querying.component.ts index f63bda64..e92dea76 100644 --- a/src/app/views/querying/graphical-querying/graphical-querying.component.ts +++ b/src/app/views/querying/graphical-querying/graphical-querying.component.ts @@ -525,6 +525,11 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest this.fieldDepthCounter = 0; this.fieldDepth.push(this.fieldDepthCounter); this.logicalDepth.push(-1); + console.log('The DepthCounter is: ' + this.fieldDepthCounter); + console.log('The DepthCounterList is: ' + this.fieldDepth); + console.log('The Fieldlist is: ' + this.fieldList); + console.log('The logicalDepthCounter is: ' + this.logicalDepthCounter); + console.log('The logicaldepthlist: ' + this.logicalDepth); } addMQLFieldKeyObject() { // adding a property @@ -533,6 +538,11 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest this.fieldDepthCounter += 1; this.fieldDepth.push(this.fieldDepthCounter); this.logicalDepth.push(-1); + console.log('The DepthCounter is: ' + this.fieldDepthCounter); + console.log('The DepthCounterList is: ' + this.fieldDepth); + console.log('The Fieldlist is: ' + this.fieldList); + console.log('The logicalDepthCounter is: ' + this.logicalDepthCounter); + console.log('The logicaldepthlist: ' + this.logicalDepth); //this.mqlDropdown[] = undefined;// deleting equal from field before } @@ -541,20 +551,30 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest this.fieldList.push(String(this.fieldCounter)); //adding addition marker to fieldList this.fieldDepth.push(this.fieldDepthCounter); this.logicalDepth.push(-1); + console.log('The DepthCounter is: ' + this.fieldDepthCounter); + console.log('The DepthCounterList is: ' + this.fieldDepth); + console.log('The Fieldlist is: ' + this.fieldList); + console.log('The logicalDepthCounter is: ' + this.logicalDepthCounter); + console.log('The logicaldepthlist: ' + this.logicalDepth); } addLogicalOperator(logical: string) { // adding Logical Operator AND or OR this.fieldCounter += 1; - this.fieldList.push(logical); //adding addition marker to fieldList + this.fieldList.push(logical); this.fieldDepth.push(this.fieldDepthCounter); this.logicalDepth.push(this.logicalDepthCounter); this.logicalDepthCounter += 1; this.logicalOperatorStack.push(logical); + console.log('The DepthCounter is: ' + this.fieldDepthCounter); + console.log('The DepthCounterList is: ' + this.fieldDepth); + console.log('The Fieldlist is: ' + this.fieldList); + console.log('The logicalDepthCounter is: ' + this.logicalDepthCounter); + console.log('The logicaldepthlist: ' + this.logicalDepth); } endLogicalOperator() { // ending Logical Operator AND or OR this.fieldCounter += 1; - this.fieldList.push('END'); //adding addition marker to fieldList + this.fieldList.push('END'); this.fieldDepth.push(this.fieldDepthCounter); this.logicalDepthCounter -= 1; this.logicalDepth.push(this.logicalDepthCounter); @@ -575,21 +595,21 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest } deleteMQLField(x:number) { - this.mqlDropdown.splice(x, 1); - this.mqlText1.splice(x, 1); - this.mqlText2.splice(x, 1); - this.mqlTextX.splice(x, 1); - if (x === this.mqlText1.length - 1 && x !== 0) { //if last row of rows, we have to adapt fieldDepthCounter - this.fieldDepthCounter = this.fieldDepth[x - 1]; - } - this.fieldDepth.splice(x, 1); - this.fieldCounter -= 1; if (this.fieldList[x] === 'AND' || this.fieldList[x] === 'OR' || this.fieldList[x] === 'END') { //Deleting logical Operator and its END const indicesToRemove: number[] = []; for (let i = x; i < this.fieldList.length; i++) { if (this.logicalDepth[i] === this.logicalDepth[x]) { //should only delete the next element of logical Operator indicesToRemove.push(i); if (indicesToRemove.length === 2) { + if (indicesToRemove[1] === this.fieldList.length && x !== 0) { //if last row of rows, we have to adapt fieldDepthCounter + this.fieldDepthCounter = this.fieldDepth[x - 1]; + } + this.mqlDropdown.splice(indicesToRemove[1], 1); + this.mqlText1.splice(indicesToRemove[1], 1); + this.mqlText2.splice(indicesToRemove[1], 1); + this.mqlTextX.splice(indicesToRemove[1], 1); + this.fieldDepth.splice(indicesToRemove[1], 1); + this.fieldCounter -= 1; break; } } @@ -598,12 +618,24 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest this.logicalDepth = this.logicalDepth.filter((_, index) => !indicesToRemove.includes(index)); if (indicesToRemove.length === 1) { // there is no END, so the logical depth counter has to be substracted this.logicalDepthCounter -= 1; + if (x === this.fieldList.length && x !== 0) { //if last row of rows, we have to adapt fieldDepthCounter + this.fieldDepthCounter = this.fieldDepth[x - 1]; + } } } else { this.fieldList.splice(x, 1); this.logicalDepth.splice(x, 1); + if (x === this.fieldList.length && x !== 0) { //if last row of rows, we have to adapt fieldDepthCounter + this.fieldDepthCounter = this.fieldDepth[x - 1]; + } } + this.mqlDropdown.splice(x, 1); + this.mqlText1.splice(x, 1); + this.mqlText2.splice(x, 1); + this.mqlTextX.splice(x, 1); + this.fieldDepth.splice(x, 1); + this.fieldCounter -= 1; this.generateMQL(); } From e0a31c712406ef267b2712501890cce33e2dc741 Mon Sep 17 00:00:00 2001 From: svamel00 Date: Mon, 6 Mar 2023 21:08:20 +0100 Subject: [PATCH 20/60] corrected comma bug in MQL --- .../graphical-querying.component.ts | 39 +++++++++---------- 1 file changed, 18 insertions(+), 21 deletions(-) diff --git a/src/app/views/querying/graphical-querying/graphical-querying.component.ts b/src/app/views/querying/graphical-querying/graphical-querying.component.ts index e92dea76..9ba4ceb7 100644 --- a/src/app/views/querying/graphical-querying/graphical-querying.component.ts +++ b/src/app/views/querying/graphical-querying/graphical-querying.component.ts @@ -525,11 +525,6 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest this.fieldDepthCounter = 0; this.fieldDepth.push(this.fieldDepthCounter); this.logicalDepth.push(-1); - console.log('The DepthCounter is: ' + this.fieldDepthCounter); - console.log('The DepthCounterList is: ' + this.fieldDepth); - console.log('The Fieldlist is: ' + this.fieldList); - console.log('The logicalDepthCounter is: ' + this.logicalDepthCounter); - console.log('The logicaldepthlist: ' + this.logicalDepth); } addMQLFieldKeyObject() { // adding a property @@ -538,11 +533,6 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest this.fieldDepthCounter += 1; this.fieldDepth.push(this.fieldDepthCounter); this.logicalDepth.push(-1); - console.log('The DepthCounter is: ' + this.fieldDepthCounter); - console.log('The DepthCounterList is: ' + this.fieldDepth); - console.log('The Fieldlist is: ' + this.fieldList); - console.log('The logicalDepthCounter is: ' + this.logicalDepthCounter); - console.log('The logicaldepthlist: ' + this.logicalDepth); //this.mqlDropdown[] = undefined;// deleting equal from field before } @@ -551,11 +541,6 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest this.fieldList.push(String(this.fieldCounter)); //adding addition marker to fieldList this.fieldDepth.push(this.fieldDepthCounter); this.logicalDepth.push(-1); - console.log('The DepthCounter is: ' + this.fieldDepthCounter); - console.log('The DepthCounterList is: ' + this.fieldDepth); - console.log('The Fieldlist is: ' + this.fieldList); - console.log('The logicalDepthCounter is: ' + this.logicalDepthCounter); - console.log('The logicaldepthlist: ' + this.logicalDepth); } addLogicalOperator(logical: string) { // adding Logical Operator AND or OR @@ -565,11 +550,6 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest this.logicalDepth.push(this.logicalDepthCounter); this.logicalDepthCounter += 1; this.logicalOperatorStack.push(logical); - console.log('The DepthCounter is: ' + this.fieldDepthCounter); - console.log('The DepthCounterList is: ' + this.fieldDepth); - console.log('The Fieldlist is: ' + this.fieldList); - console.log('The logicalDepthCounter is: ' + this.logicalDepthCounter); - console.log('The logicaldepthlist: ' + this.logicalDepth); } endLogicalOperator() { // ending Logical Operator AND or OR @@ -703,7 +683,14 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest if (isInsideLogicalCondition.length !== 0){ mql += '}'; } - if (i + 1 <= this.mqlDropdown.length - 1) { + const fieldListf = this.fieldList.filter((el) => el !== 'AND' && el !== 'OR' && el !== 'END'); + let matchingIndex = -1; + for (let j = 0; j < fieldListf.length; j++) { + if (fieldListf[j] === this.fieldList[i]) { + matchingIndex = j; + } + } + if (matchingIndex + 1 <= fieldListf.length - 1 && matchingIndex !== -1) { mql += ', '; } } @@ -716,6 +703,16 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest this.editorGenerated.setCode(mql); } + findMatchingIndex(array1: any[], array2: any[]): number { + for (let i = 0; i < array1.length; i++) { + const matchingIndex = array2.indexOf(array1[i]); + if (matchingIndex !== -1) { + return matchingIndex; + } + } + return -1; + } + async generateSQL() { this.whereCounter = 0; this.andCounter = 0; From a155b91d2123841c03f60488258fb09c5036b9cf Mon Sep 17 00:00:00 2001 From: svamel00 Date: Mon, 6 Mar 2023 23:57:03 +0100 Subject: [PATCH 21/60] added dynamic new fields for cypher --- .../graphical-querying.component.html | 201 +++++++++++------- .../graphical-querying.component.ts | 22 +- 2 files changed, 140 insertions(+), 83 deletions(-) diff --git a/src/app/views/querying/graphical-querying/graphical-querying.component.html b/src/app/views/querying/graphical-querying/graphical-querying.component.html index ac415331..834a7f15 100644 --- a/src/app/views/querying/graphical-querying/graphical-querying.component.html +++ b/src/app/views/querying/graphical-querying/graphical-querying.component.html @@ -102,112 +102,169 @@
    Query Result
    -

    1. Select your graph from the left sidebar: {{ graphName !== undefined ? ' ' + graphName : '' }}

    +

    Select your graph from the left sidebar: {{ graphName !== undefined ? ' ' + graphName : '' }}

    -

    2. Fill in the details.

    -
    -
    - -
    - -
    - +

    Fill in the details.

    -
    +
    - +
    - +
    - -
    -
    -
    -
    - +
    + +
    +
    +
    +
    +
    +
    + +
    +
    -
    -
    -
    -
    -
    - -
    - +
    + +
    -
    -
    -
    -
    - + +
    + +
    +
    +
    +
    + +
    + +
    +
    + +
    +
    +
    +
    + +
    + +
    +
    +
    +
    +
    + +
    + +
    +
    +
    +
    +
    +
    +
    + +
    + +
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    - +
    +
    +
    +
    +
    +
    +
    + +
    + +
    +
    +
    +
    +
    +
    +
    + +
    + +
    -
    -
    -
    -
    -
    - + +
    +
    +
    +
    +
    + +
    +
    - +
    +
    + +
    - -
    -
    - + +
    +
    + +
    -
    + -
    -
    - +
    +
    +
    +
    + +
    + +
    -
    Generated query
    diff --git a/src/app/views/querying/graphical-querying/graphical-querying.component.ts b/src/app/views/querying/graphical-querying/graphical-querying.component.ts index 9ba4ceb7..38d52887 100644 --- a/src/app/views/querying/graphical-querying/graphical-querying.component.ts +++ b/src/app/views/querying/graphical-querying/graphical-querying.component.ts @@ -83,8 +83,8 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest cypherWhere = ''; cypherReturn = ''; cypherDropdown: string; - cypherRelationship: string[] = ['','','','']; // [0] = Relationship, [1] = Node, [2] = 2.Relationship, [3] = 2.Node + fieldListCypher: string[] = []; fieldList: string[] = ['0']; // each newly created input field in mql gets another value fieldDepth: number[] = [0]; fieldDepthCounter = 0; @@ -437,6 +437,7 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest this.mqlText2 = []; this.fieldCounter = 0; this.logicalDepth = [0]; + this.logicalOperatorStack = []; this.fieldList = ['0']; this.fieldDepth = [0]; this.fieldDepthCounter = 0; @@ -458,6 +459,7 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest this.fieldDepthCounter = 0; this.logicalDepth = [0]; this.logicalDepthCounter = 0; + this.logicalOperatorStack = []; break; case 'mql': this.graphName = undefined; @@ -519,6 +521,10 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest } } + addCypherField(type: string) { + this.fieldListCypher.push(type); + } + addMQLField() { // 'normal new Field' this.fieldCounter += 1; this.fieldList.push(String(this.fieldCounter)); @@ -574,6 +580,10 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest this.mqlText1[index] = prependText + this.mqlTextX[index]; } + deleteCypherField(x:number) { + this.fieldListCypher.splice(x, 1); + } + deleteMQLField(x:number) { if (this.fieldList[x] === 'AND' || this.fieldList[x] === 'OR' || this.fieldList[x] === 'END') { //Deleting logical Operator and its END const indicesToRemove: number[] = []; @@ -703,16 +713,6 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest this.editorGenerated.setCode(mql); } - findMatchingIndex(array1: any[], array2: any[]): number { - for (let i = 0; i < array1.length; i++) { - const matchingIndex = array2.indexOf(array1[i]); - if (matchingIndex !== -1) { - return matchingIndex; - } - } - return -1; - } - async generateSQL() { this.whereCounter = 0; this.andCounter = 0; From 2b93c21d20fcb02a49fdd30112b7e31781856c08 Mon Sep 17 00:00:00 2001 From: svamel00 Date: Tue, 7 Mar 2023 00:57:57 +0100 Subject: [PATCH 22/60] added hardcoded node & relationship labels to cypher --- .../graphical-querying.component.html | 24 +++++++++++++++---- .../graphical-querying.component.scss | 22 +++++++++++++++++ .../graphical-querying.component.ts | 10 ++++++++ 3 files changed, 51 insertions(+), 5 deletions(-) diff --git a/src/app/views/querying/graphical-querying/graphical-querying.component.html b/src/app/views/querying/graphical-querying/graphical-querying.component.html index 834a7f15..40c64253 100644 --- a/src/app/views/querying/graphical-querying/graphical-querying.component.html +++ b/src/app/views/querying/graphical-querying/graphical-querying.component.html @@ -104,12 +104,26 @@
    Query Result

    Select your graph from the left sidebar: {{ graphName !== undefined ? ' ' + graphName : '' }}

    - - - -

    Fill in the details.

    + + +

    Node Labels:

    +
    +

    {{label}}

    +
    + + +

    Relationship Labels:

    +
    +

    {{label}}

    +
    + + + + + +
    diff --git a/src/app/views/querying/graphical-querying/graphical-querying.component.scss b/src/app/views/querying/graphical-querying/graphical-querying.component.scss index ef9f586b..ac6c79c5 100644 --- a/src/app/views/querying/graphical-querying/graphical-querying.component.scss +++ b/src/app/views/querying/graphical-querying/graphical-querying.component.scss @@ -70,3 +70,25 @@ display: block !important; } +//Label Container +.label-container { + display: flex; +} + +.label-container p { + margin-right: 2.5em; +} + +.label-node { + padding-left: 0.5em; + padding-right: 0.5em; + border: 1px solid black; +} + +.label-relation { + padding-left: 0.5em; + padding-right: 0.5em; + border-radius: 1.5em; + border: 1px solid black; +} + diff --git a/src/app/views/querying/graphical-querying/graphical-querying.component.ts b/src/app/views/querying/graphical-querying/graphical-querying.component.ts index 38d52887..1afcfe01 100644 --- a/src/app/views/querying/graphical-querying/graphical-querying.component.ts +++ b/src/app/views/querying/graphical-querying/graphical-querying.component.ts @@ -75,6 +75,9 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest } // new additions by me: + + nodeLabels: string[] = ['Movie', 'Person']; //Hardcoded for the moment + relationLabels: string[] = ['DIRECTED', 'ACTED_IN', 'FATHER_OF']; //Hardcoded for the moment lang: string; // usage as lang in console.component.hmtl 'sql', 'cypher', 'mql' tableId: string; config: TableConfig; @@ -521,6 +524,13 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest } } + //infinite color generation for labels + generateColor(index: number): string { + const hue = (index * 70) % 360; + const color = `hsl(${hue}, 50%, 60%)`; + return color; + } + addCypherField(type: string) { this.fieldListCypher.push(type); } From 02fc7af85b6e9bd9a02e821a8944f61af29798a8 Mon Sep 17 00:00:00 2001 From: svamel00 Date: Tue, 7 Mar 2023 01:35:46 +0100 Subject: [PATCH 23/60] added simple drag function to the cypher labels --- .../graphical-querying/graphical-querying.component.html | 6 +++--- .../graphical-querying/graphical-querying.component.ts | 7 +++++++ 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/app/views/querying/graphical-querying/graphical-querying.component.html b/src/app/views/querying/graphical-querying/graphical-querying.component.html index 40c64253..040c2256 100644 --- a/src/app/views/querying/graphical-querying/graphical-querying.component.html +++ b/src/app/views/querying/graphical-querying/graphical-querying.component.html @@ -104,18 +104,18 @@
    Query Result

    Select your graph from the left sidebar: {{ graphName !== undefined ? ' ' + graphName : '' }}

    -

    Fill in the details.

    +

    Fill in the details. You can drag and drop the labels into the input fields.

    Node Labels:

    -

    {{label}}

    +

    {{label}}

    Relationship Labels:

    -

    {{label}}

    +

    {{label}}

    diff --git a/src/app/views/querying/graphical-querying/graphical-querying.component.ts b/src/app/views/querying/graphical-querying/graphical-querying.component.ts index 1afcfe01..7b252e83 100644 --- a/src/app/views/querying/graphical-querying/graphical-querying.component.ts +++ b/src/app/views/querying/graphical-querying/graphical-querying.component.ts @@ -524,6 +524,11 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest } } + //drag and drop for cypher labels + drag(event: any) { + event.dataTransfer.setData('text/plain', event.target.innerText); + } + //infinite color generation for labels generateColor(index: number): string { const hue = (index * 70) % 360; @@ -615,6 +620,7 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest } } this.fieldList = this.fieldList.filter((_, index) => !indicesToRemove.includes(index)); + this.logicalOperatorStack = this.fieldList.filter((el) => el === 'AND' || el === 'OR' || el === 'END'); this.logicalDepth = this.logicalDepth.filter((_, index) => !indicesToRemove.includes(index)); if (indicesToRemove.length === 1) { // there is no END, so the logical depth counter has to be substracted this.logicalDepthCounter -= 1; @@ -637,6 +643,7 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest this.fieldDepth.splice(x, 1); this.fieldCounter -= 1; this.generateMQL(); + console.log(this.logicalOperatorStack); } async generateCypher() { From 0c1571908e96336b71d609da3e9b6bf3c13ff213 Mon Sep 17 00:00:00 2001 From: svamel00 Date: Tue, 7 Mar 2023 01:45:53 +0100 Subject: [PATCH 24/60] corrected bug with not undefined dropdown when adding fieldkeyobject --- .../graphical-querying/graphical-querying.component.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/app/views/querying/graphical-querying/graphical-querying.component.ts b/src/app/views/querying/graphical-querying/graphical-querying.component.ts index 7b252e83..f0c209fa 100644 --- a/src/app/views/querying/graphical-querying/graphical-querying.component.ts +++ b/src/app/views/querying/graphical-querying/graphical-querying.component.ts @@ -549,12 +549,12 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest } addMQLFieldKeyObject() { // adding a property + this.mqlDropdown[this.fieldCounter] = undefined;// deleting equal from field before this.fieldCounter += 1; this.fieldList.push(String(this.fieldCounter)); //adding addition marker to fieldList this.fieldDepthCounter += 1; this.fieldDepth.push(this.fieldDepthCounter); this.logicalDepth.push(-1); - //this.mqlDropdown[] = undefined;// deleting equal from field before } addMQLFieldKeyObject2() { // staying on the same 'level' of property @@ -717,9 +717,10 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest matchingIndex = j; } } - if (matchingIndex + 1 <= fieldListf.length - 1 && matchingIndex !== -1) { + if (matchingIndex + 1 <= fieldListf.length - 1 && matchingIndex !== -1 && this.mqlDropdown[i] !== undefined) { mql += ', '; } + console.log(this.mqlDropdown); } if (this.fieldList[i] === 'END') { mql += ']'; From 9dbd64481f41f2d899e4916876bbe93745f4da09 Mon Sep 17 00:00:00 2001 From: svamel00 Date: Wed, 8 Mar 2023 18:10:57 +0100 Subject: [PATCH 25/60] added draggable mql rows --- .../graphical-querying.component.html | 34 +++++++---------- .../graphical-querying.component.ts | 37 ++++++++++++++++++- 2 files changed, 49 insertions(+), 22 deletions(-) diff --git a/src/app/views/querying/graphical-querying/graphical-querying.component.html b/src/app/views/querying/graphical-querying/graphical-querying.component.html index 040c2256..301d6fa5 100644 --- a/src/app/views/querying/graphical-querying/graphical-querying.component.html +++ b/src/app/views/querying/graphical-querying/graphical-querying.component.html @@ -337,9 +337,9 @@
    Query Result

    Fill in the details:

    -
    -
    -
    +
    + +
    AND
    @@ -347,9 +347,9 @@
    Query Result
    -
    -
    -
    + + +
    OR
    @@ -357,20 +357,20 @@
    Query Result
    -
    -
    -
    + + +
    END
    -
    -
    -
    + + +
    - +
    @@ -379,9 +379,6 @@
    Query Result
    -
    - -
    @@ -410,7 +404,7 @@
    Query Result
    -
    +
    diff --git a/src/app/views/querying/graphical-querying/graphical-querying.component.ts b/src/app/views/querying/graphical-querying/graphical-querying.component.ts index f0c209fa..f6092e99 100644 --- a/src/app/views/querying/graphical-querying/graphical-querying.component.ts +++ b/src/app/views/querying/graphical-querying/graphical-querying.component.ts @@ -113,6 +113,8 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest private debounce: any; private debounceDelay = 200; + initialrect: DOMRect; + ngOnInit() { this._leftSidebar.open(); this.initSchema(this.lang); @@ -529,6 +531,39 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest event.dataTransfer.setData('text/plain', event.target.innerText); } + //drag and drop for mql rows + onDragStart(event: DragEvent, str: string) { + event.dataTransfer?.setData('text/plain', str); + const targetElement = event.currentTarget as HTMLElement; + this.initialrect = targetElement.getBoundingClientRect(); + } + + onDragOver(event: DragEvent) { + event.preventDefault(); + } + + onDrop(event: DragEvent) { + event.preventDefault(); + const data = event.dataTransfer?.getData('text/plain'); + if (data) { + const index = this.fieldList.indexOf(data); + const targetElement = event.currentTarget as HTMLElement; + setTimeout(() => { + const rect = targetElement.getBoundingClientRect(); + const mouseY = rect.top - this.initialrect.top; + const targetIndex = Math.round(mouseY / rect.height) + index; + if (index !== -1 && targetIndex !== -1 && index !== targetIndex) { + this.fieldList.splice(targetIndex, 0, this.fieldList.splice(index, 1)[0]); + this.mqlDropdown.splice(targetIndex, 0, this.mqlDropdown.splice(index, 1)[0]); + this.mqlText1.splice(targetIndex, 0, this.mqlText1.splice(index, 1)[0]); + this.mqlText2.splice(targetIndex, 0, this.mqlText2.splice(index, 1)[0]); + this.mqlTextX.splice(targetIndex, 0, this.mqlTextX.splice(index, 1)[0]); + this.fieldDepth.splice(targetIndex, 0, this.fieldDepth.splice(index, 1)[0]); + } + }, 0); + } + } + //infinite color generation for labels generateColor(index: number): string { const hue = (index * 70) % 360; @@ -643,7 +678,6 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest this.fieldDepth.splice(x, 1); this.fieldCounter -= 1; this.generateMQL(); - console.log(this.logicalOperatorStack); } async generateCypher() { @@ -720,7 +754,6 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest if (matchingIndex + 1 <= fieldListf.length - 1 && matchingIndex !== -1 && this.mqlDropdown[i] !== undefined) { mql += ', '; } - console.log(this.mqlDropdown); } if (this.fieldList[i] === 'END') { mql += ']'; From b1abc378d64b3f8e96ce783a06679cbc7a23d23c Mon Sep 17 00:00:00 2001 From: svamel00 Date: Wed, 8 Mar 2023 20:52:30 +0100 Subject: [PATCH 26/60] changed sidebar to support crossmodel --- .../graphical-querying.component.ts | 146 +++++++++--------- 1 file changed, 70 insertions(+), 76 deletions(-) diff --git a/src/app/views/querying/graphical-querying/graphical-querying.component.ts b/src/app/views/querying/graphical-querying/graphical-querying.component.ts index f6092e99..ddceb369 100644 --- a/src/app/views/querying/graphical-querying/graphical-querying.component.ts +++ b/src/app/views/querying/graphical-querying/graphical-querying.component.ts @@ -113,7 +113,7 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest private debounce: any; private debounceDelay = 200; - initialrect: DOMRect; + private initialrect: DOMRect; ngOnInit() { this._leftSidebar.open(); @@ -154,83 +154,76 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest } initSchema(lang:string) { - console.log(lang); - if (lang === 'sql') { - this._crud.getSchema(new SchemaRequest('views/graphical-querying/', true, 3, false, false, [DataModels.RELATIONAL])).subscribe( - res => { - const nodeAction = (tree, node, $event) => { - if (!node.isActive && node.isLeaf) { - this.addCol(node.data); - node.setIsActive(true, true); - } else if (node.isActive && node.isLeaf) { - node.setIsActive(false, true); - this.removeCol(node.data.id); - - //deletes the selection if nothing is choosen - if (this.selectedColumn['column'].toString() === node.data.id) { - this.selectedCol([]); + console.log(lang); + if (lang === 'sql') { + this._crud.getSchema(new SchemaRequest('views/graphical-querying/', true, 3, false, false )).subscribe( + res => { + const nodeAction = (tree, node, $event) => { + if (!node.isActive && node.isLeaf) { + this.addCol(node.data); + node.setIsActive(true, true); + } else if (node.isActive && node.isLeaf) { + node.setIsActive(false, true); + this.removeCol(node.data.id); + //deletes the selection if nothing is choosen + if (this.selectedColumn['column'].toString() === node.data.id) { + this.selectedCol([]); + } + } + }; + const schemaTemp = res; + const schema = []; + for (const s of schemaTemp) { + const node = SidebarNode.fromJson(s, {allowRouting: false, autoActive: false, action: nodeAction}); + schema.push(node); + } + this._leftSidebar.setNodes(schema); + this._leftSidebar.open(); } - } - }; - - const schemaTemp = res; - const schema = []; - for (const s of schemaTemp) { - const node = SidebarNode.fromJson(s, {allowRouting: false, autoActive: false, action: nodeAction}); - schema.push(node); - } - - this._leftSidebar.setNodes(schema); - this._leftSidebar.open(); - } - ); - } - else if (lang === 'cypher') { - this._crud.getSchema(new SchemaRequest('views/graphical-querying/', true, 1, false, false, [DataModels.GRAPH])).subscribe( - res => { - const nodeAction = (tree, node, $event) => { - console.log(node.id); - this.graphName = node.id; - this.setDefaultDB(node.id); //changes the activeNamespace to the one chosen on the left side - }; - - const schemaTemp = res; - const schema = []; - for (const s of schemaTemp) { - const node = SidebarNode.fromJson(s, {allowRouting: false, autoActive: false, action: nodeAction}); - schema.push(node); - } - - this._leftSidebar.setNodes(schema); - this._leftSidebar.open(); - } - ); - } - else if (lang === 'mql') { - this._crud.getSchema(new SchemaRequest('views/graphical-querying/', true, 2, false, false, [DataModels.DOCUMENT])).subscribe( - res => { - const nodeAction = (tree, node, $event) => { // TO DO: it only shows columns _id_ and _data_ but not correct ones. - if (!node.isActive && node.isLeaf) { - console.log(node.parent.id); - this.setDefaultDB(node.parent.id); - console.log(node.displayField); - this.collectionName = node.displayField; - } - }; - - const schemaTemp = res; - const schema = []; - for (const s of schemaTemp) { - const node = SidebarNode.fromJson(s, {allowRouting: false, autoActive: false, action: nodeAction}); - schema.push(node); - } - - this._leftSidebar.setNodes(schema); - this._leftSidebar.open(); - } - ); + ); + } + else if (lang === 'cypher') { + this._crud.getSchema(new SchemaRequest('views/graphical-querying/', true, 1, false, false)).subscribe( + res => { + const nodeAction = (tree, node, $event) => { + console.log(node.id); + this.graphName = node.id; + this.setDefaultDB(node.id); //changes the activeNamespace to the one chosen on the left side + }; + const schemaTemp = res; + const schema = []; + for (const s of schemaTemp) { + const node = SidebarNode.fromJson(s, {allowRouting: false, autoActive: false, action: nodeAction}); + schema.push(node); + } + this._leftSidebar.setNodes(schema); + this._leftSidebar.open(); + } + ); + } + else if (lang === 'mql') { + this._crud.getSchema(new SchemaRequest('views/graphical-querying/', true, 2, false, false)).subscribe( + res => { + const nodeAction = (tree, node, $event) => { // TO DO: it only shows columns _id_ and _data_ but not correct ones. + if (!node.isActive && node.isLeaf) { + console.log(node.parent.id); + this.setDefaultDB(node.parent.id); + console.log(node.displayField); + this.collectionName = node.displayField; + } + }; + const schemaTemp = res; + const schema = []; + for (const s of schemaTemp) { + const node = SidebarNode.fromJson(s, {allowRouting: false, autoActive: false, action: nodeAction}); + schema.push(node); + } + this._leftSidebar.setNodes(schema); + this._leftSidebar.open(); + } + ); + } } - } initGraphicalQuerying() { const self = this; @@ -562,6 +555,7 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest } }, 0); } + this.generateMQL(); } //infinite color generation for labels From fb73879739684214c54016c717e71f9ab9628cbf Mon Sep 17 00:00:00 2001 From: svamel00 Date: Sat, 11 Mar 2023 15:35:07 +0100 Subject: [PATCH 27/60] added code generation for new dynamic cypher fields --- .../graphical-querying.component.html | 64 ++++++++----------- .../graphical-querying.component.ts | 57 +++++++++-------- 2 files changed, 57 insertions(+), 64 deletions(-) diff --git a/src/app/views/querying/graphical-querying/graphical-querying.component.html b/src/app/views/querying/graphical-querying/graphical-querying.component.html index 301d6fa5..8e3981d1 100644 --- a/src/app/views/querying/graphical-querying/graphical-querying.component.html +++ b/src/app/views/querying/graphical-querying/graphical-querying.component.html @@ -124,18 +124,6 @@
    Query Result
    [config]="config"> --> -
    -
    -
    -
    - -
    - -
    -
    -
    -
    @@ -145,7 +133,7 @@
    Query Result
    + [(ngModel)]="cypherFields[i][0]" (keyup)="generateCypher()" placeholder="Node">
    @@ -155,7 +143,7 @@
    Query Result
    -
    +
    @@ -163,7 +151,7 @@
    Query Result
    - @@ -174,59 +162,59 @@
    Query Result
    -
    +
    - +
    - +
    -
    +
    - +
    - +
    -
    +
    - +
    - +
    -
    +
    -
    +
    - +
    - +
    -
    +
    - +
    - +
    @@ -241,7 +229,7 @@
    Query Result
    + [(ngModel)]="cypherFields[i][0]" (keyup)="generateCypher()">
    @@ -253,7 +241,7 @@
    Query Result
    -
    +
    diff --git a/src/app/views/querying/graphical-querying/graphical-querying.component.ts b/src/app/views/querying/graphical-querying/graphical-querying.component.ts index ddceb369..4b72fa55 100644 --- a/src/app/views/querying/graphical-querying/graphical-querying.component.ts +++ b/src/app/views/querying/graphical-querying/graphical-querying.component.ts @@ -82,12 +82,12 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest tableId: string; config: TableConfig; // cypher input fields - cypherMatch = ''; - cypherWhere = ''; + //cypherMatch: string[] = []; + cypherFields: string[][] = [[]]; // Matrix à [n,5] size -> [1] = Relationship, [2] = Node, [3] = 2.Relationship, [4] = 2.Node cypherReturn = ''; - cypherDropdown: string; - cypherRelationship: string[] = ['','','','']; // [0] = Relationship, [1] = Node, [2] = 2.Relationship, [3] = 2.Node - fieldListCypher: string[] = []; + cypherDropdown: string[] = []; + //cypherRelationship: string[] = ['','','','']; // [0] = Relationship, [1] = Node, [2] = 2.Relationship, [3] = 2.Node + fieldListCypher: string[] = ['MATCH']; fieldList: string[] = ['0']; // each newly created input field in mql gets another value fieldDepth: number[] = [0]; fieldDepthCounter = 0; @@ -439,10 +439,8 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest this.fieldList = ['0']; this.fieldDepth = [0]; this.fieldDepthCounter = 0; - this.cypherMatch = ''; // three input fields for match - this.cypherWhere = ''; + this.cypherFields = [[]]; this.cypherReturn = ''; - this.cypherRelationship = ['','','','']; this.logicalDepthCounter = 0; break; case 'cypher': @@ -461,10 +459,8 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest break; case 'mql': this.graphName = undefined; - this.cypherMatch = ''; // three input fields for match - this.cypherWhere = ''; + this.cypherFields = [[]]; this.cypherReturn = ''; - this.cypherRelationship = ['','','','']; break; } } @@ -567,6 +563,7 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest addCypherField(type: string) { this.fieldListCypher.push(type); + this.cypherFields.push([]); } addMQLField() { // 'normal new Field' @@ -626,6 +623,8 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest deleteCypherField(x:number) { this.fieldListCypher.splice(x, 1); + this.cypherFields.splice(x, 1); + this.generateCypher(); } deleteMQLField(x:number) { @@ -676,22 +675,27 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest async generateCypher() { let cypher = ''; - cypher += 'MATCH ' + '(' + this.cypherMatch + ')'; - switch (this.cypherDropdown) { - case 'cypher-outgoing': - cypher += '-->(' + this.cypherRelationship[1] + ')'; - break; - case 'cypher-directed': - cypher += '-[' + this.cypherRelationship[0] + ']->(' + this.cypherRelationship[1] + ')'; - break; - case 'cypher-multiple': - cypher += '-[' + this.cypherRelationship[0] + ']->(' + this.cypherRelationship[1] + ')<-[' + this.cypherRelationship[2] + ']-(' + this.cypherRelationship[3] + ')'; - break; - } - if (this.cypherWhere !== '') { - cypher += '\nWHERE ' + this.cypherWhere; + for (let i = 0; i < this.fieldListCypher.length; i++) { // MATCH, RELATIONSHIP & WHERE + if (this.fieldListCypher[i] === 'MATCH') { + cypher += 'MATCH ' + '(' + this.cypherFields[i][0] + ')'; + switch (this.cypherDropdown[i]) { + case 'cypher-outgoing': + cypher += '-->(' + this.cypherFields[i][2] + ')'; + break; + case 'cypher-directed': + cypher += '-[' + this.cypherFields[i][1] + ']->(' + this.cypherFields[i][2] + ')'; + break; + case 'cypher-multiple': + cypher += '-[' + this.cypherFields[i][1] + ']->(' + this.cypherFields[i][2] + ')<-[' + this.cypherFields[i][3] + ']-(' + this.cypherFields[i][4] + ')'; + break; + } + } + if (this.fieldListCypher[i] === 'WHERE') { + cypher += 'WHERE ' + this.cypherFields[i][0]; + } + cypher += '\n'; } - cypher += '\nRETURN ' + this.cypherReturn + ';'; + cypher += 'RETURN ' + this.cypherReturn + ';'; this.editorGenerated.setCode(cypher); } @@ -756,6 +760,7 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest } mql += '})'; this.editorGenerated.setCode(mql); + console.log(this.fieldList); } async generateSQL() { From 1d6e43bfe4971ae92de42fc45e8e0fd0b8fa3a56 Mon Sep 17 00:00:00 2001 From: svamel00 Date: Sat, 11 Mar 2023 20:45:08 +0100 Subject: [PATCH 28/60] added operators to cypher where clause --- .../graphical-querying.component.html | 140 ++++++++++++++---- .../graphical-querying.component.ts | 24 ++- 2 files changed, 134 insertions(+), 30 deletions(-) diff --git a/src/app/views/querying/graphical-querying/graphical-querying.component.html b/src/app/views/querying/graphical-querying/graphical-querying.component.html index 8e3981d1..ee57bee9 100644 --- a/src/app/views/querying/graphical-querying/graphical-querying.component.html +++ b/src/app/views/querying/graphical-querying/graphical-querying.component.html @@ -8,16 +8,16 @@
    Graphical Querying

    Select your query language:

    - - - -
    + + + +
    @@ -164,18 +164,12 @@
    Query Result
    -
    - -
    -
    - -
    @@ -184,9 +178,6 @@
    Query Result
    -
    - -
    @@ -199,9 +190,6 @@
    Query Result
    -
    - -
    @@ -210,9 +198,6 @@
    Query Result
    -
    - -
    @@ -223,20 +208,121 @@
    Query Result
    -
    +
    - +
    +
    +
    +
    + +
    +
    +
    +
    + +
    +
    +
    + + +
    +
    +
    +
    + + + +
    +
    +
    + +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    + +
    +
    +
    +
    + + + +
    +
    diff --git a/src/app/views/querying/graphical-querying/graphical-querying.component.ts b/src/app/views/querying/graphical-querying/graphical-querying.component.ts index 4b72fa55..1c7c3dea 100644 --- a/src/app/views/querying/graphical-querying/graphical-querying.component.ts +++ b/src/app/views/querying/graphical-querying/graphical-querying.component.ts @@ -429,6 +429,7 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest case 'sql': this.collectionName = undefined; this.graphName = undefined; + //mql this.mqlDropdown = []; this.mqlTextX = []; this.mqlText1 = []; @@ -439,9 +440,11 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest this.fieldList = ['0']; this.fieldDepth = [0]; this.fieldDepthCounter = 0; + this.logicalDepthCounter = 0; + //cypher this.cypherFields = [[]]; this.cypherReturn = ''; - this.logicalDepthCounter = 0; + this.fieldListCypher = ['MATCH']; break; case 'cypher': this.collectionName = undefined; @@ -461,6 +464,7 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest this.graphName = undefined; this.cypherFields = [[]]; this.cypherReturn = ''; + this.fieldListCypher = ['MATCH']; break; } } @@ -566,6 +570,17 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest this.cypherFields.push([]); } + changeCypherField(type: string, index : number) { + if (index + 1 > this.fieldListCypher.length-1) { + this.fieldListCypher.push(type); + this.cypherFields.push([]); + } + else { + this.fieldListCypher[index + 1] = type; + } + } + + addMQLField() { // 'normal new Field' this.fieldCounter += 1; this.fieldList.push(String(this.fieldCounter)); @@ -675,7 +690,7 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest async generateCypher() { let cypher = ''; - for (let i = 0; i < this.fieldListCypher.length; i++) { // MATCH, RELATIONSHIP & WHERE + for (let i = 0; i < this.fieldListCypher.length; i++) { if (this.fieldListCypher[i] === 'MATCH') { cypher += 'MATCH ' + '(' + this.cypherFields[i][0] + ')'; switch (this.cypherDropdown[i]) { @@ -691,7 +706,10 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest } } if (this.fieldListCypher[i] === 'WHERE') { - cypher += 'WHERE ' + this.cypherFields[i][0]; + cypher += 'WHERE ' + this.cypherFields[i][0] + ' ' + this.cypherFields[i][1] + ' ' + this.cypherFields[i][2]; + } + if (this.fieldListCypher[i] === 'OR' || this.fieldListCypher[i] === 'AND' || this.fieldListCypher[i] === 'NOR') { + cypher += this.fieldListCypher[i] + ' ' + this.cypherFields[i][0] + ' ' + this.cypherFields[i][1] + ' ' + this.cypherFields[i][2]; } cypher += '\n'; } From 96bc887014619b3ee3f26f2bc4851241b5df85b9 Mon Sep 17 00:00:00 2001 From: svamel00 Date: Sat, 11 Mar 2023 20:45:28 +0100 Subject: [PATCH 29/60] added operators to cypher where clause --- .../querying/graphical-querying/graphical-querying.component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/views/querying/graphical-querying/graphical-querying.component.ts b/src/app/views/querying/graphical-querying/graphical-querying.component.ts index 1c7c3dea..9baaa47c 100644 --- a/src/app/views/querying/graphical-querying/graphical-querying.component.ts +++ b/src/app/views/querying/graphical-querying/graphical-querying.component.ts @@ -570,7 +570,7 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest this.cypherFields.push([]); } - changeCypherField(type: string, index : number) { + changeCypherField(type: string, index: number) { if (index + 1 > this.fieldListCypher.length-1) { this.fieldListCypher.push(type); this.cypherFields.push([]); From 1a2213b947fd7cd85b0bbdd651550406fa173cf0 Mon Sep 17 00:00:00 2001 From: svamel00 Date: Mon, 13 Mar 2023 10:36:05 +0100 Subject: [PATCH 30/60] corrected colors for labels in cypher similiar to data-graph.component.ts --- .../graphical-querying.component.ts | 26 ++++++------------- 1 file changed, 8 insertions(+), 18 deletions(-) diff --git a/src/app/views/querying/graphical-querying/graphical-querying.component.ts b/src/app/views/querying/graphical-querying/graphical-querying.component.ts index 9baaa47c..27e2f9c1 100644 --- a/src/app/views/querying/graphical-querying/graphical-querying.component.ts +++ b/src/app/views/querying/graphical-querying/graphical-querying.component.ts @@ -1,13 +1,4 @@ -import { - AfterViewInit, - Component, - Input, - OnDestroy, - OnInit, - TemplateRef, - ViewChild, - ViewEncapsulation -} from '@angular/core'; +import {AfterViewInit, Component, OnDestroy, OnInit, TemplateRef, ViewChild, ViewEncapsulation} from '@angular/core'; import * as $ from 'jquery'; import 'jquery-ui/ui/widget'; import 'jquery-ui/ui/widgets/sortable'; @@ -16,19 +7,18 @@ import {CrudService} from '../../../services/crud.service'; import {FilteredUserInput, ResultSet} from '../../../components/data-view/models/result-set.model'; import {LeftSidebarService} from '../../../components/left-sidebar/left-sidebar.service'; import {ToastService} from '../../../components/toast/toast.service'; -import {DataModels, EditTableRequest, QueryRequest, SchemaRequest} from '../../../models/ui-request.model'; +import {EditTableRequest, QueryRequest, SchemaRequest} from '../../../models/ui-request.model'; import {SidebarNode} from '../../../models/sidebar-node.model'; import {ForeignKey, Uml} from '../../uml/uml.model'; -import {ActivatedRoute, Router} from '@angular/router'; +import {Router} from '@angular/router'; import {Subscription} from 'rxjs'; import {WebuiSettingsService} from '../../../services/webui-settings.service'; import {WebSocket} from '../../../services/webSocket'; import {BsModalRef, BsModalService} from 'ngx-bootstrap/modal'; import {ViewInformation} from '../../../components/data-view/data-view.component'; // new import added to extent graph -import {DataGraphComponent} from '../../../components/data-view/data-graph/data-graph.component'; -import {DbmsTypesService} from '../../../services/dbms-types.service'; import {TableConfig} from '../../../components/data-view/data-table/table-config'; +import * as d3 from 'd3'; @Component({ selector: 'app-graphical-querying', @@ -558,11 +548,11 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest this.generateMQL(); } - //infinite color generation for labels + //similiar to data-graph.component.ts generateColor(index: number): string { - const hue = (index * 70) % 360; - const color = `hsl(${hue}, 50%, 60%)`; - return color; + const color = d3.interpolateSinebow; + const ratio = 1 / (this.nodeLabels.length + this.relationLabels.length); + return color(ratio * index); } addCypherField(type: string) { From 1500ee7ceaf67eb74bd6c942a1b584542d4fe2a4 Mon Sep 17 00:00:00 2001 From: svamel00 Date: Mon, 13 Mar 2023 16:16:25 +0100 Subject: [PATCH 31/60] simplified and cleaned code for mql --- .../graphical-querying.component.html | 52 +++---- .../graphical-querying.component.ts | 140 ++++++++---------- 2 files changed, 83 insertions(+), 109 deletions(-) diff --git a/src/app/views/querying/graphical-querying/graphical-querying.component.html b/src/app/views/querying/graphical-querying/graphical-querying.component.html index ee57bee9..894ca869 100644 --- a/src/app/views/querying/graphical-querying/graphical-querying.component.html +++ b/src/app/views/querying/graphical-querying/graphical-querying.component.html @@ -380,6 +380,8 @@
    Query Result
    + +
    Error: @@ -393,9 +395,12 @@
    Query Result
    -
    +
    +
    +

    Sidebar

    +
    @@ -412,20 +417,10 @@
    Query Result
    - -
    -
    - AND -
    -
    - -
    -
    -
    - -
    + +
    - OR + {{fieldNumber}}
    @@ -433,27 +428,27 @@
    Query Result
    -
    +
    END
    -
    +
    + [(ngModel)]="mqlFields[i][3]" (keyup)="prependKeyObject(this.mqlFields[i][5], i); generateMQL()" placeholder="key">
    -
    +
    - @@ -466,10 +461,10 @@
    Query Result
    -
    +
    + [(ngModel)]="mqlFields[i][2]" (keyup)="generateMQL()" placeholder="value">
    @@ -489,14 +484,16 @@
    Query Result
  • -
    +
  • -
  • - -
  • +
    +
  • + +
  • +
  • - -
    - -
    -
    Generated query

    Edit your code if needed.

    diff --git a/src/app/views/querying/graphical-querying/graphical-querying.component.ts b/src/app/views/querying/graphical-querying/graphical-querying.component.ts index 27e2f9c1..354446b2 100644 --- a/src/app/views/querying/graphical-querying/graphical-querying.component.ts +++ b/src/app/views/querying/graphical-querying/graphical-querying.component.ts @@ -78,16 +78,12 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest cypherDropdown: string[] = []; //cypherRelationship: string[] = ['','','','']; // [0] = Relationship, [1] = Node, [2] = 2.Relationship, [3] = 2.Node fieldListCypher: string[] = ['MATCH']; - fieldList: string[] = ['0']; // each newly created input field in mql gets another value - fieldDepth: number[] = [0]; + fieldList: string[] = ['0']; + fieldDepthCounter = 0; - logicalDepth: number[] = [-1]; logicalDepthCounter = 0; // mql input fields - mqlDropdown: string[] = []; - mqlTextX: string[] = []; - mqlText1: string[] = []; - mqlText2: string[] = []; + mqlFields: any[][] = [['','','','',0,0]]; //mqlText1 = 0, mqlDropdown = 1, mqlText2 = 3, mqlTextX = 4, fieldDepth = 5, logicalDepth = 6 activeNamespace: string; // same usage as console.components.ts collectionName: string; graphName: string; @@ -105,6 +101,7 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest private initialrect: DOMRect; + ngOnInit() { this._leftSidebar.open(); this.initSchema(this.lang); @@ -420,15 +417,10 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest this.collectionName = undefined; this.graphName = undefined; //mql - this.mqlDropdown = []; - this.mqlTextX = []; - this.mqlText1 = []; - this.mqlText2 = []; + this.mqlFields = [['','','','',0,0]]; this.fieldCounter = 0; - this.logicalDepth = [0]; this.logicalOperatorStack = []; this.fieldList = ['0']; - this.fieldDepth = [0]; this.fieldDepthCounter = 0; this.logicalDepthCounter = 0; //cypher @@ -438,15 +430,10 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest break; case 'cypher': this.collectionName = undefined; - this.mqlDropdown = []; - this.mqlTextX = []; - this.mqlText1 = []; - this.mqlText2 = []; + this.mqlFields = [['','','','',0,0]]; this.fieldCounter = 0; this.fieldList = ['0']; - this.fieldDepth = [0]; this.fieldDepthCounter = 0; - this.logicalDepth = [0]; this.logicalDepthCounter = 0; this.logicalOperatorStack = []; break; @@ -537,11 +524,9 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest const targetIndex = Math.round(mouseY / rect.height) + index; if (index !== -1 && targetIndex !== -1 && index !== targetIndex) { this.fieldList.splice(targetIndex, 0, this.fieldList.splice(index, 1)[0]); - this.mqlDropdown.splice(targetIndex, 0, this.mqlDropdown.splice(index, 1)[0]); - this.mqlText1.splice(targetIndex, 0, this.mqlText1.splice(index, 1)[0]); - this.mqlText2.splice(targetIndex, 0, this.mqlText2.splice(index, 1)[0]); - this.mqlTextX.splice(targetIndex, 0, this.mqlTextX.splice(index, 1)[0]); - this.fieldDepth.splice(targetIndex, 0, this.fieldDepth.splice(index, 1)[0]); + this.mqlFields.splice(targetIndex, 0, this.mqlFields.splice(index, 1)[0]); + // Logical Operators + this.logicalOperatorStack.splice(targetIndex, 0, this.logicalOperatorStack.splice(index, 1)[0]); } }, 0); } @@ -549,6 +534,7 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest } //similiar to data-graph.component.ts + generateColor(index: number): string { const color = d3.interpolateSinebow; const ratio = 1 / (this.nodeLabels.length + this.relationLabels.length); @@ -575,55 +561,61 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest this.fieldCounter += 1; this.fieldList.push(String(this.fieldCounter)); this.fieldDepthCounter = 0; - this.fieldDepth.push(this.fieldDepthCounter); - this.logicalDepth.push(-1); + this.mqlFields.push([]); + this.mqlFields[this.fieldList.length-1][5] = 0; //Key-Object Depth + this.mqlFields[this.fieldList.length-1][6] = -1; //Logical Operator Depth + } addMQLFieldKeyObject() { // adding a property - this.mqlDropdown[this.fieldCounter] = undefined;// deleting equal from field before + this.mqlFields[this.fieldCounter][1] = undefined;// deleting equal from field before this.fieldCounter += 1; - this.fieldList.push(String(this.fieldCounter)); //adding addition marker to fieldList this.fieldDepthCounter += 1; - this.fieldDepth.push(this.fieldDepthCounter); - this.logicalDepth.push(-1); + this.fieldList.push(String(this.fieldCounter)); //adding addition marker to fieldList + this.mqlFields.push([]); + this.mqlFields[this.fieldList.length-1][5] = this.fieldDepthCounter; //Key-Object Depth + this.mqlFields[this.fieldList.length-1][6] = -1; //Logical Operator Depth } addMQLFieldKeyObject2() { // staying on the same 'level' of property this.fieldCounter += 1; this.fieldList.push(String(this.fieldCounter)); //adding addition marker to fieldList - this.fieldDepth.push(this.fieldDepthCounter); - this.logicalDepth.push(-1); + this.mqlFields.push([]); + this.mqlFields[this.fieldList.length-1][5] = this.fieldDepthCounter; //Key-Object Depth + this.mqlFields[this.fieldList.length-1][6] = -1; //Logical Operator Depth } addLogicalOperator(logical: string) { // adding Logical Operator AND or OR this.fieldCounter += 1; this.fieldList.push(logical); - this.fieldDepth.push(this.fieldDepthCounter); - this.logicalDepth.push(this.logicalDepthCounter); - this.logicalDepthCounter += 1; this.logicalOperatorStack.push(logical); + this.mqlFields.push([]); + this.mqlFields[this.fieldList.length-1][5] = this.fieldDepthCounter; //Key-Object Depth + this.mqlFields[this.fieldList.length-1][6] = this.logicalDepthCounter; //Logical Operator Depth + this.logicalDepthCounter += 1; } endLogicalOperator() { // ending Logical Operator AND or OR this.fieldCounter += 1; - this.fieldList.push('END'); - this.fieldDepth.push(this.fieldDepthCounter); this.logicalDepthCounter -= 1; - this.logicalDepth.push(this.logicalDepthCounter); + this.fieldList.push('END'); this.logicalOperatorStack.pop(); + this.mqlFields.push([]); + this.mqlFields[this.fieldList.length-1][5] = this.fieldDepthCounter; //Key-Object Depth + this.mqlFields[this.fieldList.length-1][6] = this.logicalDepthCounter; //Logical Operator Depth } prependKeyObject(depth: number, index: number) { //creating the dot notation for objects let prependText = ''; if (depth !== 0) { //does not have to iterarate through this if depth 0 - for (let i = this.mqlText1.length - 1; i >= 0; i--) { //searches elements in array with lower depth to append for dot-notation - if (this.fieldDepth[i] < depth) { - prependText += this.mqlText1[i] + '.'; + for (let i = this.mqlFields.length - 1; i >= 0; i--) { //searches elements in array with lower depth to append for dot-notation + if (this.mqlFields[i][5] < depth) { + prependText += this.mqlFields[i][0] + '.'; break; } } } - this.mqlText1[index] = prependText + this.mqlTextX[index]; + this.mqlFields[index][0] = prependText + this.mqlFields[index][3]; } deleteCypherField(x:number) { @@ -634,47 +626,37 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest deleteMQLField(x:number) { if (this.fieldList[x] === 'AND' || this.fieldList[x] === 'OR' || this.fieldList[x] === 'END') { //Deleting logical Operator and its END - const indicesToRemove: number[] = []; - for (let i = x; i < this.fieldList.length; i++) { - if (this.logicalDepth[i] === this.logicalDepth[x]) { //should only delete the next element of logical Operator + const indicesToRemove = []; + for (let i = x; i < this.fieldList.length; i++) { // finds element and next element with same logical depth + console.log('The iterator goes to ' + i); + if (this.mqlFields[i][6] === this.mqlFields[x][6]) { // comparing logical depths indicesToRemove.push(i); - if (indicesToRemove.length === 2) { - if (indicesToRemove[1] === this.fieldList.length && x !== 0) { //if last row of rows, we have to adapt fieldDepthCounter - this.fieldDepthCounter = this.fieldDepth[x - 1]; - } - this.mqlDropdown.splice(indicesToRemove[1], 1); - this.mqlText1.splice(indicesToRemove[1], 1); - this.mqlText2.splice(indicesToRemove[1], 1); - this.mqlTextX.splice(indicesToRemove[1], 1); - this.fieldDepth.splice(indicesToRemove[1], 1); - this.fieldCounter -= 1; - break; - } } + if (indicesToRemove.length === 2) { + break; + } + } + console.log(indicesToRemove); + this.mqlFields = this.mqlFields.filter((_, index) => !indicesToRemove.includes(index)); + this.fieldCounter = this.fieldCounter - indicesToRemove.length; + if (indicesToRemove[1] === this.fieldList.length && x !== 0) { //if last row of rows, we have to adapt fieldDepthCounter + this.fieldDepthCounter = this.mqlFields[x - 1][5]; } this.fieldList = this.fieldList.filter((_, index) => !indicesToRemove.includes(index)); this.logicalOperatorStack = this.fieldList.filter((el) => el === 'AND' || el === 'OR' || el === 'END'); - this.logicalDepth = this.logicalDepth.filter((_, index) => !indicesToRemove.includes(index)); if (indicesToRemove.length === 1) { // there is no END, so the logical depth counter has to be substracted this.logicalDepthCounter -= 1; - if (x === this.fieldList.length && x !== 0) { //if last row of rows, we have to adapt fieldDepthCounter - this.fieldDepthCounter = this.fieldDepth[x - 1]; - } + console.log('The Logical DepthCounter is' + this.logicalDepthCounter); } } - else { + else { // normal field this.fieldList.splice(x, 1); - this.logicalDepth.splice(x, 1); + this.mqlFields.splice(x, 1); + this.fieldCounter -= 1; if (x === this.fieldList.length && x !== 0) { //if last row of rows, we have to adapt fieldDepthCounter - this.fieldDepthCounter = this.fieldDepth[x - 1]; + this.fieldDepthCounter = this.mqlFields[x-1][5]; } } - this.mqlDropdown.splice(x, 1); - this.mqlText1.splice(x, 1); - this.mqlText2.splice(x, 1); - this.mqlTextX.splice(x, 1); - this.fieldDepth.splice(x, 1); - this.fieldCounter -= 1; this.generateMQL(); } @@ -724,27 +706,27 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest if (isInsideLogicalCondition.length !== 0){ mql += '{'; } - switch (this.mqlDropdown[i]) { + switch (this.mqlFields[i][1]) { case 'equal': - mql += '"' + this.mqlText1[i] + '" : ' + this.mqlText2[i]; + mql += '"' + this.mqlFields[i][0] + '" : ' + this.mqlFields[i][2]; break; case 'notequal': - mql += '"' + this.mqlText1[i] + '" : {"$ne" : ' + this.mqlText2[i] + '}'; + mql += '"' + this.mqlFields[i][0] + '" : {"$ne" : ' + this.mqlFields[i][2] + '}'; break; case 'greater': - mql += '"' + this.mqlText1[i] + '" : {"$gt" : ' + this.mqlText2[i] + '}'; + mql += '"' + this.mqlFields[i][0] + '" : {"$gt" : ' + this.mqlFields[i][2] + '}'; break; case 'lesser': - mql += '"' + this.mqlText1[i] + '" : {"$lt" : ' + this.mqlText2[i] + '}'; + mql += '"' + this.mqlFields[i][0] + '" : {"$lt" : ' + this.mqlFields[i][2] + '}'; break; case 'contains': - mql += '"' + this.mqlText1[i] + '" : {$regex: \'/.*' + this.mqlText2[i] + '.*/i\'}'; + mql += '"' + this.mqlFields[i][0] + '" : {$regex: \'/.*' + this.mqlFields[i][2] + '.*/i\'}'; break; case 'notcontains': - mql += '"' + this.mqlText1[i] + '" : {"$not" : /.*' + this.mqlText2[i] + '.*/i}'; + mql += '"' + this.mqlFields[i][0] + '" : {"$not" : /.*' + this.mqlFields[i][2] + '.*/i}'; break; case 'type': - mql += '"' + this.mqlText1[i] + '" : {"$type" : ' + this.mqlText2[i] + '}'; + mql += '"' + this.mqlFields[i][0] + '" : {"$type" : ' + this.mqlFields[i][2] + '}'; break; } if (isInsideLogicalCondition.length !== 0){ @@ -757,7 +739,7 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest matchingIndex = j; } } - if (matchingIndex + 1 <= fieldListf.length - 1 && matchingIndex !== -1 && this.mqlDropdown[i] !== undefined) { + if (matchingIndex + 1 <= fieldListf.length - 1 && matchingIndex !== -1 && this.mqlFields[i][1] !== undefined) { mql += ', '; } } From 0d87f74921eac4ff1bdf8f90f053c500eb22a8cd Mon Sep 17 00:00:00 2001 From: svamel00 Date: Mon, 13 Mar 2023 23:23:37 +0100 Subject: [PATCH 32/60] added basic aggregate interface for mql --- .../graphical-querying.component.html | 788 ++++++++++------ .../graphical-querying.component.scss | 23 +- .../graphical-querying.component.ts | 875 ++++++++++++++---- 3 files changed, 1225 insertions(+), 461 deletions(-) diff --git a/src/app/views/querying/graphical-querying/graphical-querying.component.html b/src/app/views/querying/graphical-querying/graphical-querying.component.html index 894ca869..76b331ad 100644 --- a/src/app/views/querying/graphical-querying/graphical-querying.component.html +++ b/src/app/views/querying/graphical-querying/graphical-querying.component.html @@ -100,22 +100,24 @@
    Query Result
    - +
    -

    Select your graph from the left sidebar: {{ graphName !== undefined ? ' ' + graphName : '' }}

    +

    Select your graph from the left sidebar: {{ graphName !== undefined ? ' ' + graphName : '' }}

    Fill in the details. You can drag and drop the labels into the input fields.

    - -

    Node Labels:

    -
    -

    {{label}}

    -
    +
    + +

    Node Labels:

    +
    +

    {{label}}

    +
    - -

    Relationship Labels:

    -
    -

    {{label}}

    + +

    Relationship Labels:

    +
    +

    {{label}}

    +
    @@ -124,233 +126,235 @@
    Query Result
    [config]="config"> --> -
    -
    -
    -
    -
    -
    - +
    +
    +
    +
    +
    +
    +
    + +
    +
    -
    -
    -
    - - +
    + + +
    -
    -
    - -
    -
    -
    -
    - +
    + +
    +
    +
    +
    + +
    +
    -
    -
    - -
    -
    -
    - + +
    +
    +
    + +
    +
    +
    +
    + +
    -
    -
    - +
    +
    +
    + +
    -
    -
    -
    - +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    +
    +
    + +
    -
    -
    -
    -
    -
    + +
    +
    +
    - +
    + +
    +
    -
    -
    -
    +
    - +
    -
    -
    -
    - -
    -
    -
    -
    -
    - +
    +
    +
    -
    -
    -
    -
    - +
    + +
    -
    -
    - +
    +
    + + +
    -
    - - -
    -
    -
    - - - -
    -
    -
    - -
    -
    -
    -
    - + +
    +
    +
    +
    + +
    -
    -
    -
    - +
    +
    + +
    -
    -
    -
    - +
    +
    + +
    +
    +
    + +
    -
    - - -
    -
    -
    -
    - - - +
    +
    + + + +
    -
    - -
    -
    - - + +
    +
    + + +
    -
    - -
    -
    -
    -
    - + +
    +
    +
    +
    + +
    +
    -
    @@ -398,7 +402,7 @@
    Query Result
    -
    +

    Sidebar

    @@ -409,109 +413,335 @@
    Query Result
    -

    Select your collection from the left sidebar: {{ collectionName !== undefined ? ' ' + collectionName : '' }}

    +

    Select your collection from the left sidebar: {{ collectionName2 !== undefined ? ' ' + collectionName2 : '' }}

    Fill in the details:

    +
    +

    Choose what you want to do:

    +
    + + +
    +
    - -
    - -
    -
    - {{fieldNumber}} + +
    +
    + +
    + Match stage +
    + +
    +
    + {{fieldNumber}} +
    +
    + +
    +
    +
    + +
    +
    + END +
    +
    +
    + +
    +
    +
    +
    + +
    + +
    +
    +
    +
    +
    + +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    + + +
    +
    +
    -
    - + +
    +
    + + +
    - - -
    -
    - END + + +
    + Group stage +
    + +
    +
    + {{fieldNumber}} +
    +
    + +
    +
    +
    + +
    +
    + END +
    +
    +
    + +
    +
    +
    +
    + +
    + +
    +
    +
    +
    +
    + +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    + + +
    +
    +
    +
    + +
    +
    + + +
    - - -
    -
    -
    -
    - +
    +
    + + +
    +
    +
    + +
    +
    + {{fieldNumber}} +
    +
    +
    -
    -
    -
    -
    -
    - + + +
    +
    + END
    -
    -
    -
    -
    - + + +
    +
    +
    +
    + +
    + +
    +
    +
    +
    +
    + +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    + +
    -
    -
    - - -
    +
    - -
    -
    -
    - - +
    diff --git a/src/app/views/querying/graphical-querying/graphical-querying.component.scss b/src/app/views/querying/graphical-querying/graphical-querying.component.scss index ac6c79c5..91a93fb9 100644 --- a/src/app/views/querying/graphical-querying/graphical-querying.component.scss +++ b/src/app/views/querying/graphical-querying/graphical-querying.component.scss @@ -69,8 +69,29 @@ .show-error { display: block !important; } +.label { + margin-bottom:1.5em; +} + +.cypher-sidebar { + background-color: #f0f3f5; + border: 1px solid #c8ced3; +} + +.mql-second-text-fields { + background-color: rgb(210, 210, 210, 0.9); + padding: 1em; + border: 1px rgba(0, 0, 0, 0.125) solid; +} + +.text-fields { + background-color: #dcdcdc; + padding: 1em; + margin-bottom: 1.5em; + border: 1px rgba(0, 0, 0, 0.125) solid; +} -//Label Container + //Label Container .label-container { display: flex; } diff --git a/src/app/views/querying/graphical-querying/graphical-querying.component.ts b/src/app/views/querying/graphical-querying/graphical-querying.component.ts index 354446b2..6952d226 100644 --- a/src/app/views/querying/graphical-querying/graphical-querying.component.ts +++ b/src/app/views/querying/graphical-querying/graphical-querying.component.ts @@ -72,35 +72,55 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest tableId: string; config: TableConfig; // cypher input fields - //cypherMatch: string[] = []; cypherFields: string[][] = [[]]; // Matrix à [n,5] size -> [1] = Relationship, [2] = Node, [3] = 2.Relationship, [4] = 2.Node cypherReturn = ''; cypherDropdown: string[] = []; //cypherRelationship: string[] = ['','','','']; // [0] = Relationship, [1] = Node, [2] = 2.Relationship, [3] = 2.Node fieldListCypher: string[] = ['MATCH']; fieldList: string[] = ['0']; - + fieldListMATCH: string[] = ['0']; + fieldListGROUP: string[] = ['0']; fieldDepthCounter = 0; + fieldDepthCounterMATCH = 0; + fieldDepthCounterGROUP = 0; logicalDepthCounter = 0; + logicalDepthCounterMATCH = 0; + logicalDepthCounterGROUP = 0; // mql input fields mqlFields: any[][] = [['','','','',0,0]]; //mqlText1 = 0, mqlDropdown = 1, mqlText2 = 3, mqlTextX = 4, fieldDepth = 5, logicalDepth = 6 + + mqlFieldsMATCH: any[][] = [['','','','',0,0]]; + mqlFieldsGROUP: any[][] = [['','','','',0,0]]; activeNamespace: string; // same usage as console.components.ts collectionName: string; + collectionName2: string; graphName: string; logicalOperatorStack: string[] = []; + logicalOperatorStackMATCH: string[] = []; + logicalOperatorStackGROUP: string[] = []; fieldCounter = 0; + fieldCounterMATCH = 0; + fieldCounterGROUP = 0; private readonly LOCAL_STORAGE_NAMESPACE_KEY = 'polypheny-namespace'; // same usage as console.components.ts // Dropdown show = false; + showFIND = false; + showMATCH = false; + showGROUP = false; show2 = false; + showFIND2 = false; + showMATCH2 = false; + showGROUP2 = false; private debounce: any; private debounceDelay = 200; private initialrect: DOMRect; + mqlType: string; + ngOnInit() { this._leftSidebar.open(); @@ -193,10 +213,9 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest res => { const nodeAction = (tree, node, $event) => { // TO DO: it only shows columns _id_ and _data_ but not correct ones. if (!node.isActive && node.isLeaf) { - console.log(node.parent.id); this.setDefaultDB(node.parent.id); - console.log(node.displayField); this.collectionName = node.displayField; + this.collectionName2 = node.id; } }; const schemaTemp = res; @@ -415,14 +434,27 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest switch (inputlang) { case 'sql': this.collectionName = undefined; + this.collectionName2 = undefined; this.graphName = undefined; //mql this.mqlFields = [['','','','',0,0]]; + this.mqlFieldsMATCH = [['','','','',0,0]]; + this.mqlFieldsGROUP = [['','','','',0,0]]; this.fieldCounter = 0; this.logicalOperatorStack = []; this.fieldList = ['0']; this.fieldDepthCounter = 0; this.logicalDepthCounter = 0; + this.fieldCounterMATCH = 0; + this.logicalOperatorStackMATCH = []; + this.fieldListMATCH = ['0']; + this.fieldDepthCounterMATCH = 0; + this.logicalDepthCounterMATCH = 0; + this.fieldCounterGROUP = 0; + this.logicalOperatorStackGROUP = []; + this.fieldListGROUP = ['0']; + this.fieldDepthCounterGROUP = 0; + this.logicalDepthCounterGROUP = 0; //cypher this.cypherFields = [[]]; this.cypherReturn = ''; @@ -430,12 +462,25 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest break; case 'cypher': this.collectionName = undefined; + this.collectionName2 = undefined; this.mqlFields = [['','','','',0,0]]; + this.mqlFieldsMATCH = [['','','','',0,0]]; + this.mqlFieldsGROUP = [['','','','',0,0]]; this.fieldCounter = 0; + this.logicalOperatorStack = []; this.fieldList = ['0']; this.fieldDepthCounter = 0; this.logicalDepthCounter = 0; - this.logicalOperatorStack = []; + this.fieldCounterMATCH = 0; + this.logicalOperatorStackMATCH = []; + this.fieldListMATCH = ['0']; + this.fieldDepthCounterMATCH = 0; + this.logicalDepthCounterMATCH = 0; + this.fieldCounterGROUP = 0; + this.logicalOperatorStackGROUP = []; + this.fieldListGROUP = ['0']; + this.fieldDepthCounterGROUP = 0; + this.logicalDepthCounterGROUP = 0; break; case 'mql': this.graphName = undefined; @@ -454,46 +499,153 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest } //taken from json-editor.component.ts - setMenuShow(doShow: boolean, instant = false) { - if (instant) { - this.show = doShow; - return; - } - if (!doShow) { - this.debounce = setTimeout(() => { - this.show = false; - }, this.debounceDelay); - } else { - this.show = true; + setMenuShow(doShow: boolean, instant = false, mqlCase: string) { + switch (mqlCase) { + case 'Cypher': + if (instant) { + this.show = doShow; + return; + } + if (!doShow) { + this.debounce = setTimeout(() => { + this.show = false; + }, this.debounceDelay); + } else { + this.show = true; + } + break; + case 'Find': + if (instant) { + this.showFIND = doShow; + return; + } + if (!doShow) { + this.debounce = setTimeout(() => { + this.showFIND = false; + }, this.debounceDelay); + } else { + this.showFIND = true; + } + break; + case 'Aggr1': + if (instant) { + this.showMATCH = doShow; + return; + } + if (!doShow) { + this.debounce = setTimeout(() => { + this.showMATCH = false; + }, this.debounceDelay); + } else { + this.showMATCH = true; + } + break; + case 'Aggr2': + if (instant) { + this.showGROUP = doShow; + return; + } + if (!doShow) { + this.debounce = setTimeout(() => { + this.showGROUP = false; + }, this.debounceDelay); + } else { + this.showGROUP = true; + } + break; } } //taken from json-editor.component.ts - menuEnter() { - if (this.show) { - clearTimeout(this.debounce); + menuEnter(mqlCase: string) { + switch (mqlCase) { + case 'Cypher': + if (this.show) { + clearTimeout(this.debounce); + } + break; + case 'Find': + if (this.showFIND) { + clearTimeout(this.debounce); + } + break; + case 'Aggr1': + if (this.showMATCH) { + clearTimeout(this.debounce); + } + break; + case 'Aggr2': + if (this.showGROUP) { + clearTimeout(this.debounce); + } + break; } } - setMenuShow2(doShow2: boolean, instant = false) { - if (instant) { - this.show2 = doShow2; - return; - } - if (!doShow2) { - this.debounce = setTimeout(() => { - this.show2 = false; - }, this.debounceDelay); - } else { - this.show2 = true; + setMenuShow2(doShow: boolean, instant = false, mqlCase: string) { + switch (mqlCase) { + case 'Find': + if (instant) { + this.show2 = doShow; + return; + } + if (!doShow) { + this.debounce = setTimeout(() => { + this.show2 = false; + }, this.debounceDelay); + } else { + this.show2 = true; + } + break; + case 'Aggr1': + if (instant) { + this.showMATCH2 = doShow; + return; + } + if (!doShow) { + this.debounce = setTimeout(() => { + this.showMATCH2 = false; + }, this.debounceDelay); + } else { + this.showMATCH2 = true; + } + break; + case 'Aggr2': + if (instant) { + this.showGROUP2 = doShow; + return; + } + if (!doShow) { + this.debounce = setTimeout(() => { + this.showGROUP2 = false; + }, this.debounceDelay); + } else { + this.showGROUP2 = true; + } + break; } } //taken from json-editor.component.ts - menuEnter2() { - if (this.show2) { - clearTimeout(this.debounce); + menuEnter2(mqlCase: string) { + switch (mqlCase) { + case 'Find': + if (this.showFIND2) { + clearTimeout(this.debounce); + } + break; + case 'Aggr1': + if (this.showMATCH2) { + clearTimeout(this.debounce); + } + break; + case 'Aggr2': + if (this.showGROUP2) { + clearTimeout(this.debounce); + } + break; } + } //drag and drop for cypher labels @@ -512,25 +664,65 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest event.preventDefault(); } - onDrop(event: DragEvent) { + onDrop(event: DragEvent, mqlCase: string) { event.preventDefault(); const data = event.dataTransfer?.getData('text/plain'); - if (data) { - const index = this.fieldList.indexOf(data); - const targetElement = event.currentTarget as HTMLElement; - setTimeout(() => { - const rect = targetElement.getBoundingClientRect(); - const mouseY = rect.top - this.initialrect.top; - const targetIndex = Math.round(mouseY / rect.height) + index; - if (index !== -1 && targetIndex !== -1 && index !== targetIndex) { - this.fieldList.splice(targetIndex, 0, this.fieldList.splice(index, 1)[0]); - this.mqlFields.splice(targetIndex, 0, this.mqlFields.splice(index, 1)[0]); - // Logical Operators - this.logicalOperatorStack.splice(targetIndex, 0, this.logicalOperatorStack.splice(index, 1)[0]); + switch (mqlCase) { + case 'Find': + if (data) { + const index = this.fieldList.indexOf(data); + const targetElement = event.currentTarget as HTMLElement; + setTimeout(() => { + const rect = targetElement.getBoundingClientRect(); + const mouseY = rect.top - this.initialrect.top; + const targetIndex = Math.round(mouseY / rect.height) + index; + if (index !== -1 && targetIndex !== -1 && index !== targetIndex) { + this.fieldList.splice(targetIndex, 0, this.fieldList.splice(index, 1)[0]); + this.mqlFields.splice(targetIndex, 0, this.mqlFields.splice(index, 1)[0]); + // Logical Operators + this.logicalOperatorStack.splice(targetIndex, 0, this.logicalOperatorStack.splice(index, 1)[0]); + } + }, 0); } - }, 0); + this.generateMQL(); + break; + case 'Aggr1': + if (data) { + const index = this.fieldListMATCH.indexOf(data); + const targetElement = event.currentTarget as HTMLElement; + setTimeout(() => { + const rect = targetElement.getBoundingClientRect(); + const mouseY = rect.top - this.initialrect.top; + const targetIndex = Math.round(mouseY / rect.height) + index; + if (index !== -1 && targetIndex !== -1 && index !== targetIndex) { + this.fieldListMATCH.splice(targetIndex, 0, this.fieldListMATCH.splice(index, 1)[0]); + this.mqlFieldsMATCH.splice(targetIndex, 0, this.mqlFieldsMATCH.splice(index, 1)[0]); + // Logical Operators + this.logicalOperatorStackMATCH.splice(targetIndex, 0, this.logicalOperatorStackMATCH.splice(index, 1)[0]); + } + }, 0); + } + this.generateMQL(); + break; + case 'Aggr2': + if (data) { + const index = this.fieldListGROUP.indexOf(data); + const targetElement = event.currentTarget as HTMLElement; + setTimeout(() => { + const rect = targetElement.getBoundingClientRect(); + const mouseY = rect.top - this.initialrect.top; + const targetIndex = Math.round(mouseY / rect.height) + index; + if (index !== -1 && targetIndex !== -1 && index !== targetIndex) { + this.fieldListGROUP.splice(targetIndex, 0, this.fieldListGROUP.splice(index, 1)[0]); + this.mqlFieldsGROUP.splice(targetIndex, 0, this.mqlFieldsGROUP.splice(index, 1)[0]); + // Logical Operators + this.logicalOperatorStackGROUP.splice(targetIndex, 0, this.logicalOperatorStackGROUP.splice(index, 1)[0]); + } + }, 0); + } + this.generateMQL(); + break; } - this.generateMQL(); } //similiar to data-graph.component.ts @@ -557,65 +749,194 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest } - addMQLField() { // 'normal new Field' - this.fieldCounter += 1; - this.fieldList.push(String(this.fieldCounter)); - this.fieldDepthCounter = 0; - this.mqlFields.push([]); - this.mqlFields[this.fieldList.length-1][5] = 0; //Key-Object Depth - this.mqlFields[this.fieldList.length-1][6] = -1; //Logical Operator Depth - + addMQLField(mqlCase: string) { // 'normal new Field' + switch (mqlCase) { + case 'Find': + this.fieldCounter += 1; + this.fieldList.push(String(this.fieldCounter)); + this.fieldDepthCounter = 0; + this.mqlFields.push([]); + this.mqlFields[this.fieldList.length-1][5] = 0; //Key-Object Depth + this.mqlFields[this.fieldList.length-1][6] = -1; //Logical Operator Depth + break; + case 'Aggr1': + this.fieldCounterMATCH += 1; + this.fieldListMATCH.push(String(this.fieldCounterMATCH)); + this.fieldDepthCounterMATCH = 0; + this.mqlFieldsMATCH.push([]); + this.mqlFieldsMATCH[this.fieldListMATCH.length-1][5] = 0; + this.mqlFieldsMATCH[this.fieldListMATCH.length-1][6] = -1; + break; + case 'Aggr2': + this.fieldCounterGROUP += 1; + this.fieldListGROUP.push(String(this.fieldCounterGROUP)); + this.fieldDepthCounterGROUP = 0; + this.mqlFieldsGROUP.push([]); + this.mqlFieldsGROUP[this.fieldListGROUP.length-1][5] = 0; + this.mqlFieldsGROUP[this.fieldListGROUP.length-1][6] = -1; + break; + } } - addMQLFieldKeyObject() { // adding a property - this.mqlFields[this.fieldCounter][1] = undefined;// deleting equal from field before - this.fieldCounter += 1; - this.fieldDepthCounter += 1; - this.fieldList.push(String(this.fieldCounter)); //adding addition marker to fieldList - this.mqlFields.push([]); - this.mqlFields[this.fieldList.length-1][5] = this.fieldDepthCounter; //Key-Object Depth - this.mqlFields[this.fieldList.length-1][6] = -1; //Logical Operator Depth + addMQLFieldKeyObject(mqlCase: string) { // adding a property + switch (mqlCase) { + case 'Find': + this.mqlFields[this.fieldCounter][1] = undefined;// deleting equal from field before + this.fieldCounter += 1; + this.fieldDepthCounter += 1; + this.fieldList.push(String(this.fieldCounter)); //adding addition marker to fieldList + this.mqlFields.push([]); + this.mqlFields[this.fieldList.length-1][5] = this.fieldDepthCounter; //Key-Object Depth + this.mqlFields[this.fieldList.length-1][6] = -1; //Logical Operator Depth + break; + case 'Aggr1': + this.mqlFieldsMATCH[this.fieldCounterMATCH][1] = undefined; + this.fieldCounterMATCH += 1; + this.fieldDepthCounterMATCH += 1; + this.fieldListMATCH.push(String(this.fieldCounterMATCH)); + this.mqlFieldsMATCH.push([]); + this.mqlFieldsMATCH[this.fieldListMATCH.length-1][5] = this.fieldDepthCounterMATCH; + this.mqlFieldsMATCH[this.fieldListMATCH.length-1][6] = -1; + break; + case 'Aggr2': + this.mqlFieldsGROUP[this.fieldCounterGROUP][1] = undefined; + this.fieldCounterGROUP += 1; + this.fieldDepthCounterGROUP += 1; + this.fieldListGROUP.push(String(this.fieldCounterGROUP)); + this.mqlFieldsGROUP.push([]); + this.mqlFieldsGROUP[this.fieldListGROUP.length-1][5] = this.fieldDepthCounterGROUP; + this.mqlFieldsGROUP[this.fieldListGROUP.length-1][6] = -1; + break; + } } - addMQLFieldKeyObject2() { // staying on the same 'level' of property - this.fieldCounter += 1; - this.fieldList.push(String(this.fieldCounter)); //adding addition marker to fieldList - this.mqlFields.push([]); - this.mqlFields[this.fieldList.length-1][5] = this.fieldDepthCounter; //Key-Object Depth - this.mqlFields[this.fieldList.length-1][6] = -1; //Logical Operator Depth + addMQLFieldKeyObject2(mqlCase: string) { // staying on the same 'level' of property + switch (mqlCase) { + case 'Find': + this.fieldCounter += 1; + this.fieldList.push(String(this.fieldCounter)); //adding addition marker to fieldList + this.mqlFields.push([]); + this.mqlFields[this.fieldList.length - 1][5] = this.fieldDepthCounter; //Key-Object Depth + this.mqlFields[this.fieldList.length - 1][6] = -1; //Logical Operator Depth + break; + case 'Aggr1': + this.fieldCounterMATCH += 1; + this.fieldListMATCH.push(String(this.fieldCounterMATCH)); + this.mqlFieldsMATCH.push([]); + this.mqlFieldsMATCH[this.fieldListMATCH.length - 1][5] = this.fieldDepthCounterMATCH; + this.mqlFieldsMATCH[this.fieldListMATCH.length - 1][6] = -1; + break; + case 'Aggr2': + this.fieldCounterGROUP += 1; + this.fieldListGROUP.push(String(this.fieldCounterGROUP)); + this.mqlFieldsGROUP.push([]); + this.mqlFieldsGROUP[this.fieldListGROUP.length - 1][5] = this.fieldDepthCounterGROUP; + this.mqlFieldsGROUP[this.fieldListGROUP.length - 1][6] = -1; + break; + } } - addLogicalOperator(logical: string) { // adding Logical Operator AND or OR - this.fieldCounter += 1; - this.fieldList.push(logical); - this.logicalOperatorStack.push(logical); - this.mqlFields.push([]); - this.mqlFields[this.fieldList.length-1][5] = this.fieldDepthCounter; //Key-Object Depth - this.mqlFields[this.fieldList.length-1][6] = this.logicalDepthCounter; //Logical Operator Depth - this.logicalDepthCounter += 1; + addLogicalOperator(logical: string, mqlCase: string) { // adding Logical Operator AND or OR + switch (mqlCase) { + case 'Find': + this.fieldCounter += 1; + this.fieldList.push(logical); + this.logicalOperatorStack.push(logical); + this.mqlFields.push([]); + this.mqlFields[this.fieldList.length - 1][5] = this.fieldDepthCounter; //Key-Object Depth + this.mqlFields[this.fieldList.length - 1][6] = this.logicalDepthCounter; //Logical Operator Depth + this.logicalDepthCounter += 1; + break; + case 'Aggr1': + this.fieldCounterMATCH += 1; + this.fieldListMATCH.push(logical); + this.logicalOperatorStackMATCH.push(logical); + this.mqlFieldsMATCH.push([]); + this.mqlFieldsMATCH[this.fieldListMATCH.length - 1][5] = this.fieldDepthCounterMATCH; + this.mqlFieldsMATCH[this.fieldListMATCH.length - 1][6] = this.logicalDepthCounterMATCH; + this.logicalDepthCounterMATCH += 1; + break; + case 'Aggr2': + this.fieldCounterGROUP += 1; + this.fieldListGROUP.push(logical); + this.logicalOperatorStackGROUP.push(logical); + this.mqlFieldsGROUP.push([]); + this.mqlFieldsGROUP[this.fieldListGROUP.length - 1][5] = this.fieldDepthCounterGROUP; + this.mqlFieldsGROUP[this.fieldListGROUP.length - 1][6] = this.logicalDepthCounterGROUP; + this.logicalDepthCounterGROUP += 1; + break; + } } - endLogicalOperator() { // ending Logical Operator AND or OR - this.fieldCounter += 1; - this.logicalDepthCounter -= 1; - this.fieldList.push('END'); - this.logicalOperatorStack.pop(); - this.mqlFields.push([]); - this.mqlFields[this.fieldList.length-1][5] = this.fieldDepthCounter; //Key-Object Depth - this.mqlFields[this.fieldList.length-1][6] = this.logicalDepthCounter; //Logical Operator Depth + endLogicalOperator(mqlCase: string) { // ending Logical Operator AND or OR + switch (mqlCase) { + case 'Find': + this.fieldCounter += 1; + this.logicalDepthCounter -= 1; + this.fieldList.push('END'); + this.logicalOperatorStack.pop(); + this.mqlFields.push([]); + this.mqlFields[this.fieldList.length-1][5] = this.fieldDepthCounter; //Key-Object Depth + this.mqlFields[this.fieldList.length-1][6] = this.logicalDepthCounter; //Logical Operator Depth + break; + case 'Aggr1': + this.fieldCounterMATCH += 1; + this.logicalDepthCounterMATCH -= 1; + this.fieldListMATCH.push('END'); + this.logicalOperatorStackMATCH.pop(); + this.mqlFieldsMATCH.push([]); + this.mqlFieldsMATCH[this.fieldListMATCH.length-1][5] = this.fieldDepthCounterMATCH; + this.mqlFieldsMATCH[this.fieldListMATCH.length-1][6] = this.logicalDepthCounterMATCH; + break; + case 'Aggr2': + this.fieldCounterGROUP += 1; + this.logicalDepthCounterGROUP -= 1; + this.fieldListGROUP.push('END'); + this.logicalOperatorStackGROUP.pop(); + this.mqlFieldsGROUP.push([]); + this.mqlFieldsGROUP[this.fieldListGROUP.length-1][5] = this.fieldDepthCounterGROUP; + this.mqlFieldsGROUP[this.fieldListGROUP.length-1][6] = this.logicalDepthCounterGROUP; + break; + } } - prependKeyObject(depth: number, index: number) { //creating the dot notation for objects + prependKeyObject(depth: number, index: number, mqlCase:string) { //creating the dot notation for objects let prependText = ''; - if (depth !== 0) { //does not have to iterarate through this if depth 0 - for (let i = this.mqlFields.length - 1; i >= 0; i--) { //searches elements in array with lower depth to append for dot-notation - if (this.mqlFields[i][5] < depth) { - prependText += this.mqlFields[i][0] + '.'; - break; + switch (mqlCase) { + case 'Find': + if (depth !== 0) { //does not have to iterarate through this if depth 0 + for (let i = this.mqlFields.length - 1; i >= 0; i--) { //searches elements in array with lower depth to append for dot-notation + if (this.mqlFields[i][5] < depth) { + prependText += this.mqlFields[i][0] + '.'; + break; + } + } } - } + this.mqlFields[index][0] = prependText + this.mqlFields[index][3]; + break; + case 'Aggr1': + if (depth !== 0) { + for (let i = this.mqlFieldsMATCH.length - 1; i >= 0; i--) { + if (this.mqlFieldsMATCH[i][5] < depth) { + prependText += this.mqlFieldsMATCH[i][0] + '.'; + break; + } + } + } + this.mqlFieldsMATCH[index][0] = prependText + this.mqlFieldsMATCH[index][3]; + break; + case 'Aggr2': + if (depth !== 0) { + for (let i = this.mqlFieldsGROUP.length - 1; i >= 0; i--) { + if (this.mqlFieldsGROUP[i][5] < depth) { + prependText += this.mqlFieldsGROUP[i][0] + '.'; + break; + } + } + } + this.mqlFieldsGROUP[index][0] = prependText + this.mqlFieldsGROUP[index][3]; + break; } - this.mqlFields[index][0] = prependText + this.mqlFields[index][3]; } deleteCypherField(x:number) { @@ -624,40 +945,105 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest this.generateCypher(); } - deleteMQLField(x:number) { - if (this.fieldList[x] === 'AND' || this.fieldList[x] === 'OR' || this.fieldList[x] === 'END') { //Deleting logical Operator and its END - const indicesToRemove = []; - for (let i = x; i < this.fieldList.length; i++) { // finds element and next element with same logical depth - console.log('The iterator goes to ' + i); - if (this.mqlFields[i][6] === this.mqlFields[x][6]) { // comparing logical depths - indicesToRemove.push(i); + deleteMQLField(x:number, mqlCase:string) { + switch (mqlCase) { + case 'Find': + if (this.fieldList[x] === 'AND' || this.fieldList[x] === 'OR' || this.fieldList[x] === 'END') { //Deleting logical Operator and its END + const indicesToRemove = []; + for (let i = x; i < this.fieldList.length; i++) { // finds element and next element with same logical depth + if (this.mqlFields[i][6] === this.mqlFields[x][6]) { // comparing logical depths + indicesToRemove.push(i); + } + if (indicesToRemove.length === 2) { + break; + } + } + this.mqlFields = this.mqlFields.filter((_, index) => !indicesToRemove.includes(index)); + this.fieldCounter = this.fieldCounter - indicesToRemove.length; + if (indicesToRemove[1] === this.fieldList.length && x !== 0) { //if last row of rows, we have to adapt fieldDepthCounter + this.fieldDepthCounter = this.mqlFields[x - 1][5]; + } + this.fieldList = this.fieldList.filter((_, index) => !indicesToRemove.includes(index)); + this.logicalOperatorStack = this.fieldList.filter((el) => el === 'AND' || el === 'OR' || el === 'END'); + if (indicesToRemove.length === 1) { // there is no END, so the logical depth counter has to be substracted + this.logicalDepthCounter -= 1; + } } - if (indicesToRemove.length === 2) { - break; + else { // normal field + this.fieldList.splice(x, 1); + this.mqlFields.splice(x, 1); + this.fieldCounter -= 1; + if (x === this.fieldList.length && x !== 0) { //if last row of rows, we have to adapt fieldDepthCounter + this.fieldDepthCounter = this.mqlFields[x-1][5]; + } } - } - console.log(indicesToRemove); - this.mqlFields = this.mqlFields.filter((_, index) => !indicesToRemove.includes(index)); - this.fieldCounter = this.fieldCounter - indicesToRemove.length; - if (indicesToRemove[1] === this.fieldList.length && x !== 0) { //if last row of rows, we have to adapt fieldDepthCounter - this.fieldDepthCounter = this.mqlFields[x - 1][5]; - } - this.fieldList = this.fieldList.filter((_, index) => !indicesToRemove.includes(index)); - this.logicalOperatorStack = this.fieldList.filter((el) => el === 'AND' || el === 'OR' || el === 'END'); - if (indicesToRemove.length === 1) { // there is no END, so the logical depth counter has to be substracted - this.logicalDepthCounter -= 1; - console.log('The Logical DepthCounter is' + this.logicalDepthCounter); - } - } - else { // normal field - this.fieldList.splice(x, 1); - this.mqlFields.splice(x, 1); - this.fieldCounter -= 1; - if (x === this.fieldList.length && x !== 0) { //if last row of rows, we have to adapt fieldDepthCounter - this.fieldDepthCounter = this.mqlFields[x-1][5]; - } + this.generateMQL(); + break; + case 'Aggr1': + if (this.fieldListMATCH[x] === 'AND' || this.fieldListMATCH[x] === 'OR' || this.fieldListMATCH[x] === 'END') { + const indicesToRemove = []; + for (let i = x; i < this.fieldListMATCH.length; i++) { + if (this.mqlFieldsMATCH[i][6] === this.mqlFieldsMATCH[x][6]) { + indicesToRemove.push(i); + } + if (indicesToRemove.length === 2) { + break; + } + } + this.mqlFieldsMATCH = this.mqlFieldsMATCH.filter((_, index) => !indicesToRemove.includes(index)); + this.fieldCounterMATCH = this.fieldCounterMATCH - indicesToRemove.length; + if (indicesToRemove[1] === this.fieldListMATCH.length && x !== 0) { + this.fieldDepthCounterMATCH = this.mqlFieldsMATCH[x - 1][5]; + } + this.fieldListMATCH = this.fieldListMATCH.filter((_, index) => !indicesToRemove.includes(index)); + this.logicalOperatorStackMATCH = this.fieldListMATCH.filter((el) => el === 'AND' || el === 'OR' || el === 'END'); + if (indicesToRemove.length === 1) { + this.logicalDepthCounterMATCH -= 1; + } + } + else { // normal field + this.fieldListMATCH.splice(x, 1); + this.mqlFieldsMATCH.splice(x, 1); + this.fieldCounterMATCH -= 1; + if (x === this.fieldListMATCH.length && x !== 0) { + this.fieldDepthCounterMATCH = this.mqlFieldsMATCH[x-1][5]; + } + } + this.generateMQL(); + break; + case 'Aggr2': + if (this.fieldListGROUP[x] === 'AND' || this.fieldListGROUP[x] === 'OR' || this.fieldListGROUP[x] === 'END') { + const indicesToRemove = []; + for (let i = x; i < this.fieldListGROUP.length; i++) { + if (this.mqlFieldsGROUP[i][6] === this.mqlFieldsGROUP[x][6]) { + indicesToRemove.push(i); + } + if (indicesToRemove.length === 2) { + break; + } + } + this.mqlFieldsGROUP = this.mqlFieldsGROUP.filter((_, index) => !indicesToRemove.includes(index)); + this.fieldCounterGROUP = this.fieldCounterGROUP - indicesToRemove.length; + if (indicesToRemove[1] === this.fieldListGROUP.length && x !== 0) { + this.fieldDepthCounterGROUP = this.mqlFieldsGROUP[x - 1][5]; + } + this.fieldListGROUP = this.fieldListGROUP.filter((_, index) => !indicesToRemove.includes(index)); + this.logicalOperatorStackGROUP = this.fieldListGROUP.filter((el) => el === 'AND' || el === 'OR' || el === 'END'); + if (indicesToRemove.length === 1) { + this.logicalDepthCounterGROUP -= 1; + } + } + else { // normal field + this.fieldListGROUP.splice(x, 1); + this.mqlFieldsGROUP.splice(x, 1); + this.fieldCounterGROUP -= 1; + if (x === this.fieldListGROUP.length && x !== 0) { + this.fieldDepthCounterGROUP = this.mqlFieldsGROUP[x-1][5]; + } + } + this.generateMQL(); + break; } - this.generateMQL(); } async generateCypher() { @@ -692,65 +1078,186 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest async generateMQL() { let mql = ''; const isInsideLogicalCondition = []; - mql += 'db.getCollection("' + this.collectionName + '").find({'; - for (let i = 0; i < this.fieldList.length; i++) { - if (this.fieldList[i] === 'AND') { - mql += '$and: ['; - isInsideLogicalCondition.push('AND'); - } - if (this.fieldList[i] === 'OR') { - mql += '$or: ['; - isInsideLogicalCondition.push('OR'); - } - if (this.fieldList[i] !== 'AND' && this.fieldList[i] !== 'OR' && this.fieldList[i] !== 'END') { - if (isInsideLogicalCondition.length !== 0){ - mql += '{'; - } - switch (this.mqlFields[i][1]) { - case 'equal': - mql += '"' + this.mqlFields[i][0] + '" : ' + this.mqlFields[i][2]; - break; - case 'notequal': - mql += '"' + this.mqlFields[i][0] + '" : {"$ne" : ' + this.mqlFields[i][2] + '}'; - break; - case 'greater': - mql += '"' + this.mqlFields[i][0] + '" : {"$gt" : ' + this.mqlFields[i][2] + '}'; - break; - case 'lesser': - mql += '"' + this.mqlFields[i][0] + '" : {"$lt" : ' + this.mqlFields[i][2] + '}'; - break; - case 'contains': - mql += '"' + this.mqlFields[i][0] + '" : {$regex: \'/.*' + this.mqlFields[i][2] + '.*/i\'}'; - break; - case 'notcontains': - mql += '"' + this.mqlFields[i][0] + '" : {"$not" : /.*' + this.mqlFields[i][2] + '.*/i}'; - break; - case 'type': - mql += '"' + this.mqlFields[i][0] + '" : {"$type" : ' + this.mqlFields[i][2] + '}'; - break; - } - if (isInsideLogicalCondition.length !== 0){ - mql += '}'; + switch (this.mqlType) { + case 'FIND': + mql += 'db.getCollection("' + this.collectionName + '").find({'; + for (let i = 0; i < this.fieldList.length; i++) { + if (this.fieldList[i] === 'AND') { + mql += '$and: ['; + isInsideLogicalCondition.push('AND'); + } + if (this.fieldList[i] === 'OR') { + mql += '$or: ['; + isInsideLogicalCondition.push('OR'); + } + if (this.fieldList[i] !== 'AND' && this.fieldList[i] !== 'OR' && this.fieldList[i] !== 'END') { + if (isInsideLogicalCondition.length !== 0){ + mql += '{'; + } + switch (this.mqlFields[i][1]) { + case 'equal': + mql += '"' + this.mqlFields[i][0] + '" : ' + this.mqlFields[i][2]; + break; + case 'notequal': + mql += '"' + this.mqlFields[i][0] + '" : {"$ne" : ' + this.mqlFields[i][2] + '}'; + break; + case 'greater': + mql += '"' + this.mqlFields[i][0] + '" : {"$gt" : ' + this.mqlFields[i][2] + '}'; + break; + case 'lesser': + mql += '"' + this.mqlFields[i][0] + '" : {"$lt" : ' + this.mqlFields[i][2] + '}'; + break; + case 'contains': + mql += '"' + this.mqlFields[i][0] + '" : {$regex: \'/.*' + this.mqlFields[i][2] + '.*/i\'}'; + break; + case 'notcontains': + mql += '"' + this.mqlFields[i][0] + '" : {"$not" : /.*' + this.mqlFields[i][2] + '.*/i}'; + break; + case 'type': + mql += '"' + this.mqlFields[i][0] + '" : {"$type" : ' + this.mqlFields[i][2] + '}'; + break; + } + if (isInsideLogicalCondition.length !== 0){ + mql += '}'; + } + const fieldListf = this.fieldList.filter((el) => el !== 'AND' && el !== 'OR' && el !== 'END'); + let matchingIndex = -1; + for (let j = 0; j < fieldListf.length; j++) { + if (fieldListf[j] === this.fieldList[i]) { + matchingIndex = j; + } + } + if (matchingIndex + 1 <= fieldListf.length - 1 && matchingIndex !== -1 && this.mqlFields[i][1] !== undefined) { + mql += ', '; + } + } + if (this.fieldList[i] === 'END') { + mql += ']'; + isInsideLogicalCondition.pop(); + } } - const fieldListf = this.fieldList.filter((el) => el !== 'AND' && el !== 'OR' && el !== 'END'); - let matchingIndex = -1; - for (let j = 0; j < fieldListf.length; j++) { - if (fieldListf[j] === this.fieldList[i]) { - matchingIndex = j; + mql += '})'; + this.editorGenerated.setCode(mql); + break; + case 'AGGR': + mql += 'db.getCollection("' + this.collectionName + '").aggregate([{$match: {'; + // Match-Loop + for (let i = 0; i < this.fieldListMATCH.length; i++) { + if (this.fieldListMATCH[i] === 'AND') { + mql += '$and: ['; + isInsideLogicalCondition.push('AND'); + } + if (this.fieldListMATCH[i] === 'OR') { + mql += '$or: ['; + isInsideLogicalCondition.push('OR'); + } + if (this.fieldListMATCH[i] !== 'AND' && this.fieldListMATCH[i] !== 'OR' && this.fieldListMATCH[i] !== 'END') { + if (isInsideLogicalCondition.length !== 0){ + mql += '{'; + } + switch (this.mqlFieldsMATCH[i][1]) { + case 'equal': + mql += '"' + this.mqlFieldsMATCH[i][0] + '" : ' + this.mqlFieldsMATCH[i][2]; + break; + case 'notequal': + mql += '"' + this.mqlFieldsMATCH[i][0] + '" : {"$ne" : ' + this.mqlFieldsMATCH[i][2] + '}'; + break; + case 'greater': + mql += '"' + this.mqlFieldsMATCH[i][0] + '" : {"$gt" : ' + this.mqlFieldsMATCH[i][2] + '}'; + break; + case 'lesser': + mql += '"' + this.mqlFieldsMATCH[i][0] + '" : {"$lt" : ' + this.mqlFieldsMATCH[i][2] + '}'; + break; + case 'contains': + mql += '"' + this.mqlFieldsMATCH[i][0] + '" : {$regex: \'/.*' + this.mqlFieldsMATCH[i][2] + '.*/i\'}'; + break; + case 'notcontains': + mql += '"' + this.mqlFieldsMATCH[i][0] + '" : {"$not" : /.*' + this.mqlFieldsMATCH[i][2] + '.*/i}'; + break; + case 'type': + mql += '"' + this.mqlFieldsMATCH[i][0] + '" : {"$type" : ' + this.mqlFieldsMATCH[i][2] + '}'; + break; + } + if (isInsideLogicalCondition.length !== 0){ + mql += '}'; + } + const fieldListf = this.fieldListMATCH.filter((el) => el !== 'AND' && el !== 'OR' && el !== 'END'); + let matchingIndex = -1; + for (let j = 0; j < fieldListf.length; j++) { + if (fieldListf[j] === this.fieldListMATCH[i]) { + matchingIndex = j; + } + } + if (matchingIndex + 1 <= fieldListf.length - 1 && matchingIndex !== -1 && this.mqlFieldsMATCH[i][1] !== undefined) { + mql += ', '; + } + } + if (this.fieldListMATCH[i] === 'END') { + mql += ']'; + isInsideLogicalCondition.pop(); } } - if (matchingIndex + 1 <= fieldListf.length - 1 && matchingIndex !== -1 && this.mqlFields[i][1] !== undefined) { - mql += ', '; + mql += '},{$group: {'; + //Group-Loop + for (let i = 0; i < this.fieldList.length; i++) { + if (this.fieldListGROUP[i] === 'AND') { + mql += '$and: ['; + isInsideLogicalCondition.push('AND'); + } + if (this.fieldListGROUP[i] === 'OR') { + mql += '$or: ['; + isInsideLogicalCondition.push('OR'); + } + if (this.fieldListGROUP[i] !== 'AND' && this.fieldListGROUP[i] !== 'OR' && this.fieldListGROUP[i] !== 'END') { + if (isInsideLogicalCondition.length !== 0){ + mql += '{'; + } + switch (this.mqlFieldsGROUP[i][1]) { + case 'equal': + mql += '"' + this.mqlFieldsGROUP[i][0] + '" : ' + this.mqlFieldsGROUP[i][2]; + break; + case 'notequal': + mql += '"' + this.mqlFieldsGROUP[i][0] + '" : {"$ne" : ' + this.mqlFieldsGROUP[i][2] + '}'; + break; + case 'greater': + mql += '"' + this.mqlFieldsGROUP[i][0] + '" : {"$gt" : ' + this.mqlFieldsGROUP[i][2] + '}'; + break; + case 'lesser': + mql += '"' + this.mqlFieldsGROUP[i][0] + '" : {"$lt" : ' + this.mqlFieldsGROUP[i][2] + '}'; + break; + case 'contains': + mql += '"' + this.mqlFieldsGROUP[i][0] + '" : {$regex: \'/.*' + this.mqlFieldsGROUP[i][2] + '.*/i\'}'; + break; + case 'notcontains': + mql += '"' + this.mqlFieldsGROUP[i][0] + '" : {"$not" : /.*' + this.mqlFieldsGROUP[i][2] + '.*/i}'; + break; + case 'type': + mql += '"' + this.mqlFieldsGROUP[i][0] + '" : {"$type" : ' + this.mqlFieldsGROUP[i][2] + '}'; + break; + } + if (isInsideLogicalCondition.length !== 0){ + mql += '}'; + } + const fieldListf = this.fieldListGROUP.filter((el) => el !== 'AND' && el !== 'OR' && el !== 'END'); + let matchingIndex = -1; + for (let j = 0; j < fieldListf.length; j++) { + if (fieldListf[j] === this.fieldListGROUP[i]) { + matchingIndex = j; + } + } + if (matchingIndex + 1 <= fieldListf.length - 1 && matchingIndex !== -1 && this.mqlFieldsGROUP[i][1] !== undefined) { + mql += ', '; + } + } + if (this.fieldListGROUP[i] === 'END') { + mql += ']'; + isInsideLogicalCondition.pop(); + } } - } - if (this.fieldList[i] === 'END') { - mql += ']'; - isInsideLogicalCondition.pop(); - } + mql += '}])'; + this.editorGenerated.setCode(mql); + break; } - mql += '})'; - this.editorGenerated.setCode(mql); - console.log(this.fieldList); } async generateSQL() { @@ -852,8 +1359,14 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest executeQuery() { this.loading = true; const code = this.editorGenerated.getCode(); - console.log(code); - console.log(this.activeNamespace); + if (!this._crud.anyQuery(this.webSocket, new QueryRequest(code, false, true, this.lang, this.activeNamespace))) { + this.loading = false; + this.resultSet = new ResultSet('Could not establish a connection with the server.', code); + } + } + + executeCypherFilter(code: string) { + this.loading = true; if (!this._crud.anyQuery(this.webSocket, new QueryRequest(code, false, true, this.lang, this.activeNamespace))) { this.loading = false; this.resultSet = new ResultSet('Could not establish a connection with the server.', code); From e0ea834d7a3af88783effc9d582c244ad360e4bb Mon Sep 17 00:00:00 2001 From: svamel00 Date: Mon, 13 Mar 2023 23:37:55 +0100 Subject: [PATCH 33/60] removed boolean operators and and or from the group stage --- .../graphical-querying.component.html | 17 ----- .../graphical-querying.component.ts | 68 ------------------- 2 files changed, 85 deletions(-) diff --git a/src/app/views/querying/graphical-querying/graphical-querying.component.html b/src/app/views/querying/graphical-querying/graphical-querying.component.html index 76b331ad..38234312 100644 --- a/src/app/views/querying/graphical-querying/graphical-querying.component.html +++ b/src/app/views/querying/graphical-querying/graphical-querying.component.html @@ -617,23 +617,6 @@
    Query Result
    -
  • - -
  • -
    -
  • - -
  • -
    diff --git a/src/app/views/querying/graphical-querying/graphical-querying.component.ts b/src/app/views/querying/graphical-querying/graphical-querying.component.ts index 6952d226..ff34c281 100644 --- a/src/app/views/querying/graphical-querying/graphical-querying.component.ts +++ b/src/app/views/querying/graphical-querying/graphical-querying.component.ts @@ -85,7 +85,6 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest fieldDepthCounterGROUP = 0; logicalDepthCounter = 0; logicalDepthCounterMATCH = 0; - logicalDepthCounterGROUP = 0; // mql input fields mqlFields: any[][] = [['','','','',0,0]]; //mqlText1 = 0, mqlDropdown = 1, mqlText2 = 3, mqlTextX = 4, fieldDepth = 5, logicalDepth = 6 @@ -98,7 +97,6 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest logicalOperatorStack: string[] = []; logicalOperatorStackMATCH: string[] = []; - logicalOperatorStackGROUP: string[] = []; fieldCounter = 0; fieldCounterMATCH = 0; fieldCounterGROUP = 0; @@ -113,7 +111,6 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest show2 = false; showFIND2 = false; showMATCH2 = false; - showGROUP2 = false; private debounce: any; private debounceDelay = 200; @@ -451,10 +448,8 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest this.fieldDepthCounterMATCH = 0; this.logicalDepthCounterMATCH = 0; this.fieldCounterGROUP = 0; - this.logicalOperatorStackGROUP = []; this.fieldListGROUP = ['0']; this.fieldDepthCounterGROUP = 0; - this.logicalDepthCounterGROUP = 0; //cypher this.cypherFields = [[]]; this.cypherReturn = ''; @@ -477,10 +472,8 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest this.fieldDepthCounterMATCH = 0; this.logicalDepthCounterMATCH = 0; this.fieldCounterGROUP = 0; - this.logicalOperatorStackGROUP = []; this.fieldListGROUP = ['0']; this.fieldDepthCounterGROUP = 0; - this.logicalDepthCounterGROUP = 0; break; case 'mql': this.graphName = undefined; @@ -610,19 +603,6 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest this.showMATCH2 = true; } break; - case 'Aggr2': - if (instant) { - this.showGROUP2 = doShow; - return; - } - if (!doShow) { - this.debounce = setTimeout(() => { - this.showGROUP2 = false; - }, this.debounceDelay); - } else { - this.showGROUP2 = true; - } - break; } } @@ -639,11 +619,6 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest clearTimeout(this.debounce); } break; - case 'Aggr2': - if (this.showGROUP2) { - clearTimeout(this.debounce); - } - break; } } @@ -716,7 +691,6 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest this.fieldListGROUP.splice(targetIndex, 0, this.fieldListGROUP.splice(index, 1)[0]); this.mqlFieldsGROUP.splice(targetIndex, 0, this.mqlFieldsGROUP.splice(index, 1)[0]); // Logical Operators - this.logicalOperatorStackGROUP.splice(targetIndex, 0, this.logicalOperatorStackGROUP.splice(index, 1)[0]); } }, 0); } @@ -856,15 +830,6 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest this.mqlFieldsMATCH[this.fieldListMATCH.length - 1][6] = this.logicalDepthCounterMATCH; this.logicalDepthCounterMATCH += 1; break; - case 'Aggr2': - this.fieldCounterGROUP += 1; - this.fieldListGROUP.push(logical); - this.logicalOperatorStackGROUP.push(logical); - this.mqlFieldsGROUP.push([]); - this.mqlFieldsGROUP[this.fieldListGROUP.length - 1][5] = this.fieldDepthCounterGROUP; - this.mqlFieldsGROUP[this.fieldListGROUP.length - 1][6] = this.logicalDepthCounterGROUP; - this.logicalDepthCounterGROUP += 1; - break; } } @@ -888,15 +853,6 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest this.mqlFieldsMATCH[this.fieldListMATCH.length-1][5] = this.fieldDepthCounterMATCH; this.mqlFieldsMATCH[this.fieldListMATCH.length-1][6] = this.logicalDepthCounterMATCH; break; - case 'Aggr2': - this.fieldCounterGROUP += 1; - this.logicalDepthCounterGROUP -= 1; - this.fieldListGROUP.push('END'); - this.logicalOperatorStackGROUP.pop(); - this.mqlFieldsGROUP.push([]); - this.mqlFieldsGROUP[this.fieldListGROUP.length-1][5] = this.fieldDepthCounterGROUP; - this.mqlFieldsGROUP[this.fieldListGROUP.length-1][6] = this.logicalDepthCounterGROUP; - break; } } @@ -1028,10 +984,6 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest this.fieldDepthCounterGROUP = this.mqlFieldsGROUP[x - 1][5]; } this.fieldListGROUP = this.fieldListGROUP.filter((_, index) => !indicesToRemove.includes(index)); - this.logicalOperatorStackGROUP = this.fieldListGROUP.filter((el) => el === 'AND' || el === 'OR' || el === 'END'); - if (indicesToRemove.length === 1) { - this.logicalDepthCounterGROUP -= 1; - } } else { // normal field this.fieldListGROUP.splice(x, 1); @@ -1200,18 +1152,6 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest mql += '},{$group: {'; //Group-Loop for (let i = 0; i < this.fieldList.length; i++) { - if (this.fieldListGROUP[i] === 'AND') { - mql += '$and: ['; - isInsideLogicalCondition.push('AND'); - } - if (this.fieldListGROUP[i] === 'OR') { - mql += '$or: ['; - isInsideLogicalCondition.push('OR'); - } - if (this.fieldListGROUP[i] !== 'AND' && this.fieldListGROUP[i] !== 'OR' && this.fieldListGROUP[i] !== 'END') { - if (isInsideLogicalCondition.length !== 0){ - mql += '{'; - } switch (this.mqlFieldsGROUP[i][1]) { case 'equal': mql += '"' + this.mqlFieldsGROUP[i][0] + '" : ' + this.mqlFieldsGROUP[i][2]; @@ -1235,9 +1175,6 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest mql += '"' + this.mqlFieldsGROUP[i][0] + '" : {"$type" : ' + this.mqlFieldsGROUP[i][2] + '}'; break; } - if (isInsideLogicalCondition.length !== 0){ - mql += '}'; - } const fieldListf = this.fieldListGROUP.filter((el) => el !== 'AND' && el !== 'OR' && el !== 'END'); let matchingIndex = -1; for (let j = 0; j < fieldListf.length; j++) { @@ -1248,11 +1185,6 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest if (matchingIndex + 1 <= fieldListf.length - 1 && matchingIndex !== -1 && this.mqlFieldsGROUP[i][1] !== undefined) { mql += ', '; } - } - if (this.fieldListGROUP[i] === 'END') { - mql += ']'; - isInsideLogicalCondition.pop(); - } } mql += '}])'; this.editorGenerated.setCode(mql); From 7ef36fc2c547124861957512a621a4fc6feef553 Mon Sep 17 00:00:00 2001 From: svamel00 Date: Tue, 14 Mar 2023 11:23:13 +0100 Subject: [PATCH 34/60] added simple query generation for the group stage in the aggregate pipeline --- .../graphical-querying.component.html | 33 +++--------- .../graphical-querying.component.ts | 54 ++++++------------- 2 files changed, 22 insertions(+), 65 deletions(-) diff --git a/src/app/views/querying/graphical-querying/graphical-querying.component.html b/src/app/views/querying/graphical-querying/graphical-querying.component.html index 38234312..3dbe9713 100644 --- a/src/app/views/querying/graphical-querying/graphical-querying.component.html +++ b/src/app/views/querying/graphical-querying/graphical-querying.component.html @@ -540,24 +540,6 @@
    Query Result
    Group stage
    - -
    -
    - {{fieldNumber}} -
    -
    - -
    -
    -
    - -
    -
    - END -
    -
    -
    -
    @@ -572,13 +554,13 @@
    Query Result
    @@ -596,7 +578,6 @@
    Query Result
    -
    diff --git a/src/app/views/querying/graphical-querying/graphical-querying.component.ts b/src/app/views/querying/graphical-querying/graphical-querying.component.ts index ff34c281..a70901b1 100644 --- a/src/app/views/querying/graphical-querying/graphical-querying.component.ts +++ b/src/app/views/querying/graphical-querying/graphical-querying.component.ts @@ -89,7 +89,7 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest mqlFields: any[][] = [['','','','',0,0]]; //mqlText1 = 0, mqlDropdown = 1, mqlText2 = 3, mqlTextX = 4, fieldDepth = 5, logicalDepth = 6 mqlFieldsMATCH: any[][] = [['','','','',0,0]]; - mqlFieldsGROUP: any[][] = [['','','','',0,0]]; + mqlFieldsGROUP: any[][] = [['_id','','','_id',0,0]]; activeNamespace: string; // same usage as console.components.ts collectionName: string; collectionName2: string; @@ -436,7 +436,7 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest //mql this.mqlFields = [['','','','',0,0]]; this.mqlFieldsMATCH = [['','','','',0,0]]; - this.mqlFieldsGROUP = [['','','','',0,0]]; + this.mqlFieldsGROUP = [['_id','','','_id',0,0]]; this.fieldCounter = 0; this.logicalOperatorStack = []; this.fieldList = ['0']; @@ -460,7 +460,7 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest this.collectionName2 = undefined; this.mqlFields = [['','','','',0,0]]; this.mqlFieldsMATCH = [['','','','',0,0]]; - this.mqlFieldsGROUP = [['','','','',0,0]]; + this.mqlFieldsGROUP = [['_id','','','_id',0,0]]; this.fieldCounter = 0; this.logicalOperatorStack = []; this.fieldList = ['0']; @@ -1149,44 +1149,20 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest isInsideLogicalCondition.pop(); } } - mql += '},{$group: {'; + mql += '}, {$group: {'; //Group-Loop - for (let i = 0; i < this.fieldList.length; i++) { - switch (this.mqlFieldsGROUP[i][1]) { - case 'equal': - mql += '"' + this.mqlFieldsGROUP[i][0] + '" : ' + this.mqlFieldsGROUP[i][2]; - break; - case 'notequal': - mql += '"' + this.mqlFieldsGROUP[i][0] + '" : {"$ne" : ' + this.mqlFieldsGROUP[i][2] + '}'; - break; - case 'greater': - mql += '"' + this.mqlFieldsGROUP[i][0] + '" : {"$gt" : ' + this.mqlFieldsGROUP[i][2] + '}'; - break; - case 'lesser': - mql += '"' + this.mqlFieldsGROUP[i][0] + '" : {"$lt" : ' + this.mqlFieldsGROUP[i][2] + '}'; - break; - case 'contains': - mql += '"' + this.mqlFieldsGROUP[i][0] + '" : {$regex: \'/.*' + this.mqlFieldsGROUP[i][2] + '.*/i\'}'; - break; - case 'notcontains': - mql += '"' + this.mqlFieldsGROUP[i][0] + '" : {"$not" : /.*' + this.mqlFieldsGROUP[i][2] + '.*/i}'; - break; - case 'type': - mql += '"' + this.mqlFieldsGROUP[i][0] + '" : {"$type" : ' + this.mqlFieldsGROUP[i][2] + '}'; - break; - } - const fieldListf = this.fieldListGROUP.filter((el) => el !== 'AND' && el !== 'OR' && el !== 'END'); - let matchingIndex = -1; - for (let j = 0; j < fieldListf.length; j++) { - if (fieldListf[j] === this.fieldListGROUP[i]) { - matchingIndex = j; - } - } - if (matchingIndex + 1 <= fieldListf.length - 1 && matchingIndex !== -1 && this.mqlFieldsGROUP[i][1] !== undefined) { - mql += ', '; - } + for (let i = 0; i < this.fieldListGROUP.length; i++) { + if (this.mqlFieldsGROUP[i][0] === '_id') { + mql += '"' + this.mqlFieldsGROUP[i][0] + '" : ' + this.mqlFieldsGROUP[i][2]; + } + else { + mql += '"' + this.mqlFieldsGROUP[i][0] + '" : { ' + this.mqlFieldsGROUP[i][1] + ' : { $' + this.mqlFieldsGROUP[i][2] + ' }}'; + } + if (i < this.mqlFieldsGROUP.length-1) { + mql += ', '; + } } - mql += '}])'; + mql += '}}])'; this.editorGenerated.setCode(mql); break; } From 73d36c1fef2855a71d824d605923dfb08a59f4c9 Mon Sep 17 00:00:00 2001 From: svamel00 Date: Tue, 14 Mar 2023 14:02:28 +0100 Subject: [PATCH 35/60] added tooltips to cypher --- .../graphical-querying.component.html | 31 ++++++++++++------- .../graphical-querying.component.scss | 2 ++ 2 files changed, 21 insertions(+), 12 deletions(-) diff --git a/src/app/views/querying/graphical-querying/graphical-querying.component.html b/src/app/views/querying/graphical-querying/graphical-querying.component.html index 3dbe9713..9a2efae3 100644 --- a/src/app/views/querying/graphical-querying/graphical-querying.component.html +++ b/src/app/views/querying/graphical-querying/graphical-querying.component.html @@ -108,13 +108,17 @@
    Query Result
    -

    Node Labels:

    +
    +

    Node Labels:

    +

    {{label}}

    -

    Relationship Labels:

    +
    +

    Relationship Labels:

    +

    {{label}}

    @@ -133,7 +137,9 @@
    Query Result
    - +
    @@ -152,7 +158,9 @@
    Query Result
    - +
    @@ -350,7 +359,8 @@
    Query Result
    - +
    @@ -408,8 +418,6 @@
    Query Result
    -
    -
    @@ -434,8 +442,8 @@
    Query Result
    + Match stage
    - Match stage
    @@ -537,8 +545,8 @@
    Query Result
    + Group stage
    - Group stage
    @@ -608,6 +616,7 @@
    Query Result
    + Find
    @@ -759,8 +768,6 @@
    Query Result
    - -
    diff --git a/src/app/views/querying/graphical-querying/graphical-querying.component.scss b/src/app/views/querying/graphical-querying/graphical-querying.component.scss index 91a93fb9..6bf7b802 100644 --- a/src/app/views/querying/graphical-querying/graphical-querying.component.scss +++ b/src/app/views/querying/graphical-querying/graphical-querying.component.scss @@ -113,3 +113,5 @@ border: 1px solid black; } + + From 998e57af636a89f22323f0735227ad990c72afba Mon Sep 17 00:00:00 2001 From: svamel00 Date: Tue, 14 Mar 2023 20:36:58 +0100 Subject: [PATCH 36/60] added Modal + text for the find method in mql --- .../graphical-querying.component.html | 134 +++++++++++++++--- .../graphical-querying.component.scss | 5 - .../graphical-querying.component.ts | 8 ++ 3 files changed, 126 insertions(+), 21 deletions(-) diff --git a/src/app/views/querying/graphical-querying/graphical-querying.component.html b/src/app/views/querying/graphical-querying/graphical-querying.component.html index 9a2efae3..a82f01de 100644 --- a/src/app/views/querying/graphical-querying/graphical-querying.component.html +++ b/src/app/views/querying/graphical-querying/graphical-querying.component.html @@ -108,22 +108,46 @@
    Query Result
    -
    -

    Node Labels:

    +
    + Node Labels:

    {{label}}

    -
    -

    Relationship Labels:

    +
    + Relationship Labels:

    {{label}}

    + +
    + + +
    +
    @@ -426,15 +452,87 @@
    Query Result

    Fill in the details:

    -
    -

    Choose what you want to do:

    -
    - - +

    Choose what you want to do:

    +
    +
    +
    + + +
    +
    +
    + + + +
    +
    + + +
    @@ -442,7 +540,9 @@
    Query Result
    - Match stage +
    + Match stage +
    @@ -545,7 +645,9 @@
    Query Result
    - Group stage +
    + Group stage +
    @@ -763,8 +865,8 @@
    Query Result
    -
    +
    diff --git a/src/app/views/querying/graphical-querying/graphical-querying.component.scss b/src/app/views/querying/graphical-querying/graphical-querying.component.scss index 6bf7b802..4ac3601e 100644 --- a/src/app/views/querying/graphical-querying/graphical-querying.component.scss +++ b/src/app/views/querying/graphical-querying/graphical-querying.component.scss @@ -69,9 +69,6 @@ .show-error { display: block !important; } -.label { - margin-bottom:1.5em; -} .cypher-sidebar { background-color: #f0f3f5; @@ -113,5 +110,3 @@ border: 1px solid black; } - - diff --git a/src/app/views/querying/graphical-querying/graphical-querying.component.ts b/src/app/views/querying/graphical-querying/graphical-querying.component.ts index a70901b1..8344aa7d 100644 --- a/src/app/views/querying/graphical-querying/graphical-querying.component.ts +++ b/src/app/views/querying/graphical-querying/graphical-querying.component.ts @@ -20,6 +20,7 @@ import {ViewInformation} from '../../../components/data-view/data-view.component import {TableConfig} from '../../../components/data-view/data-table/table-config'; import * as d3 from 'd3'; + @Component({ selector: 'app-graphical-querying', templateUrl: './graphical-querying.component.html', @@ -118,6 +119,8 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest mqlType: string; + activeMode: string; + ngOnInit() { this._leftSidebar.open(); @@ -427,6 +430,11 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest return '"' + k.split('.').join('"."') + '"'; } + onCloseModal() { + this.activeMode = undefined; + } + + setDefaultState(inputlang: string) { //sets the field values to zero if the user switches languages switch (inputlang) { case 'sql': From f79277ce08a10bd789a92af17d598eaa7b10d416 Mon Sep 17 00:00:00 2001 From: svamel00 Date: Tue, 14 Mar 2023 21:16:39 +0100 Subject: [PATCH 37/60] added Modal + text for cypher --- .../graphical-querying.component.html | 36 ++++++++++++++++--- 1 file changed, 31 insertions(+), 5 deletions(-) diff --git a/src/app/views/querying/graphical-querying/graphical-querying.component.html b/src/app/views/querying/graphical-querying/graphical-querying.component.html index a82f01de..2454126b 100644 --- a/src/app/views/querying/graphical-querying/graphical-querying.component.html +++ b/src/app/views/querying/graphical-querying/graphical-querying.component.html @@ -139,7 +139,33 @@
    @@ -484,11 +510,11 @@ You can begin to build your query by filling in the input fields. Here's an example of a find() query:

    -
    • db.yourCollection.find({{"{" }} "name": "John"})
    - {{ "{" }} "name": "John" } specifies the criteria for selecting documents. In this case, the query will select documents where the value of the name field is equal to "John". +
    • db.yourCollection.find({{"{" }} "name": "John"})
    + {{ "{" }} "name": "John" } specifies the criteria for selecting documents. In this case, the query will select documents where the value of the name field is equal to "John".

    - To recreate this query, you can write name into the first input field. Next, select equals from the dropdown menu. Finally, enter "John" into the last input field. Don't forget the quotation marks if it is a string your looking for. + To recreate this query, you can write name into the first input field. Next, select equals from the dropdown menu. Finally, enter "John" into the last input field. Don't forget the quotation marks if it is a string your looking for.

    Additional Features: @@ -498,9 +524,9 @@
    • Adding new keys: You can add new keys by clicking on the plus-button. To delete a key, click on the trash-button.
    • -
    • Defining key-objects: You can define key-objects by creating a new key and adding sub-keys to it through the plus-button. For example, if you want to add an address key containing sub-keys street and number, you can create a new key address, then add the key-object street, and then the object number to it.
    • +
    • Defining key-objects: You can define key-objects by creating a new key and adding key-objects to it through the plus-button. For example, if you want to add an address key containing objects street and number, you can create a new key address, then add the key-object street, and then the object number to it.
    • -
    • Using Boolean Operators: You can use Boolean Operators (AND, OR) to create more complex conditions. Every Boolean Operator should be closed by an END on the same depth level. You can do this throug the plus-button. You can add multiple Boolean Operators in succession to create nested conditions. Every row between the condition and its END is logically connected.
    • +
    • Using Boolean Operators: You can use Boolean Operators (AND, OR) to create more complex conditions. Every Boolean Operator should be closed by an END on the same depth level. You can do this through the plus-button. You can add multiple Boolean Operators in succession to create nested conditions. Every row between the condition and its END is logically connected.
    • Drag and Drop: You can also drag and drop rows to transfer them inside the logical Operators or insert them into a different order. This can be useful if you made a mistake and need to correct the order of the criteria.
    From c3d32b750a25dde7c280a01834dfe841a6dc3aac Mon Sep 17 00:00:00 2001 From: svamel00 Date: Tue, 14 Mar 2023 22:52:11 +0100 Subject: [PATCH 38/60] added sort stage and added unfinished basic modal text for the moment --- .../graphical-querying.component.html | 116 +++++++++++++++-- .../graphical-querying.component.ts | 123 ++++++++++++++++++ 2 files changed, 231 insertions(+), 8 deletions(-) diff --git a/src/app/views/querying/graphical-querying/graphical-querying.component.html b/src/app/views/querying/graphical-querying/graphical-querying.component.html index 2454126b..22f9e5a0 100644 --- a/src/app/views/querying/graphical-querying/graphical-querying.component.html +++ b/src/app/views/querying/graphical-querying/graphical-querying.component.html @@ -148,7 +148,7 @@
    To recreate this query, you can follow these steps:
      -
    1. In the MATCH input field, type tom:Person
    2. +
    3. In the MATCH input field, type tom:Person {{"{" }}name: "Tom Hanks"}
    4. Select the Relationship Directed from the dropdown menu
    5. Enter ACTED_IN into the first, and tomHanksMovies into the second appearing field
    6. Finally, add tom, tomHanksMovies to the RETURN input field
    7. @@ -510,11 +510,11 @@ You can begin to build your query by filling in the input fields. Here's an example of a find() query:

      -
      • db.yourCollection.find({{"{" }} "name": "John"})
      - {{ "{" }} "name": "John" } specifies the criteria for selecting documents. In this case, the query will select documents where the value of the name field is equal to "John". +
      • db.yourCollection.find({{"{" }} "name": "Jane"})
      + {{ "{" }} "name": "Jane" } specifies the criteria for selecting documents. In this case, the query will select documents where the value of the name field is equal to "Jane".

      - To recreate this query, you can write name into the first input field. Next, select equals from the dropdown menu. Finally, enter "John" into the last input field. Don't forget the quotation marks if it is a string your looking for. + To recreate this query, you can write name into the first input field. Next, select equals from the dropdown menu. Finally, enter "Jane" into the last input field. Don't forget the quotation marks if it is a string your looking for.

      Additional Features: @@ -551,8 +551,52 @@
    -
    +
    @@ -674,7 +719,7 @@
    Group stage
    -
    +
    @@ -692,7 +737,7 @@ +
    +
    +
    +
    +
    + +
    +
    +
    +
    + + +
    +
    +
    + +
    +
    + + +
    +
    +
    diff --git a/src/app/views/querying/graphical-querying/graphical-querying.component.ts b/src/app/views/querying/graphical-querying/graphical-querying.component.ts index 8344aa7d..ed3336d2 100644 --- a/src/app/views/querying/graphical-querying/graphical-querying.component.ts +++ b/src/app/views/querying/graphical-querying/graphical-querying.component.ts @@ -81,9 +81,11 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest fieldList: string[] = ['0']; fieldListMATCH: string[] = ['0']; fieldListGROUP: string[] = ['0']; + fieldListSORT: string[] = ['0']; fieldDepthCounter = 0; fieldDepthCounterMATCH = 0; fieldDepthCounterGROUP = 0; + fieldDepthCounterSORT = 0; logicalDepthCounter = 0; logicalDepthCounterMATCH = 0; // mql input fields @@ -91,6 +93,8 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest mqlFieldsMATCH: any[][] = [['','','','',0,0]]; mqlFieldsGROUP: any[][] = [['_id','','','_id',0,0]]; + + mqlFieldsSORT: any[][] = [['','','','',0,0]]; activeNamespace: string; // same usage as console.components.ts collectionName: string; collectionName2: string; @@ -98,9 +102,11 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest logicalOperatorStack: string[] = []; logicalOperatorStackMATCH: string[] = []; + fieldCounter = 0; fieldCounterMATCH = 0; fieldCounterGROUP = 0; + fieldCounterSORT = 0; private readonly LOCAL_STORAGE_NAMESPACE_KEY = 'polypheny-namespace'; // same usage as console.components.ts // Dropdown @@ -109,9 +115,12 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest showMATCH = false; showGROUP = false; + showSORT = false; + show2 = false; showFIND2 = false; showMATCH2 = false; + showGROUP2 = false; private debounce: any; private debounceDelay = 200; @@ -445,6 +454,7 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest this.mqlFields = [['','','','',0,0]]; this.mqlFieldsMATCH = [['','','','',0,0]]; this.mqlFieldsGROUP = [['_id','','','_id',0,0]]; + this.mqlFieldsSORT = [['_id','','','_id',0,0]]; this.fieldCounter = 0; this.logicalOperatorStack = []; this.fieldList = ['0']; @@ -458,6 +468,9 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest this.fieldCounterGROUP = 0; this.fieldListGROUP = ['0']; this.fieldDepthCounterGROUP = 0; + this.fieldCounterSORT = 0; + this.fieldListSORT = ['0']; + this.fieldDepthCounterSORT = 0; //cypher this.cypherFields = [[]]; this.cypherReturn = ''; @@ -469,6 +482,7 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest this.mqlFields = [['','','','',0,0]]; this.mqlFieldsMATCH = [['','','','',0,0]]; this.mqlFieldsGROUP = [['_id','','','_id',0,0]]; + this.mqlFieldsSORT = [['_id','','','_id',0,0]]; this.fieldCounter = 0; this.logicalOperatorStack = []; this.fieldList = ['0']; @@ -482,6 +496,9 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest this.fieldCounterGROUP = 0; this.fieldListGROUP = ['0']; this.fieldDepthCounterGROUP = 0; + this.fieldCounterSORT = 0; + this.fieldListSORT = ['0']; + this.fieldDepthCounterSORT = 0; break; case 'mql': this.graphName = undefined; @@ -554,6 +571,19 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest this.showGROUP = true; } break; + case 'Aggr3': + if (instant) { + this.showSORT = doShow; + return; + } + if (!doShow) { + this.debounce = setTimeout(() => { + this.showSORT = false; + }, this.debounceDelay); + } else { + this.showSORT = true; + } + break; } } @@ -580,6 +610,11 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest clearTimeout(this.debounce); } break; + case 'Aggr3': + if (this.showSORT) { + clearTimeout(this.debounce); + } + break; } } @@ -704,6 +739,23 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest } this.generateMQL(); break; + case 'Aggr3': + if (data) { + const index = this.fieldListSORT.indexOf(data); + const targetElement = event.currentTarget as HTMLElement; + setTimeout(() => { + const rect = targetElement.getBoundingClientRect(); + const mouseY = rect.top - this.initialrect.top; + const targetIndex = Math.round(mouseY / rect.height) + index; + if (index !== -1 && targetIndex !== -1 && index !== targetIndex) { + this.fieldListSORT.splice(targetIndex, 0, this.fieldListSORT.splice(index, 1)[0]); + this.mqlFieldsSORT.splice(targetIndex, 0, this.mqlFieldsSORT.splice(index, 1)[0]); + // Logical Operators + } + }, 0); + } + this.generateMQL(); + break; } } @@ -757,6 +809,14 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest this.mqlFieldsGROUP[this.fieldListGROUP.length-1][5] = 0; this.mqlFieldsGROUP[this.fieldListGROUP.length-1][6] = -1; break; + case 'Aggr3': + this.fieldCounterSORT += 1; + this.fieldListSORT.push(String(this.fieldCounterSORT)); + this.fieldDepthCounterSORT = 0; + this.mqlFieldsSORT.push([]); + this.mqlFieldsSORT[this.fieldListSORT.length-1][5] = 0; + this.mqlFieldsSORT[this.fieldListSORT.length-1][6] = -1; + break; } } @@ -789,6 +849,15 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest this.mqlFieldsGROUP[this.fieldListGROUP.length-1][5] = this.fieldDepthCounterGROUP; this.mqlFieldsGROUP[this.fieldListGROUP.length-1][6] = -1; break; + case 'Aggr3': + this.mqlFieldsSORT[this.fieldCounterSORT][1] = undefined; + this.fieldCounterSORT += 1; + this.fieldDepthCounterSORT += 1; + this.fieldListSORT.push(String(this.fieldCounterSORT)); + this.mqlFieldsSORT.push([]); + this.mqlFieldsSORT[this.fieldListSORT.length-1][5] = this.fieldDepthCounterSORT; + this.mqlFieldsSORT[this.fieldListSORT.length-1][6] = -1; + break; } } @@ -815,6 +884,13 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest this.mqlFieldsGROUP[this.fieldListGROUP.length - 1][5] = this.fieldDepthCounterGROUP; this.mqlFieldsGROUP[this.fieldListGROUP.length - 1][6] = -1; break; + case 'Aggr3': + this.fieldCounterSORT += 1; + this.fieldListSORT.push(String(this.fieldCounterSORT)); + this.mqlFieldsSORT.push([]); + this.mqlFieldsSORT[this.fieldListSORT.length - 1][5] = this.fieldDepthCounterSORT; + this.mqlFieldsSORT[this.fieldListSORT.length - 1][6] = -1; + break; } } @@ -900,6 +976,17 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest } this.mqlFieldsGROUP[index][0] = prependText + this.mqlFieldsGROUP[index][3]; break; + case 'Aggr3': + if (depth !== 0) { + for (let i = this.mqlFieldsSORT.length - 1; i >= 0; i--) { + if (this.mqlFieldsSORT[i][5] < depth) { + prependText += this.mqlFieldsSORT[i][0] + '.'; + break; + } + } + } + this.mqlFieldsSORT[index][0] = prependText + this.mqlFieldsSORT[index][3]; + break; } } @@ -1003,6 +1090,34 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest } this.generateMQL(); break; + case 'Aggr3': + if (this.fieldListSORT[x] === 'AND' || this.fieldListSORT[x] === 'OR' || this.fieldListSORT[x] === 'END') { + const indicesToRemove = []; + for (let i = x; i < this.fieldListSORT.length; i++) { + if (this.mqlFieldsSORT[i][6] === this.mqlFieldsSORT[x][6]) { + indicesToRemove.push(i); + } + if (indicesToRemove.length === 2) { + break; + } + } + this.mqlFieldsSORT = this.mqlFieldsSORT.filter((_, index) => !indicesToRemove.includes(index)); + this.fieldCounterSORT = this.fieldCounterSORT - indicesToRemove.length; + if (indicesToRemove[1] === this.fieldListSORT.length && x !== 0) { + this.fieldDepthCounterSORT = this.mqlFieldsSORT[x - 1][5]; + } + this.fieldListSORT = this.fieldListSORT.filter((_, index) => !indicesToRemove.includes(index)); + } + else { // normal field + this.fieldListSORT.splice(x, 1); + this.mqlFieldsSORT.splice(x, 1); + this.fieldCounterSORT -= 1; + if (x === this.fieldListSORT.length && x !== 0) { + this.fieldDepthCounterSORT = this.mqlFieldsSORT[x-1][5]; + } + } + this.generateMQL(); + break; } } @@ -1170,6 +1285,14 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest mql += ', '; } } + mql += '}}, {$sort: {'; + //Sort-Loop + for (let i = 0; i < this.fieldListSORT.length; i++) { + mql += '"' + this.mqlFieldsSORT[i][0] + '" : ' + this.mqlFieldsSORT[i][1]; + if (i < this.mqlFieldsSORT.length-1) { + mql += ', '; + } + } mql += '}}])'; this.editorGenerated.setCode(mql); break; From 48fd764c0e8394e4a7d69b7c55f0d0b8a4747fcc Mon Sep 17 00:00:00 2001 From: svamel00 Date: Wed, 15 Mar 2023 17:15:28 +0100 Subject: [PATCH 39/60] added dynamic return fields --- .../graphical-querying.component.html | 16 ++++++---- .../graphical-querying.component.ts | 29 +++++++++++++++---- 2 files changed, 33 insertions(+), 12 deletions(-) diff --git a/src/app/views/querying/graphical-querying/graphical-querying.component.html b/src/app/views/querying/graphical-querying/graphical-querying.component.html index 22f9e5a0..5abdf7f5 100644 --- a/src/app/views/querying/graphical-querying/graphical-querying.component.html +++ b/src/app/views/querying/graphical-querying/graphical-querying.component.html @@ -405,17 +405,21 @@
    -
    -
    +
    +
    -
    -
    - +
    +
    + + +
    diff --git a/src/app/views/querying/graphical-querying/graphical-querying.component.ts b/src/app/views/querying/graphical-querying/graphical-querying.component.ts index ed3336d2..cd46573c 100644 --- a/src/app/views/querying/graphical-querying/graphical-querying.component.ts +++ b/src/app/views/querying/graphical-querying/graphical-querying.component.ts @@ -74,9 +74,9 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest config: TableConfig; // cypher input fields cypherFields: string[][] = [[]]; // Matrix à [n,5] size -> [1] = Relationship, [2] = Node, [3] = 2.Relationship, [4] = 2.Node - cypherReturn = ''; + cypherReturn: string[] = ['']; + cypherReturn2: string[] = ['']; cypherDropdown: string[] = []; - //cypherRelationship: string[] = ['','','','']; // [0] = Relationship, [1] = Node, [2] = 2.Relationship, [3] = 2.Node fieldListCypher: string[] = ['MATCH']; fieldList: string[] = ['0']; fieldListMATCH: string[] = ['0']; @@ -473,7 +473,8 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest this.fieldDepthCounterSORT = 0; //cypher this.cypherFields = [[]]; - this.cypherReturn = ''; + this.cypherReturn = ['']; + this.cypherReturn2 = ['']; this.fieldListCypher = ['MATCH']; break; case 'cypher': @@ -503,7 +504,8 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest case 'mql': this.graphName = undefined; this.cypherFields = [[]]; - this.cypherReturn = ''; + this.cypherReturn = ['']; + this.cypherReturn2 = ['']; this.fieldListCypher = ['MATCH']; break; } @@ -1146,7 +1148,13 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest } cypher += '\n'; } - cypher += 'RETURN ' + this.cypherReturn + ';'; + cypher += 'RETURN '; + for (let i = 0; i < this.cypherReturn.length; i++) { + cypher += this.cypherReturn[i]; + if (i < this.cypherReturn.length - 1) { + cypher += ', '; + } + } this.editorGenerated.setCode(cypher); } @@ -1404,8 +1412,17 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest } } - executeCypherFilter(code: string) { + executeCypherFilter() { this.loading = true; + let code = this.editorGenerated.getCode(); + code += ', \n'; + for (let i = 0; i < this.cypherReturn.length; i++) { + code += 'DISTINCT LABELS(' + this.cypherReturn[i] +') as test'; + if (i < this.cypherReturn.length-1) { + code += ',\n'; + } + } + console.log(code); if (!this._crud.anyQuery(this.webSocket, new QueryRequest(code, false, true, this.lang, this.activeNamespace))) { this.loading = false; this.resultSet = new ResultSet('Could not establish a connection with the server.', code); From 9724cdef204a458b8b6af2ad5887388de27c11a7 Mon Sep 17 00:00:00 2001 From: svamel00 Date: Wed, 15 Mar 2023 17:57:38 +0100 Subject: [PATCH 40/60] corrected small logical operator bug for mql --- .../graphical-querying/graphical-querying.component.html | 2 +- .../graphical-querying/graphical-querying.component.ts | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/app/views/querying/graphical-querying/graphical-querying.component.html b/src/app/views/querying/graphical-querying/graphical-querying.component.html index 5abdf7f5..b18ba8b7 100644 --- a/src/app/views/querying/graphical-querying/graphical-querying.component.html +++ b/src/app/views/querying/graphical-querying/graphical-querying.component.html @@ -698,7 +698,7 @@
  • -
    +
    +
    +
    +
    +
    + +
    + +
    +
    +
    +
    +
    + +
    +
    +
    +
    +
    +
    @@ -769,6 +791,7 @@
    +
    diff --git a/src/app/views/querying/graphical-querying/graphical-querying.component.ts b/src/app/views/querying/graphical-querying/graphical-querying.component.ts index ccd8fd5e..1379579e 100644 --- a/src/app/views/querying/graphical-querying/graphical-querying.component.ts +++ b/src/app/views/querying/graphical-querying/graphical-querying.component.ts @@ -454,7 +454,7 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest this.mqlFields = [['','','','',0,0]]; this.mqlFieldsMATCH = [['','','','',0,0]]; this.mqlFieldsGROUP = [['_id','','','_id',0,0]]; - this.mqlFieldsSORT = [['_id','','','_id',0,0]]; + this.mqlFieldsSORT = [['','','','',0,0]]; this.fieldCounter = 0; this.logicalOperatorStack = []; this.fieldList = ['0']; @@ -483,7 +483,7 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest this.mqlFields = [['','','','',0,0]]; this.mqlFieldsMATCH = [['','','','',0,0]]; this.mqlFieldsGROUP = [['_id','','','_id',0,0]]; - this.mqlFieldsSORT = [['_id','','','_id',0,0]]; + this.mqlFieldsSORT = [['','','','',0,0]]; this.fieldCounter = 0; this.logicalOperatorStack = []; this.fieldList = ['0']; From 82a45a0e82d2193bf3f863fccd925d36fe55b631 Mon Sep 17 00:00:00 2001 From: svamel00 Date: Wed, 22 Mar 2023 16:18:13 +0100 Subject: [PATCH 43/60] changed getColletion() to directly the collection --- .../graphical-querying/graphical-querying.component.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/app/views/querying/graphical-querying/graphical-querying.component.ts b/src/app/views/querying/graphical-querying/graphical-querying.component.ts index 1379579e..2f0d7e70 100644 --- a/src/app/views/querying/graphical-querying/graphical-querying.component.ts +++ b/src/app/views/querying/graphical-querying/graphical-querying.component.ts @@ -1163,7 +1163,7 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest const isInsideLogicalCondition = []; switch (this.mqlType) { case 'FIND': - mql += 'db.getCollection("' + this.collectionName + '").find({'; + mql += 'db.' + this.collectionName + '.find({'; for (let i = 0; i < this.fieldList.length; i++) { if (this.fieldList[i] === 'AND') { mql += '$and: ['; @@ -1223,7 +1223,7 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest this.editorGenerated.setCode(mql); break; case 'AGGR': - mql += 'db.getCollection("' + this.collectionName + '").aggregate([{$match: {'; + mql += 'db.' + this.collectionName + '.aggregate([{$match: {'; // Match-Loop for (let i = 0; i < this.fieldListMATCH.length; i++) { if (this.fieldListMATCH[i] === 'AND') { From cd2b7375da07b52befa6278fae043cc817cb1b98 Mon Sep 17 00:00:00 2001 From: svamel00 Date: Wed, 22 Mar 2023 22:07:19 +0100 Subject: [PATCH 44/60] created one cypher property field modal for match --- .../graphical-querying.component.html | 80 ++++++++++++++++++- .../graphical-querying.component.ts | 75 ++++++++++++++++- 2 files changed, 153 insertions(+), 2 deletions(-) diff --git a/src/app/views/querying/graphical-querying/graphical-querying.component.html b/src/app/views/querying/graphical-querying/graphical-querying.component.html index 35b6966c..f1363517 100644 --- a/src/app/views/querying/graphical-querying/graphical-querying.component.html +++ b/src/app/views/querying/graphical-querying/graphical-querying.component.html @@ -192,7 +192,85 @@ >MATCH
    + [(ngModel)]="cypherFields[i][0]" (click)="this.matchModal.show();" placeholder="Node"> + +
    diff --git a/src/app/views/querying/graphical-querying/graphical-querying.component.ts b/src/app/views/querying/graphical-querying/graphical-querying.component.ts index 2f0d7e70..b3b24df4 100644 --- a/src/app/views/querying/graphical-querying/graphical-querying.component.ts +++ b/src/app/views/querying/graphical-querying/graphical-querying.component.ts @@ -74,10 +74,14 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest config: TableConfig; // cypher input fields cypherFields: string[][] = [[]]; // Matrix à [n,5] size -> [1] = Relationship, [2] = Node, [3] = 2.Relationship, [4] = 2.Node + + cypherMatch: string[][] = [[]]; cypherReturn: string[] = ['']; cypherReturn2: string[] = ['']; cypherDropdown: string[] = []; fieldListCypher: string[] = ['MATCH']; + + fieldListCypherMatch: string[] = ['NODE']; fieldList: string[] = ['0']; fieldListMATCH: string[] = ['0']; fieldListGROUP: string[] = ['0']; @@ -112,6 +116,7 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest // Dropdown show = false; showFIND = false; + showCypherMatch = false; showMATCH = false; showGROUP = false; @@ -473,9 +478,11 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest this.fieldDepthCounterSORT = 0; //cypher this.cypherFields = [[]]; + this.cypherMatch = [[]]; this.cypherReturn = ['']; this.cypherReturn2 = ['']; this.fieldListCypher = ['MATCH']; + this.fieldListCypherMatch = ['NODE']; break; case 'cypher': this.collectionName = undefined; @@ -504,9 +511,11 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest case 'mql': this.graphName = undefined; this.cypherFields = [[]]; + this.cypherMatch = [[]]; this.cypherReturn = ['']; this.cypherReturn2 = ['']; this.fieldListCypher = ['MATCH']; + this.fieldListCypherMatch = ['NODE']; break; } } @@ -534,6 +543,19 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest this.show = true; } break; + case 'CypherMatch': + if (instant) { + this.showCypherMatch = doShow; + return; + } + if (!doShow) { + this.debounce = setTimeout(() => { + this.showCypherMatch = false; + }, this.debounceDelay); + } else { + this.showCypherMatch = true; + } + break; case 'Find': if (instant) { this.showFIND = doShow; @@ -774,6 +796,11 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest this.cypherFields.push([]); } + addCypherMatchField(type: string) { + this.fieldListCypherMatch.push(type); + this.cypherMatch.push([]); + } + changeCypherField(type: string, index: number) { if (index + 1 > this.fieldListCypher.length-1) { this.fieldListCypher.push(type); @@ -998,6 +1025,11 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest this.generateCypher(); } + deleteCypherMatchField(x:number) { + this.fieldListCypherMatch.splice(x, 1); + this.cypherMatch.splice(x, 1); + } + deleteMQLField(x:number, mqlCase:string) { switch (mqlCase) { case 'Find': @@ -1123,11 +1155,52 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest } } + async generateMatch(index: number) { + this.cypherFields[index][0] = ''; + const nodeStack = []; + const propertyStack = []; + // generate the content of the field + for (let i = 0; i < this.fieldListCypherMatch.length; i++) { + if (this.fieldListCypherMatch[i] === 'NODE') { // Node Element + if (nodeStack.pop() !== undefined) { + if (propertyStack.pop() !== undefined) { + this.cypherFields[index][0] += '}'; + } + this.cypherFields[index][0] += '),'; + } + if (this.cypherMatch[i][1] === '') { // dropdown is empty + this.cypherFields[index][0] += '(' + this.cypherMatch[i][0]; + } + else { // dropdown is not empty and label + this.cypherFields[index][0] += '(' + this.cypherMatch[i][0] + ':' + this.cypherMatch[i][1]; + } + nodeStack.push(1); + } + else { // Property Element + if (propertyStack.length === 0) { + this.cypherFields[index][0] += '{'; + propertyStack.push(1); + } + this.cypherFields[index][0] += this.cypherMatch[i][0] + ':' + this.cypherMatch[i][1]; + if (i < this.fieldListCypherMatch.length - 1 && this.fieldListCypherMatch[i+1] !== 'NODE') { + this.cypherFields[index][0] += ','; + } + } + } + if (propertyStack.pop() !== undefined) { + this.cypherFields[index][0] += '}'; + } + if (this.fieldListCypherMatch.length > 0) { + this.cypherFields[index][0] += ')'; + } + this.generateCypher(); + } + async generateCypher() { let cypher = ''; for (let i = 0; i < this.fieldListCypher.length; i++) { if (this.fieldListCypher[i] === 'MATCH') { - cypher += 'MATCH ' + '(' + this.cypherFields[i][0] + ')'; + cypher += 'MATCH ' + this.cypherFields[i][0]; switch (this.cypherDropdown[i]) { case 'cypher-outgoing': cypher += '-->(' + this.cypherFields[i][2] + ')'; From 491fe8485d0f8ddc3b6031faaab102f9bd39572b Mon Sep 17 00:00:00 2001 From: svamel00 Date: Wed, 22 Mar 2023 22:07:19 +0100 Subject: [PATCH 45/60] made the modal more beautiful and added some tooltips --- .../graphical-querying.component.html | 91 ++++++++++++++++++- .../graphical-querying.component.ts | 75 ++++++++++++++- 2 files changed, 164 insertions(+), 2 deletions(-) diff --git a/src/app/views/querying/graphical-querying/graphical-querying.component.html b/src/app/views/querying/graphical-querying/graphical-querying.component.html index 35b6966c..8261f191 100644 --- a/src/app/views/querying/graphical-querying/graphical-querying.component.html +++ b/src/app/views/querying/graphical-querying/graphical-querying.component.html @@ -192,7 +192,96 @@ >MATCH
    + [(ngModel)]="cypherFields[i][0]" (click)="this.matchModal.show();" placeholder="Node"> + +
  • diff --git a/src/app/views/querying/graphical-querying/graphical-querying.component.ts b/src/app/views/querying/graphical-querying/graphical-querying.component.ts index 2f0d7e70..b3b24df4 100644 --- a/src/app/views/querying/graphical-querying/graphical-querying.component.ts +++ b/src/app/views/querying/graphical-querying/graphical-querying.component.ts @@ -74,10 +74,14 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest config: TableConfig; // cypher input fields cypherFields: string[][] = [[]]; // Matrix à [n,5] size -> [1] = Relationship, [2] = Node, [3] = 2.Relationship, [4] = 2.Node + + cypherMatch: string[][] = [[]]; cypherReturn: string[] = ['']; cypherReturn2: string[] = ['']; cypherDropdown: string[] = []; fieldListCypher: string[] = ['MATCH']; + + fieldListCypherMatch: string[] = ['NODE']; fieldList: string[] = ['0']; fieldListMATCH: string[] = ['0']; fieldListGROUP: string[] = ['0']; @@ -112,6 +116,7 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest // Dropdown show = false; showFIND = false; + showCypherMatch = false; showMATCH = false; showGROUP = false; @@ -473,9 +478,11 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest this.fieldDepthCounterSORT = 0; //cypher this.cypherFields = [[]]; + this.cypherMatch = [[]]; this.cypherReturn = ['']; this.cypherReturn2 = ['']; this.fieldListCypher = ['MATCH']; + this.fieldListCypherMatch = ['NODE']; break; case 'cypher': this.collectionName = undefined; @@ -504,9 +511,11 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest case 'mql': this.graphName = undefined; this.cypherFields = [[]]; + this.cypherMatch = [[]]; this.cypherReturn = ['']; this.cypherReturn2 = ['']; this.fieldListCypher = ['MATCH']; + this.fieldListCypherMatch = ['NODE']; break; } } @@ -534,6 +543,19 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest this.show = true; } break; + case 'CypherMatch': + if (instant) { + this.showCypherMatch = doShow; + return; + } + if (!doShow) { + this.debounce = setTimeout(() => { + this.showCypherMatch = false; + }, this.debounceDelay); + } else { + this.showCypherMatch = true; + } + break; case 'Find': if (instant) { this.showFIND = doShow; @@ -774,6 +796,11 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest this.cypherFields.push([]); } + addCypherMatchField(type: string) { + this.fieldListCypherMatch.push(type); + this.cypherMatch.push([]); + } + changeCypherField(type: string, index: number) { if (index + 1 > this.fieldListCypher.length-1) { this.fieldListCypher.push(type); @@ -998,6 +1025,11 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest this.generateCypher(); } + deleteCypherMatchField(x:number) { + this.fieldListCypherMatch.splice(x, 1); + this.cypherMatch.splice(x, 1); + } + deleteMQLField(x:number, mqlCase:string) { switch (mqlCase) { case 'Find': @@ -1123,11 +1155,52 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest } } + async generateMatch(index: number) { + this.cypherFields[index][0] = ''; + const nodeStack = []; + const propertyStack = []; + // generate the content of the field + for (let i = 0; i < this.fieldListCypherMatch.length; i++) { + if (this.fieldListCypherMatch[i] === 'NODE') { // Node Element + if (nodeStack.pop() !== undefined) { + if (propertyStack.pop() !== undefined) { + this.cypherFields[index][0] += '}'; + } + this.cypherFields[index][0] += '),'; + } + if (this.cypherMatch[i][1] === '') { // dropdown is empty + this.cypherFields[index][0] += '(' + this.cypherMatch[i][0]; + } + else { // dropdown is not empty and label + this.cypherFields[index][0] += '(' + this.cypherMatch[i][0] + ':' + this.cypherMatch[i][1]; + } + nodeStack.push(1); + } + else { // Property Element + if (propertyStack.length === 0) { + this.cypherFields[index][0] += '{'; + propertyStack.push(1); + } + this.cypherFields[index][0] += this.cypherMatch[i][0] + ':' + this.cypherMatch[i][1]; + if (i < this.fieldListCypherMatch.length - 1 && this.fieldListCypherMatch[i+1] !== 'NODE') { + this.cypherFields[index][0] += ','; + } + } + } + if (propertyStack.pop() !== undefined) { + this.cypherFields[index][0] += '}'; + } + if (this.fieldListCypherMatch.length > 0) { + this.cypherFields[index][0] += ')'; + } + this.generateCypher(); + } + async generateCypher() { let cypher = ''; for (let i = 0; i < this.fieldListCypher.length; i++) { if (this.fieldListCypher[i] === 'MATCH') { - cypher += 'MATCH ' + '(' + this.cypherFields[i][0] + ')'; + cypher += 'MATCH ' + this.cypherFields[i][0]; switch (this.cypherDropdown[i]) { case 'cypher-outgoing': cypher += '-->(' + this.cypherFields[i][2] + ')'; From 8a244ce9ea59f5faa83bb036d8faeeb20af2f066 Mon Sep 17 00:00:00 2001 From: svamel00 Date: Thu, 23 Mar 2023 20:05:33 +0100 Subject: [PATCH 46/60] made the match modal to adapt dynamically per added match field --- .../graphical-querying.component.html | 18 ++++---- .../graphical-querying.component.ts | 44 ++++++++++--------- 2 files changed, 33 insertions(+), 29 deletions(-) diff --git a/src/app/views/querying/graphical-querying/graphical-querying.component.html b/src/app/views/querying/graphical-querying/graphical-querying.component.html index 8261f191..89907d09 100644 --- a/src/app/views/querying/graphical-querying/graphical-querying.component.html +++ b/src/app/views/querying/graphical-querying/graphical-querying.component.html @@ -218,7 +218,7 @@
    -
    +

    @@ -226,17 +226,17 @@
    + [(ngModel)]="cypherMatch[i][j][0]" (keyup)="generateMatch(i);" placeholder="Node">
    -
    - +
    @@ -246,15 +246,15 @@
    + [(ngModel)]="cypherMatch[i][j][0]" (keyup)="generateMatch(i)" placeholder="Property">
    + [(ngModel)]="cypherMatch[i][j][1]" (keyup)="generateMatch(i);" placeholder="equals value">
    - +
    @@ -267,10 +267,10 @@ class="fa fa-plus">
    diff --git a/src/app/views/querying/graphical-querying/graphical-querying.component.ts b/src/app/views/querying/graphical-querying/graphical-querying.component.ts index b3b24df4..d840fc42 100644 --- a/src/app/views/querying/graphical-querying/graphical-querying.component.ts +++ b/src/app/views/querying/graphical-querying/graphical-querying.component.ts @@ -75,13 +75,13 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest // cypher input fields cypherFields: string[][] = [[]]; // Matrix à [n,5] size -> [1] = Relationship, [2] = Node, [3] = 2.Relationship, [4] = 2.Node - cypherMatch: string[][] = [[]]; + cypherMatch: string[][][] = [[[]]]; cypherReturn: string[] = ['']; cypherReturn2: string[] = ['']; cypherDropdown: string[] = []; fieldListCypher: string[] = ['MATCH']; - fieldListCypherMatch: string[] = ['NODE']; + fieldListCypherMatch: string[][] = [['NODE']]; fieldList: string[] = ['0']; fieldListMATCH: string[] = ['0']; fieldListGROUP: string[] = ['0']; @@ -478,11 +478,11 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest this.fieldDepthCounterSORT = 0; //cypher this.cypherFields = [[]]; - this.cypherMatch = [[]]; + this.cypherMatch = [[[]]]; this.cypherReturn = ['']; this.cypherReturn2 = ['']; this.fieldListCypher = ['MATCH']; - this.fieldListCypherMatch = ['NODE']; + this.fieldListCypherMatch = [['NODE']]; break; case 'cypher': this.collectionName = undefined; @@ -511,11 +511,11 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest case 'mql': this.graphName = undefined; this.cypherFields = [[]]; - this.cypherMatch = [[]]; + this.cypherMatch = [[[]]]; this.cypherReturn = ['']; this.cypherReturn2 = ['']; this.fieldListCypher = ['MATCH']; - this.fieldListCypherMatch = ['NODE']; + this.fieldListCypherMatch = [['NODE']]; break; } } @@ -794,11 +794,15 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest addCypherField(type: string) { this.fieldListCypher.push(type); this.cypherFields.push([]); + if (type === 'MATCH') { + this.fieldListCypherMatch.push(['NODE']); + this.cypherMatch.push([[]]); + } } - addCypherMatchField(type: string) { - this.fieldListCypherMatch.push(type); - this.cypherMatch.push([]); + addCypherMatchField(index: number, type: string) { + this.fieldListCypherMatch[index].push(type); + this.cypherMatch[index].push([]); } changeCypherField(type: string, index: number) { @@ -1025,9 +1029,9 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest this.generateCypher(); } - deleteCypherMatchField(x:number) { - this.fieldListCypherMatch.splice(x, 1); - this.cypherMatch.splice(x, 1); + deleteCypherMatchField(index: number, x:number) { + this.fieldListCypherMatch[index].splice(x, 1); + this.cypherMatch[index].splice(x, 1); } deleteMQLField(x:number, mqlCase:string) { @@ -1160,19 +1164,19 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest const nodeStack = []; const propertyStack = []; // generate the content of the field - for (let i = 0; i < this.fieldListCypherMatch.length; i++) { - if (this.fieldListCypherMatch[i] === 'NODE') { // Node Element + for (let i = 0; i < this.fieldListCypherMatch[index].length; i++) { + if (this.fieldListCypherMatch[index][i] === 'NODE') { // Node Element if (nodeStack.pop() !== undefined) { if (propertyStack.pop() !== undefined) { this.cypherFields[index][0] += '}'; } this.cypherFields[index][0] += '),'; } - if (this.cypherMatch[i][1] === '') { // dropdown is empty - this.cypherFields[index][0] += '(' + this.cypherMatch[i][0]; + if (this.cypherMatch[index][i][1] === '') { // dropdown is empty + this.cypherFields[index][0] += '(' + this.cypherMatch[index][i][0]; } else { // dropdown is not empty and label - this.cypherFields[index][0] += '(' + this.cypherMatch[i][0] + ':' + this.cypherMatch[i][1]; + this.cypherFields[index][0] += '(' + this.cypherMatch[index][i][0] + ':' + this.cypherMatch[index][i][1]; } nodeStack.push(1); } @@ -1181,8 +1185,8 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest this.cypherFields[index][0] += '{'; propertyStack.push(1); } - this.cypherFields[index][0] += this.cypherMatch[i][0] + ':' + this.cypherMatch[i][1]; - if (i < this.fieldListCypherMatch.length - 1 && this.fieldListCypherMatch[i+1] !== 'NODE') { + this.cypherFields[index][0] += this.cypherMatch[index][i][0] + ':' + this.cypherMatch[index][i][1]; + if (i < this.fieldListCypherMatch[index].length - 1 && this.fieldListCypherMatch[index][i+1] !== 'NODE') { this.cypherFields[index][0] += ','; } } @@ -1190,7 +1194,7 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest if (propertyStack.pop() !== undefined) { this.cypherFields[index][0] += '}'; } - if (this.fieldListCypherMatch.length > 0) { + if (this.fieldListCypherMatch[index].length > 0) { this.cypherFields[index][0] += ')'; } this.generateCypher(); From 7f5e5cb03578eb376a5a4b109094825c8817d7fe Mon Sep 17 00:00:00 2001 From: svamel00 Date: Fri, 24 Mar 2023 00:51:29 +0100 Subject: [PATCH 47/60] input for nodes inside match modal is differentiated between field --- .../graphical-querying.component.html | 331 ++++++++++++++++-- .../graphical-querying.component.ts | 192 +++++++--- 2 files changed, 444 insertions(+), 79 deletions(-) diff --git a/src/app/views/querying/graphical-querying/graphical-querying.component.html b/src/app/views/querying/graphical-querying/graphical-querying.component.html index 89907d09..1b28a6fc 100644 --- a/src/app/views/querying/graphical-querying/graphical-querying.component.html +++ b/src/app/views/querying/graphical-querying/graphical-querying.component.html @@ -173,13 +173,6 @@
    - - - - - -
    @@ -192,7 +185,7 @@ >MATCH
    + [(ngModel)]="cypherFields[i][0]" (click)="this.matchModal.show();" placeholder="Node" autocomplete="off">
    - -
    + +

    @@ -226,17 +219,17 @@
    + [(ngModel)]="cypherNode[i][j][0]" (keyup)="generateMatch(i,1);" placeholder="Node" autocomplete="off">
    -
    - +
    @@ -246,15 +239,15 @@
    + [(ngModel)]="cypherNode[i][j][0]" (keyup)="generateMatch(i,1)" placeholder="Property" autocomplete="off">
    + [(ngModel)]="cypherNode[i][j][1]" (keyup)="generateMatch(i,1);" placeholder="equals value" autocomplete="off">
    - +
    @@ -267,10 +260,10 @@ class="fa fa-plus">
    @@ -315,13 +308,102 @@
    + [(ngModel)]="cypherFields[i][2]" (click)="this.matchModal2.show();" placeholder="Node" autocomplete="off"> + +
    + [(ngModel)]="cypherFields[i][1]" (keyup)="generateCypher()" placeholder="Relationship" autocomplete="off">
    @@ -329,7 +411,96 @@
    + [(ngModel)]="cypherFields[i][2]" (click)="this.matchModal2.show();" placeholder="Node" autocomplete="off"> + +
    @@ -341,7 +512,7 @@
    + [(ngModel)]="cypherFields[i][3]" (keyup)="generateCypher()" placeholder="2. Relationship" autocomplete="off">
    @@ -349,7 +520,95 @@
    + [(ngModel)]="cypherFields[i][4]" (click)="this.matchModal3.show()" placeholder="2. Node" autocomplete="off"> +
    @@ -365,7 +624,7 @@ >WHERE
    + [(ngModel)]="cypherFields[i][0]" (keyup)="generateCypher()" autocomplete="off">
    @@ -395,7 +654,7 @@
    + [(ngModel)]="cypherFields[i][2]" (keyup)="generateCypher()" placeholder="value" autocomplete="off">
    @@ -423,7 +682,7 @@
    + [(ngModel)]="cypherFields[i][0]" (keyup)="generateCypher()" autocomplete="off">
    @@ -453,7 +712,7 @@
    + [(ngModel)]="cypherFields[i][2]" (keyup)="generateCypher()" placeholder="value" autocomplete="off">
    @@ -502,7 +761,7 @@ >RETURN
    + [(ngModel)]="cypherReturn[i]" (keyup)="generateCypher()" autocomplete="off">
    @@ -740,7 +999,7 @@
    + [(ngModel)]="mqlFieldsMATCH[i][3]" (keyup)="prependKeyObject(this.mqlFieldsMATCH[i][5], i,'Aggr1'); generateMQL()" placeholder="key" autocomplete="off">
    @@ -762,7 +1021,7 @@
    + [(ngModel)]="mqlFieldsMATCH[i][2]" (keyup)="generateMQL()" placeholder="value" autocomplete="off">
    @@ -835,7 +1094,7 @@
    + [(ngModel)]="mqlFieldsGROUP[i][2]" (keyup)="generateMQL()" placeholder="value" autocomplete="off">
    @@ -849,7 +1108,7 @@
    + [(ngModel)]="mqlFieldsGROUP[i][3]" (keyup)="prependKeyObject(this.mqlFieldsGROUP[i][5], i,'Aggr2'); generateMQL()" placeholder="key" autocomplete="off">
    @@ -871,7 +1130,7 @@
    + [(ngModel)]="mqlFieldsGROUP[i][2]" (keyup)="generateMQL()" placeholder="value" autocomplete="off">
    @@ -918,7 +1177,7 @@
    + [(ngModel)]="mqlFieldsSORT[i][3]" (keyup)="prependKeyObject(this.mqlFieldsSORT[i][5], i,'Aggr3'); generateMQL()" placeholder="key" autocomplete="off">
    @@ -993,7 +1252,7 @@
    + [(ngModel)]="mqlFields[i][3]" (keyup)="prependKeyObject(this.mqlFields[i][5], i,'Find'); generateMQL()" placeholder="key" autocomplete="off">
    @@ -1015,7 +1274,7 @@
    + [(ngModel)]="mqlFields[i][2]" (keyup)="generateMQL()" placeholder="value" autocomplete="off">
    diff --git a/src/app/views/querying/graphical-querying/graphical-querying.component.ts b/src/app/views/querying/graphical-querying/graphical-querying.component.ts index d840fc42..cbaa13c5 100644 --- a/src/app/views/querying/graphical-querying/graphical-querying.component.ts +++ b/src/app/views/querying/graphical-querying/graphical-querying.component.ts @@ -75,13 +75,21 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest // cypher input fields cypherFields: string[][] = [[]]; // Matrix à [n,5] size -> [1] = Relationship, [2] = Node, [3] = 2.Relationship, [4] = 2.Node - cypherMatch: string[][][] = [[[]]]; + cypherNode: string[][][] = [[[]]]; + + cypherNode2: string[][][] = [[[]]]; + + cypherNode3: string[][][] = [[[]]]; cypherReturn: string[] = ['']; cypherReturn2: string[] = ['']; cypherDropdown: string[] = []; fieldListCypher: string[] = ['MATCH']; - fieldListCypherMatch: string[][] = [['NODE']]; + fieldListCypherNode: string[][] = [['NODE']]; + + fieldListCypherNode2: string[][] = [['NODE']]; + + fieldListCypherNode3: string[][] = [['NODE']]; fieldList: string[] = ['0']; fieldListMATCH: string[] = ['0']; fieldListGROUP: string[] = ['0']; @@ -478,11 +486,11 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest this.fieldDepthCounterSORT = 0; //cypher this.cypherFields = [[]]; - this.cypherMatch = [[[]]]; + this.cypherNode = [[[]]]; this.cypherReturn = ['']; this.cypherReturn2 = ['']; this.fieldListCypher = ['MATCH']; - this.fieldListCypherMatch = [['NODE']]; + this.fieldListCypherNode = [['NODE']]; break; case 'cypher': this.collectionName = undefined; @@ -511,11 +519,11 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest case 'mql': this.graphName = undefined; this.cypherFields = [[]]; - this.cypherMatch = [[[]]]; + this.cypherNode = [[[]]]; this.cypherReturn = ['']; this.cypherReturn2 = ['']; this.fieldListCypher = ['MATCH']; - this.fieldListCypherMatch = [['NODE']]; + this.fieldListCypherNode = [['NODE']]; break; } } @@ -795,14 +803,28 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest this.fieldListCypher.push(type); this.cypherFields.push([]); if (type === 'MATCH') { - this.fieldListCypherMatch.push(['NODE']); - this.cypherMatch.push([[]]); + this.fieldListCypherNode.push(['NODE']); + this.cypherNode.push([[]]); + this.fieldListCypherNode2.push(['NODE']); + this.cypherNode2.push([[]]); + this.fieldListCypherNode3.push(['NODE']); + this.cypherNode3.push([[]]); } } - addCypherMatchField(index: number, type: string) { - this.fieldListCypherMatch[index].push(type); - this.cypherMatch[index].push([]); + addCypherMatchField(index: number, type: string, field:number) { + if (field === 1){ + this.fieldListCypherNode[index].push(type); + this.cypherNode[index].push([]); + } + if (field === 2){ + this.fieldListCypherNode2[index].push(type); + this.cypherNode2[index].push([]); + } + if (field === 3){ + this.fieldListCypherNode3[index].push(type); + this.cypherNode3[index].push([]); + } } changeCypherField(type: string, index: number) { @@ -1029,9 +1051,19 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest this.generateCypher(); } - deleteCypherMatchField(index: number, x:number) { - this.fieldListCypherMatch[index].splice(x, 1); - this.cypherMatch[index].splice(x, 1); + deleteCypherMatchField(index: number, x:number, field: number) { + if (field === 1){ + this.fieldListCypherNode[index].splice(x, 1); + this.cypherNode[index].splice(x, 1); + } + if (field === 2) { + this.fieldListCypherNode2[index].splice(x, 1); + this.cypherNode2[index].splice(x, 1); + } + if (field === 3) { + this.fieldListCypherNode3[index].splice(x, 1); + this.cypherNode3[index].splice(x, 1); + } } deleteMQLField(x:number, mqlCase:string) { @@ -1159,43 +1191,117 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest } } - async generateMatch(index: number) { - this.cypherFields[index][0] = ''; + async generateMatch(index: number, field: number) { const nodeStack = []; const propertyStack = []; // generate the content of the field - for (let i = 0; i < this.fieldListCypherMatch[index].length; i++) { - if (this.fieldListCypherMatch[index][i] === 'NODE') { // Node Element - if (nodeStack.pop() !== undefined) { - if (propertyStack.pop() !== undefined) { - this.cypherFields[index][0] += '}'; + if (field === 1) { + this.cypherFields[index][0] = ''; + for (let i = 0; i < this.fieldListCypherNode[index].length; i++) { + if (this.fieldListCypherNode[index][i] === 'NODE') { // Node Element + if (nodeStack.pop() !== undefined) { + if (propertyStack.pop() !== undefined) { + this.cypherFields[index][0] += '}'; + } + this.cypherFields[index][0] += '),'; } - this.cypherFields[index][0] += '),'; - } - if (this.cypherMatch[index][i][1] === '') { // dropdown is empty - this.cypherFields[index][0] += '(' + this.cypherMatch[index][i][0]; + if (this.cypherNode[index][i][1] === '') { // dropdown is empty + this.cypherFields[index][0] += '(' + this.cypherNode[index][i][0]; + } + else { // dropdown is not empty and label + this.cypherFields[index][0] += '(' + this.cypherNode[index][i][0] + ':' + this.cypherNode[index][i][1]; + } + nodeStack.push(1); } - else { // dropdown is not empty and label - this.cypherFields[index][0] += '(' + this.cypherMatch[index][i][0] + ':' + this.cypherMatch[index][i][1]; + else { // Property Element + if (propertyStack.length === 0) { + this.cypherFields[index][0] += '{'; + propertyStack.push(1); + } + this.cypherFields[index][0] += this.cypherNode[index][i][0] + ':' + this.cypherNode[index][i][1]; + if (i < this.fieldListCypherNode[index].length - 1 && this.fieldListCypherNode[index][i+1] !== 'NODE') { + this.cypherFields[index][0] += ','; + } } - nodeStack.push(1); } - else { // Property Element - if (propertyStack.length === 0) { - this.cypherFields[index][0] += '{'; - propertyStack.push(1); + if (propertyStack.pop() !== undefined) { + this.cypherFields[index][0] += '}'; + } + if (this.fieldListCypherNode[index].length > 0) { + this.cypherFields[index][0] += ')'; + } + } + if (field === 2) { + this.cypherFields[index][2] = ''; + for (let i = 0; i < this.fieldListCypherNode2[index].length; i++) { + if (this.fieldListCypherNode2[index][i] === 'NODE') { // Node Element + if (nodeStack.pop() !== undefined) { + if (propertyStack.pop() !== undefined) { + this.cypherFields[index][2] += '}'; + } + this.cypherFields[index][2] += '),'; + } + if (this.cypherNode2[index][i][1] === '') { // dropdown is empty + this.cypherFields[index][2] += '(' + this.cypherNode2[index][i][0]; + } + else { // dropdown is not empty and label + this.cypherFields[index][2] += '(' + this.cypherNode2[index][i][0] + ':' + this.cypherNode2[index][i][1]; + } + nodeStack.push(1); } - this.cypherFields[index][0] += this.cypherMatch[index][i][0] + ':' + this.cypherMatch[index][i][1]; - if (i < this.fieldListCypherMatch[index].length - 1 && this.fieldListCypherMatch[index][i+1] !== 'NODE') { - this.cypherFields[index][0] += ','; + else { // Property Element + if (propertyStack.length === 0) { + this.cypherFields[index][2] += '{'; + propertyStack.push(1); + } + this.cypherFields[index][2] += this.cypherNode2[index][i][0] + ':' + this.cypherNode2[index][i][1]; + if (i < this.fieldListCypherNode2[index].length - 1 && this.fieldListCypherNode2[index][i+1] !== 'NODE') { + this.cypherFields[index][2] += ','; + } } } + if (propertyStack.pop() !== undefined) { + this.cypherFields[index][2] += '}'; + } + if (this.fieldListCypherNode2[index].length > 0) { + this.cypherFields[index][2] += ')'; + } } - if (propertyStack.pop() !== undefined) { - this.cypherFields[index][0] += '}'; - } - if (this.fieldListCypherMatch[index].length > 0) { - this.cypherFields[index][0] += ')'; + if (field === 3) { + this.cypherFields[index][4] = ''; + for (let i = 0; i < this.fieldListCypherNode3[index].length; i++) { + if (this.fieldListCypherNode3[index][i] === 'NODE') { // Node Element + if (nodeStack.pop() !== undefined) { + if (propertyStack.pop() !== undefined) { + this.cypherFields[index][4] += '}'; + } + this.cypherFields[index][4] += '),'; + } + if (this.cypherNode3[index][i][1] === '') { // dropdown is empty + this.cypherFields[index][4] += '(' + this.cypherNode3[index][i][0]; + } + else { // dropdown is not empty and label + this.cypherFields[index][4] += '(' + this.cypherNode3[index][i][0] + ':' + this.cypherNode3[index][i][1]; + } + nodeStack.push(1); + } + else { // Property Element + if (propertyStack.length === 0) { + this.cypherFields[index][4] += '{'; + propertyStack.push(1); + } + this.cypherFields[index][4] += this.cypherNode3[index][i][0] + ':' + this.cypherNode3[index][i][1]; + if (i < this.fieldListCypherNode3[index].length - 1 && this.fieldListCypherNode3[index][i+1] !== 'NODE') { + this.cypherFields[index][4] += ','; + } + } + } + if (propertyStack.pop() !== undefined) { + this.cypherFields[index][4] += '}'; + } + if (this.fieldListCypherNode3[index].length > 0) { + this.cypherFields[index][4] += ')'; + } } this.generateCypher(); } @@ -1207,13 +1313,13 @@ export class GraphicalQueryingComponent implements OnInit, AfterViewInit, OnDest cypher += 'MATCH ' + this.cypherFields[i][0]; switch (this.cypherDropdown[i]) { case 'cypher-outgoing': - cypher += '-->(' + this.cypherFields[i][2] + ')'; + cypher += '-->' + this.cypherFields[i][2]; break; case 'cypher-directed': - cypher += '-[' + this.cypherFields[i][1] + ']->(' + this.cypherFields[i][2] + ')'; + cypher += '-[' + this.cypherFields[i][1] + ']->' + this.cypherFields[i][2]; break; case 'cypher-multiple': - cypher += '-[' + this.cypherFields[i][1] + ']->(' + this.cypherFields[i][2] + ')<-[' + this.cypherFields[i][3] + ']-(' + this.cypherFields[i][4] + ')'; + cypher += '-[' + this.cypherFields[i][1] + ']->' + this.cypherFields[i][2] + '<-[' + this.cypherFields[i][3] + ']-' + this.cypherFields[i][4]; break; } } From c04b3de5e87c254ab3b84acf32c5b6eac7f01369 Mon Sep 17 00:00:00 2001 From: svamel00 Date: Fri, 24 Mar 2023 13:56:54 +0100 Subject: [PATCH 48/60] added dynamic relationship modal for properties --- .../graphical-querying.component.html | 189 +++++++++++++++++- .../graphical-querying.component.ts | 118 ++++++++++- 2 files changed, 299 insertions(+), 8 deletions(-) diff --git a/src/app/views/querying/graphical-querying/graphical-querying.component.html b/src/app/views/querying/graphical-querying/graphical-querying.component.html index 1b28a6fc..32d36853 100644 --- a/src/app/views/querying/graphical-querying/graphical-querying.component.html +++ b/src/app/views/querying/graphical-querying/graphical-querying.component.html @@ -124,7 +124,7 @@
    Query Result
    - +
    - +