Merge branch 'release' of https://github.com/appsmithorg/appsmith into fix/filepicker-clear-files
This commit is contained in:
commit
eea0472a72
43
.github/ISSUE_TEMPLATE/---epic.md
vendored
43
.github/ISSUE_TEMPLATE/---epic.md
vendored
|
|
@ -6,24 +6,43 @@ labels: Epic, Product Note
|
|||
assignees: Nikhil-Nandagopal
|
||||
---
|
||||
|
||||
## Problem statement
|
||||
|
||||
Why is this needed?
|
||||
What does it hope to achieve?
|
||||
# Objective
|
||||
Here you fill in the objective of the feature/product that you are writing about.
|
||||
|
||||
## Related issues
|
||||
|
||||
[ ] #issue1
|
||||
|
||||
## Success criteria
|
||||
# Success Metrics
|
||||
List of all metrics you are tracking and the desired goal.
|
||||
| Goal | Metric |
|
||||
| ------------- | ------------- |
|
||||
| e.g. Simplify user experience | Customer satisfaction score increases |
|
||||
| e.g. Simplify onboarding flow | Decrease churn rate down to 30% |
|
||||
|
||||
How will we know the project succeeded?
|
||||
# Assumptions
|
||||
List any assumptions that you have about your users, technical constraints, or business goals (e.g., Most users will access this feature from tablet).
|
||||
|
||||
## User story
|
||||
- Assumption 1
|
||||
- Assumption 2
|
||||
- Assumption 3
|
||||
|
||||
How does a user use this feature? How does it relate to the problem?
|
||||
# Requirements
|
||||
| Requirement | User Story | Importance | Notes |
|
||||
| ------------- | ------------- | ------------- | ------------- |
|
||||
| e.g. Must be mobile responsive | e.g. as a user, I want to be able to access the platform via mobile phone | High, Low or Medium | Content Cell |
|
||||
| e.g. The user should be able to leave a comment | e.g as a user, I want to be able to communicate with the other members on the canvas | High, Low or Medium | Content Cell |
|
||||
|
||||
## Details
|
||||
# Out of Scope
|
||||
List the things that are out of cope or might be revisited after the first release.
|
||||
- Item 1
|
||||
- Item 2
|
||||
- Item 3
|
||||
|
||||
What are the specifications of the implementation?
|
||||
Product notes, designs etc.
|
||||
# Developer Handoff Document in Figma
|
||||
Link to the developer Handoff Document:
|
||||
|
||||
# Questions
|
||||
| Question | Answer | Date Answered |
|
||||
| ------------- | ------------- | ------------- |
|
||||
| e.g. How might we ensure that the comments section doesn't cover the canvas | Content Cell | Content Cell |
|
||||
| Content Cell | Content Cell | Content Cell |
|
||||
|
|
|
|||
2
.github/workflows/client-build.yml
vendored
2
.github/workflows/client-build.yml
vendored
|
|
@ -103,8 +103,6 @@ jobs:
|
|||
with:
|
||||
fullCoverageDiff: false
|
||||
runCommand: cd app/client && REACT_APP_ENVIRONMENT=${{steps.vars.outputs.REACT_APP_ENVIRONMENT}} yarn run test:unit
|
||||
# percentage of drop in coverage accepted
|
||||
delta: 2
|
||||
|
||||
# We burn React environment & the Segment analytics key into the build itself.
|
||||
# This is to ensure that we don't need to configure it in each installation
|
||||
|
|
|
|||
2
.github/workflows/external-client-test.yml
vendored
2
.github/workflows/external-client-test.yml
vendored
|
|
@ -38,7 +38,7 @@ jobs:
|
|||
- name: Set up JDK 1.11
|
||||
uses: actions/setup-java@v1
|
||||
with:
|
||||
java-version: 1.11
|
||||
java-version: "11.0.10"
|
||||
|
||||
# Retrieve maven dependencies from cache. After a successful run, these dependencies are cached again
|
||||
- name: Cache maven dependencies
|
||||
|
|
|
|||
2
.github/workflows/server.yml
vendored
2
.github/workflows/server.yml
vendored
|
|
@ -50,7 +50,7 @@ jobs:
|
|||
- name: Set up JDK 1.11
|
||||
uses: actions/setup-java@v1
|
||||
with:
|
||||
java-version: 1.11
|
||||
java-version: "11.0.10"
|
||||
|
||||
# Retrieve maven dependencies from cache. After a successful run, these dependencies are cached again
|
||||
- name: Cache maven dependencies
|
||||
|
|
|
|||
16
README.md
16
README.md
|
|
@ -6,7 +6,7 @@
|
|||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://app.appsmith.com/signup"><strong>Try Online Sandbox</strong></a>
|
||||
<a href="https://app.appsmith.com/signup?utm_source=github&utm_medium=social&utm_content=website&utm_campaign=null&utm_term=website"><strong>Try Online Sandbox</strong></a>
|
||||
</p>
|
||||
<p align="center">
|
||||
<a href="https://docs.appsmith.com/">Documentation</a>
|
||||
|
|
@ -63,7 +63,7 @@ But if you’d rather check out some real applications that can be built with Ap
|
|||
|
||||
The following steps introduce you to building a simple user-list dashboard on Appsmith.
|
||||
|
||||
1. [Sign up on Appsmith Cloud](https://bit.ly/appsmith-signup-github) or [Deploy Appsmith](https://docs.appsmith.com/setup).
|
||||
1. [Sign up on Appsmith Cloud](https://app.appsmith.com/signup?utm_source=github&utm_medium=social&utm_content=website&utm_campaign=null&utm_term=website) or [Deploy Appsmith](https://docs.appsmith.com/setup).
|
||||
2. Create a new app within the organization that has already been created for you.
|
||||
3. Click on the `+` icon next to the `Queries` section to add a new query in the mock database
|
||||
1. Name the query `usersQuery`.
|
||||
|
|
@ -79,12 +79,12 @@ Connect your own data to build apps for your team. [Read more here.](https://doc
|
|||
## 📚 Tutorials
|
||||
|
||||
1. [Building an Admin Panel on MongoDB using Appsmith](https://blog.appsmith.com/building-an-admin-panel-with-mongodb-using-appsmith) ([Video](https://www.youtube.com/watch?v=tisUaIgI86k))
|
||||
2. [Building a customer support dashboard in Appsmith](https://www.youtube.com/watch?v=-O_6OLREEzo&t=272s)
|
||||
3. [Running CI/CD jobs manually using Appsmith](https://blog.appsmith.com/how-to-run-manual-jobs-in-gitlab-cicd) ([Video](https://www.youtube.com/watch?v=CYdeJcD4I8A))
|
||||
4. [Building a calendly clone in Appsmith](https://blog.appsmith.com/how-to-build-a-calendly-clone-in-30-minutes)
|
||||
5. [Building Internal Tools with Appsmith](https://youtu.be/eYYYfuW-kEE) `Community`
|
||||
6. [Building an Issue Tracker with Appsmith](https://dev.to/pjmantoss/how-to-build-an-issue-tracker-with-appsmith-204e) `Community`
|
||||
|
||||
2. [Building a Customer Support Dashboard in Appsmith](https://www.youtube.com/watch?v=-O_6OLREEzo&t=272s)
|
||||
3. [Building a Store Catalogue Management System using Appsmith and GraphQL](https://blog.appsmith.com/building-a-store-catalogue-management-system-using-appsmith-and-graphql)
|
||||
4. [Running CI/CD Jobs Manually using Appsmith](https://blog.appsmith.com/how-to-run-manual-jobs-in-gitlab-cicd) ([Video](https://www.youtube.com/watch?v=CYdeJcD4I8A))
|
||||
5. [Building a Calendly Clone in Appsmith](https://blog.appsmith.com/how-to-build-a-calendly-clone-in-30-minutes)
|
||||
6. [Building Internal Tools with Appsmith](https://youtu.be/eYYYfuW-kEE) `Community`
|
||||
7. [Building an Issue Tracker with Appsmith](https://dev.to/pjmantoss/how-to-build-an-issue-tracker-with-appsmith-204e) `Community`
|
||||
|
||||
## 📕 Support & Troubleshooting
|
||||
|
||||
|
|
|
|||
|
|
@ -102,6 +102,7 @@
|
|||
"AlertModalName": "Alert_Modal",
|
||||
"FormModalName": "Form_Modal",
|
||||
"TextLabelValue": "Test Text Label",
|
||||
"TextLabelValueScrollable": "Test Text Label to check scroll feature",
|
||||
"TextName": "TestTextBox",
|
||||
"TextLabel": "Paragraph",
|
||||
"TextBody": "Heading 2",
|
||||
|
|
|
|||
7
app/client/cypress/fixtures/resetPassword.json
Normal file
7
app/client/cypress/fixtures/resetPassword.json
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"responseMeta": {
|
||||
"status": 200,
|
||||
"success": true
|
||||
},
|
||||
"data": true
|
||||
}
|
||||
45
app/client/cypress/fixtures/textDsl.json
Normal file
45
app/client/cypress/fixtures/textDsl.json
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
{
|
||||
"dsl": {
|
||||
"widgetName": "MainContainer",
|
||||
"backgroundColor": "none",
|
||||
"rightColumn": 966,
|
||||
"snapColumns": 16,
|
||||
"detachFromLayout": true,
|
||||
"widgetId": "0",
|
||||
"topRow": 0,
|
||||
"bottomRow": 240,
|
||||
"containerStyle": "none",
|
||||
"snapRows": 33,
|
||||
"parentRowSpace": 1,
|
||||
"type": "CANVAS_WIDGET",
|
||||
"canExtend": true,
|
||||
"version": 16,
|
||||
"minHeight": 280,
|
||||
"parentColumnSpace": 1,
|
||||
"dynamicTriggerPathList": [],
|
||||
"dynamicBindingPathList": [],
|
||||
"leftColumn": 0,
|
||||
"children": [
|
||||
{
|
||||
"isVisible": true,
|
||||
"text": "Label",
|
||||
"fontSize": "PARAGRAPH",
|
||||
"fontStyle": "BOLD",
|
||||
"textAlign": "LEFT",
|
||||
"textColor": "#231F20",
|
||||
"widgetName": "Text1",
|
||||
"version": 1,
|
||||
"type": "TEXT_WIDGET",
|
||||
"isLoading": false,
|
||||
"parentColumnSpace": 57.875,
|
||||
"parentRowSpace": 40,
|
||||
"leftColumn": 4,
|
||||
"rightColumn": 8,
|
||||
"topRow": 1,
|
||||
"bottomRow": 2,
|
||||
"parentId": "0",
|
||||
"widgetId": "266vj9u1mr"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
@ -126,6 +126,14 @@ describe("Table Widget property pane feature validation", function() {
|
|||
cy.get(commonlocators.editPropCrossButton).click();
|
||||
});
|
||||
|
||||
it("Edit column name and test for table header changes", function() {
|
||||
cy.openPropertyPane("tablewidget");
|
||||
cy.editColumn("email");
|
||||
cy.editColName("Email Address");
|
||||
cy.get(".draggable-header:contains('Email Address')").should("be.visible");
|
||||
cy.get(commonlocators.editPropCrossButton).click();
|
||||
});
|
||||
|
||||
it("Test to validate text color and text background", function() {
|
||||
cy.openPropertyPane("tablewidget");
|
||||
cy.get(widgetsPage.textColor)
|
||||
|
|
|
|||
|
|
@ -10,21 +10,8 @@ describe("Table Widget property pane feature validation", function() {
|
|||
cy.addDsl(dsl);
|
||||
});
|
||||
|
||||
it("Check collapse section feature in property pane", function() {
|
||||
cy.openPropertyPane("tablewidget");
|
||||
//check open and collapse
|
||||
cy.get(commonlocators.collapsesection)
|
||||
.first()
|
||||
.should("be.visible")
|
||||
.click();
|
||||
cy.assertControlVisibility("tabledata");
|
||||
});
|
||||
|
||||
it("Check open section and column data in property pane", function() {
|
||||
cy.get(commonlocators.collapsesection)
|
||||
.scrollIntoView()
|
||||
.first()
|
||||
.click();
|
||||
cy.openPropertyPane("tablewidget");
|
||||
cy.tableColumnDataValidation("id");
|
||||
cy.tableColumnDataValidation("email");
|
||||
cy.tableColumnDataValidation("userName");
|
||||
|
|
|
|||
|
|
@ -0,0 +1,109 @@
|
|||
const commonlocators = require("../../../../locators/commonlocators.json");
|
||||
const widgetsPage = require("../../../../locators/Widgets.json");
|
||||
const publishPage = require("../../../../locators/publishWidgetspage.json");
|
||||
const dsl = require("../../../../fixtures/textDsl.json");
|
||||
const pages = require("../../../../locators/Pages.json");
|
||||
|
||||
describe("Text Widget color/font/alignment Functionality", function() {
|
||||
before(() => {
|
||||
cy.addDsl(dsl);
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
cy.openPropertyPane("textwidget");
|
||||
});
|
||||
|
||||
it("Text-TextStyle Heading, Text Name Validation", function() {
|
||||
//changing the Text Name and verifying
|
||||
cy.widgetText(
|
||||
this.data.TextName,
|
||||
widgetsPage.textWidget,
|
||||
widgetsPage.textWidget + " " + commonlocators.widgetNameTag,
|
||||
);
|
||||
|
||||
//Changing the text label
|
||||
cy.testCodeMirror(this.data.TextLabelValueScrollable);
|
||||
|
||||
cy.ChangeTextStyle(
|
||||
this.data.TextHeading,
|
||||
commonlocators.headingTextStyle,
|
||||
this.data.TextLabelValueScrollable,
|
||||
);
|
||||
cy.wait("@updateLayout");
|
||||
cy.PublishtheApp();
|
||||
cy.get(commonlocators.headingTextStyle)
|
||||
.should("have.text", this.data.TextLabelValueScrollable)
|
||||
.should("have.css", "font-size", "24px");
|
||||
cy.get(publishPage.backToEditor).click({ force: true });
|
||||
});
|
||||
|
||||
it("Test to validate text format", function() {
|
||||
//Changing the Text Style's and validating
|
||||
cy.get(widgetsPage.italics).click({ force: true });
|
||||
cy.readTextDataValidateCSS("font-style", "italic");
|
||||
cy.get(widgetsPage.bold).click({ force: true });
|
||||
cy.readTextDataValidateCSS("font-weight", "400");
|
||||
cy.get(widgetsPage.bold).click({ force: true });
|
||||
cy.readTextDataValidateCSS("font-weight", "700");
|
||||
cy.get(widgetsPage.italics).click({ force: true });
|
||||
cy.readTextDataValidateCSS("font-style", "normal");
|
||||
cy.closePropertyPane();
|
||||
});
|
||||
|
||||
it("Test to validate color changes in text and background", function() {
|
||||
//Changing the Text Style's and validating
|
||||
cy.get(widgetsPage.textColor)
|
||||
.first()
|
||||
.click({ force: true });
|
||||
cy.xpath(widgetsPage.greenColor).click();
|
||||
// eslint-disable-next-line cypress/no-unnecessary-waiting
|
||||
cy.wait(500);
|
||||
cy.wait("@updateLayout");
|
||||
cy.readTextDataValidateCSS("color", "rgb(3, 179, 101)");
|
||||
cy.get(widgetsPage.textColor)
|
||||
.clear({ force: true })
|
||||
.type("purple", { force: true });
|
||||
cy.wait("@updateLayout");
|
||||
cy.readTextDataValidateCSS("color", "rgb(128, 0, 128)");
|
||||
cy.get(widgetsPage.backgroundColor)
|
||||
.first()
|
||||
.click({ force: true });
|
||||
// eslint-disable-next-line cypress/no-unnecessary-waiting
|
||||
cy.wait(500);
|
||||
cy.xpath(widgetsPage.greenColor)
|
||||
.first()
|
||||
.click();
|
||||
// eslint-disable-next-line cypress/no-unnecessary-waiting
|
||||
cy.wait(500);
|
||||
cy.wait("@updateLayout");
|
||||
cy.PublishtheApp();
|
||||
cy.get(publishPage.backToEditor).click({ force: true });
|
||||
});
|
||||
|
||||
it("Test to validate text alignment", function() {
|
||||
cy.get(widgetsPage.centerAlign)
|
||||
.first()
|
||||
.click({ force: true });
|
||||
cy.readTextDataValidateCSS("text-align", "center");
|
||||
cy.get(widgetsPage.rightAlign)
|
||||
.first()
|
||||
.click({ force: true });
|
||||
cy.readTextDataValidateCSS("text-align", "right");
|
||||
cy.get(widgetsPage.leftAlign)
|
||||
.first()
|
||||
.click({ force: true });
|
||||
cy.readTextDataValidateCSS("text-align", "left");
|
||||
cy.closePropertyPane();
|
||||
});
|
||||
|
||||
it("Test to validate enable scroll feature", function() {
|
||||
cy.get(".t--property-control-enablescroll .bp3-switch").click({
|
||||
force: true,
|
||||
});
|
||||
cy.wait("@updateLayout");
|
||||
cy.get(commonlocators.headingTextStyle).trigger("mouseover", {
|
||||
force: true,
|
||||
});
|
||||
cy.get(commonlocators.headingTextStyle).scrollIntoView({ duration: 2000 });
|
||||
});
|
||||
});
|
||||
|
|
@ -1,10 +1,11 @@
|
|||
const pages = require("../../../../locators/Pages.json");
|
||||
const publish = require("../../../../locators/publishWidgetspage.json");
|
||||
|
||||
const pageOne = "MyPage1";
|
||||
const pageTwo = "MyPage2";
|
||||
|
||||
describe("Hide page", function() {
|
||||
it("Hide page", function() {
|
||||
describe("Hide / Show page test functionality", function() {
|
||||
it("Hide page test ", function() {
|
||||
cy.Createpage(pageOne);
|
||||
cy.Createpage(pageTwo);
|
||||
|
||||
|
|
@ -14,8 +15,19 @@ describe("Hide page", function() {
|
|||
.click({ force: true });
|
||||
cy.get(pages.hidePage).click({ force: true });
|
||||
cy.ClearSearch();
|
||||
|
||||
cy.PublishtheApp();
|
||||
cy.get(".t--page-switch-tab").should("have.length", 2);
|
||||
});
|
||||
|
||||
it("Show page test ", function() {
|
||||
cy.get(publish.backToEditor).click();
|
||||
cy.GlobalSearchEntity(pageOne);
|
||||
cy.xpath(pages.popover)
|
||||
.last()
|
||||
.click({ force: true });
|
||||
cy.get(pages.showPage).click({ force: true });
|
||||
cy.ClearSearch();
|
||||
cy.PublishtheApp();
|
||||
cy.get(".t--page-switch-tab").should("have.length", 3);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
const dsl = require("../../../../fixtures/PageLoadDsl.json");
|
||||
const commonlocators = require("../../../../locators/commonlocators.json");
|
||||
const pages = require("../../../../locators/Pages.json");
|
||||
const publish = require("../../../../locators/publishWidgetspage.json");
|
||||
|
||||
describe("Page Load tests", () => {
|
||||
before(() => {
|
||||
|
|
@ -61,4 +63,27 @@ describe("Page Load tests", () => {
|
|||
"This is Page 1",
|
||||
);
|
||||
});
|
||||
it("Hide Page and validate published app", () => {
|
||||
cy.get(publish.backToEditor).click();
|
||||
cy.GlobalSearchEntity("Page1");
|
||||
cy.xpath(pages.popover)
|
||||
.last()
|
||||
.click({ force: true });
|
||||
cy.get(pages.hidePage).click({ force: true });
|
||||
cy.ClearSearch();
|
||||
cy.PublishtheApp();
|
||||
// Assert active page DSL
|
||||
cy.get(commonlocators.headingTextStyle).should(
|
||||
"have.text",
|
||||
"This is Page 1",
|
||||
);
|
||||
cy.get(publish.backToEditor).click();
|
||||
cy.SearchEntityandOpen("Page2");
|
||||
cy.PublishtheApp();
|
||||
// Assert active page DSL
|
||||
cy.get(commonlocators.headingTextStyle).should(
|
||||
"have.text",
|
||||
"This is Page 2",
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -0,0 +1,40 @@
|
|||
const queryLocators = require("../../../../locators/QueryEditor.json");
|
||||
const datasource = require("../../../../locators/DatasourcesEditor.json");
|
||||
|
||||
let datasourceName;
|
||||
|
||||
describe("Create a query with a empty datasource, run, save the query", function() {
|
||||
beforeEach(() => {
|
||||
cy.startRoutesForDatasource();
|
||||
});
|
||||
|
||||
it("Create a empty datasource", function() {
|
||||
cy.NavigateToDatasourceEditor();
|
||||
cy.get(datasource.PostgreSQL).click();
|
||||
cy.testSaveDatasource();
|
||||
cy.get("@createDatasource").then((httpResponse) => {
|
||||
datasourceName = httpResponse.response.body.data.name;
|
||||
});
|
||||
});
|
||||
|
||||
it("Create a query for empty/incorrect datasource and validate", () => {
|
||||
cy.NavigateToQueryEditor();
|
||||
cy.contains(".t--datasource-name", datasourceName)
|
||||
.find(queryLocators.createQuery)
|
||||
.click();
|
||||
|
||||
cy.get(queryLocators.templateMenu).click();
|
||||
cy.get(".CodeMirror textarea")
|
||||
.first()
|
||||
.focus()
|
||||
.type("select * from users limit 10");
|
||||
|
||||
cy.EvaluateCurrentValue("select * from users limit 10");
|
||||
cy.runQuery();
|
||||
cy.get(".react-tabs p")
|
||||
.last()
|
||||
.contains(
|
||||
"[Missing endpoint., Missing username for authentication., Missing password for authentication.]",
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
@ -5,7 +5,7 @@ describe("Update a user's name", function() {
|
|||
|
||||
it("Update a user's name", function() {
|
||||
cy.get(homePage.profileMenu).click();
|
||||
cy.get(".t--edit-profile").click();
|
||||
cy.get(".t--edit-profile").click({ force: true });
|
||||
|
||||
cy.generateUUID().then((uid) => {
|
||||
username = uid;
|
||||
|
|
@ -14,12 +14,37 @@ describe("Update a user's name", function() {
|
|||
// Waiting as the input onchange has a debounce
|
||||
// eslint-disable-next-line cypress/no-unnecessary-waiting
|
||||
cy.wait(2000);
|
||||
|
||||
cy.get(".t--back").click();
|
||||
cy.reload();
|
||||
|
||||
cy.get(homePage.profileMenu).click();
|
||||
cy.get(".t--user-name").contains(username);
|
||||
});
|
||||
});
|
||||
|
||||
it("Validate email address and Reset pwd", function() {
|
||||
cy.intercept("POST", "/api/v1/users/forgotPassword", {
|
||||
fixture: "resetPassword.json",
|
||||
}).as("resetPwd");
|
||||
cy.get(".t--edit-profile").click({ force: true });
|
||||
|
||||
// Waiting as the input onchange has a debounce
|
||||
// eslint-disable-next-line cypress/no-unnecessary-waiting
|
||||
cy.wait(2000);
|
||||
cy.get(".react-tabs .cs-text")
|
||||
.last()
|
||||
.invoke("text")
|
||||
.then((text) => {
|
||||
const someText = text;
|
||||
expect(someText).to.equal(Cypress.env("USERNAME"));
|
||||
});
|
||||
cy.get(".react-tabs a")
|
||||
.last()
|
||||
.contains("Reset Password")
|
||||
.click();
|
||||
cy.wait("@resetPwd").should(
|
||||
"have.nested.property",
|
||||
"response.body.responseMeta.status",
|
||||
200,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -19,5 +19,6 @@
|
|||
"clonePage": ".single-select >div:contains('Clone')",
|
||||
"deletePage": ".single-select >div:contains('Delete')",
|
||||
"hidePage": ".single-select >div:contains('Hide')",
|
||||
"entityQuery": ".t--entity-name:contains('Queries')"
|
||||
"entityQuery": ".t--entity-name:contains('Queries')",
|
||||
"showPage": ".single-select >div:contains('Show')"
|
||||
}
|
||||
|
|
@ -1409,6 +1409,14 @@ Cypress.Commands.add(
|
|||
},
|
||||
);
|
||||
|
||||
Cypress.Commands.add("readTextDataValidateCSS", (cssProperty, cssValue) => {
|
||||
cy.get(commonlocators.headingTextStyle).should(
|
||||
"have.css",
|
||||
cssProperty,
|
||||
cssValue,
|
||||
);
|
||||
});
|
||||
|
||||
Cypress.Commands.add("evaluateErrorMessage", (value) => {
|
||||
cy.get(commonlocators.evaluateMsg)
|
||||
.first()
|
||||
|
|
|
|||
|
|
@ -26,6 +26,21 @@ export const updateDatasource = (
|
|||
};
|
||||
};
|
||||
|
||||
export type UpdateDatasourceSuccessAction = {
|
||||
type: string;
|
||||
payload: Datasource;
|
||||
redirect: boolean;
|
||||
};
|
||||
|
||||
export const updateDatasourceSuccess = (
|
||||
payload: Datasource,
|
||||
redirect = true,
|
||||
): UpdateDatasourceSuccessAction => ({
|
||||
type: ReduxActionTypes.UPDATE_DATASOURCE_SUCCESS,
|
||||
payload,
|
||||
redirect,
|
||||
});
|
||||
|
||||
export const redirectAuthorizationCode = (
|
||||
pageId: string,
|
||||
datasourceId: string,
|
||||
|
|
|
|||
|
|
@ -97,6 +97,7 @@ export interface CopyActionRequest {
|
|||
|
||||
export interface UpdateActionNameRequest {
|
||||
pageId: string;
|
||||
actionId: string;
|
||||
layoutId: string;
|
||||
newName: string;
|
||||
oldName: string;
|
||||
|
|
@ -107,11 +108,7 @@ class ActionAPI extends API {
|
|||
static apiUpdateCancelTokenSource: CancelTokenSource;
|
||||
static queryUpdateCancelTokenSource: CancelTokenSource;
|
||||
|
||||
static fetchAPI(id: string): AxiosPromise<GenericApiResponse<Action>> {
|
||||
return API.get(`${ActionAPI.url}/${id}`);
|
||||
}
|
||||
|
||||
static createAPI(
|
||||
static createAction(
|
||||
apiConfig: Partial<Action>,
|
||||
): AxiosPromise<ActionCreateUpdateResponse> {
|
||||
return API.post(ActionAPI.url, apiConfig);
|
||||
|
|
@ -135,7 +132,7 @@ class ActionAPI extends API {
|
|||
return API.get(ActionAPI.url, { pageId });
|
||||
}
|
||||
|
||||
static updateAPI(
|
||||
static updateAction(
|
||||
apiConfig: Partial<Action>,
|
||||
): AxiosPromise<ActionCreateUpdateResponse> {
|
||||
if (ActionAPI.apiUpdateCancelTokenSource) {
|
||||
|
|
@ -158,24 +155,6 @@ class ActionAPI extends API {
|
|||
return API.delete(`${ActionAPI.url}/${id}`);
|
||||
}
|
||||
|
||||
static createQuery(
|
||||
createQuery: CreateActionRequest<QueryConfig>,
|
||||
): AxiosPromise<ActionCreateUpdateResponse> {
|
||||
return API.post(ActionAPI.url, createQuery);
|
||||
}
|
||||
|
||||
static updateQuery(
|
||||
updateQuery: UpdateActionRequest<QueryConfig>,
|
||||
): AxiosPromise<ActionCreateUpdateResponse> {
|
||||
if (ActionAPI.queryUpdateCancelTokenSource) {
|
||||
ActionAPI.queryUpdateCancelTokenSource.cancel();
|
||||
}
|
||||
ActionAPI.queryUpdateCancelTokenSource = axios.CancelToken.source();
|
||||
return API.post(ActionAPI.url, updateQuery, undefined, {
|
||||
cancelToken: ActionAPI.queryUpdateCancelTokenSource.token,
|
||||
});
|
||||
}
|
||||
|
||||
static executeAction(
|
||||
executeAction: ExecuteActionRequest,
|
||||
timeout?: number,
|
||||
|
|
@ -191,12 +170,6 @@ class ActionAPI extends API {
|
|||
});
|
||||
}
|
||||
|
||||
static executeQuery(
|
||||
executeAction: any,
|
||||
): AxiosPromise<ActionExecutionResponse> {
|
||||
return API.post(ActionAPI.url + "/execute", executeAction);
|
||||
}
|
||||
|
||||
static toggleActionExecuteOnLoad(actionId: string, shouldExecute: boolean) {
|
||||
return API.put(ActionAPI.url + `/executeOnLoad/${actionId}`, undefined, {
|
||||
flag: shouldExecute.toString(),
|
||||
|
|
|
|||
|
|
@ -140,29 +140,30 @@ const MyMapComponent = withGoogleMap((props: any) => {
|
|||
<StyledInput type="text" placeholder="Enter location to search" />
|
||||
</SearchBox>
|
||||
)}
|
||||
{props.markers.map((marker: any, index: number) => (
|
||||
<Marker
|
||||
key={index}
|
||||
title={marker.title}
|
||||
position={{ lat: marker.lat, lng: marker.long }}
|
||||
clickable
|
||||
draggable={
|
||||
props.selectedMarker &&
|
||||
props.selectedMarker.lat === marker.lat &&
|
||||
props.selectedMarker.long === marker.long
|
||||
}
|
||||
onClick={() => {
|
||||
setMapCenter({
|
||||
...marker,
|
||||
lng: marker.long,
|
||||
});
|
||||
props.selectMarker(marker.lat, marker.long, marker.title);
|
||||
}}
|
||||
onDragEnd={(de) => {
|
||||
props.updateMarker(de.latLng.lat(), de.latLng.lng(), index);
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
{Array.isArray(props.markers) &&
|
||||
props.markers.map((marker: MarkerProps, index: number) => (
|
||||
<Marker
|
||||
key={index}
|
||||
title={marker.title}
|
||||
position={{ lat: marker.lat, lng: marker.long }}
|
||||
clickable
|
||||
draggable={
|
||||
props.selectedMarker &&
|
||||
props.selectedMarker.lat === marker.lat &&
|
||||
props.selectedMarker.long === marker.long
|
||||
}
|
||||
onClick={() => {
|
||||
setMapCenter({
|
||||
...marker,
|
||||
lng: marker.long,
|
||||
});
|
||||
props.selectMarker(marker.lat, marker.long, marker.title);
|
||||
}}
|
||||
onDragEnd={(de) => {
|
||||
props.updateMarker(de.latLng.lat(), de.latLng.lng(), index);
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
{props.enablePickLocation && (
|
||||
<PickMyLocationWrapper
|
||||
title="Pick My Location"
|
||||
|
|
|
|||
|
|
@ -1,5 +1,11 @@
|
|||
import { sortTableFunction } from "components/designSystems/appsmith/TableComponent/CommonUtilities";
|
||||
import { ColumnTypes } from "components/designSystems/appsmith/TableComponent/Constants";
|
||||
import {
|
||||
sortTableFunction,
|
||||
transformTableDataIntoCsv,
|
||||
} from "components/designSystems/appsmith/TableComponent/CommonUtilities";
|
||||
import {
|
||||
ColumnTypes,
|
||||
TableColumnProps,
|
||||
} from "components/designSystems/appsmith/TableComponent/Constants";
|
||||
|
||||
describe("TableUtilities", () => {
|
||||
it("works as expected for sort table rows", () => {
|
||||
|
|
@ -29,3 +35,82 @@ describe("TableUtilities", () => {
|
|||
expect(sortedTableData).toStrictEqual(expected);
|
||||
});
|
||||
});
|
||||
|
||||
describe("TransformTableDataIntoArrayOfArray", () => {
|
||||
const columns: TableColumnProps[] = [
|
||||
{
|
||||
Header: "Id",
|
||||
accessor: "id",
|
||||
minWidth: 60,
|
||||
draggable: true,
|
||||
metaProperties: {
|
||||
isHidden: false,
|
||||
type: "string",
|
||||
},
|
||||
columnProperties: {
|
||||
id: "id",
|
||||
label: "Id",
|
||||
columnType: "string",
|
||||
isVisible: true,
|
||||
index: 0,
|
||||
width: 60,
|
||||
isDerived: false,
|
||||
computedValue: "",
|
||||
},
|
||||
},
|
||||
];
|
||||
it("work as expected", () => {
|
||||
const data = [
|
||||
{
|
||||
id: "abc",
|
||||
},
|
||||
{
|
||||
id: "xyz",
|
||||
},
|
||||
];
|
||||
const csvData = transformTableDataIntoCsv({
|
||||
columns,
|
||||
data,
|
||||
});
|
||||
const expectedCsvData = [["Id"], ["abc"], ["xyz"]];
|
||||
expect(JSON.stringify(csvData)).toStrictEqual(
|
||||
JSON.stringify(expectedCsvData),
|
||||
);
|
||||
});
|
||||
it("work as expected with newline", () => {
|
||||
const data = [
|
||||
{
|
||||
id: "abc\ntest",
|
||||
},
|
||||
{
|
||||
id: "xyz",
|
||||
},
|
||||
];
|
||||
const csvData = transformTableDataIntoCsv({
|
||||
columns,
|
||||
data,
|
||||
});
|
||||
const expectedCsvData = [["Id"], ["abc test"], ["xyz"]];
|
||||
expect(JSON.stringify(csvData)).toStrictEqual(
|
||||
JSON.stringify(expectedCsvData),
|
||||
);
|
||||
});
|
||||
it("work as expected with comma", () => {
|
||||
const data = [
|
||||
{
|
||||
id: "abc,test",
|
||||
},
|
||||
{
|
||||
id: "xyz",
|
||||
},
|
||||
];
|
||||
const csvData = transformTableDataIntoCsv({
|
||||
columns,
|
||||
data,
|
||||
});
|
||||
const expectedCsvData = [["Id"], ['"abc,test"'], ["xyz"]];
|
||||
expect(JSON.stringify(csvData)).toStrictEqual(
|
||||
JSON.stringify(expectedCsvData),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,5 +1,8 @@
|
|||
import { ColumnTypes } from "components/designSystems/appsmith/TableComponent/Constants";
|
||||
import { isPlainObject, isNil } from "lodash";
|
||||
import {
|
||||
ColumnTypes,
|
||||
TableColumnProps,
|
||||
} from "components/designSystems/appsmith/TableComponent/Constants";
|
||||
import { isPlainObject, isNil, isString } from "lodash";
|
||||
import moment from "moment";
|
||||
|
||||
export function sortTableFunction(
|
||||
|
|
@ -51,3 +54,41 @@ export function sortTableFunction(
|
|||
},
|
||||
);
|
||||
}
|
||||
|
||||
export const transformTableDataIntoCsv = (props: {
|
||||
columns: TableColumnProps[];
|
||||
data: Array<Record<string, unknown>>;
|
||||
}) => {
|
||||
const csvData = [];
|
||||
csvData.push(
|
||||
props.columns
|
||||
.map((column: TableColumnProps) => {
|
||||
if (column.metaProperties && !column.metaProperties.isHidden) {
|
||||
return column.Header;
|
||||
}
|
||||
return null;
|
||||
})
|
||||
.filter((i) => !!i),
|
||||
);
|
||||
for (let row = 0; row < props.data.length; row++) {
|
||||
const data: { [key: string]: any } = props.data[row];
|
||||
const csvDataRow = [];
|
||||
for (let colIndex = 0; colIndex < props.columns.length; colIndex++) {
|
||||
const column = props.columns[colIndex];
|
||||
let value = data[column.accessor];
|
||||
if (column.metaProperties && !column.metaProperties.isHidden) {
|
||||
value =
|
||||
isString(value) && value.includes("\n")
|
||||
? value.replace("\n", " ")
|
||||
: value;
|
||||
if (isString(value) && value.includes(",")) {
|
||||
csvDataRow.push(`"${value}"`);
|
||||
} else {
|
||||
csvDataRow.push(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
csvData.push(csvDataRow);
|
||||
}
|
||||
return csvData;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -103,7 +103,7 @@ export interface TableColumnMetaProps {
|
|||
type: string;
|
||||
}
|
||||
|
||||
export interface ReactTableColumnProps {
|
||||
export interface TableColumnProps {
|
||||
Header: string;
|
||||
accessor: string;
|
||||
width?: number;
|
||||
|
|
@ -114,6 +114,8 @@ export interface ReactTableColumnProps {
|
|||
metaProperties?: TableColumnMetaProps;
|
||||
isDerived?: boolean;
|
||||
columnProperties: ColumnProperties;
|
||||
}
|
||||
export interface ReactTableColumnProps extends TableColumnProps {
|
||||
Cell: (props: any) => JSX.Element;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import { ReactComponent as DownloadIcon } from "assets/icons/control/download-ta
|
|||
import { ReactTableColumnProps } from "components/designSystems/appsmith/TableComponent/Constants";
|
||||
import { TableIconWrapper } from "components/designSystems/appsmith/TableComponent/TableStyledWrappers";
|
||||
import TableActionIcon from "components/designSystems/appsmith/TableComponent/TableActionIcon";
|
||||
import { isString } from "lodash";
|
||||
import { transformTableDataIntoCsv } from "./CommonUtilities";
|
||||
|
||||
interface TableDataDownloadProps {
|
||||
data: Array<Record<string, unknown>>;
|
||||
|
|
@ -13,63 +13,49 @@ interface TableDataDownloadProps {
|
|||
widgetName: string;
|
||||
}
|
||||
|
||||
const downloadDataAsCSV = (props: {
|
||||
csvData: Array<Array<any>>;
|
||||
fileName: string;
|
||||
}) => {
|
||||
let csvContent = "";
|
||||
props.csvData.forEach((infoArray: Array<any>, index: number) => {
|
||||
const dataString = infoArray.join(",");
|
||||
csvContent += index < props.csvData.length ? dataString + "\n" : dataString;
|
||||
});
|
||||
const anchor = document.createElement("a");
|
||||
const mimeType = "application/octet-stream";
|
||||
if (navigator.msSaveBlob) {
|
||||
navigator.msSaveBlob(
|
||||
new Blob([csvContent], {
|
||||
type: mimeType,
|
||||
}),
|
||||
props.fileName,
|
||||
);
|
||||
} else if (URL && "download" in anchor) {
|
||||
anchor.href = URL.createObjectURL(
|
||||
new Blob([csvContent], {
|
||||
type: mimeType,
|
||||
}),
|
||||
);
|
||||
anchor.setAttribute("download", props.fileName);
|
||||
document.body.appendChild(anchor);
|
||||
anchor.click();
|
||||
document.body.removeChild(anchor);
|
||||
}
|
||||
};
|
||||
|
||||
const TableDataDownload = (props: TableDataDownloadProps) => {
|
||||
const [selected, toggleButtonClick] = React.useState(false);
|
||||
const downloadTableData = () => {
|
||||
toggleButtonClick(true);
|
||||
const csvData = [];
|
||||
csvData.push(
|
||||
props.columns
|
||||
.map((column: ReactTableColumnProps) => {
|
||||
if (column.metaProperties && !column.metaProperties.isHidden) {
|
||||
return column.Header;
|
||||
}
|
||||
return null;
|
||||
})
|
||||
.filter((i) => !!i),
|
||||
);
|
||||
for (let row = 0; row < props.data.length; row++) {
|
||||
const data: { [key: string]: any } = props.data[row];
|
||||
const csvDataRow = [];
|
||||
for (let colIndex = 0; colIndex < props.columns.length; colIndex++) {
|
||||
const column = props.columns[colIndex];
|
||||
const value = data[column.accessor];
|
||||
if (column.metaProperties && !column.metaProperties.isHidden) {
|
||||
if (isString(value) && value.includes(",")) {
|
||||
csvDataRow.push(`"${value}"`);
|
||||
} else {
|
||||
csvDataRow.push(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
csvData.push(csvDataRow);
|
||||
}
|
||||
let csvContent = "";
|
||||
csvData.forEach(function(infoArray, index) {
|
||||
const dataString = infoArray.join(",");
|
||||
csvContent += index < csvData.length ? dataString + "\n" : dataString;
|
||||
const csvData = transformTableDataIntoCsv({
|
||||
columns: props.columns,
|
||||
data: props.data,
|
||||
});
|
||||
downloadDataAsCSV({
|
||||
csvData: csvData,
|
||||
fileName: `${props.widgetName}.csv`,
|
||||
});
|
||||
const fileName = `${props.widgetName}.csv`;
|
||||
const anchor = document.createElement("a");
|
||||
const mimeType = "application/octet-stream";
|
||||
if (navigator.msSaveBlob) {
|
||||
navigator.msSaveBlob(
|
||||
new Blob([csvContent], {
|
||||
type: mimeType,
|
||||
}),
|
||||
fileName,
|
||||
);
|
||||
} else if (URL && "download" in anchor) {
|
||||
anchor.href = URL.createObjectURL(
|
||||
new Blob([csvContent], {
|
||||
type: mimeType,
|
||||
}),
|
||||
);
|
||||
anchor.setAttribute("download", fileName);
|
||||
document.body.appendChild(anchor);
|
||||
anchor.click();
|
||||
document.body.removeChild(anchor);
|
||||
}
|
||||
toggleButtonClick(false);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -239,6 +239,7 @@ class EmbeddedDatasourcePathComponent extends React.Component<Props> {
|
|||
<StoreAsDatasource enable={!!displayValue} />
|
||||
) : datasource && "id" in datasource ? (
|
||||
<DatasourceIcon
|
||||
enable={true}
|
||||
onClick={() =>
|
||||
history.push(
|
||||
DATA_SOURCES_EDITOR_ID_URL(
|
||||
|
|
|
|||
|
|
@ -244,6 +244,26 @@ describe("getConfigInitialValues test", () => {
|
|||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
input: [
|
||||
{
|
||||
sectionName: "Settings",
|
||||
children: [
|
||||
{
|
||||
label: "Smart substitution",
|
||||
configProperty: "datasourceConfiguration.isSmart",
|
||||
controlType: "SWITCH",
|
||||
initialValue: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
output: {
|
||||
datasourceConfiguration: {
|
||||
isSmart: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
testCases.forEach((testCase) => {
|
||||
|
|
|
|||
|
|
@ -104,7 +104,7 @@ export const getConfigInitialValues = (config: Record<string, any>[]) => {
|
|||
return parseConfig(subSection);
|
||||
}
|
||||
|
||||
if (subSection.initialValue) {
|
||||
if ("initialValue" in subSection) {
|
||||
if (subSection.controlType === "KEYVALUE_ARRAY") {
|
||||
subSection.initialValue.forEach(
|
||||
(initialValue: string | number, index: number) => {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,9 @@
|
|||
export default [
|
||||
{
|
||||
dependencies: {
|
||||
"actionConfiguration.body": [
|
||||
"actionConfiguration.pluginSpecifiedTemplates[0].value",
|
||||
],
|
||||
},
|
||||
},
|
||||
];
|
||||
|
|
@ -28,7 +28,7 @@ export default [
|
|||
controlType: "CHECKBOX",
|
||||
info:
|
||||
"Turning on this property fixes the JSON substitution of bindings in API body by adding/removing quotes intelligently and reduces developer errors",
|
||||
initialValue: "false",
|
||||
initialValue: false,
|
||||
},
|
||||
// {
|
||||
// label: "Cache response",
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import { getPropertyControlTypes } from "components/propertyControls";
|
||||
import { VALIDATION_TYPES } from "constants/WidgetValidation";
|
||||
const ControlTypes = getPropertyControlTypes();
|
||||
export type ControlType = typeof ControlTypes[keyof typeof ControlTypes];
|
||||
|
||||
|
|
@ -42,6 +43,7 @@ export type PropertyPaneControlConfig = {
|
|||
hidden?: (props: any, propertyPath: string) => boolean;
|
||||
isBindProperty: boolean;
|
||||
isTriggerProperty: boolean;
|
||||
validation?: VALIDATION_TYPES;
|
||||
useValidationMessage?: boolean;
|
||||
additionalAutoComplete?: (
|
||||
props: any,
|
||||
|
|
|
|||
|
|
@ -2,34 +2,34 @@ import { WidgetProps } from "widgets/BaseWidget";
|
|||
import { DataTree } from "entities/DataTree/dataTreeFactory";
|
||||
import { EXECUTION_PARAM_KEY } from "constants/AppsmithActionConstants/ActionConstants";
|
||||
|
||||
// Always add a validator function in ./Validators for these types
|
||||
export const VALIDATION_TYPES = {
|
||||
TEXT: "TEXT",
|
||||
REGEX: "REGEX",
|
||||
NUMBER: "NUMBER",
|
||||
BOOLEAN: "BOOLEAN",
|
||||
OBJECT: "OBJECT",
|
||||
ARRAY: "ARRAY",
|
||||
TABLE_DATA: "TABLE_DATA",
|
||||
OPTIONS_DATA: "OPTIONS_DATA",
|
||||
DATE_ISO_STRING: "DATE_ISO_STRING",
|
||||
DEFAULT_DATE: "DEFAULT_DATE",
|
||||
MIN_DATE: "MIN_DATE",
|
||||
MAX_DATE: "MAX_DATE",
|
||||
TABS_DATA: "TABS_DATA",
|
||||
CHART_DATA: "CHART_DATA",
|
||||
CUSTOM_FUSION_CHARTS_DATA: "CUSTOM_FUSION_CHARTS_DATA",
|
||||
MARKERS: "MARKERS",
|
||||
ACTION_SELECTOR: "ACTION_SELECTOR",
|
||||
ARRAY_ACTION_SELECTOR: "ARRAY_ACTION_SELECTOR",
|
||||
SELECTED_TAB: "SELECTED_TAB",
|
||||
DEFAULT_OPTION_VALUE: "DEFAULT_OPTION_VALUE",
|
||||
DEFAULT_SELECTED_ROW: "DEFAULT_SELECTED_ROW",
|
||||
COLUMN_PROPERTIES_ARRAY: "COLUMN_PROPERTIES_ARRAY",
|
||||
LAT_LONG: "LAT_LONG",
|
||||
TABLE_PAGE_NO: "TABLE_PAGE_NO",
|
||||
ROW_INDICES: "ROW_INDICES",
|
||||
};
|
||||
// Always add a validator function in ./worker/validation for these types
|
||||
export enum VALIDATION_TYPES {
|
||||
TEXT = "TEXT",
|
||||
REGEX = "REGEX",
|
||||
NUMBER = "NUMBER",
|
||||
BOOLEAN = "BOOLEAN",
|
||||
OBJECT = "OBJECT",
|
||||
ARRAY = "ARRAY",
|
||||
TABLE_DATA = "TABLE_DATA",
|
||||
OPTIONS_DATA = "OPTIONS_DATA",
|
||||
DATE_ISO_STRING = "DATE_ISO_STRING",
|
||||
DEFAULT_DATE = "DEFAULT_DATE",
|
||||
MIN_DATE = "MIN_DATE",
|
||||
MAX_DATE = "MAX_DATE",
|
||||
TABS_DATA = "TABS_DATA",
|
||||
CHART_DATA = "CHART_DATA",
|
||||
CUSTOM_FUSION_CHARTS_DATA = "CUSTOM_FUSION_CHARTS_DATA",
|
||||
MARKERS = "MARKERS",
|
||||
ACTION_SELECTOR = "ACTION_SELECTOR",
|
||||
ARRAY_ACTION_SELECTOR = "ARRAY_ACTION_SELECTOR",
|
||||
SELECTED_TAB = "SELECTED_TAB",
|
||||
DEFAULT_OPTION_VALUE = "DEFAULT_OPTION_VALUE",
|
||||
DEFAULT_SELECTED_ROW = "DEFAULT_SELECTED_ROW",
|
||||
COLUMN_PROPERTIES_ARRAY = "COLUMN_PROPERTIES_ARRAY",
|
||||
LAT_LONG = "LAT_LONG",
|
||||
TABLE_PAGE_NO = "TABLE_PAGE_NO",
|
||||
ROW_INDICES = "ROW_INDICES",
|
||||
}
|
||||
|
||||
export type ValidationResponse = {
|
||||
isValid: boolean;
|
||||
|
|
@ -38,7 +38,6 @@ export type ValidationResponse = {
|
|||
transformed?: any;
|
||||
};
|
||||
|
||||
export type ValidationType = typeof VALIDATION_TYPES[keyof typeof VALIDATION_TYPES];
|
||||
export type Validator = (
|
||||
value: any,
|
||||
props: WidgetProps,
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import { AppDataState } from "reducers/entityReducers/appReducer";
|
|||
import { DynamicPath } from "utils/DynamicBindingUtils";
|
||||
import { generateDataTreeAction } from "entities/DataTree/dataTreeAction";
|
||||
import { generateDataTreeWidget } from "entities/DataTree/dataTreeWidget";
|
||||
import { VALIDATION_TYPES } from "constants/WidgetValidation";
|
||||
|
||||
export type ActionDescription<T> = {
|
||||
type: string;
|
||||
|
|
@ -52,6 +53,7 @@ export interface DataTreeAction extends Omit<ActionData, "data" | "config"> {
|
|||
export interface DataTreeWidget extends WidgetProps {
|
||||
bindingPaths: Record<string, boolean>;
|
||||
triggerPaths: Record<string, boolean>;
|
||||
validationPaths: Record<string, VALIDATION_TYPES>;
|
||||
ENTITY_TYPE: ENTITY_TYPE.WIDGET;
|
||||
}
|
||||
|
||||
|
|
|
|||
245
app/client/src/entities/DataTree/dataTreeWidget.test.ts
Normal file
245
app/client/src/entities/DataTree/dataTreeWidget.test.ts
Normal file
|
|
@ -0,0 +1,245 @@
|
|||
import { FlattenedWidgetProps } from "reducers/entityReducers/canvasWidgetsReducer";
|
||||
import { generateDataTreeWidget } from "entities/DataTree/dataTreeWidget";
|
||||
import { DataTreeWidget, ENTITY_TYPE } from "entities/DataTree/dataTreeFactory";
|
||||
import { RenderModes, WidgetTypes } from "constants/WidgetConstants";
|
||||
import WidgetFactory from "utils/WidgetFactory";
|
||||
import { VALIDATION_TYPES } from "constants/WidgetValidation";
|
||||
|
||||
describe("generateDataTreeWidget", () => {
|
||||
beforeEach(() => {
|
||||
const getMetaProps = jest.spyOn(
|
||||
WidgetFactory,
|
||||
"getWidgetMetaPropertiesMap",
|
||||
);
|
||||
getMetaProps.mockReturnValueOnce({
|
||||
text: undefined,
|
||||
isDirty: false,
|
||||
isFocused: false,
|
||||
});
|
||||
|
||||
const getDerivedProps = jest.spyOn(
|
||||
WidgetFactory,
|
||||
"getWidgetDerivedPropertiesMap",
|
||||
);
|
||||
getDerivedProps.mockReturnValueOnce({
|
||||
isValid: "{{true}}",
|
||||
value: "{{this.text}}",
|
||||
});
|
||||
|
||||
const getDefaultProps = jest.spyOn(
|
||||
WidgetFactory,
|
||||
"getWidgetDefaultPropertiesMap",
|
||||
);
|
||||
getDefaultProps.mockReturnValueOnce({
|
||||
text: "defaultText",
|
||||
});
|
||||
|
||||
const getPropertyConfig = jest.spyOn(
|
||||
WidgetFactory,
|
||||
"getWidgetPropertyPaneConfig",
|
||||
);
|
||||
getPropertyConfig.mockReturnValueOnce([
|
||||
{
|
||||
sectionName: "General",
|
||||
children: [
|
||||
{
|
||||
propertyName: "inputType",
|
||||
label: "Data Type",
|
||||
controlType: "DROP_DOWN",
|
||||
isBindProperty: false,
|
||||
isTriggerProperty: false,
|
||||
},
|
||||
{
|
||||
propertyName: "defaultText",
|
||||
label: "Default Text",
|
||||
controlType: "INPUT_TEXT",
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: VALIDATION_TYPES.TEXT,
|
||||
},
|
||||
{
|
||||
propertyName: "placeholderText",
|
||||
label: "Placeholder",
|
||||
controlType: "INPUT_TEXT",
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: VALIDATION_TYPES.TEXT,
|
||||
},
|
||||
{
|
||||
propertyName: "regex",
|
||||
label: "Regex",
|
||||
controlType: "INPUT_TEXT",
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: VALIDATION_TYPES.REGEX,
|
||||
},
|
||||
{
|
||||
propertyName: "errorMessage",
|
||||
label: "Error Message",
|
||||
controlType: "INPUT_TEXT",
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: VALIDATION_TYPES.TEXT,
|
||||
},
|
||||
{
|
||||
propertyName: "isRequired",
|
||||
label: "Required",
|
||||
controlType: "SWITCH",
|
||||
isJSConvertible: true,
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: VALIDATION_TYPES.BOOLEAN,
|
||||
},
|
||||
{
|
||||
propertyName: "isVisible",
|
||||
label: "Visible",
|
||||
controlType: "SWITCH",
|
||||
isJSConvertible: true,
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: VALIDATION_TYPES.BOOLEAN,
|
||||
},
|
||||
{
|
||||
propertyName: "isDisabled",
|
||||
label: "Disabled",
|
||||
controlType: "SWITCH",
|
||||
isJSConvertible: true,
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: VALIDATION_TYPES.BOOLEAN,
|
||||
},
|
||||
{
|
||||
propertyName: "resetOnSubmit",
|
||||
label: "Reset on submit",
|
||||
controlType: "SWITCH",
|
||||
isJSConvertible: true,
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: VALIDATION_TYPES.BOOLEAN,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
sectionName: "Actions",
|
||||
children: [
|
||||
{
|
||||
propertyName: "onTextChanged",
|
||||
label: "onTextChanged",
|
||||
controlType: "ACTION_SELECTOR",
|
||||
isJSConvertible: true,
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: true,
|
||||
},
|
||||
{
|
||||
propertyName: "onSubmit",
|
||||
label: "onSubmit",
|
||||
controlType: "ACTION_SELECTOR",
|
||||
isJSConvertible: true,
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
it("generates enhanced widget with the right properties", () => {
|
||||
const widget: FlattenedWidgetProps = {
|
||||
bottomRow: 0,
|
||||
isLoading: false,
|
||||
leftColumn: 0,
|
||||
parentColumnSpace: 0,
|
||||
parentRowSpace: 0,
|
||||
renderMode: RenderModes.CANVAS,
|
||||
rightColumn: 0,
|
||||
topRow: 0,
|
||||
type: WidgetTypes.INPUT_WIDGET,
|
||||
version: 0,
|
||||
widgetId: "123",
|
||||
widgetName: "Input1",
|
||||
defaultText: "Testing",
|
||||
};
|
||||
|
||||
const widgetMetaProps: Record<string, unknown> = {
|
||||
text: "Tester",
|
||||
isDirty: true,
|
||||
};
|
||||
|
||||
const getMetaProps = jest.spyOn(
|
||||
WidgetFactory,
|
||||
"getWidgetMetaPropertiesMap",
|
||||
);
|
||||
|
||||
getMetaProps.mockReturnValueOnce({
|
||||
text: true,
|
||||
isDirty: true,
|
||||
});
|
||||
|
||||
const expected: DataTreeWidget = {
|
||||
bindingPaths: {
|
||||
defaultText: true,
|
||||
errorMessage: true,
|
||||
isDirty: true,
|
||||
isDisabled: true,
|
||||
isFocused: true,
|
||||
isRequired: true,
|
||||
isValid: true,
|
||||
isVisible: true,
|
||||
placeholderText: true,
|
||||
regex: true,
|
||||
resetOnSubmit: true,
|
||||
text: true,
|
||||
value: true,
|
||||
},
|
||||
triggerPaths: {
|
||||
onSubmit: true,
|
||||
onTextChanged: true,
|
||||
},
|
||||
validationPaths: {
|
||||
defaultText: VALIDATION_TYPES.TEXT,
|
||||
errorMessage: VALIDATION_TYPES.TEXT,
|
||||
isDisabled: VALIDATION_TYPES.BOOLEAN,
|
||||
isRequired: VALIDATION_TYPES.BOOLEAN,
|
||||
isVisible: VALIDATION_TYPES.BOOLEAN,
|
||||
placeholderText: VALIDATION_TYPES.TEXT,
|
||||
regex: VALIDATION_TYPES.REGEX,
|
||||
resetOnSubmit: VALIDATION_TYPES.BOOLEAN,
|
||||
},
|
||||
dynamicBindingPathList: [
|
||||
{
|
||||
key: "isValid",
|
||||
},
|
||||
{
|
||||
key: "value",
|
||||
},
|
||||
],
|
||||
value: "{{Input1.text}}",
|
||||
isDirty: true,
|
||||
isFocused: false,
|
||||
isValid: "{{true}}",
|
||||
text: "Tester",
|
||||
bottomRow: 0,
|
||||
isLoading: false,
|
||||
leftColumn: 0,
|
||||
parentColumnSpace: 0,
|
||||
parentRowSpace: 0,
|
||||
renderMode: RenderModes.CANVAS,
|
||||
rightColumn: 0,
|
||||
topRow: 0,
|
||||
type: WidgetTypes.INPUT_WIDGET,
|
||||
version: 0,
|
||||
widgetId: "123",
|
||||
widgetName: "Input1",
|
||||
ENTITY_TYPE: ENTITY_TYPE.WIDGET,
|
||||
defaultText: "Testing",
|
||||
};
|
||||
|
||||
const result = generateDataTreeWidget(widget, widgetMetaProps);
|
||||
|
||||
expect(result).toStrictEqual(expected);
|
||||
});
|
||||
});
|
||||
|
|
@ -19,7 +19,11 @@ export const generateDataTreeWidget = (
|
|||
const propertyPaneConfigs = WidgetFactory.getWidgetPropertyPaneConfig(
|
||||
widget.type,
|
||||
);
|
||||
const { bindingPaths, triggerPaths } = getAllPathsFromPropertyConfig(
|
||||
const {
|
||||
bindingPaths,
|
||||
triggerPaths,
|
||||
validationPaths,
|
||||
} = getAllPathsFromPropertyConfig(
|
||||
widget,
|
||||
propertyPaneConfigs,
|
||||
Object.fromEntries(
|
||||
|
|
@ -67,6 +71,7 @@ export const generateDataTreeWidget = (
|
|||
dynamicBindingPathList,
|
||||
bindingPaths,
|
||||
triggerPaths,
|
||||
validationPaths,
|
||||
ENTITY_TYPE: ENTITY_TYPE.WIDGET,
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -145,6 +145,12 @@ describe("getAllPathsFromPropertyConfig", () => {
|
|||
onPageSizeChange: true,
|
||||
"primaryColumns.status.onClick": true,
|
||||
},
|
||||
validationPaths: {
|
||||
defaultSearchText: "TEXT",
|
||||
defaultSelectedRow: "DEFAULT_SELECTED_ROW",
|
||||
isVisible: "BOOLEAN",
|
||||
tableData: "TABLE_DATA",
|
||||
},
|
||||
};
|
||||
|
||||
const result = getAllPathsFromPropertyConfig(widget, config, {
|
||||
|
|
@ -202,6 +208,14 @@ describe("getAllPathsFromPropertyConfig", () => {
|
|||
triggerPaths: {
|
||||
onDataPointClick: true,
|
||||
},
|
||||
validationPaths: {
|
||||
"chartData[0].data": "CHART_DATA",
|
||||
"chartData[0].seriesName": "TEXT",
|
||||
chartName: "TEXT",
|
||||
isVisible: "BOOLEAN",
|
||||
xAxisName: "TEXT",
|
||||
yAxisName: "TEXT",
|
||||
},
|
||||
};
|
||||
|
||||
const result = getAllPathsFromPropertyConfig(widget, config, {});
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import { WidgetProps } from "widgets/BaseWidget";
|
|||
import { PropertyPaneConfig } from "constants/PropertyControlConstants";
|
||||
import { get } from "lodash";
|
||||
import { FlattenedWidgetProps } from "reducers/entityReducers/canvasWidgetsReducer";
|
||||
import { VALIDATION_TYPES } from "constants/WidgetValidation";
|
||||
|
||||
export const getAllPathsFromPropertyConfig = (
|
||||
widget: WidgetProps,
|
||||
|
|
@ -10,9 +11,11 @@ export const getAllPathsFromPropertyConfig = (
|
|||
): {
|
||||
bindingPaths: Record<string, true>;
|
||||
triggerPaths: Record<string, true>;
|
||||
validationPaths: Record<string, VALIDATION_TYPES>;
|
||||
} => {
|
||||
const bindingPaths: Record<string, true> = derivedProperties;
|
||||
const triggerPaths: Record<string, true> = {};
|
||||
const validationPaths: Record<any, VALIDATION_TYPES> = {};
|
||||
widgetConfig.forEach((config) => {
|
||||
if (config.children) {
|
||||
config.children.forEach((controlConfig: any) => {
|
||||
|
|
@ -27,6 +30,10 @@ export const getAllPathsFromPropertyConfig = (
|
|||
!controlConfig.isTriggerProperty
|
||||
) {
|
||||
bindingPaths[controlConfig.propertyName] = true;
|
||||
if (controlConfig.validation) {
|
||||
validationPaths[controlConfig.propertyName] =
|
||||
controlConfig.validation;
|
||||
}
|
||||
} else if (
|
||||
controlConfig.isBindProperty &&
|
||||
controlConfig.isTriggerProperty
|
||||
|
|
@ -66,6 +73,10 @@ export const getAllPathsFromPropertyConfig = (
|
|||
!panelColumnControlConfig.isTriggerProperty
|
||||
) {
|
||||
bindingPaths[panelPropertyPath] = true;
|
||||
if (panelColumnControlConfig.validation) {
|
||||
validationPaths[panelPropertyPath] =
|
||||
panelColumnControlConfig.validation;
|
||||
}
|
||||
} else if (
|
||||
panelColumnControlConfig.isBindProperty &&
|
||||
panelColumnControlConfig.isTriggerProperty
|
||||
|
|
@ -97,6 +108,10 @@ export const getAllPathsFromPropertyConfig = (
|
|||
!childPropertyConfig.isTriggerProperty
|
||||
) {
|
||||
bindingPaths[childArrayPropertyPath] = true;
|
||||
if (childPropertyConfig.validation) {
|
||||
validationPaths[childArrayPropertyPath] =
|
||||
childPropertyConfig.validation;
|
||||
}
|
||||
} else if (
|
||||
childPropertyConfig.isBindProperty &&
|
||||
childPropertyConfig.isTriggerProperty
|
||||
|
|
@ -112,7 +127,7 @@ export const getAllPathsFromPropertyConfig = (
|
|||
}
|
||||
});
|
||||
|
||||
return { bindingPaths, triggerPaths };
|
||||
return { bindingPaths, triggerPaths, validationPaths };
|
||||
};
|
||||
|
||||
export const nextAvailableRowInContainer = (
|
||||
|
|
|
|||
|
|
@ -102,4 +102,3 @@ div.bp3-popover-arrow {
|
|||
background: white !important;
|
||||
border-bottom: 1px solid #E7E7E7 !important;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -199,16 +199,6 @@ const WidgetConfigResponse: WidgetConfigReducerState = {
|
|||
widgetName: "RadioGroup",
|
||||
version: 1,
|
||||
},
|
||||
ALERT_WIDGET: {
|
||||
alertType: "NOTIFICATION",
|
||||
intent: "SUCCESS",
|
||||
rows: 3,
|
||||
columns: 3,
|
||||
header: "",
|
||||
message: "",
|
||||
widgetName: "Alert",
|
||||
version: 1,
|
||||
},
|
||||
FILE_PICKER_WIDGET: {
|
||||
rows: 1,
|
||||
files: [],
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ const PostBodyContainer = styled.div`
|
|||
|
||||
const JSONEditorFieldWrapper = styled.div`
|
||||
margin: 0 30px;
|
||||
width: 65%;
|
||||
.CodeMirror {
|
||||
height: auto;
|
||||
min-height: 250px;
|
||||
|
|
|
|||
|
|
@ -121,7 +121,11 @@ const PropertyPaneTitle = memo((props: PropertyPaneTitleProps) => {
|
|||
const { title, updatePropertyTitle } = props;
|
||||
const updateNewTitle = useCallback(
|
||||
(value: string) => {
|
||||
if (value && value.trim().length > 0 && value.trim() !== title.trim()) {
|
||||
if (
|
||||
value &&
|
||||
value.trim().length > 0 &&
|
||||
value.trim() !== (title && title.trim())
|
||||
) {
|
||||
updatePropertyTitle && updatePropertyTitle(value.trim());
|
||||
}
|
||||
},
|
||||
|
|
@ -166,7 +170,9 @@ const PropertyPaneTitle = memo((props: PropertyPaneTitleProps) => {
|
|||
)}
|
||||
|
||||
<EditableText
|
||||
valueTransform={removeSpecialChars}
|
||||
valueTransform={
|
||||
!props.isPanelTitle ? removeSpecialChars : undefined
|
||||
}
|
||||
defaultValue={name}
|
||||
placeholder={props.title}
|
||||
editInteractionKind={EditInteractionKind.SINGLE}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,6 @@ import { TableWidgetProps } from "../../widgets/TableWidget/TableWidgetConstants
|
|||
import { DropdownWidgetProps } from "../../widgets/DropdownWidget";
|
||||
import { CheckboxWidgetProps } from "../../widgets/CheckboxWidget";
|
||||
import { RadioGroupWidgetProps } from "../../widgets/RadioGroupWidget";
|
||||
import { AlertWidgetProps } from "../../widgets/AlertWidget";
|
||||
import { FilePickerWidgetProps } from "../../widgets/FilepickerWidget";
|
||||
import {
|
||||
TabsWidgetProps,
|
||||
|
|
@ -67,7 +66,6 @@ export interface WidgetConfigReducerState {
|
|||
CHECKBOX_WIDGET: Partial<CheckboxWidgetProps> & WidgetConfigProps;
|
||||
SWITCH_WIDGET: Partial<SwitchWidgetProps> & WidgetConfigProps;
|
||||
RADIO_GROUP_WIDGET: Partial<RadioGroupWidgetProps> & WidgetConfigProps;
|
||||
ALERT_WIDGET: Partial<AlertWidgetProps> & WidgetConfigProps;
|
||||
FILE_PICKER_WIDGET: Partial<FilePickerWidgetProps> & WidgetConfigProps;
|
||||
TABS_WIDGET: Partial<TabsWidgetProps<TabContainerWidgetProps>> &
|
||||
WidgetConfigProps;
|
||||
|
|
|
|||
|
|
@ -110,7 +110,7 @@ export function* createActionSaga(
|
|||
payload = merge(initialValues, actionPayload.payload);
|
||||
}
|
||||
|
||||
const response: ActionCreateUpdateResponse = yield ActionAPI.createAPI(
|
||||
const response: ActionCreateUpdateResponse = yield ActionAPI.createAction(
|
||||
payload,
|
||||
);
|
||||
const isValidResponse = yield validateResponse(response);
|
||||
|
|
@ -267,7 +267,7 @@ export function* updateActionSaga(actionPayload: ReduxAction<{ id: string }>) {
|
|||
action = transformRestAction(action);
|
||||
}
|
||||
|
||||
const response: GenericApiResponse<Action> = yield ActionAPI.updateAPI(
|
||||
const response: GenericApiResponse<Action> = yield ActionAPI.updateAction(
|
||||
action,
|
||||
);
|
||||
const isValidResponse = yield validateResponse(response);
|
||||
|
|
@ -424,7 +424,7 @@ function* copyActionSaga(
|
|||
pageId: action.payload.destinationPageId,
|
||||
}) as Partial<Action>;
|
||||
delete copyAction.id;
|
||||
const response = yield ActionAPI.createAPI(copyAction);
|
||||
const response = yield ActionAPI.createAction(copyAction);
|
||||
const datasources = yield select(getDataSources);
|
||||
|
||||
const isValidResponse = yield validateResponse(response);
|
||||
|
|
@ -486,6 +486,7 @@ export function* refactorActionName(
|
|||
// call to refactor action
|
||||
const refactorResponse = yield ActionAPI.updateActionName({
|
||||
layoutId,
|
||||
actionId: id,
|
||||
pageId: pageId,
|
||||
oldName: oldName,
|
||||
newName: newName,
|
||||
|
|
|
|||
|
|
@ -508,12 +508,12 @@ function* handleApiNameChangeSuccessSaga(
|
|||
if (!actionObj) {
|
||||
// Error case, log to sentry
|
||||
Toaster.show({
|
||||
text: createMessage(ERROR_ACTION_RENAME_FAIL, actionObj.name),
|
||||
text: createMessage(ERROR_ACTION_RENAME_FAIL, ""),
|
||||
variant: Variant.danger,
|
||||
});
|
||||
|
||||
Sentry.captureException(
|
||||
new Error(createMessage(ERROR_ACTION_RENAME_FAIL, actionObj.name)),
|
||||
new Error(createMessage(ERROR_ACTION_RENAME_FAIL, "")),
|
||||
{
|
||||
extra: {
|
||||
actionId: actionId,
|
||||
|
|
|
|||
|
|
@ -33,6 +33,8 @@ import {
|
|||
expandDatasourceEntity,
|
||||
fetchDatasourceStructure,
|
||||
createDatasourceFromForm,
|
||||
updateDatasourceSuccess,
|
||||
UpdateDatasourceSuccessAction,
|
||||
} from "actions/datasourceActions";
|
||||
import { GenericApiResponse } from "api/ApiResponses";
|
||||
import DatasourcesApi, { CreateDatasourceConfig } from "api/DatasourcesApi";
|
||||
|
|
@ -162,10 +164,10 @@ function* updateDatasourceSaga(
|
|||
const datasourceStruture =
|
||||
state.entities.datasources.structure[response.data.id];
|
||||
|
||||
yield put({
|
||||
type: ReduxActionTypes.UPDATE_DATASOURCE_SUCCESS,
|
||||
payload: response.data,
|
||||
});
|
||||
// Dont redirect if action payload has an onSuccess
|
||||
yield put(
|
||||
updateDatasourceSuccess(response.data, !actionPayload.onSuccess),
|
||||
);
|
||||
if (actionPayload.onSuccess) {
|
||||
yield put(actionPayload.onSuccess);
|
||||
}
|
||||
|
|
@ -452,14 +454,15 @@ function* storeAsDatasourceSaga() {
|
|||
yield put(changeDatasource(createdDatasource));
|
||||
}
|
||||
|
||||
function* updateDatasourceSuccessSaga(action: ReduxAction<Datasource>) {
|
||||
function* updateDatasourceSuccessSaga(action: UpdateDatasourceSuccessAction) {
|
||||
const state = yield select();
|
||||
const actionRouteInfo = _.get(state, "ui.datasourcePane.actionRouteInfo");
|
||||
const updatedDatasource = action.payload;
|
||||
|
||||
if (
|
||||
actionRouteInfo &&
|
||||
updatedDatasource.id === actionRouteInfo.datasourceId
|
||||
updatedDatasource.id === actionRouteInfo.datasourceId &&
|
||||
action.redirect
|
||||
) {
|
||||
history.push(
|
||||
API_EDITOR_ID_URL(
|
||||
|
|
|
|||
|
|
@ -23,7 +23,6 @@ import {
|
|||
EvalErrorTypes,
|
||||
} from "utils/DynamicBindingUtils";
|
||||
import log from "loglevel";
|
||||
import { WidgetType } from "constants/WidgetConstants";
|
||||
import { WidgetProps } from "widgets/BaseWidget";
|
||||
import PerformanceTracker, {
|
||||
PerformanceTransactionName,
|
||||
|
|
@ -209,17 +208,17 @@ export function* clearEvalPropertyCacheOfWidget(widgetName: string) {
|
|||
}
|
||||
|
||||
export function* validateProperty(
|
||||
widgetType: WidgetType,
|
||||
property: string,
|
||||
value: any,
|
||||
props: WidgetProps,
|
||||
) {
|
||||
const unevalTree = yield select(getUnevaluatedDataTree);
|
||||
const validation = unevalTree[props.widgetName].validationPaths[property];
|
||||
return yield call(worker.request, EVAL_WORKER_ACTIONS.VALIDATE_PROPERTY, {
|
||||
widgetTypeConfigMap,
|
||||
widgetType,
|
||||
property,
|
||||
value,
|
||||
props,
|
||||
validation,
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -160,12 +160,12 @@ function* handleNameChangeSuccessSaga(
|
|||
if (!actionObj) {
|
||||
// Error case, log to sentry
|
||||
Toaster.show({
|
||||
text: createMessage(ERROR_ACTION_RENAME_FAIL, actionObj.name),
|
||||
text: createMessage(ERROR_ACTION_RENAME_FAIL, ""),
|
||||
variant: Variant.danger,
|
||||
});
|
||||
|
||||
Sentry.captureException(
|
||||
new Error(createMessage(ERROR_ACTION_RENAME_FAIL, actionObj.name)),
|
||||
new Error(createMessage(ERROR_ACTION_RENAME_FAIL, "")),
|
||||
{
|
||||
extra: {
|
||||
actionId: actionId,
|
||||
|
|
|
|||
|
|
@ -817,7 +817,6 @@ function* setWidgetDynamicPropertySaga(
|
|||
});
|
||||
const { parsed } = yield call(
|
||||
validateProperty,
|
||||
widget.type,
|
||||
propertyPath,
|
||||
propertyValue,
|
||||
widget,
|
||||
|
|
|
|||
|
|
@ -262,6 +262,7 @@ const createLoadingWidget = (
|
|||
ENTITY_TYPE: ENTITY_TYPE.WIDGET,
|
||||
bindingPaths: {},
|
||||
triggerPaths: {},
|
||||
validationPaths: {},
|
||||
isLoading: true,
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -5,10 +5,6 @@ import {
|
|||
WidgetDataProps,
|
||||
WidgetState,
|
||||
} from "widgets/BaseWidget";
|
||||
import {
|
||||
WidgetPropertyValidationType,
|
||||
BASE_WIDGET_VALIDATION,
|
||||
} from "./WidgetValidation";
|
||||
import React from "react";
|
||||
import {
|
||||
PropertyPaneConfig,
|
||||
|
|
@ -49,10 +45,6 @@ class WidgetFactory {
|
|||
WidgetType,
|
||||
WidgetBuilder<WidgetProps, WidgetState>
|
||||
> = new Map();
|
||||
static widgetPropValidationMap: Map<
|
||||
WidgetType,
|
||||
WidgetPropertyValidationType
|
||||
> = new Map();
|
||||
static widgetDerivedPropertiesGetterMap: Map<
|
||||
WidgetType,
|
||||
WidgetDerivedPropertyType
|
||||
|
|
@ -74,14 +66,12 @@ class WidgetFactory {
|
|||
static registerWidgetBuilder(
|
||||
widgetType: WidgetType,
|
||||
widgetBuilder: WidgetBuilder<WidgetProps, WidgetState>,
|
||||
widgetPropertyValidation: WidgetPropertyValidationType,
|
||||
derivedPropertiesMap: DerivedPropertiesMap,
|
||||
defaultPropertiesMap: Record<string, string>,
|
||||
metaPropertiesMap: Record<string, any>,
|
||||
propertyPaneConfig?: PropertyPaneConfig[],
|
||||
) {
|
||||
this.widgetMap.set(widgetType, widgetBuilder);
|
||||
this.widgetPropValidationMap.set(widgetType, widgetPropertyValidation);
|
||||
this.derivedPropertiesMap.set(widgetType, derivedPropertiesMap);
|
||||
this.defaultPropertiesMap.set(widgetType, defaultPropertiesMap);
|
||||
this.metaPropertiesMap.set(widgetType, metaPropertiesMap);
|
||||
|
|
@ -122,17 +112,6 @@ class WidgetFactory {
|
|||
return Array.from(this.widgetMap.keys());
|
||||
}
|
||||
|
||||
static getWidgetPropertyValidationMap(
|
||||
widgetType: WidgetType,
|
||||
): WidgetPropertyValidationType {
|
||||
const map = this.widgetPropValidationMap.get(widgetType);
|
||||
if (!map) {
|
||||
console.error("Widget type validation is not defined");
|
||||
return BASE_WIDGET_VALIDATION;
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
static getWidgetDerivedPropertiesMap(
|
||||
widgetType: WidgetType,
|
||||
): DerivedPropertiesMap {
|
||||
|
|
@ -181,7 +160,6 @@ class WidgetFactory {
|
|||
const typeConfigMap: WidgetTypeConfigMap = {};
|
||||
WidgetFactory.getWidgetTypes().forEach((type) => {
|
||||
typeConfigMap[type] = {
|
||||
validations: WidgetFactory.getWidgetPropertyValidationMap(type),
|
||||
defaultProperties: WidgetFactory.getWidgetDefaultPropertiesMap(type),
|
||||
derivedProperties: WidgetFactory.getWidgetDerivedPropertiesMap(type),
|
||||
metaProperties: WidgetFactory.getWidgetMetaPropertiesMap(type),
|
||||
|
|
@ -194,7 +172,6 @@ class WidgetFactory {
|
|||
export type WidgetTypeConfigMap = Record<
|
||||
string,
|
||||
{
|
||||
validations: WidgetPropertyValidationType;
|
||||
derivedProperties: WidgetDerivedPropertyType;
|
||||
defaultProperties: Record<string, string>;
|
||||
metaProperties: Record<string, any>;
|
||||
|
|
|
|||
|
|
@ -105,7 +105,6 @@ export default class WidgetBuilderRegistry {
|
|||
return <ProfiledContainerWidget {...widgetData} />;
|
||||
},
|
||||
},
|
||||
ContainerWidget.getPropertyValidationMap(),
|
||||
ContainerWidget.getDerivedPropertiesMap(),
|
||||
ContainerWidget.getDefaultPropertiesMap(),
|
||||
ContainerWidget.getMetaPropertiesMap(),
|
||||
|
|
@ -119,7 +118,6 @@ export default class WidgetBuilderRegistry {
|
|||
return <ProfiledTextWidget {...widgetData} />;
|
||||
},
|
||||
},
|
||||
TextWidget.getPropertyValidationMap(),
|
||||
TextWidget.getDerivedPropertiesMap(),
|
||||
TextWidget.getDefaultPropertiesMap(),
|
||||
TextWidget.getMetaPropertiesMap(),
|
||||
|
|
@ -133,7 +131,6 @@ export default class WidgetBuilderRegistry {
|
|||
return <ProfiledButtonWidget {...widgetData} />;
|
||||
},
|
||||
},
|
||||
ButtonWidget.getPropertyValidationMap(),
|
||||
ButtonWidget.getDerivedPropertiesMap(),
|
||||
ButtonWidget.getDefaultPropertiesMap(),
|
||||
ButtonWidget.getMetaPropertiesMap(),
|
||||
|
|
@ -147,7 +144,6 @@ export default class WidgetBuilderRegistry {
|
|||
return <ProfiledInputWidget {...widgetData} />;
|
||||
},
|
||||
},
|
||||
InputWidget.getPropertyValidationMap(),
|
||||
InputWidget.getDerivedPropertiesMap(),
|
||||
InputWidget.getDefaultPropertiesMap(),
|
||||
InputWidget.getMetaPropertiesMap(),
|
||||
|
|
@ -161,7 +157,6 @@ export default class WidgetBuilderRegistry {
|
|||
return <ProfiledCheckboxWidget {...widgetData} />;
|
||||
},
|
||||
},
|
||||
CheckboxWidget.getPropertyValidationMap(),
|
||||
CheckboxWidget.getDerivedPropertiesMap(),
|
||||
CheckboxWidget.getDefaultPropertiesMap(),
|
||||
CheckboxWidget.getMetaPropertiesMap(),
|
||||
|
|
@ -175,7 +170,6 @@ export default class WidgetBuilderRegistry {
|
|||
return <ProfiledSwitchWidget {...widgetData} />;
|
||||
},
|
||||
},
|
||||
SwitchWidget.getPropertyValidationMap(),
|
||||
SwitchWidget.getDerivedPropertiesMap(),
|
||||
SwitchWidget.getDefaultPropertiesMap(),
|
||||
SwitchWidget.getMetaPropertiesMap(),
|
||||
|
|
@ -189,7 +183,6 @@ export default class WidgetBuilderRegistry {
|
|||
return <ProfiledDropDownWidget {...widgetData} />;
|
||||
},
|
||||
},
|
||||
DropdownWidget.getPropertyValidationMap(),
|
||||
DropdownWidget.getDerivedPropertiesMap(),
|
||||
DropdownWidget.getDefaultPropertiesMap(),
|
||||
DropdownWidget.getMetaPropertiesMap(),
|
||||
|
|
@ -203,7 +196,6 @@ export default class WidgetBuilderRegistry {
|
|||
return <ProfiledRadioGroupWidget {...widgetData} />;
|
||||
},
|
||||
},
|
||||
RadioGroupWidget.getPropertyValidationMap(),
|
||||
RadioGroupWidget.getDerivedPropertiesMap(),
|
||||
RadioGroupWidget.getDefaultPropertiesMap(),
|
||||
RadioGroupWidget.getMetaPropertiesMap(),
|
||||
|
|
@ -217,7 +209,6 @@ export default class WidgetBuilderRegistry {
|
|||
return <ProfiledImageWidget {...widgetData} />;
|
||||
},
|
||||
},
|
||||
ImageWidget.getPropertyValidationMap(),
|
||||
ImageWidget.getDerivedPropertiesMap(),
|
||||
ImageWidget.getDefaultPropertiesMap(),
|
||||
ImageWidget.getMetaPropertiesMap(),
|
||||
|
|
@ -230,7 +221,6 @@ export default class WidgetBuilderRegistry {
|
|||
return <ProfiledTableWidget {...widgetData} />;
|
||||
},
|
||||
},
|
||||
TableWidget.getPropertyValidationMap(),
|
||||
TableWidget.getDerivedPropertiesMap(),
|
||||
TableWidget.getDefaultPropertiesMap(),
|
||||
TableWidget.getMetaPropertiesMap(),
|
||||
|
|
@ -244,7 +234,6 @@ export default class WidgetBuilderRegistry {
|
|||
return <ProfiledVideoWidget {...widgetData} />;
|
||||
},
|
||||
},
|
||||
VideoWidget.getPropertyValidationMap(),
|
||||
VideoWidget.getDerivedPropertiesMap(),
|
||||
VideoWidget.getDefaultPropertiesMap(),
|
||||
VideoWidget.getMetaPropertiesMap(),
|
||||
|
|
@ -258,7 +247,6 @@ export default class WidgetBuilderRegistry {
|
|||
return <ProfiledFilePickerWidget {...widgetData} />;
|
||||
},
|
||||
},
|
||||
FilePickerWidget.getPropertyValidationMap(),
|
||||
FilePickerWidget.getDerivedPropertiesMap(),
|
||||
FilePickerWidget.getDefaultPropertiesMap(),
|
||||
FilePickerWidget.getMetaPropertiesMap(),
|
||||
|
|
@ -271,7 +259,6 @@ export default class WidgetBuilderRegistry {
|
|||
return <ProfiledDatePickerWidget {...widgetData} />;
|
||||
},
|
||||
},
|
||||
DatePickerWidget.getPropertyValidationMap(),
|
||||
DatePickerWidget.getDerivedPropertiesMap(),
|
||||
DatePickerWidget.getDefaultPropertiesMap(),
|
||||
DatePickerWidget.getMetaPropertiesMap(),
|
||||
|
|
@ -284,7 +271,6 @@ export default class WidgetBuilderRegistry {
|
|||
return <ProfiledDatePickerWidget2 {...widgetData} />;
|
||||
},
|
||||
},
|
||||
DatePickerWidget2.getPropertyValidationMap(),
|
||||
DatePickerWidget2.getDerivedPropertiesMap(),
|
||||
DatePickerWidget2.getDefaultPropertiesMap(),
|
||||
DatePickerWidget2.getMetaPropertiesMap(),
|
||||
|
|
@ -299,7 +285,6 @@ export default class WidgetBuilderRegistry {
|
|||
return <ProfiledTabsWidget {...widgetProps} />;
|
||||
},
|
||||
},
|
||||
TabsWidget.getPropertyValidationMap(),
|
||||
TabsWidget.getDerivedPropertiesMap(),
|
||||
TabsWidget.getDefaultPropertiesMap(),
|
||||
TabsWidget.getMetaPropertiesMap(),
|
||||
|
|
@ -312,7 +297,6 @@ export default class WidgetBuilderRegistry {
|
|||
return <ProfiledModalWidget {...widgetProps} />;
|
||||
},
|
||||
},
|
||||
BaseWidget.getPropertyValidationMap(),
|
||||
BaseWidget.getDerivedPropertiesMap(),
|
||||
BaseWidget.getDefaultPropertiesMap(),
|
||||
BaseWidget.getMetaPropertiesMap(),
|
||||
|
|
@ -325,7 +309,6 @@ export default class WidgetBuilderRegistry {
|
|||
return <ProfiledRichTextEditorWidget {...widgetData} />;
|
||||
},
|
||||
},
|
||||
RichTextEditorWidget.getPropertyValidationMap(),
|
||||
RichTextEditorWidget.getDerivedPropertiesMap(),
|
||||
RichTextEditorWidget.getDefaultPropertiesMap(),
|
||||
RichTextEditorWidget.getMetaPropertiesMap(),
|
||||
|
|
@ -338,7 +321,6 @@ export default class WidgetBuilderRegistry {
|
|||
return <ProfiledChartWidget {...widgetData} />;
|
||||
},
|
||||
},
|
||||
ChartWidget.getPropertyValidationMap(),
|
||||
ChartWidget.getDerivedPropertiesMap(),
|
||||
ChartWidget.getDefaultPropertiesMap(),
|
||||
ChartWidget.getMetaPropertiesMap(),
|
||||
|
|
@ -353,7 +335,6 @@ export default class WidgetBuilderRegistry {
|
|||
return <ProfiledFormWidget {...widgetProps} />;
|
||||
},
|
||||
},
|
||||
FormWidget.getPropertyValidationMap(),
|
||||
FormWidget.getDerivedPropertiesMap(),
|
||||
FormWidget.getDefaultPropertiesMap(),
|
||||
FormWidget.getMetaPropertiesMap(),
|
||||
|
|
@ -367,7 +348,6 @@ export default class WidgetBuilderRegistry {
|
|||
return <ProfiledFormButtonWidget {...widgetProps} />;
|
||||
},
|
||||
},
|
||||
FormButtonWidget.getPropertyValidationMap(),
|
||||
FormButtonWidget.getDerivedPropertiesMap(),
|
||||
FormButtonWidget.getDefaultPropertiesMap(),
|
||||
FormButtonWidget.getMetaPropertiesMap(),
|
||||
|
|
@ -381,7 +361,6 @@ export default class WidgetBuilderRegistry {
|
|||
return <ProfiledMapWidget {...widgetProps} />;
|
||||
},
|
||||
},
|
||||
MapWidget.getPropertyValidationMap(),
|
||||
MapWidget.getDerivedPropertiesMap(),
|
||||
MapWidget.getDefaultPropertiesMap(),
|
||||
MapWidget.getMetaPropertiesMap(),
|
||||
|
|
@ -397,7 +376,6 @@ export default class WidgetBuilderRegistry {
|
|||
return <ProfiledCanvasWidget {...widgetData} />;
|
||||
},
|
||||
},
|
||||
CanvasWidget.getPropertyValidationMap(),
|
||||
CanvasWidget.getDerivedPropertiesMap(),
|
||||
CanvasWidget.getDefaultPropertiesMap(),
|
||||
CanvasWidget.getMetaPropertiesMap(),
|
||||
|
|
@ -411,7 +389,6 @@ export default class WidgetBuilderRegistry {
|
|||
return <ProfiledIconWidget {...widgetProps} />;
|
||||
},
|
||||
},
|
||||
IconWidget.getPropertyValidationMap(),
|
||||
IconWidget.getDerivedPropertiesMap(),
|
||||
IconWidget.getDefaultPropertiesMap(),
|
||||
IconWidget.getMetaPropertiesMap(),
|
||||
|
|
@ -425,7 +402,6 @@ export default class WidgetBuilderRegistry {
|
|||
return <ProfiledSkeletonWidget {...widgetProps} />;
|
||||
},
|
||||
},
|
||||
SkeletonWidget.getPropertyValidationMap(),
|
||||
SkeletonWidget.getDerivedPropertiesMap(),
|
||||
SkeletonWidget.getDefaultPropertiesMap(),
|
||||
SkeletonWidget.getMetaPropertiesMap(),
|
||||
|
|
@ -439,7 +415,6 @@ export default class WidgetBuilderRegistry {
|
|||
return <ProfiledModalWidget {...widgetData} />;
|
||||
},
|
||||
},
|
||||
ModalWidget.getPropertyValidationMap(),
|
||||
ModalWidget.getDerivedPropertiesMap(),
|
||||
ModalWidget.getDefaultPropertiesMap(),
|
||||
ModalWidget.getMetaPropertiesMap(),
|
||||
|
|
|
|||
|
|
@ -1,16 +0,0 @@
|
|||
import {
|
||||
VALIDATION_TYPES,
|
||||
ValidationType,
|
||||
Validator,
|
||||
} from "constants/WidgetValidation";
|
||||
|
||||
export const BASE_WIDGET_VALIDATION = {
|
||||
isLoading: VALIDATION_TYPES.BOOLEAN,
|
||||
isVisible: VALIDATION_TYPES.BOOLEAN,
|
||||
isDisabled: VALIDATION_TYPES.BOOLEAN,
|
||||
};
|
||||
|
||||
export type WidgetPropertyValidationType = Record<
|
||||
string,
|
||||
ValidationType | Validator
|
||||
>;
|
||||
|
|
@ -31,6 +31,7 @@ describe("dataTreeTypeDefCreator", () => {
|
|||
triggerPaths: {
|
||||
onTextChange: true,
|
||||
},
|
||||
validationPaths: {},
|
||||
},
|
||||
};
|
||||
const def = dataTreeTypeDefCreator(dataTree);
|
||||
|
|
|
|||
|
|
@ -1,20 +0,0 @@
|
|||
import React, { Component } from "react";
|
||||
import { WidgetProps } from "./BaseWidget";
|
||||
|
||||
class AlertWidget extends Component {
|
||||
getPageView() {
|
||||
return <div />;
|
||||
}
|
||||
}
|
||||
|
||||
export type AlertType = "DIALOG" | "NOTIFICATION";
|
||||
export type MessageIntent = "SUCCESS" | "ERROR" | "INFO" | "WARNING";
|
||||
|
||||
export interface AlertWidgetProps extends WidgetProps {
|
||||
alertType: AlertType;
|
||||
intent: MessageIntent;
|
||||
header: string;
|
||||
message: string;
|
||||
}
|
||||
|
||||
export default AlertWidget;
|
||||
|
|
@ -24,10 +24,6 @@ import shallowequal from "shallowequal";
|
|||
import { PositionTypes } from "constants/WidgetConstants";
|
||||
import { EditorContext } from "components/editorComponents/EditorContextProvider";
|
||||
import ErrorBoundary from "components/editorComponents/ErrorBoundry";
|
||||
import {
|
||||
BASE_WIDGET_VALIDATION,
|
||||
WidgetPropertyValidationType,
|
||||
} from "utils/WidgetValidation";
|
||||
import { DerivedPropertiesMap } from "utils/WidgetFactory";
|
||||
import {
|
||||
WidgetDynamicPathListProps,
|
||||
|
|
@ -57,11 +53,6 @@ abstract class BaseWidget<
|
|||
static getPropertyPaneConfig(): PropertyPaneConfig[] {
|
||||
return [];
|
||||
}
|
||||
// Needed to send a default no validation option. In case a widget needs
|
||||
// validation implement this in the widget class again
|
||||
static getPropertyValidationMap(): WidgetPropertyValidationType {
|
||||
return BASE_WIDGET_VALIDATION;
|
||||
}
|
||||
|
||||
static getDerivedPropertiesMap(): DerivedPropertiesMap {
|
||||
return {};
|
||||
|
|
|
|||
|
|
@ -5,10 +5,6 @@ import ButtonComponent, {
|
|||
ButtonType,
|
||||
} from "components/designSystems/blueprint/ButtonComponent";
|
||||
import { EventType } from "constants/AppsmithActionConstants/ActionConstants";
|
||||
import {
|
||||
WidgetPropertyValidationType,
|
||||
BASE_WIDGET_VALIDATION,
|
||||
} from "utils/WidgetValidation";
|
||||
import { VALIDATION_TYPES } from "constants/WidgetValidation";
|
||||
import * as Sentry from "@sentry/react";
|
||||
import withMeta, { WithMeta } from "./MetaHOC";
|
||||
|
|
@ -38,6 +34,7 @@ class ButtonWidget extends BaseWidget<ButtonWidgetProps, ButtonWidgetState> {
|
|||
placeholderText: "Enter label text",
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: VALIDATION_TYPES.TEXT,
|
||||
},
|
||||
{
|
||||
propertyName: "buttonStyle",
|
||||
|
|
@ -69,6 +66,7 @@ class ButtonWidget extends BaseWidget<ButtonWidgetProps, ButtonWidgetState> {
|
|||
isJSConvertible: true,
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: VALIDATION_TYPES.BOOLEAN,
|
||||
},
|
||||
{
|
||||
propertyName: "isDisabled",
|
||||
|
|
@ -78,6 +76,7 @@ class ButtonWidget extends BaseWidget<ButtonWidgetProps, ButtonWidgetState> {
|
|||
isJSConvertible: true,
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: VALIDATION_TYPES.BOOLEAN,
|
||||
},
|
||||
{
|
||||
propertyName: "googleRecaptchaKey",
|
||||
|
|
@ -87,6 +86,7 @@ class ButtonWidget extends BaseWidget<ButtonWidgetProps, ButtonWidgetState> {
|
|||
placeholderText: "Enter google recaptcha key",
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: VALIDATION_TYPES.TEXT,
|
||||
},
|
||||
],
|
||||
},
|
||||
|
|
@ -107,14 +107,6 @@ class ButtonWidget extends BaseWidget<ButtonWidgetProps, ButtonWidgetState> {
|
|||
];
|
||||
}
|
||||
|
||||
static getPropertyValidationMap(): WidgetPropertyValidationType {
|
||||
return {
|
||||
...BASE_WIDGET_VALIDATION,
|
||||
text: VALIDATION_TYPES.TEXT,
|
||||
buttonStyle: VALIDATION_TYPES.TEXT,
|
||||
// onClick: VALIDATION_TYPES.ACTION_SELECTOR,
|
||||
};
|
||||
}
|
||||
static getMetaPropertiesMap(): Record<string, any> {
|
||||
return {
|
||||
recaptchaToken: undefined,
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
import React, { lazy, Suspense } from "react";
|
||||
import BaseWidget, { WidgetProps, WidgetState } from "widgets/BaseWidget";
|
||||
import { WidgetType } from "constants/WidgetConstants";
|
||||
import { WidgetPropertyValidationType } from "utils/WidgetValidation";
|
||||
import { VALIDATION_TYPES } from "constants/WidgetValidation";
|
||||
import Skeleton from "components/utils/Skeleton";
|
||||
import * as Sentry from "@sentry/react";
|
||||
import { retryPromise } from "utils/AppsmithUtils";
|
||||
|
|
@ -20,17 +18,6 @@ const ChartComponent = lazy(() =>
|
|||
);
|
||||
|
||||
class ChartWidget extends BaseWidget<ChartWidgetProps, WidgetState> {
|
||||
static getPropertyValidationMap(): WidgetPropertyValidationType {
|
||||
return {
|
||||
xAxisName: VALIDATION_TYPES.TEXT,
|
||||
yAxisName: VALIDATION_TYPES.TEXT,
|
||||
chartName: VALIDATION_TYPES.TEXT,
|
||||
isVisible: VALIDATION_TYPES.BOOLEAN,
|
||||
chartData: VALIDATION_TYPES.CHART_DATA,
|
||||
customFusionChartConfig: VALIDATION_TYPES.CUSTOM_FUSION_CHARTS_DATA,
|
||||
};
|
||||
}
|
||||
|
||||
static getMetaPropertiesMap(): Record<string, undefined> {
|
||||
return {
|
||||
selectedDataPoint: undefined,
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import { ChartWidgetProps } from "widgets/ChartWidget";
|
||||
import { VALIDATION_TYPES } from "constants/WidgetValidation";
|
||||
|
||||
export default [
|
||||
{
|
||||
|
|
@ -12,6 +13,7 @@ export default [
|
|||
controlType: "INPUT_TEXT",
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: VALIDATION_TYPES.TEXT,
|
||||
},
|
||||
{
|
||||
helpText: "Changes the visualisation of the chart data",
|
||||
|
|
@ -56,6 +58,7 @@ export default [
|
|||
isJSConvertible: true,
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: VALIDATION_TYPES.BOOLEAN,
|
||||
},
|
||||
],
|
||||
},
|
||||
|
|
@ -69,6 +72,7 @@ export default [
|
|||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
hidden: (x: any) => x.chartType !== "CUSTOM_FUSION_CHART",
|
||||
validation: VALIDATION_TYPES.CUSTOM_FUSION_CHARTS_DATA,
|
||||
},
|
||||
{
|
||||
sectionName: "Chart Data",
|
||||
|
|
@ -92,6 +96,7 @@ export default [
|
|||
controlType: "INPUT_TEXT",
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: VALIDATION_TYPES.TEXT,
|
||||
},
|
||||
{
|
||||
helpText: "Series data",
|
||||
|
|
@ -100,6 +105,7 @@ export default [
|
|||
controlType: "INPUT_TEXT_AREA",
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: VALIDATION_TYPES.CHART_DATA,
|
||||
},
|
||||
],
|
||||
},
|
||||
|
|
@ -118,6 +124,7 @@ export default [
|
|||
controlType: "INPUT_TEXT",
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: VALIDATION_TYPES.TEXT,
|
||||
},
|
||||
{
|
||||
helpText: "Specifies the label of the y-axis",
|
||||
|
|
@ -127,6 +134,7 @@ export default [
|
|||
controlType: "INPUT_TEXT",
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: VALIDATION_TYPES.TEXT,
|
||||
},
|
||||
{
|
||||
helpText: "Enables scrolling inside the chart",
|
||||
|
|
|
|||
|
|
@ -4,10 +4,6 @@ import { WidgetType } from "constants/WidgetConstants";
|
|||
import CheckboxComponent from "components/designSystems/blueprint/CheckboxComponent";
|
||||
import { EventType } from "constants/AppsmithActionConstants/ActionConstants";
|
||||
import { VALIDATION_TYPES } from "constants/WidgetValidation";
|
||||
import {
|
||||
WidgetPropertyValidationType,
|
||||
BASE_WIDGET_VALIDATION,
|
||||
} from "utils/WidgetValidation";
|
||||
import { DerivedPropertiesMap } from "utils/WidgetFactory";
|
||||
import * as Sentry from "@sentry/react";
|
||||
import withMeta, { WithMeta } from "./MetaHOC";
|
||||
|
|
@ -27,6 +23,7 @@ class CheckboxWidget extends BaseWidget<CheckboxWidgetProps, WidgetState> {
|
|||
placeholderText: "Enter label text",
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: VALIDATION_TYPES.TEXT,
|
||||
},
|
||||
{
|
||||
propertyName: "alignWidget",
|
||||
|
|
@ -55,6 +52,7 @@ class CheckboxWidget extends BaseWidget<CheckboxWidgetProps, WidgetState> {
|
|||
isJSConvertible: true,
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: VALIDATION_TYPES.BOOLEAN,
|
||||
},
|
||||
{
|
||||
propertyName: "isRequired",
|
||||
|
|
@ -64,6 +62,7 @@ class CheckboxWidget extends BaseWidget<CheckboxWidgetProps, WidgetState> {
|
|||
isJSConvertible: true,
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: VALIDATION_TYPES.BOOLEAN,
|
||||
},
|
||||
{
|
||||
propertyName: "isVisible",
|
||||
|
|
@ -73,6 +72,7 @@ class CheckboxWidget extends BaseWidget<CheckboxWidgetProps, WidgetState> {
|
|||
isJSConvertible: true,
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: VALIDATION_TYPES.BOOLEAN,
|
||||
},
|
||||
{
|
||||
propertyName: "isDisabled",
|
||||
|
|
@ -82,6 +82,7 @@ class CheckboxWidget extends BaseWidget<CheckboxWidgetProps, WidgetState> {
|
|||
isJSConvertible: true,
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: VALIDATION_TYPES.BOOLEAN,
|
||||
},
|
||||
],
|
||||
},
|
||||
|
|
@ -101,14 +102,6 @@ class CheckboxWidget extends BaseWidget<CheckboxWidgetProps, WidgetState> {
|
|||
},
|
||||
];
|
||||
}
|
||||
static getPropertyValidationMap(): WidgetPropertyValidationType {
|
||||
return {
|
||||
...BASE_WIDGET_VALIDATION,
|
||||
label: VALIDATION_TYPES.TEXT,
|
||||
defaultCheckedState: VALIDATION_TYPES.BOOLEAN,
|
||||
// onCheckChange: VALIDATION_TYPES.ACTION_SELECTOR,
|
||||
};
|
||||
}
|
||||
|
||||
static getDefaultPropertiesMap(): Record<string, string> {
|
||||
return {
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ import {
|
|||
|
||||
import BaseWidget, { WidgetProps, WidgetState } from "./BaseWidget";
|
||||
import * as Sentry from "@sentry/react";
|
||||
import { VALIDATION_TYPES } from "constants/WidgetValidation";
|
||||
|
||||
class ContainerWidget extends BaseWidget<
|
||||
ContainerWidgetProps<WidgetProps>,
|
||||
|
|
@ -37,6 +38,7 @@ class ContainerWidget extends BaseWidget<
|
|||
controlType: "INPUT_TEXT",
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: VALIDATION_TYPES.TEXT,
|
||||
},
|
||||
{
|
||||
helpText: "Controls the visibility of the widget",
|
||||
|
|
@ -46,6 +48,7 @@ class ContainerWidget extends BaseWidget<
|
|||
isJSConvertible: true,
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: VALIDATION_TYPES.BOOLEAN,
|
||||
},
|
||||
{
|
||||
propertyName: "shouldScrollContents",
|
||||
|
|
|
|||
|
|
@ -3,10 +3,6 @@ import BaseWidget, { WidgetProps, WidgetState } from "./BaseWidget";
|
|||
import { WidgetType } from "constants/WidgetConstants";
|
||||
import { EventType } from "constants/AppsmithActionConstants/ActionConstants";
|
||||
import DatePickerComponent from "components/designSystems/blueprint/DatePickerComponent";
|
||||
import {
|
||||
WidgetPropertyValidationType,
|
||||
BASE_WIDGET_VALIDATION,
|
||||
} from "utils/WidgetValidation";
|
||||
import { VALIDATION_TYPES } from "constants/WidgetValidation";
|
||||
import { DerivedPropertiesMap } from "utils/WidgetFactory";
|
||||
import * as Sentry from "@sentry/react";
|
||||
|
|
@ -29,6 +25,7 @@ class DatePickerWidget extends BaseWidget<DatePickerWidgetProps, WidgetState> {
|
|||
isJSConvertible: true,
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: VALIDATION_TYPES.DEFAULT_DATE,
|
||||
},
|
||||
{
|
||||
helpText: "Sets the format of the selected date",
|
||||
|
|
@ -60,6 +57,7 @@ class DatePickerWidget extends BaseWidget<DatePickerWidgetProps, WidgetState> {
|
|||
],
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
dateFormat: VALIDATION_TYPES.TEXT,
|
||||
},
|
||||
{
|
||||
propertyName: "isRequired",
|
||||
|
|
@ -69,6 +67,7 @@ class DatePickerWidget extends BaseWidget<DatePickerWidgetProps, WidgetState> {
|
|||
isJSConvertible: true,
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: VALIDATION_TYPES.BOOLEAN,
|
||||
},
|
||||
{
|
||||
propertyName: "isVisible",
|
||||
|
|
@ -78,6 +77,7 @@ class DatePickerWidget extends BaseWidget<DatePickerWidgetProps, WidgetState> {
|
|||
isJSConvertible: true,
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: VALIDATION_TYPES.BOOLEAN,
|
||||
},
|
||||
{
|
||||
propertyName: "isDisabled",
|
||||
|
|
@ -87,6 +87,7 @@ class DatePickerWidget extends BaseWidget<DatePickerWidgetProps, WidgetState> {
|
|||
isJSConvertible: true,
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: VALIDATION_TYPES.BOOLEAN,
|
||||
},
|
||||
{
|
||||
propertyName: "minDate",
|
||||
|
|
@ -96,6 +97,7 @@ class DatePickerWidget extends BaseWidget<DatePickerWidgetProps, WidgetState> {
|
|||
isJSConvertible: true,
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: VALIDATION_TYPES.MIN_DATE,
|
||||
},
|
||||
{
|
||||
propertyName: "maxDate",
|
||||
|
|
@ -105,6 +107,7 @@ class DatePickerWidget extends BaseWidget<DatePickerWidgetProps, WidgetState> {
|
|||
isJSConvertible: true,
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: VALIDATION_TYPES.MAX_DATE,
|
||||
},
|
||||
],
|
||||
},
|
||||
|
|
@ -123,22 +126,6 @@ class DatePickerWidget extends BaseWidget<DatePickerWidgetProps, WidgetState> {
|
|||
},
|
||||
];
|
||||
}
|
||||
static getPropertyValidationMap(): WidgetPropertyValidationType {
|
||||
return {
|
||||
...BASE_WIDGET_VALIDATION,
|
||||
defaultDate: VALIDATION_TYPES.DEFAULT_DATE,
|
||||
timezone: VALIDATION_TYPES.TEXT,
|
||||
enableTimePicker: VALIDATION_TYPES.BOOLEAN,
|
||||
dateFormat: VALIDATION_TYPES.TEXT,
|
||||
label: VALIDATION_TYPES.TEXT,
|
||||
datePickerType: VALIDATION_TYPES.TEXT,
|
||||
maxDate: VALIDATION_TYPES.MAX_DATE,
|
||||
minDate: VALIDATION_TYPES.MIN_DATE,
|
||||
isRequired: VALIDATION_TYPES.BOOLEAN,
|
||||
// onDateSelected: VALIDATION_TYPES.ACTION_SELECTOR,
|
||||
// onDateRangeSelected: VALIDATION_TYPES.ACTION_SELECTOR,
|
||||
};
|
||||
}
|
||||
|
||||
static getDerivedPropertiesMap(): DerivedPropertiesMap {
|
||||
return {
|
||||
|
|
|
|||
|
|
@ -3,10 +3,6 @@ import BaseWidget, { WidgetProps, WidgetState } from "./BaseWidget";
|
|||
import { WidgetType } from "constants/WidgetConstants";
|
||||
import { EventType } from "constants/AppsmithActionConstants/ActionConstants";
|
||||
import DatePickerComponent from "components/designSystems/blueprint/DatePickerComponent2";
|
||||
import {
|
||||
WidgetPropertyValidationType,
|
||||
BASE_WIDGET_VALIDATION,
|
||||
} from "utils/WidgetValidation";
|
||||
import { VALIDATION_TYPES } from "constants/WidgetValidation";
|
||||
import { DerivedPropertiesMap } from "utils/WidgetFactory";
|
||||
import * as Sentry from "@sentry/react";
|
||||
|
|
@ -30,6 +26,7 @@ class DatePickerWidget extends BaseWidget<DatePickerWidget2Props, WidgetState> {
|
|||
isJSConvertible: true,
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: VALIDATION_TYPES.DEFAULT_DATE,
|
||||
},
|
||||
{
|
||||
helpText: "Sets the format of the selected date",
|
||||
|
|
@ -122,6 +119,7 @@ class DatePickerWidget extends BaseWidget<DatePickerWidget2Props, WidgetState> {
|
|||
],
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: VALIDATION_TYPES.TEXT,
|
||||
},
|
||||
{
|
||||
propertyName: "isRequired",
|
||||
|
|
@ -131,6 +129,7 @@ class DatePickerWidget extends BaseWidget<DatePickerWidget2Props, WidgetState> {
|
|||
isJSConvertible: true,
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: VALIDATION_TYPES.BOOLEAN,
|
||||
},
|
||||
{
|
||||
propertyName: "isVisible",
|
||||
|
|
@ -140,6 +139,7 @@ class DatePickerWidget extends BaseWidget<DatePickerWidget2Props, WidgetState> {
|
|||
isJSConvertible: true,
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: VALIDATION_TYPES.BOOLEAN,
|
||||
},
|
||||
{
|
||||
propertyName: "isDisabled",
|
||||
|
|
@ -149,6 +149,7 @@ class DatePickerWidget extends BaseWidget<DatePickerWidget2Props, WidgetState> {
|
|||
isJSConvertible: true,
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: VALIDATION_TYPES.BOOLEAN,
|
||||
},
|
||||
{
|
||||
propertyName: "minDate",
|
||||
|
|
@ -159,6 +160,7 @@ class DatePickerWidget extends BaseWidget<DatePickerWidget2Props, WidgetState> {
|
|||
isJSConvertible: true,
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: VALIDATION_TYPES.DATE_ISO_STRING,
|
||||
},
|
||||
{
|
||||
propertyName: "maxDate",
|
||||
|
|
@ -169,6 +171,7 @@ class DatePickerWidget extends BaseWidget<DatePickerWidget2Props, WidgetState> {
|
|||
isJSConvertible: true,
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: VALIDATION_TYPES.DATE_ISO_STRING,
|
||||
},
|
||||
],
|
||||
},
|
||||
|
|
@ -188,23 +191,6 @@ class DatePickerWidget extends BaseWidget<DatePickerWidget2Props, WidgetState> {
|
|||
];
|
||||
}
|
||||
|
||||
static getPropertyValidationMap(): WidgetPropertyValidationType {
|
||||
return {
|
||||
...BASE_WIDGET_VALIDATION,
|
||||
defaultDate: VALIDATION_TYPES.DEFAULT_DATE,
|
||||
timezone: VALIDATION_TYPES.TEXT,
|
||||
enableTimePicker: VALIDATION_TYPES.BOOLEAN,
|
||||
dateFormat: VALIDATION_TYPES.TEXT,
|
||||
label: VALIDATION_TYPES.TEXT,
|
||||
datePickerType: VALIDATION_TYPES.TEXT,
|
||||
maxDate: VALIDATION_TYPES.DATE_ISO_STRING,
|
||||
minDate: VALIDATION_TYPES.DATE_ISO_STRING,
|
||||
isRequired: VALIDATION_TYPES.BOOLEAN,
|
||||
// onDateSelected: VALIDATION_TYPES.ACTION_SELECTOR,
|
||||
// onDateRangeSelected: VALIDATION_TYPES.ACTION_SELECTOR,
|
||||
};
|
||||
}
|
||||
|
||||
static getDerivedPropertiesMap(): DerivedPropertiesMap {
|
||||
return {
|
||||
isValid: `{{ this.isRequired ? !!this.selectedDate : true }}`,
|
||||
|
|
|
|||
|
|
@ -4,10 +4,6 @@ import { WidgetType } from "constants/WidgetConstants";
|
|||
import { EventType } from "constants/AppsmithActionConstants/ActionConstants";
|
||||
import DropDownComponent from "components/designSystems/blueprint/DropdownComponent";
|
||||
import _ from "lodash";
|
||||
import {
|
||||
WidgetPropertyValidationType,
|
||||
BASE_WIDGET_VALIDATION,
|
||||
} from "utils/WidgetValidation";
|
||||
import { VALIDATION_TYPES } from "constants/WidgetValidation";
|
||||
import { Intent as BlueprintIntent } from "@blueprintjs/core";
|
||||
import * as Sentry from "@sentry/react";
|
||||
|
|
@ -48,6 +44,7 @@ class DropdownWidget extends BaseWidget<DropdownWidgetProps, WidgetState> {
|
|||
placeholderText: 'Enter [{label: "label1", value: "value2"}]',
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: VALIDATION_TYPES.OPTIONS_DATA,
|
||||
},
|
||||
{
|
||||
helpText: "Selects the option with value by default",
|
||||
|
|
@ -57,6 +54,7 @@ class DropdownWidget extends BaseWidget<DropdownWidgetProps, WidgetState> {
|
|||
placeholderText: "Enter option value",
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: VALIDATION_TYPES.DEFAULT_OPTION_VALUE,
|
||||
},
|
||||
{
|
||||
propertyName: "isRequired",
|
||||
|
|
@ -66,6 +64,7 @@ class DropdownWidget extends BaseWidget<DropdownWidgetProps, WidgetState> {
|
|||
isJSConvertible: true,
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: VALIDATION_TYPES.BOOLEAN,
|
||||
},
|
||||
{
|
||||
helpText: "Controls the visibility of the widget",
|
||||
|
|
@ -75,6 +74,7 @@ class DropdownWidget extends BaseWidget<DropdownWidgetProps, WidgetState> {
|
|||
isJSConvertible: true,
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: VALIDATION_TYPES.BOOLEAN,
|
||||
},
|
||||
{
|
||||
propertyName: "isDisabled",
|
||||
|
|
@ -84,6 +84,7 @@ class DropdownWidget extends BaseWidget<DropdownWidgetProps, WidgetState> {
|
|||
isJSConvertible: true,
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: VALIDATION_TYPES.BOOLEAN,
|
||||
},
|
||||
],
|
||||
},
|
||||
|
|
@ -103,21 +104,6 @@ class DropdownWidget extends BaseWidget<DropdownWidgetProps, WidgetState> {
|
|||
},
|
||||
];
|
||||
}
|
||||
static getPropertyValidationMap(): WidgetPropertyValidationType {
|
||||
return {
|
||||
...BASE_WIDGET_VALIDATION,
|
||||
placeholderText: VALIDATION_TYPES.TEXT,
|
||||
label: VALIDATION_TYPES.TEXT,
|
||||
options: VALIDATION_TYPES.OPTIONS_DATA,
|
||||
selectionType: VALIDATION_TYPES.TEXT,
|
||||
isRequired: VALIDATION_TYPES.BOOLEAN,
|
||||
// onOptionChange: VALIDATION_TYPES.ACTION_SELECTOR,
|
||||
selectedOptionValues: VALIDATION_TYPES.ARRAY,
|
||||
selectedOptionLabels: VALIDATION_TYPES.ARRAY,
|
||||
selectedOptionLabel: VALIDATION_TYPES.TEXT,
|
||||
defaultOptionValue: VALIDATION_TYPES.DEFAULT_OPTION_VALUE,
|
||||
};
|
||||
}
|
||||
|
||||
static getDerivedPropertiesMap() {
|
||||
return {
|
||||
|
|
|
|||
|
|
@ -7,10 +7,6 @@ import GoogleDrive from "@uppy/google-drive";
|
|||
import Webcam from "@uppy/webcam";
|
||||
import Url from "@uppy/url";
|
||||
import OneDrive from "@uppy/onedrive";
|
||||
import {
|
||||
WidgetPropertyValidationType,
|
||||
BASE_WIDGET_VALIDATION,
|
||||
} from "utils/WidgetValidation";
|
||||
import { VALIDATION_TYPES } from "constants/WidgetValidation";
|
||||
import {
|
||||
EventType,
|
||||
|
|
@ -50,6 +46,7 @@ class FilePickerWidget extends BaseWidget<
|
|||
inputType: "TEXT",
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: VALIDATION_TYPES.TEXT,
|
||||
},
|
||||
{
|
||||
propertyName: "maxNumFiles",
|
||||
|
|
@ -61,6 +58,7 @@ class FilePickerWidget extends BaseWidget<
|
|||
inputType: "INTEGER",
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: VALIDATION_TYPES.NUMBER,
|
||||
},
|
||||
{
|
||||
propertyName: "maxFileSize",
|
||||
|
|
@ -115,6 +113,7 @@ class FilePickerWidget extends BaseWidget<
|
|||
isJSConvertible: true,
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: VALIDATION_TYPES.ARRAY,
|
||||
},
|
||||
{
|
||||
helpText: "Set the format of the data read from the files",
|
||||
|
|
@ -146,6 +145,7 @@ class FilePickerWidget extends BaseWidget<
|
|||
isJSConvertible: true,
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: VALIDATION_TYPES.BOOLEAN,
|
||||
},
|
||||
{
|
||||
propertyName: "isVisible",
|
||||
|
|
@ -155,6 +155,7 @@ class FilePickerWidget extends BaseWidget<
|
|||
isJSConvertible: true,
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: VALIDATION_TYPES.BOOLEAN,
|
||||
},
|
||||
{
|
||||
propertyName: "uploadedFileUrlPaths",
|
||||
|
|
@ -175,6 +176,7 @@ class FilePickerWidget extends BaseWidget<
|
|||
isJSConvertible: true,
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: VALIDATION_TYPES.BOOLEAN,
|
||||
},
|
||||
],
|
||||
},
|
||||
|
|
@ -195,17 +197,6 @@ class FilePickerWidget extends BaseWidget<
|
|||
},
|
||||
];
|
||||
}
|
||||
static getPropertyValidationMap(): WidgetPropertyValidationType {
|
||||
return {
|
||||
...BASE_WIDGET_VALIDATION,
|
||||
label: VALIDATION_TYPES.TEXT,
|
||||
maxNumFiles: VALIDATION_TYPES.NUMBER,
|
||||
allowedFileTypes: VALIDATION_TYPES.ARRAY,
|
||||
selectedFiles: VALIDATION_TYPES.ARRAY,
|
||||
isRequired: VALIDATION_TYPES.BOOLEAN,
|
||||
// onFilesSelected: VALIDATION_TYPES.ACTION_SELECTOR,
|
||||
};
|
||||
}
|
||||
|
||||
static getDerivedPropertiesMap(): DerivedPropertiesMap {
|
||||
return {
|
||||
|
|
|
|||
|
|
@ -8,10 +8,6 @@ import {
|
|||
EventType,
|
||||
ExecutionResult,
|
||||
} from "constants/AppsmithActionConstants/ActionConstants";
|
||||
import {
|
||||
BASE_WIDGET_VALIDATION,
|
||||
WidgetPropertyValidationType,
|
||||
} from "utils/WidgetValidation";
|
||||
import { VALIDATION_TYPES } from "constants/WidgetValidation";
|
||||
import * as Sentry from "@sentry/react";
|
||||
import withMeta, { WithMeta } from "./MetaHOC";
|
||||
|
|
@ -45,6 +41,7 @@ class FormButtonWidget extends BaseWidget<
|
|||
placeholderText: "Enter label text",
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: VALIDATION_TYPES.TEXT,
|
||||
},
|
||||
{
|
||||
propertyName: "buttonStyle",
|
||||
|
|
@ -86,6 +83,7 @@ class FormButtonWidget extends BaseWidget<
|
|||
isJSConvertible: true,
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: VALIDATION_TYPES.BOOLEAN,
|
||||
},
|
||||
{
|
||||
propertyName: "isVisible",
|
||||
|
|
@ -95,6 +93,7 @@ class FormButtonWidget extends BaseWidget<
|
|||
isJSConvertible: true,
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: VALIDATION_TYPES.BOOLEAN,
|
||||
},
|
||||
{
|
||||
propertyName: "googleRecaptchaKey",
|
||||
|
|
@ -104,6 +103,7 @@ class FormButtonWidget extends BaseWidget<
|
|||
placeholderText: "Enter google recaptcha key",
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: VALIDATION_TYPES.TEXT,
|
||||
},
|
||||
],
|
||||
},
|
||||
|
|
@ -130,16 +130,6 @@ class FormButtonWidget extends BaseWidget<
|
|||
};
|
||||
}
|
||||
|
||||
static getPropertyValidationMap(): WidgetPropertyValidationType {
|
||||
return {
|
||||
...BASE_WIDGET_VALIDATION,
|
||||
text: VALIDATION_TYPES.TEXT,
|
||||
disabledWhenInvalid: VALIDATION_TYPES.BOOLEAN,
|
||||
buttonStyle: VALIDATION_TYPES.TEXT,
|
||||
buttonType: VALIDATION_TYPES.TEXT,
|
||||
};
|
||||
}
|
||||
|
||||
clickWithRecaptcha(token: string) {
|
||||
if (this.props.onClick) {
|
||||
this.setState({
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import ContainerWidget, { ContainerWidgetProps } from "widgets/ContainerWidget";
|
|||
import { ContainerComponentProps } from "components/designSystems/appsmith/ContainerComponent";
|
||||
import * as Sentry from "@sentry/react";
|
||||
import withMeta from "./MetaHOC";
|
||||
import { VALIDATION_TYPES } from "constants/WidgetValidation";
|
||||
|
||||
class FormWidget extends ContainerWidget {
|
||||
static getPropertyPaneConfig() {
|
||||
|
|
@ -21,6 +22,7 @@ class FormWidget extends ContainerWidget {
|
|||
controlType: "INPUT_TEXT",
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: VALIDATION_TYPES.TEXT,
|
||||
},
|
||||
{
|
||||
helpText: "Controls the visibility of the widget",
|
||||
|
|
@ -30,6 +32,7 @@ class FormWidget extends ContainerWidget {
|
|||
isJSConvertible: true,
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: VALIDATION_TYPES.BOOLEAN,
|
||||
},
|
||||
{
|
||||
propertyName: "shouldScrollContents",
|
||||
|
|
|
|||
|
|
@ -2,10 +2,6 @@ import * as React from "react";
|
|||
import BaseWidget, { WidgetProps, WidgetState } from "./BaseWidget";
|
||||
import { WidgetType, RenderModes } from "constants/WidgetConstants";
|
||||
import ImageComponent from "components/designSystems/appsmith/ImageComponent";
|
||||
import {
|
||||
WidgetPropertyValidationType,
|
||||
BASE_WIDGET_VALIDATION,
|
||||
} from "utils/WidgetValidation";
|
||||
import { VALIDATION_TYPES } from "constants/WidgetValidation";
|
||||
import * as Sentry from "@sentry/react";
|
||||
import { EventType } from "constants/AppsmithActionConstants/ActionConstants";
|
||||
|
|
@ -28,6 +24,7 @@ class ImageWidget extends BaseWidget<ImageWidgetProps, WidgetState> {
|
|||
placeholderText: "Enter URL / Base64",
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: VALIDATION_TYPES.TEXT,
|
||||
},
|
||||
{
|
||||
helpText: "Renders the url or Base64 when no image is provided",
|
||||
|
|
@ -37,6 +34,7 @@ class ImageWidget extends BaseWidget<ImageWidgetProps, WidgetState> {
|
|||
placeholderText: "Enter URL / Base64",
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: VALIDATION_TYPES.TEXT,
|
||||
},
|
||||
{
|
||||
helpText: "Controls the visibility of the widget",
|
||||
|
|
@ -46,6 +44,7 @@ class ImageWidget extends BaseWidget<ImageWidgetProps, WidgetState> {
|
|||
isJSConvertible: true,
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: VALIDATION_TYPES.BOOLEAN,
|
||||
},
|
||||
{
|
||||
helpText: "Controls the max zoom of the widget",
|
||||
|
|
@ -77,6 +76,7 @@ class ImageWidget extends BaseWidget<ImageWidgetProps, WidgetState> {
|
|||
isJSConvertible: true,
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: VALIDATION_TYPES.NUMBER,
|
||||
},
|
||||
],
|
||||
},
|
||||
|
|
@ -97,15 +97,6 @@ class ImageWidget extends BaseWidget<ImageWidgetProps, WidgetState> {
|
|||
},
|
||||
];
|
||||
}
|
||||
static getPropertyValidationMap(): WidgetPropertyValidationType {
|
||||
return {
|
||||
...BASE_WIDGET_VALIDATION,
|
||||
image: VALIDATION_TYPES.TEXT,
|
||||
imageShape: VALIDATION_TYPES.TEXT,
|
||||
defaultImage: VALIDATION_TYPES.TEXT,
|
||||
maxZoomLevel: VALIDATION_TYPES.NUMBER,
|
||||
};
|
||||
}
|
||||
getPageView() {
|
||||
const { maxZoomLevel } = this.props;
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -8,10 +8,6 @@ import {
|
|||
EventType,
|
||||
ExecutionResult,
|
||||
} from "constants/AppsmithActionConstants/ActionConstants";
|
||||
import {
|
||||
WidgetPropertyValidationType,
|
||||
BASE_WIDGET_VALIDATION,
|
||||
} from "utils/WidgetValidation";
|
||||
import { VALIDATION_TYPES } from "constants/WidgetValidation";
|
||||
import { createMessage, FIELD_REQUIRED_ERROR } from "constants/messages";
|
||||
import { DerivedPropertiesMap } from "utils/WidgetFactory";
|
||||
|
|
@ -65,6 +61,7 @@ class InputWidget extends BaseWidget<InputWidgetProps, WidgetState> {
|
|||
placeholderText: "Enter default text",
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: VALIDATION_TYPES.TEXT,
|
||||
},
|
||||
{
|
||||
helpText: "Sets a placeholder text for the input",
|
||||
|
|
@ -74,6 +71,7 @@ class InputWidget extends BaseWidget<InputWidgetProps, WidgetState> {
|
|||
placeholderText: "Enter placeholder text",
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: VALIDATION_TYPES.TEXT,
|
||||
},
|
||||
{
|
||||
helpText:
|
||||
|
|
@ -85,6 +83,7 @@ class InputWidget extends BaseWidget<InputWidgetProps, WidgetState> {
|
|||
inputType: "TEXT",
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: VALIDATION_TYPES.REGEX,
|
||||
},
|
||||
{
|
||||
helpText:
|
||||
|
|
@ -96,6 +95,7 @@ class InputWidget extends BaseWidget<InputWidgetProps, WidgetState> {
|
|||
inputType: "TEXT",
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: VALIDATION_TYPES.TEXT,
|
||||
},
|
||||
{
|
||||
propertyName: "isRequired",
|
||||
|
|
@ -105,6 +105,7 @@ class InputWidget extends BaseWidget<InputWidgetProps, WidgetState> {
|
|||
isJSConvertible: true,
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: VALIDATION_TYPES.BOOLEAN,
|
||||
},
|
||||
{
|
||||
helpText: "Controls the visibility of the widget",
|
||||
|
|
@ -114,6 +115,7 @@ class InputWidget extends BaseWidget<InputWidgetProps, WidgetState> {
|
|||
isJSConvertible: true,
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: VALIDATION_TYPES.BOOLEAN,
|
||||
},
|
||||
{
|
||||
helpText: "Disables input to this widget",
|
||||
|
|
@ -123,6 +125,7 @@ class InputWidget extends BaseWidget<InputWidgetProps, WidgetState> {
|
|||
isJSConvertible: true,
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: VALIDATION_TYPES.BOOLEAN,
|
||||
},
|
||||
{
|
||||
helpText: "Clears the input value after submit",
|
||||
|
|
@ -132,6 +135,7 @@ class InputWidget extends BaseWidget<InputWidgetProps, WidgetState> {
|
|||
isJSConvertible: true,
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: VALIDATION_TYPES.BOOLEAN,
|
||||
},
|
||||
],
|
||||
},
|
||||
|
|
@ -161,29 +165,6 @@ class InputWidget extends BaseWidget<InputWidgetProps, WidgetState> {
|
|||
},
|
||||
];
|
||||
}
|
||||
static getPropertyValidationMap(): WidgetPropertyValidationType {
|
||||
return {
|
||||
...BASE_WIDGET_VALIDATION,
|
||||
inputType: VALIDATION_TYPES.TEXT,
|
||||
defaultText: VALIDATION_TYPES.TEXT,
|
||||
isDisabled: VALIDATION_TYPES.BOOLEAN,
|
||||
text: VALIDATION_TYPES.TEXT,
|
||||
regex: VALIDATION_TYPES.REGEX,
|
||||
errorMessage: VALIDATION_TYPES.TEXT,
|
||||
placeholderText: VALIDATION_TYPES.TEXT,
|
||||
maxChars: VALIDATION_TYPES.NUMBER,
|
||||
minNum: VALIDATION_TYPES.NUMBER,
|
||||
maxNum: VALIDATION_TYPES.NUMBER,
|
||||
label: VALIDATION_TYPES.TEXT,
|
||||
inputValidators: VALIDATION_TYPES.ARRAY,
|
||||
focusIndex: VALIDATION_TYPES.NUMBER,
|
||||
isAutoFocusEnabled: VALIDATION_TYPES.BOOLEAN,
|
||||
// onTextChanged: VALIDATION_TYPES.ACTION_SELECTOR,
|
||||
isRequired: VALIDATION_TYPES.BOOLEAN,
|
||||
isValid: VALIDATION_TYPES.BOOLEAN,
|
||||
resetOnSubmit: VALIDATION_TYPES.BOOLEAN,
|
||||
};
|
||||
}
|
||||
|
||||
static getDerivedPropertiesMap(): DerivedPropertiesMap {
|
||||
return {
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ import React from "react";
|
|||
import BaseWidget, { WidgetProps, WidgetState } from "./BaseWidget";
|
||||
import { WidgetType } from "constants/WidgetConstants";
|
||||
import MapComponent from "components/designSystems/appsmith/MapComponent";
|
||||
import { WidgetPropertyValidationType } from "utils/WidgetValidation";
|
||||
import { VALIDATION_TYPES } from "constants/WidgetValidation";
|
||||
import { EventType } from "constants/AppsmithActionConstants/ActionConstants";
|
||||
import { getAppsmithConfigs } from "configs";
|
||||
|
|
@ -52,6 +51,7 @@ class MapWidget extends BaseWidget<MapWidgetProps, WidgetState> {
|
|||
controlType: "LOCATION_SEARCH",
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: VALIDATION_TYPES.LAT_LONG,
|
||||
},
|
||||
{
|
||||
propertyName: "defaultMarkers",
|
||||
|
|
@ -62,6 +62,7 @@ class MapWidget extends BaseWidget<MapWidgetProps, WidgetState> {
|
|||
placeholderText: 'Enter [{ "lat": "val1", "long": "val2" }]',
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: VALIDATION_TYPES.MARKERS,
|
||||
},
|
||||
{
|
||||
propertyName: "enableSearch",
|
||||
|
|
@ -104,6 +105,7 @@ class MapWidget extends BaseWidget<MapWidgetProps, WidgetState> {
|
|||
isJSConvertible: true,
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: VALIDATION_TYPES.BOOLEAN,
|
||||
},
|
||||
],
|
||||
},
|
||||
|
|
@ -130,19 +132,6 @@ class MapWidget extends BaseWidget<MapWidgetProps, WidgetState> {
|
|||
},
|
||||
];
|
||||
}
|
||||
static getPropertyValidationMap(): WidgetPropertyValidationType {
|
||||
return {
|
||||
defaultMarkers: VALIDATION_TYPES.MARKERS,
|
||||
isDisabled: VALIDATION_TYPES.BOOLEAN,
|
||||
isVisible: VALIDATION_TYPES.BOOLEAN,
|
||||
enableSearch: VALIDATION_TYPES.BOOLEAN,
|
||||
enablePickLocation: VALIDATION_TYPES.BOOLEAN,
|
||||
enableCreateMarker: VALIDATION_TYPES.BOOLEAN,
|
||||
allowZoom: VALIDATION_TYPES.BOOLEAN,
|
||||
zoomLevel: VALIDATION_TYPES.NUMBER,
|
||||
mapCenter: VALIDATION_TYPES.LAT_LONG,
|
||||
};
|
||||
}
|
||||
|
||||
static getDefaultPropertiesMap(): Record<string, string> {
|
||||
return {
|
||||
|
|
|
|||
|
|
@ -3,10 +3,6 @@ import BaseWidget, { WidgetProps, WidgetState } from "./BaseWidget";
|
|||
import { WidgetType } from "constants/WidgetConstants";
|
||||
import RadioGroupComponent from "components/designSystems/blueprint/RadioGroupComponent";
|
||||
import { EventType } from "constants/AppsmithActionConstants/ActionConstants";
|
||||
import {
|
||||
WidgetPropertyValidationType,
|
||||
BASE_WIDGET_VALIDATION,
|
||||
} from "utils/WidgetValidation";
|
||||
import { VALIDATION_TYPES } from "constants/WidgetValidation";
|
||||
import * as Sentry from "@sentry/react";
|
||||
import withMeta, { WithMeta } from "./MetaHOC";
|
||||
|
|
@ -26,6 +22,7 @@ class RadioGroupWidget extends BaseWidget<RadioGroupWidgetProps, WidgetState> {
|
|||
isJSConvertible: true,
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: VALIDATION_TYPES.OPTIONS_DATA,
|
||||
},
|
||||
{
|
||||
helpText: "Selects a value of the options entered by default",
|
||||
|
|
@ -35,6 +32,7 @@ class RadioGroupWidget extends BaseWidget<RadioGroupWidgetProps, WidgetState> {
|
|||
controlType: "INPUT_TEXT",
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: VALIDATION_TYPES.TEXT,
|
||||
},
|
||||
{
|
||||
propertyName: "isRequired",
|
||||
|
|
@ -44,6 +42,7 @@ class RadioGroupWidget extends BaseWidget<RadioGroupWidgetProps, WidgetState> {
|
|||
isJSConvertible: true,
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: VALIDATION_TYPES.BOOLEAN,
|
||||
},
|
||||
{
|
||||
helpText: "Controls the visibility of the widget",
|
||||
|
|
@ -53,6 +52,7 @@ class RadioGroupWidget extends BaseWidget<RadioGroupWidgetProps, WidgetState> {
|
|||
isJSConvertible: true,
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: VALIDATION_TYPES.BOOLEAN,
|
||||
},
|
||||
{
|
||||
propertyName: "isDisabled",
|
||||
|
|
@ -62,6 +62,7 @@ class RadioGroupWidget extends BaseWidget<RadioGroupWidgetProps, WidgetState> {
|
|||
isJSConvertible: true,
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: VALIDATION_TYPES.BOOLEAN,
|
||||
},
|
||||
],
|
||||
},
|
||||
|
|
@ -82,17 +83,6 @@ class RadioGroupWidget extends BaseWidget<RadioGroupWidgetProps, WidgetState> {
|
|||
},
|
||||
];
|
||||
}
|
||||
static getPropertyValidationMap(): WidgetPropertyValidationType {
|
||||
return {
|
||||
...BASE_WIDGET_VALIDATION,
|
||||
label: VALIDATION_TYPES.TEXT,
|
||||
options: VALIDATION_TYPES.OPTIONS_DATA,
|
||||
selectedOptionValue: VALIDATION_TYPES.TEXT,
|
||||
defaultOptionValue: VALIDATION_TYPES.TEXT,
|
||||
isRequired: VALIDATION_TYPES.BOOLEAN,
|
||||
// onSelectionChange: VALIDATION_TYPES.ACTION_SELECTOR,
|
||||
};
|
||||
}
|
||||
static getDerivedPropertiesMap() {
|
||||
return {
|
||||
selectedOption:
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ import React, { lazy, Suspense } from "react";
|
|||
import BaseWidget, { WidgetProps, WidgetState } from "./BaseWidget";
|
||||
import { WidgetType } from "constants/WidgetConstants";
|
||||
import { EventType } from "constants/AppsmithActionConstants/ActionConstants";
|
||||
import { WidgetPropertyValidationType } from "utils/WidgetValidation";
|
||||
import { VALIDATION_TYPES } from "constants/WidgetValidation";
|
||||
import { DerivedPropertiesMap } from "utils/WidgetFactory";
|
||||
import Skeleton from "components/utils/Skeleton";
|
||||
|
|
@ -60,6 +59,7 @@ class RichTextEditorWidget extends BaseWidget<
|
|||
placeholderText: "Enter HTML",
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: VALIDATION_TYPES.TEXT,
|
||||
},
|
||||
{
|
||||
propertyName: "isVisible",
|
||||
|
|
@ -69,6 +69,7 @@ class RichTextEditorWidget extends BaseWidget<
|
|||
isJSConvertible: true,
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: VALIDATION_TYPES.BOOLEAN,
|
||||
},
|
||||
{
|
||||
propertyName: "isDisabled",
|
||||
|
|
@ -78,6 +79,7 @@ class RichTextEditorWidget extends BaseWidget<
|
|||
isJSConvertible: true,
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: VALIDATION_TYPES.BOOLEAN,
|
||||
},
|
||||
],
|
||||
},
|
||||
|
|
@ -97,14 +99,6 @@ class RichTextEditorWidget extends BaseWidget<
|
|||
},
|
||||
];
|
||||
}
|
||||
static getPropertyValidationMap(): WidgetPropertyValidationType {
|
||||
return {
|
||||
placeholder: VALIDATION_TYPES.TEXT,
|
||||
defaultText: VALIDATION_TYPES.TEXT,
|
||||
isDisabled: VALIDATION_TYPES.BOOLEAN,
|
||||
isVisible: VALIDATION_TYPES.BOOLEAN,
|
||||
};
|
||||
}
|
||||
|
||||
static getMetaPropertiesMap(): Record<string, any> {
|
||||
return {
|
||||
|
|
|
|||
|
|
@ -3,10 +3,6 @@ import BaseWidget, { WidgetProps, WidgetState } from "./BaseWidget";
|
|||
import { WidgetType } from "constants/WidgetConstants";
|
||||
import * as Sentry from "@sentry/react";
|
||||
import withMeta, { WithMeta } from "./MetaHOC";
|
||||
import {
|
||||
BASE_WIDGET_VALIDATION,
|
||||
WidgetPropertyValidationType,
|
||||
} from "utils/WidgetValidation";
|
||||
import { VALIDATION_TYPES } from "constants/WidgetValidation";
|
||||
import { SwitchComponent } from "components/designSystems/blueprint/SwitchComponent";
|
||||
import { EventType } from "constants/AppsmithActionConstants/ActionConstants";
|
||||
|
|
@ -26,6 +22,7 @@ class SwitchWidget extends BaseWidget<SwitchWidgetProps, WidgetState> {
|
|||
placeholderText: "Enter label text",
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: VALIDATION_TYPES.TEXT,
|
||||
},
|
||||
{
|
||||
propertyName: "alignWidget",
|
||||
|
|
@ -54,6 +51,7 @@ class SwitchWidget extends BaseWidget<SwitchWidgetProps, WidgetState> {
|
|||
isJSConvertible: true,
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: VALIDATION_TYPES.BOOLEAN,
|
||||
},
|
||||
{
|
||||
propertyName: "isVisible",
|
||||
|
|
@ -63,6 +61,7 @@ class SwitchWidget extends BaseWidget<SwitchWidgetProps, WidgetState> {
|
|||
isJSConvertible: true,
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: VALIDATION_TYPES.BOOLEAN,
|
||||
},
|
||||
{
|
||||
propertyName: "isDisabled",
|
||||
|
|
@ -72,6 +71,7 @@ class SwitchWidget extends BaseWidget<SwitchWidgetProps, WidgetState> {
|
|||
isJSConvertible: true,
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: VALIDATION_TYPES.BOOLEAN,
|
||||
},
|
||||
],
|
||||
},
|
||||
|
|
@ -110,14 +110,6 @@ class SwitchWidget extends BaseWidget<SwitchWidgetProps, WidgetState> {
|
|||
return "SWITCH_WIDGET";
|
||||
}
|
||||
|
||||
static getPropertyValidationMap(): WidgetPropertyValidationType {
|
||||
return {
|
||||
...BASE_WIDGET_VALIDATION,
|
||||
label: VALIDATION_TYPES.TEXT,
|
||||
defaultSwitchState: VALIDATION_TYPES.BOOLEAN,
|
||||
};
|
||||
}
|
||||
|
||||
static getDefaultPropertiesMap(): Record<string, string> {
|
||||
return {
|
||||
isSwitchedOn: "defaultSwitchState",
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import { get } from "lodash";
|
|||
import { Colors } from "constants/Colors";
|
||||
import { ColumnProperties } from "components/designSystems/appsmith/TableComponent/Constants";
|
||||
import { TableWidgetProps } from "./TableWidgetConstants";
|
||||
import { VALIDATION_TYPES } from "constants/WidgetValidation";
|
||||
|
||||
// A hook to update all column styles when global table styles are updated
|
||||
const updateColumnStyles = (
|
||||
|
|
@ -142,6 +143,7 @@ export default [
|
|||
inputType: "ARRAY",
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: VALIDATION_TYPES.TABLE_DATA,
|
||||
},
|
||||
{
|
||||
helpText: "Columns",
|
||||
|
|
@ -637,6 +639,7 @@ export default [
|
|||
placeholderText: "Enter default search text",
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: VALIDATION_TYPES.TEXT,
|
||||
},
|
||||
{
|
||||
helpText: "Selects the default selected row",
|
||||
|
|
@ -646,6 +649,7 @@ export default [
|
|||
placeholderText: "Enter row index",
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: VALIDATION_TYPES.DEFAULT_SELECTED_ROW,
|
||||
},
|
||||
{
|
||||
helpText:
|
||||
|
|
@ -664,6 +668,7 @@ export default [
|
|||
controlType: "SWITCH",
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: VALIDATION_TYPES.BOOLEAN,
|
||||
},
|
||||
{
|
||||
propertyName: "multiRowSelection",
|
||||
|
|
|
|||
|
|
@ -10,11 +10,6 @@ import {
|
|||
renderActions,
|
||||
} from "components/designSystems/appsmith/TableComponent/TableUtilities";
|
||||
import { getAllTableColumnKeys } from "components/designSystems/appsmith/TableComponent/TableHelpers";
|
||||
import { VALIDATION_TYPES } from "constants/WidgetValidation";
|
||||
import {
|
||||
BASE_WIDGET_VALIDATION,
|
||||
WidgetPropertyValidationType,
|
||||
} from "utils/WidgetValidation";
|
||||
import Skeleton from "components/utils/Skeleton";
|
||||
import moment from "moment";
|
||||
import { isNumber, isString, isNil, isEqual, xor, without } from "lodash";
|
||||
|
|
@ -45,22 +40,6 @@ const ReactTableComponent = lazy(() =>
|
|||
);
|
||||
|
||||
class TableWidget extends BaseWidget<TableWidgetProps, WidgetState> {
|
||||
static getPropertyValidationMap(): WidgetPropertyValidationType {
|
||||
return {
|
||||
...BASE_WIDGET_VALIDATION,
|
||||
tableData: VALIDATION_TYPES.TABLE_DATA,
|
||||
nextPageKey: VALIDATION_TYPES.TEXT,
|
||||
prevPageKey: VALIDATION_TYPES.TEXT,
|
||||
label: VALIDATION_TYPES.TEXT,
|
||||
searchText: VALIDATION_TYPES.TEXT,
|
||||
defaultSearchText: VALIDATION_TYPES.TEXT,
|
||||
defaultSelectedRow: VALIDATION_TYPES.DEFAULT_SELECTED_ROW,
|
||||
pageSize: VALIDATION_TYPES.NUMBER,
|
||||
selectedRowIndices: VALIDATION_TYPES.ROW_INDICES,
|
||||
pageNo: VALIDATION_TYPES.TABLE_PAGE_NO,
|
||||
};
|
||||
}
|
||||
|
||||
static getPropertyPaneConfig() {
|
||||
return tablePropertyPaneConfig;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ import TabsComponent from "components/designSystems/appsmith/TabsComponent";
|
|||
import { WidgetType, WidgetTypes } from "constants/WidgetConstants";
|
||||
import BaseWidget, { WidgetProps, WidgetState } from "./BaseWidget";
|
||||
import WidgetFactory from "utils/WidgetFactory";
|
||||
import { WidgetPropertyValidationType } from "utils/WidgetValidation";
|
||||
import { VALIDATION_TYPES } from "constants/WidgetValidation";
|
||||
import _ from "lodash";
|
||||
import { EventType } from "constants/AppsmithActionConstants/ActionConstants";
|
||||
|
|
@ -29,6 +28,7 @@ class TabsWidget extends BaseWidget<
|
|||
controlType: "TABS_INPUT",
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: VALIDATION_TYPES.TABS_DATA,
|
||||
},
|
||||
{
|
||||
propertyName: "defaultTab",
|
||||
|
|
@ -38,6 +38,7 @@ class TabsWidget extends BaseWidget<
|
|||
controlType: "INPUT_TEXT",
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: VALIDATION_TYPES.SELECTED_TAB,
|
||||
},
|
||||
{
|
||||
propertyName: "shouldShowTabs",
|
||||
|
|
@ -63,6 +64,7 @@ class TabsWidget extends BaseWidget<
|
|||
isJSConvertible: true,
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: VALIDATION_TYPES.BOOLEAN,
|
||||
},
|
||||
],
|
||||
},
|
||||
|
|
@ -82,12 +84,6 @@ class TabsWidget extends BaseWidget<
|
|||
},
|
||||
];
|
||||
}
|
||||
static getPropertyValidationMap(): WidgetPropertyValidationType {
|
||||
return {
|
||||
tabs: VALIDATION_TYPES.TABS_DATA,
|
||||
defaultTab: VALIDATION_TYPES.SELECTED_TAB,
|
||||
};
|
||||
}
|
||||
|
||||
onTabChange = (tabWidgetId: string) => {
|
||||
this.props.updateWidgetMetaProperty("selectedTabWidgetId", tabWidgetId, {
|
||||
|
|
|
|||
|
|
@ -3,10 +3,6 @@ import BaseWidget, { WidgetProps, WidgetState } from "./BaseWidget";
|
|||
import { WidgetType, TextSize } from "constants/WidgetConstants";
|
||||
import TextComponent from "components/designSystems/blueprint/TextComponent";
|
||||
import { VALIDATION_TYPES } from "constants/WidgetValidation";
|
||||
import {
|
||||
WidgetPropertyValidationType,
|
||||
BASE_WIDGET_VALIDATION,
|
||||
} from "utils/WidgetValidation";
|
||||
import { DerivedPropertiesMap } from "utils/WidgetFactory";
|
||||
import * as Sentry from "@sentry/react";
|
||||
|
||||
|
|
@ -24,6 +20,7 @@ class TextWidget extends BaseWidget<TextWidgetProps, WidgetState> {
|
|||
placeholderText: "Enter text",
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: VALIDATION_TYPES.TEXT,
|
||||
},
|
||||
{
|
||||
propertyName: "shouldScroll",
|
||||
|
|
@ -41,6 +38,7 @@ class TextWidget extends BaseWidget<TextWidgetProps, WidgetState> {
|
|||
isJSConvertible: true,
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: VALIDATION_TYPES.BOOLEAN,
|
||||
},
|
||||
],
|
||||
},
|
||||
|
|
@ -143,14 +141,6 @@ class TextWidget extends BaseWidget<TextWidgetProps, WidgetState> {
|
|||
},
|
||||
];
|
||||
}
|
||||
static getPropertyValidationMap(): WidgetPropertyValidationType {
|
||||
return {
|
||||
...BASE_WIDGET_VALIDATION,
|
||||
text: VALIDATION_TYPES.TEXT,
|
||||
textStyle: VALIDATION_TYPES.TEXT,
|
||||
shouldScroll: VALIDATION_TYPES.BOOLEAN,
|
||||
};
|
||||
}
|
||||
|
||||
getPageView() {
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -3,10 +3,6 @@ import BaseWidget, { WidgetProps, WidgetState } from "./BaseWidget";
|
|||
import { WidgetType } from "constants/WidgetConstants";
|
||||
import { EventType } from "constants/AppsmithActionConstants/ActionConstants";
|
||||
import { VALIDATION_TYPES } from "constants/WidgetValidation";
|
||||
import {
|
||||
WidgetPropertyValidationType,
|
||||
BASE_WIDGET_VALIDATION,
|
||||
} from "utils/WidgetValidation";
|
||||
import Skeleton from "components/utils/Skeleton";
|
||||
import * as Sentry from "@sentry/react";
|
||||
import { retryPromise } from "utils/AppsmithUtils";
|
||||
|
|
@ -40,6 +36,7 @@ class VideoWidget extends BaseWidget<VideoWidgetProps, WidgetState> {
|
|||
inputType: "TEXT",
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: VALIDATION_TYPES.TEXT,
|
||||
},
|
||||
{
|
||||
propertyName: "autoPlay",
|
||||
|
|
@ -49,6 +46,7 @@ class VideoWidget extends BaseWidget<VideoWidgetProps, WidgetState> {
|
|||
isJSConvertible: true,
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: VALIDATION_TYPES.BOOLEAN,
|
||||
},
|
||||
{
|
||||
helpText: "Controls the visibility of the widget",
|
||||
|
|
@ -58,6 +56,7 @@ class VideoWidget extends BaseWidget<VideoWidgetProps, WidgetState> {
|
|||
isJSConvertible: true,
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: VALIDATION_TYPES.BOOLEAN,
|
||||
},
|
||||
],
|
||||
},
|
||||
|
|
@ -96,12 +95,6 @@ class VideoWidget extends BaseWidget<VideoWidgetProps, WidgetState> {
|
|||
];
|
||||
}
|
||||
private _player = React.createRef<ReactPlayer>();
|
||||
static getPropertyValidationMap(): WidgetPropertyValidationType {
|
||||
return {
|
||||
...BASE_WIDGET_VALIDATION,
|
||||
url: VALIDATION_TYPES.TEXT,
|
||||
};
|
||||
}
|
||||
|
||||
static getMetaPropertiesMap(): Record<string, any> {
|
||||
return {
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ import {
|
|||
CrashingError,
|
||||
DataTreeDiffEvent,
|
||||
getAllPaths,
|
||||
getEntityNameAndPropertyPath,
|
||||
getImmediateParentsOfPropertyPaths,
|
||||
getValidatedTree,
|
||||
makeParentsDependOnChildren,
|
||||
|
|
@ -86,7 +87,7 @@ export default class DataTreeEvaluator {
|
|||
const evaluateEnd = performance.now();
|
||||
// Validate Widgets
|
||||
const validateStart = performance.now();
|
||||
this.evalTree = getValidatedTree(this.widgetConfigMap, evaluatedTree);
|
||||
this.evalTree = getValidatedTree(evaluatedTree);
|
||||
const validateEnd = performance.now();
|
||||
|
||||
this.oldUnEvalTree = unEvalTree;
|
||||
|
|
@ -350,24 +351,25 @@ export default class DataTreeEvaluator {
|
|||
const tree = _.cloneDeep(oldUnevalTree);
|
||||
try {
|
||||
return sortedDependencies.reduce(
|
||||
(currentTree: DataTree, propertyPath: string) => {
|
||||
this.logs.push(`evaluating ${propertyPath}`);
|
||||
const entityName = propertyPath.split(".")[0];
|
||||
(currentTree: DataTree, fullPropertyPath: string) => {
|
||||
this.logs.push(`evaluating ${fullPropertyPath}`);
|
||||
const { entityName, propertyPath } = getEntityNameAndPropertyPath(
|
||||
fullPropertyPath,
|
||||
);
|
||||
const entity: DataTreeEntity = currentTree[entityName];
|
||||
const unEvalPropertyValue = _.get(currentTree as any, propertyPath);
|
||||
const unEvalPropertyValue = _.get(
|
||||
currentTree as any,
|
||||
fullPropertyPath,
|
||||
);
|
||||
const isABindingPath =
|
||||
(isAction(entity) || isWidget(entity)) &&
|
||||
isPathADynamicBinding(
|
||||
entity,
|
||||
propertyPath.substring(propertyPath.indexOf(".") + 1),
|
||||
);
|
||||
isPathADynamicBinding(entity, propertyPath);
|
||||
let evalPropertyValue;
|
||||
const requiresEval =
|
||||
isABindingPath && isDynamicValue(unEvalPropertyValue);
|
||||
if (requiresEval) {
|
||||
try {
|
||||
evalPropertyValue = this.evaluateDynamicProperty(
|
||||
propertyPath,
|
||||
currentTree,
|
||||
unEvalPropertyValue,
|
||||
);
|
||||
|
|
@ -376,7 +378,7 @@ export default class DataTreeEvaluator {
|
|||
type: EvalErrorTypes.EVAL_PROPERTY_ERROR,
|
||||
message: e.message,
|
||||
context: {
|
||||
propertyPath,
|
||||
propertyPath: fullPropertyPath,
|
||||
},
|
||||
});
|
||||
evalPropertyValue = undefined;
|
||||
|
|
@ -386,42 +388,37 @@ export default class DataTreeEvaluator {
|
|||
}
|
||||
if (isWidget(entity)) {
|
||||
const widgetEntity = entity;
|
||||
// TODO fix for nested properties
|
||||
// For nested properties like Table1.selectedRow.email
|
||||
// The following line will calculated the property name to be selectedRow
|
||||
// instead of selectedRow.email
|
||||
const propertyName = propertyPath.split(".")[1];
|
||||
const defaultPropertyMap = this.widgetConfigMap[widgetEntity.type]
|
||||
.defaultProperties;
|
||||
const isDefaultProperty = !!Object.values(
|
||||
defaultPropertyMap,
|
||||
).filter(
|
||||
(defaultPropertyName) => propertyName === defaultPropertyName,
|
||||
(defaultPropertyName) => propertyPath === defaultPropertyName,
|
||||
).length;
|
||||
if (propertyName) {
|
||||
if (propertyPath) {
|
||||
let parsedValue = this.validateAndParseWidgetProperty(
|
||||
propertyPath,
|
||||
fullPropertyPath,
|
||||
widgetEntity,
|
||||
currentTree,
|
||||
evalPropertyValue,
|
||||
unEvalPropertyValue,
|
||||
isDefaultProperty,
|
||||
);
|
||||
const hasDefaultProperty = propertyName in defaultPropertyMap;
|
||||
const hasDefaultProperty = propertyPath in defaultPropertyMap;
|
||||
if (hasDefaultProperty) {
|
||||
const defaultProperty = defaultPropertyMap[propertyName];
|
||||
const defaultProperty = defaultPropertyMap[propertyPath];
|
||||
parsedValue = this.overwriteDefaultDependentProps(
|
||||
defaultProperty,
|
||||
parsedValue,
|
||||
propertyPath,
|
||||
fullPropertyPath,
|
||||
widgetEntity,
|
||||
);
|
||||
}
|
||||
return _.set(currentTree, propertyPath, parsedValue);
|
||||
return _.set(currentTree, fullPropertyPath, parsedValue);
|
||||
}
|
||||
return _.set(currentTree, propertyPath, evalPropertyValue);
|
||||
return _.set(currentTree, fullPropertyPath, evalPropertyValue);
|
||||
} else {
|
||||
return _.set(currentTree, propertyPath, evalPropertyValue);
|
||||
return _.set(currentTree, fullPropertyPath, evalPropertyValue);
|
||||
}
|
||||
},
|
||||
tree,
|
||||
|
|
@ -573,7 +570,6 @@ export default class DataTreeEvaluator {
|
|||
}
|
||||
|
||||
evaluateDynamicProperty(
|
||||
propertyPath: string,
|
||||
currentTree: DataTree,
|
||||
unEvalPropertyValue: any,
|
||||
): any {
|
||||
|
|
@ -581,14 +577,14 @@ export default class DataTreeEvaluator {
|
|||
}
|
||||
|
||||
validateAndParseWidgetProperty(
|
||||
propertyPath: string,
|
||||
fullPropertyPath: string,
|
||||
widget: DataTreeWidget,
|
||||
currentTree: DataTree,
|
||||
evalPropertyValue: any,
|
||||
unEvalPropertyValue: string,
|
||||
isDefaultProperty: boolean,
|
||||
): any {
|
||||
const entityPropertyName = _.drop(propertyPath.split(".")).join(".");
|
||||
const { propertyPath } = getEntityNameAndPropertyPath(fullPropertyPath);
|
||||
let valueToValidate = evalPropertyValue;
|
||||
if (isPathADynamicTrigger(widget, propertyPath)) {
|
||||
const { triggers } = this.getDynamicValue(
|
||||
|
|
@ -599,12 +595,12 @@ export default class DataTreeEvaluator {
|
|||
);
|
||||
valueToValidate = triggers;
|
||||
}
|
||||
const validation = widget.validationPaths[propertyPath];
|
||||
const { parsed, isValid, message, transformed } = validateWidgetProperty(
|
||||
this.widgetConfigMap,
|
||||
widget.type,
|
||||
entityPropertyName,
|
||||
propertyPath,
|
||||
valueToValidate,
|
||||
widget,
|
||||
validation,
|
||||
currentTree,
|
||||
);
|
||||
const evaluatedValue = isValid
|
||||
|
|
@ -613,23 +609,23 @@ export default class DataTreeEvaluator {
|
|||
? evalPropertyValue
|
||||
: transformed;
|
||||
const safeEvaluatedValue = removeFunctions(evaluatedValue);
|
||||
_.set(widget, `evaluatedValues.${entityPropertyName}`, safeEvaluatedValue);
|
||||
_.set(widget, `evaluatedValues.${propertyPath}`, safeEvaluatedValue);
|
||||
if (!isValid) {
|
||||
_.set(widget, `invalidProps.${entityPropertyName}`, true);
|
||||
_.set(widget, `validationMessages.${entityPropertyName}`, message);
|
||||
_.set(widget, `invalidProps.${propertyPath}`, true);
|
||||
_.set(widget, `validationMessages.${propertyPath}`, message);
|
||||
} else {
|
||||
_.set(widget, `invalidProps.${entityPropertyName}`, false);
|
||||
_.set(widget, `validationMessages.${entityPropertyName}`, "");
|
||||
_.set(widget, `invalidProps.${propertyPath}`, false);
|
||||
_.set(widget, `validationMessages.${propertyPath}`, "");
|
||||
}
|
||||
|
||||
if (isPathADynamicTrigger(widget, entityPropertyName)) {
|
||||
if (isPathADynamicTrigger(widget, propertyPath)) {
|
||||
return unEvalPropertyValue;
|
||||
} else {
|
||||
const parsedCache = this.getParsedValueCache(propertyPath);
|
||||
const parsedCache = this.getParsedValueCache(fullPropertyPath);
|
||||
// In case this is a default property, always set the cache even if the value remains the same so that the version
|
||||
// in cache gets updated and the property dependent on default property updates accordingly.
|
||||
if (!equal(parsedCache.value, parsed) || isDefaultProperty) {
|
||||
this.parsedValueCache.set(propertyPath, {
|
||||
this.parsedValueCache.set(fullPropertyPath, {
|
||||
value: parsed,
|
||||
version: Date.now(),
|
||||
});
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ describe("evaluate", () => {
|
|||
ENTITY_TYPE: ENTITY_TYPE.WIDGET,
|
||||
bindingPaths: {},
|
||||
triggerPaths: {},
|
||||
validationPaths: {},
|
||||
};
|
||||
const dataTree: DataTree = {
|
||||
Input1: widget,
|
||||
|
|
|
|||
|
|
@ -7,27 +7,15 @@ import { WidgetTypeConfigMap } from "../utils/WidgetFactory";
|
|||
import { RenderModes, WidgetTypes } from "../constants/WidgetConstants";
|
||||
import { PluginType } from "../entities/Action";
|
||||
import DataTreeEvaluator from "workers/DataTreeEvaluator";
|
||||
import { VALIDATION_TYPES } from "constants/WidgetValidation";
|
||||
|
||||
const WIDGET_CONFIG_MAP: WidgetTypeConfigMap = {
|
||||
CONTAINER_WIDGET: {
|
||||
validations: {
|
||||
isLoading: "BOOLEAN",
|
||||
isVisible: "BOOLEAN",
|
||||
isDisabled: "BOOLEAN",
|
||||
},
|
||||
defaultProperties: {},
|
||||
derivedProperties: {},
|
||||
metaProperties: {},
|
||||
},
|
||||
TEXT_WIDGET: {
|
||||
validations: {
|
||||
isLoading: "BOOLEAN",
|
||||
isVisible: "BOOLEAN",
|
||||
isDisabled: "BOOLEAN",
|
||||
text: "TEXT",
|
||||
textStyle: "TEXT",
|
||||
shouldScroll: "BOOLEAN",
|
||||
},
|
||||
defaultProperties: {},
|
||||
derivedProperties: {
|
||||
value: "{{ this.text }}",
|
||||
|
|
@ -35,38 +23,11 @@ const WIDGET_CONFIG_MAP: WidgetTypeConfigMap = {
|
|||
metaProperties: {},
|
||||
},
|
||||
BUTTON_WIDGET: {
|
||||
validations: {
|
||||
isLoading: "BOOLEAN",
|
||||
isVisible: "BOOLEAN",
|
||||
isDisabled: "BOOLEAN",
|
||||
text: "TEXT",
|
||||
buttonStyle: "TEXT",
|
||||
},
|
||||
defaultProperties: {},
|
||||
derivedProperties: {},
|
||||
metaProperties: {},
|
||||
},
|
||||
INPUT_WIDGET: {
|
||||
validations: {
|
||||
isLoading: "BOOLEAN",
|
||||
isVisible: "BOOLEAN",
|
||||
isDisabled: "BOOLEAN",
|
||||
inputType: "TEXT",
|
||||
defaultText: "TEXT",
|
||||
text: "TEXT",
|
||||
regex: "REGEX",
|
||||
errorMessage: "TEXT",
|
||||
placeholderText: "TEXT",
|
||||
maxChars: "NUMBER",
|
||||
minNum: "NUMBER",
|
||||
maxNum: "NUMBER",
|
||||
label: "TEXT",
|
||||
inputValidators: "ARRAY",
|
||||
focusIndex: "NUMBER",
|
||||
isAutoFocusEnabled: "BOOLEAN",
|
||||
isRequired: "BOOLEAN",
|
||||
isValid: "BOOLEAN",
|
||||
},
|
||||
defaultProperties: {
|
||||
text: "defaultText",
|
||||
},
|
||||
|
|
@ -81,13 +42,6 @@ const WIDGET_CONFIG_MAP: WidgetTypeConfigMap = {
|
|||
},
|
||||
},
|
||||
CHECKBOX_WIDGET: {
|
||||
validations: {
|
||||
isLoading: "BOOLEAN",
|
||||
isVisible: "BOOLEAN",
|
||||
isDisabled: "BOOLEAN",
|
||||
label: "TEXT",
|
||||
defaultCheckedState: "BOOLEAN",
|
||||
},
|
||||
defaultProperties: {
|
||||
isChecked: "defaultCheckedState",
|
||||
},
|
||||
|
|
@ -97,18 +51,6 @@ const WIDGET_CONFIG_MAP: WidgetTypeConfigMap = {
|
|||
metaProperties: {},
|
||||
},
|
||||
DROP_DOWN_WIDGET: {
|
||||
validations: {
|
||||
isLoading: "BOOLEAN",
|
||||
isVisible: "BOOLEAN",
|
||||
isDisabled: "BOOLEAN",
|
||||
placeholderText: "TEXT",
|
||||
label: "TEXT",
|
||||
options: "OPTIONS_DATA",
|
||||
selectionType: "TEXT",
|
||||
isRequired: "BOOLEAN",
|
||||
selectedOptionValues: "ARRAY",
|
||||
defaultOptionValue: "DEFAULT_OPTION_VALUE",
|
||||
},
|
||||
defaultProperties: {
|
||||
selectedOptionValue: "defaultOptionValue",
|
||||
selectedOptionValueArr: "defaultOptionValue",
|
||||
|
|
@ -131,16 +73,6 @@ const WIDGET_CONFIG_MAP: WidgetTypeConfigMap = {
|
|||
metaProperties: {},
|
||||
},
|
||||
RADIO_GROUP_WIDGET: {
|
||||
validations: {
|
||||
isLoading: "BOOLEAN",
|
||||
isVisible: "BOOLEAN",
|
||||
isDisabled: "BOOLEAN",
|
||||
label: "TEXT",
|
||||
options: "OPTIONS_DATA",
|
||||
selectedOptionValue: "TEXT",
|
||||
defaultOptionValue: "TEXT",
|
||||
isRequired: "BOOLEAN",
|
||||
},
|
||||
defaultProperties: {
|
||||
selectedOptionValue: "defaultOptionValue",
|
||||
},
|
||||
|
|
@ -153,32 +85,11 @@ const WIDGET_CONFIG_MAP: WidgetTypeConfigMap = {
|
|||
metaProperties: {},
|
||||
},
|
||||
IMAGE_WIDGET: {
|
||||
validations: {
|
||||
isLoading: "BOOLEAN",
|
||||
isVisible: "BOOLEAN",
|
||||
isDisabled: "BOOLEAN",
|
||||
image: "TEXT",
|
||||
imageShape: "TEXT",
|
||||
defaultImage: "TEXT",
|
||||
maxZoomLevel: "NUMBER",
|
||||
},
|
||||
defaultProperties: {},
|
||||
derivedProperties: {},
|
||||
metaProperties: {},
|
||||
},
|
||||
TABLE_WIDGET: {
|
||||
validations: {
|
||||
isLoading: "BOOLEAN",
|
||||
isVisible: "BOOLEAN",
|
||||
isDisabled: "BOOLEAN",
|
||||
tableData: "TABLE_DATA",
|
||||
nextPageKey: "TEXT",
|
||||
prevPageKey: "TEXT",
|
||||
label: "TEXT",
|
||||
searchText: "TEXT",
|
||||
defaultSearchText: "TEXT",
|
||||
defaultSelectedRow: "DEFAULT_SELECTED_ROW",
|
||||
},
|
||||
defaultProperties: {
|
||||
searchText: "defaultSearchText",
|
||||
selectedRowIndex: "defaultSelectedRow",
|
||||
|
|
@ -195,12 +106,6 @@ const WIDGET_CONFIG_MAP: WidgetTypeConfigMap = {
|
|||
},
|
||||
},
|
||||
VIDEO_WIDGET: {
|
||||
validations: {
|
||||
isLoading: "BOOLEAN",
|
||||
isVisible: "BOOLEAN",
|
||||
isDisabled: "BOOLEAN",
|
||||
url: "TEXT",
|
||||
},
|
||||
defaultProperties: {},
|
||||
derivedProperties: {},
|
||||
metaProperties: {
|
||||
|
|
@ -208,16 +113,6 @@ const WIDGET_CONFIG_MAP: WidgetTypeConfigMap = {
|
|||
},
|
||||
},
|
||||
FILE_PICKER_WIDGET: {
|
||||
validations: {
|
||||
isLoading: "BOOLEAN",
|
||||
isVisible: "BOOLEAN",
|
||||
isDisabled: "BOOLEAN",
|
||||
label: "TEXT",
|
||||
maxNumFiles: "NUMBER",
|
||||
allowedFileTypes: "ARRAY",
|
||||
files: "ARRAY",
|
||||
isRequired: "BOOLEAN",
|
||||
},
|
||||
defaultProperties: {},
|
||||
derivedProperties: {
|
||||
isValid: "{{ this.isRequired ? this.files.length > 0 : true }}",
|
||||
|
|
@ -229,20 +124,6 @@ const WIDGET_CONFIG_MAP: WidgetTypeConfigMap = {
|
|||
},
|
||||
},
|
||||
DATE_PICKER_WIDGET: {
|
||||
validations: {
|
||||
isLoading: "BOOLEAN",
|
||||
isVisible: "BOOLEAN",
|
||||
isDisabled: "BOOLEAN",
|
||||
defaultDate: "DATE",
|
||||
timezone: "TEXT",
|
||||
enableTimePicker: "BOOLEAN",
|
||||
dateFormat: "TEXT",
|
||||
label: "TEXT",
|
||||
datePickerType: "TEXT",
|
||||
maxDate: "DATE",
|
||||
minDate: "DATE",
|
||||
isRequired: "BOOLEAN",
|
||||
},
|
||||
defaultProperties: {
|
||||
selectedDate: "defaultDate",
|
||||
},
|
||||
|
|
@ -253,20 +134,6 @@ const WIDGET_CONFIG_MAP: WidgetTypeConfigMap = {
|
|||
metaProperties: {},
|
||||
},
|
||||
DATE_PICKER_WIDGET2: {
|
||||
validations: {
|
||||
isLoading: "BOOLEAN",
|
||||
isVisible: "BOOLEAN",
|
||||
isDisabled: "BOOLEAN",
|
||||
defaultDate: "DATE",
|
||||
timezone: "TEXT",
|
||||
enableTimePicker: "BOOLEAN",
|
||||
dateFormat: "TEXT",
|
||||
label: "TEXT",
|
||||
datePickerType: "TEXT",
|
||||
maxDate: "DATE",
|
||||
minDate: "DATE",
|
||||
isRequired: "BOOLEAN",
|
||||
},
|
||||
defaultProperties: {
|
||||
selectedDate: "defaultDate",
|
||||
},
|
||||
|
|
@ -277,10 +144,6 @@ const WIDGET_CONFIG_MAP: WidgetTypeConfigMap = {
|
|||
metaProperties: {},
|
||||
},
|
||||
TABS_WIDGET: {
|
||||
validations: {
|
||||
tabs: "TABS_DATA",
|
||||
defaultTab: "SELECTED_TAB",
|
||||
},
|
||||
defaultProperties: {},
|
||||
derivedProperties: {
|
||||
selectedTab:
|
||||
|
|
@ -289,23 +152,11 @@ const WIDGET_CONFIG_MAP: WidgetTypeConfigMap = {
|
|||
metaProperties: {},
|
||||
},
|
||||
MODAL_WIDGET: {
|
||||
validations: {
|
||||
isLoading: "BOOLEAN",
|
||||
isVisible: "BOOLEAN",
|
||||
isDisabled: "BOOLEAN",
|
||||
},
|
||||
defaultProperties: {},
|
||||
derivedProperties: {},
|
||||
metaProperties: {},
|
||||
},
|
||||
RICH_TEXT_EDITOR_WIDGET: {
|
||||
validations: {
|
||||
text: "TEXT",
|
||||
placeholder: "TEXT",
|
||||
defaultValue: "TEXT",
|
||||
isDisabled: "BOOLEAN",
|
||||
isVisible: "BOOLEAN",
|
||||
},
|
||||
defaultProperties: {
|
||||
text: "defaultText",
|
||||
},
|
||||
|
|
@ -315,52 +166,21 @@ const WIDGET_CONFIG_MAP: WidgetTypeConfigMap = {
|
|||
metaProperties: {},
|
||||
},
|
||||
CHART_WIDGET: {
|
||||
validations: {
|
||||
xAxisName: "TEXT",
|
||||
yAxisName: "TEXT",
|
||||
chartName: "TEXT",
|
||||
isVisible: "BOOLEAN",
|
||||
chartData: "CHART_DATA",
|
||||
},
|
||||
defaultProperties: {},
|
||||
derivedProperties: {},
|
||||
metaProperties: {},
|
||||
},
|
||||
FORM_WIDGET: {
|
||||
validations: {
|
||||
isLoading: "BOOLEAN",
|
||||
isVisible: "BOOLEAN",
|
||||
isDisabled: "BOOLEAN",
|
||||
},
|
||||
defaultProperties: {},
|
||||
derivedProperties: {},
|
||||
metaProperties: {},
|
||||
},
|
||||
FORM_BUTTON_WIDGET: {
|
||||
validations: {
|
||||
isLoading: "BOOLEAN",
|
||||
isVisible: "BOOLEAN",
|
||||
isDisabled: "BOOLEAN",
|
||||
text: "TEXT",
|
||||
disabledWhenInvalid: "BOOLEAN",
|
||||
buttonStyle: "TEXT",
|
||||
buttonType: "TEXT",
|
||||
},
|
||||
defaultProperties: {},
|
||||
derivedProperties: {},
|
||||
metaProperties: {},
|
||||
},
|
||||
MAP_WIDGET: {
|
||||
validations: {
|
||||
defaultMarkers: "MARKERS",
|
||||
isDisabled: "BOOLEAN",
|
||||
isVisible: "BOOLEAN",
|
||||
enableSearch: "BOOLEAN",
|
||||
enablePickLocation: "BOOLEAN",
|
||||
allowZoom: "BOOLEAN",
|
||||
zoomLevel: "NUMBER",
|
||||
mapCenter: "OBJECT",
|
||||
},
|
||||
defaultProperties: {
|
||||
markers: "defaultMarkers",
|
||||
center: "mapCenter",
|
||||
|
|
@ -369,31 +189,16 @@ const WIDGET_CONFIG_MAP: WidgetTypeConfigMap = {
|
|||
metaProperties: {},
|
||||
},
|
||||
CANVAS_WIDGET: {
|
||||
validations: {
|
||||
isLoading: "BOOLEAN",
|
||||
isVisible: "BOOLEAN",
|
||||
isDisabled: "BOOLEAN",
|
||||
},
|
||||
defaultProperties: {},
|
||||
derivedProperties: {},
|
||||
metaProperties: {},
|
||||
},
|
||||
ICON_WIDGET: {
|
||||
validations: {
|
||||
isLoading: "BOOLEAN",
|
||||
isVisible: "BOOLEAN",
|
||||
isDisabled: "BOOLEAN",
|
||||
},
|
||||
defaultProperties: {},
|
||||
derivedProperties: {},
|
||||
metaProperties: {},
|
||||
},
|
||||
SKELETON_WIDGET: {
|
||||
validations: {
|
||||
isLoading: "BOOLEAN",
|
||||
isVisible: "BOOLEAN",
|
||||
isDisabled: "BOOLEAN",
|
||||
},
|
||||
defaultProperties: {},
|
||||
derivedProperties: {},
|
||||
metaProperties: {},
|
||||
|
|
@ -416,6 +221,7 @@ const BASE_WIDGET: DataTreeWidget = {
|
|||
version: 1,
|
||||
bindingPaths: {},
|
||||
triggerPaths: {},
|
||||
validationPaths: {},
|
||||
ENTITY_TYPE: ENTITY_TYPE.WIDGET,
|
||||
};
|
||||
|
||||
|
|
@ -457,6 +263,9 @@ describe("DataTreeEvaluator", () => {
|
|||
bindingPaths: {
|
||||
text: true,
|
||||
},
|
||||
validationPaths: {
|
||||
text: VALIDATION_TYPES.TEXT,
|
||||
},
|
||||
},
|
||||
Text3: {
|
||||
...BASE_WIDGET,
|
||||
|
|
@ -467,6 +276,9 @@ describe("DataTreeEvaluator", () => {
|
|||
bindingPaths: {
|
||||
text: true,
|
||||
},
|
||||
validationPaths: {
|
||||
text: VALIDATION_TYPES.TEXT,
|
||||
},
|
||||
},
|
||||
Dropdown1: {
|
||||
...BASE_WIDGET,
|
||||
|
|
@ -506,6 +318,9 @@ describe("DataTreeEvaluator", () => {
|
|||
selectedRow: true,
|
||||
selectedRows: true,
|
||||
},
|
||||
validationPaths: {
|
||||
tableData: VALIDATION_TYPES.TABLE_DATA,
|
||||
},
|
||||
},
|
||||
Text4: {
|
||||
...BASE_WIDGET,
|
||||
|
|
@ -515,6 +330,9 @@ describe("DataTreeEvaluator", () => {
|
|||
bindingPaths: {
|
||||
text: true,
|
||||
},
|
||||
validationPaths: {
|
||||
text: VALIDATION_TYPES.TEXT,
|
||||
},
|
||||
},
|
||||
};
|
||||
const evaluator = new DataTreeEvaluator(WIDGET_CONFIG_MAP);
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ ctx.addEventListener(
|
|||
});
|
||||
console.error(e);
|
||||
}
|
||||
dataTree = getValidatedTree(widgetTypeConfigMap, unevalTree);
|
||||
dataTree = getValidatedTree(unevalTree);
|
||||
dataTreeEvaluator = undefined;
|
||||
}
|
||||
return {
|
||||
|
|
@ -148,21 +148,9 @@ ctx.addEventListener(
|
|||
return true;
|
||||
}
|
||||
case EVAL_WORKER_ACTIONS.VALIDATE_PROPERTY: {
|
||||
const {
|
||||
widgetType,
|
||||
widgetTypeConfigMap,
|
||||
property,
|
||||
value,
|
||||
props,
|
||||
} = requestData;
|
||||
const { property, value, props, validation } = requestData;
|
||||
return removeFunctions(
|
||||
validateWidgetProperty(
|
||||
widgetTypeConfigMap,
|
||||
widgetType,
|
||||
property,
|
||||
value,
|
||||
props,
|
||||
),
|
||||
validateWidgetProperty(property, value, props, validation),
|
||||
);
|
||||
}
|
||||
default: {
|
||||
|
|
|
|||
|
|
@ -3,9 +3,7 @@ import {
|
|||
isChildPropertyPath,
|
||||
isDynamicValue,
|
||||
} from "utils/DynamicBindingUtils";
|
||||
import { WidgetType } from "constants/WidgetConstants";
|
||||
import { WidgetProps } from "widgets/BaseWidget";
|
||||
import { WidgetTypeConfigMap } from "utils/WidgetFactory";
|
||||
import { VALIDATORS } from "./validations";
|
||||
import { Diff } from "deep-diff";
|
||||
import {
|
||||
|
|
@ -16,6 +14,7 @@ import {
|
|||
ENTITY_TYPE,
|
||||
} from "entities/DataTree/dataTreeFactory";
|
||||
import _ from "lodash";
|
||||
import { VALIDATION_TYPES } from "constants/WidgetValidation";
|
||||
|
||||
// Dropdown1.options[1].value -> Dropdown1.options[1]
|
||||
// Dropdown1.options[1] -> Dropdown1.options
|
||||
|
|
@ -61,6 +60,16 @@ function isInt(val: string | number): boolean {
|
|||
return !isNaN(parseInt(val));
|
||||
}
|
||||
|
||||
// Removes the entity name from the property path
|
||||
export function getEntityNameAndPropertyPath(
|
||||
fullPath: string,
|
||||
): { entityName: string; propertyPath: string } {
|
||||
const indexOfFirstDot = fullPath.indexOf(".");
|
||||
const entityName = fullPath.substring(0, indexOfFirstDot);
|
||||
const propertyPath = fullPath.substring(fullPath.indexOf(".") + 1);
|
||||
return { entityName, propertyPath };
|
||||
}
|
||||
|
||||
export const translateDiffEventToDataTreeDiffEvent = (
|
||||
difference: Diff<any, any>,
|
||||
): DataTreeDiff => {
|
||||
|
|
@ -244,73 +253,53 @@ export const getImmediateParentsOfPropertyPaths = (
|
|||
};
|
||||
|
||||
export function validateWidgetProperty(
|
||||
widgetConfigMap: WidgetTypeConfigMap,
|
||||
widgetType: WidgetType,
|
||||
property: string,
|
||||
value: any,
|
||||
props: WidgetProps,
|
||||
validation?: VALIDATION_TYPES,
|
||||
dataTree?: DataTree,
|
||||
) {
|
||||
const propertyValidationTypes = widgetConfigMap[widgetType].validations;
|
||||
const validationTypeOrValidator = propertyValidationTypes[property];
|
||||
let validator;
|
||||
|
||||
if (typeof validationTypeOrValidator === "function") {
|
||||
validator = validationTypeOrValidator;
|
||||
} else {
|
||||
validator = VALIDATORS[validationTypeOrValidator];
|
||||
}
|
||||
if (validator) {
|
||||
return validator(value, props, dataTree);
|
||||
} else {
|
||||
if (!validation) {
|
||||
return { isValid: true, parsed: value };
|
||||
}
|
||||
const validator = VALIDATORS[validation];
|
||||
if (!validator) {
|
||||
return { isValid: true, parsed: value };
|
||||
}
|
||||
return validator(value, props, dataTree);
|
||||
}
|
||||
|
||||
export function getValidatedTree(
|
||||
widgetConfigMap: WidgetTypeConfigMap,
|
||||
tree: DataTree,
|
||||
) {
|
||||
export function getValidatedTree(tree: DataTree) {
|
||||
return Object.keys(tree).reduce((tree, entityKey: string) => {
|
||||
const entity = tree[entityKey] as DataTreeWidget;
|
||||
if (!isWidget(entity)) {
|
||||
return tree;
|
||||
}
|
||||
const parsedEntity = { ...entity };
|
||||
Object.keys(entity).forEach((property: string) => {
|
||||
const validationProperties = widgetConfigMap[entity.type].validations;
|
||||
|
||||
if (property in validationProperties) {
|
||||
const value = _.get(entity, property);
|
||||
// Pass it through parse
|
||||
const {
|
||||
parsed,
|
||||
isValid,
|
||||
message,
|
||||
transformed,
|
||||
} = validateWidgetProperty(
|
||||
widgetConfigMap,
|
||||
entity.type,
|
||||
property,
|
||||
value,
|
||||
entity,
|
||||
tree,
|
||||
);
|
||||
parsedEntity[property] = parsed;
|
||||
const evaluatedValue = isValid
|
||||
? parsed
|
||||
: _.isUndefined(transformed)
|
||||
? value
|
||||
: transformed;
|
||||
const safeEvaluatedValue = removeFunctions(evaluatedValue);
|
||||
_.set(parsedEntity, `evaluatedValues.${property}`, safeEvaluatedValue);
|
||||
if (!isValid) {
|
||||
_.set(parsedEntity, `invalidProps.${property}`, true);
|
||||
_.set(parsedEntity, `validationMessages.${property}`, message);
|
||||
} else {
|
||||
_.set(parsedEntity, `invalidProps.${property}`, false);
|
||||
_.set(parsedEntity, `validationMessages.${property}`, "");
|
||||
}
|
||||
Object.entries(entity.validationPaths).forEach(([property, validation]) => {
|
||||
const value = _.get(entity, property);
|
||||
// Pass it through parse
|
||||
const { parsed, isValid, message, transformed } = validateWidgetProperty(
|
||||
property,
|
||||
value,
|
||||
entity,
|
||||
validation,
|
||||
tree,
|
||||
);
|
||||
_.set(parsedEntity, property, parsed);
|
||||
const evaluatedValue = isValid
|
||||
? parsed
|
||||
: _.isUndefined(transformed)
|
||||
? value
|
||||
: transformed;
|
||||
const safeEvaluatedValue = removeFunctions(evaluatedValue);
|
||||
_.set(parsedEntity, `evaluatedValues.${property}`, safeEvaluatedValue);
|
||||
if (!isValid) {
|
||||
_.set(parsedEntity, `invalidProps.${property}`, true);
|
||||
_.set(parsedEntity, `validationMessages.${property}`, message);
|
||||
} else {
|
||||
_.set(parsedEntity, `invalidProps.${property}`, false);
|
||||
_.set(parsedEntity, `validationMessages.${property}`, "");
|
||||
}
|
||||
});
|
||||
return { ...tree, [entityKey]: parsedEntity };
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ import {
|
|||
ISO_DATE_FORMAT,
|
||||
VALIDATION_TYPES,
|
||||
ValidationResponse,
|
||||
ValidationType,
|
||||
Validator,
|
||||
} from "../constants/WidgetValidation";
|
||||
import { DataTree } from "../entities/DataTree/dataTreeFactory";
|
||||
|
|
@ -48,7 +47,7 @@ export function validateDateString(
|
|||
|
||||
const WIDGET_TYPE_VALIDATION_ERROR = "Value does not match type"; // TODO: Lot's of changes in validations.ts file
|
||||
|
||||
export const VALIDATORS: Record<ValidationType, Validator> = {
|
||||
export const VALIDATORS: Record<VALIDATION_TYPES, Validator> = {
|
||||
[VALIDATION_TYPES.TEXT]: (value: any): ValidationResponse => {
|
||||
let parsed = value;
|
||||
if (isUndefined(value) || value === null) {
|
||||
|
|
|
|||
|
|
@ -3504,11 +3504,6 @@
|
|||
dependencies:
|
||||
"@types/tern" "*"
|
||||
|
||||
"@types/component-emitter@^1.2.10":
|
||||
version "1.2.10"
|
||||
resolved "https://registry.yarnpkg.com/@types/component-emitter/-/component-emitter-1.2.10.tgz#ef5b1589b9f16544642e473db5ea5639107ef3ea"
|
||||
integrity sha512-bsjleuRKWmGqajMerkzox19aGbscQX5rmmvvXl3wlIp5gMG1HgkiwPxsN5p070fBDKTNSPgojVbuY1+HWMbFhg==
|
||||
|
||||
"@types/cookie@^0.4.0":
|
||||
version "0.4.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/cookie/-/cookie-0.4.0.tgz#14f854c0f93d326e39da6e3b6f34f7d37513d108"
|
||||
|
|
@ -6920,7 +6915,7 @@ debug@4, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1:
|
|||
dependencies:
|
||||
ms "2.1.2"
|
||||
|
||||
debug@^4.3.0, debug@~4.3.1:
|
||||
debug@^4.3.0:
|
||||
version "4.3.1"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.1.tgz#f0d229c505e0c6d8c49ac553d1b13dc183f6b2ee"
|
||||
integrity sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==
|
||||
|
|
@ -8197,6 +8192,7 @@ fd-slicer@~1.1.0:
|
|||
figgy-pudding@^3.5.1:
|
||||
version "3.5.2"
|
||||
resolved "https://registry.yarnpkg.com/figgy-pudding/-/figgy-pudding-3.5.2.tgz#b4eee8148abb01dcf1d1ac34367d59e12fa61d6e"
|
||||
integrity sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw==
|
||||
|
||||
figures@^1.7.0:
|
||||
version "1.7.0"
|
||||
|
|
@ -11106,7 +11102,7 @@ lodash.uniq@4.5.0, lodash.uniq@^4.5.0:
|
|||
version "4.5.0"
|
||||
resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773"
|
||||
|
||||
lodash@4.x:
|
||||
lodash@4.x, lodash@^4.6.1:
|
||||
version "4.17.21"
|
||||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
|
||||
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
|
||||
|
|
@ -11115,11 +11111,6 @@ lodash@4.x:
|
|||
version "4.17.20"
|
||||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52"
|
||||
|
||||
lodash@^4.6.1:
|
||||
version "4.17.21"
|
||||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
|
||||
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
|
||||
|
||||
log-symbols@3.0.0, log-symbols@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-3.0.0.tgz#f3a08516a5dea893336a7dee14d18a1cfdab77c4"
|
||||
|
|
@ -15666,8 +15657,9 @@ sshpk@^1.7.0:
|
|||
tweetnacl "~0.14.0"
|
||||
|
||||
ssri@^6.0.1:
|
||||
version "6.0.1"
|
||||
resolved "https://registry.yarnpkg.com/ssri/-/ssri-6.0.1.tgz#2a3c41b28dd45b62b63676ecb74001265ae9edd8"
|
||||
version "6.0.2"
|
||||
resolved "https://registry.yarnpkg.com/ssri/-/ssri-6.0.2.tgz#157939134f20464e7301ddba3e90ffa8f7728ac5"
|
||||
integrity sha512-cepbSq/neFK7xB6A50KHN0xHDotYzq58wWCa5LeWqnPrHG8GzfEjO/4O8kpmcGW+oaxkvhEJCWgbgNk4/ZV93Q==
|
||||
dependencies:
|
||||
figgy-pudding "^3.5.1"
|
||||
|
||||
|
|
|
|||
|
|
@ -30,4 +30,4 @@ In order to test the code, you can run the following command:
|
|||
mvn -B clean package
|
||||
```
|
||||
|
||||
Please make sure that you have a local Redis instance running for the test cases. During tests, the MongoDB is run in-memory. So you don't require to be running a local MongoDB instance.
|
||||
Please make sure that you have a local Redis instance running for the test cases. During tests, the MongoDB is run in-memory. So you don't require to be running a local MongoDB instance.
|
||||
|
|
|
|||
|
|
@ -58,8 +58,9 @@ public class DocumentTypeMapper implements TypeInformationMapper {
|
|||
|
||||
@Override
|
||||
public TypeInformation<?> resolveTypeFrom(Alias alias) {
|
||||
if (aliasToTypeMap.containsKey((String) alias.getValue())) {
|
||||
return aliasToTypeMap.get(alias.getValue());
|
||||
final String aliasAsString = alias.mapTyped(String.class);
|
||||
if (aliasAsString != null && aliasToTypeMap.containsKey(aliasAsString)) {
|
||||
return aliasToTypeMap.get(aliasAsString);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,6 +38,9 @@ public class EncryptionHandler {
|
|||
// At this point source class represents the true polymorphic type of the document
|
||||
Class<?> sourceClass = source.getClass();
|
||||
|
||||
// Lock a thread wanting to find information about the same type
|
||||
// So that this information retrieval is only done once
|
||||
// Ignore this warning, this class reference will be on the heap
|
||||
List<CandidateField> candidateFields = this.encryptedFieldsMap.get(sourceClass);
|
||||
|
||||
if (candidateFields != null) {
|
||||
|
|
@ -192,6 +195,7 @@ public class EncryptionHandler {
|
|||
encryptedFieldsMap.put(sourceClass, finalCandidateFields);
|
||||
|
||||
return finalCandidateFields;
|
||||
|
||||
}
|
||||
|
||||
boolean convertEncryption(Object source, Function<String, String> transformer) {
|
||||
|
|
@ -243,7 +247,6 @@ public class EncryptionHandler {
|
|||
// unknown types as polymorphic candidates over time
|
||||
// If that is the case then do we need to store the candidate field type by
|
||||
// known, unknown or polymorphic types at all?
|
||||
// TODO Discuss w/ reviewer
|
||||
}
|
||||
} else {
|
||||
final Type[] typeNames = ((ParameterizedType) field.getGenericType()).getActualTypeArguments();
|
||||
|
|
|
|||
|
|
@ -16,14 +16,14 @@ public class Property {
|
|||
/*
|
||||
* A convenience constructor to create a Property object with just a key and a value.
|
||||
*/
|
||||
public Property(String key, String value) {
|
||||
public Property(String key, Object value) {
|
||||
this.key = key;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
String key;
|
||||
|
||||
String value;
|
||||
Object value;
|
||||
|
||||
Boolean editable;
|
||||
|
||||
|
|
|
|||
|
|
@ -315,7 +315,7 @@ public class AmazonS3Plugin extends BasePlugin {
|
|||
}
|
||||
|
||||
|
||||
AmazonS3Action s3Action = AmazonS3Action.valueOf(properties.get(ACTION_PROPERTY_INDEX).getValue());
|
||||
AmazonS3Action s3Action = AmazonS3Action.valueOf((String) properties.get(ACTION_PROPERTY_INDEX).getValue());
|
||||
query[0] = s3Action.name();
|
||||
|
||||
if (properties.size() < (1 + BUCKET_NAME_PROPERTY_INDEX)
|
||||
|
|
@ -329,7 +329,7 @@ public class AmazonS3Plugin extends BasePlugin {
|
|||
);
|
||||
}
|
||||
|
||||
final String bucketName = properties.get(BUCKET_NAME_PROPERTY_INDEX).getValue();
|
||||
final String bucketName = (String) properties.get(BUCKET_NAME_PROPERTY_INDEX).getValue();
|
||||
requestProperties.put("bucket", bucketName == null ? "" : bucketName);
|
||||
|
||||
if (StringUtils.isEmpty(bucketName)) {
|
||||
|
|
@ -378,7 +378,7 @@ public class AmazonS3Plugin extends BasePlugin {
|
|||
if (properties.size() > PREFIX_PROPERTY_INDEX
|
||||
&& properties.get(PREFIX_PROPERTY_INDEX) != null
|
||||
&& properties.get(PREFIX_PROPERTY_INDEX).getValue() != null) {
|
||||
prefix = properties.get(PREFIX_PROPERTY_INDEX).getValue();
|
||||
prefix = (String) properties.get(PREFIX_PROPERTY_INDEX).getValue();
|
||||
}
|
||||
|
||||
ArrayList<String> listOfFiles = listAllFilesInBucket(connection, bucketName, prefix);
|
||||
|
|
@ -390,13 +390,13 @@ public class AmazonS3Plugin extends BasePlugin {
|
|||
int durationInMinutes;
|
||||
if (properties.size() < (1 + URL_EXPIRY_DURATION_PROPERTY_INDEX)
|
||||
|| properties.get(URL_EXPIRY_DURATION_PROPERTY_INDEX) == null
|
||||
|| StringUtils.isEmpty(properties.get(URL_EXPIRY_DURATION_PROPERTY_INDEX).getValue())) {
|
||||
|| StringUtils.isEmpty((String) properties.get(URL_EXPIRY_DURATION_PROPERTY_INDEX).getValue())) {
|
||||
durationInMinutes = DEFAULT_URL_EXPIRY_IN_MINUTES;
|
||||
} else {
|
||||
try {
|
||||
durationInMinutes = Integer
|
||||
.parseInt(
|
||||
properties
|
||||
(String) properties
|
||||
.get(URL_EXPIRY_DURATION_PROPERTY_INDEX)
|
||||
.getValue()
|
||||
);
|
||||
|
|
@ -451,13 +451,13 @@ public class AmazonS3Plugin extends BasePlugin {
|
|||
int durationInMinutes;
|
||||
if (properties.size() < (1 + URL_EXPIRY_DURATION_FOR_UPLOAD_PROPERTY_INDEX)
|
||||
|| properties.get(URL_EXPIRY_DURATION_FOR_UPLOAD_PROPERTY_INDEX) == null
|
||||
|| StringUtils.isEmpty(properties.get(URL_EXPIRY_DURATION_FOR_UPLOAD_PROPERTY_INDEX).getValue())) {
|
||||
|| StringUtils.isEmpty((String) properties.get(URL_EXPIRY_DURATION_FOR_UPLOAD_PROPERTY_INDEX).getValue())) {
|
||||
durationInMinutes = DEFAULT_URL_EXPIRY_IN_MINUTES;
|
||||
} else {
|
||||
try {
|
||||
durationInMinutes = Integer
|
||||
.parseInt(
|
||||
properties
|
||||
(String) properties
|
||||
.get(URL_EXPIRY_DURATION_FOR_UPLOAD_PROPERTY_INDEX)
|
||||
.getValue()
|
||||
);
|
||||
|
|
@ -591,7 +591,7 @@ public class AmazonS3Plugin extends BasePlugin {
|
|||
*/
|
||||
if (properties == null
|
||||
|| properties.get(S3_SERVICE_PROVIDER_PROPERTY_INDEX) == null
|
||||
|| StringUtils.isEmpty(properties.get(S3_SERVICE_PROVIDER_PROPERTY_INDEX).getValue())) {
|
||||
|| StringUtils.isEmpty((String) properties.get(S3_SERVICE_PROVIDER_PROPERTY_INDEX).getValue())) {
|
||||
return Mono.error(
|
||||
new AppsmithPluginException(
|
||||
AppsmithPluginError.PLUGIN_DATASOURCE_ARGUMENT_ERROR,
|
||||
|
|
@ -607,7 +607,7 @@ public class AmazonS3Plugin extends BasePlugin {
|
|||
if (!usingCustomEndpoint
|
||||
&& (properties.size() < (AWS_S3_REGION_PROPERTY_INDEX + 1)
|
||||
|| properties.get(AWS_S3_REGION_PROPERTY_INDEX) == null
|
||||
|| StringUtils.isEmpty(properties.get(AWS_S3_REGION_PROPERTY_INDEX).getValue()))) {
|
||||
|| StringUtils.isEmpty((String) properties.get(AWS_S3_REGION_PROPERTY_INDEX).getValue()))) {
|
||||
return Mono.error(
|
||||
new AppsmithPluginException(
|
||||
AppsmithPluginError.PLUGIN_DATASOURCE_ARGUMENT_ERROR,
|
||||
|
|
@ -636,7 +636,7 @@ public class AmazonS3Plugin extends BasePlugin {
|
|||
if (usingCustomEndpoint
|
||||
&& (properties.size() < (CUSTOM_ENDPOINT_REGION_PROPERTY_INDEX + 1)
|
||||
|| properties.get(CUSTOM_ENDPOINT_REGION_PROPERTY_INDEX) == null
|
||||
|| StringUtils.isEmpty(properties.get(CUSTOM_ENDPOINT_REGION_PROPERTY_INDEX).getValue()))) {
|
||||
|| StringUtils.isEmpty((String) properties.get(CUSTOM_ENDPOINT_REGION_PROPERTY_INDEX).getValue()))) {
|
||||
return Mono.error(
|
||||
new AppsmithPluginException(
|
||||
AppsmithPluginError.PLUGIN_DATASOURCE_ARGUMENT_ERROR,
|
||||
|
|
@ -647,9 +647,9 @@ public class AmazonS3Plugin extends BasePlugin {
|
|||
);
|
||||
}
|
||||
|
||||
final String region = usingCustomEndpoint ?
|
||||
properties.get(CUSTOM_ENDPOINT_REGION_PROPERTY_INDEX).getValue() :
|
||||
properties.get(AWS_S3_REGION_PROPERTY_INDEX).getValue();
|
||||
final String region = (String) (usingCustomEndpoint ?
|
||||
properties.get(CUSTOM_ENDPOINT_REGION_PROPERTY_INDEX).getValue() :
|
||||
properties.get(AWS_S3_REGION_PROPERTY_INDEX).getValue());
|
||||
|
||||
DBAuth authentication = (DBAuth) datasourceConfiguration.getAuthentication();
|
||||
if (authentication == null
|
||||
|
|
@ -776,7 +776,7 @@ public class AmazonS3Plugin extends BasePlugin {
|
|||
*/
|
||||
if (properties == null
|
||||
|| properties.get(S3_SERVICE_PROVIDER_PROPERTY_INDEX) == null
|
||||
|| StringUtils.isEmpty(properties.get(S3_SERVICE_PROVIDER_PROPERTY_INDEX).getValue())) {
|
||||
|| StringUtils.isEmpty((String) properties.get(S3_SERVICE_PROVIDER_PROPERTY_INDEX).getValue())) {
|
||||
invalids.add("Appsmith has failed to fetch the 'S3 Service Provider' field properties. Please " +
|
||||
"reach out to Appsmith customer support to resolve this.");
|
||||
}
|
||||
|
|
@ -786,7 +786,7 @@ public class AmazonS3Plugin extends BasePlugin {
|
|||
if (!usingCustomEndpoint
|
||||
&& (properties.size() < (AWS_S3_REGION_PROPERTY_INDEX + 1)
|
||||
|| properties.get(AWS_S3_REGION_PROPERTY_INDEX) == null
|
||||
|| StringUtils.isEmpty(properties.get(AWS_S3_REGION_PROPERTY_INDEX).getValue()))) {
|
||||
|| StringUtils.isEmpty((String) properties.get(AWS_S3_REGION_PROPERTY_INDEX).getValue()))) {
|
||||
invalids.add("Required parameter 'Region' is empty. Did you forget to edit the 'Region' field" +
|
||||
" in the datasource creation form ? You need to fill it with the region where " +
|
||||
"your AWS S3 instance is hosted.");
|
||||
|
|
@ -805,7 +805,7 @@ public class AmazonS3Plugin extends BasePlugin {
|
|||
if (usingCustomEndpoint
|
||||
&& (properties.size() < (CUSTOM_ENDPOINT_REGION_PROPERTY_INDEX + 1)
|
||||
|| properties.get(CUSTOM_ENDPOINT_REGION_PROPERTY_INDEX) == null
|
||||
|| StringUtils.isEmpty(properties.get(CUSTOM_ENDPOINT_REGION_PROPERTY_INDEX).getValue()))) {
|
||||
|| StringUtils.isEmpty((String) properties.get(CUSTOM_ENDPOINT_REGION_PROPERTY_INDEX).getValue()))) {
|
||||
invalids.add("Required parameter 'Region' is empty. Did you forget to edit the 'Region' field" +
|
||||
" in the datasource creation form ? You need to fill it with the region where " +
|
||||
"your S3 instance is hosted.");
|
||||
|
|
|
|||
|
|
@ -187,7 +187,7 @@ public class ElasticSearchPlugin extends BasePlugin {
|
|||
clientBuilder.setDefaultHeaders(
|
||||
(Header[]) datasourceConfiguration.getHeaders()
|
||||
.stream()
|
||||
.map(h -> new BasicHeader(h.getKey(), h.getValue()))
|
||||
.map(h -> new BasicHeader(h.getKey(), (String) h.getValue()))
|
||||
.toArray()
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,7 +43,6 @@ import java.io.IOException;
|
|||
import java.io.InputStream;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
|
|
@ -114,7 +113,7 @@ public class FirestorePlugin extends BasePlugin {
|
|||
final List<Property> properties = actionConfiguration.getPluginSpecifiedTemplates();
|
||||
final com.external.plugins.Method method = CollectionUtils.isEmpty(properties)
|
||||
? null
|
||||
: com.external.plugins.Method.valueOf(properties.get(0).getValue());
|
||||
: com.external.plugins.Method.valueOf((String) properties.get(0).getValue());
|
||||
requestData.put("method", method == null ? "" : method.toString());
|
||||
|
||||
final PaginationField paginationField = executeActionDTO == null ? null : executeActionDTO.getPaginationField();
|
||||
|
|
@ -189,10 +188,10 @@ public class FirestorePlugin extends BasePlugin {
|
|||
|| Method.CREATE_DOCUMENT.equals(method) || Method.ADD_TO_COLLECTION.equals(method))
|
||||
&& (properties == null || ((properties.size() < FIELDVALUE_TIMESTAMP_PROPERTY_INDEX + 1
|
||||
|| properties.get(FIELDVALUE_TIMESTAMP_PROPERTY_INDEX) == null
|
||||
|| StringUtils.isEmpty(properties.get(FIELDVALUE_TIMESTAMP_PROPERTY_INDEX).getValue()))
|
||||
|| StringUtils.isEmpty((String) properties.get(FIELDVALUE_TIMESTAMP_PROPERTY_INDEX).getValue()))
|
||||
&& (properties.size() < FIELDVALUE_DELETE_PROPERTY_INDEX
|
||||
|| properties.get(FIELDVALUE_DELETE_PROPERTY_INDEX) == null
|
||||
|| StringUtils.isEmpty(properties.get(FIELDVALUE_DELETE_PROPERTY_INDEX).getValue()))))) {
|
||||
|| StringUtils.isEmpty((String) properties.get(FIELDVALUE_DELETE_PROPERTY_INDEX).getValue()))))) {
|
||||
return Mono.error(new AppsmithPluginException(
|
||||
AppsmithPluginError.PLUGIN_EXECUTE_ARGUMENT_ERROR,
|
||||
"The method " + method.toString() + " needs at least one of the following " +
|
||||
|
|
@ -250,7 +249,7 @@ public class FirestorePlugin extends BasePlugin {
|
|||
if(!Method.UPDATE_DOCUMENT.equals(method)
|
||||
&& properties.size() > FIELDVALUE_DELETE_PROPERTY_INDEX
|
||||
&& properties.get(FIELDVALUE_DELETE_PROPERTY_INDEX) != null
|
||||
&& !StringUtils.isEmpty(properties.get(FIELDVALUE_DELETE_PROPERTY_INDEX).getValue())) {
|
||||
&& !StringUtils.isEmpty((String) properties.get(FIELDVALUE_DELETE_PROPERTY_INDEX).getValue())) {
|
||||
throw new AppsmithPluginException(
|
||||
AppsmithPluginError.PLUGIN_ERROR,
|
||||
"Appsmith has found an unexpected query form property - 'Delete Key Value Pair Path'. Please " +
|
||||
|
|
@ -263,8 +262,8 @@ public class FirestorePlugin extends BasePlugin {
|
|||
*/
|
||||
if( properties.size() > FIELDVALUE_DELETE_PROPERTY_INDEX
|
||||
&& properties.get(FIELDVALUE_DELETE_PROPERTY_INDEX) != null
|
||||
&& !StringUtils.isEmpty(properties.get(FIELDVALUE_DELETE_PROPERTY_INDEX).getValue())) {
|
||||
String deletePaths = properties.get(FIELDVALUE_DELETE_PROPERTY_INDEX).getValue();
|
||||
&& !StringUtils.isEmpty((String) properties.get(FIELDVALUE_DELETE_PROPERTY_INDEX).getValue())) {
|
||||
String deletePaths = (String) properties.get(FIELDVALUE_DELETE_PROPERTY_INDEX).getValue();
|
||||
List<String> deletePathsList;
|
||||
try {
|
||||
deletePathsList = objectMapper.readValue(deletePaths, new TypeReference<List<String>>(){});
|
||||
|
|
@ -297,7 +296,7 @@ public class FirestorePlugin extends BasePlugin {
|
|||
|| Method.DELETE_DOCUMENT.equals(method))
|
||||
&& properties.size() > FIELDVALUE_TIMESTAMP_PROPERTY_INDEX
|
||||
&& properties.get(FIELDVALUE_TIMESTAMP_PROPERTY_INDEX) != null
|
||||
&& !StringUtils.isEmpty(properties.get(FIELDVALUE_TIMESTAMP_PROPERTY_INDEX).getValue())) {
|
||||
&& !StringUtils.isEmpty((String) properties.get(FIELDVALUE_TIMESTAMP_PROPERTY_INDEX).getValue())) {
|
||||
throw new AppsmithPluginException(
|
||||
AppsmithPluginError.PLUGIN_ERROR,
|
||||
"Appsmith has found an unexpected query form property - 'Timestamp Value Path'. Please reach " +
|
||||
|
|
@ -310,8 +309,8 @@ public class FirestorePlugin extends BasePlugin {
|
|||
*/
|
||||
if(properties.size() > FIELDVALUE_TIMESTAMP_PROPERTY_INDEX
|
||||
&& properties.get(FIELDVALUE_TIMESTAMP_PROPERTY_INDEX) != null
|
||||
&& !StringUtils.isEmpty(properties.get(FIELDVALUE_TIMESTAMP_PROPERTY_INDEX).getValue())) {
|
||||
String timestampValuePaths = properties.get(FIELDVALUE_TIMESTAMP_PROPERTY_INDEX).getValue();
|
||||
&& !StringUtils.isEmpty((String) properties.get(FIELDVALUE_TIMESTAMP_PROPERTY_INDEX).getValue())) {
|
||||
String timestampValuePaths = (String) properties.get(FIELDVALUE_TIMESTAMP_PROPERTY_INDEX).getValue();
|
||||
List<String> timestampPathsStringList; // ["key1.key2", "key3.key4"]
|
||||
try {
|
||||
timestampPathsStringList = objectMapper.readValue(timestampValuePaths,
|
||||
|
|
@ -511,7 +510,7 @@ public class FirestorePlugin extends BasePlugin {
|
|||
return defaultValue;
|
||||
}
|
||||
|
||||
final String value = property.getValue();
|
||||
final String value = (String) property.getValue();
|
||||
return value != null ? value : defaultValue;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -129,7 +129,14 @@ public class MongoPlugin extends BasePlugin {
|
|||
|
||||
// Since properties is not empty, we are guaranteed to find the first property.
|
||||
} else if (properties.get(SMART_BSON_SUBSTITUTION_INDEX) != null){
|
||||
smartBsonSubstitution = Boolean.parseBoolean(properties.get(SMART_BSON_SUBSTITUTION_INDEX).getValue());
|
||||
Object ssubValue = properties.get(SMART_BSON_SUBSTITUTION_INDEX).getValue();
|
||||
if (ssubValue instanceof Boolean) {
|
||||
smartBsonSubstitution = (Boolean) ssubValue;
|
||||
} else if (ssubValue instanceof String) {
|
||||
smartBsonSubstitution = Boolean.parseBoolean((String) ssubValue);
|
||||
} else {
|
||||
smartBsonSubstitution = false;
|
||||
}
|
||||
} else {
|
||||
smartBsonSubstitution = false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"dependencies" : {
|
||||
"actionConfiguration.body" : ["actionConfiguration.pluginSpecifiedTemplates[0].value"]
|
||||
}
|
||||
}
|
||||
|
|
@ -11,8 +11,11 @@
|
|||
"evaluationSubstitutionType": "SMART_SUBSTITUTE",
|
||||
"hidden": {
|
||||
"path": "actionConfiguration.pluginSpecifiedTemplates[0].value",
|
||||
"comparison": "EQUALS",
|
||||
"value": "false"
|
||||
"comparison": "IN",
|
||||
"value": [
|
||||
"false",
|
||||
false
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
@ -22,8 +25,11 @@
|
|||
"evaluationSubstitutionType": "TEMPLATE",
|
||||
"hidden": {
|
||||
"path": "actionConfiguration.pluginSpecifiedTemplates[0].value",
|
||||
"comparison": "EQUALS",
|
||||
"value": "true"
|
||||
"comparison": "IN",
|
||||
"value": [
|
||||
"true",
|
||||
true
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@
|
|||
"info": "Turning on this property fixes the BSON substitution of bindings in the Mongo BSON document by adding/removing quotes intelligently and reduces developer errors",
|
||||
"configProperty": "actionConfiguration.pluginSpecifiedTemplates[0].value",
|
||||
"controlType": "SWITCH",
|
||||
"initialValue": "false"
|
||||
"initialValue": false
|
||||
},
|
||||
{
|
||||
"label": "Query timeout (in milliseconds)",
|
||||
|
|
|
|||
|
|
@ -123,7 +123,14 @@ public class MssqlPlugin extends BasePlugin {
|
|||
*/
|
||||
isPreparedStatement = false;
|
||||
} else if (properties.get(PREPARED_STATEMENT_INDEX) != null){
|
||||
isPreparedStatement = Boolean.parseBoolean(properties.get(PREPARED_STATEMENT_INDEX).getValue());
|
||||
Object psValue = properties.get(PREPARED_STATEMENT_INDEX).getValue();
|
||||
if (psValue instanceof Boolean) {
|
||||
isPreparedStatement = (Boolean) psValue;
|
||||
} else if (psValue instanceof String) {
|
||||
isPreparedStatement = Boolean.parseBoolean((String) psValue);
|
||||
} else {
|
||||
isPreparedStatement = false;
|
||||
}
|
||||
} else {
|
||||
isPreparedStatement = false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"dependencies" : {
|
||||
"actionConfiguration.body" : ["actionConfiguration.pluginSpecifiedTemplates[0].value"]
|
||||
}
|
||||
}
|
||||
|
|
@ -11,8 +11,11 @@
|
|||
"evaluationSubstitutionType": "PARAMETER",
|
||||
"hidden": {
|
||||
"path": "actionConfiguration.pluginSpecifiedTemplates[0].value",
|
||||
"comparison": "EQUALS",
|
||||
"value": "false"
|
||||
"comparison": "IN",
|
||||
"value": [
|
||||
"false",
|
||||
false
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
@ -22,8 +25,11 @@
|
|||
"evaluationSubstitutionType": "TEMPLATE",
|
||||
"hidden": {
|
||||
"path": "actionConfiguration.pluginSpecifiedTemplates[0].value",
|
||||
"comparison": "EQUALS",
|
||||
"value": "true"
|
||||
"comparison": "IN",
|
||||
"value": [
|
||||
"true",
|
||||
true
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@
|
|||
"info": "Turning on Prepared Statement makes the query parametrized. This in turn makes it resilient against SQL injections",
|
||||
"configProperty": "actionConfiguration.pluginSpecifiedTemplates[0].value",
|
||||
"controlType": "SWITCH",
|
||||
"initialValue": "false"
|
||||
"initialValue": false
|
||||
},
|
||||
{
|
||||
"label": "Query timeout (in milliseconds)",
|
||||
|
|
|
|||
|
|
@ -166,7 +166,14 @@ public class MySqlPlugin extends BasePlugin {
|
|||
*/
|
||||
isPreparedStatement = false;
|
||||
} else if (properties.get(PREPARED_STATEMENT_INDEX) != null){
|
||||
isPreparedStatement = Boolean.parseBoolean(properties.get(PREPARED_STATEMENT_INDEX).getValue());
|
||||
Object psValue = properties.get(PREPARED_STATEMENT_INDEX).getValue();
|
||||
if (psValue instanceof Boolean) {
|
||||
isPreparedStatement = (Boolean) psValue;
|
||||
} else if (psValue instanceof String) {
|
||||
isPreparedStatement = Boolean.parseBoolean((String) psValue);
|
||||
} else {
|
||||
isPreparedStatement = false;
|
||||
}
|
||||
} else {
|
||||
isPreparedStatement = false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"dependencies" : {
|
||||
"actionConfiguration.body" : ["actionConfiguration.pluginSpecifiedTemplates[0].value"]
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user