diff --git a/packages/survey-creator-core/src/components/action-container-view-model.ts b/packages/survey-creator-core/src/components/action-container-view-model.ts index 3f00d7ff94..d7ed5df612 100644 --- a/packages/survey-creator-core/src/components/action-container-view-model.ts +++ b/packages/survey-creator-core/src/components/action-container-view-model.ts @@ -14,6 +14,7 @@ import { SurveyCreatorModel } from "../creator-base"; import { settings } from "../creator-settings"; import { DesignerStateManager } from "./tabs/designer-state-manager"; import { TabDesignerPlugin } from "./tabs/designer-plugin"; +import { isPanelDynamic } from "../survey-elements"; export class SurveyElementActionContainer extends AdaptiveActionContainer { private needToShrink(item: Action, shrinkStart: boolean, shrinkEnd: boolean) { @@ -93,6 +94,11 @@ export class SurveyElementAdornerBase e protected expandCollapseAction: IAction; protected designerStateManager: DesignerStateManager; @property({ defaultValue: true }) allowDragging: boolean; + + protected get dragInsideCollapsedContainer(): boolean { + return this.collapsed && this.creator.dragDropSurveyElements.insideContainer; + } + @property({ defaultValue: true }) allowExpandCollapse: boolean; @property({ onSet: (val, target: SurveyElementAdornerBase) => { @@ -108,6 +114,34 @@ export class SurveyElementAdornerBase e }) collapsed: boolean; @property() renderedCollapsed: boolean; + private dragCollapsedTimer; + + protected get canExpandOnDrag() { + return this.surveyElement.isPanel || this.surveyElement.isPage || isPanelDynamic(this.surveyElement); + } + private draggedIn = false; + protected dragIn() { + if (!this.draggedIn) { + if (this.canExpandOnDrag && this.collapsed) { + this.draggedIn = true; + this.dragCollapsedTimer = setTimeout(() => { + this.expandWithDragIn(); + }, this.creator.expandOnDragTimeOut); + } + } + } + protected expandWithDragIn() { + this.collapsed = false; + this.dragCollapsedTimer = undefined; + } + + protected dragOut() { + if (this.draggedIn) { + clearTimeout(this.dragCollapsedTimer); + this.draggedIn = false; + } + } + public dblclick(event) { if (this.allowExpandCollapse) this.collapsed = !this.collapsed; event.stopPropagation(); diff --git a/packages/survey-creator-core/src/components/page.scss b/packages/survey-creator-core/src/components/page.scss index 0b1f1cf590..fb3320811d 100644 --- a/packages/survey-creator-core/src/components/page.scss +++ b/packages/survey-creator-core/src/components/page.scss @@ -36,7 +36,7 @@ svc-page { visibility: hidden; top: calcSize(1); inset-inline-end: 0; // right - padding: 0 calcSize(1.5); + padding: 0 calcSize(1); z-index: 1; .sv-action-bar-separator { @@ -139,6 +139,33 @@ svc-page { visibility: visible; } } + +.svc-creator .svc-page .svc-page__content--collapsed { + &::after { + content: ""; + width: 100%; + height: 100%; + position: absolute; + top: 0; + left: 0; + border: 2px $border dashed; + margin: -2px; + border-radius: calcSize(1.25); + box-sizing: content-box; + pointer-events: none; + } + &.svc-page__content--collapsed-drag-over-inside { + box-shadow: 0 0 0 2px $primary; + background: $primary-light; + animation: collapsed-drag-over-inside-blinking 1s infinite; + &::after { + border: 2px $primary solid; + background: $primary-light; + animation: collapsed-drag-over-inside-blinking 1s infinite; + } + } +} + .svc-creator--mobile { .svc-page .svc-page__content--collapsed { &::after { @@ -151,8 +178,6 @@ svc-page { &.svc-creator .svc-page .svc-page__content--selected:focus, .svc-hovered.svc-page__content { &.svc-page__content--selected { - box-shadow: 0 0 0 2px inset $secondary; - box-shadow: 0 0 0 2px inset var(--ctr-survey-page-border-color-selected, $secondary); background: var(--ctr-survey-page-background-color-selected, $secondary-backcolor-semi-light); diff --git a/packages/survey-creator-core/src/components/page.ts b/packages/survey-creator-core/src/components/page.ts index 4efd1e972b..b938f486a2 100644 --- a/packages/survey-creator-core/src/components/page.ts +++ b/packages/survey-creator-core/src/components/page.ts @@ -40,6 +40,10 @@ export class PageAdorner extends SurveyElementAdornerBase { this.attachElement(page); } + protected get dragInsideCollapsedContainer(): boolean { + return this.collapsed; + } + protected attachElement(surveyElement: PageModel): void { super.attachElement(surveyElement); this.dragTypeOverMe = null; @@ -184,6 +188,12 @@ export class PageAdorner extends SurveyElementAdornerBase { result += " svc-page--drag-over-empty-no-add-button"; } } + if (!!this.dragTypeOverMe && this.collapsed) { + this.dragIn(); + result += " svc-page__content--collapsed-drag-over-inside"; + } else { + this.dragOut(); + } if (this.isGhost) { return result + " svc-page__content--new"; } diff --git a/packages/survey-creator-core/src/components/question.scss b/packages/survey-creator-core/src/components/question.scss index 1d64a58448..7ff064bad5 100644 --- a/packages/survey-creator-core/src/components/question.scss +++ b/packages/survey-creator-core/src/components/question.scss @@ -17,7 +17,9 @@ svc-question { display: flex; flex-direction: column; justify-content: stretch; - + &.svc-question__adorner--collapsed { + height: fit-content; + } .sv-action-bar { overflow: visible; @@ -270,6 +272,23 @@ svc-question { .svc-question__content--selected:not(.svc-question__content--dragged) { box-shadow: 0 0 0 2px $secondary; } +.svc-question__content--collapsed-drag-over-inside:not(.svc-question__content--dragged) { + box-shadow: 0 0 0 2px $primary; + background: $primary-light; + animation: collapsed-drag-over-inside-blinking 1s; +} + +@keyframes collapsed-drag-over-inside-blinking { + 0%{ background: $primary-light } + 40%{ background: $primary-light } + 50%{ background: transparent } + 55%{ background: $primary-light } + 65%{ background: transparent } + 70%{ background: $primary-light } + 80%{ background: transparent } + 85%{ background: $primary-light } + 100%{ background: $primary-light } +} .svc-question__content--selected:not(.svc-question__content--dragged), .svc-creator:not(.svc-creator--mobile) diff --git a/packages/survey-creator-core/src/components/question.ts b/packages/survey-creator-core/src/components/question.ts index c802df7662..1d121ac7f9 100644 --- a/packages/survey-creator-core/src/components/question.ts +++ b/packages/survey-creator-core/src/components/question.ts @@ -34,7 +34,7 @@ import { SurveyElementAdornerBase } from "./action-container-view-model"; require("./question.scss"); import { settings } from "../creator-settings"; import { StringEditorConnector, StringItemsNavigatorBase } from "./string-editor"; -import { DragDropSurveyElements } from "../survey-elements"; +import { DragDropSurveyElements, isPanelDynamic } from "../survey-elements"; import { QuestionToolbox, QuestionToolboxItem } from "../toolbox"; export interface QuestionBannerParams { @@ -130,49 +130,47 @@ export class QuestionAdornerViewModel extends SurveyElementAdornerBase { if (this.isDragMe) { result += " svc-question__content--dragged"; - } else { - result = result.replace(" svc-question__content--dragged", ""); - } - - if (this.dragTypeOverMe === DragTypeOverMeEnum.InsideEmptyPanel) { - result += " svc-question__content--drag-over-inside"; - } else { - result = result.replace(" svc-question__content--drag-over-inside", ""); } - if (this.dragTypeOverMe === DragTypeOverMeEnum.Left) { - result += " svc-question__content--drag-over-left"; + if (!!this.dragTypeOverMe && (this.canExpandOnDrag) && this.dragInsideCollapsedContainer) { + this.dragIn(); + result += " svc-question__content--collapsed-drag-over-inside"; } else { - result = result.replace(" svc-question__content--drag-over-left", ""); + this.dragOut(); } - if (this.dragTypeOverMe === DragTypeOverMeEnum.Right) { - result += " svc-question__content--drag-over-right"; - } else { - result = result.replace(" svc-question__content--drag-over-right", ""); + if (this.dragTypeOverMe === DragTypeOverMeEnum.InsideEmptyPanel) { + result += " svc-question__content--drag-over-inside"; } + if (!this.dragInsideCollapsedContainer) { + if (this.dragTypeOverMe === DragTypeOverMeEnum.Left) { + result += " svc-question__content--drag-over-left"; + } - if (this.dragTypeOverMe === DragTypeOverMeEnum.Top) { - result += " svc-question__content--drag-over-top"; - } else { - result = result.replace(" svc-question__content--drag-over-top", ""); - } + if (this.dragTypeOverMe === DragTypeOverMeEnum.Right) { + result += " svc-question__content--drag-over-right"; + } - if (this.dragTypeOverMe === DragTypeOverMeEnum.Bottom) { - result += " svc-question__content--drag-over-bottom"; - } else { - result = result.replace(" svc-question__content--drag-over-bottom", ""); - } - if (this.creator) { - result = this.creator.getElementAddornerCssCallback(this.surveyElement, result); + if (this.dragTypeOverMe === DragTypeOverMeEnum.Top) { + result += " svc-question__content--drag-over-top"; + } + if (this.dragTypeOverMe === DragTypeOverMeEnum.Bottom) { + result += " svc-question__content--drag-over-bottom"; + } + if (this.creator) { + result = this.creator.getElementAddornerCssCallback(this.surveyElement, result); + } } return result; } - + protected expandWithDragIn() { + super.expandWithDragIn(); + this.element.dragTypeOverMe = null; + this.creator.dragDropSurveyElements.dropTarget = null; + } get isDragMe(): boolean { return this.surveyElement.isDragMe; } - get dragTypeOverMe() { return this.element.dragTypeOverMe; } diff --git a/packages/survey-creator-core/src/creator-base.ts b/packages/survey-creator-core/src/creator-base.ts index b12fefa686..b704f1b7cf 100644 --- a/packages/survey-creator-core/src/creator-base.ts +++ b/packages/survey-creator-core/src/creator-base.ts @@ -1888,8 +1888,9 @@ export class SurveyCreatorModel extends Base this.dragDropSurveyElements.onDragEnd.add((sender, options) => { this.stopUndoRedoTransaction(); const editTitle = isDraggedFromToolbox && this.startEditTitleOnQuestionAdded; - this.selectElement(options.draggedElement, undefined, false, editTitle); isDraggedFromToolbox = false; + if (!options.draggedElement) return; + this.selectElement(options.draggedElement, undefined, false, editTitle); this.onDragEnd.fire(this, options); if (!options.fromElement) { this.setModified({ type: "ADDED_FROM_TOOLBOX", question: options.draggedElement }); @@ -3814,6 +3815,8 @@ export class SurveyCreatorModel extends Base */ @property({ defaultValue: "never" }) expandCollapseButtonVisibility?: "never" | "onhover" | "always"; + expandOnDragTimeOut: number = 1000; + selectFromStringEditor: boolean; @property({ diff --git a/packages/survey-creator-core/src/survey-elements.ts b/packages/survey-creator-core/src/survey-elements.ts index 9647963e80..6015222994 100644 --- a/packages/survey-creator-core/src/survey-elements.ts +++ b/packages/survey-creator-core/src/survey-elements.ts @@ -1,4 +1,4 @@ -import { DragDropAllowEvent, DragDropCore, DragTypeOverMeEnum, IElement, IPanel, IShortcutText, ISurveyElement, JsonObject, PageModel, PanelModelBase, QuestionRowModel, Serializer, SurveyModel } from "survey-core"; +import { DragDropAllowEvent, DragDropCore, DragTypeOverMeEnum, IElement, IPanel, IShortcutText, ISurveyElement, JsonObject, PageModel, PanelModelBase, QuestionPanelDynamicModel, QuestionRowModel, Serializer, SurveyModel } from "survey-core"; import { settings } from "./creator-settings"; import { IQuestionToolboxItem } from "./toolbox"; import { SurveyHelper } from "./survey-helper"; @@ -43,6 +43,10 @@ export function calculateDragOverLocation(clientX: number, clientY: number, drop } } +export function isPanelDynamic(element: ISurveyElement) { + return element instanceof QuestionPanelDynamicModel; +} + export class DragDropSurveyElements extends DragDropCore { public static newGhostPage: PageModel = null; public static restrictDragQuestionBetweenPages: boolean = false; @@ -50,7 +54,7 @@ export class DragDropSurveyElements extends DragDropCore { public static nestedPanelDepth: number = -1; public static ghostSurveyElementName = "sv-drag-drop-ghost-survey-element-name"; // before renaming use globa search (we have also css selectors) - private insideEmptyContainer = null; + public insideContainer = null; protected prevIsEdge: any = null; // protected ghostSurveyElement: IElement = null; protected dragOverIndicatorElement: any = null; @@ -154,7 +158,8 @@ export class DragDropSurveyElements extends DragDropCore { } protected getDropTargetByDataAttributeValue(dataAttributeValue: string, dropTargetNode: HTMLElement, event: PointerEvent): any { - this.removeDragOverMarker(this.dragOverIndicatorElement); + const oldDragOverIndicatorElement = this.dragOverIndicatorElement; + this.dragOverIndicatorElement = null; if (!dataAttributeValue) { @@ -179,10 +184,6 @@ export class DragDropSurveyElements extends DragDropCore { // drop to page let page: any = this.survey.getPageByName(dataAttributeValue); if (page) { - if (page.elements.length !== 0) { - // TODO we can't drop on not empty page directly for now - return null; - } return page; } @@ -199,12 +200,12 @@ export class DragDropSurveyElements extends DragDropCore { }); // drop to paneldynamic - if (dropTarget.getType() === "paneldynamic" && this.insideEmptyContainer) { + if (dropTarget.getType() === "paneldynamic" && this.insideContainer) { dropTarget = (dropTarget).template; } // drop to matrix detail panel - if ((dropTarget.getType() === "matrixdropdown" || dropTarget.getType() === "matrixdynamic") && (dropTarget).detailPanelMode !== "none" && this.insideEmptyContainer) { + if ((dropTarget.getType() === "matrixdropdown" || dropTarget.getType() === "matrixdynamic") && (dropTarget).detailPanelMode !== "none" && this.insideContainer) { dropTarget = (dropTarget).detailPanel; } @@ -217,7 +218,9 @@ export class DragDropSurveyElements extends DragDropCore { let page: any = this.survey.getPageByName(dataAttributeValue); dropTarget.__page = page; } - + if (this.dragOverIndicatorElement != oldDragOverIndicatorElement) { + this.removeDragOverMarker(oldDragOverIndicatorElement); + } this.dragOverIndicatorElement = dragOverElement; return dropTarget; // EO drop to question or panel @@ -311,8 +314,8 @@ export class DragDropSurveyElements extends DragDropCore { return allowOptions.allow; } public dragOverCore(dropTarget: ISurveyElement, dragOverLocation: DragTypeOverMeEnum): void { - this.removeDragOverMarker(this.dragOverIndicatorElement); - this.removeDragOverMarker(this.dropTarget); + const oldDragOverIndicatorElement = this.dragOverIndicatorElement; + const oldDropTarget = this.dropTarget; if (this.isSameElement(dropTarget)) { this.allowDropHere = false; return; @@ -339,6 +342,8 @@ export class DragDropSurveyElements extends DragDropCore { dragOverIndicator.dragTypeOverMe = this.dragOverLocation; } } + if (this.dragOverIndicatorElement != oldDragOverIndicatorElement) this.removeDragOverMarker(oldDragOverIndicatorElement); + if (this.dropTarget != oldDropTarget) this.removeDragOverMarker(oldDropTarget); } private isSameElement(target: ISurveyElement): boolean { while (!!target) { @@ -358,12 +363,12 @@ export class DragDropSurveyElements extends DragDropCore { this.banDropHere(); return; } - this.insideEmptyContainer = !calculateIsEdge(dropTargetNode, event.clientY) && !calculateIsSide(dropTargetNode, event.clientX); + this.insideContainer = !calculateIsEdge(dropTargetNode, event.clientY) && !calculateIsSide(dropTargetNode, event.clientX); const dropTarget = this.getDropTargetByNode(dropTargetNode, event); let dragOverLocation = calculateDragOverLocation(event.clientX, event.clientY, dropTargetNode); if (dropTarget && (dropTarget.isPanel || dropTarget.isPage) && dropTarget.elements.length === 0) { - if (dropTarget.isPage || this.insideEmptyContainer) { + if (dropTarget.isPage || this.insideContainer) { dragOverLocation = DragTypeOverMeEnum.InsideEmptyPanel; } } @@ -421,8 +426,9 @@ export class DragDropSurveyElements extends DragDropCore { srcContainer.removeElement(src); } const dest = this.dragOverIndicatorElement?.isPanel ? this.dragOverIndicatorElement : this.dropTarget; + if (dest.isPage && dest.elements.length > 0 && !this.insideContainer) return; const isTargetIsContainer = dest.isPanel || dest.isPage; - if (isTargetIsContainer && this.dragOverLocation == DragTypeOverMeEnum.InsideEmptyPanel) { + if (isTargetIsContainer && this.insideContainer) { dest.insertElement(src); } else { (dest.parent || dest.page).insertElement(src, dest, convertLocation()); @@ -442,7 +448,7 @@ export class DragDropSurveyElements extends DragDropCore { } public clear(): void { - this.insideEmptyContainer = null; + this.insideContainer = null; this.removeDragOverMarker(this.prevDropTarget); this.removeDragOverMarker(this.dropTarget); this.removeDragOverMarker(this.dragOverIndicatorElement); diff --git a/packages/survey-creator-core/tests/dragdrop-elements.tests.ts b/packages/survey-creator-core/tests/dragdrop-elements.tests.ts index 02f2a00d1e..97236e6fe2 100644 --- a/packages/survey-creator-core/tests/dragdrop-elements.tests.ts +++ b/packages/survey-creator-core/tests/dragdrop-elements.tests.ts @@ -810,6 +810,7 @@ test("drag drop to panel vertical", () => { const ddHelper: any = new DragDropSurveyElements(survey); ddHelper.draggedElement = q1; + ddHelper.insideContainer = true; ddHelper.dragOverCore(p1, DragTypeOverMeEnum.InsideEmptyPanel); ddHelper.doDrop(); @@ -828,6 +829,7 @@ test("drag drop to panel vertical", () => { }); ddHelper.draggedElement = q2; + ddHelper.insideContainer = false; ddHelper.dragOverCore(survey.getQuestionByName("q1"), DragTypeOverMeEnum.Top); ddHelper.doDrop(); @@ -896,6 +898,7 @@ test("drag drop to panel horizontal", () => { const ddHelper: any = new DragDropSurveyElements(survey); ddHelper.draggedElement = q1; + ddHelper.insideContainer = true; ddHelper.dragOverCore(p1, DragTypeOverMeEnum.InsideEmptyPanel); ddHelper.doDrop(); @@ -913,6 +916,7 @@ test("drag drop to panel horizontal", () => { }] }); + ddHelper.insideContainer = false; ddHelper.draggedElement = q2; ddHelper.dragOverCore(survey.getQuestionByName("q1"), DragTypeOverMeEnum.Left); ddHelper.doDrop(); @@ -1200,7 +1204,7 @@ test("drag drop one empty panel to other empty panel - https://github.com/survey const ddHelper: any = new DragDropSurveyElements(survey); ddHelper.draggedElement = p2; - + ddHelper.insideContainer = true; ddHelper.dragOverCore(p1, DragTypeOverMeEnum.InsideEmptyPanel); ddHelper.doDrop(); diff --git a/testCafe/designer/drag-drop.ts b/testCafe/designer/drag-drop.ts index 75707aaa32..9f23ed9d7f 100644 --- a/testCafe/designer/drag-drop.ts +++ b/testCafe/designer/drag-drop.ts @@ -372,6 +372,257 @@ test("Drag Drop to Panel", async (t) => { const resultJson = await getJSON(); await t.expect(resultJson).eql(expectedJson); }); + +test("Drag Drop to collapsed panel", async (t) => { + await ClientFunction(() => { window["creator"].expandCollapseButtonVisibility = "always"; })(); + + await t.resizeWindow(1600, 1000); + const json = { + pages: [ + { + name: "page1", + elements: [ + { + type: "panel", + name: "panel1", + elements: [{ + type: "text", + name: "q1" + }] + } + ] + } + ] + }; + await setJSON(json); + + const expectedJson = { + "pages": [ + { + "name": "page1", + "elements": [ + { + "type": "panel", + "name": "panel1", + "elements": [ + { + "type": "text", + "name": "q1" + }, + { + "type": "radiogroup", + "name": "question1", + "choices": [ + "Item 1", + "Item 2", + "Item 3" + ] + } + ] + } + ] + } + ] + }; + + const qCollapseButton = Selector(".svc-question__content #collapse"); + await t.click(qCollapseButton.filterVisible()); + + const Panel = Selector("[data-sv-drop-target-survey-element=\"panel1\"]"); + const toolboxToolAction = Selector(".svc-toolbox__tool > .sv-action__content"); + + await t + .hover(toolboxToolAction) + .dispatchEvent(toolboxToolAction, "pointerdown") + .hover(Panel, { offsetX: 150 }) + .expect(Panel.find(".svc-question__content--collapsed-drag-over-inside").exists).ok() + .dispatchEvent(toolboxToolAction, "pointerup"); + const resultJson0 = await getJSON(); + await t.expect(resultJson0).eql(expectedJson); + + await t + .hover(toolboxToolAction) + .dispatchEvent(toolboxToolAction, "pointerdown") + .hover(Panel, { offsetX: 5 }) + .expect(Panel.find(".svc-question__content--drag-over-left").exists).ok() + .expect(Panel.find(".svc-question__content--collapsed-drag-over-inside").exists).notOk() + .wait(2000) + .hover(Panel, { offsetX: 100 }) + .expect(Panel.find(".svc-question__content--collapsed").exists).ok() + .wait(2000) + .expect(Panel.find(".svc-question__content--collapsed").exists).notOk() + .expect(Panel.find(".svc-question__content--drag-over-left").exists).notOk() + .dispatchEvent(toolboxToolAction, "pointerup"); +}); + +test("Drag Drop to selected collapsed panel", async (t) => { + await ClientFunction(() => { window["creator"].expandCollapseButtonVisibility = "always"; })(); + + await t.resizeWindow(1600, 1000); + const json = { + pages: [ + { + name: "page1", + elements: [ + { + type: "panel", + name: "panel1", + elements: [{ + type: "text", + name: "q1" + }] + } + ] + } + ] + }; + await setJSON(json); + + const qCollapseButton = Selector(".svc-question__content #collapse"); + await t.click(qCollapseButton.filterVisible()); + + const Panel = Selector("[data-sv-drop-target-survey-element=\"panel1\"]"); + const toolboxToolAction = Selector(".svc-toolbox__tool > .sv-action__content"); + + await t + .click(Panel, { offsetX: 1, offsetY: 1 }) + .hover(toolboxToolAction) + .dispatchEvent(toolboxToolAction, "pointerdown") + .hover(Panel, { offsetX: 100 }) + .expect(Panel.find(".svc-question__content--collapsed").exists).ok() + .expect(Panel.find(".svc-question__content--collapsed").exists).notOk({ timeout: 3000 }) + .dispatchEvent(toolboxToolAction, "pointerup"); + + const resultJson0 = await getJSON(); + await t.expect(resultJson0).eql(json); + + await t.expect(Selector(".spg-question[data-name=name] input").value).eql("panel1"); +}); + +test("Drag Drop to collapsed dynamic panel", async (t) => { + await ClientFunction(() => { + window["creator"].expandCollapseButtonVisibility = "always"; + window["creator"].expandOnDragTimeOut = 2000; + })(); + + await t.resizeWindow(1600, 1000); + const json = { + "pages": [ + { + "name": "page1", + "elements": [ + { + "type": "paneldynamic", + "name": "panel1", + "templateElements": [ + { + "type": "text", + "name": "question1" + } + ] + } + ] + } + ] + }; + await setJSON(json); + + const qCollapseButton = Selector(".svc-question__content #collapse"); + await t.click(qCollapseButton.filterVisible()); + + const Panel = Selector("[data-sv-drop-target-survey-element=\"panel1\"]"); + const toolboxToolAction = Selector(".svc-toolbox__tool > .sv-action__content"); + await t + .hover(toolboxToolAction) + .dispatchEvent(toolboxToolAction, "pointerdown") + .hover(Panel, { offsetX: 5 }) + .expect(Panel.find(".svc-question__content--drag-over-left").exists).ok() + .expect(Panel.find(".svc-question__content--collapsed-drag-over-inside").exists).notOk() + .wait(2000) + .hover(Panel, { offsetX: 100, speed: 0.5 }) + .expect(Panel.find(".svc-question__content--collapsed").exists).ok() + .wait(2000) + .expect(Panel.find(".svc-question__content--collapsed").exists).notOk() + .expect(Panel.find(".svc-question__content--drag-over-left").exists).notOk() + .dispatchEvent(toolboxToolAction, "pointerup"); + + const resultJson = await getJSON(); + await t.expect(resultJson).eql(json); +}); + +test("Drag Drop to collapsed page", async (t) => { + await ClientFunction(() => { window["creator"].expandCollapseButtonVisibility = "always"; })(); + + await t.resizeWindow(1600, 1000); + const json = { + pages: [ + { + name: "page1", + elements: [ + { + type: "panel", + name: "panel1", + elements: [{ + type: "text", + name: "q1" + }] + }, + ] + } + ] + }; + await setJSON(json); + + const qCollapseButton = Selector(".svc-page__content #collapse"); + await t.click(qCollapseButton.filterVisible()); + + const Page = Selector(".svc-page"); + const toolboxToolAction = Selector(".svc-toolbox__tool > .sv-action__content"); + const expectedJson = { + pages: [ + { + name: "page1", + elements: [ + { + type: "panel", + name: "panel1", + elements: [{ + type: "text", + name: "q1" + }] + }, { + "type": "radiogroup", + "name": "question1", + "choices": [ + "Item 1", + "Item 2", + "Item 3" + ] + } + ] + } + ] + }; + + await t + .hover(toolboxToolAction) + .dispatchEvent(toolboxToolAction, "pointerdown") + .hover(Page, { offsetX: 150 }) + .expect(Page.find(".svc-page__content--collapsed-drag-over-inside").exists).ok() + .dispatchEvent(toolboxToolAction, "pointerup"); + const resultJson0 = await getJSON(); + await t.expect(resultJson0).eql(expectedJson); + + await t + .hover(toolboxToolAction) + .dispatchEvent(toolboxToolAction, "pointerdown") + .hover(Page) + + .expect(Page.find(".svc-page__content--collapsed").exists).ok() + .wait(2000) + .expect(Page.find(".svc-page__content--collapsed").exists).notOk(); +}); + test("Drag Drop Question from a panel", async (t) => { await t.resizeWindow(2560, 1440); const json = { diff --git a/visualRegressionTests/tests/designer/drag-drop.ts b/visualRegressionTests/tests/designer/drag-drop.ts index ba330be02a..03ecffa27f 100644 --- a/visualRegressionTests/tests/designer/drag-drop.ts +++ b/visualRegressionTests/tests/designer/drag-drop.ts @@ -671,4 +671,87 @@ test("Drag Drop (choices): scroll", async (t) => { await takeElementScreenshot("drag-drop-scroll.png", newGhostPagePage, t, comparer); }); -}); \ No newline at end of file +}); + +test("Drag Drop to collapsed panel", async (t) => { + await wrapVisualTest(t, async (t, comparer) => { + await ClientFunction(() => { + window["creator"].expandCollapseButtonVisibility = "onhover"; + window["creator"].expandOnDragTimeOut = 1000000; + document.head.insertAdjacentHTML("beforeend", ""); + })(); + + await t.resizeWindow(1600, 1000); + const json = { + pages: [ + { + name: "page1", + elements: [ + { + type: "panel", + name: "panel1", + elements: [{ + type: "text", + name: "q1" + }] + } + ] + } + ] + }; + await setJSON(json); + + const qCollapseButton = Selector(".svc-question__content #collapse"); + const Panel = Selector("[data-sv-drop-target-survey-element=\"panel1\"]"); + await t.hover(Panel, { offsetX: 5, offsetY: 5 }); + await t.click(qCollapseButton.filterVisible()); + + const toolboxToolAction = Selector(".svc-toolbox__tool > .sv-action__content"); + await t + .hover(toolboxToolAction) + .dispatchEvent(toolboxToolAction, "pointerdown") + .hover(Panel); + await takeElementScreenshot("drag-drop-in-collapsed-panel.png", Selector(".svc-page__content"), t, comparer); + }); +}); + +test("Drag Drop to collapsed page", async (t) => { + await wrapVisualTest(t, async (t, comparer) => { + await ClientFunction(() => { + window["creator"].expandCollapseButtonVisibility = "onhover"; + window["creator"].expandOnDragTimeOut = 1000000; + document.head.insertAdjacentHTML("beforeend", ""); + })(); + + await t.resizeWindow(1600, 500); + const json = { + pages: [ + { + name: "page1", + elements: [ + { + type: "panel", + name: "panel1", + elements: [{ + type: "text", + name: "q1" + }] + } + ] + } + ] + }; + await setJSON(json); + const qCollapseButton = Selector(".svc-page__content #collapse"); + const Page = Selector(".svc-page"); + await t.hover(Page, { offsetX: 5, offsetY: 5 }); + await t.click(qCollapseButton.filterVisible()); + + const toolboxToolAction = Selector(".svc-toolbox__tool > .sv-action__content"); + await t + .hover(toolboxToolAction) + .dispatchEvent(toolboxToolAction, "pointerdown") + .hover(Page); + await takeElementScreenshot("drag-drop-in-collapsed-page.png", ".svc-tab-designer_content", t, comparer); + }); +}); diff --git a/visualRegressionTests/tests/designer/etalons/creator-mobile-page-selected-paddings.png b/visualRegressionTests/tests/designer/etalons/creator-mobile-page-selected-paddings.png index a6cec89141..d71f44548b 100644 Binary files a/visualRegressionTests/tests/designer/etalons/creator-mobile-page-selected-paddings.png and b/visualRegressionTests/tests/designer/etalons/creator-mobile-page-selected-paddings.png differ diff --git a/visualRegressionTests/tests/designer/etalons/drag-drop-in-collapsed-page.png b/visualRegressionTests/tests/designer/etalons/drag-drop-in-collapsed-page.png new file mode 100644 index 0000000000..2e18aa4032 Binary files /dev/null and b/visualRegressionTests/tests/designer/etalons/drag-drop-in-collapsed-page.png differ diff --git a/visualRegressionTests/tests/designer/etalons/drag-drop-in-collapsed-panel.png b/visualRegressionTests/tests/designer/etalons/drag-drop-in-collapsed-panel.png new file mode 100644 index 0000000000..aa53a56c46 Binary files /dev/null and b/visualRegressionTests/tests/designer/etalons/drag-drop-in-collapsed-panel.png differ diff --git a/visualRegressionTests/tests/designer/etalons/page-adorner-collapsed-selected.png b/visualRegressionTests/tests/designer/etalons/page-adorner-collapsed-selected.png new file mode 100644 index 0000000000..5316664732 Binary files /dev/null and b/visualRegressionTests/tests/designer/etalons/page-adorner-collapsed-selected.png differ diff --git a/visualRegressionTests/tests/designer/etalons/page-adorner-collapsed.png b/visualRegressionTests/tests/designer/etalons/page-adorner-collapsed.png index 8f46e240b7..17e93ffa48 100644 Binary files a/visualRegressionTests/tests/designer/etalons/page-adorner-collapsed.png and b/visualRegressionTests/tests/designer/etalons/page-adorner-collapsed.png differ diff --git a/visualRegressionTests/tests/designer/etalons/page-adorner-expanded.png b/visualRegressionTests/tests/designer/etalons/page-adorner-expanded.png index a4329853da..30e3b81509 100644 Binary files a/visualRegressionTests/tests/designer/etalons/page-adorner-expanded.png and b/visualRegressionTests/tests/designer/etalons/page-adorner-expanded.png differ diff --git a/visualRegressionTests/tests/designer/etalons/page-content-click.png b/visualRegressionTests/tests/designer/etalons/page-content-click.png index 5c2510d1ea..f1f7b352e0 100644 Binary files a/visualRegressionTests/tests/designer/etalons/page-content-click.png and b/visualRegressionTests/tests/designer/etalons/page-content-click.png differ diff --git a/visualRegressionTests/tests/designer/etalons/page-content-hover.png b/visualRegressionTests/tests/designer/etalons/page-content-hover.png index 575cc3005b..fd499679e2 100644 Binary files a/visualRegressionTests/tests/designer/etalons/page-content-hover.png and b/visualRegressionTests/tests/designer/etalons/page-content-hover.png differ diff --git a/visualRegressionTests/tests/designer/etalons/page-selected-responsive.png b/visualRegressionTests/tests/designer/etalons/page-selected-responsive.png index 26d8f9fcea..ccc7d800ba 100644 Binary files a/visualRegressionTests/tests/designer/etalons/page-selected-responsive.png and b/visualRegressionTests/tests/designer/etalons/page-selected-responsive.png differ diff --git a/visualRegressionTests/tests/designer/etalons/page-title-click.png b/visualRegressionTests/tests/designer/etalons/page-title-click.png index bb39b4be3b..d17d15da4f 100644 Binary files a/visualRegressionTests/tests/designer/etalons/page-title-click.png and b/visualRegressionTests/tests/designer/etalons/page-title-click.png differ diff --git a/visualRegressionTests/tests/designer/surface.ts b/visualRegressionTests/tests/designer/surface.ts index cc07975fe8..adee04a7b0 100644 --- a/visualRegressionTests/tests/designer/surface.ts +++ b/visualRegressionTests/tests/designer/surface.ts @@ -2161,11 +2161,11 @@ test("Question adorner - collapsed", async (t) => { test("Page adorner - collapsed", async (t) => { await wrapVisualTest(t, async (t, comparer) => { - await t.resizeWindow(1920, 1080); + await t.resizeWindow(1600, 500); const json = { elements: [ { - type: "html", + type: "expression", name: "question1" } ] @@ -2178,11 +2178,13 @@ test("Page adorner - collapsed", async (t) => { const qCollapseButton = Selector(".svc-page__content #collapse"); await t.hover(qContent.nth(0), { offsetX: 10, offsetY: 10 }); await t.expect(qContent.nth(0).hasClass("svc-hovered")).ok(); - await takeElementScreenshot("page-adorner-expanded.png", qContent.nth(0), t, comparer); + await takeElementScreenshot("page-adorner-expanded.png", ".svc-tab-designer_content", t, comparer); await t.click(qContent.nth(0), { offsetX: 10, offsetY: 10 }); await t.click(qCollapseButton.filterVisible()); - await t.hover(".svc-toolbox"); - await takeElementScreenshot("page-adorner-collapsed.png", qContent.nth(0), t, comparer); + await t.hover(".svc-toolbox", { speed: 0.1 }); + await takeElementScreenshot("page-adorner-collapsed-selected.png", ".svc-tab-designer_content", t, comparer); + await t.click(".svc-tab-designer_content", { offsetX: 1, offsetY: 1 }); + await takeElementScreenshot("page-adorner-collapsed.png", ".svc-tab-designer_content", t, comparer); }); });