Skip to content

Commit

Permalink
Issue/5680-Expand-panels-and-pages-on-dragged-in (#5746)
Browse files Browse the repository at this point in the history
* #5610 Add an option to expand and collapse pages on a design surface
Fixes #5610

* #5610 - add option

* #5610 - support doubleclick

* #5610 add screenshots

* #5610 - fix unit-tests

* #5610 fixed react event bubbling
Fixes #5610

* #5610 - do not expand on doubleclick when setting is "never"

* #5610 - key for pages in vue

* #5610 - move page collapse button to toolbar

* #5610 broken double click
Fixes #5610

* #5610 fixed page styles
Fixes #5610

* #5610 - fix border radius for dashed page

* #5610 - updated screenshots

* #5610 - keep inner border for mobile pages

* #5610 - update screenshots and mask

* #5610 - update screenshots

* #5610 - fixed tests

* #5680 Expand panels and pages on dragged in
Fixes #5680

* #5610 refresh screenshots
Fixes #5610

* #5680 Expand panels and pages on dragged in Fixes #5680

* #5680 fixed collapsed page color priority on drag in
Fixes #5680

* #5680 fix styles and add blinking
Fixes #5680

* #5680 Expand panels and pages on dragged in
Fixes #5680

* #5680 - revert unnecessery changes

* #5680 - revert broken merge

* #5680 - add tests

* #5680 - removed calculatedCollapsed property

* #5680 - restore renderedCollapsed

* #5680 - switch off animation in tests

* #5680 - update screenshot

* #5680 fix dragging and timers
Fixes #5680

* #5680 blink for selected page
Fixes #5680

* #5680 - supported dynamic panel

* #5680 Expand panels and pages on dragged in
Fixes #5680

* Revert "#5680 Expand panels and pages on dragged in"

This reverts commit 73adf43.

* #5680 Expand panels and pages on dragged in
Fixes #5680

* #5680 Expand panels and pages on dragged in - add test for dynamic panel
Fixes #5680

* #5680 - fix styles

* #5680 fixed drop to collapsed panel
Fixes #5680

* #5680 transparent color for blinking
Fixes #5680

* #5680 drop to collapse
Fixes #5680

* #5680 fix page adorner button position
Fixes #5680

* #5680 - fix drop to collapsed page and selected panel

* #5680 - fix unit test

* #5680 fix unit test

* #5680 - update screenshors

* #5680 - fixed selection after drag
  • Loading branch information
novikov82 authored Aug 20, 2024
1 parent 621624b commit 6beb101
Show file tree
Hide file tree
Showing 21 changed files with 493 additions and 58 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -93,6 +94,11 @@ export class SurveyElementAdornerBase<T extends SurveyElement = SurveyElement> 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<T>) => {
Expand All @@ -108,6 +114,34 @@ export class SurveyElementAdornerBase<T extends SurveyElement = SurveyElement> 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();
Expand Down
31 changes: 28 additions & 3 deletions packages/survey-creator-core/src/components/page.scss
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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 {
Expand All @@ -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);

Expand Down
10 changes: 10 additions & 0 deletions packages/survey-creator-core/src/components/page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ export class PageAdorner extends SurveyElementAdornerBase<PageModel> {
this.attachElement(page);
}

protected get dragInsideCollapsedContainer(): boolean {
return this.collapsed;
}

protected attachElement(surveyElement: PageModel): void {
super.attachElement(surveyElement);
this.dragTypeOverMe = null;
Expand Down Expand Up @@ -184,6 +188,12 @@ export class PageAdorner extends SurveyElementAdornerBase<PageModel> {
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";
}
Expand Down
21 changes: 20 additions & 1 deletion packages/survey-creator-core/src/components/question.scss
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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)
Expand Down
58 changes: 28 additions & 30 deletions packages/survey-creator-core/src/components/question.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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;
}
Expand Down
5 changes: 4 additions & 1 deletion packages/survey-creator-core/src/creator-base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 });
Expand Down Expand Up @@ -3814,6 +3815,8 @@ export class SurveyCreatorModel extends Base
*/
@property({ defaultValue: "never" }) expandCollapseButtonVisibility?: "never" | "onhover" | "always";

expandOnDragTimeOut: number = 1000;

selectFromStringEditor: boolean;

@property({
Expand Down
38 changes: 22 additions & 16 deletions packages/survey-creator-core/src/survey-elements.ts
Original file line number Diff line number Diff line change
@@ -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";
Expand Down Expand Up @@ -43,14 +43,18 @@ export function calculateDragOverLocation(clientX: number, clientY: number, drop
}
}

export function isPanelDynamic(element: ISurveyElement) {
return element instanceof QuestionPanelDynamicModel;
}

export class DragDropSurveyElements extends DragDropCore<any> {
public static newGhostPage: PageModel = null;
public static restrictDragQuestionBetweenPages: boolean = false;
public static edgeHeight: number = 30;
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;
Expand Down Expand Up @@ -154,7 +158,8 @@ export class DragDropSurveyElements extends DragDropCore<any> {
}

protected getDropTargetByDataAttributeValue(dataAttributeValue: string, dropTargetNode: HTMLElement, event: PointerEvent): any {
this.removeDragOverMarker(this.dragOverIndicatorElement);
const oldDragOverIndicatorElement = this.dragOverIndicatorElement;

this.dragOverIndicatorElement = null;

if (!dataAttributeValue) {
Expand All @@ -179,10 +184,6 @@ export class DragDropSurveyElements extends DragDropCore<any> {
// 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;
}

Expand All @@ -199,12 +200,12 @@ export class DragDropSurveyElements extends DragDropCore<any> {
});

// drop to paneldynamic
if (dropTarget.getType() === "paneldynamic" && this.insideEmptyContainer) {
if (dropTarget.getType() === "paneldynamic" && this.insideContainer) {
dropTarget = (<any>dropTarget).template;
}

// drop to matrix detail panel
if ((dropTarget.getType() === "matrixdropdown" || dropTarget.getType() === "matrixdynamic") && (<any>dropTarget).detailPanelMode !== "none" && this.insideEmptyContainer) {
if ((dropTarget.getType() === "matrixdropdown" || dropTarget.getType() === "matrixdynamic") && (<any>dropTarget).detailPanelMode !== "none" && this.insideContainer) {
dropTarget = (<any>dropTarget).detailPanel;
}

Expand All @@ -217,7 +218,9 @@ export class DragDropSurveyElements extends DragDropCore<any> {
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
Expand Down Expand Up @@ -311,8 +314,8 @@ export class DragDropSurveyElements extends DragDropCore<any> {
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;
Expand All @@ -339,6 +342,8 @@ export class DragDropSurveyElements extends DragDropCore<any> {
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) {
Expand All @@ -358,12 +363,12 @@ export class DragDropSurveyElements extends DragDropCore<any> {
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;
}
}
Expand Down Expand Up @@ -421,8 +426,9 @@ export class DragDropSurveyElements extends DragDropCore<any> {
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());
Expand All @@ -442,7 +448,7 @@ export class DragDropSurveyElements extends DragDropCore<any> {
}

public clear(): void {
this.insideEmptyContainer = null;
this.insideContainer = null;
this.removeDragOverMarker(this.prevDropTarget);
this.removeDragOverMarker(this.dropTarget);
this.removeDragOverMarker(this.dragOverIndicatorElement);
Expand Down
Loading

0 comments on commit 6beb101

Please sign in to comment.