diff --git a/core/amber/src/main/scala/edu/uci/ics/texera/web/service/JobResultService.scala b/core/amber/src/main/scala/edu/uci/ics/texera/web/service/JobResultService.scala index a5b8168b3ae..d0c367faa69 100644 --- a/core/amber/src/main/scala/edu/uci/ics/texera/web/service/JobResultService.scala +++ b/core/amber/src/main/scala/edu/uci/ics/texera/web/service/JobResultService.scala @@ -31,7 +31,7 @@ import scala.concurrent.duration.DurationInt object JobResultService { - val defaultPageSize: Int = 10 + val defaultPageSize: Int = 5 // convert Tuple from engine's format to JSON format def webDataFromTuple( diff --git a/core/new-gui/angular.json b/core/new-gui/angular.json index 935108a0e26..438c4490ba1 100644 --- a/core/new-gui/angular.json +++ b/core/new-gui/angular.json @@ -29,6 +29,7 @@ } ], "styles": [ + "node_modules/jquery-contextmenu/dist/jquery.contextMenu.min.css", "node_modules/ng-zorro-antd/ng-zorro-antd.min.css", "node_modules/jointjs/css/layout.css", "node_modules/jointjs/css/themes/material.css", @@ -37,6 +38,9 @@ "src/styles.scss" ], "scripts": [ + "node_modules/jquery/dist/jquery.min.js", + "node_modules/jquery-contextmenu/dist/jquery.contextMenu.min.js", + "node_modules/jquery-contextmenu/dist/jquery.ui.position.min.js", "./node_modules/ngx-monaco-editor/assets/monaco/vs/loader.js" ], "allowedCommonJsDependencies": [ diff --git a/core/new-gui/package.json b/core/new-gui/package.json index 5df270c6fc7..8a7c423fbbd 100644 --- a/core/new-gui/package.json +++ b/core/new-gui/package.json @@ -61,6 +61,7 @@ "jointjs": "~3.5.4", "jquery": "~3.6.0", "jquery-ui-dist": "~1.13.1", + "jquery-contextmenu": "^2.9.2", "js-abbreviation-number": "~1.4.0", "jwt-decode": "~3.1.2", "lodash-es": "~4.17.21", @@ -109,6 +110,7 @@ "@types/jasminewd2": "~2.0.10", "@types/jquery": "~3.5.14", "@types/jqueryui": "1.12.10", + "@types/jquery.contextmenu": "1.7.35", "@types/json-schema": "~7.0.9", "@types/lodash": "~4.14.179", "@types/uuid": "~8.3.4", diff --git a/core/new-gui/src/app/workspace/component/result-panel/result-panel.component.html b/core/new-gui/src/app/workspace/component/result-panel/result-panel.component.html index 88ba14308f0..406b84d9cce 100644 --- a/core/new-gui/src/app/workspace/component/result-panel/result-panel.component.html +++ b/core/new-gui/src/app/workspace/component/result-panel/result-panel.component.html @@ -1,5 +1,13 @@
+
+ +
+

No results available to display.

+
+
+
+
+

Empty result set.

+
- - - - {{ column.header }} - - - - - - {{ column.getCell(row) }} - - - - +
+ + + + + {{ column.header }} + + + + + + + {{ column.getCell(row) }} + + + + +
diff --git a/core/new-gui/src/app/workspace/component/result-panel/result-table-frame/result-table-frame.component.scss b/core/new-gui/src/app/workspace/component/result-panel/result-table-frame/result-table-frame.component.scss index e69de29bb2d..2fa38e9fea1 100644 --- a/core/new-gui/src/app/workspace/component/result-panel/result-table-frame/result-table-frame.component.scss +++ b/core/new-gui/src/app/workspace/component/result-panel/result-table-frame/result-table-frame.component.scss @@ -0,0 +1,33 @@ +:host ::ng-deep .ant-table-wrapper { + width: 500px; +} + +:host ::ng-deep .ant-table-pagination.ant-pagination { + margin: 10px; +} + +:host ::ng-deep .ant-table-pagination-right { + justify-content: left; +} +:host ::ng-deep .ant-table-header { + width: 200vw; +} + +:host ::ng-deep .ant-table-body { + width: 200vw; +} + +div.scroll { + margin: 0px, 0px; + padding: 0px; + width: 100%; + overflow-x: scroll; +} + +td.data-size { + font-size: 9px; +} + +th.header-size { + font-size: 10px; +} diff --git a/core/new-gui/src/app/workspace/component/workflow-editor/workflow-editor.component.ts b/core/new-gui/src/app/workspace/component/workflow-editor/workflow-editor.component.ts index c4f3ed485c6..e08bbe14c90 100644 --- a/core/new-gui/src/app/workspace/component/workflow-editor/workflow-editor.component.ts +++ b/core/new-gui/src/app/workspace/component/workflow-editor/workflow-editor.component.ts @@ -75,6 +75,7 @@ export const WORKFLOW_EDITOR_JOINTJS_ID = "texera-workflow-editor-jointjs-body-i * @author Henry Chen * */ + @UntilDestroy() @Component({ selector: "texera-workflow-editor", @@ -160,6 +161,8 @@ export class WorkflowEditorComponent implements AfterViewInit, OnDestroy { this.handleOperatorSuggestionHighlightEvent(); this.dragDropService.registerWorkflowEditorDrop(this.WORKFLOW_EDITOR_JOINTJS_ID); + this.rightClickContextMenu(); + this.handleElementDelete(); this.handleElementSelectAll(); this.handleElementCopy(); @@ -602,6 +605,104 @@ export class WorkflowEditorComponent implements AfterViewInit, OnDestroy { }); } + private rightClickContextMenu(): void { + const highlightedOperatorIDs = this.workflowActionService.getJointGraphWrapper().getCurrentHighlightedOperatorIDs(); + + const highlightedGroupIDs = this.workflowActionService.getJointGraphWrapper().getCurrentHighlightedGroupIDs(); + + var isVisible = function (key: any, opt: { $trigger: { nodeName: string } }) { + if (highlightedOperatorIDs.length > 0 || highlightedGroupIDs.length > 0) { + return true; + } else { + return false; + } + }; + + jQuery(() => { + jQuery.contextMenu({ + selector: ".texera-workspace-workflow-editor-body", + + callback: (key: any, options: any) => { + if (key == "copy") { + this.clearCopiedElements(); + this.saveHighlighedElements(); + } else if (key == "paste") { + if (this.copiedOperators.size > 0 || this.copiedGroups.size > 0) { + const operatorsAndPositions: { op: OperatorPredicate; pos: Point }[] = []; + const links: OperatorLink[] = []; + const groups: Group[] = []; + const positions: Point[] = []; + + this.copiedOperators = new Map( + Array.from(this.copiedOperators).sort((first, second) => first[1].layer - second[1].layer) + ); + + this.copiedOperators.forEach((copiedOperator: { operator: any }, operatorID: any) => { + const newOperator = this.copyOperator(copiedOperator.operator); + const newOperatorPosition = this.calcOperatorPosition(newOperator.operatorID, operatorID, positions); + operatorsAndPositions.push({ + op: newOperator, + pos: newOperatorPosition, + }); + positions.push(newOperatorPosition); + }); + + this.copiedGroups.forEach((copiedGroup: { group: any; position: any }, groupID: any) => { + const newGroup = this.copyGroup(copiedGroup.group); + + const oldPosition = copiedGroup.position; + const newPosition = this.calcGroupPosition(newGroup.groupID, groupID, positions); + positions.push(newPosition); + + const delta = { + x: newPosition.x - oldPosition.x, + y: newPosition.y - oldPosition.y, + }; + + newGroup.operators.forEach( + (operatorInfo: { position: { x: number; y: number }; operator: any }, operatorID: any) => { + operatorInfo.position.x += delta.x; + operatorInfo.position.y += delta.x; + + operatorsAndPositions.push({ + op: operatorInfo.operator, + pos: operatorInfo.position, + }); + } + ); + + newGroup.links.forEach((linkInfo: { link: OperatorLink }, operatorID: any) => { + links.push(linkInfo.link); + }); + + groups.push(newGroup); + }); + + this.workflowActionService.addOperatorsAndLinks(operatorsAndPositions, links, groups, new Map()); + } + } else if (key == "cut") { + this.clearCopiedElements(); + this.saveHighlighedElements(); + this.workflowActionService.deleteOperatorsAndLinks(highlightedOperatorIDs, [], highlightedGroupIDs); + } else if (key == "delete") { + this.workflowActionService.deleteOperatorsAndLinks(highlightedOperatorIDs, [], highlightedGroupIDs); + } + if (highlightedOperatorIDs.length == 0 || highlightedGroupIDs.length == 0) { + } + //var m = "clicked: " + key; + //alert(m); ' + return true; + }, + items: { + copy: { name: "Copy", icon: "copy", visible: isVisible }, + paste: { name: "Paste", icon: "paste" }, + cut: { name: "Cut", icon: "cut", visible: isVisible }, + delete: { name: "Delete", icon: "delete", visible: isVisible }, + }, + }); + }); + } + private handleHighlightMouseDBClickInput(): void { fromJointPaperEvent(this.getJointPaper(), "cell:pointerdblclick") .pipe(untilDestroyed(this)) @@ -854,6 +955,7 @@ export class WorkflowEditorComponent implements AfterViewInit, OnDestroy { } /** + * * Handles the event where the Delete button is clicked for a Link, * and call workflowAction to delete the corresponding link. * diff --git a/core/new-gui/src/app/workspace/component/workspace.component.scss b/core/new-gui/src/app/workspace/component/workspace.component.scss index d9e167c63f3..4c754e36b17 100644 --- a/core/new-gui/src/app/workspace/component/workspace.component.scss +++ b/core/new-gui/src/app/workspace/component/workspace.component.scss @@ -46,10 +46,10 @@ grid-template-columns: 200px auto 350px; grid-template-rows: var(--header-height) - calc((100% - var(--header-height) - var(--resultbar-height)) * 0.6) + calc((100% - var(--header-height) - var(--resultbar-height)) * 0.4) 0px var(--resultbar-height) - calc((100% - var(--header-height) - var(--resultbar-height)) * 0.4); + calc((100% - var(--header-height) - var(--resultbar-height)) * 0.6); position: relative; } @@ -129,8 +129,7 @@ .texera-result-panel-grid-container { grid-column: 2/3; grid-row: 5/6; - overflow: auto; - transition: height 1s; + transition: height 2s; } .texera-result-panel-toggle-grid-container { diff --git a/core/new-gui/src/app/workspace/service/workflow-result/workflow-result.service.ts b/core/new-gui/src/app/workspace/service/workflow-result/workflow-result.service.ts index df1f27b9862..5befdc46ffb 100644 --- a/core/new-gui/src/app/workspace/service/workflow-result/workflow-result.service.ts +++ b/core/new-gui/src/app/workspace/service/workflow-result/workflow-result.service.ts @@ -13,9 +13,9 @@ import { Observable, of, Subject } from "rxjs"; import { v4 as uuid } from "uuid"; import { ChartType } from "../../types/visualization.interface"; -export const DEFAULT_PAGE_SIZE = 10; +export const DEFAULT_PAGE_SIZE = 5; -/** +/* * WorkflowResultService manages the result data of a workflow execution. */ @Injectable({ diff --git a/core/new-gui/src/environments/environment.default.ts b/core/new-gui/src/environments/environment.default.ts index ac9a51ba010..c42c40b6880 100644 --- a/core/new-gui/src/environments/environment.default.ts +++ b/core/new-gui/src/environments/environment.default.ts @@ -14,7 +14,7 @@ export const defaultEnvironment = { * whether fetching available source tables is enabled * see SourceTablesService for details */ - sourceTableEnabled: false, + sourceTableEnabled: true, /** * whether operator schema propagation and autocomplete feature is enabled, * see SchemaPropagationService for details @@ -36,7 +36,7 @@ export const defaultEnvironment = { /** * whether user system is enabled */ - userSystemEnabled: false, + userSystemEnabled: true, /** * whether user preset feature is enabled, requires user system to be enabled diff --git a/core/new-gui/src/tsconfig.app.json b/core/new-gui/src/tsconfig.app.json index 26727d8c999..4a93fd74166 100644 --- a/core/new-gui/src/tsconfig.app.json +++ b/core/new-gui/src/tsconfig.app.json @@ -3,7 +3,7 @@ "compilerOptions": { "outDir": "../out-tsc/app", // include jqueryui type definition here because Angular does not include it if it's not imported - "types": ["jqueryui", "gapi.auth2", "gapi"] + "types": ["jqueryui", "jquery.contextmenu", "gapi.auth2", "gapi"] }, // ask Angular to check template error during the compilation process "angularCompilerOptions": { diff --git a/core/new-gui/yarn.lock b/core/new-gui/yarn.lock index 06ae4a46b44..1418850c329 100644 --- a/core/new-gui/yarn.lock +++ b/core/new-gui/yarn.lock @@ -3339,6 +3339,13 @@ dependencies: "@types/jasmine" "*" +"@types/jquery.contextmenu@1.7.35": + version "1.7.35" + resolved "https://registry.yarnpkg.com/@types/jquery.contextmenu/-/jquery.contextmenu-1.7.35.tgz#f7fc43f0c5529c48bd687ef5aaf858a3090cca2f" + integrity sha512-0KmOOYgU6ySqOcglRYxFz8KyoFyOeN5YJ0ykg8IL1SJmmLTkeplVixqspcSmFtpLRORPl46a893An5YbuLr6rw== + dependencies: + "@types/jquery" "*" + "@types/jquery@*", "@types/jquery@~3.5.14": version "3.5.14" resolved "https://registry.npmjs.org/@types/jquery/-/jquery-3.5.14.tgz" @@ -8902,6 +8909,13 @@ jointjs@~3.5.4: jquery "~3.6.0" lodash "~4.17.21" +jquery-contextmenu@^2.9.2: + version "2.9.2" + resolved "https://registry.yarnpkg.com/jquery-contextmenu/-/jquery-contextmenu-2.9.2.tgz#f9dc362e45871dda2e50fa45de2243e917446ced" + integrity sha512-6S6sH/08owDStC/7zNwcN366yR0ydX6PmMB0RnjLRQOp7Nc/rqwEHglshfHrrw2kdTev97GXwRXrayDUmToIOw== + dependencies: + jquery "^3.5.0" + jquery-ui-dist@~1.13.1: version "1.13.1" resolved "https://registry.npmjs.org/jquery-ui-dist/-/jquery-ui-dist-1.13.1.tgz" @@ -8909,7 +8923,7 @@ jquery-ui-dist@~1.13.1: dependencies: jquery ">=1.8.0 <4.0.0" -"jquery@>=1.8.0 <4.0.0", jquery@~3.6.0: +"jquery@>=1.8.0 <4.0.0", jquery@^3.5.0, jquery@~3.6.0: version "3.6.0" resolved "https://registry.npmjs.org/jquery/-/jquery-3.6.0.tgz" integrity sha512-JVzAR/AjBvVt2BmYhxRCSYysDsPcssdmTFnzyLEts9qNwmjmu4JTAMYubEfwVOSwpQ1I1sKKFcxhZCI2buerfw==