mirror of
https://github.com/ToolJet/ToolJet
synced 2026-05-23 08:58:26 +00:00
Merge branch 'main' into appbuilder/sprint-9
This commit is contained in:
commit
a907554b28
1296 changed files with 100484 additions and 12385 deletions
2
.github/workflows/docs-pr-app.yml
vendored
2
.github/workflows/docs-pr-app.yml
vendored
|
|
@ -53,7 +53,7 @@ jobs:
|
|||
],
|
||||
"serviceDetails": {
|
||||
"pullRequestPreviewsEnabled": "no",
|
||||
"buildCommand": "bash build-latest-version.sh",
|
||||
"buildCommand": "npm i && npm run build",
|
||||
"publishPath": "build/",
|
||||
"url": "https://tooljet-pr-${{ env.PR_NUMBER }}.onrender.com"
|
||||
}
|
||||
|
|
|
|||
54
README.md
54
README.md
|
|
@ -46,13 +46,7 @@ ToolJet is an **open-source low-code framework** to build and deploy internal to
|
|||
<hr>
|
||||
|
||||
## Quickstart
|
||||
The easiest way to get started with ToolJet is by creating a [ToolJet Cloud](https://tooljet.com) account. ToolJet Cloud offers a hosted solution of ToolJet. If you want to self-host ToolJet, kindly proceed to [deployment documentation](https://docs.tooljet.com/docs/setup/).
|
||||
|
||||
You can deploy ToolJet on DigitalOcean using one-click-deployment.
|
||||
|
||||
<p align="center">
|
||||
<a href="https://cloud.digitalocean.com/apps/new?repo=https://github.com/ToolJet/ToolJet/tree/main"><img src="https://www.deploytodo.com/do-btn-blue.svg" alt="Deploy to DigitalOcean" height=32></a>
|
||||
</p>
|
||||
The easiest way to get started with ToolJet is by creating a [ToolJet Cloud](https://tooljet.ai) account. ToolJet Cloud offers a hosted solution of ToolJet. If you want to self-host ToolJet, kindly proceed to [deployment documentation](https://docs.tooljet.ai/docs/setup/).
|
||||
|
||||
### Try using Docker
|
||||
Want to give ToolJet a quick spin on your local machine? You can run the following command from your terminal to have ToolJet up and running right away.
|
||||
|
|
@ -65,42 +59,42 @@ docker run \
|
|||
-p 80:80 \
|
||||
--platform linux/amd64 \
|
||||
-v tooljet_data:/var/lib/postgresql/13/main \
|
||||
tooljet/try:EE-LTS-latest
|
||||
tooljet/try:ee-lts-latest
|
||||
```
|
||||
|
||||
*For users upgrading their ToolJet version, we recommend choosing the LTS version over the latest version. The LTS version ensures stability with production bug fixes, security patches, and performance enhancements.*
|
||||
|
||||
## Tutorials and examples
|
||||
|
||||
[Time Tracker Application](https://docs.tooljet.com/docs/#quickstart-guide)<br>
|
||||
[Build your own CMS using low-code](https://blog.tooljet.com/build-cms-using-lowcode-and-mongodb/)<br>
|
||||
[AWS S3 Browser](https://blog.tooljet.com/build-an-aws-s3-broswer-with-tooljet/)<br>
|
||||
[Time Tracker Application](https://docs.tooljet.ai/docs/#quickstart-guide)<br>
|
||||
[Build your own CMS using low-code](https://blog.tooljet.ai/build-cms-using-lowcode-and-mongodb/)<br>
|
||||
[AWS S3 Browser](https://blog.tooljet.ai/build-an-aws-s3-broswer-with-tooljet/)<br>
|
||||
|
||||
## Documentation
|
||||
Documentation is available at https://docs.tooljet.com.
|
||||
Documentation is available at https://docs.tooljet.ai.
|
||||
|
||||
- [Getting Started](https://docs.tooljet.com)<br>
|
||||
- [Data source Reference](https://docs.tooljet.com/docs/data-sources/airtable/)<br>
|
||||
- [Component Reference](https://docs.tooljet.com/docs/widgets/button)
|
||||
- [Getting Started](https://docs.tooljet.ai)<br>
|
||||
- [Data source Reference](https://docs.tooljet.ai/docs/data-sources/airtable/)<br>
|
||||
- [Component Reference](https://docs.tooljet.ai/docs/widgets/button)
|
||||
|
||||
## Self-hosted
|
||||
You can use ToolJet Cloud for a fully managed solution. If you want to self-host ToolJet, we have guides on deploying ToolJet on Kubernetes, AWS EC2, Docker, and more.
|
||||
|
||||
| Provider | Documentation |
|
||||
| :------------- | :------------- |
|
||||
| Digital Ocean | [Link](https://docs.tooljet.com/docs/setup/digitalocean) |
|
||||
| Docker | [Link](https://docs.tooljet.com/docs/setup/docker) |
|
||||
| AWS EC2 | [Link](https://docs.tooljet.com/docs/setup/ec2) |
|
||||
| AWS ECS | [Link](https://docs.tooljet.com/docs/setup/ecs) |
|
||||
| OpenShift | [Link](https://docs.tooljet.com/docs/setup/openshift) |
|
||||
| Helm | [Link](https://docs.tooljet.com/docs/setup/helm) |
|
||||
| AWS EKS (Kubernetes) | [Link](https://docs.tooljet.com/docs/setup/kubernetes) |
|
||||
| GCP GKE (Kubernetes) | [Link](https://docs.tooljet.com/docs/setup/kubernetes-gke) |
|
||||
| Azure AKS (Kubernetes) | [Link](https://docs.tooljet.com/docs/setup/kubernetes-aks) |
|
||||
| Azure Container | [Link](https://docs.tooljet.com/docs/setup/azure-container) |
|
||||
| Google Cloud Run | [Link](https://docs.tooljet.com/docs/setup/google-cloud-run) |
|
||||
| Deploying ToolJet client | [Link](https://docs.tooljet.com/docs/setup/client) |
|
||||
| Deploying ToolJet on a Subpath | [Link](https://docs.tooljet.com/docs/setup/tooljet-subpath/) |
|
||||
| Digital Ocean | [Link](https://docs.tooljet.ai/docs/setup/digitalocean) |
|
||||
| Docker | [Link](https://docs.tooljet.ai/docs/setup/docker) |
|
||||
| AWS EC2 | [Link](https://docs.tooljet.ai/docs/setup/ec2) |
|
||||
| AWS ECS | [Link](https://docs.tooljet.ai/docs/setup/ecs) |
|
||||
| OpenShift | [Link](https://docs.tooljet.ai/docs/setup/openshift) |
|
||||
| Helm | [Link](https://docs.tooljet.ai/docs/setup/helm) |
|
||||
| AWS EKS (Kubernetes) | [Link](https://docs.tooljet.ai/docs/setup/kubernetes) |
|
||||
| GCP GKE (Kubernetes) | [Link](https://docs.tooljet.ai/docs/setup/kubernetes-gke) |
|
||||
| Azure AKS (Kubernetes) | [Link](https://docs.tooljet.ai/docs/setup/kubernetes-aks) |
|
||||
| Azure Container | [Link](https://docs.tooljet.ai/docs/setup/azure-container) |
|
||||
| Google Cloud Run | [Link](https://docs.tooljet.ai/docs/setup/google-cloud-run) |
|
||||
| Deploying ToolJet client | [Link](https://docs.tooljet.ai/docs/setup/client) |
|
||||
| Deploying ToolJet on a Subpath | [Link](https://docs.tooljet.ai/docs/setup/tooljet-subpath/) |
|
||||
|
||||
## Marketplace
|
||||
ToolJet can now be found on both AWS and Azure Marketplaces, making it simpler than ever to access and deploy our app-building platform.
|
||||
|
|
@ -108,9 +102,9 @@ ToolJet can now be found on both AWS and Azure Marketplaces, making it simpler t
|
|||
Find ToolJet on AWS Marketplace [here](https://aws.amazon.com/marketplace/pp/prodview-fxjto27jkpqfg?sr=0-1&ref_=beagle&applicationId=AWSMPContessa) and explore seamless integration on Azure Marketplace [here](https://azuremarketplace.microsoft.com/en-us/marketplace/apps/tooljetsolutioninc1679496832216.tooljet?tab=Overview).
|
||||
|
||||
## Community support
|
||||
For general help using ToolJet, please refer to the official [documentation](https://docs.tooljet.com/docs/). For additional help, you can use one of these channels to ask a question:
|
||||
For general help using ToolJet, please refer to the official [documentation](https://docs.tooljet.ai/docs/). For additional help, you can use one of these channels to ask a question:
|
||||
|
||||
- [Slack](https://tooljet.com/slack) - Discussions with the community and the team.
|
||||
- [Slack](https://tooljet.ai/slack) - Discussions with the community and the team.
|
||||
- [GitHub](https://github.com/ToolJet/ToolJet/issues) - For bug reports and feature requests.
|
||||
- [𝕏 (Twitter)](https://twitter.com/ToolJet) - Get the product updates quickly.
|
||||
|
||||
|
|
|
|||
|
|
@ -117,7 +117,7 @@ Cypress.Commands.add(
|
|||
|
||||
const splitIntoFlatArray = (value) => {
|
||||
const regex =
|
||||
/(\{|\}|\(|\)|\[|\]|,|:|;|=>|'[^']*'|"[^"]*"|[a-zA-Z0-9._-]+|\s+)/g;
|
||||
/(\{|\}|\(|\)|\[|\]|,|:|;|=>|'[^']*'|"[^"]*"|[a-zA-Z0-9._+\-*]+|\s+)/g;
|
||||
let prefix = "";
|
||||
|
||||
return (
|
||||
|
|
@ -136,8 +136,12 @@ Cypress.Commands.add(
|
|||
acc.push(prefix + ":");
|
||||
} else if (part === '"') {
|
||||
acc.push(prefix + '"');
|
||||
} else if (part.includes("-")) {
|
||||
acc.push(prefix + part); // Ensure hyphen is included
|
||||
} else if (
|
||||
part.includes("-") ||
|
||||
part.includes("+") ||
|
||||
part.includes("*")
|
||||
) {
|
||||
acc.push(prefix + part);
|
||||
} else {
|
||||
acc.push(prefix + part);
|
||||
prefix = "";
|
||||
|
|
@ -526,6 +530,82 @@ Cypress.Commands.overwrite(
|
|||
}
|
||||
);
|
||||
|
||||
Cypress.Commands.add("installMarketplacePlugin", (pluginName) => {
|
||||
const MARKETPLACE_URL = `${Cypress.config("baseUrl")}/integrations/marketplace`;
|
||||
|
||||
cy.visit(MARKETPLACE_URL);
|
||||
cy.wait(1000);
|
||||
|
||||
cy.get('[data-cy="-list-item"]').eq(0).click();
|
||||
cy.wait(1000);
|
||||
|
||||
cy.get("body").then(($body) => {
|
||||
if ($body.find(".plugins-card").length === 0) {
|
||||
cy.log("No plugins found, proceeding to install...");
|
||||
installPlugin(pluginName);
|
||||
} else {
|
||||
cy.get(".plugins-card").then(($cards) => {
|
||||
const isInstalled = $cards.toArray().some((card) => {
|
||||
return (
|
||||
Cypress.$(card)
|
||||
.find(".font-weight-medium.text-capitalize")
|
||||
.text()
|
||||
.trim() === pluginName
|
||||
);
|
||||
});
|
||||
|
||||
if (isInstalled) {
|
||||
cy.log(`${pluginName} is already installed. Skipping installation.`);
|
||||
cy.get(commonSelectors.globalDataSourceIcon).click();
|
||||
} else {
|
||||
installPlugin(pluginName);
|
||||
cy.get(commonSelectors.globalDataSourceIcon).click();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
function installPlugin(pluginName) {
|
||||
cy.get('[data-cy="-list-item"]').eq(1).click();
|
||||
cy.wait(1000);
|
||||
|
||||
cy.contains(".plugins-card", pluginName).within(() => {
|
||||
cy.get(".marketplace-install").click();
|
||||
cy.wait(1000);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
Cypress.Commands.add("uninstallMarketplacePlugin", (pluginName) => {
|
||||
const MARKETPLACE_URL = `${Cypress.config("baseUrl")}/integrations/marketplace`;
|
||||
|
||||
cy.visit(MARKETPLACE_URL);
|
||||
cy.wait(1000);
|
||||
|
||||
cy.get('[data-cy="-list-item"]').eq(0).click();
|
||||
cy.wait(1000);
|
||||
|
||||
cy.get(".plugins-card").each(($card) => {
|
||||
cy.wrap($card)
|
||||
.find(".font-weight-medium.text-capitalize")
|
||||
.invoke("text")
|
||||
.then((text) => {
|
||||
if (text.trim() === pluginName) {
|
||||
cy.wrap($card).find(".link-primary").contains("Remove").click();
|
||||
cy.wait(1000);
|
||||
|
||||
cy.get('[data-cy="delete-plugin-title"]').should("be.visible");
|
||||
cy.get('[data-cy="yes-button"]').click();
|
||||
cy.wait(2000);
|
||||
|
||||
cy.log(`${pluginName} has been successfully uninstalled.`);
|
||||
} else {
|
||||
cy.log(`${pluginName} is not installed. Skipping uninstallation.`);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Cypress.Commands.add("verifyElement", (selector, text, eqValue) => {
|
||||
const element =
|
||||
eqValue !== undefined ? cy.get(selector).eq(eqValue) : cy.get(selector);
|
||||
|
|
|
|||
|
|
@ -38,3 +38,25 @@ export const minioSelectors = {
|
|||
contentTypeInputField: '[data-cy="contenttype-input-field"]',
|
||||
dataInput: '[data-cy="data-input-field"]',
|
||||
};
|
||||
|
||||
export const harperDbSelectors = {
|
||||
recordsInputField: '[data-cy="records-input-field"]',
|
||||
hashValueInputField: '[data-cy="hash-values-input-field"]',
|
||||
attributesInputField: '[data-cy="attributes-input-field"]',
|
||||
searchValueInputField: '[data-cy="search-value-input-field"]',
|
||||
searchAttributeInputField: '[data-cy="search-attribute-input-field"]',
|
||||
conditionInputField: '[data-cy="conditions-input-field"]',
|
||||
sqlQueryInputField: '[data-cy="sql-query-input-field"]',
|
||||
schemaInputField: '[data-cy="schema-input-field"]',
|
||||
TableInputField: '[data-cy="table-input-field"]',
|
||||
};
|
||||
|
||||
export const awsTextractSelectors = {
|
||||
documentInputField: '[data-cy="document-input-field"]',
|
||||
bucketNameInputField: '[data-cy="bucket-input-field"]',
|
||||
keyNameInputField: '[data-cy="key-input-field"]',
|
||||
};
|
||||
|
||||
export const graphQLSelectors = {
|
||||
urlInputField: '[data-cy="url-text-field"]',
|
||||
};
|
||||
|
|
|
|||
44
cypress-tests/cypress/constants/selectors/restAPI.js
Normal file
44
cypress-tests/cypress/constants/selectors/restAPI.js
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
export const cyParamName = (paramName = "") => {
|
||||
return String(paramName)
|
||||
.toLowerCase()
|
||||
.replace(/\(s\)/g, "")
|
||||
.replace(/\s+/g, "-");
|
||||
};
|
||||
export const restAPISelector = {
|
||||
accordionHeader: (header) => {
|
||||
return `[data-cy="widget-accordion-${cyParamName(header)}"]`;
|
||||
},
|
||||
subHeaderLabel: (header) => {
|
||||
return `[data-cy="label-${cyParamName(header)}"]`;
|
||||
},
|
||||
subSection: (header) => {
|
||||
return `[data-cy="${cyParamName(header)}-section"]`;
|
||||
},
|
||||
keyInputField: (header, index) => {
|
||||
return `[data-cy="${cyParamName(header)}-key-input-field-${cyParamName(index)}"]`;
|
||||
},
|
||||
valueInputField: (header, index) => {
|
||||
return `[data-cy="${cyParamName(header)}-value-input-field-${cyParamName(index)}"]`;
|
||||
},
|
||||
deleteButton: (header, index) => {
|
||||
return `[data-cy="${cyParamName(header)}-delete-button-${cyParamName(index)}"]`;
|
||||
},
|
||||
addMoreButton: (header) => {
|
||||
return `[data-cy="${cyParamName(header)}-add-more-button"]`;
|
||||
},
|
||||
dropdownLabel: (label) => {
|
||||
return `[data-cy="${cyParamName(label)}-dropdown-label"]`;
|
||||
},
|
||||
inputField: (fieldName) => {
|
||||
return `[data-cy="${cyParamName(fieldName)}-input-field"]`;
|
||||
},
|
||||
button: (buttonName) => {
|
||||
return `[data-cy="button-${cyParamName(buttonName)}"]`;
|
||||
},
|
||||
authenticationAllUsersToggleSwitch:
|
||||
'[data-cy="authentication-required-for-all-users-toggle-switch"]',
|
||||
retryNetworkToggleSwitch: '[data-cy="retry-network-errors-toggle-input"]',
|
||||
retryNetworkToggleText: '[data-cy="retry-network-errors-toggle-text"]',
|
||||
retryNetworkToggleSubtext: '[data-cy="retry-network-errors-toggle-subtext"]',
|
||||
readDocumentationLinkText: '[data-cy="link-read-documentation"]',
|
||||
};
|
||||
8
cypress-tests/cypress/constants/texts/awsLambda.js
Normal file
8
cypress-tests/cypress/constants/texts/awsLambda.js
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
export const awsLambdaText = {
|
||||
awsLambda: "AWS Lambda",
|
||||
cypressawsLambda: "cypress-aws-lambda",
|
||||
labelAccesskey: "Access key",
|
||||
labelSecretKey: "Secret key",
|
||||
placeholderAccessKey: "Enter access key",
|
||||
placeholderSecretKey: "**************",
|
||||
};
|
||||
12
cypress-tests/cypress/constants/texts/awsTextract.js
Normal file
12
cypress-tests/cypress/constants/texts/awsTextract.js
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
export const awsTextractText = {
|
||||
awsTextract: "AWS Textract",
|
||||
cypressawsLambda: "cypress-aws-textract",
|
||||
labelAccesskey: "Access key",
|
||||
labelSecretKey: "Secret key",
|
||||
placeholderAccessKey: "Enter access key",
|
||||
placeholderSecretKey: "**************",
|
||||
documentName:
|
||||
"JVBERi0xLjQKJeLjz9MKMSAwIG9iago8PCAvVHlwZSAvQ2F0YWxvZyAvUGFnZXMgMiAwIFIgPj4KZW5kb2JqCjIgMCBvYmoKPDwgL1R5cGUgL1BhZ2VzIC9LaWRzIFszIDAgUl0gL0NvdW50IDEgPj4KZW5kb2JqCjMgMCBvYmoKPDwgL1R5cGUgL1BhZ2UgL1BhcmVudCAyIDAgUiAvUmVzb3VyY2VzIDw8IC9Gb250IDw8IC9GMSA0IDAgUiA+PiA+PiAvQ29udGVudHMgNSAwIFIgPj4KZW5kb2JqCjQgMCBvYmoKPDwgL1R5cGUgL0ZvbnQgL1N1YnR5cGUgL1R5cGUxIC9CYXNlRm9udCAvSGVsdmV0aWNhLUJvbGQgPj4KZW5kb2JqCjUgMCBvYmoKPDwgL0xlbmd0aCAxMjUgPj4Kc3RyZWFtCkJUIC9GMSAxMiBUZiAxMDAgNzAwIFRkICgoSGVsbG8sIEFtYXpvbiBUZXh0cmFjdCEpIFRqIEVUCmVuZHN0cmVhbQplbmRvYmoKeHJlZgowIDYKMDAwMDAwMDAwMCA2NTUzNSBmIAowMDAwMDAwMDExIDAwMDAwIG4gCjAwMDAwMDAwNTQgMDAwMDAgbgAKMDAwMDAwMDEwMyAwMDAwMCBuIAowMDAwMDAwMTcyIDAwMDAwIG4gCnRyYWlsZXIKPDwgL1NpemUgNiAvUm9vdCAxIDAgUiA+PgpzdGFydHhyZWYKMjIzCiUlRU9G",
|
||||
bucketName: "reimbursement-receipt-files",
|
||||
keyName: "reimbursement_receipt_1718364944018.png",
|
||||
};
|
||||
|
|
@ -80,4 +80,11 @@ export const dataSourceText = {
|
|||
labelNoEventhandler: "No event handlers",
|
||||
toastDSSaved: "Data Source Saved",
|
||||
unSavedModalTitle: "Unsaved Changes",
|
||||
|
||||
sslCertificateLabel: "SSL Certificate",
|
||||
caCertificateOption: "CA certificate",
|
||||
clientCertificateOption: "Client certificate",
|
||||
clientKeyLabel: "Client Key",
|
||||
clientCertLabel: "Client Cert",
|
||||
caCertLabel: "CA Cert",
|
||||
};
|
||||
|
|
|
|||
6
cypress-tests/cypress/constants/texts/graphQL.js
Normal file
6
cypress-tests/cypress/constants/texts/graphQL.js
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
export const GraphQLText = {
|
||||
GraphQL: "GraphQL",
|
||||
cypressGraphQL: "cypress-GraphQL",
|
||||
urlInputLabel: "URL",
|
||||
urlInputPlaceholder: "https://api.example.com/v1/graphql",
|
||||
};
|
||||
21
cypress-tests/cypress/constants/texts/harperDb.js
Normal file
21
cypress-tests/cypress/constants/texts/harperDb.js
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
export const harperDbText = {
|
||||
harperDb: "HarperDB",
|
||||
cypressHarperDB: "cypressHarperDB",
|
||||
hostLabel: "Host",
|
||||
hostInputPlaceholder: "Enter host",
|
||||
portLabel: "Port",
|
||||
portPlaceholder: "Enter port",
|
||||
userNameLabel: "Username",
|
||||
passwordlabel: "Password",
|
||||
userNamePlaceholder: "Enter username",
|
||||
passwordPlaceholder: "**************",
|
||||
recordsValue: `[{id: 10, name: 'QA', age: 24}]`,
|
||||
hashValue: "[10]",
|
||||
attributesValue: "['name']",
|
||||
searchAttributeValue: "name",
|
||||
searchValue: "QA",
|
||||
condtionValue: `[{'search_attribute': 'name', 'search_type': 'between', 'search_value': [1, 5]}, {'search_attribute': 'name', 'search_type': 'equals', 'search_value': 'QA'}]`,
|
||||
sqlValue: "SELECT * FROM test_schema.test_table",
|
||||
schemaValue: "test_schema",
|
||||
tableValue: "test_table",
|
||||
};
|
||||
|
|
@ -2,8 +2,7 @@ export const redisText = {
|
|||
redis: "Redis",
|
||||
cypressRedis: "cypress-redis",
|
||||
|
||||
errorMaxRetries:
|
||||
'Reached the max retries per request limit (which is 1). Refer to "maxRetriesPerRequest" option for details.',
|
||||
errorPort: "Port should be >= 0 and < 65536. Received type number (108299).",
|
||||
errorInvalidUserOrPassword: "WRONGPASS invalid username-password pair",
|
||||
errorMaxRetries: "Connection could not be established",
|
||||
errorPort: "Connection could not be established",
|
||||
errorInvalidUserOrPassword: "Connection could not be established",
|
||||
};
|
||||
|
|
|
|||
58
cypress-tests/cypress/constants/texts/restAPI.js
Normal file
58
cypress-tests/cypress/constants/texts/restAPI.js
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
export const restAPIText = {
|
||||
restAPI: "REST API",
|
||||
credentialsText: "CREDENTIALS",
|
||||
baseUrlLabel: "Base URL",
|
||||
headersLabel: "Headers",
|
||||
urlParametesLabel: "URL parameters",
|
||||
bodyLabel: "Body",
|
||||
cookiesLabel: "Cookies",
|
||||
authenticationText: "AUTHENTICATION",
|
||||
authenticationTypeLabel: "Authentication type",
|
||||
noneText: "None",
|
||||
editButtonText: "Edit",
|
||||
basicAuth: {
|
||||
basicText: "Basic",
|
||||
usernameLabel: "Username",
|
||||
passwordLabel: "Password",
|
||||
},
|
||||
bearerAuth: {
|
||||
bearerText: "Bearer",
|
||||
tokenLabel: "Token",
|
||||
},
|
||||
oAuthText: "OAuth 2.0",
|
||||
grantTypeLabel: "Grant type",
|
||||
authorizationCode: {
|
||||
authorizationCodeLabel: "Authorization code",
|
||||
addAccessTokenLabel: "Add access token to",
|
||||
headerPrefixLabel: "Header prefix",
|
||||
requestHeader: "Request header",
|
||||
accessTokenURLLabel: "Access token URL",
|
||||
accessTokenURLCustomHeadersLabel: "Access token URL custom headers",
|
||||
clientIDLabel: "Client ID",
|
||||
clientSecretLabel: "Client secret",
|
||||
scopeLabel: "Scope(s)",
|
||||
customQueryParametersLabel: "Custom query parameters",
|
||||
authorizationURLLabel: "Authorization URL",
|
||||
customAuthenticationParametersLabel: "Custom authentication parameters",
|
||||
clientAuthentication: "Client authentication",
|
||||
sendBasicAuthheaderOption: "Send as basic auth header",
|
||||
sendClientCredentialsBodyOption: "Send client credentials in body",
|
||||
authenticationRequiredUsersToggle: "Authentication required for all users",
|
||||
},
|
||||
|
||||
clientCredentials: {
|
||||
clientCredentialsLabel: "Client credentials",
|
||||
accessTokenURLLabel: "Access token URL",
|
||||
accessTokenURLCustomHeadersLabel: "Access token URL custom headers",
|
||||
clientIDLabel: "Client ID",
|
||||
clientSecretLabel: "Client secret",
|
||||
scopeLabel: "Scope(s)",
|
||||
audiencelabel: "Audience",
|
||||
},
|
||||
authenticationHeader: "Authentication",
|
||||
secureSocketsLayerText: "SECURE SOCKETS LAYER",
|
||||
generalSettingsText: "GENERAL SETTINGS",
|
||||
retryNetworkErrorsToggleLabel: "Retry on network errors",
|
||||
retryToggleHelperText:
|
||||
"By default, ToolJet tries to hit API endpoint 3 times before declaring query failed as server did not respond",
|
||||
};
|
||||
|
|
@ -11,6 +11,8 @@ const data = {};
|
|||
data.dsNamefake = fake.lastName.toLowerCase().replaceAll("[^A-Za-z]", "");
|
||||
data.dsNamefake1 = fake.lastName.toLowerCase().replaceAll("[^A-Za-z]", "");
|
||||
const cyParamName = (name) => name.toLowerCase().replace(/[^a-z0-9]/g, "-");
|
||||
data.workspaceName = fake.lastName.toLowerCase().replaceAll("[^A-Za-z]", "");
|
||||
data.workspaceSlug = fake.lastName.toLowerCase().replace(/\s+/g, "-");
|
||||
|
||||
const dataSources = [
|
||||
"BigQuery",
|
||||
|
|
@ -62,10 +64,12 @@ const dataSources = [
|
|||
describe("Add all Data sources to app", () => {
|
||||
beforeEach(() => {
|
||||
cy.apiLogin();
|
||||
cy.defaultWorkspaceLogin();
|
||||
});
|
||||
|
||||
it("Should verify global data source page", () => {
|
||||
cy.apiCreateWorkspace(data.workspaceName, data.workspaceSlug);
|
||||
cy.visit(`${data.workspaceSlug}`);
|
||||
|
||||
cy.get(commonSelectors.globalDataSourceIcon).click();
|
||||
closeDSModal();
|
||||
|
||||
|
|
@ -84,6 +88,8 @@ describe("Add all Data sources to app", () => {
|
|||
});
|
||||
|
||||
it("Should add all data sources in data source page", () => {
|
||||
cy.visit(`${data.workspaceSlug}`);
|
||||
|
||||
dataSources.forEach((dsName) => {
|
||||
cy.get(commonSelectors.globalDataSourceIcon).click();
|
||||
selectAndAddDataSource("databases", dsName, dsName); // Using the correct fake name
|
||||
|
|
@ -104,6 +110,7 @@ describe("Add all Data sources to app", () => {
|
|||
});
|
||||
|
||||
it("Should add all data sources in the app", () => {
|
||||
cy.visit(`${data.workspaceSlug}`);
|
||||
cy.get(commonSelectors.dashboardIcon).click();
|
||||
cy.get(commonSelectors.appCreateButton).click();
|
||||
cy.get(commonSelectors.appNameInput).click().type(data.dsNamefake);
|
||||
|
|
@ -129,6 +136,7 @@ describe("Add all Data sources to app", () => {
|
|||
});
|
||||
|
||||
it("Should install all makretplace plugins and add them into the app", () => {
|
||||
cy.visit(`${data.workspaceSlug}`);
|
||||
const dataSourcesMarketplace = [
|
||||
"Plivo",
|
||||
"GitHub",
|
||||
|
|
|
|||
|
|
@ -9,18 +9,13 @@ import {
|
|||
fillDataSourceTextField,
|
||||
selectAndAddDataSource,
|
||||
} from "Support/utils/postgreSql";
|
||||
import { redisText } from "Texts/redis";
|
||||
|
||||
import {
|
||||
verifyCouldnotConnectWithAlert,
|
||||
deleteDatasource,
|
||||
closeDSModal,
|
||||
addQuery,
|
||||
addDsAndAddQuery,
|
||||
selectDatasource,
|
||||
deleteAppandDatasourceAfterExecution,
|
||||
} from "Support/utils/dataSource";
|
||||
|
||||
import { openQueryEditor } from "Support/utils/dataSource";
|
||||
import { dataSourceSelector } from "../../../../../constants/selectors/dataSource";
|
||||
|
||||
const data = {};
|
||||
|
|
@ -284,6 +279,10 @@ describe("Data source Airtable", () => {
|
|||
commonSelectors.toastMessage,
|
||||
`Query (${data.dsName1}) completed.`
|
||||
);
|
||||
deleteAppandDatasourceAfterExecution(
|
||||
data.dsName,
|
||||
`cypress-${data.dsName}-airtable`
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -13,14 +13,10 @@ import {
|
|||
} from "Support/utils/postgreSql";
|
||||
|
||||
import {
|
||||
verifyCouldnotConnectWithAlert,
|
||||
deleteDatasource,
|
||||
closeDSModal,
|
||||
addQuery,
|
||||
addDsAndAddQuery,
|
||||
deleteAppandDatasourceAfterExecution,
|
||||
} from "Support/utils/dataSource";
|
||||
|
||||
import { openQueryEditor } from "Support/utils/dataSource";
|
||||
import { dataSourceSelector } from "../../../../../constants/selectors/dataSource";
|
||||
|
||||
const data = {};
|
||||
|
|
@ -203,5 +199,9 @@ describe("Data source amazon athena", () => {
|
|||
commonSelectors.toastMessage,
|
||||
`Query (${data.dsName}) completed.`
|
||||
);
|
||||
deleteAppandDatasourceAfterExecution(
|
||||
data.dsName,
|
||||
`cypress-${data.dsName}-amazon-Athena`
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -12,14 +12,11 @@ import {
|
|||
} from "Support/utils/postgreSql";
|
||||
|
||||
import {
|
||||
verifyCouldnotConnectWithAlert,
|
||||
deleteDatasource,
|
||||
closeDSModal,
|
||||
addQuery,
|
||||
addDsAndAddQuery,
|
||||
deleteAppandDatasourceAfterExecution,
|
||||
} from "Support/utils/dataSource";
|
||||
|
||||
import { openQueryEditor } from "Support/utils/dataSource";
|
||||
import { dataSourceSelector } from "../../../../../constants/selectors/dataSource";
|
||||
|
||||
const data = {};
|
||||
|
|
@ -200,5 +197,9 @@ describe("Data source amazon ses", () => {
|
|||
commonSelectors.toastMessage,
|
||||
`Query (${data.dsName}) completed.`
|
||||
);
|
||||
deleteAppandDatasourceAfterExecution(
|
||||
data.dsName,
|
||||
`cypress-${data.dsName}-amazon-ses`
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -12,14 +12,11 @@ import {
|
|||
} from "Support/utils/postgreSql";
|
||||
|
||||
import {
|
||||
verifyCouldnotConnectWithAlert,
|
||||
deleteDatasource,
|
||||
closeDSModal,
|
||||
addQuery,
|
||||
addDsAndAddQuery,
|
||||
deleteAppandDatasourceAfterExecution,
|
||||
} from "Support/utils/dataSource";
|
||||
|
||||
import { openQueryEditor } from "Support/utils/dataSource";
|
||||
import { dataSourceSelector } from "../../../../../constants/selectors/dataSource";
|
||||
|
||||
const data = {};
|
||||
|
|
@ -41,11 +38,18 @@ describe("Data source AppWrite", () => {
|
|||
cy.get(commonSelectors.globalDataSourceIcon).click();
|
||||
closeDSModal();
|
||||
|
||||
cy.get(postgreSqlSelector.allDatasourceLabelAndCount).should(
|
||||
"have.text",
|
||||
postgreSqlText.allDataSources()
|
||||
);
|
||||
cy.get(postgreSqlSelector.commonlyUsedLabelAndCount).should(
|
||||
"have.text",
|
||||
postgreSqlText.commonlyUsed
|
||||
);
|
||||
|
||||
cy.get(postgreSqlSelector.databaseLabelAndCount).should(
|
||||
"have.text",
|
||||
postgreSqlText.allDatabase()
|
||||
);
|
||||
cy.get(postgreSqlSelector.apiLabelAndCount).should(
|
||||
"have.text",
|
||||
postgreSqlText.allApis
|
||||
|
|
@ -297,12 +301,15 @@ describe("Data source AppWrite", () => {
|
|||
}
|
||||
cy.get(dataSourceSelector.queryPreviewButton).click();
|
||||
|
||||
// Verify toast message
|
||||
cy.verifyToastMessage(
|
||||
commonSelectors.toastMessage,
|
||||
`Query (${data.dsName}) completed.`
|
||||
);
|
||||
});
|
||||
deleteAppandDatasourceAfterExecution(
|
||||
data.dsName,
|
||||
`cypress-${data.dsName}-Appwrite`
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -0,0 +1,187 @@
|
|||
import { fake } from "Fixtures/fake";
|
||||
import { postgreSqlSelector } from "Selectors/postgreSql";
|
||||
import { pluginSelectors } from "Selectors/plugins";
|
||||
import { postgreSqlText } from "Texts/postgreSql";
|
||||
import { awsLambdaText } from "Texts/awsLambda";
|
||||
import { commonSelectors } from "Selectors/common";
|
||||
import { commonText } from "Texts/common";
|
||||
|
||||
import {
|
||||
fillDataSourceTextField,
|
||||
selectAndAddDataSource,
|
||||
} from "Support/utils/postgreSql";
|
||||
|
||||
import {
|
||||
deleteDatasource,
|
||||
closeDSModal,
|
||||
deleteAppandDatasourceAfterExecution,
|
||||
} from "Support/utils/dataSource";
|
||||
|
||||
import { dataSourceSelector } from "../../../../../constants/selectors/dataSource";
|
||||
|
||||
const data = {};
|
||||
data.dsName = fake.lastName.toLowerCase().replaceAll("[^A-Za-z]", "");
|
||||
|
||||
describe("Data source AWS Lambda", () => {
|
||||
beforeEach(() => {
|
||||
cy.apiLogin();
|
||||
cy.defaultWorkspaceLogin();
|
||||
cy.intercept("POST", "/api/data_queries").as("createQuery");
|
||||
});
|
||||
|
||||
it("Should verify elements on AWS Lambda connection form", () => {
|
||||
const Accesskey = Cypress.env("awslamda_access");
|
||||
const Secretkey = Cypress.env("awslamda_secret");
|
||||
|
||||
cy.get(commonSelectors.globalDataSourceIcon).click();
|
||||
closeDSModal();
|
||||
|
||||
cy.get(postgreSqlSelector.allDatasourceLabelAndCount).should(
|
||||
"have.text",
|
||||
postgreSqlText.allDataSources()
|
||||
);
|
||||
cy.get(postgreSqlSelector.commonlyUsedLabelAndCount).should(
|
||||
"have.text",
|
||||
postgreSqlText.commonlyUsed
|
||||
);
|
||||
cy.get(postgreSqlSelector.databaseLabelAndCount).should(
|
||||
"have.text",
|
||||
postgreSqlText.allDatabase()
|
||||
);
|
||||
cy.get(postgreSqlSelector.apiLabelAndCount).should(
|
||||
"have.text",
|
||||
postgreSqlText.allApis
|
||||
);
|
||||
cy.get(postgreSqlSelector.cloudStorageLabelAndCount).should(
|
||||
"have.text",
|
||||
postgreSqlText.allCloudStorage
|
||||
);
|
||||
|
||||
cy.installMarketplacePlugin("AWS Lambda");
|
||||
|
||||
selectAndAddDataSource("databases", awsLambdaText.awsLambda, data.dsName);
|
||||
|
||||
cy.get(".react-select__dropdown-indicator").eq(1).click();
|
||||
cy.get(".react-select__option").contains("US West (N. California)").click();
|
||||
|
||||
cy.get(pluginSelectors.amazonsesAccesKey).click().type(Accesskey);
|
||||
|
||||
fillDataSourceTextField(
|
||||
awsLambdaText.labelSecretKey,
|
||||
"**************",
|
||||
Secretkey
|
||||
);
|
||||
|
||||
cy.get(postgreSqlSelector.buttonSave)
|
||||
.verifyVisibleElement("have.text", postgreSqlText.buttonTextSave)
|
||||
.click();
|
||||
cy.verifyToastMessage(
|
||||
commonSelectors.toastMessage,
|
||||
postgreSqlText.toastDSSaved
|
||||
);
|
||||
|
||||
deleteDatasource(`cypress-${data.dsName}-aws-lambda`);
|
||||
});
|
||||
|
||||
it("Should verify the functionality of AWS Lambda connection form", () => {
|
||||
const Accesskey = Cypress.env("awslamda_access");
|
||||
const Secretkey = Cypress.env("awslamda_secret");
|
||||
|
||||
cy.get(commonSelectors.globalDataSourceIcon).click();
|
||||
closeDSModal();
|
||||
|
||||
cy.installMarketplacePlugin("AWS Lambda");
|
||||
|
||||
selectAndAddDataSource("databases", awsLambdaText.awsLambda, data.dsName);
|
||||
|
||||
cy.get(".react-select__dropdown-indicator").eq(1).click();
|
||||
cy.get(".react-select__option").contains("US West (N. California)").click();
|
||||
|
||||
cy.get(pluginSelectors.amazonsesAccesKey).click().type(Accesskey);
|
||||
|
||||
fillDataSourceTextField(
|
||||
awsLambdaText.labelSecretKey,
|
||||
"**************",
|
||||
Secretkey
|
||||
);
|
||||
|
||||
cy.get(postgreSqlSelector.buttonSave)
|
||||
.verifyVisibleElement("have.text", postgreSqlText.buttonTextSave)
|
||||
.click();
|
||||
cy.verifyToastMessage(
|
||||
commonSelectors.toastMessage,
|
||||
postgreSqlText.toastDSSaved
|
||||
);
|
||||
|
||||
deleteDatasource(`cypress-${data.dsName}-aws-lambda`);
|
||||
});
|
||||
|
||||
it("Should able to run the query with valid conection", () => {
|
||||
const Accesskey = Cypress.env("awslamda_access");
|
||||
const Secretkey = Cypress.env("awslamda_secret");
|
||||
|
||||
cy.get(commonSelectors.globalDataSourceIcon).click();
|
||||
closeDSModal();
|
||||
|
||||
cy.installMarketplacePlugin("AWS Lambda");
|
||||
|
||||
selectAndAddDataSource("databases", awsLambdaText.awsLambda, data.dsName);
|
||||
|
||||
cy.get(".react-select__dropdown-indicator").eq(1).click();
|
||||
cy.get(".react-select__option")
|
||||
.contains("US West (N. California)")
|
||||
.wait(500)
|
||||
.click();
|
||||
|
||||
cy.get(pluginSelectors.amazonsesAccesKey).click().type(Accesskey);
|
||||
|
||||
fillDataSourceTextField(
|
||||
awsLambdaText.labelSecretKey,
|
||||
"**************",
|
||||
Secretkey
|
||||
);
|
||||
|
||||
cy.get(postgreSqlSelector.buttonSave)
|
||||
.verifyVisibleElement("have.text", postgreSqlText.buttonTextSave)
|
||||
.click();
|
||||
|
||||
cy.verifyToastMessage(
|
||||
commonSelectors.toastMessage,
|
||||
postgreSqlText.toastDSSaved
|
||||
);
|
||||
|
||||
cy.get(commonSelectors.dashboardIcon).click();
|
||||
cy.get(commonSelectors.appCreateButton).click();
|
||||
cy.get(commonSelectors.appNameInput).click().type(data.dsName);
|
||||
cy.get(commonSelectors.createAppButton).click();
|
||||
cy.skipWalkthrough();
|
||||
|
||||
cy.get('[data-cy="show-ds-popover-button"]').click();
|
||||
cy.get(".css-4e90k9").type(`${data.dsName}`);
|
||||
cy.contains(`[id*="react-select-"]`, data.dsName).click();
|
||||
cy.get('[data-cy="query-rename-input"]').clear().type(data.dsName);
|
||||
|
||||
cy.get(pluginSelectors.operationDropdown)
|
||||
.click()
|
||||
.type("Invoke Lambda Function{enter}");
|
||||
|
||||
cy.wait(500);
|
||||
|
||||
cy.get(
|
||||
'[data-cy="function-name-section"] .cm-content'
|
||||
).clearAndTypeOnCodeMirror("testAwslambdaPlugin");
|
||||
|
||||
cy.wait(500);
|
||||
|
||||
cy.get(dataSourceSelector.queryPreviewButton).click();
|
||||
cy.verifyToastMessage(
|
||||
commonSelectors.toastMessage,
|
||||
`Query (${data.dsName}) completed.`
|
||||
);
|
||||
deleteAppandDatasourceAfterExecution(
|
||||
data.dsName,
|
||||
`cypress-${data.dsName}-aws-lambda`
|
||||
);
|
||||
cy.uninstallMarketplacePlugin("AWS Lambda");
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,225 @@
|
|||
import { fake } from "Fixtures/fake";
|
||||
import { postgreSqlSelector } from "Selectors/postgreSql";
|
||||
import { pluginSelectors } from "Selectors/plugins";
|
||||
import { awsTextractSelectors } from "Selectors/Plugins";
|
||||
import { postgreSqlText } from "Texts/postgreSql";
|
||||
import { awsTextractText } from "Texts/awsTextract";
|
||||
import { commonSelectors } from "Selectors/common";
|
||||
import { commonText } from "Texts/common";
|
||||
|
||||
import {
|
||||
fillDataSourceTextField,
|
||||
selectAndAddDataSource,
|
||||
} from "Support/utils/postgreSql";
|
||||
|
||||
import {
|
||||
deleteDatasource,
|
||||
closeDSModal,
|
||||
deleteAppandDatasourceAfterExecution,
|
||||
} from "Support/utils/dataSource";
|
||||
|
||||
import { dataSourceSelector } from "../../../../../constants/selectors/dataSource";
|
||||
|
||||
const data = {};
|
||||
data.dsName = fake.lastName.toLowerCase().replaceAll("[^A-Za-z]", "");
|
||||
|
||||
describe("Data source AWS Textract", () => {
|
||||
beforeEach(() => {
|
||||
cy.apiLogin();
|
||||
cy.defaultWorkspaceLogin();
|
||||
cy.intercept("POST", "/api/data_queries").as("createQuery");
|
||||
});
|
||||
|
||||
it("Should verify elements on AWS Textract connection form", () => {
|
||||
const Accesskey = Cypress.env("awstextract_access");
|
||||
const Secretkey = Cypress.env("awstextract_secret");
|
||||
|
||||
cy.get(commonSelectors.globalDataSourceIcon).click();
|
||||
closeDSModal();
|
||||
|
||||
cy.get(postgreSqlSelector.allDatasourceLabelAndCount).should(
|
||||
"have.text",
|
||||
postgreSqlText.allDataSources()
|
||||
);
|
||||
cy.get(postgreSqlSelector.commonlyUsedLabelAndCount).should(
|
||||
"have.text",
|
||||
postgreSqlText.commonlyUsed
|
||||
);
|
||||
cy.get(postgreSqlSelector.databaseLabelAndCount).should(
|
||||
"have.text",
|
||||
postgreSqlText.allDatabase()
|
||||
);
|
||||
cy.get(postgreSqlSelector.apiLabelAndCount).should(
|
||||
"have.text",
|
||||
postgreSqlText.allApis
|
||||
);
|
||||
cy.get(postgreSqlSelector.cloudStorageLabelAndCount).should(
|
||||
"have.text",
|
||||
postgreSqlText.allCloudStorage
|
||||
);
|
||||
|
||||
cy.installMarketplacePlugin("AWS Textract");
|
||||
|
||||
selectAndAddDataSource(
|
||||
"databases",
|
||||
awsTextractText.awsTextract,
|
||||
data.dsName
|
||||
);
|
||||
|
||||
cy.get(".react-select__dropdown-indicator").eq(1).click();
|
||||
cy.get(".react-select__option").contains("US West (N. California)").click();
|
||||
|
||||
cy.get(pluginSelectors.amazonsesAccesKey).click().type(Accesskey);
|
||||
|
||||
fillDataSourceTextField(
|
||||
awsTextractText.labelSecretKey,
|
||||
"**************",
|
||||
Secretkey
|
||||
);
|
||||
|
||||
cy.get(postgreSqlSelector.buttonSave)
|
||||
.verifyVisibleElement("have.text", postgreSqlText.buttonTextSave)
|
||||
.click();
|
||||
cy.verifyToastMessage(
|
||||
commonSelectors.toastMessage,
|
||||
postgreSqlText.toastDSSaved
|
||||
);
|
||||
|
||||
deleteDatasource(`cypress-${data.dsName}-aws-textract`);
|
||||
});
|
||||
|
||||
it("Should verify functionality of AWS Textract connection form", () => {
|
||||
const Accesskey = Cypress.env("awstextract_access");
|
||||
const Secretkey = Cypress.env("awstextract_secret");
|
||||
|
||||
cy.get(commonSelectors.globalDataSourceIcon).click();
|
||||
closeDSModal();
|
||||
|
||||
cy.installMarketplacePlugin("AWS Textract");
|
||||
|
||||
selectAndAddDataSource(
|
||||
"databases",
|
||||
awsTextractText.awsTextract,
|
||||
data.dsName
|
||||
);
|
||||
|
||||
cy.get(".react-select__dropdown-indicator").eq(1).click();
|
||||
cy.get(".react-select__option").contains("US West (N. California)").click();
|
||||
|
||||
cy.get(pluginSelectors.amazonsesAccesKey).click().type(Accesskey);
|
||||
|
||||
fillDataSourceTextField(
|
||||
awsTextractText.labelSecretKey,
|
||||
"**************",
|
||||
Secretkey
|
||||
);
|
||||
|
||||
cy.get(postgreSqlSelector.buttonSave)
|
||||
.verifyVisibleElement("have.text", postgreSqlText.buttonTextSave)
|
||||
.click();
|
||||
cy.verifyToastMessage(
|
||||
commonSelectors.toastMessage,
|
||||
postgreSqlText.toastDSSaved
|
||||
);
|
||||
|
||||
deleteDatasource(`cypress-${data.dsName}-aws-textract`);
|
||||
});
|
||||
|
||||
it("Should able to run the query with valid conection", () => {
|
||||
const Accesskey = Cypress.env("awstextract_access");
|
||||
const Secretkey = Cypress.env("awstextract_secret");
|
||||
|
||||
cy.get(commonSelectors.globalDataSourceIcon).click();
|
||||
closeDSModal();
|
||||
|
||||
cy.installMarketplacePlugin("AWS Textract");
|
||||
|
||||
selectAndAddDataSource(
|
||||
"databases",
|
||||
awsTextractText.awsTextract,
|
||||
data.dsName
|
||||
);
|
||||
|
||||
cy.get(".react-select__dropdown-indicator").eq(1).click();
|
||||
cy.get(".react-select__option")
|
||||
.contains("US West (N. California)")
|
||||
.wait(500)
|
||||
.click();
|
||||
|
||||
cy.get(pluginSelectors.amazonsesAccesKey).click().type(Accesskey);
|
||||
|
||||
fillDataSourceTextField(
|
||||
awsTextractText.labelSecretKey,
|
||||
"**************",
|
||||
Secretkey
|
||||
);
|
||||
|
||||
cy.get(postgreSqlSelector.buttonSave)
|
||||
.verifyVisibleElement("have.text", postgreSqlText.buttonTextSave)
|
||||
.click();
|
||||
cy.verifyToastMessage(
|
||||
commonSelectors.toastMessage,
|
||||
postgreSqlText.toastDSSaved
|
||||
);
|
||||
|
||||
cy.get(commonSelectors.dashboardIcon).click();
|
||||
cy.get(commonSelectors.appCreateButton).click();
|
||||
cy.get(commonSelectors.appNameInput).click().type(data.dsName);
|
||||
cy.get(commonSelectors.createAppButton).click();
|
||||
cy.skipWalkthrough();
|
||||
|
||||
cy.get('[data-cy="show-ds-popover-button"]').click();
|
||||
cy.get(".css-4e90k9").type(`${data.dsName}`);
|
||||
cy.contains(`[id*="react-select-"]`, data.dsName).click();
|
||||
cy.get('[data-cy="query-rename-input"]').clear().type(data.dsName);
|
||||
|
||||
// Verifying analyze document operation
|
||||
cy.get(pluginSelectors.operationDropdown)
|
||||
.click()
|
||||
.wait(500)
|
||||
.type("Analyze Document{enter}");
|
||||
|
||||
cy.wait(500);
|
||||
|
||||
cy.get(awsTextractSelectors.documentInputField).clearAndTypeOnCodeMirror(
|
||||
awsTextractText.documentName
|
||||
);
|
||||
|
||||
cy.wait(500);
|
||||
|
||||
cy.get(dataSourceSelector.queryPreviewButton).click();
|
||||
cy.verifyToastMessage(
|
||||
commonSelectors.toastMessage,
|
||||
`Query (${data.dsName}) completed.`
|
||||
);
|
||||
// Verifying Analyze document stored in AWS S3 operation
|
||||
|
||||
cy.get(pluginSelectors.operationDropdown)
|
||||
.click()
|
||||
.wait(500)
|
||||
.type("Analyze document stored in AWS S3{enter}");
|
||||
|
||||
cy.wait(500);
|
||||
|
||||
cy.get(awsTextractSelectors.bucketNameInputField).clearAndTypeOnCodeMirror(
|
||||
awsTextractText.bucketName
|
||||
);
|
||||
|
||||
cy.get(awsTextractSelectors.keyNameInputField).clearAndTypeOnCodeMirror(
|
||||
awsTextractText.keyName
|
||||
);
|
||||
|
||||
cy.wait(500);
|
||||
|
||||
cy.get(dataSourceSelector.queryPreviewButton).click();
|
||||
cy.verifyToastMessage(
|
||||
commonSelectors.toastMessage,
|
||||
`Query (${data.dsName}) completed.`
|
||||
);
|
||||
deleteAppandDatasourceAfterExecution(
|
||||
data.dsName,
|
||||
`cypress-${data.dsName}-aws-textract`
|
||||
);
|
||||
cy.uninstallMarketplacePlugin("AWS Textract");
|
||||
});
|
||||
});
|
||||
|
|
@ -2,9 +2,7 @@ import { fake } from "Fixtures/fake";
|
|||
import { postgreSqlSelector } from "Selectors/postgreSql";
|
||||
import { pluginSelectors, baserowSelectors } from "Selectors/plugins";
|
||||
import { postgreSqlText } from "Texts/postgreSql";
|
||||
import { amazonSesText } from "Texts/amazonSes";
|
||||
import { baseRowText } from "Texts/baseRow";
|
||||
import { amazonAthenaText } from "Texts/amazonAthena";
|
||||
import { commonSelectors } from "Selectors/common";
|
||||
import { commonText } from "Texts/common";
|
||||
|
||||
|
|
@ -14,14 +12,11 @@ import {
|
|||
} from "Support/utils/postgreSql";
|
||||
|
||||
import {
|
||||
verifyCouldnotConnectWithAlert,
|
||||
deleteDatasource,
|
||||
closeDSModal,
|
||||
addQuery,
|
||||
addDsAndAddQuery,
|
||||
deleteAppandDatasourceAfterExecution,
|
||||
} from "Support/utils/dataSource";
|
||||
|
||||
import { openQueryEditor } from "Support/utils/dataSource";
|
||||
import { dataSourceSelector } from "../../../../../constants/selectors/dataSource";
|
||||
|
||||
const data = {};
|
||||
|
|
@ -215,5 +210,9 @@ describe("Data source baserow", () => {
|
|||
`Query (${data.dsName}) completed.`
|
||||
);
|
||||
});
|
||||
deleteAppandDatasourceAfterExecution(
|
||||
data.dsName,
|
||||
`cypress-${data.dsName}-baserow`
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -0,0 +1,153 @@
|
|||
import { fake } from "Fixtures/fake";
|
||||
import { postgreSqlSelector } from "Selectors/postgreSql";
|
||||
import { postgreSqlText } from "Texts/postgreSql";
|
||||
import { GraphQLText } from "Texts/graphQL";
|
||||
import { commonSelectors } from "Selectors/common";
|
||||
import { commonText } from "Texts/common";
|
||||
|
||||
import {
|
||||
fillDataSourceTextField,
|
||||
selectAndAddDataSource,
|
||||
} from "Support/utils/postgreSql";
|
||||
|
||||
import {
|
||||
deleteDatasource,
|
||||
closeDSModal,
|
||||
deleteAppandDatasourceAfterExecution,
|
||||
} from "Support/utils/dataSource";
|
||||
|
||||
import { dataSourceSelector } from "../../../../../constants/selectors/dataSource";
|
||||
|
||||
const data = {};
|
||||
data.dsName = fake.lastName.toLowerCase().replaceAll("[^A-Za-z]", "");
|
||||
|
||||
describe("Data source GraphQL", () => {
|
||||
beforeEach(() => {
|
||||
cy.apiLogin();
|
||||
cy.defaultWorkspaceLogin();
|
||||
});
|
||||
|
||||
it("Should verify elements on GraphQL connection form", () => {
|
||||
const Url = Cypress.env("GraphQl_Url");
|
||||
|
||||
cy.get(commonSelectors.globalDataSourceIcon).click();
|
||||
closeDSModal();
|
||||
|
||||
cy.get(postgreSqlSelector.allDatasourceLabelAndCount).should(
|
||||
"have.text",
|
||||
postgreSqlText.allDataSources()
|
||||
);
|
||||
cy.get(postgreSqlSelector.commonlyUsedLabelAndCount).should(
|
||||
"have.text",
|
||||
postgreSqlText.commonlyUsed
|
||||
);
|
||||
cy.get(postgreSqlSelector.databaseLabelAndCount).should(
|
||||
"have.text",
|
||||
postgreSqlText.allDatabase()
|
||||
);
|
||||
cy.get(postgreSqlSelector.apiLabelAndCount).should(
|
||||
"have.text",
|
||||
postgreSqlText.allApis
|
||||
);
|
||||
cy.get(postgreSqlSelector.cloudStorageLabelAndCount).should(
|
||||
"have.text",
|
||||
postgreSqlText.allCloudStorage
|
||||
);
|
||||
|
||||
selectAndAddDataSource("databases", GraphQLText.GraphQL, data.dsName);
|
||||
|
||||
fillDataSourceTextField(
|
||||
GraphQLText.urlInputLabel,
|
||||
GraphQLText.urlInputPlaceholder,
|
||||
Url
|
||||
);
|
||||
|
||||
cy.get(postgreSqlSelector.buttonSave)
|
||||
.verifyVisibleElement("have.text", postgreSqlText.buttonTextSave)
|
||||
.click();
|
||||
cy.verifyToastMessage(
|
||||
commonSelectors.toastMessage,
|
||||
postgreSqlText.toastDSSaved
|
||||
);
|
||||
|
||||
deleteDatasource(`cypress-${data.dsName}-GraphQL`);
|
||||
});
|
||||
|
||||
it("Should verify the functionality of GraphQL connection form", () => {
|
||||
const Url = Cypress.env("GraphQl_Url");
|
||||
|
||||
cy.get(commonSelectors.globalDataSourceIcon).click();
|
||||
closeDSModal();
|
||||
|
||||
selectAndAddDataSource("databases", GraphQLText.GraphQL, data.dsName);
|
||||
|
||||
fillDataSourceTextField(
|
||||
GraphQLText.urlInputLabel,
|
||||
GraphQLText.urlInputPlaceholder,
|
||||
Url
|
||||
);
|
||||
|
||||
cy.get(postgreSqlSelector.buttonSave)
|
||||
.verifyVisibleElement("have.text", postgreSqlText.buttonTextSave)
|
||||
.click();
|
||||
cy.verifyToastMessage(
|
||||
commonSelectors.toastMessage,
|
||||
postgreSqlText.toastDSSaved
|
||||
);
|
||||
|
||||
deleteDatasource(`cypress-${data.dsName}-GraphQL`);
|
||||
});
|
||||
|
||||
it("Should able to run the query with valid conection", () => {
|
||||
const Url = Cypress.env("GraphQl_Url");
|
||||
|
||||
cy.get(commonSelectors.globalDataSourceIcon).click();
|
||||
closeDSModal();
|
||||
|
||||
selectAndAddDataSource("databases", GraphQLText.GraphQL, data.dsName);
|
||||
|
||||
fillDataSourceTextField(
|
||||
GraphQLText.urlInputLabel,
|
||||
GraphQLText.urlInputPlaceholder,
|
||||
Url
|
||||
);
|
||||
|
||||
cy.get(postgreSqlSelector.buttonSave)
|
||||
.verifyVisibleElement("have.text", postgreSqlText.buttonTextSave)
|
||||
.click();
|
||||
cy.verifyToastMessage(
|
||||
commonSelectors.toastMessage,
|
||||
postgreSqlText.toastDSSaved
|
||||
);
|
||||
|
||||
cy.get(commonSelectors.globalDataSourceIcon).click();
|
||||
|
||||
cy.get(commonSelectors.dashboardIcon).click();
|
||||
cy.get(commonSelectors.appCreateButton).click();
|
||||
cy.get(commonSelectors.appNameInput).click().type(data.dsName);
|
||||
cy.get(commonSelectors.createAppButton).click();
|
||||
cy.skipWalkthrough();
|
||||
|
||||
cy.get('[data-cy="show-ds-popover-button"]').click();
|
||||
cy.get(".css-4e90k9").type(`${data.dsName}`);
|
||||
cy.contains(`[id*="react-select-"]`, data.dsName).click();
|
||||
cy.get('[data-cy="query-rename-input"]').clear().type(data.dsName);
|
||||
|
||||
cy.get('[data-cy="query-input-field"]').clearAndTypeOnCodeMirror(
|
||||
`{
|
||||
allFilms {
|
||||
films { title director }
|
||||
}
|
||||
}`
|
||||
);
|
||||
cy.get(dataSourceSelector.queryPreviewButton).click();
|
||||
cy.verifyToastMessage(
|
||||
commonSelectors.toastMessage,
|
||||
`Query (${data.dsName}) completed.`
|
||||
);
|
||||
deleteAppandDatasourceAfterExecution(
|
||||
data.dsName,
|
||||
`cypress-${data.dsName}-GraphQL`
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,343 @@
|
|||
import { fake } from "Fixtures/fake";
|
||||
import { postgreSqlSelector } from "Selectors/postgreSql";
|
||||
import { postgreSqlText } from "Texts/postgreSql";
|
||||
import { harperDbText } from "Texts/harperDb";
|
||||
import { harperDbSelectors } from "Selectors/Plugins";
|
||||
import { commonSelectors } from "Selectors/common";
|
||||
import { commonText } from "Texts/common";
|
||||
|
||||
import {
|
||||
fillDataSourceTextField,
|
||||
selectAndAddDataSource,
|
||||
} from "Support/utils/postgreSql";
|
||||
|
||||
import {
|
||||
deleteDatasource,
|
||||
closeDSModal,
|
||||
deleteAppandDatasourceAfterExecution,
|
||||
} from "Support/utils/dataSource";
|
||||
|
||||
import { dataSourceSelector } from "../../../../../constants/selectors/dataSource";
|
||||
|
||||
const data = {};
|
||||
data.dsName = fake.lastName.toLowerCase().replaceAll("[^A-Za-z]", "");
|
||||
data.dsName1 = fake.lastName.toLowerCase().replaceAll("[^A-Za-z]", "");
|
||||
|
||||
describe("Data source HarperDB", () => {
|
||||
beforeEach(() => {
|
||||
cy.apiLogin();
|
||||
cy.defaultWorkspaceLogin();
|
||||
});
|
||||
|
||||
it("Should verify elements on HarperDB connection form", () => {
|
||||
const Host = Cypress.env("harperdb_host");
|
||||
const Port = Cypress.env("harperdb_port");
|
||||
const Username = Cypress.env("harperdb_username");
|
||||
const Password = Cypress.env("harperdb_password");
|
||||
|
||||
cy.get(commonSelectors.globalDataSourceIcon).click();
|
||||
closeDSModal();
|
||||
|
||||
cy.get(postgreSqlSelector.allDatasourceLabelAndCount).should(
|
||||
"have.text",
|
||||
postgreSqlText.allDataSources()
|
||||
);
|
||||
cy.get(postgreSqlSelector.commonlyUsedLabelAndCount).should(
|
||||
"have.text",
|
||||
postgreSqlText.commonlyUsed
|
||||
);
|
||||
cy.get(postgreSqlSelector.databaseLabelAndCount).should(
|
||||
"have.text",
|
||||
postgreSqlText.allDatabase()
|
||||
);
|
||||
cy.get(postgreSqlSelector.apiLabelAndCount).should(
|
||||
"have.text",
|
||||
postgreSqlText.allApis
|
||||
);
|
||||
cy.get(postgreSqlSelector.cloudStorageLabelAndCount).should(
|
||||
"have.text",
|
||||
postgreSqlText.allCloudStorage
|
||||
);
|
||||
|
||||
cy.installMarketplacePlugin("HarperDB");
|
||||
|
||||
selectAndAddDataSource("databases", harperDbText.harperDb, data.dsName);
|
||||
|
||||
fillDataSourceTextField(
|
||||
harperDbText.hostLabel,
|
||||
harperDbText.hostInputPlaceholder,
|
||||
Host
|
||||
);
|
||||
|
||||
fillDataSourceTextField(
|
||||
harperDbText.portLabel,
|
||||
harperDbText.portPlaceholder,
|
||||
Port
|
||||
);
|
||||
|
||||
fillDataSourceTextField(
|
||||
harperDbText.userNameLabel,
|
||||
harperDbText.userNamePlaceholder,
|
||||
Username
|
||||
);
|
||||
|
||||
fillDataSourceTextField(
|
||||
harperDbText.passwordlabel,
|
||||
harperDbText.passwordPlaceholder,
|
||||
Password
|
||||
);
|
||||
|
||||
cy.get(postgreSqlSelector.buttonTestConnection).click();
|
||||
cy.get(postgreSqlSelector.textConnectionVerified, {
|
||||
timeout: 10000,
|
||||
}).should("have.text", postgreSqlText.labelConnectionVerified);
|
||||
|
||||
cy.get(postgreSqlSelector.buttonSave)
|
||||
.verifyVisibleElement("have.text", postgreSqlText.buttonTextSave)
|
||||
.click();
|
||||
|
||||
cy.verifyToastMessage(
|
||||
commonSelectors.toastMessage,
|
||||
postgreSqlText.toastDSSaved
|
||||
);
|
||||
|
||||
deleteDatasource(`cypress-${data.dsName}-HarperDB`);
|
||||
});
|
||||
|
||||
it("Should verify functionality of HarperDB connection form", () => {
|
||||
const Host = Cypress.env("harperdb_host");
|
||||
const Port = Cypress.env("harperdb_port");
|
||||
const Username = Cypress.env("harperdb_username");
|
||||
const Password = Cypress.env("harperdb_password");
|
||||
|
||||
cy.get(commonSelectors.globalDataSourceIcon).click();
|
||||
closeDSModal();
|
||||
|
||||
cy.installMarketplacePlugin("HarperDB");
|
||||
|
||||
selectAndAddDataSource("databases", harperDbText.harperDb, data.dsName);
|
||||
|
||||
fillDataSourceTextField(
|
||||
harperDbText.hostLabel,
|
||||
harperDbText.hostInputPlaceholder,
|
||||
Host
|
||||
);
|
||||
|
||||
fillDataSourceTextField(
|
||||
harperDbText.portLabel,
|
||||
harperDbText.portPlaceholder,
|
||||
Port
|
||||
);
|
||||
|
||||
fillDataSourceTextField(
|
||||
harperDbText.userNameLabel,
|
||||
harperDbText.userNamePlaceholder,
|
||||
Username
|
||||
);
|
||||
|
||||
fillDataSourceTextField(
|
||||
harperDbText.passwordlabel,
|
||||
harperDbText.passwordPlaceholder,
|
||||
Password
|
||||
);
|
||||
|
||||
cy.get(postgreSqlSelector.buttonTestConnection).click();
|
||||
cy.get(postgreSqlSelector.textConnectionVerified, {
|
||||
timeout: 10000,
|
||||
}).should("have.text", postgreSqlText.labelConnectionVerified);
|
||||
|
||||
cy.get(postgreSqlSelector.buttonSave)
|
||||
.verifyVisibleElement("have.text", postgreSqlText.buttonTextSave)
|
||||
.click();
|
||||
|
||||
cy.verifyToastMessage(
|
||||
commonSelectors.toastMessage,
|
||||
postgreSqlText.toastDSSaved
|
||||
);
|
||||
|
||||
deleteDatasource(`cypress-${data.dsName}-HarperDB`);
|
||||
});
|
||||
|
||||
it("Should be able to run the query with a valid connection", () => {
|
||||
const Host = Cypress.env("harperdb_host");
|
||||
const Port = Cypress.env("harperdb_port");
|
||||
const Username = Cypress.env("harperdb_username");
|
||||
const Password = Cypress.env("harperdb_password");
|
||||
|
||||
cy.get(commonSelectors.globalDataSourceIcon).click();
|
||||
closeDSModal();
|
||||
|
||||
cy.installMarketplacePlugin("HarperDB");
|
||||
|
||||
selectAndAddDataSource("databases", harperDbText.harperDb, data.dsName);
|
||||
|
||||
fillDataSourceTextField(
|
||||
harperDbText.hostLabel,
|
||||
harperDbText.hostInputPlaceholder,
|
||||
Host
|
||||
);
|
||||
|
||||
fillDataSourceTextField(
|
||||
harperDbText.portLabel,
|
||||
harperDbText.portPlaceholder,
|
||||
Port
|
||||
);
|
||||
|
||||
fillDataSourceTextField(
|
||||
harperDbText.userNameLabel,
|
||||
harperDbText.userNamePlaceholder,
|
||||
Username
|
||||
);
|
||||
|
||||
fillDataSourceTextField(
|
||||
harperDbText.passwordlabel,
|
||||
harperDbText.passwordPlaceholder,
|
||||
Password
|
||||
);
|
||||
|
||||
cy.get(postgreSqlSelector.buttonTestConnection).click();
|
||||
cy.get(postgreSqlSelector.textConnectionVerified, {
|
||||
timeout: 10000,
|
||||
}).should("have.text", postgreSqlText.labelConnectionVerified);
|
||||
|
||||
cy.get(postgreSqlSelector.buttonSave)
|
||||
.verifyVisibleElement("have.text", postgreSqlText.buttonTextSave)
|
||||
.click();
|
||||
|
||||
cy.verifyToastMessage(
|
||||
commonSelectors.toastMessage,
|
||||
postgreSqlText.toastDSSaved
|
||||
);
|
||||
|
||||
cy.get(commonSelectors.dashboardIcon).click();
|
||||
cy.get(commonSelectors.appCreateButton).click();
|
||||
cy.get(commonSelectors.appNameInput).click().type(data.dsName);
|
||||
cy.get(commonSelectors.createAppButton).click();
|
||||
cy.skipWalkthrough();
|
||||
|
||||
cy.get('[data-cy="show-ds-popover-button"]').click();
|
||||
cy.get(".css-4e90k9").type(`${data.dsName}`);
|
||||
cy.contains(`[id*="react-select-"]`, data.dsName).click();
|
||||
cy.get('[data-cy="query-rename-input"]').clear().type(data.dsName);
|
||||
|
||||
// Verifying NoSQL Operation
|
||||
|
||||
cy.get(".react-select__input")
|
||||
.eq(1)
|
||||
.click({ force: true })
|
||||
.wait(500)
|
||||
.type(`NoSQL mode{enter}`, { force: true });
|
||||
|
||||
const operationsDB = [
|
||||
"Insert",
|
||||
"Update",
|
||||
"Search By Hash",
|
||||
"Search By Value",
|
||||
"Search By Condition",
|
||||
"Delete",
|
||||
];
|
||||
|
||||
operationsDB.forEach((operation) => {
|
||||
cy.get(".react-select__input")
|
||||
.eq(2)
|
||||
.click({ force: true })
|
||||
.wait(500)
|
||||
.type(`${operation}{enter}`, { force: true });
|
||||
|
||||
const commonFields = {
|
||||
"schema-input-field": harperDbText.schemaValue,
|
||||
"table-input-field": harperDbText.tableValue,
|
||||
};
|
||||
|
||||
Object.entries(commonFields).forEach(([field, value]) => {
|
||||
cy.get(`[data-cy="${field}"]`).clearAndTypeOnCodeMirror(value);
|
||||
});
|
||||
|
||||
if (["Insert", "Update"].includes(operation)) {
|
||||
cy.get(harperDbSelectors.recordsInputField).clearAndTypeOnCodeMirror(
|
||||
harperDbText.recordsValue
|
||||
);
|
||||
}
|
||||
|
||||
if (operation === "Search By Hash") {
|
||||
cy.get(harperDbSelectors.hashValueInputField).clearAndTypeOnCodeMirror(
|
||||
harperDbText.hashValue
|
||||
);
|
||||
cy.get(harperDbSelectors.attributesInputField).clearAndTypeOnCodeMirror(
|
||||
harperDbText.attributesValue
|
||||
);
|
||||
}
|
||||
|
||||
if (operation === "Search By Value") {
|
||||
cy.get(
|
||||
harperDbSelectors.searchAttributeInputField
|
||||
).clearAndTypeOnCodeMirror(harperDbText.searchAttributeValue);
|
||||
|
||||
cy.get(
|
||||
harperDbSelectors.searchValueInputField
|
||||
).clearAndTypeOnCodeMirror(harperDbText.searchValue);
|
||||
cy.get(harperDbSelectors.attributesInputField).clearAndTypeOnCodeMirror(
|
||||
harperDbText.attributesValue
|
||||
);
|
||||
}
|
||||
|
||||
if (operation === "Search By Condition") {
|
||||
cy.get(".react-select__input")
|
||||
.eq(3)
|
||||
.click({ force: true })
|
||||
.wait(500)
|
||||
.type("Or{enter}", { force: true });
|
||||
|
||||
cy.get(harperDbSelectors.attributesInputField).clearAndTypeOnCodeMirror(
|
||||
harperDbText.attributesValue
|
||||
);
|
||||
cy.get(harperDbSelectors.conditionInputField).clearAndTypeOnCodeMirror(
|
||||
harperDbText.condtionValue
|
||||
);
|
||||
}
|
||||
|
||||
if (operation === "Delete") {
|
||||
cy.get(harperDbSelectors.hashValueInputField).clearAndTypeOnCodeMirror(
|
||||
harperDbText.hashValue
|
||||
);
|
||||
}
|
||||
|
||||
cy.get(dataSourceSelector.queryPreviewButton).click();
|
||||
cy.verifyToastMessage(
|
||||
commonSelectors.toastMessage,
|
||||
`Query (${data.dsName}) completed.`
|
||||
);
|
||||
});
|
||||
|
||||
// Verifying SQL Operation
|
||||
cy.get('[data-cy="show-ds-popover-button"]').click();
|
||||
cy.get(".css-4e90k9").type(`${data.dsName}`);
|
||||
cy.contains(`[id*="react-select-"]`, data.dsName).click();
|
||||
cy.get('[data-cy="query-rename-input"]').clear().type(data.dsName1);
|
||||
|
||||
cy.get(".react-select__input")
|
||||
.eq(1)
|
||||
.should("be.visible")
|
||||
.click({ force: true })
|
||||
.wait(500)
|
||||
.type(`SQL mode{enter}`, { force: true });
|
||||
|
||||
cy.wait(1000);
|
||||
|
||||
cy.get(harperDbSelectors.sqlQueryInputField).clearAndTypeOnCodeMirror(
|
||||
harperDbText.sqlValue
|
||||
);
|
||||
|
||||
cy.get(dataSourceSelector.queryPreviewButton).click();
|
||||
|
||||
cy.verifyToastMessage(
|
||||
commonSelectors.toastMessage,
|
||||
`Query (${data.dsName1}) completed.`
|
||||
);
|
||||
deleteAppandDatasourceAfterExecution(
|
||||
data.dsName,
|
||||
`cypress-${data.dsName}-HarperDB`
|
||||
);
|
||||
cy.uninstallMarketplacePlugin("HarperDB");
|
||||
});
|
||||
});
|
||||
|
|
@ -12,14 +12,11 @@ import {
|
|||
} from "Support/utils/postgreSql";
|
||||
|
||||
import {
|
||||
verifyCouldnotConnectWithAlert,
|
||||
deleteDatasource,
|
||||
closeDSModal,
|
||||
addQuery,
|
||||
addDsAndAddQuery,
|
||||
deleteAppandDatasourceAfterExecution,
|
||||
} from "Support/utils/dataSource";
|
||||
|
||||
import { openQueryEditor } from "Support/utils/dataSource";
|
||||
import { dataSourceSelector } from "../../../../../constants/selectors/dataSource";
|
||||
|
||||
const data = {};
|
||||
|
|
@ -40,16 +37,22 @@ describe("Data source minio", () => {
|
|||
cy.get(commonSelectors.globalDataSourceIcon).click();
|
||||
closeDSModal();
|
||||
|
||||
cy.get(postgreSqlSelector.allDatasourceLabelAndCount).should(
|
||||
"have.text",
|
||||
postgreSqlText.allDataSources()
|
||||
);
|
||||
cy.get(postgreSqlSelector.commonlyUsedLabelAndCount).should(
|
||||
"have.text",
|
||||
postgreSqlText.commonlyUsed
|
||||
);
|
||||
|
||||
cy.get(postgreSqlSelector.databaseLabelAndCount).should(
|
||||
"have.text",
|
||||
postgreSqlText.allDatabase()
|
||||
);
|
||||
cy.get(postgreSqlSelector.apiLabelAndCount).should(
|
||||
"have.text",
|
||||
postgreSqlText.allApis
|
||||
);
|
||||
|
||||
cy.get(postgreSqlSelector.cloudStorageLabelAndCount).should(
|
||||
"have.text",
|
||||
postgreSqlText.allCloudStorage
|
||||
|
|
@ -274,5 +277,9 @@ describe("Data source minio", () => {
|
|||
`Query (${data.dsName}) completed.`
|
||||
);
|
||||
});
|
||||
deleteAppandDatasourceAfterExecution(
|
||||
data.dsName,
|
||||
`cypress-${data.dsName}-minio`
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -11,26 +11,22 @@ import {
|
|||
} from "Support/utils/postgreSql";
|
||||
|
||||
import {
|
||||
verifyCouldnotConnectWithAlert,
|
||||
deleteDatasource,
|
||||
closeDSModal,
|
||||
addQuery,
|
||||
addDsAndAddQuery,
|
||||
deleteAppandDatasourceAfterExecution,
|
||||
} from "Support/utils/dataSource";
|
||||
|
||||
import { openQueryEditor } from "Support/utils/dataSource";
|
||||
import { dataSourceSelector } from "../../../../../constants/selectors/dataSource";
|
||||
|
||||
const data = {};
|
||||
data.dsName = fake.lastName.toLowerCase().replaceAll("[^A-Za-z]", "");
|
||||
|
||||
describe("Data source Redis", () => {
|
||||
beforeEach(() => {
|
||||
cy.appUILogin();
|
||||
cy.intercept("POST", "/api/data_queries").as("createQuery");
|
||||
cy.apiLogin();
|
||||
cy.defaultWorkspaceLogin();
|
||||
});
|
||||
|
||||
it("Should verify elements on connection Redison form", () => {
|
||||
it("Should verify elements on connection Redis form", () => {
|
||||
cy.get(commonSelectors.globalDataSourceIcon).click();
|
||||
closeDSModal();
|
||||
|
||||
|
|
@ -114,7 +110,7 @@ describe("Data source Redis", () => {
|
|||
deleteDatasource(`cypress-${data.dsName}-redis`);
|
||||
});
|
||||
|
||||
it("Should verify the functionality of Redis connection form.", () => {
|
||||
it("Should verify the functionality of Redis connection form", () => {
|
||||
selectAndAddDataSource("databases", redisText.redis, data.dsName);
|
||||
|
||||
fillDataSourceTextField(
|
||||
|
|
@ -143,7 +139,7 @@ describe("Data source Redis", () => {
|
|||
cy.get(postgreSqlSelector.buttonTestConnection).click();
|
||||
cy.get('[data-cy="connection-alert-text"]').should(
|
||||
"have.text",
|
||||
"WRONGPASS invalid username-password pair or user is disabled."
|
||||
redisText.errorInvalidUserOrPassword
|
||||
);
|
||||
fillDataSourceTextField(
|
||||
postgreSqlText.labelHost,
|
||||
|
|
@ -176,7 +172,7 @@ describe("Data source Redis", () => {
|
|||
cy.get(postgreSqlSelector.buttonTestConnection).click();
|
||||
cy.get('[data-cy="connection-alert-text"]').should(
|
||||
"have.text",
|
||||
"WRONGPASS invalid username-password pair or user is disabled."
|
||||
redisText.errorInvalidUserOrPassword
|
||||
);
|
||||
|
||||
fillDataSourceTextField(
|
||||
|
|
@ -193,7 +189,7 @@ describe("Data source Redis", () => {
|
|||
cy.get(postgreSqlSelector.buttonTestConnection).click();
|
||||
cy.get('[data-cy="connection-alert-text"]').should(
|
||||
"have.text",
|
||||
"WRONGPASS invalid username-password pair or user is disabled."
|
||||
redisText.errorInvalidUserOrPassword
|
||||
);
|
||||
|
||||
fillDataSourceTextField(
|
||||
|
|
@ -256,5 +252,9 @@ describe("Data source Redis", () => {
|
|||
cy.skipWalkthrough();
|
||||
|
||||
addDsAndAddQuery("redis", `TIME`, `cypress-${data.dsName}-redis`);
|
||||
deleteAppandDatasourceAfterExecution(
|
||||
data.dsName,
|
||||
`cypress-${data.dsName}-redis`
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -0,0 +1,383 @@
|
|||
import { fake } from "Fixtures/fake";
|
||||
import { commonSelectors } from "Selectors/common";
|
||||
import { closeDSModal, deleteDatasource } from "Support/utils/dataSource";
|
||||
import { postgreSqlSelector } from "Selectors/postgreSql";
|
||||
import { postgreSqlText } from "Texts/postgreSql";
|
||||
import { restAPISelector } from "Selectors/restAPI";
|
||||
import { restAPIText } from "Texts/restAPI";
|
||||
import { fillDataSourceTextField } from "Support/utils/postgreSql";
|
||||
|
||||
const data = {};
|
||||
const authenticationDropdownSelector =
|
||||
".dynamic-form-element > .css-nwhe5y-container > .react-select__control";
|
||||
const grantTypeDropdown =
|
||||
":nth-child(1) > :nth-child(2) > .react-select__control";
|
||||
const addAccessTokenDropdown =
|
||||
":nth-child(9) > .css-nwhe5y-container > .react-select__control";
|
||||
const clientAuthenticationDropdown =
|
||||
":nth-child(14) > .css-nwhe5y-container > .react-select__control";
|
||||
|
||||
describe("Data source Rest API", () => {
|
||||
beforeEach(() => {
|
||||
cy.defaultWorkspaceLogin();
|
||||
cy.intercept("GET", "/api/v2/data_sources");
|
||||
data.dataSourceName = fake.lastName
|
||||
.toLowerCase()
|
||||
.replaceAll("[^A-Za-z]", "");
|
||||
});
|
||||
it("Should verify elements on Rest API connection form", () => {
|
||||
cy.get(commonSelectors.globalDataSourceIcon).click();
|
||||
closeDSModal();
|
||||
cy.get(postgreSqlSelector.allDatasourceLabelAndCount).should(
|
||||
"have.text",
|
||||
postgreSqlText.allDataSources()
|
||||
);
|
||||
cy.get(postgreSqlSelector.commonlyUsedLabelAndCount).should(
|
||||
"have.text",
|
||||
postgreSqlText.commonlyUsed
|
||||
);
|
||||
cy.get(postgreSqlSelector.databaseLabelAndCount).should(
|
||||
"have.text",
|
||||
postgreSqlText.allDatabase()
|
||||
);
|
||||
cy.get(postgreSqlSelector.apiLabelAndCount).should(
|
||||
"have.text",
|
||||
postgreSqlText.allApis
|
||||
);
|
||||
cy.get(postgreSqlSelector.cloudStorageLabelAndCount).should(
|
||||
"have.text",
|
||||
postgreSqlText.allCloudStorage
|
||||
);
|
||||
|
||||
cy.apiCreateGDS(
|
||||
`${Cypress.env("server_host")}/api/data-sources`,
|
||||
`cypress-${data.dataSourceName}-restapi`,
|
||||
"restapi",
|
||||
[
|
||||
{ key: "url", value: "" },
|
||||
{ key: "auth_type", value: "none" },
|
||||
{ key: "grant_type", value: "authorization_code" },
|
||||
{ key: "add_token_to", value: "header" },
|
||||
{ key: "header_prefix", value: "Bearer " },
|
||||
{ key: "access_token_url", value: "" },
|
||||
{ key: "client_id", value: "" },
|
||||
{ key: "client_secret", value: "", encrypted: true },
|
||||
{ key: "audience", value: "" },
|
||||
{ key: "scopes", value: "read, write" },
|
||||
{ key: "username", value: "", encrypted: false },
|
||||
{ key: "password", value: "", encrypted: true },
|
||||
{ key: "bearer_token", value: "", encrypted: true },
|
||||
{ key: "auth_url", value: "" },
|
||||
{ key: "client_auth", value: "header" },
|
||||
{ key: "headers", value: [["", ""]] },
|
||||
{ key: "custom_query_params", value: [["", ""]], encrypted: false },
|
||||
{ key: "custom_auth_params", value: [["", ""]] },
|
||||
{
|
||||
key: "access_token_custom_headers",
|
||||
value: [["", ""]],
|
||||
encrypted: false,
|
||||
},
|
||||
{ key: "multiple_auth_enabled", value: false, encrypted: false },
|
||||
{ key: "ssl_certificate", value: "none", encrypted: false },
|
||||
{ key: "retry_network_errors", value: true, encrypted: false },
|
||||
]
|
||||
);
|
||||
cy.reload();
|
||||
cy.get(`[data-cy="cypress-${data.dataSourceName}-restapi-button"]`)
|
||||
.should("be.visible")
|
||||
.click();
|
||||
cy.get(restAPISelector.inputField("data-source-name")).should(
|
||||
"have.value",
|
||||
`cypress-${data.dataSourceName}-restapi`
|
||||
);
|
||||
cy.get(restAPISelector.subHeaderLabel(restAPIText.credentialsText)).should(
|
||||
"have.text",
|
||||
restAPIText.credentialsText
|
||||
);
|
||||
const sections = [
|
||||
restAPIText.baseUrlLabel,
|
||||
restAPIText.headersLabel,
|
||||
restAPIText.urlParametesLabel,
|
||||
restAPIText.bodyLabel,
|
||||
restAPIText.cookiesLabel,
|
||||
];
|
||||
|
||||
sections.forEach((section) => {
|
||||
cy.get(restAPISelector.subHeaderLabel(section)).should(
|
||||
"have.text",
|
||||
section
|
||||
);
|
||||
|
||||
if (section !== restAPIText.baseUrlLabel) {
|
||||
cy.get(restAPISelector.keyInputField(section, 0)).should("be.visible");
|
||||
cy.get(restAPISelector.valueInputField(section, 0)).should(
|
||||
"be.visible"
|
||||
);
|
||||
cy.get(restAPISelector.deleteButton(section, 0)).should("be.visible");
|
||||
cy.get(restAPISelector.addMoreButton(section)).should("be.visible");
|
||||
} else {
|
||||
cy.get('[data-cy="base-url-text-field"]').should("be.visible");
|
||||
}
|
||||
});
|
||||
|
||||
cy.get(
|
||||
restAPISelector.subHeaderLabel(restAPIText.authenticationText)
|
||||
).should("have.text", restAPIText.authenticationText);
|
||||
cy.get(
|
||||
restAPISelector.subHeaderLabel(restAPIText.authenticationTypeLabel)
|
||||
).should("have.text", restAPIText.authenticationTypeLabel);
|
||||
|
||||
cy.get(authenticationDropdownSelector).click();
|
||||
cy.contains(
|
||||
`[id*="react-select-"]`,
|
||||
restAPIText.basicAuth.basicText
|
||||
).click();
|
||||
cy.get(authenticationDropdownSelector).should(
|
||||
"have.text",
|
||||
restAPIText.basicAuth.basicText
|
||||
);
|
||||
|
||||
cy.get(
|
||||
restAPISelector.subHeaderLabel(restAPIText.basicAuth.usernameLabel)
|
||||
).should("have.text", restAPIText.basicAuth.usernameLabel);
|
||||
cy.get(
|
||||
restAPISelector.inputField(restAPIText.basicAuth.usernameLabel)
|
||||
).should("be.visible");
|
||||
cy.get(
|
||||
restAPISelector.subHeaderLabel(restAPIText.basicAuth.passwordLabel)
|
||||
).should("have.text", restAPIText.basicAuth.passwordLabel);
|
||||
cy.get(restAPISelector.button(restAPIText.editButtonText)).should(
|
||||
"be.visible"
|
||||
);
|
||||
cy.get(
|
||||
restAPISelector.inputField(restAPIText.basicAuth.passwordLabel)
|
||||
).should("be.visible");
|
||||
|
||||
cy.get(authenticationDropdownSelector).click();
|
||||
cy.contains(`[id*="react-select-"]`, restAPIText.bearerAuth.bearerText)
|
||||
.should("be.visible")
|
||||
.click();
|
||||
cy.get(authenticationDropdownSelector).should(
|
||||
"have.text",
|
||||
restAPIText.bearerAuth.bearerText
|
||||
);
|
||||
cy.get(
|
||||
restAPISelector.subHeaderLabel(restAPIText.bearerAuth.tokenLabel)
|
||||
).should("have.text", restAPIText.bearerAuth.tokenLabel);
|
||||
cy.get(
|
||||
restAPISelector.inputField(restAPIText.bearerAuth.tokenLabel)
|
||||
).should("be.visible");
|
||||
|
||||
cy.get(authenticationDropdownSelector).click();
|
||||
cy.contains(`[id*="react-select-"]`, restAPIText.oAuthText).click();
|
||||
cy.get(authenticationDropdownSelector).should(
|
||||
"have.text",
|
||||
restAPIText.oAuthText
|
||||
);
|
||||
cy.get(restAPISelector.subHeaderLabel(restAPIText.grantTypeLabel)).should(
|
||||
"have.text",
|
||||
restAPIText.grantTypeLabel
|
||||
);
|
||||
cy.get(grantTypeDropdown).click();
|
||||
cy.contains(
|
||||
`[id*="react-select-"]`,
|
||||
restAPIText.authorizationCode.authorizationCodeLabel
|
||||
)
|
||||
.should("be.visible")
|
||||
.click();
|
||||
cy.get(grantTypeDropdown).should(
|
||||
"contain",
|
||||
restAPIText.authorizationCode.authorizationCodeLabel
|
||||
);
|
||||
cy.get(
|
||||
restAPISelector.inputField(
|
||||
restAPIText.authorizationCode.headerPrefixLabel
|
||||
)
|
||||
).should(($input) => {
|
||||
expect($input.val().trim()).to.equal(restAPIText.bearerAuth.bearerText);
|
||||
});
|
||||
cy.get(
|
||||
restAPISelector.inputField(
|
||||
restAPIText.authorizationCode.accessTokenURLLabel
|
||||
)
|
||||
)
|
||||
.invoke("attr", "placeholder")
|
||||
.should("eq", "https://api.example.com/oauth/token");
|
||||
cy.get(
|
||||
restAPISelector.inputField(restAPIText.authorizationCode.clientIDLabel)
|
||||
).should("be.visible");
|
||||
cy.get(restAPISelector.button(restAPIText.editButtonText)).should(
|
||||
"be.visible"
|
||||
);
|
||||
cy.get(
|
||||
restAPISelector.inputField(
|
||||
restAPIText.authorizationCode.clientSecretLabel
|
||||
)
|
||||
).should("be.visible");
|
||||
Object.entries(restAPIText.authorizationCode).forEach(([key, value]) => {
|
||||
if (
|
||||
key !== "authorizationCodeLabel" &&
|
||||
key !== "requestHeader" &&
|
||||
key !== "sendBasicAuthheaderOption" &&
|
||||
key !== "sendClientCredentialsBodyOption"
|
||||
) {
|
||||
cy.get(
|
||||
restAPISelector.subHeaderLabel(restAPIText.authorizationCode[key])
|
||||
).should("have.text", value);
|
||||
}
|
||||
});
|
||||
cy.get(addAccessTokenDropdown)
|
||||
.should("be.visible")
|
||||
.and("contain", restAPIText.authorizationCode.requestHeader);
|
||||
cy.get(
|
||||
restAPISelector.inputField(restAPIText.authorizationCode.scopeLabel)
|
||||
).should("be.visible");
|
||||
|
||||
const authorizationCodeSections = [
|
||||
restAPIText.authorizationCode.accessTokenURLCustomHeadersLabel,
|
||||
restAPIText.authorizationCode.customQueryParametersLabel,
|
||||
restAPIText.authorizationCode.customAuthenticationParametersLabel,
|
||||
];
|
||||
authorizationCodeSections.forEach((authorizationCodeSections) => {
|
||||
cy.get(
|
||||
restAPISelector.subHeaderLabel(authorizationCodeSections)
|
||||
).verifyVisibleElement("have.text", authorizationCodeSections);
|
||||
if (authorizationCodeSections !== restAPIText.baseUrlLabel) {
|
||||
cy.get(
|
||||
restAPISelector.keyInputField(authorizationCodeSections, 0)
|
||||
).should("be.visible");
|
||||
cy.get(
|
||||
restAPISelector.valueInputField(authorizationCodeSections, 0)
|
||||
).should("be.visible");
|
||||
cy.get(
|
||||
restAPISelector.deleteButton(authorizationCodeSections, 0)
|
||||
).should("be.visible");
|
||||
cy.get(restAPISelector.addMoreButton(authorizationCodeSections)).should(
|
||||
"be.visible"
|
||||
);
|
||||
} else {
|
||||
cy.get('[data-cy="base-url-text-field"]').should("be.visible");
|
||||
}
|
||||
});
|
||||
cy.get(clientAuthenticationDropdown).click();
|
||||
cy.contains(
|
||||
`[id*="react-select-"]`,
|
||||
restAPIText.authorizationCode.sendClientCredentialsBodyOption
|
||||
).should("be.visible");
|
||||
cy.contains(
|
||||
`[id*="react-select-"]`,
|
||||
restAPIText.authorizationCode.sendBasicAuthheaderOption
|
||||
)
|
||||
.should("be.visible")
|
||||
.click();
|
||||
cy.get(clientAuthenticationDropdown).should(
|
||||
"have.text",
|
||||
restAPIText.authorizationCode.sendBasicAuthheaderOption
|
||||
);
|
||||
cy.get(
|
||||
restAPISelector.subHeaderLabel(
|
||||
restAPIText.authorizationCode.authenticationRequiredUsersToggle
|
||||
)
|
||||
).verifyVisibleElement(
|
||||
"have.text",
|
||||
restAPIText.authorizationCode.authenticationRequiredUsersToggle
|
||||
);
|
||||
cy.get(restAPISelector.authenticationAllUsersToggleSwitch).should(
|
||||
"be.visible"
|
||||
);
|
||||
cy.get(grantTypeDropdown).click();
|
||||
cy.contains(
|
||||
`[id*="react-select-"]`,
|
||||
restAPIText.clientCredentials.clientCredentialsLabel
|
||||
)
|
||||
.should("be.visible")
|
||||
.click();
|
||||
cy.get(grantTypeDropdown).should(
|
||||
"contain",
|
||||
restAPIText.clientCredentials.clientCredentialsLabel
|
||||
);
|
||||
Object.entries(restAPIText.clientCredentials).forEach(([key, value]) => {
|
||||
if (key !== "clientCredentialsLabel") {
|
||||
cy.get(
|
||||
restAPISelector.subHeaderLabel(restAPIText.clientCredentials[key])
|
||||
).should("have.text", value);
|
||||
}
|
||||
});
|
||||
|
||||
cy.get(
|
||||
restAPISelector.subHeaderLabel(restAPIText.secureSocketsLayerText)
|
||||
).should("have.text", restAPIText.secureSocketsLayerText);
|
||||
cy.get(restAPISelector.dropdownLabel("SSL Certificate")).should(
|
||||
"have.text",
|
||||
"SSL Certificate"
|
||||
);
|
||||
cy.get(
|
||||
restAPISelector.subHeaderLabel(restAPIText.generalSettingsText)
|
||||
).should("have.text", restAPIText.generalSettingsText);
|
||||
cy.get(restAPISelector.retryNetworkToggleSwitch).should("be.visible");
|
||||
cy.get(restAPISelector.retryNetworkToggleText).should(
|
||||
"have.text",
|
||||
restAPIText.retryNetworkErrorsToggleLabel
|
||||
);
|
||||
cy.get(restAPISelector.retryNetworkToggleSubtext).should(
|
||||
"have.text",
|
||||
restAPIText.retryToggleHelperText
|
||||
);
|
||||
cy.get(restAPISelector.readDocumentationLinkText).should(
|
||||
"have.text",
|
||||
postgreSqlText.readDocumentation
|
||||
);
|
||||
cy.contains("Save").click();
|
||||
cy.verifyToastMessage(commonSelectors.toastMessage, "Data Source Saved");
|
||||
deleteDatasource(`cypress-${data.dataSourceName}-restapi`);
|
||||
});
|
||||
it("Should verify connection for Rest API", () => {
|
||||
cy.apiCreateGDS(
|
||||
`${Cypress.env("server_host")}/api/data-sources`,
|
||||
`cypress-${data.dataSourceName}-restapi`,
|
||||
"restapi",
|
||||
[
|
||||
{ key: "url", value: Cypress.env("restAPI_BaseURL") },
|
||||
{ key: "auth_type", value: "none" },
|
||||
{ key: "grant_type", value: "authorization_code" },
|
||||
{ key: "add_token_to", value: "header" },
|
||||
{ key: "header_prefix", value: "Bearer " },
|
||||
{ key: "access_token_url", value: "" },
|
||||
{ key: "client_id", value: "" },
|
||||
{ key: "client_secret", value: "", encrypted: true },
|
||||
{ key: "audience", value: "" },
|
||||
{ key: "scopes", value: "read, write" },
|
||||
{ key: "username", value: "", encrypted: false },
|
||||
{ key: "password", value: "", encrypted: true },
|
||||
{ key: "bearer_token", value: "", encrypted: true },
|
||||
{ key: "auth_url", value: "" },
|
||||
{ key: "client_auth", value: "header" },
|
||||
{ key: "headers", value: [["", ""]] },
|
||||
{ key: "custom_query_params", value: [["", ""]], encrypted: false },
|
||||
{ key: "custom_auth_params", value: [["", ""]] },
|
||||
{
|
||||
key: "access_token_custom_headers",
|
||||
value: [["", ""]],
|
||||
encrypted: false,
|
||||
},
|
||||
{ key: "multiple_auth_enabled", value: false, encrypted: false },
|
||||
{ key: "ssl_certificate", value: "none", encrypted: false },
|
||||
{ key: "retry_network_errors", value: true, encrypted: false },
|
||||
]
|
||||
);
|
||||
cy.reload();
|
||||
// cy.apiCreateApp(`${fake.companyName}-restAPI-App`);
|
||||
// cy.apiAddQueryToApp(
|
||||
// "restapi1",
|
||||
// {
|
||||
// method: "get",
|
||||
// url: "",
|
||||
// url_params: [["", ""]],
|
||||
// headers: [["", ""]],
|
||||
// cookies: [["", ""]],
|
||||
// },
|
||||
// `cypress-${data.dataSourceName}-restapi`,
|
||||
// "restapi"
|
||||
// );
|
||||
});
|
||||
});
|
||||
|
|
@ -12,14 +12,11 @@ import {
|
|||
} from "Support/utils/postgreSql";
|
||||
|
||||
import {
|
||||
verifyCouldnotConnectWithAlert,
|
||||
deleteDatasource,
|
||||
closeDSModal,
|
||||
addQuery,
|
||||
addDsAndAddQuery,
|
||||
deleteAppandDatasourceAfterExecution,
|
||||
} from "Support/utils/dataSource";
|
||||
|
||||
import { openQueryEditor } from "Support/utils/dataSource";
|
||||
import { dataSourceSelector } from "../../../../../constants/selectors/dataSource";
|
||||
import { pluginSelectors } from "Selectors/plugins";
|
||||
|
||||
|
|
@ -40,11 +37,18 @@ describe("Data source Twilio", () => {
|
|||
cy.get(commonSelectors.globalDataSourceIcon).click();
|
||||
closeDSModal();
|
||||
|
||||
cy.get(postgreSqlSelector.allDatasourceLabelAndCount).should(
|
||||
"have.text",
|
||||
postgreSqlText.allDataSources()
|
||||
);
|
||||
cy.get(postgreSqlSelector.commonlyUsedLabelAndCount).should(
|
||||
"have.text",
|
||||
postgreSqlText.commonlyUsed
|
||||
);
|
||||
|
||||
cy.get(postgreSqlSelector.databaseLabelAndCount).should(
|
||||
"have.text",
|
||||
postgreSqlText.allDatabase()
|
||||
);
|
||||
cy.get(postgreSqlSelector.apiLabelAndCount).should(
|
||||
"have.text",
|
||||
postgreSqlText.allApis
|
||||
|
|
@ -185,5 +189,9 @@ describe("Data source Twilio", () => {
|
|||
commonSelectors.toastMessage,
|
||||
`Query (${data.dsName}) completed.`
|
||||
);
|
||||
deleteAppandDatasourceAfterExecution(
|
||||
data.dsName,
|
||||
`cypress-${data.dsName}-twilio`
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import { cyParamName } from "Selectors/common";
|
|||
import { commonSelectors, commonWidgetSelector } from "Selectors/common";
|
||||
import { commonText } from "Texts/common";
|
||||
import { dataSourceSelector } from "Selectors/dataSource";
|
||||
import { verifyAppDelete } from "Support/utils/dashboard";
|
||||
import { dataSourceText } from "Texts/dataSource";
|
||||
import { navigateToAppEditor } from "Support/utils/common";
|
||||
|
||||
|
|
@ -61,6 +62,16 @@ export const deleteDatasource = (datasourceName) => {
|
|||
// );
|
||||
};
|
||||
|
||||
export const deleteAppandDatasourceAfterExecution = (
|
||||
appName,
|
||||
datasourceName
|
||||
) => {
|
||||
cy.backToApps();
|
||||
cy.deleteApp(appName);
|
||||
verifyAppDelete(appName);
|
||||
deleteDatasource(datasourceName);
|
||||
};
|
||||
|
||||
export const closeDSModal = () => {
|
||||
cy.get("body").then(($body) => {
|
||||
cy.wait(500);
|
||||
|
|
@ -96,9 +107,7 @@ export const addQueryN = (queryName, query, dbName) => {
|
|||
export const addQuery = (queryName, query, dbName) => {
|
||||
cy.get('[data-cy="show-ds-popover-button"]').click();
|
||||
cy.get(".css-4e90k9").type(`${dbName}`);
|
||||
cy.intercept("POST", "/api/data_queries").as(
|
||||
"createQuery"
|
||||
);
|
||||
cy.intercept("POST", "/api/data_queries").as("createQuery");
|
||||
cy.contains(`[id*="react-select-"]`, dbName).click();
|
||||
|
||||
cy.get('[data-cy="query-rename-input"]').clear().type(queryName);
|
||||
|
|
@ -225,7 +234,14 @@ export const createDataQuery = (appName, url, key, value) => {
|
|||
});
|
||||
};
|
||||
|
||||
export const createRestAPIQuery = (queryName, dsName, key = '', value = '', url = "", run = true) => {
|
||||
export const createRestAPIQuery = (
|
||||
queryName,
|
||||
dsName,
|
||||
key = "",
|
||||
value = "",
|
||||
url = "",
|
||||
run = true
|
||||
) => {
|
||||
cy.getCookie("tj_auth_token").then((cookie) => {
|
||||
const headers = {
|
||||
"Tj-Workspace-Id": Cypress.env("workspaceId"),
|
||||
|
|
|
|||
|
|
@ -125,7 +125,8 @@ export const fillDataSourceTextField = (
|
|||
);
|
||||
cy.get(`[data-cy="${cyParamName(fieldName)}-text-field"]`).then(($field) => {
|
||||
if ($field.is(":disabled")) {
|
||||
cy.get(".datasource-edit-btn").click();
|
||||
cy.get(".datasource-edit-btn").wait(500).click();
|
||||
cy.wait(500);
|
||||
}
|
||||
});
|
||||
cy.get(`[data-cy="${cyParamName(fieldName)}-text-field"]`)
|
||||
|
|
@ -133,7 +134,9 @@ export const fillDataSourceTextField = (
|
|||
.should("eq", placeholder.replace(/\u00a0/g, " "));
|
||||
|
||||
cy.get(`[data-cy="${cyParamName(fieldName)}-text-field"]`)
|
||||
.wait(500)
|
||||
.clear()
|
||||
.wait(500)
|
||||
.type(input, args);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
# The application expects a separate .env.test for test environment configuration
|
||||
# Get detailed information about each variable here: https://docs.tooljet.com/docs/setup/env-vars
|
||||
|
||||
TOOLJET_HOST=http://localhost:80
|
||||
TOOLJET_HOST=http://localhost:8082
|
||||
LOCKBOX_MASTER_KEY= # replace_with_lockbox_master_key
|
||||
SECRET_KEY_BASE= # replace_with_secret_key_base
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
<h1 align="center">ToolJet Documentation</h1>
|
||||
</p>
|
||||
|
||||
The directory "ToolJet/docs/" holds the code and markdown source files for the ToolJet documentation website, which is accessible at [docs.tooljet.com](docs.tooljet.com)
|
||||
The directory "ToolJet/docs/" holds the code and markdown source files for the ToolJet documentation website, which is accessible at [docs.tooljet.ai](docs.tooljet.ai)
|
||||
|
||||
## Index
|
||||
- [Feedback](#feedback)
|
||||
|
|
@ -26,7 +26,7 @@ In case you encounter any issues with the ToolJet product, please select the rel
|
|||
To contribute to ToolJet documentation, you need to fork this repository and submit a pull request for the Markdown and/or image changes that you're proposing.
|
||||
|
||||
### Repository organization
|
||||
The content in this directory follows the organization of documentation at https://docs.tooljet.com
|
||||
The content in this directory follows the organization of documentation at https://docs.tooljet.ai
|
||||
|
||||
This directory contains the following folders:
|
||||
|
||||
|
|
@ -41,15 +41,15 @@ This directory contains the following folders:
|
|||
├── versioned_docs
|
||||
│ ├── version-x.x.x # Current/latest version (set it on docusauras.config.js)
|
||||
│ │ ├── Enterprise
|
||||
│ │ │ └── multi-environment.md # https://docs.tooljet.com/docs/Enterprise/multi-environment
|
||||
│ │ └── tooljet-database.md. # https://docs.tooljet.com/docs/tooljet-database
|
||||
│ │ │ └── multi-environment.md # https://docs.tooljet.ai/docs/Enterprise/multi-environment
|
||||
│ │ └── tooljet-database.md. # https://docs.tooljet.ai/docs/tooljet-database
|
||||
│ └── version-2.0.0
|
||||
│ │ ├── Enterprise
|
||||
│ │ │ └── multi-environment.md # https://docs.tooljet.com/docs/2.0.0/Enterprise/multi-environment
|
||||
│ │ │ └── multi-environment.md # https://docs.tooljet.ai/docs/2.0.0/Enterprise/multi-environment
|
||||
│ │ └── tooljet-database.md
|
||||
│ └── version-1.0.0
|
||||
│ ├── Enterprise
|
||||
│ │ └── multi-environment.md # https://docs.tooljet.com/docs/1.0.0/Enterprise/multi-environment
|
||||
│ │ └── multi-environment.md # https://docs.tooljet.ai/docs/1.0.0/Enterprise/multi-environment
|
||||
│ └── tooljet-database.md
|
||||
├── versioned_sidebars # includes sidebar for the specific versions
|
||||
│ ├── version-x.x.x-sidebars.json
|
||||
|
|
|
|||
|
|
@ -1,31 +1,17 @@
|
|||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
CONFIG_FILE="docusaurus.config.js"
|
||||
VERSIONS_FILE="versions.json"
|
||||
|
||||
# Extract lastVersion from docusaurus.config.js using sed
|
||||
LAST_VERSION=$(sed -n "s/.*lastVersion: *'\\([^']*\\)'.*/\\1/p" "$CONFIG_FILE")
|
||||
if [ -z "$LAST_VERSION" ]; then
|
||||
echo "Error: lastVersion not found in $CONFIG_FILE"
|
||||
# Ensure versions.json exists
|
||||
if [ ! -f "$VERSIONS_FILE" ]; then
|
||||
echo "Error: $VERSIONS_FILE not found."
|
||||
exit 1
|
||||
fi
|
||||
echo "Found lastVersion: $LAST_VERSION"
|
||||
|
||||
# Extract all version numbers from the entire file
|
||||
ALL_VERSIONS=$(grep -oE "'[0-9]+\.[0-9]+\.[0-9]+(-[A-Za-z]+)?'" "$CONFIG_FILE" | sed "s/'//g" | sort -u -V -r)
|
||||
if [ -z "$ALL_VERSIONS" ]; then
|
||||
echo "Error: No versions found in $CONFIG_FILE"
|
||||
exit 1
|
||||
fi
|
||||
echo "Found raw versions:"
|
||||
echo "$ALL_VERSIONS"
|
||||
|
||||
# Convert the extracted versions into a JSON array format
|
||||
VERSION_ARRAY=$(echo "$ALL_VERSIONS" | jq -R -s -c 'split("\n")[:-1] + ["'"$LAST_VERSION"'"] | unique')
|
||||
echo "Updating versions.json with: $VERSION_ARRAY"
|
||||
|
||||
# Update versions.json with combined data
|
||||
echo $VERSION_ARRAY | jq . > versions.json
|
||||
# Output existing versions from versions.json for reference
|
||||
echo "Using versions from $VERSIONS_FILE:"
|
||||
jq . "$VERSIONS_FILE"
|
||||
|
||||
# Install dependencies and build the project
|
||||
npm i && npm run build
|
||||
|
|
|
|||
|
|
@ -1,5 +0,0 @@
|
|||
{
|
||||
"label": "Enterprise",
|
||||
"position": 9,
|
||||
"collapsed": true
|
||||
}
|
||||
|
|
@ -1,320 +0,0 @@
|
|||
---
|
||||
id: superadmin
|
||||
title: Super Admin
|
||||
---
|
||||
|
||||
<div className='badge badge--primary heading-badge'>Available on: Paid plans</div>
|
||||
|
||||
A Super Admin is the user who has full access to all the Workspaces, Users, and Groups of an instance. An instance can have more than one Super Admin. A Super Admin has full control over other users' workspaces and can create users, groups, and other super admins.
|
||||
|
||||
The user details entered while setting up ToolJet will have Super Admin privileges.
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## How Super Admin is Different from Admin
|
||||
|
||||
| <div style={{ width:"100px"}}>Privilege </div>| Admin | Super Admin |
|
||||
| --------- | ----- | ----------- |
|
||||
| Manage Users in their workspace (Invite/Archive/Unarchive) | ✅ | ✅ |
|
||||
| Manage Groups in their workspace (Create Group/Add or Delete Users from groups/ Modify Group Permissions) | ✅ | ✅ |
|
||||
| Manage SSO in their workspace | ✅ | ✅ |
|
||||
| Manage Workspace Variables in their workspace | ✅ | ✅ |
|
||||
| Manage Workspace Constants in their workspace | ✅ | ✅ |
|
||||
| [Manage data sources for the user group in their workspace](/docs/data-sources/overview#user-permissions) | ✅ | ✅ |
|
||||
| [Access any user's personal workspace (create, edit or delete apps)](#access-any-workspace) | ❌ | ✅ |
|
||||
| [Archive Admin or any user of any workspace](#archiveunarchive-users) | ❌ | ✅ |
|
||||
| [Access any user's ToolJet database (create, edit or delete database)](#access-tooljet-db-in-any-workspace) | ❌ | ✅ |
|
||||
| [Manage any workspace's setting (Groups/SSO/Workspace constants)](#manage-workspace-settings-groupsssoworkspace-constants) | ❌ | ✅ |
|
||||
| [Manage all users from all the workspaces in the instance](#manage-all-users-in-the-instance) | ❌ | ✅ |
|
||||
| [Archive/Unarchive any user from all the workspaces in the instance](#archiving-a-user-from-all-the-workspaces-instance-level) | ❌ | ✅ |
|
||||
| [Reset password of any user](#reset-password-of-any-user) | ❌ | ✅ |
|
||||
| [Edit name of any user](#edit-name) | ❌ | ✅ |
|
||||
| [Make any user Super Admin](#make-the-user-super-admin) | ❌ | ✅ |
|
||||
| [Manage all workspaces in the instance(Archive/Unarchive)](#all-workspaces) | ❌ | ✅ |
|
||||
| [Restrict creation of personal workspace of users](#restrict-creation-of-personal-workspace-of-users) | ❌ | ✅ |
|
||||
| [Configure instance level login](#instance-login) | ❌ | ✅ |
|
||||
| [Enable Multiplayer editing](#enable-multiplayer-editing) | ❌ | ✅ |
|
||||
| [Implement White Labelling](#white-labelling) | ❌ | ✅ |
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## Super Admin features
|
||||
|
||||
### Access any workspace
|
||||
|
||||
If a user is a Super Admin, they can switch to any workspace created by any user within the instance using the Workspace Switcher located in the bottom left corner of the screen.
|
||||
|
||||
The dropdown will display all workspaces, including those created by both Super Admins and any other users.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/enterprise/superadmin/workspaceswitcher.png" alt="Superadmin: settings" />
|
||||
</div>
|
||||
|
||||
### Create, Edit or Delete apps from any user's personal workspace
|
||||
|
||||
Once the Super Admin access the workspace of any other user, they can create, edit or delete app on the workspace.
|
||||
|
||||
This also includes - modifying folders and importing, exporting, or cloning apps to any user's workspace.
|
||||
|
||||
### Archive/Unarchive Users
|
||||
|
||||
Super Admin can not only archive/unarchive users/admins on their workspace but also from the workspaces of any other user.
|
||||
|
||||
If a user is Super Admin, they just need to open the workspace in which they want to archive or unarchive a user. Then go to the **Workspace Settings** from the sidebar -> **Manage Users** -> **Archive/Unarchive** any user/admin
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/enterprise/superadmin/archiveusersa.png" alt="Superadmin: settings" />
|
||||
</div>
|
||||
|
||||
### Access ToolJet DB in any workspace
|
||||
|
||||
Super Admins have access to the database of any user's workspace - just like Super Admins can access any application in any workspace. They have full access to modify or create any table in the ToolJet DB of any workspace.
|
||||
|
||||
### Manage Workspace Settings (Groups/SSO/Workspace constants)
|
||||
|
||||
Super Admins have all the privileges that an Admin of a workspace have, Super Admins can:
|
||||
- **✅ Manage Groups**: Creating/Deleting/Updating a Group in any workspace
|
||||
- **✅ Manage SSO**: Full control over General Settings, Password login and other SSO options
|
||||
- **✅ Workspace Variables**: Adding, updating or deleting workspace variables
|
||||
- **✅ Workspace Constants**: Adding, updating or deleting workspace constants
|
||||
- **✅ Copilot**: Enabling or disabling Copilot
|
||||
- **✅ Custom Styles**: Adding or modifying custom styles
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## Settings
|
||||
|
||||
Only Super Admins can access the Settings. To access the Settings page, click on the **⚙️** button and select **Settings** from the dropdown.
|
||||
|
||||
- **[All Users](#all-users)**
|
||||
- **[All workspaces](#all-workspaces)**
|
||||
- **[Manage instance settings](#manage-instance-settings)**
|
||||
- **[License](#license)**
|
||||
- **[White labelling](#white-labelling)**
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img style={{ border:'0', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/enterprise/superadmin/settings.png" alt="Superadmin: settings" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## All Users
|
||||
|
||||
### Manage all Users in the Instance
|
||||
|
||||
**All Users** settings can be used to check the list of all the users available on all the workspaces in the instance. Super Admins can also promote/demote any user to/from Super Admin from this page. They can also archive/unarchive any user at an instance level from this setting.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/enterprise/superadmin/allusers1.png" alt="Superadmin: settings" />
|
||||
</div>
|
||||
|
||||
### Archiving a User from all the Workspaces (Instance Level)
|
||||
|
||||
Super Admins have the authority to deactivate any user at instance level. This will remove the user from all the workspaces in the instance.
|
||||
|
||||
To archive a user, go to the **All Users** settings, click on the kebab menu next to the user that is to be archived and select **Archive** option. Once the user is archived, the status will change from **Active** to **Archived**. The user will not be able to login to any workspace in the instance.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img style={{ border:'0', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/enterprise/superadmin/archiveinstance.png" alt="Superadmin: settings" />
|
||||
</div>
|
||||
|
||||
<br/>
|
||||
|
||||
**Unarchiving** a user from **All Users** settings will unarchive the user from the instance and not at workspace level.
|
||||
|
||||
**Info**: The user will be unarchived from instance level automatically if a workspace admin unarchives the user from their workspace.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/enterprise/superadmin/unarchiveinstance.png" alt="Superadmin: settings" />
|
||||
</div>
|
||||
|
||||
### Reset Password of any User
|
||||
|
||||
Super Admins can reset the password of any user from the **All Users** settings. To reset the password, click on the kebab menu next to the user and select **Reset Password** option. A pop-up will appear asking either to auto-generate a password or to enter a new password.
|
||||
|
||||
### Edit User Details
|
||||
|
||||
Super Admins can edit the details of any user from the **All Users** settings. To edit the details, click on the kebab menu next to the user and select **Edit user details** option.
|
||||
|
||||
#### Edit name
|
||||
|
||||
On selecting the **Edit user details** option, a drawer will open from the right. Super Admins can edit the name of the user from this drawer. Once the changes are made, click on the **Update** button.
|
||||
|
||||
#### Make the user Super Admin
|
||||
|
||||
From the **Edit user details** drawer, Super Admins can make any user as Super Admin or remove any Super Admin from the **All Users** settings. To make a user Super Admin, toggle on the **Super Admin** radio button. The user will become Super Admin and the Type column will update from **`Workspace`** to **`Instance`**.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/enterprise/superadmin/edituserdetailsinstance.png" alt="Superadmin: settings" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## All Workspaces
|
||||
|
||||
The All Workspaces tab provides a comprehensive view of all workspaces within the ToolJet instance. Super Admins can use this functionality to monitor and manage workspaces collectively, ensuring efficient administration and organization-wide oversight.
|
||||
|
||||
Super Admins have the authority to **archive** or **unarchive** workspaces of any user in the instance as needed. Archiving a workspace essentially sets it to an inactive state, removing it from active use. Conversely, unarchiving reactivates a previously archived workspace, making it accessible once again.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img style={{ border:'0', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/enterprise/superadmin/workspaces1.png" alt="Superadmin: settings" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
### Current Workspace
|
||||
|
||||
The **Current Workspace** label will be displayed next to the workspace that the Super Admin has currently opened. If the Super Admin archives the current workspace, they will be prompted to switch to another active workspace to ensure continuous accessibility.
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
### Open Active Workspaces
|
||||
|
||||
In the list of active workspaces, there is an option to open the workspace directly. This feature helps superadmins to quickly navigate to the workspace on the new tab of the browser and manage the workspace.
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
### Archive Workspaces
|
||||
|
||||
The **Archive** button on the right of the workspace name allows Super Admins to archive the workspace. Once archived, the workspace will be moved to the **Archived Workspaces** section.
|
||||
|
||||
**Impact**:
|
||||
- The apps on the archived workspace won't be accessable through the URL
|
||||
- Users will be logged out if they don't have access to any active workspace
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
### Archived Workspaces
|
||||
|
||||
The **Archived** section displays a list of all archived workspaces. Super Admins can unarchive any workspace from this section by clicking the **Unarchive** button.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img style={{ border:'0', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/enterprise/superadmin/workspaces2.png" alt="Superadmin: settings" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## Manage Instance Settings
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img style={{ border:'0', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/enterprise/superadmin/instanceoptions.png" alt="Superadmin: settings" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
### Restrict Creation of Personal Workspace of Users
|
||||
|
||||
When a user joins a workspace, they are provided with their own personal workspace and option to create new workspaces.
|
||||
|
||||
Super Admins can **control** this behavior from the Manage Settings page, they can **toggle off** the option to **Allow personal workspace**. Now whenever a user joins a workspace they won't be provided a personal workspace nor they will be able to create a new workspace in the instance.
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
### Enable Multiplayer Editing
|
||||
|
||||
Super Admins can enable multiplayer editing from the Manage Settings page. Once enabled, users will be able to edit the same app simultaneously resulting in real-time collaboration.
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
### Comments
|
||||
|
||||
Super Admins can enable comments from the Manage Settings page. Once enabled, users will be able to collaborate by adding comments anywhere on the canvas.
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## White Labelling
|
||||
This feature allows you to customize the ToolJet instance with your own branding. You can change the logo, favicon, and the name of the instance.
|
||||
|
||||
Check out the [White labelling](/docs/enterprise/white-label/) page for more details.
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## Instance Login
|
||||
|
||||
Instance login configuration at the Settings level allows super admins to set up and manage the default login method for all workspaces within the instance. This ensures a standardized login experience unless individual workspace admins choose to configure a different method for their specific workspace.
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
### Access and Permissions
|
||||
|
||||
Only super admins have the authority to configure **Instance login** settings. This ensures centralized control over the default login method across the entire instance.
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
### Super Admin URL
|
||||
|
||||
This URL serves as a fail-safe in scenarios where password login is disabled, SSO is not configured, or a paid plan expires. Importantly, this URL exclusively supports password login and is accessible only by the super admin, preventing any unauthorized access.
|
||||
|
||||
The default URL for super admin login is `https://<domain>/login/super-admin`. This URL can be accessed by the super admin to log in to the instance and manage the settings.
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
### Enable sign-up
|
||||
|
||||
The "Enable Sign Up" option allows users to sign up without being invited. It is important to note that this feature includes both password login and SSO, providing a seamless onboarding experience for users.
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
### Password login
|
||||
|
||||
Super admins can enable or disable password login for the entire instance. This setting ensures that all workspaces within the instance adhere to the same login method, unless individual workspace admins choose to configure a different method for their specific workspace.
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
### Enable Workspace Configuration
|
||||
|
||||
Turning off this option restricts workspace admins from configuring the login method for their workspace. This configuration hides the Workspace Login option from the workspace settings tab.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img style={{ border:'0', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/enterprise/superadmin/instancelogin.png" alt="Superadmin: settings" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## License
|
||||
|
||||
Manage the instance license via the **Settings** page. Super Admins have the capability to update the instance's license key from this page.
|
||||
|
||||
Check out the [License](/docs/org-management/licensing/self-hosted) page for more details.
|
||||
|
||||
</div>
|
||||
|
|
@ -1,59 +0,0 @@
|
|||
---
|
||||
id: white-label
|
||||
title: White Label
|
||||
---
|
||||
|
||||
<div className='badge badge--primary heading-badge'>Available on: Paid plans</div>
|
||||
|
||||
The White Label feature allows you to completely remove ToolJet's branding from the ToolJet platform, allowing you to replace it with your own customized logo, favicon and page title. This feature grants you full control over the visual identity of your ToolJet-powered application, ensuring a seamless and personalized user experience.
|
||||
|
||||
With this feature, you gain the ability to rebrand the following key elements:
|
||||
|
||||
- **Application Logo**: This includes the logo displayed on the login screen, dashboard, and app-editor.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img style={{ border:'0', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/enterprise/white-label/whitelabeln1.png" alt="ToolJet - Enterprise - White label" />
|
||||
</div>
|
||||
|
||||
- **Favicon**: The small icon associated with your application. It is displayed in the browser tab.
|
||||
|
||||
- **Page Title**: This is the text displayed in the browser tab.
|
||||
|
||||
Example, we have set a favicon image and page title as `Bon Ton` in the below image.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img style={{ border:'0', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/enterprise/white-label/title-and-favicon.png" alt="ToolJet - Enterprise - White label" />
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## Configuration
|
||||
|
||||
To enable white labelling, click on the gear icon on the bottom left of the dashboard and select `Settings`. From the settings page, click on the `White labelling` tab. On the White labelling page, you'll be able to configure the following:
|
||||
|
||||
- **Application Logo**: Add the URL of the image you want to use as your application logo. Preferred dimensions of the logo are: width `130px` and height `26px`.
|
||||
- **Favicon**: Enter the URL of the image you want to use as your application's favicon. Preferred dimensions of the favicon are: width `32px` and height `32px` or `16px` and height `16px`.
|
||||
- **Page Title**: Enter the text you want to display as your application's title. Preferred title length are 50-60 characters.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img style={{ border:'0', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/enterprise/white-label/settings.png" alt="ToolJet - Enterprise - White label" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## ToolJet Cloud
|
||||
|
||||
If you are using ToolJet Cloud, click on the gear icon on the bottom left of the dashboard and select `Settings`. From the settings page, click on the `White labelling` tab. On the White labelling page, you'll be able to configure the following:
|
||||
|
||||
- **Application Logo**: Add the URL of the image you want to use as your application logo. Preferred dimensions of the logo are: width `130px` and height `26px`.
|
||||
- **Page Title**: Enter the text you want to display as your application's title. Preferred title length are 50-60 characters.
|
||||
- **Favicon**: Enter the URL of the image you want to use as your application's favicon. Preferred dimensions of the favicon are: width `32px` and height `32px` or `16px` and height `16px`.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img style={{ border:'0', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/enterprise/white-label/cloud1.png" alt="ToolJet - Enterprise - White label" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
|
@ -7,7 +7,7 @@ Control component action invokes the component specific actions. Component speci
|
|||
|
||||
You can find the component specific actions for the specific component in their respective documentation. For example, you can find the component specific actions for the **Bounded Box** component in the [Bounded Box](/docs/widgets/bounded-box) documentation.
|
||||
|
||||
<details>
|
||||
<details id="tj-dropdown">
|
||||
<summary>Currently, Component specific actions are supported only by the below listed components.</summary>
|
||||
<div>
|
||||
<ul>
|
||||
|
|
|
|||
131
docs/docs/app-builder/anti-patterns.md
Normal file
131
docs/docs/app-builder/anti-patterns.md
Normal file
|
|
@ -0,0 +1,131 @@
|
|||
---
|
||||
id: anti-patterns
|
||||
title: Anti-Patterns to Avoid
|
||||
---
|
||||
|
||||
When building applications with ToolJet, it's essential to follow best practices to ensure your apps are efficient, maintainable, and provide a smooth user experience. This documentation outlines common anti-patterns to avoid while using ToolJet and offers solutions to optimize your applications.
|
||||
|
||||
---
|
||||
|
||||
## 1. Unmanaged Component Naming
|
||||
|
||||
- **Anti-Pattern**: Using default or non-descriptive names for components.
|
||||
- **Solution**: **Rename all components with meaningful names to make the apps more manageable as they grow.**
|
||||
- **Reason**: Descriptive names improve readability, making it easier for you and others to understand and maintain the app's structure.
|
||||
|
||||
---
|
||||
|
||||
## 2. Exceeding Component Limits
|
||||
|
||||
- **Anti-Pattern**: Having more than 2,500 components in a single app.
|
||||
- **Solution**: **Limit each app to a maximum of 2,500 components.**
|
||||
- **Reason**: Exceeding this number can slow down the app builder and live apps, impacting both development speed and user experience.
|
||||
|
||||
---
|
||||
|
||||
## 3. Client-Side Operations for Large Data Sets
|
||||
|
||||
- **Anti-Pattern**: Handling large data sets with client-side operations on the Table component.
|
||||
- **Solution**: **Implement [server-side operations](/docs/widgets/table/serverside-operations/overview) for handling large data sets.**
|
||||
- **Reason**: Server-side operations reduces the amount of data loaded at once, improving load times and performance.
|
||||
|
||||
---
|
||||
|
||||
## 4. Simultaneous Execution of Multiple JavaScript Queries
|
||||
|
||||
- **Anti-Pattern**: Triggering a large amount of JavaScript queries simultaneously through a single event. For example, using an event to trigger a **Run JavaScript code** query that contains code to execute 15-20 other **Run JavaScript code** queries within the application.
|
||||
- **Solution**: **Limit the number of simultaneous JavaScript queries triggered by a single event.**
|
||||
- **Reason**: Triggering numerous Run JavaScript queries at the same time can significantly degrade browser performance as it each JavaScript query creates **[new execution environment](https://developer.mozilla.org/en-US/docs/Web/API/HTML_DOM_API/Microtask_guide/In_depth#javascript_execution_contexts)** within the browser. JavaScript in browsers runs on a single main thread. When multiple scripts are executed concurrently, they compete for execution time on this thread.
|
||||
|
||||
---
|
||||
|
||||
## 5. Storing Base64 Data in Variables
|
||||
|
||||
- **Anti-Pattern**: Capturing and storing Base64 data directly in variables.
|
||||
- **Solution**: **Store large data, like base64 images, in a database and retrieve it as needed.**
|
||||
- **Reason**: Storing Base64 data in variables can consume significant memory and slow down the app. Retrieving data from a database as needed optimizes performance.
|
||||
|
||||
---
|
||||
|
||||
## 6. Loading All Tabs Simultaneously
|
||||
|
||||
- **Anti-Pattern**: Loading all items in the Tab component at once when there are numerous tabs.
|
||||
- **Solution**: **Enable the “Render only active tabs” option.**
|
||||
- **Reason**: This prevents unnecessary loading of inactive tabs, reducing initial load times and improving performance.
|
||||
|
||||
---
|
||||
|
||||
## 7. Excessive Number of Pages in an App
|
||||
|
||||
- **Anti-Pattern**: Including too many pages within a single app.
|
||||
- **Solution**: **Limit the number of pages per app to maintain optimal performance.**
|
||||
- **Reason**: An excessive number of pages can slow down the app and make it difficult to manage. Organize content efficiently and consider splitting the app if necessary.
|
||||
|
||||
---
|
||||
|
||||
## 8. Using Non-Blocking Commands in JavaScript for Synchronous Operations
|
||||
|
||||
- **Anti-Pattern**: Using non-blocking commands like `Promise.all` and `setTimeout` in the **Run JavaScript code** query when an accurate isLoading state is needed.
|
||||
- **Solution**: **Avoid non-blocking operations in JavaScript Queries if you require an accurate isLoading status. Ensure your code is synchronous within the Run JavaScript code query.**
|
||||
- **Reason**: Non-blocking operations can cause **Run JavaScript code** query to exit before these commands complete, leading to an incorrect isLoading status and potentially confusing users.
|
||||
|
||||
---
|
||||
|
||||
## 9. Triggering Unnecessary Queries on Page Load
|
||||
|
||||
- **Anti-Pattern**: Triggering all queries on page load, regardless of their necessity.
|
||||
- **Solution**: **For multi-page apps, only trigger queries on page load that are needed for the specific page.**
|
||||
- **Reason**: Loading unnecessary data consumes resources and slows down page load times. Optimizing queries enhances performance.
|
||||
|
||||
---
|
||||
|
||||
## 10. Using Actions inside Loop Functions
|
||||
- **Anti-Pattern**: Using actions inside loop functions.
|
||||
|
||||
Example:
|
||||
You have a Table displaying data from `{{page.variables.data}}` and a **Save Changes** button that updates the data. When users edit rows and click **Save Changes**, you might initially implement the update like this:
|
||||
|
||||
```javascript
|
||||
const data = page.variables.data;
|
||||
Object.values(components.table1.dataUpdates).forEach(ele => {
|
||||
data[ele.id] = ele;
|
||||
actions.setPageVariable("data", data);
|
||||
});
|
||||
```
|
||||
|
||||
The setPageVariable action is executed inside the loop for each row update. This causes the table to re-render every time the variable is updated, leading to significant performance degradation, especially when multiple rows or cells are updated simultaneously.
|
||||
|
||||
- **Solution**: **Modify your code to update the page variable once after all changes are processed**:
|
||||
|
||||
```javascript
|
||||
const data = page.variables.data;
|
||||
Object.values(components.table1.dataUpdates).forEach(ele => {
|
||||
data[ele.id] = ele;
|
||||
});
|
||||
actions.setPageVariable("data", data);
|
||||
```
|
||||
|
||||
- **Reason**: By updating the variable after the loop completes, the table re-renders only once. This reduces unnecessary processing and significantly improves performance when handling multiple updates.
|
||||
|
||||
---
|
||||
|
||||
## 11. Direct Mutation of Data
|
||||
|
||||
- **Anti-Pattern**: Directly mutating data structures through JavaScript code, such as using `queries.getEmployees.data = []`.
|
||||
- **Solution**: Always use ToolJet's built in **[actions](/docs/how-to/run-actions-from-runjs/)** to manipulate data.
|
||||
- **Reason**: Direct mutation of data can lead to unexpected bugs and make debugging more complex.
|
||||
|
||||
---
|
||||
|
||||
## 12. Naming Component/Query with Hyphen or Space
|
||||
|
||||
- **Anti-Pattern**: Naming components or queries with hyphens or spaces in between, such as `run-py1` or `my query`.
|
||||
- **Solution**: **Use names without hyphens or spaces**, or reference them using bracket notation (e.g., `{{queries['run-py1'].isLoading}}`).
|
||||
- **Reason**: Hyphens and spaces can cause syntax issues. Using bracket notation or avoiding these characters ensures consistency and prevents errors in query or component references.
|
||||
|
||||
---
|
||||
|
||||
## Conclusion
|
||||
|
||||
Avoiding these anti-patterns when using ToolJet ensures that your applications are efficient, responsive, and maintainable. By following these best practices, you can enhance user experience and simplify app management. Always consider the impact of your development choices on both performance and scalability.
|
||||
|
||||
|
|
@ -3,7 +3,15 @@ id: customstyles
|
|||
title: Custom Styles
|
||||
---
|
||||
|
||||
<div className='badge badge--primary heading-badge'>Available on: Paid plans</div>
|
||||
<div className="badge badge--primary heading-badge">
|
||||
<img
|
||||
src="/img/badge-icons/premium.svg"
|
||||
alt="Icon"
|
||||
width="16"
|
||||
height="16"
|
||||
/>
|
||||
<span>Paid feature</span>
|
||||
</div>
|
||||
|
||||
The Custom Styles feature in ToolJet allows users to apply their own CSS, overriding the default app styles. This enables easy customization of app appearance, and maintains consistent themes across all ToolJet apps. By using standardized styles, users avoid the repetitive task of manually styling components for each new app, enhancing development efficiency and ensuring visual coherence for a seamless user experience
|
||||
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ Debugger consists of two main sections:
|
|||
|
||||
To configure the app's global settings, click on the kebab menu(three vertical dots) on the left of the app name. Global settings include:
|
||||
|
||||
- **Unique app slug**: The unique slug of the application. This slug is used in the URL of the application. By default, the slug is the `app id` of the application. You can change the slug to a custom value. For example, if the slug is `7b56293b-be5a-401f-8806-b71625f8ee0d` you can change it to `<unique-name>` then the new URL of the application will be `https://app.tooljet.com/<workspace-name>/apps/<unique-name>/`
|
||||
- **Unique app slug**: The unique slug of the application. This slug is used in the URL of the application. By default, the slug is the `app id` of the application. You can change the slug to a custom value. For example, if the slug is `7b56293b-be5a-401f-8806-b71625f8ee0d` you can change it to `<unique-name>` then the new URL of the application will be `https://app.tooljet.ai/<workspace-name>/apps/<unique-name>/`
|
||||
- **App link**: The link to the application. This link can be used to share the application with other users of the workspace. If you want to share the application with users outside the workspace, you can make the application public from the **[Share](/docs/app-builder/share)** modal.
|
||||
- **Hide header for launched apps**: Toggle this on to the hide the tooljet's header when the applications are launched
|
||||
- **Maintenance mode**: Toggle this on to put the application in maintenance mode. When in **maintenance mode**, on launching the app, the user will get an error message that **the app is under maintenance**.
|
||||
|
|
|
|||
|
|
@ -15,13 +15,13 @@ Getting started is straightforward – design your interface, connect your data
|
|||
|
||||
Explore these hands-on guides to start building your first app. The step-by-step guides will walk you through the App-Builder's essential features:
|
||||
|
||||
- **[Create UIs Using Pre-Built Components](/docs/beta/app-builder/walkthrough/create-ui)**
|
||||
- **[Create Queries to Interact With Data Sources](/docs/beta/app-builder/walkthrough/create-queries)**
|
||||
- **[Use Custom Code](/docs/beta/app-builder/walkthrough/using-code)**
|
||||
- **[Access and Referring Values Withing The App-Builder](/docs/beta/app-builder/walkthrough/accessing-values)**
|
||||
- **[Create and Managing Variables](/docs/beta/app-builder/walkthrough/variables)**
|
||||
- **[Create UIs Using Pre-Built Components](/docs/app-builder/walkthrough/create-ui)**
|
||||
- **[Create Queries to Interact With Data Sources](/docs/app-builder/walkthrough/create-queries)**
|
||||
- **[Use Custom Code](/docs/app-builder/walkthrough/using-code)**
|
||||
- **[Access and Referring Values Within The App-Builder](/docs/app-builder/walkthrough/accessing-values)**
|
||||
- **[Create and Managing Variables](/docs/app-builder/walkthrough/variables)**
|
||||
- **[Use Gitsync to Sync your Application with a Git Repository](/docs/gitsync)**
|
||||
- **[Versioning and Release](/docs/tutorial/versioning-and-release)**
|
||||
- **[Import and Export Apps](/docs/beta/app-builder/walkthrough/importing-exporting-applications)**
|
||||
- **[Versioning and Release](/docs/development-lifecycle/release/version-control)**
|
||||
- **[Import and Export Apps](/docs/app-builder/importing-exporting-applications)**
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ id: query-panel
|
|||
title: Query Panel
|
||||
---
|
||||
|
||||
The Query Panel, located at the bottom of the app-builder, allows you to create and manage queries to interact with connected **data sources**. It provides the capability to perform API requests, query **[databases](../data-sources/overview)**, and apply **[transformations](../tutorial/transformations)** or data manipulation using **[JavaScript](../data-sources/run-js)** and **[Python](../data-sources/run-py)**.
|
||||
The Query Panel, located at the bottom of the app-builder, allows you to create and manage queries to interact with connected **data sources**. It provides the capability to perform API requests, query **[databases](/docs/data-sources/overview)**, and apply **[transformations](/docs/tutorial/transformations)** or data manipulation using **[JavaScript](/docs/data-sources/run-js)** and **[Python](/docs/data-sources/run-py)**.
|
||||
|
||||
The Query Panel consists of two sections:
|
||||
- The **[Query Manager](#query-manager)** on the left side, which displays a list of all the created queries.
|
||||
|
|
@ -72,7 +72,7 @@ For each parameter, you need to specify:
|
|||
|
||||
**Syntax for utilizing the parameter:** Employ `parameters.<identifier>` in your query. It's important to note that parameters can only be utilized within the specific query where they are defined.
|
||||
|
||||
Learn more about **[Using Custom Parameters](../how-to/use-custom-parameters)**.
|
||||
Learn more about **[Using Custom Parameters](/docs/how-to/use-custom-parameters)**.
|
||||
|
||||
<img className="screenshot-full" src="/img/v2-beta/app-builder/querypanel/newui3/queryparams-v2.png" alt="Custom Parameters" style={{marginBottom:'15px'}}/>
|
||||
|
||||
|
|
@ -111,7 +111,7 @@ In cases where multiple data sources of the same type are connected, easily swit
|
|||
|
||||
### Transformation
|
||||
|
||||
Queries can be enhanced with transformations to modify the query results. ToolJet supports transformations using two programming languages: JavaScript & Python. Refer to the detailed documentation on **[Transformations](../tutorial/transformations)** for more information.
|
||||
Queries can be enhanced with transformations to modify the query results. ToolJet supports transformations using two programming languages: JavaScript & Python. Refer to the detailed documentation on **[Transformations](/docs/tutorial/transformations)** for more information.
|
||||
|
||||
<img className="screenshot-full" src="/img/v2-beta/app-builder/querypanel/newui2/transform-v2.png" alt="Query Editor" style={{marginBottom:'15px'}}/>
|
||||
|
||||
|
|
@ -144,7 +144,7 @@ The Result:
|
|||
- The component displaying the to-do data will be update with the lates data.
|
||||
|
||||
:::info
|
||||
Learn more about [Event Handlers and Actions](../widgets/overview#component-event-handlers).
|
||||
Learn more about [Event Handlers and Actions](/docs/widgets/overview#component-event-handlers).
|
||||
:::
|
||||
|
||||
<img className="screenshot-full" src="/img/v2-beta/app-builder/querypanel/newui2/events-v2.png" alt="Query Editor" />
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ The Developer Details icon will show a profile picture of the currently active d
|
|||
You can use the Env dropdown menu to select an environment for your app: Development, Staging, or Production. This feature facilitates seamless transition through the app development cycle.
|
||||
|
||||
:::tip
|
||||
Learn more about multi-environment configuration **[here](/docs/release-management/multi-environment/)**.
|
||||
Learn more about multi-environment configuration **[here](/docs/development-lifecycle/environment/self-hosted/multi-environment)**.
|
||||
:::
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
|
@ -64,7 +64,7 @@ Learn more about multi-environment configuration **[here](/docs/release-manageme
|
|||
You can manage application versions through the Version Manager. You can use this dropdown to edit a version name or adding/removing versions.
|
||||
|
||||
:::tip
|
||||
Versioning is also helpful when working with **[multiple environments](/docs/release-management/multi-environment/)** like development, staging and production.
|
||||
Versioning is also helpful when working with **[multiple environments](/docs/development-lifecycle/environment/self-hosted/multi-environment)** like development, staging and production.
|
||||
:::
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
|
|
|||
|
|
@ -80,7 +80,7 @@ You can insert values from the components in queries. For instance, the above co
|
|||
|
||||
```sql
|
||||
INSERT INTO feature_requests (id, title, description, votes, priority)
|
||||
VALUES (10, `{{components.textinput1.value}}`, `{{components.textinput2.value}}`, 0, 2);
|
||||
VALUES (10, '{{components.textinput1.value}}', '{{components.textinput2.value}}', 0, 2);
|
||||
```
|
||||
|
||||
You can apply the same principles to upcoming examples.
|
||||
|
|
@ -98,7 +98,7 @@ SET
|
|||
description = 'Updated Feature Description',
|
||||
votes = 15,
|
||||
priority = 2
|
||||
WHERE id = `{{components.table1.selectedRow.id}}`;
|
||||
WHERE id = '{{components.table1.selectedRow.id}}';
|
||||
```
|
||||
|
||||
<img className="screenshot-full" src="/img/v2-beta/app-builder/walkthrough/create-queries/update-data-v2.png" alt="Update Data" style={{marginBottom:'15px'}}/>
|
||||
|
|
|
|||
|
|
@ -1,60 +0,0 @@
|
|||
---
|
||||
id: sharing-apps
|
||||
title: Preview, Test and Share Apps
|
||||
---
|
||||
|
||||
ToolJet's App-Builder provides critical tools for app preview, development and deployment. Let's take a look at how you can use it throughout the development process.
|
||||
|
||||
## Preview
|
||||
You can use Preview to ensure the app functions correctly on both mobile and desktop platforms.
|
||||
|
||||
- Open the ToolJet App-Builder and navigate to your app.
|
||||
- Click the `Preview` icon located at the top-right corner to enter preview mode.
|
||||
- Use the **Mobile** and **Desktop** view options to toggle between different screen settings.
|
||||
- Observe component behavior and layout differences across devices.
|
||||
- Adjust component visibility using the `Show on mobile` and `Show on desktop` options under the component's Properties Panel.
|
||||
|
||||
## Multi-Environment Testing
|
||||
Simulate app behavior in various stages of the development lifecycle (Development, Staging, Production).
|
||||
|
||||
**Steps**:
|
||||
1. Select the desired environment from the Env dropdown menu in the top-bar.
|
||||
2. Make necessary changes and use the Version Manager to handle different versions.
|
||||
3. Preview the app to ensure it behaves as expected in the chosen environment.
|
||||
|
||||
## Share
|
||||
|
||||
### Releasing App
|
||||
To release an app to the users, you need to promote it to `Production` environment. Once you are in `Production`, the `Promote` button will have the `Release` label. Once you click on `Release` and confirm, the application will be released.
|
||||
|
||||
### Making App Public
|
||||
You can share the application with external users via a user-friendly, accessible URL.
|
||||
|
||||
- Click the `Share` button on the top-bar.
|
||||
- In the Share modal, toggle on `Make application public` to allow access without a ToolJet login.
|
||||
- Edit the default URL slug to a more memorable and relevant one for easier access.
|
||||
- Copy the newly customized URL and distribute it to your intended audience.
|
||||
|
||||
This provides external users easy and direct access to the application, enhancing reach and usability.
|
||||
|
||||
<!-- ## Embedding the App into a Website
|
||||
|
||||
**Objective**: Integrate the ToolJet app within an existing web application to provide seamless user interaction.
|
||||
|
||||
**Steps**:
|
||||
1. Ensure the app is set to public or set `ENABLE_PRIVATE_APP_EMBED` to `true` in the `.env` file for private apps.
|
||||
2. Navigate to the Share modal and copy the embeddable link.
|
||||
3. Paste the embed link into the `iframe` tag of your website's HTML code.
|
||||
|
||||
**Benefit**: Users can interact with the ToolJet app directly from your website, improving the user experience and retaining user engagement. -->
|
||||
|
||||
|
||||
### Efficient Development with Gitsync
|
||||
|
||||
Gitsync can be used to maintain application version control and facilitate collaborative development.
|
||||
|
||||
- Click on the `Gitsync` icon in the top-bar.
|
||||
- Follow the prompts to connect your ToolJet app with a GitHub repository.
|
||||
- Utilize git operations to manage app development across different branches and versions.
|
||||
|
||||
Read more about Gitsync **[here](/docs/gitsync)**.
|
||||
56
docs/docs/build-with-ai/ai-docs-assitant.md
Normal file
56
docs/docs/build-with-ai/ai-docs-assitant.md
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
---
|
||||
id: ai-docs-assistant
|
||||
title: AI Docs Assistant
|
||||
---
|
||||
|
||||
The **AI Docs Assistant** is an intelligent assistant designed to help you navigate ToolJet’s documentation with ease. Whether you need quick answers, step-by-step guides, or concept explanations, this assistant provides instant support by summarizing docs, troubleshooting issues, and guiding you through best practices.
|
||||
|
||||
You can access the AI Docs Assistant under the **Learn** tab in the Build with AI sidebar. Simply ask a question or describe what you're looking for, and the assistant will provide relevant documentation and insights.
|
||||
|
||||
<div style={{textAlign: 'center', marginBottom:'15px'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/tooljet-ai/doc0.png" alt="tooljet ai doc assistant" />
|
||||
|
||||
</div>
|
||||
|
||||
### What You Can Do with the AI Docs Assistant
|
||||
- Get guidance on setting up workspaces, managing users, and configuring roles.
|
||||
- Quickly understand complex topics with clear, actionable steps
|
||||
- Find answers to common questions and resolve issues efficiently.
|
||||
- Explore how to connect databases, APIs, and external tools.
|
||||
- Discover best practices for securing your applications.
|
||||
- Get up to speed with key functionalities and platform best practices.
|
||||
|
||||
### Examples
|
||||
|
||||
1. Custom Schema in [Form](/docs/widgets/form/) component:
|
||||
|
||||
**Prompt**: Can you create a custom schema for a Form component with two input fields for name, phone number, and a dropdown for gender?
|
||||
|
||||
<div style={{textAlign: 'center', marginBottom:'15px'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/tooljet-ai/doc1.png" alt="tooljet ai doc assistant" />
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
2. Dynamic columns in [Table](/docs/widgets/table/table-properties/) component:
|
||||
|
||||
**Prompt**: Can you explain dynamic columns in the Table component?
|
||||
|
||||
<div style={{textAlign: 'center', marginBottom:'15px'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/tooljet-ai/doc2.png" alt="tooljet ai doc assistant" />
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
3. Plotly JSON in [Chart](/docs/widgets/chart/) component:
|
||||
|
||||
**Prompt**: Can you help me with the structure of the Plotly JSON that I can pass into Chart components?
|
||||
|
||||
<div style={{textAlign: 'center', marginBottom:'15px'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/tooljet-ai/doc3.png" alt="tooljet ai doc assistant" />
|
||||
|
||||
</div>
|
||||
55
docs/docs/build-with-ai/generate-applications.md
Normal file
55
docs/docs/build-with-ai/generate-applications.md
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
---
|
||||
id: generate-applications
|
||||
title: Generate Applications
|
||||
---
|
||||
|
||||
This guide explains how to quickly generate and modify business applications using ToolJet. You can create an app from scratch with a single prompt or enhance an existing app with AI-powered assistance.
|
||||
|
||||
## Creating Application
|
||||
To create an application, follow these steps:
|
||||
|
||||
1. **Enter a prompt** – Describe the business application you want to build in the prompt input on the dashboard.
|
||||
<div style={{textAlign: 'center', marginBottom:'15px'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/tooljet-ai/generate01.png" alt="tooljet generate apps " />
|
||||
|
||||
</div>
|
||||
|
||||
2. **Accept or modify requirements** – After submitting your prompt, the app will be created, and you’ll be taken to the App Builder, where a list of features, a database schema, design details, and query specifications will be generated based on your prompt.
|
||||
<div style={{textAlign: 'center', marginBottom:'15px'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/tooljet-ai/generate02.png" alt="tooljet generate apps " />
|
||||
|
||||
</div>
|
||||
|
||||
You can accept or modify these application requirements after reviewing them thoroughly.
|
||||
<div style={{textAlign: 'center', marginBottom:'15px'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/tooljet-ai/generate03.png" alt="tooljet generate apps " />
|
||||
|
||||
</div>
|
||||
|
||||
3. **App Generation** – Once you confirm the requirements, ToolJet will build the application inside the App Builder.
|
||||
|
||||
<div style={{textAlign: 'center', marginBottom:'15px'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/tooljet-ai/generate04.png" alt="tooljet generate apps " />
|
||||
|
||||
</div>
|
||||
|
||||
## Modifying Application
|
||||
|
||||
You can modify any application in ToolJet with AI assistance, whether it's a newly created app or an existing one. You can update components and queries within your application with just a prompt.
|
||||
|
||||
For example, if you want to add a button in your app you can write a prompt for the same.
|
||||
<div style={{textAlign: 'center', marginBottom:'15px'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/tooljet-ai/generate05.png" alt="tooljet generate apps " />
|
||||
|
||||
</div>
|
||||
## Limitations
|
||||
ToolJet supports generating queries with AI for the following data sources:
|
||||
- [Postgres](/docs/data-sources/postgresql/)
|
||||
- [MySQL](/docs/data-sources/mysql/)
|
||||
- [SQL Server](/docs/data-sources/mssql/)
|
||||
- [RunJS Queries](/docs/tooljet-concepts/run-js/)
|
||||
40
docs/docs/build-with-ai/overview.md
Normal file
40
docs/docs/build-with-ai/overview.md
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
---
|
||||
id: overview
|
||||
title: Overview
|
||||
---
|
||||
With ToolJet, you can build business applications effortlessly using natural language. Whether you're starting from scratch or refining an existing app, it simplifies the process with it's intelligence.
|
||||
|
||||
Additionally, it comes with an AI-powered [documentation assistant](/docs/build-with-ai/ai-docs-assistant), ready to answer any questions about ToolJet's features, components, and integrations, helping you build faster.
|
||||
|
||||
Follow these step-by-step instructions to create an inventory management application:
|
||||
1. **Describe your application** – Provide a prompt detailing the business application you want to create. (Example: "Inventory management system for a manufacturing company.")
|
||||
<div style={{textAlign: 'center', marginBottom:'15px'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/tooljet-ai/overview-ai-1.png" alt="tooljet ai overview" />
|
||||
|
||||
</div>
|
||||
2. **Refine the requirements** – Review and accept or modify the application requirements suggested.
|
||||
<div style={{textAlign: 'center', marginBottom:'15px'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/tooljet-ai/overview-ai-2.png" alt="tooljet ai overview" />
|
||||
|
||||
</div>
|
||||
3. **Customize your application** – Use AI to customize the generated application to your specific needs, adjusting components and styles, and also data source queries.
|
||||
|
||||
- **Generated Application**
|
||||
<div style={{textAlign: 'center', marginBottom:'15px'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/tooljet-ai/overview-ai-3.png" alt="tooljet ai overview" />
|
||||
|
||||
</div>
|
||||
|
||||
- **Customizing Application**
|
||||
|
||||
<div style={{textAlign: 'center', marginBottom:'15px'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/tooljet-ai/overview-ai-4.png" alt="tooljet ai overview" />
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
Refer to [Generate Applications](/docs/build-with-ai/generate-applications) and [AI Docs Assistant](/docs/build-with-ai/ai-docs-assistant) documentation to learn more.
|
||||
|
|
@ -35,6 +35,6 @@ The quality of our documentation isn't just determined by how well it's written
|
|||
|
||||
## Next Steps...
|
||||
|
||||
Once you've set up your local environment, take some time to explore our [Style Guide](style-guide.md), understand our page structures, and learn how to work with Docusaurus, the framework we use for our documentation.
|
||||
Once you've set up your local environment, take some time to explore our [Style Guide](/docs/contributing-guide/documentation-guidelines/style-guide), understand our page structures, and learn how to work with Docusaurus, the framework we use for our documentation.
|
||||
|
||||
We look forward to your contributions and are excited to see how you'll help make ToolJet documentation even better!
|
||||
|
|
|
|||
|
|
@ -215,7 +215,7 @@ ORDER BY name ASC;
|
|||
`[Postgres tables](/schema/postgres/tables.mdx)` links to the Postgres tables page.
|
||||
|
||||
- When linking to a specific section within a page, use anchor links to direct the user precisely where needed. **Example**: <br/>
|
||||
`ToolJet supports [multiple environments,](https://docs.tooljet.com/docs/#multiple-environments)` takes the user directly to the specific section.
|
||||
`ToolJet supports [multiple environments,](https://docs.tooljet.ai/docs/#multiple-environments)` takes the user directly to the specific section.
|
||||
|
||||
|
||||
---
|
||||
|
|
|
|||
|
|
@ -3,8 +3,6 @@ id: creating-a-plugin
|
|||
title: 'Marketplace: Creating plugins'
|
||||
---
|
||||
|
||||
# Marketplace: Creating plugins
|
||||
|
||||
## What are plugins
|
||||
|
||||
ToolJet’s development has centered on extensibility, allowing developers to utilize plugins that expand their capabilities. Currently, these plugins are limited to connectors, including data source connectors like PostgreSQL, MySQL, Twilio, Stripe, and more. Using JavaScript/TypeScript, developers can develop plugins to enhance ToolJet's functionality and publish these plugins on the ToolJet Marketplace.
|
||||
|
|
@ -376,6 +374,42 @@ The GitHub class has three methods:
|
|||
|
||||
- **getConnection**: This method is a helper function that returns an authenticated octokit client, which is utilized to send requests to the GitHub API. It takes in sourceOptions as input, representing the source metadata, and returns an authenticated octokit client.
|
||||
|
||||
## Step 6: Add Error Handling
|
||||
|
||||
In case of an error, it is necessary to return the error message received from the Plugin SDK. To achieve this, include the `errorDetails` in the **run** method within the **index.ts** file. The specific parameters of the error may vary depending on the plugin. <br/><br/>
|
||||
Additionally, the **data** field in the Plugin SDK corresponds to **errorDetails** in the code, and the dynamically generated **errorMessage** maps to the **description** field in the error preview.
|
||||
|
||||
#### Example
|
||||
|
||||
Consider the case of MongoDB. If an error occurs, such as the following:
|
||||
|
||||
<img className="screenshot-full" src="/img/contributing-guide/create-plugin/mongodb-error.png" alt="MongoDB Error" />
|
||||
|
||||
You can implement error handling using the following code:
|
||||
|
||||
```js
|
||||
catch (error) {
|
||||
let errorMessage = 'An unknown error occurred';
|
||||
let errorDetails = {};
|
||||
|
||||
if (error instanceof Error) {
|
||||
errorMessage = error.message || errorMessage;
|
||||
errorDetails = {
|
||||
name: error.name,
|
||||
code: (error as any).code || null,
|
||||
codeName: (error as any).codeName || null,
|
||||
keyPattern: (error as any).keyPattern || null,
|
||||
keyValue: (error as any).keyValue || null,
|
||||
};
|
||||
}
|
||||
|
||||
throw new QueryError('Query could not be completed', errorMessage, errorDetails);
|
||||
}
|
||||
```
|
||||
|
||||
This code ensures that error messages and details are properly returned to the Plugin SDK, enabling meaningful error previews for the user.
|
||||
|
||||
<img className="screenshot-full" src="/img/contributing-guide/create-plugin/query-error.png" alt="Query Error" />
|
||||
|
||||
## Delete a plugin
|
||||
To delete a plugin, enter the following command:
|
||||
|
|
|
|||
|
|
@ -9,9 +9,9 @@ The Marketplace offers custom plugins that can be installed in your ToolJet inst
|
|||
- [Node.js](https://nodejs.org/en/download/) **(v18.18.2)**
|
||||
- [npm](https://www.npmjs.com/get-npm) **(v9.8.1)**
|
||||
|
||||
## Getting started
|
||||
## Getting Started
|
||||
|
||||
### Step 1. Setup ToolJet locally
|
||||
### Step 1. Setup ToolJet Locally
|
||||
|
||||
To obtain the ToolJet repository via git, use the command:
|
||||
|
||||
|
|
@ -25,11 +25,11 @@ Next, refer to the appropriate guide for your development environment to follow
|
|||
- **[Docker](/docs/contributing-guide/setup/docker)**
|
||||
- **[Ubuntu](/docs/contributing-guide/setup/ubuntu)**
|
||||
|
||||
### Step 2. Enabling the marketplace for your instance
|
||||
### Step 2. Enabling the Marketplace for your Instance
|
||||
|
||||
To enable the marketplace for your ToolJet instance, you need to specify the following environment variables in your **`.env`** file:
|
||||
|
||||
#### Marketplace feature enable
|
||||
#### Marketplace Feature Enable
|
||||
|
||||
Use this environment variable to enable/disable the feature that allows users to use the marketplace.
|
||||
|
||||
|
|
@ -37,7 +37,7 @@ Use this environment variable to enable/disable the feature that allows users to
|
|||
| -------------------------- | ----------------- |
|
||||
| ENABLE_MARKETPLACE_FEATURE | `true` or `false` |
|
||||
|
||||
#### Enable Marketplace plugin developement mode
|
||||
#### Enable Marketplace Plugin Developement Mode
|
||||
|
||||
The use of this environment variable facilitates plugin development by enabling automatic builds whenever package changes occur, thus simplifying the development process. Moreover, it also incorporates a reload button that retrieves all the recent local modifications from the file system for installed plugins, making it a valuable feature for improving the overall development experience.
|
||||
|
||||
|
|
@ -50,7 +50,22 @@ Please note that the marketplace is not enabled by default. After updating the v
|
|||
|
||||
For information on running ToolJet on your local machine, please refer to the instructions provided **[here](/docs/contributing-guide/setup/architecture)**. You can access the marketplace by navigating to the **'/integrations'** route.
|
||||
|
||||
### Step 3: Installation of tooljet-cli
|
||||
### Step 3: Install the Required Packages
|
||||
|
||||
The required packages must be installed from the marketplace root folder. Use the following commands to install the packages:
|
||||
|
||||
``` bash
|
||||
cd marketplace
|
||||
npm install
|
||||
```
|
||||
|
||||
After the packages are installed, run the following command to build the directory:
|
||||
|
||||
``` bash
|
||||
npm run build
|
||||
```
|
||||
|
||||
### Step 4: Installation of tooljet-cli
|
||||
|
||||
In order to manage plugins for the ToolJet marketplace, including creating, updating, and deleting, you will need to utilize **[tooljet-cli](https://www.npmjs.com/package/@tooljet/cli)**. This can be installed via npm by entering the following command:
|
||||
```bash
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ ToolJet server is a Node.js API application. Server is responsible for authentic
|
|||
**Dependencies:**
|
||||
- **PostgreSQL** - ToolJet server persists data to a postgres database.
|
||||
- **Email service** (SMTP/Sendgrid/Mailgun/etc) - Required to send user invitations and password reset emails.
|
||||
- **PostgREST (Optional)** - Standalone web server that converts PostgreSQL database into queryable RESTful APIs for ToolJet Database.
|
||||
- **PostgREST** - Standalone web server that converts PostgreSQL database into queryable RESTful APIs for ToolJet Database.
|
||||
|
||||
### 2. ToolJet Client
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ id: codespaces
|
|||
title: GitHub Codespaces
|
||||
---
|
||||
|
||||
Follow the steps below to set up ToolJet on GitHub Codespaces. We recommend reading our guide on [architecture](https://docs.tooljet.com/docs/contributing-guide/setup/architecture) of ToolJet before proceeding.
|
||||
Follow the steps below to set up ToolJet on GitHub Codespaces. We recommend reading our guide on [architecture](https://docs.tooljet.ai/docs/contributing-guide/setup/architecture) of ToolJet before proceeding.
|
||||
|
||||
Open the terminal and run the commands below.
|
||||
|
||||
|
|
@ -51,7 +51,7 @@ sudo -u postgres psql
|
|||
|
||||
### 2. Set up environment variables
|
||||
|
||||
Create a `.env` file by running the command `touch .env`. More information on the variables that can be set is given in the [environment variables reference](https://docs.tooljet.com/docs/setup/env-vars)
|
||||
Create a `.env` file by running the command `touch .env`. More information on the variables that can be set is given in the [environment variables reference](https://docs.tooljet.ai/docs/setup/env-vars)
|
||||
|
||||
**For basic set-up you add the below env variables:**
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ The following guide is intended for contributors to set up ToolJet locally. If y
|
|||
|
||||
Docker Compose is the easiest way to set up the ToolJet server and client locally.
|
||||
|
||||
*If you just want to try out ToolJet locally with docker, you can follow the steps [here](https://docs.tooljet.com/docs/setup/try-tooljet).*
|
||||
*If you just want to try out ToolJet locally with docker, you can follow the steps [here](/docs/setup/try-tooljet).*
|
||||
|
||||
## Prerequisites
|
||||
|
||||
|
|
|
|||
|
|
@ -36,11 +36,11 @@ To set up and run ToolJet on macOS for development, begin by opening your termin
|
|||
brew install postgresql@13
|
||||
```
|
||||
|
||||
1.4 Install PostgREST(optional)
|
||||
1.4 Install PostgREST
|
||||
|
||||
:::info
|
||||
Required only if ToolJet Database is being used.
|
||||
:::
|
||||
:::info
|
||||
Please use PostgREST version 12.2.0
|
||||
:::
|
||||
|
||||
```bash
|
||||
brew install postgrest
|
||||
|
|
@ -85,6 +85,10 @@ To set up and run ToolJet on macOS for development, begin by opening your termin
|
|||
PG_USER=postgres
|
||||
PG_PASS=postgres
|
||||
PG_DB=tooljet_development
|
||||
TOOLJET_DB=tooljet_db
|
||||
TOOLJET_DB_USER=postgres
|
||||
TOOLJET_DB_HOST=localhost
|
||||
TOOLJET_DB_PASS=postgres
|
||||
ORM_LOGGING=all
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -19,6 +19,6 @@ For Docker setups on Mac systems, it's advisable to use a machine with 16GB RAM
|
|||
|
||||
## Bare-Metal Setup
|
||||
|
||||
For those who prefer a [bare-metal](https://docs.tooljet.com/docs/contributing-guide/setup/docker) setup over Docker, a minimum of 8GB RAM is recommended for smooth operation.
|
||||
For those who prefer a [bare-metal](/docs/contributing-guide/setup/docker) setup over Docker, a minimum of 8GB RAM is recommended for smooth operation.
|
||||
|
||||
Before initiating the installation process, please verify that your system meets these specified requirements. It's essential to customize server specifications based on the unique demands of your deployment scenario.
|
||||
|
|
@ -39,12 +39,10 @@ Follow these steps to setup and run ToolJet on Ubuntu. Open terminal and run the
|
|||
sudo apt-get install libpq-dev
|
||||
```
|
||||
|
||||
1.3 Install PostgREST (optional)
|
||||
1.3 Install PostgREST
|
||||
|
||||
:::info
|
||||
Required only if ToolJet Database is being used.
|
||||
|
||||
Please use PostgREST version 10.1.1.x
|
||||
:::info
|
||||
Please use PostgREST version 12.2.0
|
||||
:::
|
||||
|
||||
Please follow the installation [PostgREST](https://postgrest.org/en/stable/install.html) guide
|
||||
|
|
@ -83,6 +81,17 @@ Follow these steps to setup and run ToolJet on Ubuntu. Open terminal and run the
|
|||
TOOLJET_HOST=http://localhost:8082
|
||||
LOCKBOX_MASTER_KEY=1d291a926ddfd221205a23adb4cc1db66cb9fcaf28d97c8c1950e3538e3b9281
|
||||
SECRET_KEY_BASE=4229d5774cfe7f60e75d6b3bf3a1dbb054a696b6d21b6d5de7b73291899797a222265e12c0a8e8d844f83ebacdf9a67ec42584edf1c2b23e1e7813f8a3339041
|
||||
NODE_ENV=development
|
||||
# DATABASE CONFIG
|
||||
PG_HOST=localhost
|
||||
PG_PORT=5432
|
||||
PG_USER=postgres
|
||||
PG_PASS=postgres
|
||||
PG_DB=tooljet_development
|
||||
TOOLJET_DB=tooljet_db
|
||||
TOOLJET_DB_USER=postgres
|
||||
TOOLJET_DB_HOST=localhost
|
||||
TOOLJET_DB_PASS=postgres
|
||||
```
|
||||
|
||||
5. Install and build dependencies
|
||||
|
|
|
|||
|
|
@ -13,45 +13,50 @@ Follow the steps below to setup and run the test specifications using Cypress. W
|
|||
```
|
||||
|
||||
## Running Tests
|
||||
|
||||
#### Headed mode
|
||||
|
||||
- To run cypress in **headed** mode, run the following command:
|
||||
```bash
|
||||
npm run cy:open
|
||||
```
|
||||
- In **headed** mode, the user will be able to choose the test specs from the test runner:
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
|
||||
<img className="screenshot-full" src="/img/testing/headed.png" alt="Cypress headed mode" />
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
#### Headless mode
|
||||
|
||||
- To run cypress in **headless** mode, run the following command:
|
||||
```bash
|
||||
npm run cy:run
|
||||
```
|
||||
|
||||
- For running specific spec in headless mode, run for specific spec
|
||||
```bash
|
||||
npm run cy:run
|
||||
```
|
||||
|
||||
- To run a specific spec in headless mode, run the following command:
|
||||
|
||||
```bash
|
||||
npm run cy:run -- --spec "cypress/e2e/dashboard/multi-workspace/manageSSO.cy.js
|
||||
```
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
|
||||
<img className="screenshot-full" src="/img/testing/headless.png" alt="Cypress headless mode" />
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
:::caution
|
||||
If some test specs need the environment variables, the user can pass them similar to the following command:
|
||||
|
||||
```bash
|
||||
npm run cy:open -- --env='{"pg_host":"localhost","pg_user":"postgres", "pg_password":"postgres"}'
|
||||
```
|
||||
|
||||
or the user can add env-vars in the **cypress.config.js** file
|
||||
:::
|
||||
|
||||
|
||||
:::info
|
||||
Check all the Cypress commands [here](https://docs.cypress.io/guides/guides/command-line#Commands)
|
||||
:::
|
||||
:::
|
||||
|
|
|
|||
|
|
@ -1,352 +0,0 @@
|
|||
---
|
||||
id: dashboard
|
||||
title: Dashboard
|
||||
---
|
||||
|
||||
The ToolJet Dashboard is the initial landing page that you see upon logging into your workspace. This interface serves as a central hub where you can access a variety of features. Primarily, it displays all the applications you've created within ToolJet. Moreover, you have the capability to create new workspaces and applications directly from this dashboard. Additionally, it provides an option to create folders for categorizing and managing applications for easier organization, access control, and workflow management.
|
||||
|
||||
Furthermore, the dashboard serves as a gateway to various essential sections, such as **[Workflows](/docs/workflows/overview)**, **[ToolJet Database](/docs/tooljet-db/tooljet-database/)**, **[Data Sources](/docs/data-sources/overview)**, **[Marketplace](/docs/marketplace/marketplace-overview)**, **[Workspace Settings](/docs/tutorial/manage-users-groups)**, **[Settings](/docs/enterprise/superadmin/#settings)**, and **[Audit logs](/docs/enterprise/audit_logs/)**. You can effortlessly navigate to these sections directly from the dashboard.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/dashboard/dashboardoptions-v2.png" alt="App menu options"/>
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## Workspace Manager
|
||||
|
||||
The workspace manager is located on the bottom left corner of the dashboard. Clicking on the workspace manager will open a dropdown menu listing all the workspaces you belong to. You can switch between workspaces by clicking on the workspace name from the dropdown menu.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/dashboard/workspacemenu-v2.png" alt="Dashboard"/>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
### Add New Workspace
|
||||
|
||||
On clicking the `Add new workspace` button, a modal will open where you can enter the name of the workspace, enter the unique workspace slug, and can see the preview of the workspace URL. Click on the `+ Create Workspace` button to create a new workspace.
|
||||
|
||||
Previously, the workspace slug was an automatically generated workspace ID, like this: `https://tooljet.com/262750db-b2b8-4abb-9404-8995c2ecb2a0`. Now, you can set a custom, unique slug for your workspace which will generate a more accessible or readable URL such as `https://tooljet.com/apac-team)`.
|
||||
|
||||
#### Conditions for workspace slug
|
||||
|
||||
- The workspace slug should be unique.
|
||||
- The workspace slug should not contain any special characters except `-`.
|
||||
- The workspace slug should not contain any spaces.
|
||||
- The workspace slug should not contain any capital letters.
|
||||
- The workspace slug should not be empty.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/dashboard/new-workspace-modal-v2.png" alt="Dashboard"/>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
### Edit Workspace
|
||||
|
||||
Similar to the `Add new workspace` button, clicking on the `Edit workspace` button will open a modal where you can edit the name of the workspace and the workspace slug. Click on the `Save` button to update the changes.
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## Create a New App
|
||||
|
||||
To create a new app, click on the `Create new app` button on the top left corner of the dashboard. Clicking on this button will open a modal where you can enter the name of the app and then click on the `+ Create app` button to create a new app.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/dashboard/new-app-modal-v2.png" alt="Dashboard"/>
|
||||
|
||||
</div>
|
||||
<br/>
|
||||
|
||||
There are three dots on the right side of the `Create new app` button. Clicking on these dots will open a dropdown menu with two options:
|
||||
|
||||
- **[Choose from templates](#choose-from-templates)**
|
||||
- **[Import](#import)**
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
### Choose from Templates
|
||||
|
||||
This option will open a modal with a list of pre-built templates. You can choose any template from this list to create a new app.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/dashboard/choosefromtemplate-v2.gif" alt="Dashboard"/>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
### Import
|
||||
|
||||
This option will open a file picker to import a JSON file. This JSON file should contain the app data exported from ToolJet.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/dashboard/import-app-v2.gif" alt="Dashboard"/>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
### Importing an App Connected to Marketplace Plugins
|
||||
|
||||
When importing an app with Marketplace plugins, the Marketplace plugin should be installed in the ToolJet workspace where the app is being imported. If the Marketplace plugin is not installed, the app will be imported without the queries for that plugin.
|
||||
|
||||
#### When Marketplace plugin is installed
|
||||
|
||||
If Marketplace plugin is installed in the ToolJet workspace where the app is being imported, the queries connected to the Marketplace plugin will be available in the imported application. The queries will be linked to the data source with the same name if it is already present. If the data source is not present, a new data source will be created of that Marketplace plugin and linked to the queries.
|
||||
|
||||
#### When Marketplace plugin is not installed
|
||||
|
||||
If you have an app with a query linked to a Marketplace plugin, and you import that app in a ToolJet workspace where the Marketplace plugin is not installed as the data source, the queries will be not be available in the imported application.
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
### Importing App Connected to ToolJet Table
|
||||
|
||||
When the app(JSON file) that includes the table schema is imported, and the table is not present in the ToolJet database of the workspace where the app is being imported, a new table will be created in the ToolJet database with the same name as the table in the imported app.
|
||||
|
||||
If the table with the same name is already present in the workspace, the new table will be created with the name `<table name>_<unix timestamp>`. Example: `<tablename>_1627980000`.
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## Folders
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
### Create a new folder
|
||||
|
||||
Folders can be created to organize your apps. To create a new folder, click on the `+` button on the left drawer of the dashboard. Clicking on this button will open a modal, enter the name of the folder and click on the `Create Folder` button to create a new folder.
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
### Delete or Edit Folder
|
||||
|
||||
A folder can be **deleted** or **renamed**. To delete or rename a folder, click on the kebab menu on the right side of the folder name. Clicking on kebab menu will open a dropdown menu with two options:
|
||||
|
||||
- **Edit folder**: This option will open a modal, enter the new name of the folder and click on the `Edit` button to rename the folder.
|
||||
- **Delete folder**: This option will open a confirmation modal to delete the folder. Click on the `Delete` button to delete the folder.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/dashboard/newfolder-v2.gif" alt="Dashboard"/>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
### Search Folders
|
||||
|
||||
Folders can be searched by clicking on the search icon on the left drawer of the dashboard. Clicking on the search icon will open a search bar, enter the name of the folder to search.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/dashboard/search-v2.png" alt="Dashboard"/>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
### Slug for Folders
|
||||
|
||||
The folder's URL slug is generated automatically from its name, providing direct access to the folder using the slug.
|
||||
|
||||
To get the URL of a specific folder, the user will have to select that folder and then copy the URL from the address bar of the browser. The copied URL can be used to share with other users of the workspace.
|
||||
|
||||
Example: If the name of the folder is `Customer Support`, The folder can be accessed directly from the URL `https://tooljet.com/<workspace-name>?folder=Customer%20Support`.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/dashboard/app-url-v2.png" alt="Dashboard"/>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## App Cards
|
||||
|
||||
The dashboard displays all the apps created in the workspace as cards. These cards are displayed in a grid layout. The app cards display the **name of the app**, the **name of the creator**, and the **date of creation**. The app cards also display the app **icon**, which can be changed by clicking on the `Change Icon` option from the app menu.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/dashboard/appcard-v2.png" alt="Dashboard"/>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## App Menu
|
||||
|
||||
The app menu is located on the top right corner of the app card. Clicking on the app menu will open a dropdown menu containing various options. These options are:
|
||||
|
||||
- **[Rename app](#rename-app)**
|
||||
- **[Change Icon](#change-icon)**
|
||||
- **[Add to folder](#add-to-folder)**
|
||||
- **[Clone app](#clone-app)**
|
||||
- **[Export app](#export-app)**
|
||||
- **[Delete app](#delete-app)**
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/dashboard/app-menu-v2.gif" alt="Dashboard"/>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
### Rename App
|
||||
|
||||
This option will open a modal that will allow you to rename your app.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/dashboard/rename-app.png" alt="Dashboard"/>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
### Change Icon
|
||||
|
||||
This option will open a modal with a list of icons. You can choose any icon from this list to change the app icon.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/dashboard/change-icon-v2.png" alt="Dashboard"/>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
### Add to Folder
|
||||
|
||||
This option will open a modal with a list of folders. You can choose any folder from this list to add the app to the folder.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/dashboard/add-to-folder-v2.png" alt="Dashboard"/>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
### Clone App
|
||||
|
||||
Selecting this option will open a modal where you can enter the desired name for the cloned app. After providing the desired name, click on the Clone app button. This will immediately open the cloned app in the app builder with the same configuration as the original app.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/dashboard/clone-app-v2.gif" alt="Dashboard"/>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
### Export App
|
||||
|
||||
This option downloads a JSON file containing the application data. This JSON file can be [imported](#import) to ToolJet to create a new app. The exported app will include all the queries connected to global data sources including the data source created from Marketplace plugins.
|
||||
|
||||
This option allows you to select a specific version of the app to export or export all the versions of the app. To export a specific version of the app, select a version from the list of available versions in the modal and click on the `Export selected version` and to export all the versions of the app, click on the `Export All` button.
|
||||
|
||||
#### Export ToolJet table schema
|
||||
|
||||
Selecting this option will include the schema of the ToolJet table connected to that application in the exported JSON file. This option is available for all the apps on ToolJet however only the apps with a ToolJet table connected(includes tjdb query) will have the schema included in the exported JSON file.
|
||||
|
||||
This JSON file can be used to [import](#importing-app-connected-to-tooljet-table) the application to ToolJet along with the table schema that was connected to the application.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/dashboard/export-app-v2.png" alt="Dashboard"/>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
### Delete App
|
||||
|
||||
This option will open a confirmation modal to delete the app. Click on the `Delete` button to delete the app.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/dashboard/delete-app-v2.png" alt="Dashboard"/>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## App Search
|
||||
|
||||
Apps can be searched by clicking on the search bar on the center of the dashboard. Click on the search bar and enter the name of the app to search.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/dashboard/search-app-v2.png" alt="Dashboard"/>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## Current ToolJet Version
|
||||
|
||||
The current version of ToolJet is displayed on the top right corner of the dashboard.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/dashboard/current-version-v2.png" alt="Dashboard"/>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
|
@ -82,7 +82,7 @@ Timezone and User locale are mutually dependent. If you provide a timezone, you
|
|||
<img className="screenshot-full" src="/img/datasource-reference/airtable/list-records-v3.png" alt="Airtable List Records Query" />
|
||||
|
||||
|
||||
<details>
|
||||
<details id="tj-dropdown">
|
||||
<summary>**Example Values**</summary>
|
||||
|
||||
```json
|
||||
|
|
@ -102,7 +102,7 @@ Sort: createdTime // Select direction: Ascending or Descending
|
|||
</details>
|
||||
|
||||
|
||||
<details>
|
||||
<details id="tj-dropdown">
|
||||
<summary>**Response Example**</summary>
|
||||
|
||||
```json
|
||||
|
|
@ -152,7 +152,7 @@ This operation fetches a specific record from the specified table.
|
|||
|
||||
<img className="screenshot-full" src="/img/datasource-reference/airtable/retrieve-record-v2.png" alt="Airtable Retrieve Record Query" />
|
||||
|
||||
<details>
|
||||
<details id="tj-dropdown">
|
||||
<summary>**Response Example**</summary>
|
||||
```json
|
||||
{
|
||||
|
|
@ -188,7 +188,7 @@ This operation creates a new record in the specified table.
|
|||
}
|
||||
}]
|
||||
```
|
||||
<details>
|
||||
<details id="tj-dropdown">
|
||||
<summary>**Response Example**</summary>
|
||||
```json
|
||||
{
|
||||
|
|
@ -227,7 +227,7 @@ Update a specific record by providing new data.
|
|||
"Email": "katrina.petersions2@example.com"
|
||||
}
|
||||
```
|
||||
<details>
|
||||
<details id="tj-dropdown">
|
||||
<summary>**Response Example**</summary>
|
||||
```json
|
||||
{
|
||||
|
|
@ -258,7 +258,7 @@ This operation removes a record from the specified table.
|
|||
|
||||
<img className="screenshot-full" src="/img/datasource-reference/airtable/delete-record-v2.png" alt="Airtable Delete Record Query" />
|
||||
|
||||
<details>
|
||||
<details id="tj-dropdown">
|
||||
<summary>**Response Example**</summary>
|
||||
```json
|
||||
{
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ ToolJet can connect to appwrite database to read/write data.
|
|||
|
||||
## Connection
|
||||
|
||||
To establish a connection with the Appwrite data source, you can either click on the **+ Add new Data source** button located on the query panel or navigate to the **[Data Sources](https://docs.tooljet.com/docs/data-sources/overview)** page from the ToolJet dashboard.
|
||||
To establish a connection with the Appwrite data source, you can either click on the **+ Add new Data source** button located on the query panel or navigate to the **[Data Sources](/docs/data-sources/overview)** page from the ToolJet dashboard.
|
||||
|
||||
ToolJet requires the following to connect to your Appwrite:
|
||||
- **Host (API endpoint)**
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ ToolJet can connect to **Amazon Athena** which is an interactive query service t
|
|||
|
||||
## Connection
|
||||
|
||||
To establish a connection with the **Amazon Athena** data source, you can either click on the **+ Add new Data source** button located on the query panel or navigate to the **[Data Sources](https://docs.tooljet.com/docs/data-sources/overview)** page from the ToolJet dashboard and choose **Amazon Athena** as the data source.
|
||||
To establish a connection with the **Amazon Athena** data source, you can either click on the **+ Add new Data source** button located on the query panel or navigate to the **[Data Sources](/docs/data-sources/overview)** page from the ToolJet dashboard and choose **Amazon Athena** as the data source.
|
||||
|
||||
ToolJet requires the following to connect to your Athena.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
---
|
||||
id: azureblob
|
||||
id: azureblobstorage
|
||||
title: Azure Blob
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ This query lists all the fields in a table.
|
|||
|
||||
<img className="screenshot-full" src="/img/datasource-reference/baserow/baserow-list-fields-v2.png" alt="Baserow list fields" />
|
||||
|
||||
<details>
|
||||
<details id="tj-dropdown">
|
||||
<summary>**Response Example**</summary>
|
||||
|
||||
```yaml
|
||||
|
|
@ -114,7 +114,7 @@ This query lists all the rows in a table.
|
|||
|
||||
<img className="screenshot-full" src="/img/datasource-reference/baserow/baserow-list-rows-v2.png" alt="Baserow list"/>
|
||||
|
||||
<details>
|
||||
<details id="tj-dropdown">
|
||||
<summary>**Response Example**</summary>
|
||||
|
||||
```json
|
||||
|
|
@ -162,7 +162,7 @@ This query lists all the rows in a table.
|
|||
|
||||
<img className="screenshot-full" src="/img/datasource-reference/baserow/baserow-get-row-v2.png" alt="Baserow get" />
|
||||
|
||||
<details>
|
||||
<details id="tj-dropdown">
|
||||
<summary>**Response Example**</summary>
|
||||
|
||||
```json
|
||||
|
|
@ -197,7 +197,7 @@ This query lists all the rows in a table.
|
|||
}
|
||||
```
|
||||
|
||||
<details>
|
||||
<details id="tj-dropdown">
|
||||
<summary>**Response Example**</summary>
|
||||
|
||||
```json
|
||||
|
|
@ -234,7 +234,7 @@ This query lists all the rows in a table.
|
|||
}
|
||||
```
|
||||
|
||||
<details>
|
||||
<details id="tj-dropdown">
|
||||
<summary>**Response Example**</summary>
|
||||
|
||||
```json
|
||||
|
|
@ -263,7 +263,7 @@ This query lists all the rows in a table.
|
|||
|
||||
<img className="screenshot-full" src="/img/datasource-reference/baserow/baserow-move-row-v2.png" alt="Baserow move row" />
|
||||
|
||||
<details>
|
||||
<details id="tj-dropdown">
|
||||
<summary>**Response Example**</summary>
|
||||
|
||||
```json
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ This query lists all the records in a database.
|
|||
|
||||
<img className="screenshot-full" src="/img/datasource-reference/couchdb/listing-v2.png" alt="Couch listing"/>
|
||||
|
||||
<details>
|
||||
<details id="tj-dropdown">
|
||||
<summary>**Response Example**</summary>
|
||||
```json
|
||||
{
|
||||
|
|
@ -101,7 +101,7 @@ This operation fetches a single record by its record ID.
|
|||
|
||||
<img className="screenshot-full" src="/img/datasource-reference/couchdb/retrieving-v2.png" alt="Couch retrieve view" />
|
||||
|
||||
<details>
|
||||
<details id="tj-dropdown">
|
||||
<summary> **Response Example** </summary>
|
||||
```json
|
||||
{
|
||||
|
|
@ -131,7 +131,7 @@ Inserts a new record into the database.
|
|||
[{"name":"tooljet"}]
|
||||
```
|
||||
|
||||
<details>
|
||||
<details id="tj-dropdown">
|
||||
<summary>**Response Example**</summary>
|
||||
```json
|
||||
{
|
||||
|
|
@ -161,7 +161,7 @@ You get the document as JSON in the response. For each update to the document, t
|
|||
[{"name":"tooljet"}]
|
||||
```
|
||||
|
||||
<details>
|
||||
<details id="tj-dropdown">
|
||||
<summary>**Response Example**</summary>
|
||||
```json
|
||||
{
|
||||
|
|
@ -183,7 +183,7 @@ Removes a record from the database by its record ID.
|
|||
|
||||
<img className="screenshot-full" src="/img/datasource-reference/couchdb/deleteRecord.png" alt="Couch delete view"/>
|
||||
|
||||
<details>
|
||||
<details id="tj-dropdown">
|
||||
<summary>**Response Example**</summary>
|
||||
```json
|
||||
{
|
||||
|
|
@ -241,7 +241,7 @@ Views are the primary tool used for querying and reporting on CouchDB documents.
|
|||
|
||||
<img className="screenshot-full" src="/img/datasource-reference/couchdb/get_view-v2.png" alt="Couch get view" />
|
||||
|
||||
<details>
|
||||
<details id="tj-dropdown">
|
||||
<summary>**Response Example**</summary>
|
||||
```json
|
||||
{
|
||||
|
|
|
|||
|
|
@ -138,9 +138,9 @@ This ID will be longer than the one generated earlier, and it could look like "2
|
|||
<img className="screenshot-full" src="/img/datasource-reference/custom-javascript/unique-id-2.png" alt="Run JavaScript code" />
|
||||
|
||||
:::tip Resources
|
||||
- You can also write custom JavaScript code to get the data from **External APIs** and manipulate the response for graphical representation. Here's the [tutorial](https://blog.tooljet.com/build-github-stars-history-app-in-5-minutes-using-low-code/) on how we used custom JavaScript code to build an app using GitHub API.
|
||||
- You can also write custom JavaScript code to get the data from **External APIs** and manipulate the response for graphical representation. Here's the [tutorial](https://blog.tooljet.ai/build-github-stars-history-app-in-5-minutes-using-low-code/) on how we used custom JavaScript code to build an app using GitHub API.
|
||||
- [Import external libraries](/docs/how-to/import-external-libraries-using-runjs) using RunJS.
|
||||
- [Intentionally Fail](docs/how-to/intentionally-fail-js-query) a RunJS query.
|
||||
- [Intentionally Fail](/docs/how-to/intentionally-fail-js-query) a RunJS query.
|
||||
- [Trigger query at specified intervals](/docs/how-to/run-query-at-specified-intervals) using RunJS.
|
||||
:::
|
||||
|
||||
|
|
|
|||
|
|
@ -320,7 +320,7 @@ This operation provides a compact, column-aligned view of indices in a cluster.
|
|||
<img className="screenshot-full" src="/img/datasource-reference/elasticsearch/cat-indices.png" alt="Elastic cat indices" />
|
||||
</div>
|
||||
|
||||
<details>
|
||||
<details id="tj-dropdown">
|
||||
<summary>**Response Example**</summary>
|
||||
```json
|
||||
{
|
||||
|
|
@ -414,7 +414,7 @@ This operation retrieves the status of the cluster’s health. For more details,
|
|||
<img className="screenshot-full" src="/img/datasource-reference/elasticsearch/cluster-health.png" alt="Elastic cluster health" />
|
||||
</div>
|
||||
|
||||
<details>
|
||||
<details id="tj-dropdown">
|
||||
<summary>**Response Example**</summary>
|
||||
```json
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
---
|
||||
id: google.sheets
|
||||
id: googlesheets
|
||||
title: Google Sheets
|
||||
---
|
||||
|
||||
|
|
@ -52,15 +52,17 @@ When connecting to a Google Sheets datasource, you can choose between two permis
|
|||
|
||||
Using Google sheets data source you can perform several operations from your applications like:
|
||||
|
||||
1. **[Read data from a spreadsheet](#read-data-from-a-spreadsheet)**
|
||||
2. **[Append data to a spreadsheet](#append-data-to-a-spreadsheet)**
|
||||
3. **[Update single row of a spreadsheet](#update-single-row-of-a-spreadsheet)**
|
||||
4. **[Delete row from a spreadsheet](#delete-row-from-a-spreadsheet)**
|
||||
1. **[Create a spreadsheet](#create-a-spreadsheet)**
|
||||
2. **[List all sheets of a spreadsheet](#list-all-sheets-of-a-spreadsheet)**
|
||||
3. **[Read data from a spreadsheet](#read-data-from-a-spreadsheet)**
|
||||
4. **[Append data to a spreadsheet](#append-data-to-a-spreadsheet)**
|
||||
5. **[Get spreadsheet info](#get-spreadsheet-info)**
|
||||
6. **[Update single row of a spreadsheet](#update-single-row-of-a-spreadsheet)**
|
||||
7. **[Delete row from a spreadsheet](#delete-row-from-a-spreadsheet)**
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/datasource-reference/google-sheets/operations-v2.png" alt="Google Sheet Operations" style={{marginBottom:'15px'}} />
|
||||
<img className="screenshot-full" src="/img/datasource-reference/google-sheets/operations-v3.png" alt="Google Sheet Operations" style={{marginBottom:'15px'}} />
|
||||
|
||||
</div>
|
||||
|
||||
|
|
@ -68,6 +70,32 @@ Using Google sheets data source you can perform several operations from your app
|
|||
**Spreadsheet ID** can be obtained from the URL of the spreadsheet. For example, in the URL `https://docs.google.com/spreadsheets/d/1W2S4re7zNaPk9vqv6_CqOpPdm_mDEqmLmzjVe7Nb9WM/edit#gid=0`, the `1W2S4re7zNaPk9vqv6_CqOpPdm_mDEqmLmzjVe7Nb9WM` represents the spreadsheet ID.
|
||||
:::
|
||||
|
||||
### Create a Spreadsheet
|
||||
|
||||
This operation can be used to create a new spreadsheet.
|
||||
|
||||
#### Required Parameter
|
||||
- **Title**
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/datasource-reference/google-sheets/create-sheet.png" alt="create a spreadsheet" style={{marginBottom:'15px'}} />
|
||||
|
||||
</div>
|
||||
|
||||
### List All Sheets of a Spreadsheet
|
||||
|
||||
This operation can be used to list all sheets of a spreadsheet.
|
||||
|
||||
#### Required Parameter
|
||||
- **Spreadsheet ID**
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/datasource-reference/google-sheets/list-all-sheets.png" alt="create a spreadsheet" style={{marginBottom:'15px'}} />
|
||||
|
||||
</div>
|
||||
|
||||
### Read Data From a Spreadsheet
|
||||
|
||||
This operation allows you to retrieve the table data from a spreadsheet in the form of a JSON object.
|
||||
|
|
@ -129,6 +157,16 @@ Add additional rows to a table by using the append operation.
|
|||
]
|
||||
```
|
||||
|
||||
### Get Spreadsheet Info
|
||||
|
||||
This operation allows you to retrieve basic information about the spreadsheet, including the number of sheets, theme, time zone, format, and URL, among others.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/datasource-reference/google-sheets/info-v2.png" alt="google sheets get info" style={{marginBottom:'15px'}} />
|
||||
|
||||
</div>
|
||||
|
||||
### Update Single Row of a Spreadsheet
|
||||
|
||||
This operation allows you to update existing data in a sheet.
|
||||
|
|
@ -179,14 +217,4 @@ This operation allows you to delete a specific row from the sheet.
|
|||
|
||||
</div>
|
||||
|
||||
### Get Spreadsheet Info
|
||||
|
||||
This operation allows you to retrieve basic information about the spreadsheet, including the number of sheets, theme, time zone, format, and URL, among others.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/datasource-reference/google-sheets/info-v2.png" alt="google sheets get info" />
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ Metadata is additional information about the data returned by the GraphQL query.
|
|||
While accessing the properties of the metadata object, which contains a hyphen, you can use the bracket notation. For example, to access the `content-length` property, you can use `{{queries.graphql1.metadata.request.headers["content-length"]}}` or `{{queries.graphql1.metadata.request.headers."content-length"}}`.
|
||||
:::
|
||||
|
||||
<details>
|
||||
<details id="tj-dropdown">
|
||||
<summary>**Example Metadata**</summary>
|
||||
|
||||
```json
|
||||
|
|
|
|||
50
docs/docs/data-sources/local-data-sources-migration.md
Normal file
50
docs/docs/data-sources/local-data-sources-migration.md
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
---
|
||||
|
||||
id: local-data-sources-migration
|
||||
title: Local Data Sources Migration Guide
|
||||
|
||||
---
|
||||
|
||||
Starting with ToolJet version 3.0.0, **Local Data Sources** have been fully discontinued. These were deprecated in earlier versions, and now support for them has been completely removed. This guide will help you migrate your queries that were connected to Local Data Sources to the new **Data Sources**.
|
||||
|
||||
## Migration Process for Existing ToolJet 3.0.0 Users
|
||||
|
||||
After upgrading to ToolJet 3.0.0, any queries connected to Local Data Sources will display an error message indicating that the Local Data Source is no longer supported. Follow these steps to resolve this issue:
|
||||
|
||||
## Step-by-Step Migration Guide:
|
||||
|
||||
### 1. Identify Queries with Errors:
|
||||
1. Navigate to the app where you were using Local Data Sources.
|
||||
2. Expand the Query Manager.
|
||||
3. Look for queries showing an error message related to Local Data Sources. These queries will only display the error message and the rest of content will be hidden.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/datasource-reference/v3-migration/query-error.png" alt="Identify Queries with Errors"/>
|
||||
</div>
|
||||
|
||||
### 2. Create a New Data Source:
|
||||
1. Navigate to the **Data Sources** section.
|
||||
2. Create a new Data Source of the same type (e.g., if you were using a PostgreSQL Local Data Source, create a PostgreSQL Data Source).
|
||||
3. Fill in the correct required details and save the new Data Source.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/datasource-reference/v3-migration/create-new-data-source.png" alt="Create a New Data Source"/>
|
||||
</div>
|
||||
|
||||
### 3. Reconnect Your Queries:
|
||||
1. Return to your app where the queries were previously using Local Data Sources.
|
||||
2. Open the query that was showing an error.
|
||||
3. You will see a dropdown under the **Source** field.
|
||||
4. Select the newly created Data Source of the same type from the dropdown.
|
||||
5. Your query will now be reconnected and functional.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/datasource-reference/v3-migration/query-reconnection.png" alt="Reconnect Query with Data Source"/>
|
||||
</div>
|
||||
|
||||
### 4. Test Your Queries:
|
||||
1. Run each updated query to ensure everything is working as expected.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/datasource-reference/v3-migration/test-queries.png" alt="Test Your Queries"/>
|
||||
</div>
|
||||
|
|
@ -13,7 +13,7 @@ The Mailgun API Datasource supports for interaction with the mail endpoint of th
|
|||
|
||||
## Connection
|
||||
|
||||
To establish a connection with the **Mailgun** data source, click on the **+ Add new data source** button located on the query panel or navigate to the [Data Sources](https://docs.tooljet.com/docs/data-sources/overview) page from the ToolJet dashboard.
|
||||
To establish a connection with the **Mailgun** data source, click on the **+ Add new data source** button located on the query panel or navigate to the [Data Sources](/docs/data-sources/overview) page from the ToolJet dashboard.
|
||||
|
||||
ToolJet requires the following to connect to your Mailgun:
|
||||
- **API key**
|
||||
|
|
|
|||
|
|
@ -24,7 +24,16 @@ ToolJet requires the following to connect to your MongoDB.
|
|||
|
||||
**Note:** It is recommended to create a new MongoDB user so that you can control the access levels of ToolJet.
|
||||
|
||||
<img className="screenshot-full" src="/img/datasource-reference/mongo-db/mo-connect.png" alt="ToolJet - Mongo connection" />
|
||||
<img style={{ marginBottom:'15px' }} className="screenshot-full" src="/img/datasource-reference/mongo-db/mo-connect.png" alt="ToolJet - Mongo connection" />
|
||||
|
||||
### Secure Sockets Layer (SSL)
|
||||
|
||||
- **SSL Certificate**: SSL certificate to use with MongoDB. Supported Types:
|
||||
- **None**: No SSL certificate verification.
|
||||
- **CA Certificate**: Requires a CA certificate to verify the server certificate.
|
||||
- **Client Certificate**: Requires a client certificate, client key, and CA certificate to authenticate with the server.
|
||||
|
||||
<img className="screenshot-full" src="/img/datasource-reference/mongo-db/ssl.png" alt="MongoDB - SSL Certificate" />
|
||||
|
||||
</div>
|
||||
|
||||
|
|
@ -518,7 +527,7 @@ Dynamic queries in MongoDB can be used to create flexible and parameterized quer
|
|||
{ createdAt: new Date('01/10/2020') }
|
||||
```
|
||||
|
||||
Reference on [mongodb extended JSON](https://docs.mongodb.com/manual/reference/mongodb-extended-json/) supported data types
|
||||
Reference on [mongodb extended JSON](https://docs.mongodb.com/manual/reference/mongodb-extended-json/) supported data types.
|
||||
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -21,12 +21,38 @@ ToolJet requires the following to connect to your PostgreSQL database.
|
|||
- **Port**
|
||||
- **Username**
|
||||
- **Password**
|
||||
- **Connection Options**
|
||||
- **Azure** (Select this option if you are using Azure SQL databases)
|
||||
|
||||
**Note:** It is recommended to create a new database user so that you can control the access levels of ToolJet.
|
||||
|
||||
<img className="screenshot-full" src="/img/datasource-reference/mssql/connect.png" alt="ToolJet - Redis connection"/>
|
||||
<img style={{marginBottom:'15px'}} className="screenshot-full" src="/img/datasource-reference/mssql/connect-v2.png" alt="ToolJet - Redis connection"/>
|
||||
|
||||
### Connection Options
|
||||
|
||||
You can add optional configurations in **key-value pairs** for the MS SQL data source connection.
|
||||
|
||||
#### Example:
|
||||
| Key | Value |
|
||||
|:--------------------------|:--------|
|
||||
| trustServerCertificate| true |
|
||||
|
||||
These options allow you to fine-tune the connection, such as enabling encryption when using a self-signed certificate.
|
||||
|
||||
### Enabling Encryption with a Self-Signed Certificate
|
||||
|
||||
To enhance security during data transfer, encryption can be enabled even with a self-signed certificate.
|
||||
|
||||
#### Server-Side Configuration
|
||||
1. **Create and Install a Self-Signed Certificate:**
|
||||
- Generate a self-signed certificate and install it on the SQL Server instance.
|
||||
2. **Force Encryption:**
|
||||
- Configure the SQL Server instance to force encrypted connections.
|
||||
- For Azure SQL databases, turn on the **Encryption** toggle in the Azure portal.
|
||||
|
||||
#### Client-Side Configuration
|
||||
1. Set the connection option `trustServerCertificate` to `true`.
|
||||
- This bypasses certificate chain validation and is necessary when using a self-signed certificate.
|
||||
|
||||
</div>
|
||||
|
||||
|
|
@ -54,7 +80,7 @@ SELECT * FROM users
|
|||
|
||||
<img className="screenshot-full" src="/img/datasource-reference/mssql/sql mode.png" alt="ToolJet mssql sql mode" style={{marginBottom:'15px'}}/>
|
||||
|
||||
#### **Parameterized queries**:
|
||||
#### Parameterized queries:
|
||||
|
||||
ToolJet offers support for parameterized SQL queries, which enhance security by preventing SQL injection and allow for dynamic query construction. To implement parameterized queries:
|
||||
|
||||
|
|
@ -64,10 +90,10 @@ ToolJet offers support for parameterized SQL queries, which enhance security by
|
|||
4. The values can be static values or dynamic values using the `{{ }}` notation.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img className="screenshot-full" src="/img/datasource-reference/mssql/parameterized-query.png" alt="Postgresql parameterized SQL queries"/>
|
||||
<img style={{marginBottom:'15px'}} className="screenshot-full" src="/img/datasource-reference/mssql/parameterized-query.png" alt="Postgresql parameterized SQL queries"/>
|
||||
</div>
|
||||
|
||||
**Example:**
|
||||
##### Example:
|
||||
```yaml
|
||||
Query: SELECT * FROM users WHERE username = :username
|
||||
SQL Parameters:
|
||||
|
|
@ -75,6 +101,10 @@ SQL Parameters:
|
|||
Value: oliver // or {{ components.username.value }}
|
||||
```
|
||||
|
||||
#### Query Timeout
|
||||
|
||||
You can set the timeout duration for SQL queries by adding the `PLUGINS_SQL_DB_STATEMENT_TIMEOUT` variable to the environment configuration file. By default, it is set to 120,000 ms.
|
||||
|
||||
### GUI Mode
|
||||
|
||||
GUI mode can be used to query MS SQL Server / Azure SQL Databases without writing queries.
|
||||
|
|
|
|||
|
|
@ -92,10 +92,10 @@ ToolJet offers support for parameterized SQL queries, which enhance security by
|
|||
4. The values can be static values or dynamic values using the `{{ }}` notation.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img className="screenshot-full" src="/img/datasource-reference/mysql/parameterized-query.png" alt="mysql"/>
|
||||
<img style={{marginBottom:'15px'}} className="screenshot-full" src="/img/datasource-reference/mysql/parameterized-query.png" alt="mysql"/>
|
||||
</div>
|
||||
|
||||
**Example:**
|
||||
##### Example:
|
||||
```yaml
|
||||
Query: SELECT * FROM users WHERE username = :username
|
||||
SQL Parameters:
|
||||
|
|
@ -103,6 +103,9 @@ SQL Parameters:
|
|||
Value: oliver // or {{ components.username.value }}
|
||||
```
|
||||
|
||||
#### Query Timeout
|
||||
|
||||
You can set the timeout duration for SQL queries by adding the `PLUGINS_SQL_DB_STATEMENT_TIMEOUT` variable to the environment configuration file. By default, it is set to 120,000 ms.
|
||||
|
||||
### GUI Mode
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ ToolJet can trigger n8n workflows using webhook URLs. Please refer [this](https:
|
|||
|
||||
## Connection
|
||||
|
||||
To establish a connection with the n8n data source, click on the **+ Add new Data source** button located on the query panel or navigate to the [Data Sources](https://docs.tooljet.com/docs/data-sources/overview) page from the ToolJet dashboard.
|
||||
To establish a connection with the n8n data source, click on the **+ Add new Data source** button located on the query panel or navigate to the [Data Sources](/docs/data-sources/overview) page from the ToolJet dashboard.
|
||||
|
||||
Webhooks in n8n can be configured to operate with or without **Authentication**. If no authentication is required, select `None` as the **Authentication type**. For webhooks that require authentication, choose the appropriate method from the dropdown and provide the corresponding credentials.
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ ToolJet can connect to a Notion workspace to do operations on notion pages, data
|
|||
|
||||
## Connection
|
||||
|
||||
To establish a connection with the Notion data source, click on the **+ Add new Data source** button located on the query panel or navigate to the [Data Sources](https://docs.tooljet.com/docs/data-sources/overview) page from the ToolJet dashboard.
|
||||
To establish a connection with the Notion data source, click on the **+ Add new Data source** button located on the query panel or navigate to the [Data Sources](/docs/data-sources/overview) page from the ToolJet dashboard.
|
||||
|
||||
For integrating Notion with ToolJet we will need the API token. The API token can be generated from your Notion workspace settings. Read the official Notion docs for [Creating an internal integration with notion API](https://www.notion.so/help/create-integrations-with-the-notion-api).
|
||||
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ Data Source page is available only on **ToolJet version 2.3.0 and above**.
|
|||
|
||||
3. Once the data source is added, you'll be required to input the configuration details for establishing a connection.
|
||||
|
||||
***Note: For paid plans, configuration entry and saving are necessary to enable availability across [multiple environments](/docs/release-management/multi-environment/).***
|
||||
***Note: For paid plans, configuration entry and saving are necessary to enable availability across [multiple environments](/docs/development-lifecycle/environment/self-hosted/multi-environment).***
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
|
|
@ -78,7 +78,7 @@ By default, 4 data sources will be available on every app on ToolJet:
|
|||
|
||||
## User Permissions
|
||||
|
||||
Changing the **Permissions** for Data Sources is a privilege reserved for **Admins** and **[Super Admins](/docs/Enterprise/superadmin)** within the workspace.
|
||||
Changing the **Permissions** for Data Sources is a privilege reserved for **Admins** and **[Super Admins](/docs/user-management/role-based-access/access-control#data-sources)** within the workspace.
|
||||
|
||||
To configure these permissions, navigate to **Workspace Settings** -> **Groups Settings**. Admins and Super Admins have the authority to assign the following permissions to user groups:
|
||||
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ To connect to PostgreSQL using Manual connection parameters, select **Manual con
|
|||
- **Connection Options**
|
||||
- **SSL Certificate**
|
||||
|
||||
<img className="screenshot-full" src="/img/datasource-reference/postgresql/pgconnection-v2.png" alt="PG connection"/>
|
||||
<img style={{marginBottom:'15px'}} className="screenshot-full" src="/img/datasource-reference/postgresql/pgconnection-v2.png" alt="PG connection"/>
|
||||
|
||||
### Connection String
|
||||
|
||||
|
|
@ -39,7 +39,7 @@ To connect to PostgreSQL using a connection string, select **Connection String**
|
|||
|
||||
<img className="screenshot-full" src="/img/datasource-reference/postgresql/pgconnection-string.png" alt="PG connection string"/>
|
||||
|
||||
<br/><br/><br/>
|
||||
<br/><br/>
|
||||
|
||||
**Note:** We recommend creating a new PostgreSQL database user to have control over ToolJet's access levels.
|
||||
|
||||
|
|
@ -75,9 +75,9 @@ ToolJet offers support for parameterized SQL queries, which enhance security by
|
|||
3. The keys should match the parameter names used in the query (without the colon).
|
||||
4. The values can be static values or dynamic values using the `{{ }}` notation.
|
||||
|
||||
<img className="screenshot-full" src="/img/datasource-reference/postgresql/parameterized-query.png" alt="Postgresql parameterized SQL queries"/>
|
||||
<img style={{marginBottom:'15px'}} className="screenshot-full" src="/img/datasource-reference/postgresql/parameterized-query.png" alt="Postgresql parameterized SQL queries"/>
|
||||
|
||||
**Example:**
|
||||
##### Example:
|
||||
|
||||
```yaml
|
||||
Query: SELECT * FROM users WHERE username = :username
|
||||
|
|
@ -86,6 +86,10 @@ SQL Parameters:
|
|||
Value: oliver // or {{ components.username.value }}
|
||||
```
|
||||
|
||||
#### Query Timeout
|
||||
|
||||
You can set the timeout duration for SQL queries by adding the `PLUGINS_SQL_DB_STATEMENT_TIMEOUT` variable to the environment configuration file. By default, it is set to 120,000 ms.
|
||||
|
||||
### GUI Mode
|
||||
|
||||
Choose the GUI mode from the dropdown and select the operation **Bulk update using primary key**. Provide the **Table** name and the **Primary key column** name. Then, in the editor, input the **records** as an array of objects.
|
||||
|
|
|
|||
|
|
@ -75,9 +75,12 @@ Google Cloud Platform provides access to more than 350 APIs and Services that ca
|
|||
2. Navigate to the **APIs and Services**, and then open the **OAuth consent screen** section from the left sidebar.
|
||||
3. Enter the Application details and select the appropriate scopes for your application. We will select the profile and the email scopes.
|
||||
4. Once you have created the OAuth consent screen, Create new credentials for the **OAuth client ID** from the **Credentials** section in the left sidebar.
|
||||
5. Select the application type, enter the application name, and then add the following URIs under Authorized Redirect URIs:
|
||||
1. `https://app.tooljet.com/oauth2/authorize` (if you’re using ToolJet cloud)
|
||||
5. Select the application type, enter the application name, and then add the following URIs under Authorized Redirect URIs(Callback URL):
|
||||
1. `https://app.tooljet.ai/oauth2/authorize` (if you’re using ToolJet cloud)
|
||||
2. `http://localhost:8082/oauth2/authorize` (if you’re using ToolJet locally)
|
||||
|
||||
<img class="screenshot-full" src="/img/how-to/oauth2-authorization/callback-URL.png" alt="ToolJet - How To - REST API CallBack URL in OAuth 2.0" style={{marginBottom:'15px'}}/>
|
||||
|
||||
6. Now save and then you’ll get the **Client ID and Client secret** for your application.
|
||||
|
||||
<img class="screenshot-full" src="/img/how-to/oauth2-authorization/gcp.png" alt="ToolJet - How To - REST API authentication using OAuth 2.0" style={{marginBottom:'15px'}}/>
|
||||
|
|
@ -97,7 +100,7 @@ Let's follow the steps to authorize ToolJet to access your Google profile data:
|
|||
9. Create three **Custom Authentication Parameters:**
|
||||
1. **response_type**: code ( `code` refers to the Authorization Code)
|
||||
2. **client_id**: Client ID
|
||||
3. **redirect_url**: `http://localhost:8082/oauth2/authorize` if using ToolJet locally or enter this `https://app.tooljet.com/oauth2/authorize` if using ToolJet Cloud.
|
||||
3. **redirect_url**: `http://localhost:8082/oauth2/authorize` if using ToolJet locally or enter this `https://app.tooljet.ai/oauth2/authorize` if using ToolJet Cloud.
|
||||
10. Keep the default selection for **Client Authentication** and **Save** the data source.
|
||||
|
||||
<img class="screenshot-full" src="/img/how-to/oauth2-authorization/restapi-v2.png" alt="ToolJet - How To - REST API authentication using OAuth 2.0" style={{marginBottom:'15px'}}/>
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ ToolJet requires the following to connect to a REST API data source:
|
|||
### Authentication
|
||||
|
||||
:::info
|
||||
For a detailed explanation of the authentication types supported by REST API data sources, refer to the **[Authentication](./authentication)** section.
|
||||
For a detailed explanation of the authentication types supported by REST API data sources, refer to the **[Authentication](/docs/data-sources/restapi/authentication)** section.
|
||||
:::
|
||||
|
||||
ToolJet supports the following authentication types for REST API data sources:
|
||||
|
|
@ -71,8 +71,12 @@ ToolJet supports the following authentication types for REST API data sources:
|
|||
- **CA Certificate**: Requires a CA certificate to verify the server certificate.
|
||||
- **Client Certificate**: Requires a client certificate, client key, and CA certificate to authenticate with the server.
|
||||
|
||||
<img className="screenshot-full" src="/img/datasource-reference/rest-api/ssl.png" alt="REST API - SSL Certificate" />
|
||||
<img style={{marginBottom:'15px'}} className="screenshot-full" src="/img/datasource-reference/rest-api/ssl.png" alt="REST API - SSL Certificate" />
|
||||
|
||||
</div>
|
||||
|
||||
:::info
|
||||
To interact with SOAP APIs, refer to the [SOAP API Documentation](/docs/data-sources/soap-api).
|
||||
:::
|
||||
|
||||
</div>
|
||||
|
|
@ -11,7 +11,7 @@ Metadata is additional information about the data returned by the REST API. This
|
|||
While accessing the properties of the metadata object, which contains a hyphen, you can use the bracket notation. For example, to access the `user-agent` property, you can use `{{queries.restapi1.metadata.request.headers["user-agent"]}}` or `{{queries.restapi1.metadata.request.headers."user-agent"}}`.
|
||||
:::
|
||||
|
||||
<details>
|
||||
<details id="tj-dropdown">
|
||||
<summary>**Example Metadata**</summary>
|
||||
|
||||
```json
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ Once you have connected to the REST API data source, you can easily write querie
|
|||
4. Click **Preview** to view the data returned from the query or click **Run** to execute the query.
|
||||
|
||||
:::tip
|
||||
You can also transform the query results using the **[Transformations](/docs/how-to/transformations)** feature.
|
||||
You can also transform the query results using the **[Transformations](/docs/tutorial/transformations)** feature.
|
||||
:::
|
||||
|
||||
ToolJet supports the following REST HTTP methods:
|
||||
|
|
@ -49,6 +49,12 @@ For example, to send a **multipart/form-data** body, you can add the following h
|
|||
<img className="screenshot-full" src="/img/datasource-reference/rest-api/form-headers.png" alt="ToolJet - Data source - REST API" />
|
||||
|
||||
<img className="screenshot-full" src="/img/datasource-reference/rest-api/form-body.png" alt="ToolJet - Data source - REST API" />
|
||||
<br/><br/>
|
||||
|
||||
:::info Handling OAuth Token via REST API
|
||||
To obtain an OAuth token via REST API, add the following custom header: <br/>
|
||||
`Content-Type: application/x-www-form-urlencoded`
|
||||
:::
|
||||
|
||||
|
||||
## Response Types and Handling
|
||||
|
|
@ -56,7 +62,7 @@ For example, to send a **multipart/form-data** body, you can add the following h
|
|||
REST APIs can return data in a variety of formats, including **JSON** and **Base64**. JSON is a common format used for data exchange in REST APIs, while Base64 is often used for encoding binary data, such as images or video, within a JSON response.
|
||||
When the response **content-type** is **image**, the response will be a **base64** string.
|
||||
|
||||
<details>
|
||||
<details id="tj-dropdown">
|
||||
<summary>**Example JSON response**</summary>
|
||||
|
||||
```json
|
||||
|
|
@ -120,18 +126,17 @@ You can also use JS methods like **map** to load data on components like **dropd
|
|||
|
||||
<img className="screenshot-full" src="/img/datasource-reference/rest-api/map.png" alt="ToolJet - Data source - REST API" style={{marginBottom:'15px'}} />
|
||||
|
||||
<details>
|
||||
<details id="tj-dropdown">
|
||||
<summary>**Example base64 response**</summary>
|
||||
```base64
|
||||
iVBORw0KGgoAAAANSUhEUgAAAOEAAADhCAMAAAAJbSJIAAAA/FBMVEVAYt79/f1AYt/9/f79/ftAY9s/Y93v/P89ZNv8/v38/f/9/vj9/vr+/Pz//P49ZNw8ZddUb86QpMlCYOX1//9AYeI6XdaXp+C1x+nL2fj+/vU2WMZVb8iPnsU3Xt00WNY7ZtU0WMuJncs8W8JDY801W986V9BTacRleMF+kNClt+CsvuFtiNYvVMRcedaZq9Lb5/eCl9K8zOJJWcqlr9xdb8C6w+w7XsCmvt3S5fs5ac1whs7l8v/6//B9j8wvVLrO2+o+Y7t6kMODotxPbL0+WOLf3/aesdVmfbvL5PentOmDl99RbtdMXcGOnNqTqdp+luIyVrLr7Pq/2/3mMzS8AAAKxUlEQVR4nO2cC1vbthrHLVmWJUuW3dlywWYkIRAorG1K6SgjgV5g3a3jbOf7f5fzygngcCvbeobN8/7a8rQl7eO/Jf3fiyV7HoIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIIgCIL8H+CBI0kSzj3OA5Gm9V8EQojAsw99dV8DUMg5tzYDLLWgktbAb4CHvrqvwWwM6zETMJJpmgqRwg9qLeXiMUisFcK4cZifqxsbvXMKmtlHpNDrjarNrWdPt3d2luZ8JzzL004rdGvNERSD5y9eLo9DMkc7yDfrAYxr8MAX+XdxvunWmfPLwf6r3VASIiVjMYkJ/IzhK/mmECLrrEKPJmm/vy5sb3i4O5FRzMg1uq2QOmMRxej13liWpWKxeWwKnXfa3ovtEPQxwvwoemwKPS6qN9+HqixjYyLHo1IIJpMV+29DCbOTMOVm6XV9XVTo4h73wD8Tz1ZnIZGRE8ZqHo/CIEhFElTfHeRSkxtm5iNQmP4gNl7v5ErFxpfSRb/HpVCAh1aHk7zUxhg91ezRKYRM5vV2Pi1Bn/HZzQbTSYVgnlDtwQB6xQ9jaUzMyrLU0Q1R/gKfkA+FCLKgGwrTxEKVIIQdHYXEj30ia//0b1EXRQxuA/ku5WC8XagtKOTZnqvcs9FZLu+cmBcKGajfTD3riYe++ntBaZCmCaXPvydTJV3h8AWdkrBS58cCbk43Jilk2Wk/Fe8PdBzrmYbaQ28zGqYNm8p3VRcm6JwAbGb9/UGuiGlG+dvWIVMmLuV2QR/6uu8PLKji/YGMIqXmqmQjVviMRX5z3rLSN2V+tNoJhbCQXDaa2c1JTPxIsplCJiM11eO1N09enB3kGuLjZWyUxDCp2eT9Q1/7/eFBulFBGFyYiFJOXg0Lm9nB8GUOsaG5Jk2sS7JbPfR13w+oJayl6XBZl5crEEYpVuGbDYgFaSq86izXrKnfmHIqj2wnJil4jLVeMlxmoEk2FJr8Q5GlPF3vwwwevpOqqdCt18l+1hmFXnq8k8NKK7XvX0QIOd7niQD1NIOJuiZVvKCQkbdVK8fQXdP8ocOcwKNi+BHK3CiS9eidx4OdHuUW5mia9pPiDdELCmUsT1rZCqYZFQIGhQ6qwWhQOYaD0fGHUF4NfYy8LJLUlRpQcFBvhUC8uPxubNTSIG3lGEL9zr3R52c7yw0gGlxLXpjeGdnz50pUHBK1cAtYfrgqaCsVJnTwfu9PKbUq6868Zlorra8KhJg+Oc4srzVQWr2UC7NU5u+q7KG13Ai1XvUxJE4TY1o5Yqa0jK4k2j6sw/zVwNLZIKZ/jBe9VOZbvcy2MeemdLgkQRJoAkCYjHy//u3VdegbGZ4EM4V8/YMslbn4BNyOn0c2pS1TSF0d7w13ZclchyKGWVp3CSHXNjd0KyKj1MFm4W6KV2z9GU/PFcInYU4/O7X9llkpzdJ1TqvvCVGs7l+fd0ChkPevVUlQIhpd5pO1/UFRHB+F7hOzWQpVhVTkx+e2bSMIK1CIZHhG3Hh9oQs6V65Vnufjt5/ejqPmFGYxfOOoeGg9V6EeDaitPkifKPWlPu8MpWB16lKD7ZaNIfYlDP7y/kMLugaYvqDFYVi7p38/hRqSz3JaSskgWrJZtsPg7qh4ctLK3gwvPo/rBprv31a5L+CEgeeC386fOs3+lR9ruTd4aDE3we1gj6j6KZl/d5u3lgdOEysF4vyYXaxbxiT8EVJy58uzHLcd0CQBl6FbOcyx6F7jdy5o4Y++0XCH1DTcKtq2S4jzhHM+3M2Z+SsCrw+sli6EbFde0rJIkXC3p+KnUM4LpL8JK6UxSv+8T2nbHlUIDgIHu1DD/kOFviFy8p5n7VOYQAKyImNtIA/9BwqVgVz1MF21om21L7iMV237cWx8yD/dZp/4fMvPPYHlC2FGxiQ/G0F2K9L22GiN6NtsM3T1EqsLQlan3sb4vpQ37bC4Thzp6dQ3U/1LL6n/y5Yp9FKe/RpeI/eZi3j3mZ8liSDzZvnusdey+VlDsyD1fjtZucpTQspS3U8hjDozcnmYijbuCKYZTUUg6Oo5s72+We/bHOra+1gP064DrA72My5a2X3i1BOCpw04FyJNh9/m7IuVlMtr/MiHSH+wX1ietHEMvZTaQCT1luxgvjHbbbrg2fDbO/eSOHyXqYMdKbI8zGgAJVgbx7DuRHjzveezn/Uv6w3W8hJKjdsdNYJcFKoLJuXS/motrp0CbwFm7/CbHIr+Ut+m0Jdag9FMIRkNvFa2R2/k/EIFzfhw7U5HZYoZCKL5WWVtG+PEzVyMBKzEzA5qR731aTbECS0nTwb9fvqQ1/w3qX2Dg6MSdrtCn+jdz6c27bctF70der7/3nPOKpI7HRWybZiiG+7sCE14J2wGErjMZQCXtnG3o0ods6erwcWxhNbjLtSd5uGurTEbkrsdNVJOYWcmaP1kBpIZqGHT/nlD8G5HjRTrlkKv3uW8QbnbfzDjbkftlMJ6TqaJ5dWvK+40z7wTcbejyg4pnFkF5KjH2/n4xIOJOpPI3Yav2lFv2kwKCklHFFIL6Tf3RNZbIkaNV/ru/CC/dFQKjqpcJ2Zhz0UcO4VFJxR6roSCL71fpCGxnGyKdO6oNTNHlQYyGLOgUMvOKAygRqS297vURkdK/7iZWueoc4XgqN5wTfpQSiwqhAKyI7PUc3u4OX8RljFzYRwmKhWXjprWjvrJGWrzkFrs2lW/d0Qh5Fw8PV6GtcZkvTt0stlwVFE76lYOCnVjezcojMizrii0VKy/IjKXkfadzrJ2VDHfJ8WdyidhqV1PNbpUaAzZ6kjhlNr++v6YESn9+rESY/5kxSbNrgR9Ehq28MjJ9aDCzW7s0ONpJtaPmp013+STTds8S2BBoSYLh0V9ow8Gqw932X8BnlpbLTd3d0FlpMZPmi1eN4ZaNhVGpJRnvVY+074CrZ9ArYSzfTMzCayMVf6f4m6FchoOW7ev5Gao109eLZS6vlH505G4TWH9FWLF3qDfyh7pFdzB8/76LjNmdt4Hph9jJv9Y9a86zeUY+u5UkByvix9sFyRCOLB/TAxziadSzEDIV5OjChK3xmcuFYLRGshvGAu3NsT6bJa23VB5kJ1IwzSLIohxUNDny5sDzwbNFlpzDCEswt3IfyoyLjoSLfjqM1lHu9ht22Ph09enGU0WbLKpMNJlSSY/VVmW8NNOKPSC3ieoAN0zFqV1tDQsAtci9LIb1mGdD+RKHmxuQCLUmU5pMFrSsdsuJPNwaWsEhYVLvPk1p6lzmpgwOdmrYAFCRSK6InHwzm3Dk2R8tjIKkoSvur6iaE7TVVBI3HEnyOv+3DsZ9hPIzGlmk9a7jOdK/OzzRJPw3aeV54V75QWft4abSTVkbao+7zNZ2no+8gJeb/PuTKc0efLfnVcrw4F7Z8lsb/O1z8AYlpHMD9ZOKtoN/2zC+/1qULjn2zaZr6trGmAdynz3qCq4O5Lxb1/hP8Zt/QLTSO56O9dKuHsyPLX1C8v+zWv7OoBpBvVLulwmessA/Xb4mvJT1xZPu6eQu/d0uQNB1rvlAL17jlGcZn337jk+exLTrZlKvfmL5O78DKUBP//44+TRCkMQBEEQBEEQBEEQBEEQBEEQBEEQBEEQBEEQBEEQBEEQBEEQBEEQBEEQBEGQr8n/ABGyzAUL7/lcAAAAAElFTkSuQmCC
|
||||
```
|
||||
</details>
|
||||
|
||||
Read the guide on **[loading base64 data](/docs/how-to/loading-image-pdf-from-db)**
|
||||
Read the guide on **[loading base64 data](/docs/how-to/loading-image-pdf-from-db)**.
|
||||
|
||||
<img className="screenshot-full" src="/img/datasource-reference/rest-api/base64.png" alt="ToolJet - Data source - REST API" />
|
||||
|
||||
|
||||
## Retry on Network Errors
|
||||
|
||||
ToolJet provides an option to automatically retry REST API requests in case of certain network errors or specific HTTP status codes. By default, this feature is enabled and will retry the request up to 3 times in case of failure. This feature can be toggled on or off at both the data source level and the individual query level. When enabled, retries will occur for the following scenarios:
|
||||
|
|
|
|||
|
|
@ -175,7 +175,7 @@ The presigned URLs are useful if you want your user/customer to be able to uploa
|
|||
<img className="screenshot-full" src="/img/datasource-reference/aws-s3/urluplv2-v3.png" alt="aws s3 signed upload" />
|
||||
|
||||
:::info
|
||||
We built an app to view and upload files to AWS S3 buckets. Check out the complete tutorial **[here](https://blog.tooljet.com/build-an-aws-s3-broswer-with-tooljet/)**.
|
||||
We built an app to view and upload files to AWS S3 buckets. Check out the complete tutorial **[here](https://blog.tooljet.ai/build-an-aws-s3-broswer-with-tooljet/)**.
|
||||
:::
|
||||
|
||||
</div>
|
||||
|
|
@ -29,7 +29,7 @@ This method allows you to add a sample data source to an existing application th
|
|||
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/datasource-reference/sample-data-sources/connect-via-canvas.gif" alt="Connect via Canvas" />
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/datasource-reference/sample-data-sources/connect-via-canvas-v2.png" alt="Connect via Canvas" />
|
||||
</div>
|
||||
|
||||
|
||||
|
|
@ -44,7 +44,7 @@ This method allows you to connect the sample data source to an existing applicat
|
|||
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/datasource-reference/sample-data-sources/connect-via-query-manager.gif" alt="Connect via query manager" />
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/datasource-reference/sample-data-sources/connect-via-query-manager-v2.png" alt="Connect via query manager" />
|
||||
</div>
|
||||
|
||||
|
||||
|
|
@ -59,7 +59,7 @@ This method enables the creation of a sample application with a pre-configured c
|
|||
5. By default, this application will feature a table component with tabs. These tabs will visually display the data retrieved from your sample data source.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/datasource-reference/sample-data-sources/create-sample-app.gif" alt="Create Sample App" />
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/datasource-reference/sample-data-sources/create-sample-app-v2.png" alt="Create Sample App" />
|
||||
</div>
|
||||
|
||||
## Sample Data Source Schema
|
||||
|
|
@ -68,8 +68,8 @@ The sample data source contains various tables with different data types.
|
|||
|
||||
| Table Name | Column Names| Number of Rows |
|
||||
|:-------|:---------|:---------------|
|
||||
| `sampledataxlsx_organizations` | `index`, `organization_id`, `name`, `website`, `country`, `description`, `founded`, `industry`, `number_of_employees` | 100 |
|
||||
| `sampledataxlsx_countrygdp` | `country`, `area_sq_km, population`, `exports`, `imports, gdp`, `gdp_per_capita`, `gdp_real_growth_rate`, `inflation_rate_consumer_prices`, `investment_gross_fixed_of_gdp`, `labor_force`, `unemployment_rate` | 263 |
|
||||
| `sampledataxlsx_users` | `first_name`, `last_name`, `company_name`, `address`, `city`, `county`, `state`, `zip`, `phone1`, `phone2`, `email`, `web` | 500 |
|
||||
| `sampledataxlsx_orders` | `row_id`, `order_id`, `order_date`, `ship_date`, `ship_mode`, `customer_id`, `customer_name`, `segment`, `country`, `city`, `state`, `postal_code`, `region`, `product_id`, `category`, `sub_category`, `product_name`, `sales`, `quantity`, `discount`, `profit` | 500 |
|
||||
| `sampledataxlsx_productlistcars` | `car`, `mpg`, `cylinders`, `displacement`, `horsepower`, `weight`, `acceleration`, `model`, `origin` | 406 |
|
||||
| `public.sample_data_organizations` | `index`, `organization_id`, `name`, `website`, `country`, `description`, `founded`, `industry`, `number_of_employees` | 100 |
|
||||
| `public.sample_data_country_gdp` | `country`, `area_sq_km, population`, `exports`, `imports, gdp`, `gdp_per_capita`, `gdp_real_growth_rate`, `inflation_rate_consumer_prices`, `investment_gross_fixed_of_gdp`, `labor_force`, `unemployment_rate` | 263 |
|
||||
| `public.sample_data_users` | `first_name`, `last_name`, `company_name`, `address`, `city`, `county`, `state`, `zip`, `phone1`, `phone2`, `email`, `web` | 499 |
|
||||
| `public.sample_data_orders` | `row_id`, `order_id`, `order_date`, `ship_date`, `ship_mode`, `customer_id`, `customer_name`, `segment`, `country`, `city`, `state`, `postal_code`, `region`, `product_id`, `category`, `sub_category`, `product_name`, `sales`, `quantity`, `discount`, `profit` | 500 |
|
||||
| `public.sample_data_product_cars` | `car`, `mpg`, `cylinders`, `displacement`, `horsepower`, `weight`, `acceleration`, `model`, `origin` | 406 |
|
||||
|
|
|
|||
62
docs/docs/data-sources/soapapi.md
Normal file
62
docs/docs/data-sources/soapapi.md
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
---
|
||||
id: soap-api
|
||||
title: SOAP API
|
||||
---
|
||||
|
||||
ToolJet can establish connections with SOAP APIs using its REST API integration.
|
||||
|
||||
<div style={{paddingTop:'24px'}}>
|
||||
|
||||
## Setting up a SOAP API Data Source
|
||||
|
||||
To establish a connection with a SOAP API data source, you will need to add a REST API data source, as ToolJet handles SOAP APIs using REST API configurations.
|
||||
|
||||
You can refer to [REST API Configuration Documentation](/docs/data-sources/restapi/) for more information.
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px'}}>
|
||||
|
||||
## Querying SOAP API
|
||||
|
||||
Once you have connected to the REST API data source, you can easily write queries and interact with the SOAP API in the ToolJet application. Follow these steps to get started:
|
||||
|
||||
1. Click on the **+ Add** button in the query manager at the bottom panel of the editor.
|
||||
2. Select **REST API** from the Data Source section.
|
||||
3. Select the **POST** Method and enter your SOAP API endpoint.
|
||||
4. Add Headers
|
||||
- **Content-Type** : **text/xml** (Specifies that the request body is XML.)
|
||||
- Include any other required headers (e.g., Authorization, SOAPAction).
|
||||
5. Add Request **Body** in XML format.
|
||||
6. Click **Preview** to view the data returned from the query or click **Run** to execute the query.
|
||||
|
||||
:::tip
|
||||
You can also transform the query results using the **[Transformations](/docs/tutorial/transformations)** feature.
|
||||
:::
|
||||
|
||||
**API Endpoint URL Example:** `http://www.dneonline.com/calculator.asmx`
|
||||
|
||||
<img style={{marginBottom:'15px'}} className="screenshot-full" src="/img/datasource-reference/soap-api/headers.png" alt="SOAP API Headers" />
|
||||
|
||||
**Request Body Example:**
|
||||
|
||||
```xml
|
||||
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tem="http://tempuri.org/">
|
||||
<soapenv:Header/>
|
||||
<soapenv:Body>
|
||||
<tem:Add>
|
||||
<tem:intA>100</tem:intA>
|
||||
<tem:intB>5</tem:intB>
|
||||
</tem:Add>
|
||||
</soapenv:Body>
|
||||
</soapenv:Envelope>
|
||||
```
|
||||
|
||||
<img style={{marginBottom:'15px'}} className="screenshot-full" src="/img/datasource-reference/soap-api/api-body.png" alt="SOAP API Headers" />
|
||||
|
||||
**Additional Notes:**
|
||||
- SOAP APIs typically use the POST method. Using a different method can cause errors.
|
||||
- Ensure that you have added Content-Type: text/xml header. The server requires the correct header to interpret the request as SOAP.
|
||||
- Include the SOAPAction header if specified in the API documentation.
|
||||
|
||||
</div>
|
||||
|
|
@ -6,7 +6,7 @@ title: Stripe
|
|||
ToolJet can connect to your Stripe account to read or write customers' and payments' data.
|
||||
|
||||
:::info
|
||||
Check out the **[Stripe Refund App tutorial](https://blog.tooljet.com/build-a-stripe-refund-tool-using-low-code/)**
|
||||
Check out the **[Stripe Refund App tutorial](https://blog.tooljet.ai/build-a-stripe-refund-tool-using-low-code/)**
|
||||
:::
|
||||
|
||||
<div style={{paddingTop:'24px'}}>
|
||||
|
|
|
|||
16
docs/docs/development-lifecycle/backup/gitsync-backup.md
Normal file
16
docs/docs/development-lifecycle/backup/gitsync-backup.md
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
---
|
||||
id: gitsync-backup
|
||||
title: GitSync Backup
|
||||
---
|
||||
|
||||
GitSync enables users to back up their applications by pushing changes to a Git repository, ensuring a secured history. Whenever a change is pushed to the git repository, a commit is created. And this changes can be restored in ToolJet easily ensuring smooth back-up and restoring process. For details on configuring GitSync, refer to the **[GitSync Configuration](/docs/development-lifecycle/gitsync/gitsync-config)** guide.
|
||||
|
||||
**Note**: Only the latest pushed version of the application is stored in the git repository, i.e. whenever a new version is pushed to the git repository, only the latest version is stored and all the previous versions are overridden.
|
||||
|
||||
To know how to push changes to a git repository using GitSync, please refer to **[Push Changes to Git Repo](/docs/development-lifecycle/gitsync/push)** guide.
|
||||
|
||||
## Restore Application
|
||||
|
||||
Changes can be pulled from the git repository to restore an application. To know how to pull changes from a git repository using GitSync, please refer to **[Pull Changes from Git Repo](/docs/development-lifecycle/gitsync/pull)** guide.
|
||||
|
||||
**Note:** A restored application from the git repository can't be edited. To edit the application you will need to create a clone of the application.
|
||||
30
docs/docs/development-lifecycle/environment/cloud/example.md
Normal file
30
docs/docs/development-lifecycle/environment/cloud/example.md
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
---
|
||||
id: example-configuration
|
||||
title: Example Configuraiton
|
||||
---
|
||||
|
||||
This guide will walk you through setting up a multi-environment in ToolJet with a practical example. Imagine **Nexora Enterprises**, a company building an internal application using ToolJet.
|
||||
|
||||
## Configuring Data Source
|
||||
|
||||
In ToolJet, you can configure data sources for each environment, allowing your application to connect to different databases or APIs based on the environment.
|
||||
|
||||
In this case, the company uses data from a Postgres data source for their ToolJet apps, with separate databases for development, staging, and production environments. They need to configure the Postgres data source for each environment in the Data Sources section. For more details, refer to the [Data Source](/docs/data-sources/overview) Documentation.
|
||||
|
||||
<img style={{ marginBottom:'15px' }} className="screenshot-full img-l" src="/img/development-lifecycle/environments/selfhosted-datasource.png" alt="self-hosted-env-concept" />
|
||||
|
||||
## Configuring Constants
|
||||
|
||||
The company also uses different global and secret constants for each environment. Global Constants are reusable values that can be applied consistently across the product, while Secrets are used for securely storing sensitive data. These can be configured in the Workspace Constants section. For more details, check the [Workspace Constants and Secrets](/docs/security/constants/) Documentation.
|
||||
|
||||
<img style={{ marginBottom:'15px' }} className="screenshot-full img-l" src="/img/development-lifecycle/environments/cloud-constants.png" alt="self-hosted-env-concept" />
|
||||
|
||||
## Multi-Environment Setup in ToolJet
|
||||
- The company can configure data sources and constants for each environment, and ToolJet will automatically use the appropriate ones based on the target environment.
|
||||
- Now developers can start building applications in the **development environment**, where they create and iterate on new features. In this environment, they have access to the development database, which is configured during data source setup.
|
||||
- Once the application is ready, it moves to the **staging environment**, where the QA team tests it thoroughly. If any bugs or feedback arise, developers create a new version, implement the necessary changes, and promote the updated application back to staging for further testing.
|
||||
- The data sources for each environment will be connected based on the configuration set in the previous step.
|
||||
- For details on managing versions, check the **Version Control Documentation**.
|
||||
- After successful testing, the application is promoted to **production** and released, making it available to end users. This environment uses the production database set up during data source configuration.
|
||||
|
||||
<img style={{ marginBottom:'15px' }} className="screenshot-full img-l" src="/img/development-lifecycle/environments/appbuilder.png" alt="self-hosted-env-concept" />
|
||||
|
|
@ -0,0 +1,76 @@
|
|||
---
|
||||
id: multi-environment
|
||||
title: Multi-Environment
|
||||
---
|
||||
<div className="badge badge--primary heading-badge">
|
||||
<img
|
||||
src="/img/badge-icons/premium.svg"
|
||||
alt="Icon"
|
||||
width="16"
|
||||
height="16"
|
||||
/>
|
||||
<span>Paid feature</span>
|
||||
</div>
|
||||
|
||||
Environments in ToolJet help manage different stages of application development, ensuring smooth transitions between development, testing, and production. This guide covers what environments are, their purpose, and how they function in ToolJet.
|
||||
|
||||
Environments make it easier to develop and deploy applications without disrupting production. They keep changes isolated, so testing and debugging can happen without affecting live users. Teams can collaborate more efficiently, as different environments allow them to work independently.
|
||||
|
||||
### What are Environments?
|
||||
|
||||
An environment in ToolJet represents a separate configuration space where **applications**, **data** **sources**, and **constants** can be defined and managed.
|
||||
|
||||
By default, ToolJet provides three environments:
|
||||
|
||||
- **Development**: The Development environment is where application development and initial testing take place. It is a dedicated space for ToolJet developers to build, configure, and experiment with application features. Changes in this environment do not affect live users, allowing for frequent updates and debugging.
|
||||
|
||||
- **Staging**: The Staging environment acts as a pre-production space where applications undergo thorough testing before deployment. It closely resembles the Production environment and helps ensure that all features, performance, and security aspects function as expected. Teams such as QA and product managers use this environment to validate and approve changes before releasing them to end-users.
|
||||
|
||||
- **Production**: The Production environment is the final, live version of the application where end users interact with it. This environment is stable and optimized for performance after thorough testing in the Development and Staging environments.
|
||||
|
||||
|
||||
### Multi-Environment Support in ToolJet
|
||||
|
||||
ToolJet provides environment management across different components:
|
||||
|
||||
#### Applications
|
||||
|
||||
Each application has development, staging, and production environments. Developers build the application in the development environment and then move it to staging for testing. Your testing team can review the application in staging, and once it's thoroughly tested, you can promote it to production and release it to your end users.
|
||||
|
||||
#### Data Sources
|
||||
|
||||
Data sources can be configured separately for each environment, allowing applications to connect to different databases or APIs depending on the environment. This ensures secure and structured access to relevant data during each stage of development.
|
||||
|
||||
#### Constants
|
||||
|
||||
Constants such as API keys, credentials, or other configuration variables can be defined uniquely for each environment. This helps maintain security and prevents misconfigurations across different deployment stages.
|
||||
|
||||
### Application Life cycle
|
||||
|
||||
The application lifecycle in ToolJet involves managing applications across different environments development, staging, and production. You can build the application in development environment and promote it to staging for testing. After testing you can promote it to production and release the app for your end-users.
|
||||
|
||||
You can configure data sources and constants for each environment, and ToolJet will automatically use the appropriate ones based on the target environment.
|
||||
|
||||
- **Development** – Developers build and test the application in the ToolJet app builder.
|
||||
|
||||
- **Staging** – The testing or product team validates requirements and tests the application using staging data. Apps and queries cannot be edited in this environment.
|
||||
|
||||
- **Production** – After thorough testing in staging, the application is promoted to production. This can serve as a pre-release environment where you test with production data and constants before releasing the application to end users. Refer to [Release](/docs/development-lifecycle/release/release-rollback) documentation to learn more.
|
||||
|
||||
<img className="screenshot-full img-l" src="/img/development-lifecycle/environments/cloud-env.png" alt="self-hosted-env-concept" />
|
||||
|
||||
|
||||
### Impacted behavior with environment permission
|
||||
|
||||
Each environment has a different impact on your application. Please refer the following table for details.
|
||||
|
||||
| Action | Development | Staging | Production |
|
||||
|--------------------|------------|---------|------------|
|
||||
| Edit versions | ✅ | ❌ | ❌ |
|
||||
| Rename versions | ✅ | ❌ | ❌ |
|
||||
| Delete versions | ✅ | ❌ | ❌ |
|
||||
| Create new versions | ✅ | ❌ | ❌ |
|
||||
| Promote | ✅ | ✅ | - |
|
||||
|
||||
|
||||
Checkout the [Environment-Example](/docs/development-lifecycle/environment/cloud/example-configuration) guide to learn about multi-environment in ToolJet with a practical example.
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
---
|
||||
id: example-configuration
|
||||
title: Example Configuraiton
|
||||
---
|
||||
|
||||
This guide will walk you through setting up a multi-environment in ToolJet with a practical example. Imagine **Nexora Enterprises**, a company building an internal application using ToolJet.
|
||||
|
||||
## Configuring Data Source
|
||||
|
||||
In ToolJet, you can configure data sources for each environment, allowing your application to connect to different databases or APIs based on the environment.
|
||||
|
||||
In this case, the company uses data from a Postgres data source for their ToolJet apps, with separate databases for development, staging, and production environments. They need to configure the Postgres data source for each environment in the Data Sources section. For more details, refer to the [Data Source](/docs/data-sources/overview) Documentation.
|
||||
|
||||
<img style={{ marginBottom:'15px' }} className="screenshot-full img-l" src="/img/development-lifecycle/environments/selfhosted-datasource.png" alt="self-hosted-env-concept" />
|
||||
|
||||
## Configuring Constants
|
||||
|
||||
The company also uses different global and secret constants for each environment. Global Constants are reusable values that can be applied consistently across the product, while Secrets are used for securely storing sensitive data. These can be configured in the Workspace Constants section. For more details, check the [Workspace Constants and Secrets](/docs/security/constants/) Documentation.
|
||||
|
||||
<img style={{ marginBottom:'15px' }} className="screenshot-full img-l" src="/img/development-lifecycle/environments/selfhosted-constants.png" alt="self-hosted-env-concept" />
|
||||
|
||||
## Multi-Environment Setup in ToolJet
|
||||
- The company can configure data sources and constants for each environment, and ToolJet will automatically use the appropriate ones based on the target environment.
|
||||
- Now developers can start building applications in the **development environment**, where they create and iterate on new features. In this environment, they have access to the development database, which is configured during data source setup.
|
||||
- Once the application is ready, it moves to the **staging environment**, where the QA team tests it thoroughly. If any bugs or feedback arise, developers create a new version, implement the necessary changes, and promote the updated application back to staging for further testing.
|
||||
- The data sources for each environment will be connected based on the configuration set in the previous step.
|
||||
- For details on managing versions, check the [Version Control Documentation](/docs/development-lifecycle/release/version-control).
|
||||
- After successful testing, the application is promoted to **production** and released, making it available to end users. This environment uses the production database set up during data source configuration.
|
||||
|
||||
<img style={{ marginBottom:'15px' }} className="screenshot-full img-l" src="/img/development-lifecycle/environments/appbuilder.png" alt="self-hosted-env-concept" />
|
||||
|
|
@ -0,0 +1,76 @@
|
|||
---
|
||||
id: multi-environment
|
||||
title: Multi-Environment
|
||||
---
|
||||
<div className="badge badge--primary heading-badge">
|
||||
<img
|
||||
src="/img/badge-icons/premium.svg"
|
||||
alt="Icon"
|
||||
width="16"
|
||||
height="16"
|
||||
/>
|
||||
<span>Paid feature</span>
|
||||
</div>
|
||||
|
||||
Environments in ToolJet help manage different stages of application development, ensuring smooth transitions between development, testing, and production. This guide covers what environments are, their purpose, and how they function in ToolJet.
|
||||
|
||||
Environments make it easier to develop and deploy applications without disrupting production. They keep changes isolated, so testing and debugging can happen without affecting live users. Teams can collaborate more efficiently, as different environments allow them to work independently.
|
||||
|
||||
### What are Environments?
|
||||
|
||||
An environment in ToolJet represents a separate configuration space where **applications**, **data** **sources**, and **constants** can be defined and managed.
|
||||
|
||||
By default, ToolJet provides three environments:
|
||||
|
||||
- **Development**: The Development environment is where application development and initial testing take place. It is a dedicated space for ToolJet developers to build, configure, and experiment with application features. Changes in this environment do not affect live users, allowing for frequent updates and debugging.
|
||||
|
||||
- **Staging**: The Staging environment acts as a pre-production space where applications undergo thorough testing before deployment. It closely resembles the Production environment and helps ensure that all features, performance, and security aspects function as expected. Teams such as QA and product managers use this environment to validate and approve changes before releasing them to end-users.
|
||||
|
||||
- **Production**: The Production environment is the final, live version of the application where end users interact with it. This environment is stable and optimized for performance after thorough testing in the Development and Staging environments.
|
||||
|
||||
|
||||
### Multi-Environment Support in ToolJet
|
||||
|
||||
ToolJet provides environment management across different components:
|
||||
|
||||
#### Applications
|
||||
|
||||
Each application has development, staging, and production environments. Developers build the application in the development environment and then move it to staging for testing. Your testing team can review the application in staging, and once it's thoroughly tested, you can promote it to production and release it to your end users.
|
||||
|
||||
#### Data Sources
|
||||
|
||||
Data sources can be configured separately for each environment, allowing applications to connect to different databases or APIs depending on the environment. This ensures secure and structured access to relevant data during each stage of development.
|
||||
|
||||
#### Constants
|
||||
|
||||
Constants such as API keys, credentials, or other configuration variables can be defined uniquely for each environment. This helps maintain security and prevents misconfigurations across different deployment stages.
|
||||
|
||||
### Application Life cycle
|
||||
|
||||
The application lifecycle in ToolJet involves managing applications across different environments development, staging, and production. You can build the application in development environment and promote it to staging for testing. After testing you can promote it to production and release the app for your end-users.
|
||||
|
||||
You can configure data sources and constants for each environment, and ToolJet will automatically use the appropriate ones based on the target environment.
|
||||
|
||||
- **Development** – Developers build and test the application in the ToolJet app builder.
|
||||
|
||||
- **Staging** – The testing or product team validates requirements and tests the application using staging data. Apps and queries cannot be edited in this environment.
|
||||
|
||||
- **Production** – After thorough testing in staging, the application is promoted to production. This can serve as a pre-release environment where you test with production data and constants before releasing the application to end users. Refer to [Release](/docs/development-lifecycle/release/release-rollback) documentation to learn more.
|
||||
|
||||
<img className="screenshot-full img-l" src="/img/development-lifecycle/environments/Built-in-env.png" alt="self-hosted-env-concept" />
|
||||
|
||||
|
||||
### Impacted behavior with environment permission
|
||||
|
||||
Each environment has a different impact on your application. Please refer the following table for details.
|
||||
|
||||
| Action | Development | Staging | Production |
|
||||
|--------------------|------------|---------|------------|
|
||||
| Edit versions | ✅ | ❌ | ❌ |
|
||||
| Rename versions | ✅ | ❌ | ❌ |
|
||||
| Delete versions | ✅ | ❌ | ❌ |
|
||||
| Create new versions | ✅ | ❌ | ❌ |
|
||||
| Promote | ✅ | ✅ | - |
|
||||
|
||||
|
||||
Checkout the [Environment-Example](/docs/development-lifecycle/environment/self-hosted/example-configuration) guide to learn about multi-environment in ToolJet with a practical example.
|
||||
|
|
@ -0,0 +1,81 @@
|
|||
---
|
||||
id: example-configuration
|
||||
title: Example Configuration
|
||||
---
|
||||
|
||||
|
||||
In this guide, you'll learn how to migrate applications using GitSync in a multi-instance ToolJet setup through a practical example.
|
||||
|
||||
Vertex Solutions, a company building internal applications with ToolJet, has three ToolJet instances for **development, staging, and production** environments. They have configured Gitsync in all the three instances with GitHub by following the setup instructions given in the [GitSync](/docs/development-lifecycle/gitsync/overview) documentation.
|
||||
|
||||
## Creating the App
|
||||
|
||||
The company wants to create an **Inventory Management System**. A developer starts by clicking **Create New App** on the dashboard. In the modal that appears, they enter the app name and select the **Commit changes** checkbox to save the app to the configured Git repository. Upon clicking **Create App**, the app will be added to your Git repository with a commit message.
|
||||
|
||||
<img style={{ marginBottom:'15px' }} className="screenshot-full img-l" src="/img/development-lifecycle/environments/create-app.png" alt="self-hosted-env-concept" />
|
||||
|
||||
<img style={{ marginBottom:'15px' }} className="screenshot-full img-l" src="/img/development-lifecycle/environments/create-app-github.png" alt="self-hosted-env-concept" />
|
||||
|
||||
- Developers then build the app in the App Builder by dragging and dropping components and adding relevant queries. Once the changes are complete, they can use the GitSync button in the top bar to push a commit to the Git repository.
|
||||
|
||||
<img style={{ marginBottom:'15px' }} className="screenshot-full img-l" src="/img/development-lifecycle/environments/appbuilder-1.png" alt="self-hosted-env-concept" />
|
||||
|
||||
|
||||
- Once committed, the updates appear in the Git repository, showing the commit message, author, and timestamp.
|
||||
<img style={{ marginBottom:'15px' }} className="screenshot-full img-l" src="/img/development-lifecycle/environments/github-2.png" alt="self-hosted-env-concept" />
|
||||
- The development is done and the app is ready to be pulled into the staging instance for testing.
|
||||
|
||||
|
||||
## Importing the App in Staging
|
||||
|
||||
After configuring GitSync for the staging instance with the same Git repository as the development instance, testers can import the app by following these steps:
|
||||
|
||||
- Navigate to the **ToolJet dashboard** of the staging instance.
|
||||
|
||||
- Click on the **three dots** next to the **Create New App** button.
|
||||
- Select **Import from Git Repository** to pull the app.
|
||||
<img className="screenshot-full img-m" src="/img/development-lifecycle/environments/import-1.png" alt="self-hosted-env-concept" />
|
||||
- Choose the app from the dropdown list. The app name and last commit details appear.
|
||||
|
||||
- Click **Import App** to import it into the staging instance.
|
||||
<img style={{ marginBottom:'15px' }} className="screenshot-full img-m" src="/img/development-lifecycle/environments/import-2.png" alt="self-hosted-env-concept" />
|
||||
|
||||
- Once the apps are imported into the staging instance, all data sources are imported as well. However, for security reasons, passwords and secrets in the data source configuration are not included.
|
||||
- To ensure the app functions properly in the staging instance and can be tested with staging data, users must re-enter these details in the configuration.
|
||||
- After adding the data source configuration, testers can verify the app's features and functionality. The app will open in view-only mode.
|
||||
|
||||
### Iterating and Fixing Issues
|
||||
|
||||
If testers find bugs or require modifications, developers create a **new version** in the development instance.
|
||||
|
||||
<img style={{ marginBottom:'15px' }} className="screenshot-full img-l" src="/img/development-lifecycle/environments/iterate-1.png" alt="self-hosted-env-concept" />
|
||||
|
||||
When committing a new version via **GitSync**:
|
||||
|
||||
- The JSON file inside the app folder is updated with the version name.
|
||||
|
||||
- The **meta.json** file in the .meta folder is modified with the new version ID and name.
|
||||
<img style={{ marginBottom:'15px' }} className="screenshot-full img-l" src="/img/development-lifecycle/environments/iterate-github.png" alt="self-hosted-env-concept" />
|
||||
|
||||
After implementing necessary changes, developers commit the updates to the Git repository.
|
||||
|
||||
### Pulling Updates in Staging
|
||||
|
||||
Testers in the **staging instance** update the app by:
|
||||
|
||||
- Clicking the **GitSync** button in the top bar.
|
||||
|
||||
- A modal appears with an option to **Check for Updates**.
|
||||
<img className="screenshot-full img-m" src="/img/development-lifecycle/environments/check-updates.png" alt="self-hosted-env-concept" />
|
||||
|
||||
- Clicking **Check for Updates** fetches the latest changes from the Git repository.
|
||||
|
||||
- Commit details (message, author, date) are displayed.
|
||||
|
||||
- Clicking **Pull Changes** syncs the latest updates into the staging instance.
|
||||
|
||||
<img className="screenshot-full img-m" src="/img/development-lifecycle/environments/update-app.png" alt="self-hosted-env-concept" />
|
||||
|
||||
### Deploying to Production
|
||||
|
||||
Once the application passes testing in staging, it is imported into the **production instance** using the same GitSync process. The application is then released, making it available to end users.
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
---
|
||||
id: instance-as-environment
|
||||
title: Instance as Enviroment
|
||||
---
|
||||
|
||||
|
||||
In this guide, you will learn to manage a Multi-Instance ToolJet deployment. A Multi-Instance setup allows you to deploy multiple isolated ToolJet instances, each functioning as a separate environment, such as development, staging, and production, to support a structured Software Development Life Cycle (SDLC). In this setup each instance operates independently with a strict isolation of resources, users, and applications.
|
||||
|
||||
## Setting Up Multi-Instance Environments
|
||||
|
||||
To enable a multi-instance setup, you need to deploy separate ToolJet instances on your self-hosted infrastructure. Refer to the [setup](/docs/setup/try-tooljet) guide to learn about ToolJet self-hosted deployments.
|
||||
|
||||
## Migrate applications between Instances
|
||||
|
||||
ToolJet’s GitSync feature helps to migrate applications between instances by pushing and pulling changes through a Git repository. It supports Git providers such as GitHub, GitLab, Gitea and Bitbucket. For setup instructions, refer to the [GitSync documentation](/docs/development-lifecycle/gitsync/overview).With GitSync, users can effortlessly transfer applications between instances by committing and pushing changes to a shared repository. This ensures that once an application is developed in development instance, it can be easily synchronized with other instances like staging and production.
|
||||
|
||||
## Pushing and Pulling Apps Between Instances via GitSync
|
||||
|
||||
### Pushing Changes
|
||||
|
||||
GitSync enables users to commit and push updates from your instance to your Git repository. New apps, renames, and version creations are auto-committed and you can also manually commit changes using the GitSync button in the App Builder. Refer to [Push-Gitsync](/docs/development-lifecycle/gitsync/push) doc to learn more.
|
||||
|
||||
### Pulling Changes
|
||||
|
||||
GitSync allows you to pull updates from a Git repository into your instance. You can import apps from Git through the ToolJet dashboard. Once pulled, the app will be in view-only mode. You can also check for updates, which fetches the latest commits with details like author and date. If updates are available, you can pull changes and sync them. Refer to [Pull-Gitsync](/docs/development-lifecycle/gitsync/pull) doc to learn more.Here is the diagram showing how you can use gitsync to migrate your apps across instances.
|
||||
|
||||
<img style={{ marginBottom:'15px' }} className="screenshot-full img-l" src="/img/development-lifecycle/environments/multi-instance.png" alt="self-hosted-env-concept" />
|
||||
|
||||
Checkout the [Multi-Instance-Example](/docs/development-lifecycle/environment/self-hosted/multi-instance/example-configuration) guide to learn how to use GitSync for multi-instance setup in ToolJet with a practical example.
|
||||
24
docs/docs/development-lifecycle/gitsync/delete-gitsync.md
Normal file
24
docs/docs/development-lifecycle/gitsync/delete-gitsync.md
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
---
|
||||
id: delete-gitsync
|
||||
title: Delete GitSync Configuration
|
||||
---
|
||||
|
||||
In ToolJet, GitSync can be enabled, disabled, or deleted based on your requirements.
|
||||
|
||||
- **Enabled**: When GitSync is enabled the users will be able to commit changes to the git repository.
|
||||
- **Disabled**:
|
||||
- **Non-Admin Users**: The users will not be able to commit changes to the git repository. They will see a dialogue box that the GitSync feature is not configured and they need to contact the admin to configure it.
|
||||
- **For admin users**: The users will see a dialogue box with a link to configure the GitSync feature.
|
||||
- **Delete GitSync Configuration**: Deleting the GitSync configuration will not delete the apps from the git repository. The apps will still be available in the git repository in the same state as they were before the GitSync configuration was deleted.
|
||||
|
||||
## Enable/Disable GitSync
|
||||
|
||||
To enable or disable the GitSync feature, go to the **Configure git** tab on the **Workspace settings** page, and toggle on/off the **Connect** switch. This is only available if the GitSync feature is configured.
|
||||
|
||||
<img className="screenshot-full" src="/img/development-lifecycle/gitsync/delete/connection.png" alt="GitSync" />
|
||||
|
||||
## Delete GitSync Configuration
|
||||
|
||||
To delete the GitSync configuration, go to the **Configure git** tab on the **Workspace settings** page, and click on the **Delete configuration** button. This will delete the SSH key from the ToolJet configuration and the GitSync feature will be disabled.
|
||||
|
||||
<img className="screenshot-full" src="/img/development-lifecycle/gitsync/delete/delete.png" alt="GitSync" />
|
||||
72
docs/docs/development-lifecycle/gitsync/gitsync-config.md
Normal file
72
docs/docs/development-lifecycle/gitsync/gitsync-config.md
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
---
|
||||
id: gitsync-config
|
||||
title: Configure GitSync
|
||||
---
|
||||
|
||||
In this guide, we will explore how to configure GitSync using GitHub as the repository manager. By default GitSync is configured for the **master** branch, but this can be configured to a different branch as well, refer to **[Configuring GitSync on a Different Branch](#configuring-gitsync-on-a-different-branch)** section for more information.
|
||||
|
||||
For more information on using other repository managers, such as GitLab or Gitea, refer to the **[SSH Configuration for Git Repo Manager](/docs/development-lifecycle/gitsync/ssh-config)** guide.
|
||||
|
||||
## Setting up GitSync in ToolJet
|
||||
|
||||
Role Required: **Admin**
|
||||
|
||||
1. **Create a New Repository** <br/>
|
||||
Create a new repository on your GitHub. The repository can be public or private. You can also use an existing repository. Make sure that the repository is empty.
|
||||
<img className="screenshot-full img-l" src="/img/development-lifecycle/gitsync/config/new-repo.png" alt="GitSync" />
|
||||
|
||||
2. **Obtain the SSH URL** <br/>
|
||||
When a repository is created, GitHub shows a screen with the SSH URL.
|
||||
<img className="screenshot-full" src="/img/development-lifecycle/gitsync/config/ssh.png" alt="GitSync" />
|
||||
|
||||
OR
|
||||
|
||||
If you are using an existing repository, then you can obtain the URL by clicking on the **Code** button.
|
||||
<img className="screenshot-full" src="/img/development-lifecycle/gitsync/config/ssh-code.png" alt="GitSync" />
|
||||
|
||||
To generate the SSH URL for other git repository manager, such as GitLab and Gitea, follow the **[SSH Configuration](/docs/development-lifecycle/gitsync/ssh-config#generating-ssh-url)** guide.
|
||||
|
||||
3. Go to the **Workspace settings**, and click on the **Configure git** tab. <br/>
|
||||
(Example URL - `https://app.corp.com/nexus/workspace-settings/configure-git`)
|
||||
|
||||
<img style={{ marginBottom:'15px' }} className="screenshot-full" src="/img/gitsync/gitsync-v3.png" alt="GitLab Repo" />
|
||||
|
||||
4. Enter the **SSH URL** of the repository in the **Git repo URL** field.
|
||||
|
||||
5. Click on the **Generate SSH key** button, and copy the SSH key that is generated. The SSH key is used to authenticate ToolJet with the repository.
|
||||
|
||||
<img className="screenshot-full" src="/img/development-lifecycle/gitsync/config/generate-ssh.png" alt="GitSync" />
|
||||
|
||||
There are two types of generated SSH keys:
|
||||
- **ED25519**: This is a secure and efficient algorithm that is used for generating SSH keys. It is recommended to use this key type. VCS providers like GitHub and GitLab recommend using this key type
|
||||
- **RSA**: This is an older algorithm that is used for generating SSH keys. It is not recommended to use this key type. Providers like Bitbucket recommend using this key type. <br/> <br/>
|
||||
|
||||
<img className="screenshot-full" src="/img/development-lifecycle/gitsync/config/ssh-key.png" alt="GitSync" />
|
||||
|
||||
6. Go to the **Settings** tab of the GitHub repository, and click on the **Deploy keys** tab. Click on the **Add deploy key** button.
|
||||
<img className="screenshot-full" src="/img/development-lifecycle/gitsync/config/deploy-ssh.png" alt="GitSync" />
|
||||
|
||||
7. Enter a title for the SSH key in the **Title** field.
|
||||
|
||||
8. Paste the SSH key generated from the ToolJet.
|
||||
|
||||
9. Make sure that the **Allow write access** checkbox is checked, especially when configuring the GitSync feature to [push changes to Git](/docs/development-lifecycle/gitsync/push). However, it is not mandatory to check this option when setting up the GitSync feature for [pulling changes from Git](/docs/development-lifecycle/gitsync/pull).
|
||||
|
||||
10. Finally, click on the **Add key** button.
|
||||
<img className="screenshot-full" src="/img/development-lifecycle/gitsync/config/add-key.png" alt="GitSync" />
|
||||
|
||||
To deploy the SSH key for other git repository manager, such as GitLab and Gitea, follow the **[SSH Configuration](/docs/development-lifecycle/gitsync/ssh-config#deploy-the-ssh-key)** guide.
|
||||
|
||||
11. After deploying the SSH Key, go to the **Configure git** tab on ToolJet, and click on the **Finalize setup** button. If the SSH key is configured correctly, you will see a success message.
|
||||
<img className="screenshot-full" src="/img/development-lifecycle/gitsync/config/save-config.png" alt="GitSync" />
|
||||
|
||||
## Configuring GitSync on a Different Branch
|
||||
|
||||
Starting from version **v3.5.3-ee-lts**, GitSync in ToolJet supports custom branches. This feature is available only in the Self-Hosted version of ToolJet. The custom branch for GitSync is configured at the instance level via an environment variable.
|
||||
|
||||
Different repositories can be configured for different workspaces, but the custom branch set in the **.env** file must be present in all configured repositories to ensure smooth operation. The branch specified in the **.env** file will apply to all workspaces with GitSync support.
|
||||
|
||||
To configure a custom branch for GitSync, you need to set the following environment variable in your **.env** file: <br/>
|
||||
`GITSYNC_TARGET_BRANCH` = **branch-name**
|
||||
|
||||
**Note:** **Existing GitSync users** who want to use a custom Git branch must first create a new custom branch from the master branch in the Git repository manager. Then, they must configure the branch name in the **.env** file to ensure all operations work smoothly.
|
||||
26
docs/docs/development-lifecycle/gitsync/overview.md
Normal file
26
docs/docs/development-lifecycle/gitsync/overview.md
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
---
|
||||
id: overview
|
||||
title: GitSync Overview
|
||||
---
|
||||
|
||||
<div className="badge badge--primary heading-badge">
|
||||
<img
|
||||
src="/img/badge-icons/premium.svg"
|
||||
alt="Icon"
|
||||
width="16"
|
||||
height="16"
|
||||
/>
|
||||
<span>Paid feature</span>
|
||||
</div>
|
||||
|
||||
The GitSync feature in ToolJet allows seamless synchronization of workspace applications with a Git repository, enhancing version control, environment migration, and backup management. It supports both cloud-based and self-hosted Git providers offering flexibility in managing application development and deployment. GitSync can also be configured for a custom branch. Refer to **[Configure GitSync](/docs/development-lifecycle/gitsync/gitsync-config)** guide for more information.
|
||||
|
||||
## Key Use-Cases
|
||||
|
||||
### Application Migration
|
||||
|
||||
GitSync can be used to facilitate the movement of application across different ToolJet instances such as from development to staging to production. Users can effortlessly transfer their applications across instances by pushing changes to a Git repository. This means that once an application is developed in one instance, it can be easily moved to another by simply syncing with the repository, ensuring a smooth transition without the need for manual configurations. Refer to the **[multi-instance](/docs/development-lifecycle/gitsync/gitsync-config)** guide for detailed steps.
|
||||
|
||||
### Backup of Apps
|
||||
|
||||
GitSync provides a straightforward solution for creating backups of your applications. By pushing changes to a Git repository, users can ensure a secure and versioned history of their application. This serves as a reliable backup mechanism, safeguarding against accidental application/version deletion or corruption. Refer to **[GitSync Backup](/docs/development-lifecycle/backup/gitsync-backup)** guide for more information.
|
||||
34
docs/docs/development-lifecycle/gitsync/pull.md
Normal file
34
docs/docs/development-lifecycle/gitsync/pull.md
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
---
|
||||
id: pull
|
||||
title: Pull Changes from Git Repo
|
||||
---
|
||||
|
||||
Once the GitSync is configured and the changes are committed to the git repository, after that the changes can be pulled from the git repository to restore the application or to use multi instance as multi environment.
|
||||
|
||||
## Restore Application
|
||||
|
||||
To restore an application from a git repository, click on the kebab menu (three dots) on the right side of the **Create new app** button on the dashboard. Click on the **Import from git repository** option.
|
||||
|
||||
<img style={{ marginBottom:'15px' }} className="screenshot-full" src="/img/gitsync/restore-app.png" alt="GitSync" />
|
||||
|
||||
On clicking the **Import from git repository** option, a modal will open with the dropdown to select the app to be imported from the git repository. Once the app is selected, the app name and the last commit will be displayed. Click on the **Import app** button to import the app from the git repository.
|
||||
|
||||
<img style={{ marginBottom:'15px' }} className="screenshot-full" src="/img/gitsync/importmodal-v2.png" alt="GitSync" />
|
||||
|
||||
**Note**:
|
||||
- The app imported from the git repository cannot be edited. To edit the application, you will need to clone it.
|
||||
- The app imported from the Git repository should have a unique name. If the app's name is the same as that of an existing app in the workspace, the user will need to either rename the existing app or delete it to successfully import another app with the same name.
|
||||
- Workspace constants are not synced with the git repository. After pulling the app, if the app throws an error, the user will need to manually add the workspace constants.
|
||||
|
||||
## Pull Changes
|
||||
|
||||
You can check for updates and pull changes from the git repository by following these steps:
|
||||
|
||||
1. Click on the **GitSync** button, a modal will open with the option to **Check for updates**.
|
||||
|
||||
2. Click on the **Check for updates** button to check for updates in the git repository. If there are any updates, you will see the details of the updates such as commit message, author, and the date in the modal.
|
||||
|
||||
3. Click on the **Pull changes** button to pull the changes from the git repository.
|
||||
|
||||
<img className="screenshot-full" src="/img/gitsync/updatecheck.png" alt="GitSync" />
|
||||
|
||||
134
docs/docs/development-lifecycle/gitsync/push.md
Normal file
134
docs/docs/development-lifecycle/gitsync/push.md
Normal file
|
|
@ -0,0 +1,134 @@
|
|||
---
|
||||
id: push
|
||||
title: Push Changes to Git Repo
|
||||
---
|
||||
|
||||
import Tabs from '@theme/Tabs';
|
||||
import TabItem from '@theme/TabItem';
|
||||
|
||||
Once the GitSync feature is configured, you can start pushing changes to the git repository on following points:
|
||||
|
||||
- [App Creation](#app-creation)
|
||||
- [Manual Commit Using GitSync Button](#manual-commit-using-gitsync-button)
|
||||
- [Auto Commit on App Rename](#auto-commit-on-app-rename)
|
||||
- [App Version Update](#app-version-update)
|
||||
- [Auto Commit on Promoting Environment](#auto-commit-on-promoting-environment)
|
||||
- [App Deletion](#app-deletion)
|
||||
|
||||
## App Creation
|
||||
|
||||
Whenever you create a new app, you will see an option to select the **Commit changes**. If you select the **commit changes** option, the changes will be committed to the git repository.
|
||||
|
||||
**Note**: If the app name is same as the name of an existing app in the git repo, it will overwrite the existing app in the git repo.
|
||||
|
||||
<img style={{ marginBottom:'15px' }} className="screenshot-full" src="/img/gitsync/commitchanges.png" alt="GitLab SSH Key" />
|
||||
|
||||
Selecting the **Commit changes** option will create a new commit in the git repository. The commit message will be `App creation` and the author will be the user who created the app.
|
||||
|
||||
During app creation, a **.meta** folder is generated, containing a **meta.json** file with details of the last commit. Then, an app folder is also created, storing **v1.json**, which holds app-specific details of v1 version.
|
||||
|
||||
<Tabs>
|
||||
|
||||
<TabItem value="GitHub" label="GitHub">
|
||||
|
||||
<img className="screenshot-full" src="/img/gitsync/firstcommit.png" alt="GitSync" />
|
||||
|
||||
</TabItem>
|
||||
|
||||
<TabItem value="GitLab" label="GitLab">
|
||||
|
||||
<img className="screenshot-full" src="/img/gitsync/gitlab/author.png" alt="GitSync" />
|
||||
|
||||
</TabItem>
|
||||
|
||||
</Tabs>
|
||||
|
||||
## Manual Commit Using GitSync Button
|
||||
|
||||
Whenever a user makes a change in an app, they can make a commit to the git repository by following these steps:
|
||||
|
||||
1. After making the changes, click on the **GitSync** button on the topbar.
|
||||
<img className="screenshot-full" src="/img/development-lifecycle/backup/gitsync/gitsync-button.png" alt="GitSync Button" />
|
||||
|
||||
2. On clicking the **GitSync** button, a modal will open with the option to enter the commit message.
|
||||
<img className="screenshot-full" src="/img/development-lifecycle/backup/gitsync/commit-message.png" alt="GitSync Commit Message" />
|
||||
|
||||
3. Enter the commit message and click on the **Commit changes** button to commit the changes to the git repository.
|
||||
|
||||
Along with the commit message, the user can also see the connected **Git repo URL** and the last commit details. **Last commit details** helps the user to know the last commit message, author, date, and time. This helps the user to know the last commit details and make the commit message accordingly.
|
||||
|
||||
Once the changes are committed, the user can see the commit message, author, and date in the git repository.
|
||||
|
||||
<Tabs>
|
||||
|
||||
<TabItem value="GitHub" label="GitHub">
|
||||
|
||||
<img className="screenshot-full" src="/img/development-lifecycle/backup/gitsync/github-commit.png" alt="GitSync" />
|
||||
|
||||
</TabItem>
|
||||
|
||||
<TabItem value="GitLab" label="GitLab">
|
||||
|
||||
<img className="screenshot-full" src="/img/gitsync/gitlab/lastcommitmsg.png" alt="GitSync" />
|
||||
|
||||
</TabItem>
|
||||
|
||||
</Tabs>
|
||||
|
||||
## Auto Commit on App Rename
|
||||
|
||||
Whenever an app is renamed, the changes will be automatically committed to the git repository. The commit message will be `App is renamed` and the author will be the user who renamed the app. Similarly an auto commit is generated whenever the version is renamed.
|
||||
|
||||
<Tabs>
|
||||
|
||||
<TabItem value="GitHub" label="GitHub">
|
||||
|
||||
<img className="screenshot-full" src="/img/gitsync/rename.png" alt="GitSync" />
|
||||
|
||||
</TabItem>
|
||||
|
||||
<TabItem value="GitLab" label="GitLab">
|
||||
|
||||
<img className="screenshot-full" src="/img/gitsync/gitlab/apprename.png" alt="GitSync" />
|
||||
|
||||
</TabItem>
|
||||
|
||||
</Tabs>
|
||||
|
||||
## App Version Update
|
||||
|
||||
Whenever a user creates a new version of an app, there will be an option to select **Commit changes**. If the user selects **commit changes** option, the new version of the app will be committed to the git repository and the old version will be overridden.
|
||||
|
||||
<img style={{ marginBottom:'15px' }} className="screenshot-full" src="/img/gitsync/gitlab/newversion.png" alt="GitLab SSH Key" />
|
||||
|
||||
The **JSON** file in the app folder will be replaced with the new version of the app, the **meta.json** file in the **.meta** folder gets updated with the new version id and version name. The commit message will be **Version creation** and the author will be the user who created the new version of the app.
|
||||
|
||||
<Tabs>
|
||||
|
||||
<TabItem value="GitHub" label="GitHub">
|
||||
|
||||
<img className="screenshot-full" src="/img/gitsync/replace.png" alt="GitSync" />
|
||||
|
||||
</TabItem>
|
||||
|
||||
<TabItem value="GitLab" label="GitLab">
|
||||
|
||||
<img className="screenshot-full" src="/img/gitsync/gitlab/newversion1.png" alt="GitSync" />
|
||||
|
||||
</TabItem>
|
||||
|
||||
</Tabs>
|
||||
|
||||
## Auto Commit on Promoting Environment
|
||||
|
||||
When you promote an environment, from **Development to Staging**, the changes will be automatically committed to the git repository. The commit message will be `<version_number> Version of <app_name> promoted from <source_environment> to <destination_environment>`. The author will be the user who promoted the environment. When you promote an environment, from **Staging to Production**, no changes will be committed to the git repository.
|
||||
|
||||
<img style={{ marginBottom:'15px' }} className="screenshot-full" src="/img/gitsync/promoted.png" alt="GitSync" />
|
||||
|
||||
This option can be enabled or disabled from the **Configure git** tab on the **Workspace settings** page. By default, this option is disabled.
|
||||
|
||||
<img className="screenshot-full" src="/img/gitsync/autocommit-v2.png" alt="GitSync" />
|
||||
|
||||
## App Deletion
|
||||
|
||||
Whenever a user delete an app from the workspace, the app will not be deleted from the git repository. The app will be available in the git repository in the same state as it was before the app was deleted.
|
||||
119
docs/docs/development-lifecycle/gitsync/ssh-config.md
Normal file
119
docs/docs/development-lifecycle/gitsync/ssh-config.md
Normal file
|
|
@ -0,0 +1,119 @@
|
|||
---
|
||||
id: ssh-config
|
||||
title: SSH Configuration for Git Repo Manager
|
||||
---
|
||||
|
||||
To configure a Git Manager with ToolJet using GitSync, you need the SSH URL from the Git Manager and then deploy the SSH key generated by ToolJet. You can use any Git Manager (cloud-based or self-hosted) that follows standard Git protocols. In this guide, we will cover the configuration for GitHub, GitLab, and Gitea.
|
||||
|
||||
## Generating SSH URL
|
||||
|
||||
### GitHub
|
||||
|
||||
1. **Create a New Repository** <br/>
|
||||
Create a new repository on your GitHub. The repository can be public or private. You can also use an existing repository. Make sure that the repository is empty and the default branch name should be **master**.
|
||||
<img className="screenshot-full img-l" src="/img/development-lifecycle/gitsync/config/new-repo.png" alt="GitSync" />
|
||||
|
||||
2. **Obtain the SSH URL** <br/>
|
||||
When a repository is created, GitHub shows a screen with the SSH URL.
|
||||
<img className="screenshot-full" src="/img/development-lifecycle/gitsync/config/ssh.png" alt="GitSync" />
|
||||
|
||||
OR
|
||||
|
||||
If you are using an existing repository, then you can obtain the URL by clicking on the **Code** button.
|
||||
<img className="screenshot-full" src="/img/development-lifecycle/gitsync/config/ssh-code.png" alt="GitSync" />
|
||||
|
||||
### GitLab
|
||||
|
||||
1. **Create a New Repository** <br/>
|
||||
Create a new repository on your GitLab. The repository can be public or private. You can also use an existing repository. Make sure that the repository is empty and the default branch name should be **master**.
|
||||
<img className="screenshot-full" src="/img/gitsync/gitlab/repo.png" alt="GitSync" />
|
||||
|
||||
2. **Obtain the SSH URL** <br/>
|
||||
On GitLab, you can obtain the URL by clicking on the **Clone** button and selecting the **SSH** option.
|
||||
<img className="screenshot-full" src="/img/gitsync/gitlab/gitlabssh.png" alt="GitSync" />
|
||||
|
||||
### Gitea
|
||||
|
||||
1. **Create a New Repository** <br/>
|
||||
Create a new repository on your Gitea. You can also use an existing repository. Make sure that the repository is empty and the default branch name should be **master**.
|
||||
<img className="screenshot-full" src="/img/gitsync/gitea/new-repo.png" alt="GitSync" />
|
||||
|
||||
2. **Obtain the SSH URL** <br/>
|
||||
When a repository is created, Gitea shows a screen with the SSH URL.
|
||||
<img className="screenshot-full" src="/img/gitsync/gitea/ssh-url.png" alt="GitSync" />
|
||||
|
||||
|
||||
## Deploy the SSH Key
|
||||
|
||||
### GitHub
|
||||
|
||||
1. Go to the **Settings** tab of the GitHub repository, and click on the **Deploy keys** tab. Click on the **Add deploy key** button.
|
||||
<img className="screenshot-full" src="/img/development-lifecycle/gitsync/config/deploy-ssh.png" alt="GitSync" />
|
||||
|
||||
2. Enter a title for the SSH key in the **Title** field.
|
||||
|
||||
3. Paste the SSH key generated from the ToolJet.
|
||||
|
||||
4. Make sure that the **Allow write access** checkbox is checked, especially when configuring the GitSync feature to [push changes to Git](/docs/development-lifecycle/gitsync/push). However, it is not mandatory to check this option when setting up the GitSync feature for [pulling changes from Git](/docs/development-lifecycle/gitsync/pull).
|
||||
|
||||
5. Finally, click on the **Add key** button.
|
||||
<img className="screenshot-full" src="/img/development-lifecycle/gitsync/config/add-key.png" alt="GitSync" />
|
||||
|
||||
### GitLab
|
||||
|
||||
You have two options for adding the SSH key to GitLab, you can either add it globally to access all your repositories or deploy it for a specific repository.
|
||||
|
||||
#### Option 1: Add as a User-Wide SSH Key
|
||||
|
||||
Use this option for access to all your repositories.
|
||||
|
||||
1. Click on your avatar in the top-left corner and select **Edit Profile**.
|
||||
|
||||
2. Navigate to the **SSH Keys** tab and click the **Add new key** button.
|
||||
<img className="screenshot-full" src="/img/gitsync/gitlab/addingssh.png" alt="GitLab SSH Key" />
|
||||
|
||||
3. In the **Key** field, paste the SSH key you generated from the ToolJet.
|
||||
|
||||
4. Give your key a descriptive title.
|
||||
|
||||
5. Set **Usage type** to **Authentication & signing**.
|
||||
|
||||
6. Optionally, set an expiration date.
|
||||
|
||||
7. Click **Add key** to save.
|
||||
<img style={{marginBottom:'15px'}} className="screenshot-full" src="/img/gitsync/gitlab/activessh.png" alt="GitLab SSH Key" />
|
||||
|
||||
#### Option 2: Add as a Deploy Key
|
||||
|
||||
Use this option for access to a specific repository only.
|
||||
|
||||
1. Navigate to the repository you want to add the key to.
|
||||
|
||||
2. Click on the **Settings** tab and select **Repository**.
|
||||
|
||||
3. Once you are in the **Repository Settings**, expand the **Deploy Keys** section.
|
||||
|
||||
4. Click on the **Add new deploy key** button.
|
||||
|
||||
5. Give your key a descriptive title.
|
||||
|
||||
6. In the **Key** field, paste the SSH key you generated in ToolJet's Configure Git tab during the previous step.
|
||||
|
||||
7. Enable the **Grant write permissions to this key** checkbox. We need this permission to push changes to the repository.
|
||||
|
||||
8. Click **Add key** to save.
|
||||
<img className="screenshot-full" src="/img/gitsync/gitlab/deploy-keys.png" alt="GitLab Deploy Key" />
|
||||
|
||||
### Gitea
|
||||
|
||||
1. Go to the **Settings** tab of the Gitea repository, and click on the **Deploy keys** tab. Click on the **Add deploy key** button.
|
||||
<img className="screenshot-full" src="/img/gitsync/gitea/deploy-ssh.png" alt="GitSync" />
|
||||
|
||||
2. Enter a title for the SSH key in the **Title** field.
|
||||
|
||||
3. Paste the SSH key generated from the ToolJet.
|
||||
|
||||
4. Make sure that the **Allow write access** checkbox is checked, especially when configuring the GitSync feature to [push changes to Git](/docs/development-lifecycle/gitsync/push). However, it is not mandatory to check this option when setting up the GitSync feature for [pulling changes from Git](/docs/development-lifecycle/gitsync/pull).
|
||||
|
||||
5. Finally, click on the **Add Deploy key** button.
|
||||
<img className="screenshot-full" src="/img/gitsync/gitea/final.png" alt="GitSync" />
|
||||
27
docs/docs/development-lifecycle/overview.md
Normal file
27
docs/docs/development-lifecycle/overview.md
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
---
|
||||
id: overview
|
||||
title: Overview
|
||||
---
|
||||
|
||||
This guide outlines the development life cycle for ToolJet deployments, explaining its importance and how ToolJet manages it efficiently.
|
||||
|
||||
A development life cycle (also known as the software development life cycle or SDLC) is a structured framework that ensures software is built, deployed, and maintained efficiently. It helps teams manage changes, collaborate effectively, and maintain stability in production environments. A well-defined development life cycle enhances software quality, improves efficiency, facilitates better collaboration between teams, reduces costs by catching issues early, and ensures long-term maintainability.
|
||||
|
||||
## Development Life Cycle in ToolJet
|
||||
|
||||
ToolJet enables teams to manage application changes and deployments effectively through its Environment and Version Management system. Key aspects of managing the development life cycle in ToolJet include:
|
||||
|
||||
### Release Management
|
||||
|
||||
Using ToolJet's release management, you can create multiple **[versions](/docs/development-lifecycle/release/version-control)** of your application and easily **[release](/docs/development-lifecycle/release/release-rollback)** the latest version with new features, fixes, and enhancements. ToolJet also enables you to **[roll back](#)** to a previous stable version if needed. Additionally, ToolJet lets you **[share your application](/docs/development-lifecycle/release/share-app)** in multiple ways.
|
||||
|
||||
### GitSync
|
||||
|
||||
In ToolJet, you can use **[GitSync](/docs/development-lifecycle/gitsync/overview)** to maintain a history and **[backup](/docs/development-lifecycle/backup/gitsync-backup)** of your application. By integrating with Git repositories, you can ensure that your application remains secure, organized, and easily manageable over time.
|
||||
|
||||
### Environment Management
|
||||
ToolJet comes with three predefined environments: **development, staging, and production**. These environments apply to applications, data sources, and constants, ensuring controlled testing before deployment.For more details, refer to the [Environments Documentation](/docs/development-lifecycle/environment/self-hosted/multi-environment)
|
||||
|
||||
|
||||
### Multi-Instance Environments
|
||||
You can deploy multiple ToolJet instances where each acts as a different environment. This setup isolates all resources as well as users across the instances. For more details, refer to the [Multi-Instance Environments](/docs/development-lifecycle/environment/self-hosted/multi-instance/instance-as-environment) Documentation.
|
||||
39
docs/docs/development-lifecycle/release/release-rollback.md
Normal file
39
docs/docs/development-lifecycle/release/release-rollback.md
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
---
|
||||
id: release-rollback
|
||||
title: Release and Rollback
|
||||
---
|
||||
|
||||
ToolJet allows you to **[release and share](#release)** your application and **[rollback](#rollback)** to a stable version whenever needed.
|
||||
|
||||
## Release
|
||||
|
||||
Releasing an app in ToolJet makes the selected version available to end users, allowing them to access and use the application for their tasks. This ensures a controlled rollout of features and bug fixes while ensuring that users have access to the latest version of the app. After an application is released it can be accessed in multiple ways, refer to **[Share an Application](/docs/development-lifecycle/release/share-app)** guide for more information.
|
||||
|
||||
### Steps to Release an App
|
||||
|
||||
1. Promote the required version to the **[production environment](/docs/development-lifecycle/environment/self-hosted/multi-environment)**.
|
||||
|
||||
2. Click on the Release button at the top-right corner.
|
||||
<img className="screenshot-full" src="/img/development-lifecycle/release/release/release.png" alt="release"/>
|
||||
|
||||
3. A confirmation dialog will popup that prompts you to decide whether to release the current version of the app. Clicking on the **Release** button will release the current version of the app.
|
||||
<img className="screenshot-full img-s" src="/img/development-lifecycle/release/release/confirm.png" alt="release"/>
|
||||
|
||||
## Rollback
|
||||
|
||||
The Rollback feature in ToolJet allows you to revert to a previously stable version of your app whenever needed. Whether fixing bugs, resolving errors, or addressing unexpected issues after a release, rollback ensures minimal disruption to end users. It instantly restores a prior version while keeping the application's URL the same, allowing the team to maintain application stability while debugging the faulty version offline.
|
||||
|
||||
For example, after releasing a new version v1.2.0, users report failures of the form component. Using ToolJet’s version rollback, the team can quickly rollback to the stable version v1.1.0, restoring functionality within minutes. This minimizes downtime, and allows developers to debug the faulty version offline.
|
||||
|
||||
### Steps to Rollback
|
||||
|
||||
1. Go to the **App Version Manager** from the toolbar and click on the dropdown. It will display all the available versions of the app. The released version name will be in green color.
|
||||
<img className="screenshot-full" src="/img/development-lifecycle/release/version-control/version-menu.png" alt="app version"/>
|
||||
|
||||
2. Choose the desired stable version from the dropdown.
|
||||
|
||||
3. Click on the Release button at the top-right corner.
|
||||
<img className="screenshot-full" src="/img/development-lifecycle/release/release/release.png" alt="release"/>
|
||||
|
||||
4. A confirmation dialog will popup that prompts you to decide whether to release the current version of the app. Clicking on the **Release** button will release the current version of the app.
|
||||
<img className="screenshot-full img-s" src="/img/development-lifecycle/release/release/confirm.png" alt="release"/>
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue