From d77511976d7692f3253ee61df854f926bb22f3a1 Mon Sep 17 00:00:00 2001 From: Andrew Date: Thu, 13 Apr 2023 10:32:39 +0300 Subject: [PATCH] Features/3957 link value question clickable (#3983) * Creator in read-only mode - Allow users to view the Correct question Answer fixed #3957 * Remove test.only #3957 * Fix unit test, move some checks into functional test #3957 --- .../question-link-value.component.html | 7 ++-- .../src/components/link-value.ts | 11 +++++- .../src/property-grid/index.ts | 9 +++++ .../src/property-grid/values.ts | 13 ++++--- .../property-grid/property-grid.tests.ts | 31 +++++++++++++++- .../src/question-link-value.html | 2 +- .../src/QuestionLinkValue.tsx | 2 +- testCafe/property-grid/data.ts | 35 +++++++++++++++++++ 8 files changed, 99 insertions(+), 11 deletions(-) diff --git a/packages/survey-creator-angular/src/questions/question-link-value.component.html b/packages/survey-creator-angular/src/questions/question-link-value.component.html index 17ad3fa723..375b9b5d92 100644 --- a/packages/survey-creator-angular/src/questions/question-link-value.component.html +++ b/packages/survey-creator-angular/src/questions/question-link-value.component.html @@ -1,9 +1,10 @@ - + - + \ No newline at end of file diff --git a/packages/survey-creator-core/src/components/link-value.ts b/packages/survey-creator-core/src/components/link-value.ts index 29e36add81..11c4c78b42 100644 --- a/packages/survey-creator-core/src/components/link-value.ts +++ b/packages/survey-creator-core/src/components/link-value.ts @@ -6,6 +6,7 @@ require("./link-value.scss"); export class QuestionLinkValueModel extends Question { public linkClickCallback: () => void; public resetClickCallback: () => void; + public isClickableCallback: () => boolean; @property({ defaultValue: "svc-link-value-button svc-question-link__set-button" }) public linkSetButtonCssClasses: string; @property({ defaultValue: "svc-question-link__clear-button" }) public linkClearButtonCssClasses: string; @@ -15,6 +16,7 @@ export class QuestionLinkValueModel extends Question { @property({ defaultValue: true }) allowClear: boolean; @property({ defaultValue: true }) showValueInLink: boolean; @property({ defaultValue: false }) showTooltip: boolean; + @property({ defaultValue: true }) isClickable: boolean; constructor(name: string, json: any = null) { super(name); const linkValueText = json && !json.showValueInLink && (editorLocalization.getString("pe.set")) + " " + json.title || null; @@ -27,9 +29,16 @@ export class QuestionLinkValueModel extends Question { if (this.allowClear) { this.showClear = !Helpers.isValueEmpty(newValue); } + this.updateIsClickable(); } } - + protected onReadOnlyChanged(): void { + this.updateIsClickable(); + super.onReadOnlyChanged(); + } + private updateIsClickable(): void { + this.setPropertyValue("isClickable", !this.isReadOnly || (!!this.isClickableCallback && this.isClickableCallback())); + } public get ariaRole(): string { return "button"; } diff --git a/packages/survey-creator-core/src/property-grid/index.ts b/packages/survey-creator-core/src/property-grid/index.ts index 53b61752a8..f398b8f279 100644 --- a/packages/survey-creator-core/src/property-grid/index.ts +++ b/packages/survey-creator-core/src/property-grid/index.ts @@ -1146,6 +1146,9 @@ export abstract class PropertyGridEditor implements IPropertyGridEditor { if (property.type !== "condition") { surveyPropertyEditor.editSurvey.css = defaultV2Css; } + if(question.isReadOnly) { + surveyPropertyEditor.editSurvey.mode = "display"; + } if (!settings.showModal) return surveyPropertyEditor; const prevCurrentLocale = surveyLocalization.currentLocale; const locale = editorLocalization.currentLocale; @@ -1168,6 +1171,12 @@ export abstract class PropertyGridEditor implements IPropertyGridEditor { "sv-property-editor", question.title, options.isMobileView ? "overlay" : "popup" ); + if(question.isReadOnly) { + const applyBtn = popupModel.footerToolbar.getActionById("apply"); + if(!!applyBtn) { + applyBtn.visible = false; + } + } popupModel.locale = locale; surveyLocalization.currentLocale = prevCurrentLocale; this.onModalPropertyEditorShown(editor, property, question, options); diff --git a/packages/survey-creator-core/src/property-grid/values.ts b/packages/survey-creator-core/src/property-grid/values.ts index e58d31b354..1c2c61a833 100644 --- a/packages/survey-creator-core/src/property-grid/values.ts +++ b/packages/survey-creator-core/src/property-grid/values.ts @@ -9,6 +9,7 @@ import { } from "./values-survey"; import { ISurveyCreatorOptions } from "../creator-settings"; import { SurveyHelper } from "../survey-helper"; +import { QuestionLinkValueModel } from "../components/link-value"; export abstract class PropertyGridValueEditorBase extends PropertyGridEditor { public getJSON( @@ -23,11 +24,15 @@ export abstract class PropertyGridValueEditorBase extends PropertyGridEditor { }; } public onCreated = (obj: Base, question: Question, prop: JsonObjectProperty, options: ISurveyCreatorOptions) => { - (question).linkClickCallback = () => { - this.showModalPropertyEditor(this, prop, question, options, () => (question).isSelected = false); - (question).isSelected = true; + const linkQuestion = question; + linkQuestion.isClickableCallback = () => { + return !linkQuestion.isReadOnly || !this.isValueEmpty(linkQuestion.value); }; - (question).clearClickCallback = () => { + linkQuestion.linkClickCallback = () => { + this.showModalPropertyEditor(this, prop, question, options, () => linkQuestion.isSelected = false); + linkQuestion.isSelected = true; + }; + linkQuestion.clearClickCallback = () => { this.clearPropertyValue( (question).obj, prop, diff --git a/packages/survey-creator-core/tests/property-grid/property-grid.tests.ts b/packages/survey-creator-core/tests/property-grid/property-grid.tests.ts index c9863e94a1..21d318c552 100644 --- a/packages/survey-creator-core/tests/property-grid/property-grid.tests.ts +++ b/packages/survey-creator-core/tests/property-grid/property-grid.tests.ts @@ -1850,7 +1850,36 @@ test("DefaultValue editor for invisible values", () => { expect(valueQuestion.visibleChoices).toHaveLength(3); expect(valueQuestion.visibleChoices[1].isEnabled).toBeTruthy(); }); - +test("DefaultValue editor & readOnly", () => { + PropertyGridEditorCollection.register(new PropertyGridValueEditor()); + const question = new QuestionDropdownModel("q1"); + question.choices = [1, 2, 3, 4, 5]; + question.defaultValue = 2; + const defaultValueProp = Serializer.findProperty("question", "defaultValue"); + defaultValueProp.readOnly = true; + var propertyGrid = new PropertyGridModelTester(question); + const editQuestion = propertyGrid.survey.getQuestionByName("defaultValue"); + const property = (editQuestion).property; + expect(editQuestion.isReadOnly).toBeTruthy(); + expect(editQuestion.isClickable).toBeTruthy(); + question.defaultValue = undefined; + expect(editQuestion.isReadOnly).toBeTruthy(); + expect(editQuestion.isClickable).toBeFalsy(); + question.defaultValue = 2; + const editor = ( + PropertyGridEditorCollection.getEditor(property) + ); + const valueEditor = editor.createPropertyEditorSetup( + question, + property, + editQuestion, + new EmptySurveyCreatorOptions() + ); + var valueQuestion = valueEditor.editSurvey.getQuestionByName("question"); + expect(valueQuestion).toBeTruthy(); + expect(valueQuestion.value).toEqual(2); + defaultValueProp.readOnly = false; +}); test("DefaultRowValue editor", () => { var question = new QuestionMatrixDynamicModel("q1"); question.addColumn("col1"); diff --git a/packages/survey-creator-knockout/src/question-link-value.html b/packages/survey-creator-knockout/src/question-link-value.html index e5c8553c3a..19a556569b 100644 --- a/packages/survey-creator-knockout/src/question-link-value.html +++ b/packages/survey-creator-knockout/src/question-link-value.html @@ -1,5 +1,5 @@ + params="text: linkValueText, click: koClickLink, selected: isSelected, disabled: !isClickable, classes: linkSetButtonCssClasses, title: tooltip"> this.question.doLinkClick()} selected={this.question.isSelected} - disabled={this.question.isReadOnly} + disabled={!this.question.isClickable} text={this.question.linkValueText} title={this.question.tooltip} > diff --git a/testCafe/property-grid/data.ts b/testCafe/property-grid/data.ts index 028c515a67..82135b6b55 100644 --- a/testCafe/property-grid/data.ts +++ b/testCafe/property-grid/data.ts @@ -6,6 +6,10 @@ fixture`${title}`.page`${url}`.beforeEach(async (t) => { await t.maximizeWindow(); }); +const makeCreatorReadOnly = ClientFunction(() => { + window["creator"].readOnly = true; +}); + test("Default value", async (t) => { const json = { "pages": [ @@ -47,4 +51,35 @@ test("Default value", async (t) => { const resultJson2 = await getJSON(); await t .expect(resultJson2.pages[0].elements[0].defaultValue).eql(undefined); +}); +test("Default value & readonly", async (t) => { + const json = { + "pages": [ + { + "name": "page1", + "elements": [ + { + "type": "rating", + "name": "question1", + "defaultValue": 3 + } + ] + } + ] + }; + await setJSON(json); + await makeCreatorReadOnly(); + + const question1 = Selector("[data-name=\"question1\"]"); + const dataTab = Selector("h4").withExactText("Data"); + + await t + .click(question1) + .click(dataTab) + .expect(Selector("span").withExactText("Clear").exists).notOk() + .click(Selector("span").withExactText("Change Default Answer")) + .click(Selector(".sv-popup__body-header").withExactText("Default Answer")) + .expect(Selector(".sv-popup--modal button").withExactText("Apply").filterVisible().exists).notOk() + .click(Selector(".sv-popup--modal button").withExactText("Cancel")) + .expect(Selector("span").withExactText("Change Default Answer").visible).ok(); }); \ No newline at end of file