Merge pull request #11383 from appsmithorg/feat/4182-form-detect-changes
feat: Internal property to detect changes in a form
This commit is contained in:
commit
e05e75758d
|
|
@ -19,6 +19,22 @@
|
|||
"dynamicBindingPathList": [],
|
||||
"leftColumn": 0,
|
||||
"children": [
|
||||
{
|
||||
"isVisible": true,
|
||||
"text": "Label",
|
||||
"textAlign": "LEFT",
|
||||
"widgetName": "Text1",
|
||||
"type": "TEXT_WIDGET",
|
||||
"isLoading": false,
|
||||
"parentColumnSpace": 14.015625,
|
||||
"parentRowSpace": 10,
|
||||
"leftColumn": 1,
|
||||
"rightColumn": 7,
|
||||
"topRow": 1,
|
||||
"bottomRow": 4,
|
||||
"parentId": "bxekwxgc1i",
|
||||
"widgetId": "9xcfqahpw2"
|
||||
},
|
||||
{
|
||||
"isMirrored": true,
|
||||
"widgetName": "Camera1",
|
||||
|
|
|
|||
|
|
@ -59,6 +59,22 @@
|
|||
"renderMode": "CANVAS",
|
||||
"isLoading": false,
|
||||
"isInline": true
|
||||
},
|
||||
{
|
||||
"isVisible": true,
|
||||
"text": "Label",
|
||||
"textAlign": "LEFT",
|
||||
"widgetName": "Text1",
|
||||
"type": "TEXT_WIDGET",
|
||||
"isLoading": false,
|
||||
"parentColumnSpace": 18.66171875,
|
||||
"parentRowSpace": 10,
|
||||
"leftColumn": 3,
|
||||
"rightColumn": 10,
|
||||
"topRow": 5,
|
||||
"bottomRow": 9,
|
||||
"parentId": "bxekwxgc1i",
|
||||
"widgetId": "9xcfqahpw2"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -122,6 +122,22 @@
|
|||
"renderMode":"CANVAS",
|
||||
"isLoading":false,
|
||||
"allowClear":false
|
||||
},
|
||||
{
|
||||
"isVisible": true,
|
||||
"text": "Label",
|
||||
"textAlign": "LEFT",
|
||||
"widgetName": "Text1",
|
||||
"type": "TEXT_WIDGET",
|
||||
"isLoading": false,
|
||||
"parentColumnSpace": 15.974999999999998,
|
||||
"parentRowSpace": 10,
|
||||
"leftColumn": 3,
|
||||
"rightColumn": 15,
|
||||
"topRow": 10,
|
||||
"bottomRow": 12,
|
||||
"parentId": "bxekwxgc1i",
|
||||
"widgetId": "9xcfqahpw2"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
481
app/client/cypress/fixtures/formHasChangesDsl.json
Normal file
481
app/client/cypress/fixtures/formHasChangesDsl.json
Normal file
|
|
@ -0,0 +1,481 @@
|
|||
{
|
||||
"dsl": {
|
||||
"widgetName": "MainContainer",
|
||||
"backgroundColor": "none",
|
||||
"rightColumn": 909,
|
||||
"snapColumns": 64,
|
||||
"detachFromLayout": true,
|
||||
"widgetId": "0",
|
||||
"topRow": 0,
|
||||
"bottomRow": 1290,
|
||||
"containerStyle": "none",
|
||||
"snapRows": 125,
|
||||
"parentRowSpace": 1,
|
||||
"type": "CANVAS_WIDGET",
|
||||
"canExtend": true,
|
||||
"version": 52,
|
||||
"minHeight": 690,
|
||||
"parentColumnSpace": 1,
|
||||
"dynamicBindingPathList": [],
|
||||
"leftColumn": 0,
|
||||
"children": [
|
||||
{
|
||||
"widgetName": "Form1",
|
||||
"backgroundColor": "white",
|
||||
"rightColumn": 62,
|
||||
"isCanvas": true,
|
||||
"displayName": "Form",
|
||||
"iconSVG": "/static/media/icon.ea3e08d1.svg",
|
||||
"widgetId": "ui8kenblnq",
|
||||
"topRow": 5,
|
||||
"bottomRow": 62,
|
||||
"parentRowSpace": 10,
|
||||
"isVisible": true,
|
||||
"type": "FORM_WIDGET",
|
||||
"hideCard": false,
|
||||
"parentId": "0",
|
||||
"renderMode": "CANVAS",
|
||||
"isLoading": false,
|
||||
"animateLoading": true,
|
||||
"parentColumnSpace": 14.015625,
|
||||
"leftColumn": 2,
|
||||
"children": [
|
||||
{
|
||||
"widgetName": "Canvas1",
|
||||
"rightColumn": 336.375,
|
||||
"detachFromLayout": true,
|
||||
"displayName": "Canvas",
|
||||
"widgetId": "rgnqy2hpcb",
|
||||
"containerStyle": "none",
|
||||
"topRow": 0,
|
||||
"bottomRow": 570,
|
||||
"parentRowSpace": 1,
|
||||
"isVisible": true,
|
||||
"type": "CANVAS_WIDGET",
|
||||
"canExtend": false,
|
||||
"version": 1,
|
||||
"hideCard": true,
|
||||
"parentId": "ui8kenblnq",
|
||||
"minHeight": 400,
|
||||
"renderMode": "CANVAS",
|
||||
"isLoading": false,
|
||||
"parentColumnSpace": 1,
|
||||
"leftColumn": 0,
|
||||
"children": [
|
||||
{
|
||||
"widgetName": "Text1",
|
||||
"displayName": "Text",
|
||||
"iconSVG": "/static/media/icon.97c59b52.svg",
|
||||
"topRow": 1,
|
||||
"bottomRow": 5,
|
||||
"type": "TEXT_WIDGET",
|
||||
"hideCard": false,
|
||||
"animateLoading": true,
|
||||
"dynamicTriggerPathList": [],
|
||||
"leftColumn": 1.5,
|
||||
"dynamicBindingPathList": [],
|
||||
"shouldTruncate": false,
|
||||
"truncateButtonColor": "#FFC13D",
|
||||
"text": "TopLevelForm",
|
||||
"key": "r71qxtucag",
|
||||
"rightColumn": 25.5,
|
||||
"textAlign": "LEFT",
|
||||
"widgetId": "az2x2gnx8i",
|
||||
"isVisible": true,
|
||||
"fontStyle": "BOLD",
|
||||
"textColor": "#231F20",
|
||||
"shouldScroll": false,
|
||||
"version": 1,
|
||||
"parentId": "rgnqy2hpcb",
|
||||
"renderMode": "CANVAS",
|
||||
"isLoading": false,
|
||||
"fontSize": "HEADING1"
|
||||
},
|
||||
{
|
||||
"boxShadow": "NONE",
|
||||
"widgetName": "Container1",
|
||||
"borderColor": "transparent",
|
||||
"isCanvas": true,
|
||||
"displayName": "Container",
|
||||
"iconSVG": "/static/media/icon.1977dca3.svg",
|
||||
"topRow": 7,
|
||||
"bottomRow": 55,
|
||||
"parentRowSpace": 10,
|
||||
"type": "CONTAINER_WIDGET",
|
||||
"hideCard": false,
|
||||
"animateLoading": true,
|
||||
"parentColumnSpace": 12.8271484375,
|
||||
"leftColumn": 1,
|
||||
"children": [
|
||||
{
|
||||
"widgetName": "Canvas2",
|
||||
"rightColumn": 307.8515625,
|
||||
"detachFromLayout": true,
|
||||
"displayName": "Canvas",
|
||||
"widgetId": "o16xur9huq",
|
||||
"containerStyle": "none",
|
||||
"topRow": 0,
|
||||
"bottomRow": 490,
|
||||
"parentRowSpace": 1,
|
||||
"isVisible": true,
|
||||
"type": "CANVAS_WIDGET",
|
||||
"canExtend": false,
|
||||
"version": 1,
|
||||
"hideCard": true,
|
||||
"parentId": "c3ib5l2wce",
|
||||
"minHeight": 400,
|
||||
"renderMode": "CANVAS",
|
||||
"isLoading": false,
|
||||
"parentColumnSpace": 1,
|
||||
"leftColumn": 0,
|
||||
"children": [
|
||||
{
|
||||
"widgetName": "Form2",
|
||||
"backgroundColor": "white",
|
||||
"rightColumn": 64,
|
||||
"isCanvas": true,
|
||||
"displayName": "Form",
|
||||
"iconSVG": "/static/media/icon.ea3e08d1.svg",
|
||||
"widgetId": "r0vj63apg4",
|
||||
"topRow": 1,
|
||||
"bottomRow": 47,
|
||||
"parentRowSpace": 10,
|
||||
"isVisible": true,
|
||||
"type": "FORM_WIDGET",
|
||||
"hideCard": false,
|
||||
"parentId": "o16xur9huq",
|
||||
"renderMode": "CANVAS",
|
||||
"isLoading": false,
|
||||
"animateLoading": true,
|
||||
"parentColumnSpace": 12.314224243164062,
|
||||
"leftColumn": 0,
|
||||
"children": [
|
||||
{
|
||||
"widgetName": "Canvas3",
|
||||
"rightColumn": 295.5413818359375,
|
||||
"detachFromLayout": true,
|
||||
"displayName": "Canvas",
|
||||
"widgetId": "hyxstzafwr",
|
||||
"containerStyle": "none",
|
||||
"topRow": 0,
|
||||
"bottomRow": 460,
|
||||
"parentRowSpace": 1,
|
||||
"isVisible": true,
|
||||
"type": "CANVAS_WIDGET",
|
||||
"canExtend": false,
|
||||
"version": 1,
|
||||
"hideCard": true,
|
||||
"parentId": "r0vj63apg4",
|
||||
"minHeight": 400,
|
||||
"renderMode": "CANVAS",
|
||||
"isLoading": false,
|
||||
"parentColumnSpace": 1,
|
||||
"leftColumn": 0,
|
||||
"children": [
|
||||
{
|
||||
"widgetName": "Text2",
|
||||
"displayName": "Text",
|
||||
"iconSVG": "/static/media/icon.97c59b52.svg",
|
||||
"topRow": 1,
|
||||
"bottomRow": 5,
|
||||
"type": "TEXT_WIDGET",
|
||||
"hideCard": false,
|
||||
"animateLoading": true,
|
||||
"dynamicTriggerPathList": [],
|
||||
"leftColumn": 1.5,
|
||||
"dynamicBindingPathList": [],
|
||||
"shouldTruncate": false,
|
||||
"truncateButtonColor": "#FFC13D",
|
||||
"text": "NestedForm1",
|
||||
"key": "r71qxtucag",
|
||||
"rightColumn": 25.5,
|
||||
"textAlign": "LEFT",
|
||||
"widgetId": "9x1tljetyn",
|
||||
"isVisible": true,
|
||||
"fontStyle": "BOLD",
|
||||
"textColor": "#231F20",
|
||||
"shouldScroll": false,
|
||||
"version": 1,
|
||||
"parentId": "hyxstzafwr",
|
||||
"renderMode": "CANVAS",
|
||||
"isLoading": false,
|
||||
"fontSize": "HEADING1"
|
||||
},
|
||||
{
|
||||
"boxShadow": "NONE",
|
||||
"widgetName": "Container2",
|
||||
"borderColor": "transparent",
|
||||
"isCanvas": true,
|
||||
"displayName": "Container",
|
||||
"iconSVG": "/static/media/icon.1977dca3.svg",
|
||||
"topRow": 6,
|
||||
"bottomRow": 44,
|
||||
"parentRowSpace": 10,
|
||||
"type": "CONTAINER_WIDGET",
|
||||
"hideCard": false,
|
||||
"animateLoading": true,
|
||||
"parentColumnSpace": 12.001724243164062,
|
||||
"leftColumn": 0,
|
||||
"children": [
|
||||
{
|
||||
"widgetName": "Canvas4",
|
||||
"rightColumn": 288.0413818359375,
|
||||
"detachFromLayout": true,
|
||||
"displayName": "Canvas",
|
||||
"widgetId": "bezg0vuivd",
|
||||
"containerStyle": "none",
|
||||
"topRow": 0,
|
||||
"bottomRow": 390,
|
||||
"parentRowSpace": 1,
|
||||
"isVisible": true,
|
||||
"type": "CANVAS_WIDGET",
|
||||
"canExtend": false,
|
||||
"version": 1,
|
||||
"hideCard": true,
|
||||
"parentId": "d3bbrwipbo",
|
||||
"minHeight": 400,
|
||||
"renderMode": "CANVAS",
|
||||
"isLoading": false,
|
||||
"parentColumnSpace": 1,
|
||||
"leftColumn": 0,
|
||||
"children": [
|
||||
{
|
||||
"widgetName": "Form3",
|
||||
"backgroundColor": "white",
|
||||
"rightColumn": 62,
|
||||
"isCanvas": true,
|
||||
"displayName": "Form",
|
||||
"iconSVG": "/static/media/icon.ea3e08d1.svg",
|
||||
"widgetId": "e9qj527b6g",
|
||||
"topRow": 0,
|
||||
"bottomRow": 36,
|
||||
"parentRowSpace": 10,
|
||||
"isVisible": true,
|
||||
"type": "FORM_WIDGET",
|
||||
"hideCard": false,
|
||||
"parentId": "bezg0vuivd",
|
||||
"renderMode": "CANVAS",
|
||||
"isLoading": false,
|
||||
"animateLoading": true,
|
||||
"parentColumnSpace": 12.001724243164062,
|
||||
"leftColumn": 0,
|
||||
"children": [
|
||||
{
|
||||
"widgetName": "Canvas5",
|
||||
"rightColumn": 288.0413818359375,
|
||||
"detachFromLayout": true,
|
||||
"displayName": "Canvas",
|
||||
"widgetId": "ju0erkgavw",
|
||||
"containerStyle": "none",
|
||||
"topRow": 0,
|
||||
"bottomRow": 390,
|
||||
"parentRowSpace": 1,
|
||||
"isVisible": true,
|
||||
"type": "CANVAS_WIDGET",
|
||||
"canExtend": false,
|
||||
"version": 1,
|
||||
"hideCard": true,
|
||||
"parentId": "e9qj527b6g",
|
||||
"minHeight": 400,
|
||||
"renderMode": "CANVAS",
|
||||
"isLoading": false,
|
||||
"parentColumnSpace": 1,
|
||||
"leftColumn": 0,
|
||||
"children": [
|
||||
{
|
||||
"widgetName": "Text3",
|
||||
"displayName": "Text",
|
||||
"iconSVG": "/static/media/icon.97c59b52.svg",
|
||||
"topRow": 1,
|
||||
"bottomRow": 5,
|
||||
"type": "TEXT_WIDGET",
|
||||
"hideCard": false,
|
||||
"animateLoading": true,
|
||||
"dynamicTriggerPathList": [],
|
||||
"leftColumn": 1.5,
|
||||
"dynamicBindingPathList": [],
|
||||
"shouldTruncate": false,
|
||||
"truncateButtonColor": "#FFC13D",
|
||||
"text": "NestedForm2",
|
||||
"key": "r71qxtucag",
|
||||
"rightColumn": 25.5,
|
||||
"textAlign": "LEFT",
|
||||
"widgetId": "kx3kje0esv",
|
||||
"isVisible": true,
|
||||
"fontStyle": "BOLD",
|
||||
"textColor": "#231F20",
|
||||
"shouldScroll": false,
|
||||
"version": 1,
|
||||
"parentId": "ju0erkgavw",
|
||||
"renderMode": "CANVAS",
|
||||
"isLoading": false,
|
||||
"fontSize": "HEADING1"
|
||||
},
|
||||
{
|
||||
"resetFormOnClick": true,
|
||||
"widgetName": "FormButton1",
|
||||
"buttonColor": "#03B365",
|
||||
"displayName": "FormButton",
|
||||
"iconSVG": "/static/media/icon.c8f649ed.svg",
|
||||
"topRow": 29,
|
||||
"bottomRow": 33,
|
||||
"type": "FORM_BUTTON_WIDGET",
|
||||
"hideCard": true,
|
||||
"animateLoading": true,
|
||||
"leftColumn": 47,
|
||||
"text": "Submit",
|
||||
"key": "6rckarmxa8",
|
||||
"rightColumn": 63,
|
||||
"isDefaultClickDisabled": true,
|
||||
"widgetId": "71jwl9rqyl",
|
||||
"isVisible": true,
|
||||
"recaptchaType": "V3",
|
||||
"version": 1,
|
||||
"parentId": "ju0erkgavw",
|
||||
"renderMode": "CANVAS",
|
||||
"isLoading": false,
|
||||
"disabledWhenInvalid": true,
|
||||
"buttonVariant": "PRIMARY"
|
||||
},
|
||||
{
|
||||
"resetFormOnClick": true,
|
||||
"widgetName": "FormButton2",
|
||||
"buttonColor": "#03B365",
|
||||
"displayName": "FormButton",
|
||||
"iconSVG": "/static/media/icon.c8f649ed.svg",
|
||||
"topRow": 29,
|
||||
"bottomRow": 33,
|
||||
"type": "FORM_BUTTON_WIDGET",
|
||||
"hideCard": true,
|
||||
"animateLoading": true,
|
||||
"leftColumn": 30,
|
||||
"text": "Reset",
|
||||
"key": "6rckarmxa8",
|
||||
"rightColumn": 46,
|
||||
"isDefaultClickDisabled": true,
|
||||
"widgetId": "385vwj1sak",
|
||||
"isVisible": true,
|
||||
"recaptchaType": "V3",
|
||||
"version": 1,
|
||||
"parentId": "ju0erkgavw",
|
||||
"renderMode": "CANVAS",
|
||||
"isLoading": false,
|
||||
"disabledWhenInvalid": false,
|
||||
"buttonVariant": "SECONDARY"
|
||||
},
|
||||
{
|
||||
"widgetName": "Checkbox1",
|
||||
"displayName": "Checkbox",
|
||||
"iconSVG": "/static/media/icon.aaab032b.svg",
|
||||
"topRow": 7,
|
||||
"bottomRow": 11,
|
||||
"parentRowSpace": 10,
|
||||
"type": "CHECKBOX_WIDGET",
|
||||
"alignWidget": "LEFT",
|
||||
"hideCard": false,
|
||||
"animateLoading": true,
|
||||
"parentColumnSpace": 11.011435985565186,
|
||||
"leftColumn": 1,
|
||||
"isDisabled": false,
|
||||
"key": "kn37pa6063",
|
||||
"isRequired": false,
|
||||
"rightColumn": 21,
|
||||
"widgetId": "xcs2djteir",
|
||||
"isVisible": true,
|
||||
"label": "Label",
|
||||
"version": 1,
|
||||
"parentId": "ju0erkgavw",
|
||||
"renderMode": "CANVAS",
|
||||
"isLoading": false,
|
||||
"defaultCheckedState": true
|
||||
}
|
||||
],
|
||||
"key": "invgby4psp"
|
||||
}
|
||||
],
|
||||
"key": "1yxjunjfwb"
|
||||
}
|
||||
],
|
||||
"key": "invgby4psp"
|
||||
}
|
||||
],
|
||||
"borderWidth": "0",
|
||||
"key": "tpj0tcwdhg",
|
||||
"backgroundColor": "#FFFFFF",
|
||||
"rightColumn": 64,
|
||||
"widgetId": "d3bbrwipbo",
|
||||
"containerStyle": "card",
|
||||
"isVisible": true,
|
||||
"version": 1,
|
||||
"parentId": "hyxstzafwr",
|
||||
"renderMode": "CANVAS",
|
||||
"isLoading": false,
|
||||
"borderRadius": "0"
|
||||
}
|
||||
],
|
||||
"key": "invgby4psp"
|
||||
}
|
||||
],
|
||||
"key": "1yxjunjfwb"
|
||||
}
|
||||
],
|
||||
"key": "invgby4psp"
|
||||
}
|
||||
],
|
||||
"borderWidth": "0",
|
||||
"key": "tpj0tcwdhg",
|
||||
"backgroundColor": "#FFFFFF",
|
||||
"rightColumn": 64,
|
||||
"widgetId": "c3ib5l2wce",
|
||||
"containerStyle": "card",
|
||||
"isVisible": true,
|
||||
"version": 1,
|
||||
"parentId": "rgnqy2hpcb",
|
||||
"renderMode": "CANVAS",
|
||||
"isLoading": false,
|
||||
"borderRadius": "0"
|
||||
},
|
||||
{
|
||||
"widgetName": "Text4",
|
||||
"displayName": "Text",
|
||||
"iconSVG": "/static/media/icon.97c59b52.svg",
|
||||
"topRow": 1,
|
||||
"bottomRow": 5,
|
||||
"parentRowSpace": 10,
|
||||
"type": "TEXT_WIDGET",
|
||||
"hideCard": false,
|
||||
"animateLoading": true,
|
||||
"parentColumnSpace": 12.8271484375,
|
||||
"dynamicTriggerPathList": [],
|
||||
"leftColumn": 47,
|
||||
"dynamicBindingPathList": [
|
||||
{
|
||||
"key": "text"
|
||||
}
|
||||
],
|
||||
"shouldTruncate": false,
|
||||
"truncateButtonColor": "#FFC13D",
|
||||
"text": "{{Form1.hasChanges}}",
|
||||
"key": "r71qxtucag",
|
||||
"rightColumn": 63,
|
||||
"textAlign": "LEFT",
|
||||
"widgetId": "6lwl9odtd7",
|
||||
"isVisible": true,
|
||||
"fontStyle": "BOLD",
|
||||
"textColor": "#231F20",
|
||||
"shouldScroll": false,
|
||||
"version": 1,
|
||||
"parentId": "rgnqy2hpcb",
|
||||
"renderMode": "CANVAS",
|
||||
"isLoading": false,
|
||||
"fontSize": "PARAGRAPH"
|
||||
}
|
||||
],
|
||||
"key": "invgby4psp"
|
||||
}
|
||||
],
|
||||
"key": "1yxjunjfwb"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
@ -105,6 +105,22 @@
|
|||
"bottomRow": 7,
|
||||
"parentId": "7tkpo9s22m",
|
||||
"widgetId": "6h8j08u7ea"
|
||||
},
|
||||
{
|
||||
"isVisible": true,
|
||||
"text": "Label",
|
||||
"textAlign": "LEFT",
|
||||
"widgetName": "Text1",
|
||||
"type": "TEXT_WIDGET",
|
||||
"isLoading": false,
|
||||
"parentColumnSpace": 71.75,
|
||||
"parentRowSpace": 38,
|
||||
"leftColumn": 3,
|
||||
"rightColumn": 5,
|
||||
"topRow": 10,
|
||||
"bottomRow": 12,
|
||||
"parentId": "bxekwxgc1i",
|
||||
"widgetId": "9xcfqahpw2"
|
||||
}
|
||||
],
|
||||
"widgetId": "7tkpo9s22m",
|
||||
|
|
|
|||
|
|
@ -61,6 +61,25 @@
|
|||
"leftColumn": 0,
|
||||
"dynamicBindingPathList": [],
|
||||
"children": [
|
||||
{
|
||||
"widgetName": "Text1",
|
||||
"rightColumn": 10,
|
||||
"widgetId": "4d8d2eh4xg",
|
||||
"dynamicPropertyPathList": [],
|
||||
"topRow": 0,
|
||||
"bottomRow": 3,
|
||||
"parentRowSpace": 38,
|
||||
"isVisible": true,
|
||||
"type": "TEXT_WIDGET",
|
||||
"dynamicBindingPathList": [],
|
||||
"shouldScroll": true,
|
||||
"parentId": "hjiybwqair",
|
||||
"isLoading": false,
|
||||
"parentColumnSpace": 71.75,
|
||||
"leftColumn": 1,
|
||||
"text": "Test text",
|
||||
"textStyle": "HEADING"
|
||||
},
|
||||
{
|
||||
"isRequired": false,
|
||||
"widgetName": "Input1",
|
||||
|
|
|
|||
|
|
@ -52,6 +52,25 @@
|
|||
"snapColumns": 16,
|
||||
"orientation": "VERTICAL",
|
||||
"children": [
|
||||
{
|
||||
"widgetName": "Text1",
|
||||
"rightColumn": 3,
|
||||
"widgetId": "4d8d2eh4xg",
|
||||
"dynamicPropertyPathList": [],
|
||||
"topRow": 0,
|
||||
"bottomRow": 1,
|
||||
"parentRowSpace": 38,
|
||||
"isVisible": true,
|
||||
"type": "TEXT_WIDGET",
|
||||
"dynamicBindingPathList": [],
|
||||
"shouldScroll": true,
|
||||
"parentId": "hjiybwqair",
|
||||
"isLoading": false,
|
||||
"parentColumnSpace": 71.75,
|
||||
"leftColumn": 1,
|
||||
"text": "Test text",
|
||||
"textStyle": "HEADING"
|
||||
},
|
||||
{
|
||||
"isVisible": true,
|
||||
"inputType": "TEXT",
|
||||
|
|
|
|||
|
|
@ -59,9 +59,10 @@ describe("Entity explorer Drag and Drop widgets testcases", function() {
|
|||
cy.hoverAndClickParticularIndex(1);
|
||||
cy.selectAction("Show Bindings");
|
||||
cy.get(apiwidget.propertyList).then(function($lis) {
|
||||
expect($lis).to.have.length(2);
|
||||
expect($lis).to.have.length(3);
|
||||
expect($lis.eq(0)).to.contain("{{FormTest.isVisible}}");
|
||||
expect($lis.eq(1)).to.contain("{{FormTest.data}}");
|
||||
expect($lis.eq(2)).to.contain("{{FormTest.hasChanges}}");
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -35,9 +35,10 @@ describe("Test Suite to validate copy/delete/undo functionalites", function() {
|
|||
cy.hoverAndClickParticularIndex(1);
|
||||
cy.selectAction("Show Bindings");
|
||||
cy.get(apiwidget.propertyList).then(function($lis) {
|
||||
expect($lis).to.have.length(2);
|
||||
expect($lis).to.have.length(3);
|
||||
expect($lis.eq(0)).to.contain("{{FormTest.isVisible}}");
|
||||
expect($lis.eq(1)).to.contain("{{FormTest.data}}");
|
||||
expect($lis.eq(2)).to.contain("{{FormTest.hasChanges}}");
|
||||
});
|
||||
cy.get(".t--entity-name")
|
||||
.contains("FormTest")
|
||||
|
|
@ -68,9 +69,10 @@ describe("Test Suite to validate copy/delete/undo functionalites", function() {
|
|||
cy.hoverAndClickParticularIndex(1);
|
||||
cy.selectAction("Show Bindings");
|
||||
cy.get(apiwidget.propertyList).then(function($lis) {
|
||||
expect($lis).to.have.length(2);
|
||||
expect($lis).to.have.length(3);
|
||||
expect($lis.eq(0)).to.contain("{{FormTest.isVisible}}");
|
||||
expect($lis.eq(1)).to.contain("{{FormTest.data}}");
|
||||
expect($lis.eq(2)).to.contain("{{FormTest.hasChanges}}");
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -46,9 +46,10 @@ describe("Test Suite to validate copy/delete/undo functionalites", function() {
|
|||
ee.expandCollapseEntity("FormTest");
|
||||
ee.ActionContextMenuByEntityName("FormTestCopy", "Show Bindings");
|
||||
cy.get(apiwidget.propertyList).then(function($lis) {
|
||||
expect($lis).to.have.length(2);
|
||||
expect($lis).to.have.length(3);
|
||||
expect($lis.eq(0)).to.contain("{{FormTestCopy.isVisible}}");
|
||||
expect($lis.eq(1)).to.contain("{{FormTestCopy.data}}");
|
||||
expect($lis.eq(2)).to.contain("{{FormTestCopy.hasChanges}}");
|
||||
cy.contains("FormTestCopy");
|
||||
cy.get($lis.eq(1))
|
||||
.contains("{{FormTestCopy.data}}")
|
||||
|
|
|
|||
|
|
@ -0,0 +1,40 @@
|
|||
const explorer = require("../../../../locators/explorerlocators.json");
|
||||
|
||||
const widgetName = "audiorecorderwidget";
|
||||
|
||||
describe("AudioRecorder Widget", () => {
|
||||
it("Drag & drop AudioRecorder and Text widgets", () => {
|
||||
cy.get(explorer.addWidget).click();
|
||||
cy.dragAndDropToCanvas(widgetName, { x: 300, y: 300 });
|
||||
cy.get(`.t--widget-${widgetName}`).should("exist");
|
||||
cy.dragAndDropToCanvas("textwidget", { x: 300, y: 500 });
|
||||
cy.openPropertyPane("textwidget");
|
||||
cy.updateCodeInput(
|
||||
".t--property-control-text",
|
||||
`{{AudioRecorder1.isDirty}}`,
|
||||
);
|
||||
});
|
||||
|
||||
it("Check isDirty meta property", () => {
|
||||
// Check if isDirty is false for the first time
|
||||
cy.get(".t--widget-textwidget").should("contain", "false");
|
||||
// Interact with UI
|
||||
cy.get(`.t--widget-${widgetName} button`)
|
||||
.first()
|
||||
.click();
|
||||
cy.get(`.t--widget-${widgetName} .status`)
|
||||
.should("have.text", "Press to start recording")
|
||||
.should("exist");
|
||||
// Start recording and recorder for 3 seconds
|
||||
cy.get(`.t--widget-${widgetName} button`)
|
||||
.first()
|
||||
.click();
|
||||
cy.wait(3000);
|
||||
// Stop recording
|
||||
cy.get(`.t--widget-${widgetName} button span.bp3-icon-symbol-square`)
|
||||
.first()
|
||||
.click();
|
||||
// Check if isDirty is set to true
|
||||
cy.get(".t--widget-textwidget").should("contain", "true");
|
||||
});
|
||||
});
|
||||
|
|
@ -14,12 +14,16 @@ describe("Camera Widget", () => {
|
|||
cy.goToEditFromPublish();
|
||||
});
|
||||
|
||||
it("Property: onImageSave, show modal", () => {
|
||||
it("Check isDirty, onImageSave", () => {
|
||||
const modalName = `modal`;
|
||||
const mainControlSelector =
|
||||
"//div[contains(@class, 't--widget-camerawidget')]//button";
|
||||
|
||||
cy.createModal(modalName);
|
||||
cy.openPropertyPane("textwidget");
|
||||
cy.updateCodeInput(".t--property-control-text", "{{Camera1.isDirty}}");
|
||||
// Initial value of isDirty should be false
|
||||
cy.get(".t--widget-textwidget").should("contain", "false");
|
||||
// Take photo
|
||||
cy.xpath(mainControlSelector)
|
||||
.eq(2)
|
||||
|
|
@ -32,5 +36,7 @@ describe("Camera Widget", () => {
|
|||
|
||||
// Assert: should trigger onImageSave action - modal popup
|
||||
cy.get(modalWidgetPage.modelTextField).should("have.text", modalName);
|
||||
// Check if isDirty is set to true
|
||||
cy.get(".t--widget-textwidget").should("contain", "true");
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ const publish = require("../../../../locators/publishWidgetspage.json");
|
|||
const dsl = require("../../../../fixtures/newFormDsl.json");
|
||||
const formWidgetDsl = require("../../../../fixtures/formWidgetdsl.json");
|
||||
const pages = require("../../../../locators/Pages.json");
|
||||
const explorer = require("../../../../locators/explorerlocators.json");
|
||||
|
||||
describe("Checkbox Widget Functionality", function() {
|
||||
before(() => {
|
||||
|
|
@ -72,6 +73,26 @@ describe("Checkbox Widget Functionality", function() {
|
|||
cy.get(publish.checkboxWidget + " " + "input").should("be.checked");
|
||||
cy.get(publish.backToEditor).click();
|
||||
});
|
||||
|
||||
it("Check isDirty meta property", function() {
|
||||
cy.openPropertyPane("textwidget");
|
||||
cy.updateCodeInput(".t--property-control-text", `{{checker.isDirty}}`);
|
||||
// Check if initial value of isDirty is false
|
||||
cy.get(".t--widget-textwidget").should("contain", "false");
|
||||
// Interact with UI
|
||||
cy.get(`${formWidgetsPage.checkboxWidget} label`)
|
||||
.first()
|
||||
.click();
|
||||
// Check if isDirty is set to true
|
||||
cy.get(".t--widget-textwidget").should("contain", "true");
|
||||
// Change defaultCheckedState property
|
||||
cy.openPropertyPane("checkboxwidget");
|
||||
cy.get(".t--property-control-defaultselected label")
|
||||
.last()
|
||||
.click();
|
||||
// Check if isDirty is reset to false
|
||||
cy.get(".t--widget-textwidget").should("contain", "false");
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
const commonlocators = require("../../../../locators/commonlocators.json");
|
||||
const formWidgetsPage = require("../../../../locators/FormWidgets.json");
|
||||
const publish = require("../../../../locators/publishWidgetspage.json");
|
||||
const explorer = require("../../../../locators/explorerlocators.json");
|
||||
const dsl = require("../../../../fixtures/checkboxgroupDsl.json");
|
||||
|
||||
describe("Checkbox Group Widget Functionality", function() {
|
||||
|
|
@ -129,6 +130,27 @@ describe("Checkbox Group Widget Functionality", function() {
|
|||
".t--draggable-checkboxgroupwidget div[data-cy^='checkbox-group-container']",
|
||||
).should("have.css", "justify-content", "flex-start");
|
||||
});
|
||||
|
||||
it("Check isDirty meta property", function() {
|
||||
cy.get(explorer.addWidget).click();
|
||||
cy.dragAndDropToCanvas("textwidget", { x: 300, y: 500 });
|
||||
cy.openPropertyPane("textwidget");
|
||||
cy.updateCodeInput(
|
||||
".t--property-control-text",
|
||||
`{{checkboxgrouptest.isDirty}}`,
|
||||
);
|
||||
// Change defaultSelectedValues
|
||||
cy.openPropertyPane("checkboxgroupwidget");
|
||||
cy.updateCodeInput(".t--property-control-defaultselectedvalues", "GREEN");
|
||||
// Check if isDirty is reset to false
|
||||
cy.get(".t--widget-textwidget").should("contain", "false");
|
||||
// Interact with UI
|
||||
cy.get(formWidgetsPage.labelCheckboxGroup)
|
||||
.first()
|
||||
.click();
|
||||
// Check if isDirty is set to true
|
||||
cy.get(".t--widget-textwidget").should("contain", "true");
|
||||
});
|
||||
});
|
||||
afterEach(() => {
|
||||
// put your clean up code if any
|
||||
|
|
|
|||
|
|
@ -248,4 +248,28 @@ describe("Currency widget - ", () => {
|
|||
enterAndTest(d[0], d[1]);
|
||||
});
|
||||
});
|
||||
|
||||
it("Check isDirty meta property", function() {
|
||||
cy.openPropertyPane("textwidget");
|
||||
cy.updateCodeInput(
|
||||
".t--property-control-text",
|
||||
`{{CurrencyInput1.isDirty}}`,
|
||||
);
|
||||
// Init isDirty
|
||||
cy.openPropertyPane(widgetName);
|
||||
cy.updateCodeInput(".t--property-control-defaulttext", "1");
|
||||
cy.closePropertyPane();
|
||||
// Check if initial value of isDirty is false
|
||||
cy.get(".t--widget-textwidget").should("contain", "false");
|
||||
// Interact with UI
|
||||
cy.get(widgetInput).clear();
|
||||
cy.wait(300);
|
||||
// Check if isDirty is set to true
|
||||
cy.get(".t--widget-textwidget").should("contain", "true");
|
||||
// Change defaultText
|
||||
cy.openPropertyPane(widgetName);
|
||||
cy.updateCodeInput(".t--property-control-defaulttext", "5");
|
||||
// Check if isDirty is reset to false
|
||||
cy.get(".t--widget-textwidget").should("contain", "false");
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -140,6 +140,49 @@ describe("DatePicker Widget Property pane tests with js bindings", function() {
|
|||
.should("have.text", "May 4, 2021 6:25 AM");
|
||||
});
|
||||
|
||||
it("Check isDirty meta property", function() {
|
||||
cy.openPropertyPane("textwidget");
|
||||
cy.updateCodeInput(".t--property-control-text", `{{DatePicker1.isDirty}}`);
|
||||
// Init isDirty
|
||||
cy.openPropertyPane("datepickerwidget2");
|
||||
cy.get(formWidgetsPage.toggleJsDefaultDate).click();
|
||||
cy.get(".t--property-control-defaultdate .bp3-input").clear();
|
||||
cy.get(formWidgetsPage.toggleJsDefaultDate).click();
|
||||
cy.testJsontext(
|
||||
"defaultdate",
|
||||
'{{moment("04/05/2021 05:25", "DD/MM/YYYY HH:mm").toISOString()}}',
|
||||
);
|
||||
cy.closePropertyPane();
|
||||
// Check if initial value of isDirty is false
|
||||
cy.get(".t--widget-textwidget")
|
||||
.first()
|
||||
.should("contain", "false");
|
||||
// Interact with UI
|
||||
cy.get(".t--draggable-datepickerwidget2 .bp3-input")
|
||||
.clear({
|
||||
force: true,
|
||||
})
|
||||
.type("04/05/2021 06:25");
|
||||
cy.wait("@updateLayout");
|
||||
// Check if isDirty is set to true
|
||||
cy.get(".t--widget-textwidget")
|
||||
.first()
|
||||
.should("contain", "true");
|
||||
// Change defaultDate
|
||||
cy.openPropertyPane("datepickerwidget2");
|
||||
cy.get(formWidgetsPage.toggleJsDefaultDate).click();
|
||||
cy.get(".t--property-control-defaultdate .bp3-input").clear();
|
||||
cy.get(formWidgetsPage.toggleJsDefaultDate).click();
|
||||
cy.testJsontext(
|
||||
"defaultdate",
|
||||
'{{moment("07/05/2021 05:25", "DD/MM/YYYY HH:mm").toISOString()}}',
|
||||
);
|
||||
// Check if isDirty is reset to false
|
||||
cy.get(".t--widget-textwidget")
|
||||
.first()
|
||||
.should("contain", "false");
|
||||
});
|
||||
|
||||
it("Datepicker default date validation with js binding", function() {
|
||||
cy.PublishtheApp();
|
||||
// eslint-disable-next-line cypress/no-unnecessary-waiting
|
||||
|
|
|
|||
|
|
@ -0,0 +1,30 @@
|
|||
const explorer = require("../../../../locators/explorerlocators.json");
|
||||
const commonlocators = require("../../../../locators/commonlocators.json");
|
||||
|
||||
const widgetName = "filepickerwidgetv2";
|
||||
|
||||
describe("File picker widget v2", () => {
|
||||
it("1. Drag & drop FilePicker/Text widgets", () => {
|
||||
cy.get(explorer.addWidget).click();
|
||||
cy.dragAndDropToCanvas(widgetName, { x: 300, y: 300 });
|
||||
cy.get(`.t--widget-${widgetName}`).should("exist");
|
||||
cy.dragAndDropToCanvas("textwidget", { x: 300, y: 500 });
|
||||
cy.openPropertyPane("textwidget");
|
||||
cy.updateCodeInput(".t--property-control-text", `{{FilePicker1.isDirty}}`);
|
||||
});
|
||||
|
||||
it("Check isDirty meta property", function() {
|
||||
// Check if initial value of isDirty is false
|
||||
cy.get(".t--widget-textwidget").should("contain", "false");
|
||||
// Upload a new file
|
||||
cy.get(`.t--widget-${widgetName}`).click();
|
||||
cy.get(commonlocators.filePickerInput)
|
||||
.first()
|
||||
.attachFile("testFile.mov");
|
||||
cy.get(commonlocators.filePickerUploadButton).click();
|
||||
//eslint-disable-next-line cypress/no-unnecessary-waiting
|
||||
cy.wait(500);
|
||||
// Check if isDirty is set to true
|
||||
cy.get(".t--widget-textwidget").should("contain", "true");
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
const dsl = require("../../../../fixtures/formHasChangesDsl.json");
|
||||
|
||||
describe("Form Widget", () => {
|
||||
before(() => {
|
||||
cy.addDsl(dsl);
|
||||
});
|
||||
|
||||
it("Check hasChanges meta property", () => {
|
||||
// Check if isDirty is false for the first time
|
||||
cy.contains(".t--widget-textwidget", "false").should("exist");
|
||||
// Interact with UI
|
||||
cy.get(`.t--widget-checkboxwidget label`)
|
||||
.first()
|
||||
.click();
|
||||
// Check if isDirty is set to true
|
||||
cy.contains(".t--widget-textwidget", "false").should("not.exist");
|
||||
cy.contains(".t--widget-textwidget", "true").should("exist");
|
||||
});
|
||||
});
|
||||
|
|
@ -422,6 +422,29 @@ describe("Input widget V2 - ", () => {
|
|||
cy.get(".t--widget-textwidget").should("contain", "1.0001:1.0001:true");
|
||||
});
|
||||
|
||||
it("Check isDirty meta property", function() {
|
||||
cy.openPropertyPane("textwidget");
|
||||
cy.updateCodeInput(".t--property-control-text", `{{Input1.isDirty}}`);
|
||||
// Init isDirty
|
||||
cy.openPropertyPane(widgetName);
|
||||
cy.selectDropdownValue(".t--property-control-datatype", "Text");
|
||||
cy.updateCodeInput(".t--property-control-defaulttext", "a");
|
||||
// Check if initial value of isDirty is false
|
||||
cy.get(".t--widget-textwidget").should("contain", "false");
|
||||
// Interact with UI
|
||||
cy.get(widgetInput).clear();
|
||||
cy.wait(300);
|
||||
cy.get(widgetInput).type("b");
|
||||
cy.wait(300);
|
||||
// Check if isDirty is set to true
|
||||
cy.get(".t--widget-textwidget").should("contain", "true");
|
||||
// Change defaultText
|
||||
cy.openPropertyPane(widgetName);
|
||||
cy.updateCodeInput(".t--property-control-defaulttext", "c");
|
||||
// Check if isDirty is reset to false
|
||||
cy.get(".t--widget-textwidget").should("contain", "false");
|
||||
});
|
||||
|
||||
function enterAndTest(text, expected) {
|
||||
cy.get(`.t--widget-${widgetName} input`).clear();
|
||||
cy.wait(300);
|
||||
|
|
|
|||
|
|
@ -90,6 +90,30 @@ describe("MultiSelect Widget Functionality", function() {
|
|||
.eq(1)
|
||||
.should("have.text", "Option 2");
|
||||
});
|
||||
|
||||
it("Check isDirty meta property", function() {
|
||||
cy.openPropertyPane("textwidget");
|
||||
cy.updateCodeInput(".t--property-control-text", `{{MultiSelect2.isDirty}}`);
|
||||
// Init isDirty by changing defaultOptionValue
|
||||
cy.openPropertyPane("multiselectwidgetv2");
|
||||
cy.updateCodeInput(
|
||||
".t--property-control-defaultvalue",
|
||||
'[\n {\n "label": "Option 1",\n "value": "1"\n }\n]',
|
||||
);
|
||||
cy.get(".t--widget-textwidget").should("contain", "false");
|
||||
// Interact with UI
|
||||
cy.get(".rc-select-selector").click({ force: true });
|
||||
cy.dropdownMultiSelectDynamic("Option 2");
|
||||
// Check if isDirty is set to true
|
||||
cy.get(".t--widget-textwidget").should("contain", "true");
|
||||
// Reset isDirty by changing defaultOptionValue
|
||||
cy.updateCodeInput(
|
||||
".t--property-control-defaultvalue",
|
||||
'[\n {\n "label": "Option 2",\n "value": "2"\n }\n]',
|
||||
);
|
||||
// Check if isDirty is set to false
|
||||
cy.get(".t--widget-textwidget").should("contain", "false");
|
||||
});
|
||||
});
|
||||
afterEach(() => {
|
||||
// put your clean up code if any
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ const dsl = require("../../../../fixtures/TreeSelectDsl.json");
|
|||
const formWidgetsPage = require("../../../../locators/FormWidgets.json");
|
||||
const publish = require("../../../../locators/publishWidgetspage.json");
|
||||
const commonlocators = require("../../../../locators/commonlocators.json");
|
||||
const explorer = require("../../../../locators/explorerlocators.json");
|
||||
|
||||
describe("MultiSelectTree Widget Functionality", function() {
|
||||
before(() => {
|
||||
|
|
@ -41,6 +42,32 @@ describe("MultiSelectTree Widget Functionality", function() {
|
|||
).should("be.visible");
|
||||
cy.get(publish.backToEditor).click();
|
||||
});
|
||||
|
||||
it("Check isDirty meta property", function() {
|
||||
cy.get(explorer.addWidget).click();
|
||||
cy.dragAndDropToCanvas("textwidget", { x: 300, y: 500 });
|
||||
cy.openPropertyPane("textwidget");
|
||||
cy.updateCodeInput(
|
||||
".t--property-control-text",
|
||||
`{{MultiSelectTree1.isDirty}}`,
|
||||
);
|
||||
// Change defaultValue
|
||||
cy.openPropertyPane("multiselecttreewidget");
|
||||
cy.testJsontext("defaultvalue", "GREEN\n");
|
||||
// Check if isDirty is set to false
|
||||
cy.get(".t--widget-textwidget").should("contain", "false");
|
||||
// Interact with UI
|
||||
cy.get(formWidgetsPage.treeSelectInput)
|
||||
.first()
|
||||
.click({ force: true });
|
||||
cy.treeMultiSelectDropdown("Red");
|
||||
// Check if isDirty is set to true
|
||||
cy.get(".t--widget-textwidget").should("contain", "true");
|
||||
// Reset isDirty by changing defaultValue
|
||||
cy.testJsontext("defaultvalue", "BLUE\n");
|
||||
// Check if isDirty is set to false
|
||||
cy.get(".t--widget-textwidget").should("contain", "false");
|
||||
});
|
||||
});
|
||||
afterEach(() => {
|
||||
// put your clean up code if any
|
||||
|
|
|
|||
|
|
@ -105,4 +105,27 @@ describe("Phone input widget - ", () => {
|
|||
cy.get(widgetInput).should("contain.value", "");
|
||||
cy.get(".t--widget-textwidget").should("contain", ":undefined");
|
||||
});
|
||||
|
||||
it("Check isDirty meta property", function() {
|
||||
cy.openPropertyPane("textwidget");
|
||||
cy.updateCodeInput(".t--property-control-text", `{{PhoneInput1.isDirty}}`);
|
||||
// Change defaultText
|
||||
cy.openPropertyPane(widgetName);
|
||||
cy.updateCodeInput(".t--property-control-defaulttext", "1");
|
||||
cy.closePropertyPane();
|
||||
// Check if isDirty is set to false
|
||||
cy.get(".t--widget-textwidget").should("contain", "false");
|
||||
// Interact with UI
|
||||
cy.get(widgetInput).clear();
|
||||
cy.wait(300);
|
||||
cy.get(widgetInput).type("2");
|
||||
cy.wait(300);
|
||||
// Check if isDirty is set to true
|
||||
cy.get(".t--widget-textwidget").should("contain", "true");
|
||||
// Reset isDirty by changing defaultText
|
||||
cy.openPropertyPane(widgetName);
|
||||
cy.updateCodeInput(".t--property-control-defaulttext", "3");
|
||||
// Check if isDirty is set to false
|
||||
cy.get(".t--widget-textwidget").should("contain", "false");
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -0,0 +1,30 @@
|
|||
const explorer = require("../../../../locators/explorerlocators.json");
|
||||
|
||||
const widgetName = "radiogroupwidget";
|
||||
|
||||
describe("Radio Group Widget", () => {
|
||||
it("Drag & drop Radio group & Text widgets", () => {
|
||||
cy.get(explorer.addWidget).click();
|
||||
cy.dragAndDropToCanvas(widgetName, { x: 300, y: 300 });
|
||||
cy.get(`.t--widget-${widgetName}`).should("exist");
|
||||
cy.dragAndDropToCanvas("textwidget", { x: 300, y: 500 });
|
||||
cy.openPropertyPane("textwidget");
|
||||
cy.updateCodeInput(".t--property-control-text", `{{RadioGroup1.isDirty}}`);
|
||||
});
|
||||
|
||||
it("Check isDirty meta property", function() {
|
||||
// Check if initial value of isDirty is false
|
||||
cy.get(".t--widget-textwidget").should("contain", "false");
|
||||
// Interact with UI
|
||||
cy.get(".t--widget-radiogroupwidget .bp3-radio")
|
||||
.last()
|
||||
.click();
|
||||
// Check if isDirty is set to true
|
||||
cy.get(".t--widget-textwidget").should("contain", "true");
|
||||
// Change defaultOptionValue
|
||||
cy.openPropertyPane(widgetName);
|
||||
cy.updateCodeInput(".t--property-control-defaultselectedvalue", "N");
|
||||
// Check if isDirty is reset to false
|
||||
cy.get(".t--widget-textwidget").should("contain", "false");
|
||||
});
|
||||
});
|
||||
|
|
@ -128,6 +128,28 @@ describe("RichTextEditor Widget Functionality", function() {
|
|||
);
|
||||
});
|
||||
|
||||
it("Check isDirty meta property", function() {
|
||||
cy.openPropertyPane("textwidget");
|
||||
cy.updateCodeInput(
|
||||
".t--property-control-text",
|
||||
`{{RichtextEditor.isDirty}}`,
|
||||
);
|
||||
// Change defaultText
|
||||
cy.openPropertyPane("richtexteditorwidget");
|
||||
cy.testJsontext("defaulttext", "a");
|
||||
// Check if isDirty has been changed into false
|
||||
cy.get(".t--widget-textwidget").should("contain", "false");
|
||||
// Interact with UI
|
||||
cy.setTinyMceContent("rte-6h8j08u7ea", "abc");
|
||||
// Check if isDirty is set to true
|
||||
cy.get(".t--widget-textwidget").should("contain", "true");
|
||||
// Change defaultText
|
||||
cy.openPropertyPane("richtexteditorwidget");
|
||||
cy.testJsontext("defaulttext", "b");
|
||||
// Check if isDirty is reset to false
|
||||
cy.get(".t--widget-textwidget").should("contain", "false");
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
cy.goToEditFromPublish();
|
||||
});
|
||||
|
|
|
|||
|
|
@ -0,0 +1,34 @@
|
|||
const explorer = require("../../../../locators/explorerlocators.json");
|
||||
const commonlocators = require("../../../../locators/commonlocators.json");
|
||||
const formWidgetsPage = require("../../../../locators/FormWidgets.json");
|
||||
const widgetLocators = require("../../../../locators/Widgets.json");
|
||||
|
||||
const widgetName = "selectwidget";
|
||||
|
||||
describe("Select widget", () => {
|
||||
it("1. Drag and drop Select/Text widgets", () => {
|
||||
cy.get(explorer.addWidget).click();
|
||||
cy.dragAndDropToCanvas(widgetName, { x: 300, y: 300 });
|
||||
cy.get(`.t--widget-${widgetName}`).should("exist");
|
||||
cy.dragAndDropToCanvas("textwidget", { x: 300, y: 500 });
|
||||
});
|
||||
it("2. Check isDirty meta property", () => {
|
||||
cy.openPropertyPane("textwidget");
|
||||
cy.updateCodeInput(".t--property-control-text", `{{Select1.isDirty}}`);
|
||||
// Check if initial value of isDirty is false
|
||||
cy.get(".t--widget-textwidget").should("contain", "false");
|
||||
// Interact with UI
|
||||
cy.get(formWidgetsPage.selectWidget)
|
||||
.find(widgetLocators.dropdownSingleSelect)
|
||||
.click({ force: true });
|
||||
cy.get(commonlocators.singleSelectWidgetMenuItem)
|
||||
.contains("Blue")
|
||||
.click({ force: true });
|
||||
// Check if isDirty is set to true
|
||||
cy.get(".t--widget-textwidget").should("contain", "true");
|
||||
// Change defaultOptionValue property
|
||||
cy.updateCodeInput(".t--property-control-defaultvalue", "RED");
|
||||
// Check if isDirty is reset to false
|
||||
cy.get(".t--widget-textwidget").should("contain", "false");
|
||||
});
|
||||
});
|
||||
|
|
@ -41,6 +41,35 @@ describe("Single Select Widget Functionality", function() {
|
|||
).should("be.visible");
|
||||
cy.get(publish.backToEditor).click();
|
||||
});
|
||||
|
||||
it("Check isDirty meta property", function() {
|
||||
cy.openPropertyPane("textwidget");
|
||||
cy.updateCodeInput(
|
||||
".t--property-control-text",
|
||||
`{{SingleSelectTree1.isDirty}}`,
|
||||
);
|
||||
// Change defaultText
|
||||
cy.openPropertyPane("singleselecttreewidget");
|
||||
cy.updateCodeInput(".t--property-control-defaultvalue", "GREEN");
|
||||
cy.closePropertyPane();
|
||||
// Check if isDirty is reset to false
|
||||
cy.get(".t--widget-textwidget").should("contain", "false");
|
||||
// Interact with UI
|
||||
cy.get(formWidgetsPage.treeSelectInput)
|
||||
.last()
|
||||
.click({ force: true });
|
||||
cy.get(formWidgetsPage.treeSelectFilterInput)
|
||||
.click()
|
||||
.type("light");
|
||||
cy.treeSelectDropdown("Light Blue");
|
||||
// Check if isDirty is set to true
|
||||
cy.get(".t--widget-textwidget").should("contain", "true");
|
||||
// Change defaultText
|
||||
cy.openPropertyPane("singleselecttreewidget");
|
||||
cy.updateCodeInput(".t--property-control-defaultvalue", "RED");
|
||||
// Check if isDirty is reset to false
|
||||
cy.get(".t--widget-textwidget").should("contain", "false");
|
||||
});
|
||||
});
|
||||
afterEach(() => {
|
||||
// put your clean up code if any
|
||||
|
|
|
|||
|
|
@ -100,4 +100,34 @@ describe("Switch Group Widget Functionality", function() {
|
|||
this.data.ModalName,
|
||||
);
|
||||
});
|
||||
|
||||
it("Check isDirty meta property", function() {
|
||||
cy.openPropertyPane("textwidget");
|
||||
cy.updateCodeInput(
|
||||
".t--property-control-text",
|
||||
`{{switchgrouptest.isDirty}}`,
|
||||
);
|
||||
// Change defaultSelectedValues
|
||||
cy.openPropertyPane("switchgroupwidget");
|
||||
cy.updateCodeInput(
|
||||
".t--property-control-defaultselectedvalues",
|
||||
`[\n"BLUE"\n]`,
|
||||
);
|
||||
// Check if isDirty is reset to false
|
||||
cy.get(".t--widget-textwidget").should("contain", "false");
|
||||
// Interact with UI
|
||||
cy.get(formWidgetsPage.labelSwitchGroup)
|
||||
.first()
|
||||
.click();
|
||||
// Check if isDirty is set to true
|
||||
cy.get(".t--widget-textwidget").should("contain", "true");
|
||||
// Change defaultSelectedValues
|
||||
cy.openPropertyPane("switchgroupwidget");
|
||||
cy.updateCodeInput(
|
||||
".t--property-control-defaultselectedvalues",
|
||||
`[\n"GREEN"\n]`,
|
||||
);
|
||||
// Check if isDirty is reset to false
|
||||
cy.get(".t--widget-textwidget").should("contain", "false");
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -86,6 +86,31 @@ describe("Switch Widget Functionality", function() {
|
|||
cy.get(publish.switchwidget + " " + ".bp3-align-left").should("not.exist");
|
||||
cy.get(publish.backToEditor).click();
|
||||
});
|
||||
|
||||
it("Check isDirty meta property", function() {
|
||||
cy.openPropertyPane("textwidget");
|
||||
cy.updateCodeInput(".t--property-control-text", `{{Toggler.isDirty}}`);
|
||||
// Change defaultSwitchState property
|
||||
cy.openPropertyPane("switchwidget");
|
||||
cy.get(".t--property-control-defaultselected label")
|
||||
.last()
|
||||
.click();
|
||||
// Check if isDirty is reset to false
|
||||
cy.get(".t--widget-textwidget").should("contain", "false");
|
||||
// Interact with UI
|
||||
cy.get(`${formWidgetsPage.switchWidget} label`)
|
||||
.first()
|
||||
.click();
|
||||
// Check if isDirty is set to true
|
||||
cy.get(".t--widget-textwidget").should("contain", "true");
|
||||
// Change defaultSwitchState property
|
||||
cy.openPropertyPane("switchwidget");
|
||||
cy.get(".t--property-control-defaultselected label")
|
||||
.last()
|
||||
.click();
|
||||
// Check if isDirty is reset to false
|
||||
cy.get(".t--widget-textwidget").should("contain", "false");
|
||||
});
|
||||
});
|
||||
afterEach(() => {
|
||||
// put your clean up code if any
|
||||
|
|
|
|||
|
|
@ -311,6 +311,7 @@ export const entityDefinitions: Record<string, unknown> = {
|
|||
"!url": "https://docs.appsmith.com/widget-reference/form",
|
||||
isVisible: isVisible,
|
||||
data: generateTypeDef(widget.data),
|
||||
hasChanges: "bool",
|
||||
}),
|
||||
FORM_BUTTON_WIDGET: {
|
||||
"!doc":
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ export interface AudioRecorderWidgetProps extends WidgetProps {
|
|||
onRecordingStart?: string;
|
||||
onRecordingComplete?: string;
|
||||
blobURL?: string;
|
||||
isDirty: boolean;
|
||||
}
|
||||
|
||||
class AudioRecorderWidget extends BaseWidget<
|
||||
|
|
@ -117,6 +118,7 @@ class AudioRecorderWidget extends BaseWidget<
|
|||
blobURL: undefined,
|
||||
dataURL: undefined,
|
||||
rawBinary: undefined,
|
||||
isDirty: false,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -125,6 +127,10 @@ class AudioRecorderWidget extends BaseWidget<
|
|||
}
|
||||
|
||||
handleRecordingStart = () => {
|
||||
if (!this.props.isDirty) {
|
||||
this.props.updateWidgetMetaProperty("isDirty", true);
|
||||
}
|
||||
|
||||
if (this.props.blobURL) {
|
||||
URL.revokeObjectURL(this.props.blobURL);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -906,7 +906,9 @@ function CameraComponent(props: CameraComponentProps) {
|
|||
}, [isAudioMuted, isVideoMuted]);
|
||||
|
||||
useEffect(() => {
|
||||
setIsReadyPlayerTimer(false);
|
||||
// Clean up
|
||||
resetMedia();
|
||||
|
||||
if (mode === CameraModeTypes.CAMERA) {
|
||||
setMediaCaptureStatus(MediaCaptureStatusTypes.IMAGE_DEFAULT);
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -160,10 +160,10 @@ class CameraWidget extends BaseWidget<CameraWidgetProps, WidgetState> {
|
|||
imageDataURL: undefined,
|
||||
imageRawBinary: undefined,
|
||||
mediaCaptureStatus: MediaCaptureStatusTypes.IMAGE_DEFAULT,
|
||||
timer: undefined,
|
||||
videoBlobURL: undefined,
|
||||
videoDataURL: undefined,
|
||||
videoRawBinary: undefined,
|
||||
isDirty: false,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -215,6 +215,11 @@ class CameraWidget extends BaseWidget<CameraWidgetProps, WidgetState> {
|
|||
this.props.updateWidgetMetaProperty("imageRawBinary", undefined);
|
||||
return;
|
||||
}
|
||||
// Set isDirty to true when an image is caputured
|
||||
if (!this.props.isDirty) {
|
||||
this.props.updateWidgetMetaProperty("isDirty", true);
|
||||
}
|
||||
|
||||
const base64Data = image.split(",")[1];
|
||||
const imageBlob = base64ToBlob(base64Data, "image/webp");
|
||||
const blobURL = URL.createObjectURL(imageBlob);
|
||||
|
|
@ -251,6 +256,10 @@ class CameraWidget extends BaseWidget<CameraWidgetProps, WidgetState> {
|
|||
};
|
||||
|
||||
handleRecordingStart = () => {
|
||||
if (!this.props.isDirty) {
|
||||
this.props.updateWidgetMetaProperty("isDirty", true);
|
||||
}
|
||||
|
||||
if (this.props.onRecordingStart) {
|
||||
super.executeAction({
|
||||
triggerPropertyName: "onRecordingStart",
|
||||
|
|
@ -319,6 +328,7 @@ export interface CameraWidgetProps extends WidgetProps {
|
|||
onRecordingStop?: string;
|
||||
onVideoSave?: string;
|
||||
videoBlobURL?: string;
|
||||
isDirty: boolean;
|
||||
}
|
||||
|
||||
export default CameraWidget;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import React from "react";
|
||||
import { compact } from "lodash";
|
||||
import { compact, xor } from "lodash";
|
||||
|
||||
import {
|
||||
ValidationResponse,
|
||||
|
|
@ -267,6 +267,7 @@ class CheckboxGroupWidget extends BaseWidget<
|
|||
static getMetaPropertiesMap(): Record<string, any> {
|
||||
return {
|
||||
selectedValues: undefined,
|
||||
isDirty: false,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -308,6 +309,14 @@ class CheckboxGroupWidget extends BaseWidget<
|
|||
},
|
||||
});
|
||||
}
|
||||
// Reset isDirty to false whenever defaultSelectedValues changes
|
||||
if (
|
||||
xor(this.props.defaultSelectedValues, prevProps.defaultSelectedValues)
|
||||
.length > 0 &&
|
||||
this.props.isDirty
|
||||
) {
|
||||
this.props.updateWidgetMetaProperty("isDirty", false);
|
||||
}
|
||||
}
|
||||
|
||||
getPageView() {
|
||||
|
|
@ -346,6 +355,11 @@ class CheckboxGroupWidget extends BaseWidget<
|
|||
);
|
||||
}
|
||||
|
||||
// Update isDirty to true whenever value changes
|
||||
if (!this.props.isDirty) {
|
||||
this.props.updateWidgetMetaProperty("isDirty", true);
|
||||
}
|
||||
|
||||
this.props.updateWidgetMetaProperty("selectedValues", selectedValues, {
|
||||
triggerPropertyName: "onSelectionChange",
|
||||
dynamicString: this.props.onSelectionChange,
|
||||
|
|
@ -370,6 +384,10 @@ class CheckboxGroupWidget extends BaseWidget<
|
|||
break;
|
||||
}
|
||||
|
||||
if (!this.props.isDirty) {
|
||||
this.props.updateWidgetMetaProperty("isDirty", true);
|
||||
}
|
||||
|
||||
this.props.updateWidgetMetaProperty("selectedValues", selectedValues, {
|
||||
triggerPropertyName: "onSelectionChange",
|
||||
dynamicString: this.props.onSelectionChange,
|
||||
|
|
|
|||
|
|
@ -127,9 +127,19 @@ class CheckboxWidget extends BaseWidget<CheckboxWidgetProps, WidgetState> {
|
|||
static getMetaPropertiesMap(): Record<string, any> {
|
||||
return {
|
||||
isChecked: undefined,
|
||||
isDirty: false,
|
||||
};
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps: CheckboxWidgetProps) {
|
||||
if (
|
||||
this.props.defaultCheckedState !== prevProps.defaultCheckedState &&
|
||||
this.props.isDirty
|
||||
) {
|
||||
this.props.updateWidgetMetaProperty("isDirty", false);
|
||||
}
|
||||
}
|
||||
|
||||
getPageView() {
|
||||
return (
|
||||
<CheckboxComponent
|
||||
|
|
@ -148,6 +158,10 @@ class CheckboxWidget extends BaseWidget<CheckboxWidgetProps, WidgetState> {
|
|||
}
|
||||
|
||||
onCheckChange = (isChecked: boolean) => {
|
||||
if (!this.props.isDirty) {
|
||||
this.props.updateWidgetMetaProperty("isDirty", true);
|
||||
}
|
||||
|
||||
this.props.updateWidgetMetaProperty("isChecked", isChecked, {
|
||||
triggerPropertyName: "onCheckChange",
|
||||
dynamicString: this.props.onCheckChange,
|
||||
|
|
|
|||
|
|
@ -204,6 +204,13 @@ class CurrencyInputWidget extends BaseInputWidget<
|
|||
) {
|
||||
this.formatText();
|
||||
}
|
||||
// If defaultText property has changed, reset isDirty to false
|
||||
if (
|
||||
this.props.defaultText !== prevProps.defaultText &&
|
||||
this.props.isDirty
|
||||
) {
|
||||
this.props.updateWidgetMetaProperty("isDirty", false);
|
||||
}
|
||||
}
|
||||
|
||||
formatText() {
|
||||
|
|
@ -303,6 +310,10 @@ class CurrencyInputWidget extends BaseInputWidget<
|
|||
this.props.decimals,
|
||||
String(value),
|
||||
);
|
||||
if (!this.props.isDirty) {
|
||||
this.props.updateWidgetMetaProperty("isDirty", true);
|
||||
}
|
||||
|
||||
this.props.updateWidgetMetaProperty("text", String(formattedValue), {
|
||||
triggerPropertyName: "onTextChanged",
|
||||
dynamicString: this.props.onTextChanged,
|
||||
|
|
|
|||
|
|
@ -230,9 +230,19 @@ class DatePickerWidget extends BaseWidget<DatePickerWidget2Props, WidgetState> {
|
|||
static getMetaPropertiesMap(): Record<string, any> {
|
||||
return {
|
||||
value: undefined,
|
||||
isDirty: false,
|
||||
};
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps: DatePickerWidget2Props): void {
|
||||
if (
|
||||
this.props.defaultDate !== prevProps.defaultDate &&
|
||||
this.props.isDirty
|
||||
) {
|
||||
this.props.updateWidgetMetaProperty("isDirty", false);
|
||||
}
|
||||
}
|
||||
|
||||
getPageView() {
|
||||
return (
|
||||
<DatePickerComponent
|
||||
|
|
@ -255,6 +265,10 @@ class DatePickerWidget extends BaseWidget<DatePickerWidget2Props, WidgetState> {
|
|||
}
|
||||
|
||||
onDateSelected = (selectedDate: string) => {
|
||||
if (!this.props.isDirty) {
|
||||
this.props.updateWidgetMetaProperty("isDirty", true);
|
||||
}
|
||||
|
||||
this.props.updateWidgetMetaProperty("value", selectedDate, {
|
||||
triggerPropertyName: "onDateSelected",
|
||||
dynamicString: this.props.onDateSelected,
|
||||
|
|
|
|||
|
|
@ -223,6 +223,7 @@ class FilePickerWidget extends BaseWidget<
|
|||
return {
|
||||
selectedFiles: [],
|
||||
uploadedFileData: {},
|
||||
isDirty: false,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -383,6 +384,10 @@ class FilePickerWidget extends BaseWidget<
|
|||
});
|
||||
|
||||
Promise.all(fileReaderPromises).then((files) => {
|
||||
if (!this.props.isDirty) {
|
||||
this.props.updateWidgetMetaProperty("isDirty", true);
|
||||
}
|
||||
|
||||
this.props.updateWidgetMetaProperty(
|
||||
"selectedFiles",
|
||||
dslFiles.concat(files),
|
||||
|
|
|
|||
|
|
@ -27,11 +27,45 @@ class FormWidget extends ContainerWidget {
|
|||
componentDidMount() {
|
||||
super.componentDidMount();
|
||||
this.updateFormData();
|
||||
|
||||
// Check if the form is dirty
|
||||
const hasChanges = this.checkFormValueChanges(
|
||||
get(this.props, "children[0]"),
|
||||
);
|
||||
|
||||
if (hasChanges !== this.props.hasChanges) {
|
||||
this.props.updateWidgetMetaProperty("hasChanges", hasChanges);
|
||||
}
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps: ContainerWidgetProps<any>) {
|
||||
super.componentDidUpdate(prevProps);
|
||||
this.updateFormData();
|
||||
// Check if the form is dirty
|
||||
const hasChanges = this.checkFormValueChanges(
|
||||
get(this.props, "children[0]"),
|
||||
);
|
||||
|
||||
if (hasChanges !== this.props.hasChanges) {
|
||||
this.props.updateWidgetMetaProperty("hasChanges", hasChanges);
|
||||
}
|
||||
}
|
||||
|
||||
checkFormValueChanges(
|
||||
containerWidget: ContainerWidgetProps<WidgetProps>,
|
||||
): boolean {
|
||||
const childWidgets = containerWidget.children || [];
|
||||
|
||||
const hasChanges = childWidgets.some((child) => child.isDirty);
|
||||
if (!hasChanges) {
|
||||
return childWidgets.some(
|
||||
(child) =>
|
||||
child.children &&
|
||||
this.checkFormValueChanges(get(child, "children[0]")),
|
||||
);
|
||||
}
|
||||
|
||||
return hasChanges;
|
||||
}
|
||||
|
||||
updateFormData() {
|
||||
|
|
@ -75,6 +109,7 @@ class FormWidget extends ContainerWidget {
|
|||
export interface FormWidgetProps extends ContainerComponentProps {
|
||||
name: string;
|
||||
data: Record<string, unknown>;
|
||||
hasChanges: boolean;
|
||||
}
|
||||
|
||||
export default FormWidget;
|
||||
|
|
|
|||
|
|
@ -379,6 +379,13 @@ class InputWidget extends BaseInputWidget<InputWidgetProps, WidgetState> {
|
|||
getParsedText(this.props.inputText, this.props.inputType),
|
||||
);
|
||||
}
|
||||
// If defaultText property has changed, reset isDirty to false
|
||||
if (
|
||||
this.props.defaultText !== prevProps.defaultText &&
|
||||
this.props.isDirty
|
||||
) {
|
||||
this.props.updateWidgetMetaProperty("isDirty", false);
|
||||
}
|
||||
};
|
||||
|
||||
onValueChange = (value: string) => {
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import React, { ReactNode } from "react";
|
|||
import BaseWidget, { WidgetProps, WidgetState } from "widgets/BaseWidget";
|
||||
import { TextSize, WidgetType } from "constants/WidgetConstants";
|
||||
import { EventType } from "constants/AppsmithActionConstants/ActionConstants";
|
||||
import { isArray, findIndex } from "lodash";
|
||||
import { isArray, findIndex, xor } from "lodash";
|
||||
import {
|
||||
ValidationResponse,
|
||||
ValidationTypes,
|
||||
|
|
@ -354,8 +354,20 @@ class MultiSelectTreeWidget extends BaseWidget<
|
|||
return {
|
||||
selectedOptionValueArr: undefined,
|
||||
selectedLabel: [],
|
||||
isDirty: false,
|
||||
};
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps: MultiSelectTreeWidgetProps): void {
|
||||
if (
|
||||
xor(this.props.defaultOptionValue, prevProps.defaultOptionValue).length >
|
||||
0 &&
|
||||
this.props.isDirty
|
||||
) {
|
||||
this.props.updateWidgetMetaProperty("isDirty", false);
|
||||
}
|
||||
}
|
||||
|
||||
getPageView() {
|
||||
const options =
|
||||
isArray(this.props.options) &&
|
||||
|
|
@ -407,6 +419,9 @@ class MultiSelectTreeWidget extends BaseWidget<
|
|||
}
|
||||
|
||||
onOptionChange = (value?: DefaultValueType, labelList?: ReactNode[]) => {
|
||||
if (!this.props.isDirty) {
|
||||
this.props.updateWidgetMetaProperty("isDirty", true);
|
||||
}
|
||||
this.props.updateWidgetMetaProperty("selectedOptionValueArr", value);
|
||||
this.props.updateWidgetMetaProperty("selectedLabel", labelList, {
|
||||
triggerPropertyName: "onOptionChange",
|
||||
|
|
@ -472,7 +487,7 @@ export interface MultiSelectTreeWidgetProps extends WidgetProps {
|
|||
labelTextColor?: string;
|
||||
labelTextSize?: TextSize;
|
||||
labelStyle?: string;
|
||||
isDirty?: boolean;
|
||||
isDirty: boolean;
|
||||
}
|
||||
|
||||
export default MultiSelectTreeWidget;
|
||||
|
|
|
|||
|
|
@ -2,7 +2,15 @@ import React from "react";
|
|||
import BaseWidget, { WidgetProps, WidgetState } from "widgets/BaseWidget";
|
||||
import { WidgetType } from "constants/WidgetConstants";
|
||||
import { EventType } from "constants/AppsmithActionConstants/ActionConstants";
|
||||
import { isArray, isString, isNumber, LoDashStatic } from "lodash";
|
||||
import {
|
||||
isArray,
|
||||
isEqual,
|
||||
isFinite,
|
||||
isString,
|
||||
isNumber,
|
||||
LoDashStatic,
|
||||
xorWith,
|
||||
} from "lodash";
|
||||
import {
|
||||
ValidationResponse,
|
||||
ValidationTypes,
|
||||
|
|
@ -208,7 +216,7 @@ class MultiSelectWidget extends BaseWidget<
|
|||
fn: defaultOptionValueValidation,
|
||||
expected: {
|
||||
type: "Array of values",
|
||||
example: `['option1', 'option2'] | [{ "label": "label1", "value": "value1" }]`,
|
||||
example: ` "option1, option2" | ['option1', 'option2'] | [{ "label": "label1", "value": "value1" }]`,
|
||||
autocompleteDataType: AutocompleteDataType.ARRAY,
|
||||
},
|
||||
},
|
||||
|
|
@ -431,9 +439,38 @@ class MultiSelectWidget extends BaseWidget<
|
|||
return {
|
||||
selectedOptions: undefined,
|
||||
filterText: "",
|
||||
isDirty: false,
|
||||
};
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps: MultiSelectWidgetProps): void {
|
||||
// Check if defaultOptionValue is string
|
||||
let isStringArray = false;
|
||||
if (
|
||||
this.props.defaultOptionValue.some(
|
||||
(value: any) => isString(value) || isFinite(value),
|
||||
)
|
||||
) {
|
||||
isStringArray = true;
|
||||
}
|
||||
|
||||
const hasChanges = isStringArray
|
||||
? xorWith(
|
||||
this.props.defaultOptionValue as string[],
|
||||
prevProps.defaultOptionValue as string[],
|
||||
isEqual,
|
||||
).length > 0
|
||||
: xorWith(
|
||||
this.props.defaultOptionValue as OptionValue[],
|
||||
prevProps.defaultOptionValue as OptionValue[],
|
||||
isEqual,
|
||||
).length > 0;
|
||||
|
||||
if (hasChanges && this.props.isDirty) {
|
||||
this.props.updateWidgetMetaProperty("isDirty", false);
|
||||
}
|
||||
}
|
||||
|
||||
getPageView() {
|
||||
const options = isArray(this.props.options) ? this.props.options : [];
|
||||
const dropDownWidth = MinimumPopupRows * this.props.parentColumnSpace;
|
||||
|
|
@ -527,7 +564,7 @@ export interface MultiSelectWidgetProps extends WidgetProps {
|
|||
options?: DropdownOption[];
|
||||
onOptionChange: string;
|
||||
onFilterChange: string;
|
||||
defaultOptionValue: string | string[] | OptionValue[];
|
||||
defaultOptionValue: string[] | OptionValue[];
|
||||
isRequired: boolean;
|
||||
isLoading: boolean;
|
||||
selectedOptions: LabelValueType[];
|
||||
|
|
|
|||
|
|
@ -206,6 +206,13 @@ class PhoneInputWidget extends BaseInputWidget<
|
|||
);
|
||||
this.props.updateWidgetMetaProperty("text", formattedValue);
|
||||
}
|
||||
|
||||
// If defaultText property has changed, reset isDirty to false
|
||||
if (this.props.defaultText !== prevProps.defaultText) {
|
||||
if (this.props.isDirty) {
|
||||
this.props.updateWidgetMetaProperty("isDirty", false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onISDCodeChange = (dialCode?: string) => {
|
||||
|
|
|
|||
|
|
@ -272,9 +272,19 @@ class RadioGroupWidget extends BaseWidget<RadioGroupWidgetProps, WidgetState> {
|
|||
static getMetaPropertiesMap(): Record<string, any> {
|
||||
return {
|
||||
selectedOptionValue: undefined,
|
||||
isDirty: false,
|
||||
};
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps: RadioGroupWidgetProps): void {
|
||||
if (
|
||||
this.props.defaultOptionValue !== prevProps.defaultOptionValue &&
|
||||
this.props.isDirty
|
||||
) {
|
||||
this.props.updateWidgetMetaProperty("isDirty", false);
|
||||
}
|
||||
}
|
||||
|
||||
getPageView() {
|
||||
return (
|
||||
<RadioGroupComponent
|
||||
|
|
@ -297,6 +307,11 @@ class RadioGroupWidget extends BaseWidget<RadioGroupWidgetProps, WidgetState> {
|
|||
} else {
|
||||
newVal = updatedValue;
|
||||
}
|
||||
// Set isDirty to true when the selection changes
|
||||
if (!this.props.isDirty) {
|
||||
this.props.updateWidgetMetaProperty("isDirty", true);
|
||||
}
|
||||
|
||||
this.props.updateWidgetMetaProperty("selectedOptionValue", newVal, {
|
||||
triggerPropertyName: "onSelectionChange",
|
||||
dynamicString: this.props.onSelectionChange,
|
||||
|
|
@ -318,6 +333,7 @@ export interface RadioGroupWidgetProps extends WidgetProps {
|
|||
onSelectionChange: string;
|
||||
defaultOptionValue: string;
|
||||
isRequired?: boolean;
|
||||
isDirty: boolean;
|
||||
}
|
||||
|
||||
export default RadioGroupWidget;
|
||||
|
|
|
|||
|
|
@ -130,6 +130,8 @@ class RichTextEditorWidget extends BaseWidget<
|
|||
static getMetaPropertiesMap(): Record<string, any> {
|
||||
return {
|
||||
text: undefined,
|
||||
shouldReset: false,
|
||||
isDirty: false,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -146,7 +148,30 @@ class RichTextEditorWidget extends BaseWidget<
|
|||
};
|
||||
}
|
||||
|
||||
componentDidMount(): void {
|
||||
if (this.props.defaultText) {
|
||||
this.props.updateWidgetMetaProperty("shouldReset", true);
|
||||
}
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps: RichTextEditorWidgetProps): void {
|
||||
if (this.props.defaultText !== prevProps.defaultText) {
|
||||
if (this.props.isDirty) {
|
||||
this.props.updateWidgetMetaProperty("isDirty", false);
|
||||
}
|
||||
if (this.props.defaultText) {
|
||||
this.props.updateWidgetMetaProperty("shouldReset", true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onValueChange = (text: string) => {
|
||||
if (this.props.shouldReset) {
|
||||
this.props.updateWidgetMetaProperty("shouldReset", false);
|
||||
} else if (!this.props.isDirty) {
|
||||
this.props.updateWidgetMetaProperty("isDirty", true);
|
||||
}
|
||||
|
||||
this.props.updateWidgetMetaProperty("text", text, {
|
||||
triggerPropertyName: "onTextChange",
|
||||
dynamicString: this.props.onTextChange,
|
||||
|
|
@ -196,6 +221,7 @@ export interface RichTextEditorWidgetProps extends WidgetProps {
|
|||
isVisible?: boolean;
|
||||
isRequired?: boolean;
|
||||
isToolbarHidden?: boolean;
|
||||
isDirty: boolean;
|
||||
}
|
||||
|
||||
export default RichTextEditorWidget;
|
||||
|
|
|
|||
|
|
@ -11,7 +11,14 @@ import {
|
|||
import { EvaluationSubstitutionType } from "entities/DataTree/dataTreeFactory";
|
||||
import { MinimumPopupRows, GRID_DENSITY_MIGRATION_V1 } from "widgets/constants";
|
||||
import { AutocompleteDataType } from "utils/autocomplete/TernServer";
|
||||
import { findIndex, isArray, isNumber, isString, LoDashStatic } from "lodash";
|
||||
import {
|
||||
findIndex,
|
||||
isArray,
|
||||
isEqual,
|
||||
isNumber,
|
||||
isString,
|
||||
LoDashStatic,
|
||||
} from "lodash";
|
||||
|
||||
export function defaultOptionValueValidation(
|
||||
value: unknown,
|
||||
|
|
@ -335,6 +342,7 @@ class SelectWidget extends BaseWidget<SelectWidgetProps, WidgetState> {
|
|||
value: undefined,
|
||||
label: undefined,
|
||||
filterText: "",
|
||||
isDirty: false,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -351,6 +359,16 @@ class SelectWidget extends BaseWidget<SelectWidgetProps, WidgetState> {
|
|||
this.changeSelectedOption();
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps: SelectWidgetProps): void {
|
||||
// Reset isDirty to false if defaultOptionValue changes
|
||||
if (
|
||||
!isEqual(this.props.defaultOptionValue, prevProps.defaultOptionValue) &&
|
||||
this.props.isDirty
|
||||
) {
|
||||
this.props.updateWidgetMetaProperty("isDirty", false);
|
||||
}
|
||||
}
|
||||
|
||||
isStringOrNumber = (value: any): value is string | number =>
|
||||
isString(value) || isNumber(value);
|
||||
|
||||
|
|
@ -408,6 +426,10 @@ class SelectWidget extends BaseWidget<SelectWidgetProps, WidgetState> {
|
|||
isChanged = !(this.props.selectedOptionValue === selectedOption.value);
|
||||
}
|
||||
if (isChanged) {
|
||||
if (!this.props.isDirty) {
|
||||
this.props.updateWidgetMetaProperty("isDirty", true);
|
||||
}
|
||||
|
||||
this.props.updateWidgetMetaProperty("label", selectedOption.label ?? "");
|
||||
|
||||
this.props.updateWidgetMetaProperty("value", selectedOption.value ?? "", {
|
||||
|
|
|
|||
|
|
@ -319,9 +319,19 @@ class SingleSelectTreeWidget extends BaseWidget<
|
|||
selectedOption: undefined,
|
||||
selectedOptionValueArr: undefined,
|
||||
selectedLabel: [],
|
||||
isDirty: false,
|
||||
};
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps: SingleSelectTreeWidgetProps): void {
|
||||
if (
|
||||
this.props.defaultOptionValue !== prevProps.defaultOptionValue &&
|
||||
this.props.isDirty
|
||||
) {
|
||||
this.props.updateWidgetMetaProperty("isDirty", false);
|
||||
}
|
||||
}
|
||||
|
||||
getPageView() {
|
||||
const options =
|
||||
isArray(this.props.options) &&
|
||||
|
|
@ -372,6 +382,10 @@ class SingleSelectTreeWidget extends BaseWidget<
|
|||
}
|
||||
|
||||
onOptionChange = (value?: DefaultValueType, labelList?: ReactNode[]) => {
|
||||
if (!this.props.isDirty) {
|
||||
this.props.updateWidgetMetaProperty("isDirty", true);
|
||||
}
|
||||
|
||||
this.props.updateWidgetMetaProperty("selectedOption", value);
|
||||
this.props.updateWidgetMetaProperty("selectedLabel", labelList, {
|
||||
triggerPropertyName: "onOptionChange",
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import React from "react";
|
||||
import { Alignment } from "@blueprintjs/core";
|
||||
import { xor } from "lodash";
|
||||
|
||||
import BaseWidget, { WidgetProps, WidgetState } from "widgets/BaseWidget";
|
||||
import { DerivedPropertiesMap } from "utils/WidgetFactory";
|
||||
|
|
@ -178,6 +179,7 @@ class SwitchGroupWidget extends BaseWidget<
|
|||
static getMetaPropertiesMap(): Record<string, any> {
|
||||
return {
|
||||
selectedValuesArray: undefined,
|
||||
isDirty: false,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -196,6 +198,22 @@ class SwitchGroupWidget extends BaseWidget<
|
|||
return "SWITCH_GROUP_WIDGET";
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps: SwitchGroupWidgetProps): void {
|
||||
if (
|
||||
xor(this.props.defaultSelectedValues, prevProps.defaultSelectedValues)
|
||||
.length > 0
|
||||
) {
|
||||
if (this.props.isDirty) {
|
||||
this.props.updateWidgetMetaProperty("isDirty", false);
|
||||
}
|
||||
|
||||
this.props.updateWidgetMetaProperty(
|
||||
"selectedValuesArray",
|
||||
this.props.defaultSelectedValues,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
getPageView() {
|
||||
const {
|
||||
alignment,
|
||||
|
|
@ -205,7 +223,7 @@ class SwitchGroupWidget extends BaseWidget<
|
|||
isValid,
|
||||
options,
|
||||
parentRowSpace,
|
||||
selectedValues,
|
||||
selectedValuesArray,
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
|
|
@ -217,7 +235,7 @@ class SwitchGroupWidget extends BaseWidget<
|
|||
options={options}
|
||||
required={isRequired}
|
||||
rowSpace={parentRowSpace}
|
||||
selected={selectedValues}
|
||||
selected={selectedValuesArray}
|
||||
valid={isValid}
|
||||
/>
|
||||
);
|
||||
|
|
@ -235,6 +253,10 @@ class SwitchGroupWidget extends BaseWidget<
|
|||
);
|
||||
}
|
||||
|
||||
if (!this.props.isDirty) {
|
||||
this.props.updateWidgetMetaProperty("isDirty", true);
|
||||
}
|
||||
|
||||
this.props.updateWidgetMetaProperty(
|
||||
"selectedValuesArray",
|
||||
selectedValuesArray,
|
||||
|
|
@ -253,6 +275,7 @@ class SwitchGroupWidget extends BaseWidget<
|
|||
export interface SwitchGroupWidgetProps extends WidgetProps {
|
||||
options: OptionProps[];
|
||||
defaultSelectedValues: string[];
|
||||
selectedValuesArray: string[];
|
||||
isInline: boolean;
|
||||
isRequired?: boolean;
|
||||
isValid?: boolean;
|
||||
|
|
|
|||
|
|
@ -131,6 +131,7 @@ class SwitchWidget extends BaseWidget<SwitchWidgetProps, WidgetState> {
|
|||
static getMetaPropertiesMap(): Record<string, any> {
|
||||
return {
|
||||
isSwitchedOn: undefined,
|
||||
isDirty: false,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -140,7 +141,20 @@ class SwitchWidget extends BaseWidget<SwitchWidgetProps, WidgetState> {
|
|||
};
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps: SwitchWidgetProps): void {
|
||||
if (
|
||||
this.props.defaultSwitchState !== prevProps.defaultSwitchState &&
|
||||
this.props.isDirty
|
||||
) {
|
||||
this.props.updateWidgetMetaProperty("isDirty", false);
|
||||
}
|
||||
}
|
||||
|
||||
onChange = (isSwitchedOn: boolean) => {
|
||||
if (!this.props.isDirty) {
|
||||
this.props.updateWidgetMetaProperty("isDirty", true);
|
||||
}
|
||||
|
||||
this.props.updateWidgetMetaProperty("isSwitchedOn", isSwitchedOn, {
|
||||
triggerPropertyName: "onChange",
|
||||
dynamicString: this.props.onChange,
|
||||
|
|
@ -156,6 +170,7 @@ export interface SwitchWidgetProps extends WidgetProps {
|
|||
defaultSwitchState: boolean;
|
||||
alignWidget: AlignWidget;
|
||||
label: string;
|
||||
isDirty: boolean;
|
||||
}
|
||||
|
||||
export default SwitchWidget;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user