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 ee900665b1..43f572c951 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 @@ -109,15 +109,8 @@ export class SurveyElementAdornerBase e this.actionContainer = new SurveyElementActionContainer(); this.actionContainer.dotsItem.iconSize = 16; this.actionContainer.dotsItem.popupModel.horizontalPosition = "center"; - var actions: Array = []; - this.buildActions(actions); - this.setSurveyElement(surveyElement, false); - if (this.surveyElement) { - this.creator.sidebar.onPropertyChanged.add(this.sidebarFlyoutModeChangedFunc); - this.creator.onElementMenuItemsChanged(this.surveyElement, actions); - this.actionContainer.setItems(actions); - this.updateActionsProperties(); - } + this.setSurveyElement(surveyElement); + this.creator.sidebar.onPropertyChanged.add(this.sidebarFlyoutModeChangedFunc); this.setShowAddQuestionButton(true); } @@ -131,11 +124,17 @@ export class SurveyElementAdornerBase e surveyElement.onPropertyChanged.add(this.selectedPropPageFunc); } } - protected setSurveyElement(surveyElement: T, updateActions: boolean = true): void { + protected setSurveyElement(surveyElement: T): void { this.detachElement(this.surveyElement); this.surveyElement = surveyElement; this.attachElement(this.surveyElement); - if (updateActions) { + if (this.surveyElement) { + var actions: Array = []; + this.buildActions(actions); + this.creator.onElementMenuItemsChanged(this.surveyElement, actions); + const prevActions = this.actionContainer.actions; + prevActions.forEach(action => action.dispose && action.dispose()); + this.actionContainer.setItems(actions); this.updateActionsProperties(); } } diff --git a/packages/survey-creator-react/src/ImageItemValueWrapper.tsx b/packages/survey-creator-react/src/ImageItemValueWrapper.tsx index 336e9d0eb0..22ec523696 100644 --- a/packages/survey-creator-react/src/ImageItemValueWrapper.tsx +++ b/packages/survey-creator-react/src/ImageItemValueWrapper.tsx @@ -25,11 +25,11 @@ export class ImageItemValueAdornerComponent extends CreatorModelElement< super(props); this.rootRef = React.createRef(); } - protected createModel(): void { + protected createModel(props: any): void { this.model = new ImageItemValueWrapperViewModel( - this.props.componentData.creator, - this.props.question, - this.props.item, + props.componentData.creator, + props.question, + props.item, null, null ); diff --git a/packages/survey-creator-react/src/ItemValueWrapper.tsx b/packages/survey-creator-react/src/ItemValueWrapper.tsx index 7dc74137df..e1b1f8706a 100644 --- a/packages/survey-creator-react/src/ItemValueWrapper.tsx +++ b/packages/survey-creator-react/src/ItemValueWrapper.tsx @@ -21,11 +21,11 @@ export class ItemValueAdornerComponent extends CreatorModelElement< any > { model: ItemValueWrapperViewModel; - protected createModel(): void { + protected createModel(props: any): void { this.model = new ItemValueWrapperViewModel( - this.props.componentData.creator, - this.props.question, - this.props.item + props.componentData.creator, + props.question, + props.item ); } protected getUpdatedModelProps(): string[] { diff --git a/packages/survey-creator-react/src/LogoImage.tsx b/packages/survey-creator-react/src/LogoImage.tsx index 984f3ffe2c..ee5c85dfaa 100644 --- a/packages/survey-creator-react/src/LogoImage.tsx +++ b/packages/survey-creator-react/src/LogoImage.tsx @@ -15,12 +15,12 @@ export class LogoImageComponent extends CreatorModelElement { model: MatrixCellWrapperViewModel; - protected createModel(): void { - const data = this.props.componentData; + protected createModel(props: any): void { + const data = props.componentData; + let prevIsSelected = false; + if (!!this.model) { + prevIsSelected = this.model.isSelected; + } this.model = new MatrixCellWrapperViewModel( data.creator, data.element, @@ -29,6 +33,7 @@ export class MatrixCellAdornerComponent extends CreatorModelElement< data.row, data.column || data.element.cell?.column, ); + this.model.isSelected = prevIsSelected; } protected getUpdatedModelProps(): string[] { return ["componentData"]; diff --git a/packages/survey-creator-react/src/ModelElement.tsx b/packages/survey-creator-react/src/ModelElement.tsx index 0b377b46e4..d16fffa129 100644 --- a/packages/survey-creator-react/src/ModelElement.tsx +++ b/packages/survey-creator-react/src/ModelElement.tsx @@ -3,21 +3,24 @@ import { SurveyElementBase } from "survey-react-ui"; export class CreatorModelElement extends SurveyElementBase { constructor(props: P) { super(props); - this.createModel(); + this.createModel(props); } - componentDidUpdate(prevProps: any, prevState: any): void { - super.componentDidUpdate(prevProps, prevState); - if(this.needUpdateModel(prevProps)) { - this.createModel(); + shouldComponentUpdate(nextProps: any, nextState: any): boolean { + const result = super.shouldComponentUpdate(nextProps, nextState); + if (result) { + if (this.needUpdateModel(nextProps)) { + this.createModel(nextProps); + } } + return result; } - protected createModel(): void {} - protected needUpdateModel(prevProps: any): boolean { + protected createModel(props: any): void { } + protected needUpdateModel(nextProps: any): boolean { const names = this.getUpdatedModelProps(); - if(!Array.isArray(names)) return true; - for(var i = 0; i < names.length; i ++) { + if (!Array.isArray(names)) return true; + for (var i = 0; i < names.length; i++) { const key = names[i]; - if(this.props[key] !== prevProps[key]) return true; + if (this.props[key] !== nextProps[key]) return true; } return false; } diff --git a/packages/survey-creator-react/src/PageNavigator.tsx b/packages/survey-creator-react/src/PageNavigator.tsx index 4015f0e4e7..ca3f404648 100644 --- a/packages/survey-creator-react/src/PageNavigator.tsx +++ b/packages/survey-creator-react/src/PageNavigator.tsx @@ -28,13 +28,13 @@ export class SurveyPageNavigator extends CreatorModelElement< super(props); this.containerRef = React.createRef(); } - protected createModel(): void { + protected createModel(props: any): void { if (this.model) { this.model.dispose(); } this.model = new PageNavigatorViewModel( - this.props.pagesController, - this.props.pageEditMode + props.pagesController, + props.pageEditMode ); } protected getUpdatedModelProps(): string[] { diff --git a/packages/survey-creator-react/src/Results.tsx b/packages/survey-creator-react/src/Results.tsx index f117a921c0..d202e59f87 100644 --- a/packages/survey-creator-react/src/Results.tsx +++ b/packages/survey-creator-react/src/Results.tsx @@ -13,9 +13,9 @@ export class SurveyResults extends CreatorModelElement< any > { model: SurveyResultsModel; - protected createModel(): void { + protected createModel(props: any): void { if (this.props.survey) { - this.model = new SurveyResultsModel(this.props.survey); + this.model = new SurveyResultsModel(props.survey); } } protected getUpdatedModelProps(): string[] { diff --git a/packages/survey-creator-react/src/StringEditor.tsx b/packages/survey-creator-react/src/StringEditor.tsx index ca4cb36a67..ae543d2f38 100644 --- a/packages/survey-creator-react/src/StringEditor.tsx +++ b/packages/survey-creator-react/src/StringEditor.tsx @@ -12,11 +12,11 @@ export class SurveyLocStringEditor extends CreatorModelElement { this.state = { changed: 0 }; this.svStringEditorRef = React.createRef(); } - protected createModel(): void { + protected createModel(props: any): void { if (this.baseModel) { this.baseModel.dispose(); } - this.baseModel = new StringEditorViewModelBase(this.locString, this.creator); + this.baseModel = new StringEditorViewModelBase(props.locStr.locStr, props.locStr.creator); } protected getUpdatedModelProps(): string[] { return ["creator", "locString"]; diff --git a/packages/survey-creator-react/src/adorners/CellQuestion.tsx b/packages/survey-creator-react/src/adorners/CellQuestion.tsx index 306be258ed..3173e0cfef 100644 --- a/packages/survey-creator-react/src/adorners/CellQuestion.tsx +++ b/packages/survey-creator-react/src/adorners/CellQuestion.tsx @@ -14,10 +14,10 @@ export class CellQuestionAdornerComponent extends CreatorModelElement< any > { model: QuestionAdornerViewModel; - protected createModel(): void { + protected createModel(props: any): void { this.model = new QuestionAdornerViewModel( - this.props.componentData, - this.props.question, + props.componentData, + props.question, null ); } diff --git a/packages/survey-creator-react/src/adorners/CellQuestionDropdown.tsx b/packages/survey-creator-react/src/adorners/CellQuestionDropdown.tsx index 8751fae5fa..d8848ff6ab 100644 --- a/packages/survey-creator-react/src/adorners/CellQuestionDropdown.tsx +++ b/packages/survey-creator-react/src/adorners/CellQuestionDropdown.tsx @@ -12,10 +12,10 @@ export class CellQuestionDropdownAdornerComponent extends CreatorModelElement< any > { model: QuestionAdornerViewModel; - protected createModel(): void { + protected createModel(props: any): void { this.model = new QuestionAdornerViewModel( - this.props.componentData, - this.props.question, + props.componentData, + props.question, null ); } diff --git a/packages/survey-creator-react/src/adorners/Page.tsx b/packages/survey-creator-react/src/adorners/Page.tsx index c741bb5666..5062a8e9df 100644 --- a/packages/survey-creator-react/src/adorners/Page.tsx +++ b/packages/survey-creator-react/src/adorners/Page.tsx @@ -34,10 +34,10 @@ export class CreatorSurveyPageComponent extends CreatorModelElement< super(props); this.rootRef = React.createRef(); } - protected createModel(): void { + protected createModel(props: any): void { this.model = new PageAdorner( - this.props.creator, - this.props.page + props.creator, + props.page ); } protected getUpdatedModelProps(): string[] { diff --git a/packages/survey-creator-react/src/adorners/Question.tsx b/packages/survey-creator-react/src/adorners/Question.tsx index 44c9774ee8..71e777bb62 100644 --- a/packages/survey-creator-react/src/adorners/Question.tsx +++ b/packages/survey-creator-react/src/adorners/Question.tsx @@ -25,16 +25,16 @@ export class QuestionAdornerComponent extends CreatorModelElement< private modelValue: QuestionAdornerViewModel; protected rootRef: React.RefObject; - protected createModel(): void { + protected createModel(props: any): void { if (this.modelValue) { this.modelValue.dispose(); } - this.modelValue = this.createQuestionViewModel(); + this.modelValue = this.createQuestionViewModel(props); } - protected createQuestionViewModel(): QuestionAdornerViewModel { + protected createQuestionViewModel(props: any): QuestionAdornerViewModel { return new QuestionAdornerViewModel( - this.props.componentData, - this.props.question, + props.componentData, + props.question, null ); } diff --git a/packages/survey-creator-react/src/adorners/QuestionDropdown.tsx b/packages/survey-creator-react/src/adorners/QuestionDropdown.tsx index afc83d1753..4d383981b2 100644 --- a/packages/survey-creator-react/src/adorners/QuestionDropdown.tsx +++ b/packages/survey-creator-react/src/adorners/QuestionDropdown.tsx @@ -12,10 +12,10 @@ export class QuestionDropdownAdornerComponent extends QuestionAdornerComponent { constructor(props: QuestionAdornerComponentProps) { super(props); } - protected createQuestionViewModel(): QuestionDropdownAdornerViewModel { + protected createQuestionViewModel(props: any): QuestionDropdownAdornerViewModel { return new QuestionDropdownAdornerViewModel( - this.props.componentData, - this.props.question as QuestionDropdownModel, + props.componentData, + props.question as QuestionDropdownModel, null ); } diff --git a/packages/survey-creator-react/src/adorners/QuestionImage.tsx b/packages/survey-creator-react/src/adorners/QuestionImage.tsx index b3e9b105fc..4a9b582aed 100644 --- a/packages/survey-creator-react/src/adorners/QuestionImage.tsx +++ b/packages/survey-creator-react/src/adorners/QuestionImage.tsx @@ -15,10 +15,10 @@ export class QuestionImageAdornerComponent extends QuestionAdornerComponent { super(props); this.rootRef = React.createRef(); } - protected createQuestionViewModel(): QuestionAdornerViewModel { + protected createQuestionViewModel(props: any): QuestionAdornerViewModel { return new QuestionImageAdornerViewModel( - this.props.componentData, - this.props.question as any, + props.componentData, + props.question as any, null, null ); @@ -58,7 +58,7 @@ export class QuestionImageAdornerComponent extends QuestionAdornerComponent { ); } renderChooseButton(): JSX.Element { - return(
+ return (
{this.model.allowEdit ? attachKey2click( this.imageModel.chooseFile(this.imageModel)} diff --git a/packages/survey-creator-react/src/adorners/QuestionRating.tsx b/packages/survey-creator-react/src/adorners/QuestionRating.tsx index db2e879d91..206bb1805b 100644 --- a/packages/survey-creator-react/src/adorners/QuestionRating.tsx +++ b/packages/survey-creator-react/src/adorners/QuestionRating.tsx @@ -8,13 +8,13 @@ import { CreatorModelElement } from "../ModelElement"; export class QuestionRatingAdornerComponent extends CreatorModelElement { private modelValue: QuestionRatingAdornerViewModel; - protected createModel(): void { - this.modelValue = this.createQuestionViewModel(); + protected createModel(props: any): void { + this.modelValue = this.createQuestionViewModel(props); } - protected createQuestionViewModel(): QuestionRatingAdornerViewModel { + protected createQuestionViewModel(props: any): QuestionRatingAdornerViewModel { return new QuestionRatingAdornerViewModel( - this.props.componentData, - this.props.question as any, + props.componentData, + props.question as any, null ); } diff --git a/packages/survey-creator-react/src/adorners/QuestionWidget.tsx b/packages/survey-creator-react/src/adorners/QuestionWidget.tsx index 29f4b5ae36..357c448578 100644 --- a/packages/survey-creator-react/src/adorners/QuestionWidget.tsx +++ b/packages/survey-creator-react/src/adorners/QuestionWidget.tsx @@ -9,10 +9,10 @@ import { import { attachKey2click, ReactElementFactory, SvgIcon } from "survey-react-ui"; export class QuestionWidgetAdornerComponent extends QuestionAdornerComponent { - protected createQuestionViewModel(): QuestionAdornerViewModel { + protected createQuestionViewModel(props: any): QuestionAdornerViewModel { return new QuestionAdornerViewModel( - this.props.componentData, - this.props.question as any, + props.componentData, + props.question as any, null ); } diff --git a/packages/survey-creator-react/src/adorners/Row.tsx b/packages/survey-creator-react/src/adorners/Row.tsx index 212c029876..10a7676e6f 100644 --- a/packages/survey-creator-react/src/adorners/Row.tsx +++ b/packages/survey-creator-react/src/adorners/Row.tsx @@ -18,10 +18,10 @@ export class RowWrapper extends CreatorModelElement< constructor(props: RowWrapperComponentProps) { super(props); } - protected createModel(): void { + protected createModel(props: any): void { this.model = new RowViewModel( - this.props.componentData.creator, - this.props.row, + props.componentData.creator, + props.row, null ); } diff --git a/packages/survey-creator-react/src/toolbox/ToolboxItem.tsx b/packages/survey-creator-react/src/toolbox/ToolboxItem.tsx index 1957bdc854..4c06cd9ef2 100644 --- a/packages/survey-creator-react/src/toolbox/ToolboxItem.tsx +++ b/packages/survey-creator-react/src/toolbox/ToolboxItem.tsx @@ -32,8 +32,8 @@ export class SurveyCreatorToolboxTool extends CreatorModelElement< constructor(props) { super(props); } - protected createModel(): void { - this.model = new ToolboxToolViewModel(this.item, this.props.creator); + protected createModel(props: any): void { + this.model = new ToolboxToolViewModel(props.item, props.creator); } protected getUpdatedModelProps(): string[] { return ["creator", "item"]; @@ -89,9 +89,9 @@ export class SurveyCreatorToolboxItem extends CreatorModelElement< constructor(props) { super(props); } - protected createModel(): void { - const toolboxItem: IQuestionToolboxItem = this.props.item; - this.model = new ToolboxToolViewModel(toolboxItem, this.props.creator); + protected createModel(props: any): void { + const toolboxItem: IQuestionToolboxItem = props.item; + this.model = new ToolboxToolViewModel(toolboxItem, props.creator); } protected getUpdatedModelProps(): string[] { return ["creator", "item"]; diff --git a/visualRegressionTests/tests/designer/etalons/actions-on-converted-question.png b/visualRegressionTests/tests/designer/etalons/actions-on-converted-question.png new file mode 100644 index 0000000000..cd6dc0f9e2 Binary files /dev/null and b/visualRegressionTests/tests/designer/etalons/actions-on-converted-question.png differ diff --git a/visualRegressionTests/tests/designer/etalons/actions-on-converted-question_mask.png b/visualRegressionTests/tests/designer/etalons/actions-on-converted-question_mask.png new file mode 100644 index 0000000000..5ad4fd7991 Binary files /dev/null and b/visualRegressionTests/tests/designer/etalons/actions-on-converted-question_mask.png differ diff --git a/visualRegressionTests/tests/designer/surface.ts b/visualRegressionTests/tests/designer/surface.ts index 9665d9890d..2012fc4954 100644 --- a/visualRegressionTests/tests/designer/surface.ts +++ b/visualRegressionTests/tests/designer/surface.ts @@ -1965,4 +1965,42 @@ test("Composite question - check no scroll", async (t) => { await t.hover(".sd-input.sd-text"); await takeElementScreenshot("composite-question-no-scroll.png", Selector(".svc-question__adorner"), t, comparer); }); -}); \ No newline at end of file +}); + +test("Check adorner actions responsivity after convert", async (t) => { + await wrapVisualTest(t, async (t, comparer) => { + await t.resizeWindow(1400, 900); + const root = Selector(".sd-page.sd-body__page"); + await setJSON({ + "logoPosition": "right", + "pages": [ + { + "name": "page1", + "elements": [ + { + "type": "text", + "name": "question1" + }, + { + "type": "text", + "name": "question2", + "startWithNewLine": false + }, + { + "type": "text", + "name": "question3", + "startWithNewLine": false + } + ] + } + ] + }); + await t.hover(Selector(".svc-question__adorner").nth(2), { offsetX: 10, offsetY: 10 }).click(Selector(".svc-question__adorner").nth(2), { offsetX: 10, offsetY: 10 }).click(Selector("#convertTo").nth(2)) + .click(Selector("div[data-sv-drop-target-survey-element='question3'] .sv-list__item-body[title='Yes/No (Boolean)']")) + .hover(Selector(".svc-question__adorner").nth(1), { offsetX: 10, offsetY: 10 }).click(Selector(".svc-question__adorner").nth(1), { offsetX: 10, offsetY: 10 }) + .hover(Selector(".svc-question__adorner").nth(2), { offsetX: 10, offsetY: 10 }).click(Selector(".svc-question__adorner").nth(2), { offsetX: 10, offsetY: 10 }); + await ClientFunction(() => { document.body.focus(); })(); + await t.wait(100); + await takeElementScreenshot("actions-on-converted-question.png", root.nth(0), t, comparer); + }); +});