diff --git a/packages/survey-creator-core/src/presets/editable/presets-editable-toolbox.ts b/packages/survey-creator-core/src/presets/editable/presets-editable-toolbox.ts index 00929fe368..4c27cc463c 100644 --- a/packages/survey-creator-core/src/presets/editable/presets-editable-toolbox.ts +++ b/packages/survey-creator-core/src/presets/editable/presets-editable-toolbox.ts @@ -132,6 +132,7 @@ export class CreatorPresetEditableToolboxConfigurator extends CreatorPresetEdita { type: "boolean", name: this.nameCategoriesShow, + defaultValue: false, title: "Setup toolbox items and categories" }, { @@ -162,7 +163,9 @@ export class CreatorPresetEditableToolboxConfigurator extends CreatorPresetEdita titleLocation: "hidden", selectToRankEnabled: true, minSelectedChoices: 1, - selectToRankAreasLayout: "horizontal" + selectToRankAreasLayout: "horizontal", + selectToRankEmptyRankedAreaText: "Drag toolbox items to hide them", + selectToRankEmptyUnrankedAreaText: "Drag toolbox items here" } ] }, @@ -174,6 +177,8 @@ export class CreatorPresetEditableToolboxConfigurator extends CreatorPresetEdita selectToRankEnabled: true, minSelectedChoices: 1, selectToRankAreasLayout: "horizontal", + selectToRankEmptyRankedAreaText: "Drag toolbox items to hide them", + selectToRankEmptyUnrankedAreaText: "Drag toolbox items here" } ] }; diff --git a/packages/survey-creator-core/src/presets/editable/presets-editor.ts b/packages/survey-creator-core/src/presets/editable/presets-editor.ts index cd64bc396b..8d6ec4e02b 100644 --- a/packages/survey-creator-core/src/presets/editable/presets-editor.ts +++ b/packages/survey-creator-core/src/presets/editable/presets-editor.ts @@ -1,36 +1,66 @@ import { SurveyCreatorModel } from "../../creator-base"; import { CreatorPreset, ICreatorPresetData } from "../presets"; -import { SurveyModel } from "survey-core"; +import { ActionContainer, Base, ComputedUpdater, SurveyModel } from "survey-core"; import { CreatorPresetEditableBase } from "./presets-editable-base"; import { CreatorPresetEditableToolbox, CreatorPresetEditableToolboxConfigurator, CreatorPresetEditableToolboxDefinition } from "./presets-editable-toolbox"; import { CreatorPresetEditableTabs } from "./presets-editable-tabs"; import { CreatorEditablePresetPropertyGrid, CreatorPresetEditablePropertyGridDefinition } from "./presets-editable-properties"; -export class CreatorPresetEditor { +export class CreatorPresetEditorModel extends Base { private presetValue: CreatorPreset; private creatorValue: SurveyCreatorModel; private modelValue: SurveyModel; + private navigationBarValue: ActionContainer; constructor(json?: ICreatorPresetData, creator?: SurveyCreatorModel) { + super(); this.presetValue = new CreatorPreset(json); - this.creatorValue = creator || new SurveyCreatorModel({}); + this.creatorValue = creator || this.createCreator(); this.modelValue = this.createModel(); + this.navigationBarValue = new ActionContainer(); + this.addNavigationAction("preset", "Edit Preset"); + this.addNavigationAction("creator", "Review Creator"); + this.addNavigationAction("results", "Preset JSON"); + this.activeTab = this.navigationBar.actions[0].id; } public get preset(): CreatorPreset { return this.presetValue; } public get creator(): SurveyCreatorModel { return this.creatorValue; } public get model(): SurveyModel { return this.modelValue; } + public get navigationBar(): ActionContainer { return this.navigationBarValue; } + public get activeTab(): string { + return this.getPropertyValue("activeTab"); + } + public set activeTab(val: string) { + this.setPropertyValue("activeTab", val); + } + public get json(): ICreatorPresetData { + return this.preset.getJson(); + } + public set json(val: ICreatorPresetData) { + this.preset.setJson(val); + } + protected onPropertyValueChanged(name: string, oldValue: any, newValue: any): void { + if(name === "activeTab" && oldValue === "preset") { + this.applyFromSurveyModel(); + } + } + protected createCreator(): SurveyCreatorModel { + return new SurveyCreatorModel({}); + } + private addNavigationAction(id: string, title: string): void { + const actionInfo = { + id: id, + title: title, + active: new ComputedUpdater(() => this.activeTab === id), + action: () => { this.activeTab = id; } + }; + this.navigationBar.addAction(actionInfo); + } protected createModel(): SurveyModel { const editablePresets = this.createEditablePresets(); const model = new SurveyModel(this.getEditModelJson(editablePresets)); model.editablePresets = editablePresets; - model.showCompleteButton = false; model.keepIncorrectValues = true; - model.addNavigationItem({ - id: "preset_save", - title: "Save", //TODO - action: () => { - this.applyFromSurveyModel(); - } - }); + model.showNavigationButtons = false; editablePresets.forEach(item => item.setupQuestions(model, this.creator)); const json = this.preset.getJson() || {}; editablePresets.forEach(item => item.setupQuestionsValue(model, json[item.path], this.creator)); @@ -110,13 +140,6 @@ export class CreatorPresetEditor { pages.forEach(page => modelJson.pages.push(page)); } }); - modelJson.pages.push({ - name: "page_result", - title: "Preset JSON result", - elements: [ - { type: "comment", rows: 40, name: "json_result", titleLocation: "hidden", placeholder: "Please click on the 'Save' button" } - ] - }); return modelJson; } } \ No newline at end of file diff --git a/packages/survey-creator-core/src/presets/presets.ts b/packages/survey-creator-core/src/presets/presets.ts index 28a31b6679..88a0049ec5 100644 --- a/packages/survey-creator-core/src/presets/presets.ts +++ b/packages/survey-creator-core/src/presets/presets.ts @@ -1,4 +1,4 @@ -import { CreatorPresetBase, ICreatorPreset, CreatorPresetEditableBase } from "./presets-base"; +import { CreatorPresetBase, ICreatorPreset } from "./presets-base"; import { CreatorPresetToolbox, ICreatorPresetToolboxItem } from "./presets-toolbox"; import { CreatorPresetTabs } from "./presets-tabs"; import { CreatorPresetPropertyGrid } from "./presets-properties"; diff --git a/packages/survey-creator-core/tests/presets-editor.tests.ts b/packages/survey-creator-core/tests/presets-editor.tests.ts index 7ac045bd3f..3275a186d4 100644 --- a/packages/survey-creator-core/tests/presets-editor.tests.ts +++ b/packages/survey-creator-core/tests/presets-editor.tests.ts @@ -5,23 +5,22 @@ import { ItemValue, QuestionDropdownModel, QuestionMatrixDynamicModel } from "su import { defaultPropertyGridDefinition } from "../src/question-editor/definition"; import { SurveyQuestionPresetPropertiesDetail } from "../src/presets/editable/presets-editable-properties"; import { QuestionEmbeddedSurveyModel } from "../src/components/embedded-survey"; -import { CreatorPresetEditor } from "../src/presets/editable/presets-editor"; +import { CreatorPresetEditorModel } from "../src/presets/editable/presets-editor"; export * from "../src/components/embedded-survey"; test("Preset edit model, create pages", () => { - const editor = new CreatorPresetEditor(); + const editor = new CreatorPresetEditorModel(); const survey = editor.model; - expect(survey.pages).toHaveLength(5); - expect(survey.visiblePages).toHaveLength(5); + expect(survey.pages).toHaveLength(4); + expect(survey.visiblePages).toHaveLength(4); expect(survey.pages[0].name).toEqual("page_tabs"); expect(survey.pages[1].name).toEqual("page_toolbox_definition"); expect(survey.pages[2].name).toEqual("page_toolbox"); expect(survey.pages[3].name).toEqual("page_propertyGrid_definition"); - expect(survey.pages[4].name).toEqual("page_result"); }); test("Preset edit model, page component", () => { - const editor = new CreatorPresetEditor({ tabs: { items: [] } }); + const editor = new CreatorPresetEditorModel({ tabs: { items: [] } }); const survey = editor.model; const boolQuestion = survey.getQuestionByName("tabs_show"); expect(boolQuestion).toBeTruthy(); @@ -51,7 +50,7 @@ test("Preset edit model, page component", () => { }); test("Preset edit model, tabs page with creator, default items", () => { const creator = new CreatorTester(); - const editor = new CreatorPresetEditor({}, creator); + const editor = new CreatorPresetEditorModel({}, creator); const survey = editor.model; const boolQuestion = survey.getQuestionByName("tabs_show"); boolQuestion.value = true; @@ -68,7 +67,7 @@ test("Preset edit model, tabs page with creator, default items", () => { expect(creator.activeTab).toBe("logic"); }); test("Preset edit model, tabs page with creator, default items", () => { - const editor = new CreatorPresetEditor({ tabs: { items: ["designer", "logic"], activeTab: "logic" } }); + const editor = new CreatorPresetEditorModel({ tabs: { items: ["designer", "logic"], activeTab: "logic" } }); const survey = editor.model; const boolQuestion = survey.getQuestionByName("tabs_show"); boolQuestion.value = true; @@ -79,7 +78,7 @@ test("Preset edit model, tabs page with creator, default items", () => { expect(activeTabQuestion.value).toEqual("logic"); }); test("Preset edit model, toolbox page", () => { - const editor = new CreatorPresetEditor(); + const editor = new CreatorPresetEditorModel(); const survey = editor.model; const boolDefinitionQuestion = survey.getQuestionByName("toolbox_definition_show"); const boolSetupQuestion = survey.getQuestionByName("toolbox_show"); @@ -87,7 +86,7 @@ test("Preset edit model, toolbox page", () => { expect(boolDefinitionQuestion).toBeTruthy(); expect(boolDefinitionQuestion.value).toBeFalsy(); expect(boolSetupQuestion).toBeTruthy(); - expect(boolSetupQuestion.value).toBeFalsy(); + expect(boolSetupQuestion.value).toEqual(false); expect(boolSetupCategoriesQuestion).toBeTruthy(); expect(boolSetupCategoriesQuestion.isVisible).toBeFalsy(); expect(boolSetupCategoriesQuestion.value).toBeFalsy(); @@ -96,7 +95,7 @@ test("Preset edit model, toolbox page", () => { expect(boolSetupCategoriesQuestion.isVisible).toBeTruthy(); }); test("Preset edit model, toolbox definition page", () => { - const editor = new CreatorPresetEditor(); + const editor = new CreatorPresetEditorModel(); const survey = editor.model; const page = survey.getPageByName("page_toolbox_definition"); const matrixQuestion = survey.getQuestionByName("toolbox_definition_matrix"); @@ -105,7 +104,7 @@ test("Preset edit model, toolbox definition page", () => { expect(page.isVisible).toBeTruthy(); }); test("Preset edit model, toolbox definition page, validate name/json", () => { - const editor = new CreatorPresetEditor(); + const editor = new CreatorPresetEditorModel(); const survey = editor.model; survey.setValue("toolbox_definition_show", true); const matrixQuestion = survey.getQuestionByName("toolbox_definition_matrix"); @@ -137,7 +136,7 @@ test("Preset edit model, toolbox definition page, default values", () => { ] } }; - const editor = new CreatorPresetEditor(presetJson); + const editor = new CreatorPresetEditorModel(presetJson); const survey = editor.model; expect(survey.getValue("toolbox_definition_show")).toBeTruthy(); const matrixQuestion = survey.getQuestionByName("toolbox_definition_matrix"); @@ -160,7 +159,7 @@ test("Preset edit model, toolbox definition page, default values", () => { expect(val[2]["json"]).toBeFalsy(); }); test("Preset edit model, toolbox definition page, apply", () => { - const editor = new CreatorPresetEditor(); + const editor = new CreatorPresetEditorModel(); const survey = editor.model; survey.setValue("toolbox_definition_show", true); const matrixQuestion = survey.getQuestionByName("toolbox_definition_matrix"); @@ -186,7 +185,7 @@ test("Preset edit model, toolbox definition page, apply", () => { expect(testJson).toEqual(etalon); }); test("Preset edit model, toolbox items, default value and apply", () => { - const editor = new CreatorPresetEditor(); + const editor = new CreatorPresetEditorModel(); const survey = editor.model; survey.setValue("toolbox_show", true); survey.setValue("toolbox_mode", "items"); @@ -206,7 +205,7 @@ test("Preset edit model, toolbox items, default value and apply", () => { expect(testJson).toEqual(etalon); }); test("Preset edit model, toolbox categories, default value and apply", () => { - const editor = new CreatorPresetEditor(); + const editor = new CreatorPresetEditorModel(); const survey = editor.model; survey.setValue("toolbox_show", true); survey.setValue("toolbox_mode", "categories"); @@ -244,7 +243,7 @@ test("Preset edit model, toolbox categories, default value and apply", () => { expect(category.count).toBeFalsy(); }); test("Preset edit model, toolbox items & definition page", () => { - const editor = new CreatorPresetEditor(); + const editor = new CreatorPresetEditorModel(); const survey = editor.model; survey.setValue("toolbox_definition_show", true); survey.setValue("toolbox_show", true); @@ -271,7 +270,7 @@ test("Preset edit model, toolbox items & definition page", () => { expect(itemsQuestion.choices[0].text).toEqual("Radiogroup_New"); }); test("Preset edit model, property grid, setup", () => { - const editor = new CreatorPresetEditor(); + const editor = new CreatorPresetEditorModel(); const survey = editor.model; expect(survey.getPageByName("page_propertyGrid_definition").visible).toBeTruthy(); survey.setValue("propertyGrid_definition_show", true); @@ -307,7 +306,7 @@ test("Preset edit model, property grid, setup", () => { expect(itemsQuestion.choices.length >= itemsQuestion.value.length).toBeTruthy(); }); test("Preset edit model, property grid, setup items in detail panels => survey", () => { - const editor = new CreatorPresetEditor(); + const editor = new CreatorPresetEditorModel(); const survey = editor.model; survey.setValue("propertyGrid_definition_show", true); survey.setValue("propertyGrid_definition_selector", "survey"); @@ -336,7 +335,7 @@ test("Preset edit model, property grid, SurveyQuestionPresetPropertiesDetail", ( expect(rows[0].selectbase).toBeFalsy(); }); test("Preset edit model, property grid, setup items in detail panels => radiogroup", () => { - const editor = new CreatorPresetEditor(); + const editor = new CreatorPresetEditorModel(); const survey = editor.model; survey.setValue("propertyGrid_definition_show", true); survey.setValue("propertyGrid_definition_selector", "radiogroup"); @@ -349,7 +348,7 @@ test("Preset edit model, property grid, setup items in detail panels => radiogro expect(detailPanel.elements[0].name).toBe("items"); }); test("Preset edit model, property grid, apply", () => { - const editor = new CreatorPresetEditor(); + const editor = new CreatorPresetEditorModel(); const survey = editor.model; survey.setValue("propertyGrid_definition_show", true); survey.currentPage = survey.getPageByName("page_propertyGrid_definition"); @@ -390,7 +389,7 @@ test("Preset edit model, property grid, apply", () => { expect(panels2[0].elements).toHaveLength(3); }); test("Preset edit model, live property grid", () => { - const editor = new CreatorPresetEditor(); + const editor = new CreatorPresetEditorModel(); const survey = editor.model; survey.setValue("propertyGrid_definition_show", true); survey.currentPage = survey.getPageByName("page_propertyGrid_definition"); @@ -416,7 +415,7 @@ test("Preset edit model, live property grid", () => { expect(matrix.visibleRows[1].isDetailPanelShowing).toBeFalsy(); }); test("Preset edit model, live property grid & modify value", () => { - const editor = new CreatorPresetEditor(); + const editor = new CreatorPresetEditorModel(); const survey = editor.model; survey.setValue("propertyGrid_definition_show", true); survey.currentPage = survey.getPageByName("page_propertyGrid_definition"); @@ -436,7 +435,7 @@ test("Preset edit model, live property grid & modify value", () => { expect(panels[0].elements[0].name).toBe("widthMode"); }); test("Preset edit model, live property grid & visible indexes", () => { - const editor = new CreatorPresetEditor(); + const editor = new CreatorPresetEditorModel(); const survey = editor.model; survey.setValue("propertyGrid_definition_show", true); survey.currentPage = survey.getPageByName("page_propertyGrid_definition"); @@ -457,7 +456,7 @@ test("Preset edit model, live property grid & visible indexes", () => { expect(elements[4].name).toBe("description"); }); test("Preset edit model, include columns types", () => { - const editor = new CreatorPresetEditor(); + const editor = new CreatorPresetEditorModel(); const survey = editor.model; survey.setValue("propertyGrid_definition_show", true); survey.currentPage = survey.getPageByName("page_propertyGrid_definition"); @@ -466,7 +465,7 @@ test("Preset edit model, include columns types", () => { expect(ItemValue.getItemByValue(question.choices, "matrixdropdowncolumn@checkbox")).toBeTruthy(); }); test("Preset edit model, edit matrixdropdowncolumn@default", () => { - const editor = new CreatorPresetEditor(); + const editor = new CreatorPresetEditorModel(); const survey = editor.model; survey.setValue("propertyGrid_definition_show", true); survey.currentPage = survey.getPageByName("page_propertyGrid_definition"); @@ -480,7 +479,7 @@ test("Preset edit model, edit matrixdropdowncolumn@default", () => { expect(rows[1].getQuestionByName("items").choices).toHaveLength(7); }); test("Preset edit model, live property grid & matrixdropdowncolumn@default", () => { - const editor = new CreatorPresetEditor(); + const editor = new CreatorPresetEditorModel(); const survey = editor.model; survey.setValue("propertyGrid_definition_show", true); survey.currentPage = survey.getPageByName("page_propertyGrid_definition"); @@ -502,7 +501,7 @@ test("Preset edit model, live property grid & matrixdropdowncolumn@default", () expect(panels[0].elements[0].name).toBe("cellType"); }); test("Preset edit model, live property grid & matrixdropdowncolumn@checkbox", () => { - const editor = new CreatorPresetEditor(); + const editor = new CreatorPresetEditorModel(); const survey = editor.model; survey.setValue("propertyGrid_definition_show", true); survey.currentPage = survey.getPageByName("page_propertyGrid_definition"); @@ -528,3 +527,18 @@ test("Preset edit model, live property grid & matrixdropdowncolumn@checkbox", () expect(panels[1].elements[0].name).toBe("choices"); expect(panels[1].elements[1].name).toBe("maxSelectedChoices"); }); +test("Editor: activeTab & navigationBar", () => { + const editor = new CreatorPresetEditorModel(); + expect(editor.activeTab).toEqual("preset"); + expect(editor.navigationBar.actions[0].active).toBeTruthy(); + const survey = editor.model; + const boolQuestion = survey.getQuestionByName("tabs_show"); + const itemsQuestion = survey.getQuestionByName("tabs_items"); + boolQuestion.value = true; + itemsQuestion.value = ["designer", "translation"]; + editor.navigationBar.actions[1].action(); + expect(editor.activeTab).toEqual("creator"); + expect(editor.creator.tabs).toHaveLength(2); + expect(editor.creator.tabs[0].id).toEqual("designer"); + expect(editor.creator.tabs[1].id).toEqual("translation"); +}); diff --git a/packages/survey-creator-react/src/CreatorPresetEditor.tsx b/packages/survey-creator-react/src/CreatorPresetEditor.tsx new file mode 100644 index 0000000000..5ced9622fc --- /dev/null +++ b/packages/survey-creator-react/src/CreatorPresetEditor.tsx @@ -0,0 +1,100 @@ +import React from "react"; +import { Base } from "survey-core"; +import { SurveyActionBar, SurveyElementBase, Survey } from "survey-react-ui"; +import { CreatorPresetEditorModel, SurveyCreatorModel } from "survey-creator-core"; +import { SurveyCreator, SurveyCreatorComponent } from "./SurveyCreator"; + +export class CreatorPresetEditor extends CreatorPresetEditorModel { + protected createCreator(): SurveyCreatorModel { + return new SurveyCreator({}); + } +} + +interface ICreatorPresetEditorComponentProps { + editor: CreatorPresetEditor; + style?: any; +} + +export class CreatorPresetEditorComponent extends SurveyElementBase { + constructor(props: ICreatorPresetEditorComponentProps) { + super(props); + } + get editor(): CreatorPresetEditor { + return this.props.editor; + } + protected getStateElement(): Base { + return this.editor; + } + renderElement() { + const navigation = ; + const context = this.renderContext(); + return <> + {navigation} + {context} + ; + } + private renderContext() { + const tab = this.editor.activeTab; + if (tab === "creator") { + return ; + } + if (tab === "results") return this.renderResults(); + return ; + } + private renderResults() { + const json = this.editor.json; + const els = []; + this.renderJSON(els, undefined, json, 0); + return <>{els}; + } + private renderJSON(els: Array, key: string, json: any, indent: number, hasComma?: boolean): void { + els.push(this.renderJSONElementCore(this.getJSONKey(key) + "{", indent, els.length)); + const keys = Object.keys(json); + for (let i = 0; i < keys.length; i++) { + const elKey = keys[i]; + const val = json[elKey]; + this.renderJSONElement(els, elKey, val, indent + 1, i < keys.length - 1); + } + els.push(this.renderJSONElementCore("}" + (hasComma ? "," : ""), indent, els.length)); + } + private renderJSONArray(els: Array, key: string, val: Array, indent: number, hasComma?: boolean): void { + els.push(this.renderJSONElementCore(this.getJSONKey(key) + "[", indent, els.length)); + for (let i = 0; i < val.length; i++) { + this.renderJSONElement(els, undefined, val[i], indent + 1, i < val.length - 1); + } + els.push(this.renderJSONElementCore("]" + (hasComma ? "," : ""), indent, els.length)); + } + private renderJSONElement(els: Array, key: string, val: any, indent: number, hasComma?: boolean): void { + const comma = hasComma ? "," : ""; + if (Array.isArray(val)) { + this.renderJSONArray(els, key, val, indent + 1, hasComma); + } else { + if (typeof val === "object") { + this.renderJSON(els, key, val, indent + 1, hasComma); + } else { + const str = !!key ? this.getJSONElementText(key, val) : this.getJSONElementVal(val); + els.push(this.renderJSONElementCore(str + comma, indent + 1, els.length)); + } + } + } + private renderJSONElementCore(str: string, indent: number, index: number): JSX.Element { + const key = "i" + index + 1; + const style = { marginLeft: this.getIndentMargin(indent) }; + return
{str}
; + } + private getIndentMargin(indent: number): string { + return (indent * 6) + "px"; + } + private getJSONKey(key: string): string { + return !!key ? "\"" + key + "\": " : ""; + } + private getJSONElementText(key: string, val: any): string { + return this.getJSONKey(key) + this.getJSONElementVal(val); + } + private getJSONElementVal(val: any): string { + if (val === undefined) return "undefined"; + if (val === null) return "null"; + if (typeof val === "string") return "\"" + val + "\""; + return val.toString(); + } +} diff --git a/packages/survey-creator-react/src/entries/index.ts b/packages/survey-creator-react/src/entries/index.ts index da66acc2e7..22c892a50e 100644 --- a/packages/survey-creator-react/src/entries/index.ts +++ b/packages/survey-creator-react/src/entries/index.ts @@ -4,6 +4,7 @@ Version = `${process.env.VERSION}`; // import "@survey/creator/survey-creator-core.css"; export * from "../SurveyCreator"; +export * from "../CreatorPresetEditor"; export * from "../adorners/Row"; export * from "../adorners/Question";