From f89a7fd28d2413fa3017560aec60f0479759289b Mon Sep 17 00:00:00 2001 From: srikant Date: Tue, 26 Nov 2024 12:21:51 +0530 Subject: [PATCH] #2137 Resize Right Flyout using drag (#2224) Signed-off-by: srikant --- .../common-canvas/common-canvas-test.js | 3 +- .../src/common-canvas/canvas-controller.js | 20 +-- .../src/common-canvas/cc-panels.jsx | 18 ++- .../src/common-canvas/cc-right-flyout.jsx | 121 +++++++++++++++++- .../src/common-canvas/common-canvas.scss | 25 ++++ ...css => properties-main-widths.module.scss} | 0 .../properties-main/properties-main.jsx | 53 +++++--- .../properties-main/properties-main.scss | 13 +- .../src/object-model/config-utils.js | 1 + .../src/object-model/object-model.js | 4 + .../src/object-model/redux/canvas-store.js | 2 +- .../redux/reducers/rightflyout.js | 4 +- .../cypress/e2e/canvas/bottom-panel.cy.js | 2 + .../cypress/e2e/canvas/right-flyout.cy.js | 26 ++++ .../cypress/support/canvas/operation-cmds.js | 11 ++ .../support/canvas/verification-cmds.js | 10 ++ canvas_modules/harness/src/client/App.js | 3 + .../sidepanel/canvas/sidepanel-canvas.jsx | 11 ++ docs/pages/03.02.01-canvas-config.md | 3 + 19 files changed, 294 insertions(+), 36 deletions(-) rename canvas_modules/common-canvas/src/common-properties/properties-main/{properties-main-widths.scss => properties-main-widths.module.scss} (100%) diff --git a/canvas_modules/common-canvas/__tests__/common-canvas/common-canvas-test.js b/canvas_modules/common-canvas/__tests__/common-canvas/common-canvas-test.js index 42f2a19d52..ff78170185 100644 --- a/canvas_modules/common-canvas/__tests__/common-canvas/common-canvas-test.js +++ b/canvas_modules/common-canvas/__tests__/common-canvas/common-canvas-test.js @@ -65,7 +65,8 @@ describe("CommonCanvas renders correctly", () => { const config = {}; const canvasParams = { showRightFlyout: false }; const wrapper = createCommonCanvas(config, canvasController, canvasParams); - expect(wrapper.find(CommonCanvasRightFlyout)).to.have.length(1); + // When showRightFlyout is false then Right Flyout should not be visible + expect(wrapper.find(CommonCanvasRightFlyout)).to.have.length(0); expect(canvasController.isRightFlyoutOpen() === false).to.be.true; }); diff --git a/canvas_modules/common-canvas/src/common-canvas/canvas-controller.js b/canvas_modules/common-canvas/src/common-canvas/canvas-controller.js index 6107441f10..592d876140 100644 --- a/canvas_modules/common-canvas/src/common-canvas/canvas-controller.js +++ b/canvas_modules/common-canvas/src/common-canvas/canvas-controller.js @@ -1618,6 +1618,18 @@ export default class CanvasController { this.objectModel.setBottomPanelHeight(ht); } + isLeftFlyoutOpen() { + return this.objectModel.isLeftFlyoutOpen(); + } + + setRightFlyoutWidth(wd) { + this.objectModel.setRightFlyoutWidth(wd); + } + + isRightFlyoutOpen() { + return this.objectModel.isRightFlyoutOpen(); + } + isTopPanelOpen() { return this.getObjectModel().isTopPanelOpen(); } @@ -1672,14 +1684,6 @@ export default class CanvasController { this.objectModel.toggleNotificationPanel(); } - isLeftFlyoutOpen() { - return this.objectModel.isLeftFlyoutOpen(); - } - - isRightFlyoutOpen() { - return this.objectModel.isRightFlyoutOpen(); - } - isDisplayingFullPageSubFlow() { const breadcrumbs = this.objectModel.getBreadcrumbs(); return breadcrumbs.length > 1; diff --git a/canvas_modules/common-canvas/src/common-canvas/cc-panels.jsx b/canvas_modules/common-canvas/src/common-canvas/cc-panels.jsx index 68b77d5b9c..524da00665 100644 --- a/canvas_modules/common-canvas/src/common-canvas/cc-panels.jsx +++ b/canvas_modules/common-canvas/src/common-canvas/cc-panels.jsx @@ -97,7 +97,7 @@ class CommonCanvasPanels extends React.Component { // indicated by setting the config field enablePaletteLayout to // "None" and providing some JSX in the leftFlyoutContent field // of . - isLeftPanelOpen() { + isLeftFlyoutOpen() { if (this.props.enablePaletteLayout === PALETTE_LAYOUT_DIALOG) { return false; } @@ -114,6 +114,11 @@ class CommonCanvasPanels extends React.Component { return false; } + // Returns true if the right flyout should be displayed. + isRightFlyoutOpen() { + return this.props.rightFlyoutIsOpen; + } + // Returns a JSX object for the contents of the left panel. If the application // sets enablePaletteLayout to None this indicates the app wamts its own content // to go into the left panel provided by leftFlyoutContent provided to @@ -129,6 +134,11 @@ class CommonCanvasPanels extends React.Component { return null; } + // Returns a JSX object for the contents of the right panel. + generateRightFlyout() { + return (); + } + render() { this.logger.log("render"); @@ -138,8 +148,9 @@ class CommonCanvasPanels extends React.Component { containingDivId={this.props.containingDivId} /> ); - const rightFlyout = (); - const leftFlyoutIsOpen = this.isLeftPanelOpen(); + const rightFlyoutIsOpen = this.isRightFlyoutOpen(); + const rightFlyout = rightFlyoutIsOpen ? this.generateRightFlyout() : null; + const leftFlyoutIsOpen = this.isLeftFlyoutOpen(); const leftFlyout = leftFlyoutIsOpen ? this.generateLeftFlyout() : null; const topCenterBottom = this.generateTopCenterBottom(); @@ -288,6 +299,7 @@ const mapStateToProps = (state, ownProps) => ({ enableNarrowPalette: state.canvasconfig.enableNarrowPalette, enableLeftFlyoutUnderToolbar: state.canvasconfig.enableLeftFlyoutUnderToolbar, enableRightFlyoutUnderToolbar: state.canvasconfig.enableRightFlyoutUnderToolbar, + enableRightFlyoutDragToResize: state.canvasconfig.enableRightFlyoutDragToResize, toolbarIsOpen: (state.canvasconfig.enableToolbarLayout !== PALETTE_LAYOUT_NONE), paletteIsOpen: state.palette.isOpen, topPanelIsOpen: state.toppanel.isOpen, diff --git a/canvas_modules/common-canvas/src/common-canvas/cc-right-flyout.jsx b/canvas_modules/common-canvas/src/common-canvas/cc-right-flyout.jsx index f5a2e6e8ea..4857f55319 100644 --- a/canvas_modules/common-canvas/src/common-canvas/cc-right-flyout.jsx +++ b/canvas_modules/common-canvas/src/common-canvas/cc-right-flyout.jsx @@ -19,24 +19,129 @@ import { connect } from "react-redux"; import PropTypes from "prop-types"; import Logger from "../logging/canvas-logger.js"; +// Should cover at most 70% of available width. +const MAX_WIDTH_EXTEND_PERCENT = 0.7; +// Should have a minimum width of 0 to hide flyout if there is no content. +const MIN_WIDTH = 0; +// If flyout content width is not set occupy entire width to strecth content. +const DEFAULT_WIDTH = "100%"; class CommonCanvasRightFlyout extends React.Component { constructor(props) { super(props); + + // Intial width of the flyout when opened to track resize. + this.initialWidth = MIN_WIDTH; + this.logger = new Logger("CC-RightFlyout"); + + this.rightFlyoutRef = React.createRef(); + + this.onMouseUp = this.onMouseUp.bind(this); + this.onMouseDown = this.onMouseDown.bind(this); + this.onMouseMoveX = this.onMouseMoveX.bind(this); + this.getCurrentWidth = this.getCurrentWidth.bind(this); + + this.getRightFlyoutResizeContent = this.getRightFlyoutResizeContent.bind(this); + } + + componentDidMount() { + // Since flyout content width can be dynamic set the initial width as per width of the content + const currentWidth = this.getCurrentWidth(); + this.initialWidth = currentWidth; + } + + componentWillUnmount() { + // Reset the flyout width to adjust as per content width in next render + this.props.canvasController.setRightFlyoutWidth(0); + } + + onMouseDown(e) { + // Set width as soon as resize is detected to accurately move the flyout with the drag. + const currentWidth = this.getCurrentWidth(); + this.props.canvasController.setRightFlyoutWidth(this.limitWidth(currentWidth)); + + if (e.button === 0) { + document.addEventListener("mousemove", this.onMouseMoveX, true); + document.addEventListener("mouseup", this.onMouseUp, true); + this.posX = e.clientX; + // Prevent panel contents being dragged in the test harness (which can + // happen even though draggable is false for the contents!) + e.preventDefault(); + } + } + + onMouseUp() { + document.removeEventListener("mousemove", this.onMouseMoveX, true); + document.removeEventListener("mouseup", this.onMouseUp, true); + } + + onMouseMoveX(e) { + if (e.clientX) { + const diff = e.clientX - this.posX; + const wth = this.props.panelWidth - diff; + this.props.canvasController.setRightFlyoutWidth(this.limitWidth(wth)); + this.posX = e.clientX; + } + } + + // Returns content to enable/disable resize based on feature flag. + getRightFlyoutResizeContent() { + let resizeContent = null; + + if (this.props.enableRightFlyoutDragToResize) { + resizeContent = (
); + } + + return resizeContent; + } + + // Returns present width of the flyout. + getCurrentWidth() { + let currentWidth = MIN_WIDTH; + const el = this.rightFlyoutRef?.current; + if (el) { + currentWidth = el?.offsetWidth; + } + return currentWidth; + } + + // Returns a new width for right panel limited by the need to enforce + // a minimum and maximum width + limitWidth(wd) { + const canvasContainer = document.getElementById(this.props.containingDivId); + let width = wd; + + if (canvasContainer) { + // Max Width should be 70% of the total available width (canvas + rightflyout) + const canvasWidth = canvasContainer.getBoundingClientRect().width; + const maxWidth = (canvasWidth + this.props.panelWidth) * MAX_WIDTH_EXTEND_PERCENT; + width = Math.min(Math.max(width, this.initialWidth), maxWidth); + } + + return width; } render() { this.logger.log("render"); let rightFlyout =
; // For no content, return empty
so grid siziing for parent
work correctly. + const rightFlyoutDragContent = this.getRightFlyoutResizeContent(); if (this.props.content && this.props.isOpen) { + let widthPx = this.limitWidth(this.props.panelWidth) + "px"; + // Apply 100% width if content has no width to occupy flyout. + if (this.props.panelWidth === MIN_WIDTH) { + widthPx = DEFAULT_WIDTH; + } const rfClass = this.props.enableRightFlyoutUnderToolbar ? "right-flyout-panel under-toolbar" : "right-flyout-panel"; rightFlyout = ( -
- {this.props.content} +
+ {rightFlyoutDragContent} +
+ {this.props.content} +
); } @@ -46,16 +151,24 @@ class CommonCanvasRightFlyout extends React.Component { } CommonCanvasRightFlyout.propTypes = { + // Provided by Common Canvas + canvasController: PropTypes.object, + containingDivId: PropTypes.string, + // Provided by Redux isOpen: PropTypes.bool, content: PropTypes.object, - enableRightFlyoutUnderToolbar: PropTypes.bool + enableRightFlyoutUnderToolbar: PropTypes.bool, + enableRightFlyoutDragToResize: PropTypes.bool, + panelWidth: PropTypes.number }; const mapStateToProps = (state, ownProps) => ({ isOpen: state.rightflyout.isOpen, content: state.rightflyout.content, - enableRightFlyoutUnderToolbar: state.canvasconfig.enableRightFlyoutUnderToolbar + enableRightFlyoutUnderToolbar: state.canvasconfig.enableRightFlyoutUnderToolbar, + enableRightFlyoutDragToResize: state.canvasconfig.enableRightFlyoutDragToResize, + panelWidth: state.rightflyout.panelWidth }); export default connect(mapStateToProps)(CommonCanvasRightFlyout); diff --git a/canvas_modules/common-canvas/src/common-canvas/common-canvas.scss b/canvas_modules/common-canvas/src/common-canvas/common-canvas.scss index 9e9e5db49c..d2c7406810 100644 --- a/canvas_modules/common-canvas/src/common-canvas/common-canvas.scss +++ b/canvas_modules/common-canvas/src/common-canvas/common-canvas.scss @@ -44,6 +44,13 @@ $panel-border-color: $border-subtle-01; position: relative; // This allows the State Tag to have positio: absolute } +.right-flyout-container { + display: flex; + border-left: $panel-border-width solid $panel-border-color; + min-height: fit-content; + min-width: fit-content; +} + .left-flyout-panel, .right-flyout-panel { // This combination of height and min-height enable scrolling in the child panel, @@ -51,11 +58,29 @@ $panel-border-color: $border-subtle-01; // so the contents of the panel can adjust themselves to the height accordingly. height: 0; min-height: 100%; +} +// Allow content in child to expand on drag using flex +.right-flyout-panel { + min-width: fit-content; + display: flex; + flex: 1; user-select: none; /* Prevent elements from being selectable */ background-color: $layer-01; } +.right-flyout-drag { + border-left: $panel-border-color; + cursor: col-resize; + flex: 0 0 $spacing-01; + border-left-width: 1px; + background: $layer-01; + transition: all 0.2s ease-in; + &:hover { + background: $button-tertiary; + } +} + .bottom-panel { display: flex; flex-direction: column; diff --git a/canvas_modules/common-canvas/src/common-properties/properties-main/properties-main-widths.scss b/canvas_modules/common-canvas/src/common-properties/properties-main/properties-main-widths.module.scss similarity index 100% rename from canvas_modules/common-canvas/src/common-properties/properties-main/properties-main-widths.scss rename to canvas_modules/common-canvas/src/common-properties/properties-main/properties-main-widths.module.scss diff --git a/canvas_modules/common-canvas/src/common-properties/properties-main/properties-main.jsx b/canvas_modules/common-canvas/src/common-properties/properties-main/properties-main.jsx index 7c2e06ecc5..1ddf7bfeac 100644 --- a/canvas_modules/common-canvas/src/common-properties/properties-main/properties-main.jsx +++ b/canvas_modules/common-canvas/src/common-properties/properties-main/properties-main.jsx @@ -16,6 +16,7 @@ import React from "react"; import PropTypes from "prop-types"; +import ReactResizeDetector from "react-resize-detector"; import PropertiesModal from "./../components/properties-modal"; import PropertiesEditor from "./../components/properties-editor"; import TearSheet from "../panels/tearsheet"; @@ -37,7 +38,7 @@ import TitleEditor from "./../components/title-editor"; import classNames from "classnames"; import { injectIntl } from "react-intl"; -import styles from "./properties-main-widths.scss"; +import styles from "./properties-main-widths.module.scss"; const FLYOUT_WIDTH_SMALL = parseInt(styles.flyoutWidthSmall, 10); const FLYOUT_WIDTH_MEDIUM = parseInt(styles.flyoutWidthMedium, 10); @@ -71,6 +72,7 @@ class PropertiesMain extends React.Component { }); this.setForm(props.propertiesInfo, false); this.previousErrorMessages = {}; + this.flyoutWidths = [FLYOUT_WIDTH_SMALL, FLYOUT_WIDTH_MEDIUM, FLYOUT_WIDTH_LARGE, FLYOUT_WIDTH_MAX]; // this has to be after setForm because setForm clears all error messages. // Validate all validationDefinitions but show warning messages for "colDoesExists" condition only this.propertiesController.validatePropertiesValues(false); @@ -86,7 +88,8 @@ class PropertiesMain extends React.Component { const editorSize = this.getEditorSize(); this.state = { showPropertiesButtons: true, - editorSize: editorSize + editorSize: editorSize, + containerWidth: FLYOUT_WIDTH_SMALL }; this.applyPropertiesEditing = this.applyPropertiesEditing.bind(this); this.showPropertiesButtons = this.showPropertiesButtons.bind(this); @@ -449,6 +452,10 @@ class PropertiesMain extends React.Component { } } + detectResize(width) { + this.setState({ containerWidth: width }); + } + render() { const applyOnBlurEnabled = this.props.propertiesConfig.applyOnBlur && this.props.propertiesConfig.rightFlyout; let cancelHandler = this.cancelHandler.bind(this, CANCEL); @@ -493,7 +500,13 @@ class PropertiesMain extends React.Component { showPropertiesButtons={this.state.showPropertiesButtons} disableSaveOnRequiredErrors={this.props.propertiesConfig.disableSaveOnRequiredErrors} />); - if (this._isResizeButtonRequired()) { + // Show Resize Button only under below conditions + // 1. Flyout is not dragged to resize its width. + // 2. If Flyout is dragged back to its smallest width. + // If pixel_width is set include that to test if button should be shown. + const widthArr = [...this.flyoutWidths, this._getOverrideSize()]; + const allowedWidth = widthArr.includes(this.state.containerWidth); + if (this._isResizeButtonRequired() && allowedWidth) { const resizeIcon = this._getResizeButton(); // Resize button label can be "Expand" or "Contract" const resizeBtnLabel = (resizeIcon.props && resizeIcon.props.className === "properties-resize-caret-left") @@ -591,19 +604,29 @@ class PropertiesMain extends React.Component { propertiesSizeClassname); return ( - - {resizeBtn} +
+ + {resizeBtn} +
+
); } diff --git a/canvas_modules/common-canvas/src/common-properties/properties-main/properties-main.scss b/canvas_modules/common-canvas/src/common-properties/properties-main/properties-main.scss index a386e3b6cf..7f0e0bdc91 100644 --- a/canvas_modules/common-canvas/src/common-properties/properties-main/properties-main.scss +++ b/canvas_modules/common-canvas/src/common-properties/properties-main/properties-main.scss @@ -14,13 +14,24 @@ * limitations under the License. */ -@import "./properties-main-widths.scss"; +@import "./properties-main-widths.module.scss"; $properties-modal-buttons-height: $spacing-10; $properties-resize-button-size: $spacing-06; +// Included to align resizeBtn to enable properties content to stretch on resize +.properties-right-flyout-container { + display: flex; + flex: 1; + flex-direction: column; +} + .properties-right-flyout { // Set the font explicitly to 14px to shrink them across the entire properties editor font-size: 14px; + // Stretch properties content horizontally when flyout resize is enabled + min-width: 100%; + // Stretch properties content vertically when flyout resize is enabled + min-height: 100%; width: 0; height: 100%; overflow: hidden; diff --git a/canvas_modules/common-canvas/src/object-model/config-utils.js b/canvas_modules/common-canvas/src/object-model/config-utils.js index badfe3d29f..d5f0933977 100644 --- a/canvas_modules/common-canvas/src/object-model/config-utils.js +++ b/canvas_modules/common-canvas/src/object-model/config-utils.js @@ -84,6 +84,7 @@ export default class ConfigUtils { enableDropZoneOnExternalDrag: false, enableLeftFlyoutUnderToolbar: false, enableRightFlyoutUnderToolbar: false, + enableRightFlyoutDragToResize: false, enablePanIntoViewOnOpen: false, enableZoomIntoSubFlows: false, enableBrowserEditMenu: true, diff --git a/canvas_modules/common-canvas/src/object-model/object-model.js b/canvas_modules/common-canvas/src/object-model/object-model.js index 20ce623f81..1349995ffb 100644 --- a/canvas_modules/common-canvas/src/object-model/object-model.js +++ b/canvas_modules/common-canvas/src/object-model/object-model.js @@ -1282,6 +1282,10 @@ export default class ObjectModel { return this.store.isRightFlyoutOpen(); } + setRightFlyoutWidth(wd) { + this.store.dispatch({ type: "SET_RIGHT_FLYOUT_CONFIG", data: { config: { panelWidth: wd } } }); + } + // --------------------------------------------------------------------------- // Bottom panel methods // --------------------------------------------------------------------------- diff --git a/canvas_modules/common-canvas/src/object-model/redux/canvas-store.js b/canvas_modules/common-canvas/src/object-model/redux/canvas-store.js index a662432f19..e2196b643c 100644 --- a/canvas_modules/common-canvas/src/object-model/redux/canvas-store.js +++ b/canvas_modules/common-canvas/src/object-model/redux/canvas-store.js @@ -75,7 +75,7 @@ export default class CanavasStore { texttoolbar: { isOpen: false }, contextmenu: { isOpen: false, menuDef: [], source: {} }, leftflyout: {}, - rightflyout: {}, + rightflyout: { panelWidth: 0 }, bottompanel: { panelHeight: 393 }, toppanel: { } }; diff --git a/canvas_modules/common-canvas/src/object-model/redux/reducers/rightflyout.js b/canvas_modules/common-canvas/src/object-model/redux/reducers/rightflyout.js index e3372f7415..9b7471e400 100644 --- a/canvas_modules/common-canvas/src/object-model/redux/reducers/rightflyout.js +++ b/canvas_modules/common-canvas/src/object-model/redux/reducers/rightflyout.js @@ -18,9 +18,7 @@ export default (state = {}, action) => { switch (action.type) { case "SET_RIGHT_FLYOUT_CONFIG": { if (action.data.config) { - return { - content: action.data.config.content, - isOpen: action.data.config.isOpen }; + return Object.assign({}, state, action.data.config); } return state; } diff --git a/canvas_modules/harness/cypress/e2e/canvas/bottom-panel.cy.js b/canvas_modules/harness/cypress/e2e/canvas/bottom-panel.cy.js index 0ea96b7e37..2e944b0158 100644 --- a/canvas_modules/harness/cypress/e2e/canvas/bottom-panel.cy.js +++ b/canvas_modules/harness/cypress/e2e/canvas/bottom-panel.cy.js @@ -42,7 +42,9 @@ describe("Testing bottom panel", function() { // Test bottom panel does not exceed max-size successfully cy.moveBottomPanelDivider(50); cy.verifyBottomPanelHeight(650); + }); + it("Testing bottom panel max height with rightFlyout open", function() { // Test bottom panel does not exceed max-size successfully with the right flyout open cy.setCanvasConfig({ "selectedShowRightFlyout": true }); cy.moveBottomPanelDivider(50); diff --git a/canvas_modules/harness/cypress/e2e/canvas/right-flyout.cy.js b/canvas_modules/harness/cypress/e2e/canvas/right-flyout.cy.js index 4f153fbae0..d69a1eb795 100644 --- a/canvas_modules/harness/cypress/e2e/canvas/right-flyout.cy.js +++ b/canvas_modules/harness/cypress/e2e/canvas/right-flyout.cy.js @@ -29,4 +29,30 @@ describe("Test for verifying the Right Flyout panel functionality and layout in cy.verifyRightFlyoutPanelWidth(300); cy.verifyRightFlyoutPanelHeight(709); }); + + it("Test ensuring Right Flyout panel drag is working correctly", function() { + cy.setCanvasConfig({ "selectedRightFlyoutDragToResize": true }); + cy.moveRightFlyoutDivider(400); + cy.verifyRightFlyoutPanelWidth(626); + }); + + it("Test ensuring Right Flyout panel drag only extends to a maximum width leaving width for canvas", function() { + cy.setCanvasConfig({ "selectedRightFlyoutDragToResize": true }); + cy.moveRightFlyoutDivider(100); + cy.verifyRightFlyoutPanelWidth(716); + + cy.moveRightFlyoutDivider(200); + cy.verifyRightFlyoutPanelWidth(927); + + cy.moveRightFlyoutDivider(500); + cy.verifyRightFlyoutPanelWidth(827); + }); + + it("Test ensuring Right Flyout panel drag is correctly enabled and disabled", function() { + cy.setCanvasConfig({ "selectedRightFlyoutDragToResize": false }); + cy.verifyIsRightFlyoutDragDisabled(); + + cy.setCanvasConfig({ "selectedRightFlyoutDragToResize": true }); + cy.verifyIsRightFlyoutDragEnabled(); + }); }); diff --git a/canvas_modules/harness/cypress/support/canvas/operation-cmds.js b/canvas_modules/harness/cypress/support/canvas/operation-cmds.js index 5169076916..f5b5495c30 100644 --- a/canvas_modules/harness/cypress/support/canvas/operation-cmds.js +++ b/canvas_modules/harness/cypress/support/canvas/operation-cmds.js @@ -86,3 +86,14 @@ Cypress.Commands.add("moveBottomPanelDivider", (y) => { .trigger("mouseup", 200, y, { view: win, force: true }); }); }); + +Cypress.Commands.add("moveRightFlyoutDivider", (x) => { + cy.window().then((win) => { + cy.get(".right-flyout-container .right-flyout-drag") + .trigger("mousedown", "center", { view: win, button: 0, force: true }); + cy.get("#canvas-div-0") + .trigger("mousemove", x, 200, { viewe: win, force: true }); + cy.get("#canvas-div-0") + .trigger("mouseup", x, 200, { view: win, force: true }); + }); +}); diff --git a/canvas_modules/harness/cypress/support/canvas/verification-cmds.js b/canvas_modules/harness/cypress/support/canvas/verification-cmds.js index d2bd3a3711..b505d9cbec 100644 --- a/canvas_modules/harness/cypress/support/canvas/verification-cmds.js +++ b/canvas_modules/harness/cypress/support/canvas/verification-cmds.js @@ -914,6 +914,16 @@ Cypress.Commands.add("verifyRightFlyoutPanelWidth", (width) => { }); }); +Cypress.Commands.add("verifyIsRightFlyoutDragDisabled", () => { + cy.get(".right-flyout-drag") + .should("not.exist"); +}); + +Cypress.Commands.add("verifyIsRightFlyoutDragEnabled", () => { + cy.get(".right-flyout-drag") + .should("exist"); +}); + Cypress.Commands.add("verifyRightFlyoutPanelHeight", (height) => { cy.get(".right-flyout-panel").should((element) => { compareCloseTo(element[0].offsetHeight, height); diff --git a/canvas_modules/harness/src/client/App.js b/canvas_modules/harness/src/client/App.js index 310db75a51..f4cc99ac82 100644 --- a/canvas_modules/harness/src/client/App.js +++ b/canvas_modules/harness/src/client/App.js @@ -235,6 +235,7 @@ class App extends React.Component { selectedLeftFlyoutUnderToolbar: false, selectedShowRightFlyout: false, selectedRightFlyoutUnderToolbar: false, + selectedRightFlyoutDragToResize: false, selectedPanIntoViewOnOpen: false, selectedExtraCanvasDisplayed: false, selectedSaveToPalette: false, @@ -2124,6 +2125,7 @@ class App extends React.Component { enableDropZoneOnExternalDrag: this.state.selectedDropZoneOnExternalDrag, enableLeftFlyoutUnderToolbar: this.state.selectedLeftFlyoutUnderToolbar, enableRightFlyoutUnderToolbar: this.state.selectedRightFlyoutUnderToolbar, + enableRightFlyoutDragToResize: this.state.selectedRightFlyoutDragToResize, enablePanIntoViewOnOpen: this.state.selectedPanIntoViewOnOpen, dropZoneCanvasContent: this.state.selectedDisplayCustomizedDropZoneContent ? this.dropZoneCanvasDiv : null, emptyCanvasContent: this.state.selectedDisplayCustomizedEmptyCanvasContent ? this.emptyCanvasDiv : null, @@ -2147,6 +2149,7 @@ class App extends React.Component { enableInternalObjectModel: this.state.selectedInternalObjectModel, enableDragWithoutSelect: this.state.selectedDragWithoutSelect, enablePaletteLayout: this.state.selectedPaletteLayout, + enableRightFlyoutDragToResize: this.state.selectedRightFlyoutDragToResize, selectedMoveNodesOnSupernodeResize: true, tipConfig: this.state.selectedTipConfig, schemaValidation: this.state.selectedSchemaValidation, diff --git a/canvas_modules/harness/src/client/components/sidepanel/canvas/sidepanel-canvas.jsx b/canvas_modules/harness/src/client/components/sidepanel/canvas/sidepanel-canvas.jsx index 73467a61c6..795704541a 100644 --- a/canvas_modules/harness/src/client/components/sidepanel/canvas/sidepanel-canvas.jsx +++ b/canvas_modules/harness/src/client/components/sidepanel/canvas/sidepanel-canvas.jsx @@ -772,6 +772,15 @@ export default class SidePanelForms extends React.Component { />
); + var enableRightFlyoutDragToResize = (
+ this.setStateValue(val, "selectedRightFlyoutDragToResize")} + /> +
); + var enableDragWithoutSelect = (
Top Panel
diff --git a/docs/pages/03.02.01-canvas-config.md b/docs/pages/03.02.01-canvas-config.md index b725a22745..48c9c09014 100644 --- a/docs/pages/03.02.01-canvas-config.md +++ b/docs/pages/03.02.01-canvas-config.md @@ -361,6 +361,9 @@ This is a boolean. The default is `true`. It is recommended you leave this set t #### **enableRightFlyoutUnderToolbar** This is a boolean. The default is false. If set to true the right flyout panel, when opened, will appear below the toolbar and will not cause the toolbar to compress. The default behavior is that the right flyout panel, when opened, will appear at the side of the toolbar and will compress the space available for the toolbar to be displayed. Warning: the notifications panel which is tied to the notifications icon in the toolbar will appear over the top of the right-side flyout with this option set to true. +#### **enableRightFlyoutDragToResize** +This is a boolean. The default is false. If set to true, the right flyout panel can be resized by dragging its left border. When hovering over the left border of the flyout, the cursor will change to indicate that resizing is possible. Users can drag the border to adjust the width of the flyout, allowing it to expand or collapse. This functionality offers more flexible layout options for the user. If set to false, the right-flyout panel, when open, will be displayed with a default width and cannot be resized by dragging its edge. The application can add its own sizing function if required. + #### **enableLeftFlyoutUnderToolbar** This is a boolean. The default is false. If set to true the left flyout panel, when opened, will appear below the toolbar and will not cause the toolbar to compress. The default behavior is that the left flyout panel, when opened, will appear at the side of the toolbar and will compress the space available for the toolbar to be displayed.