Merge branch 'ToolJet:develop' into develop

This commit is contained in:
Aditya Aryaman Das 2023-10-21 23:27:40 +05:30 committed by GitHub
commit fc60b423e5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
395 changed files with 65508 additions and 7540 deletions

View file

@ -144,7 +144,7 @@ jobs:
run: docker buildx use mybuilder
- name: Build docker image
run: docker buildx build --platform=linux/amd64 -f docker/production.Dockerfile . -t tooljet/tj-osv:cypress
run: docker buildx build --platform=linux/amd64 -f docker/production.Dockerfile . -t tooljet/tj-osv:cypressplaform
- name: Set up environment variables
run: |
@ -191,6 +191,9 @@ jobs:
sleep 5
done'
- name: Seeding
run: docker exec Tooljet-app npm run db:seed:prod
- name: Create Cypress environment file
id: create-json
uses: jsdaniell/create-json@1.1.2

View file

@ -38,7 +38,7 @@ jobs:
run: docker buildx use mybuilder
- name: Build docker image
run: docker buildx build --platform=linux/amd64 -f docker/production.Dockerfile . -t tooljet/tj-osv:cypress
run: docker buildx build --platform=linux/amd64 -f docker/production.Dockerfile . -t tooljet/tj-osv:cypressplaform
- name: Set up environment variables
run: |
@ -82,6 +82,9 @@ jobs:
sleep 5
done'
- name: Seeding
run: docker exec Tooljet-app npm run db:seed:prod
- name: Create Cypress environment file
id: create-json
uses: jsdaniell/create-json@1.1.2
@ -131,7 +134,7 @@ jobs:
run: docker buildx use mybuilder
- name: Build docker image
run: docker buildx build --platform=linux/amd64 -f docker/production.Dockerfile . -t tooljet/tj-osv:cypress
run: docker buildx build --platform=linux/amd64 -f docker/production.Dockerfile . -t tooljet/tj-osv:cypressplaform
- name: Set up environment variables
run: |
@ -178,6 +181,9 @@ jobs:
sleep 5
done'
- name: Seeding
run: docker exec Tooljet-app npm run db:seed:prod
- name: Create Cypress environment file
id: create-json
uses: jsdaniell/create-json@1.1.2

View file

@ -148,7 +148,7 @@ jobs:
run: docker buildx use mybuilder
- name: Build docker image
run: docker buildx build --platform=linux/amd64 -f docker/production.Dockerfile . -t tooljet/tj-osv:cypress
run: docker buildx build --platform=linux/amd64 -f docker/production.Dockerfile . -t tooljet/tj-osv:cypressplaform
- name: Set up environment variables
run: |
@ -195,6 +195,9 @@ jobs:
sleep 5
done'
- name: Seeding
run: docker exec Tooljet-app npm run db:seed:prod
- name: Create Cypress environment file
id: create-json
uses: jsdaniell/create-json@1.1.2

View file

@ -1 +1 @@
2.21.0
2.22.0

View file

@ -83,7 +83,7 @@ module.exports = defineConfig({
"cypress/e2e/editor/app-version/version.cy.js"
],
numTestsKeptInMemory: 1,
redirectionLimit: 7,
redirectionLimit: 15,
experimentalRunAllSpecs: true,
experimentalMemoryManagement: true,
video: false,

View file

@ -79,8 +79,8 @@ module.exports = defineConfig({
baseUrl: "http://localhost:8082",
specPattern: "cypress/e2e/**/*.cy.js",
downloadsFolder: "cypress/downloads",
numTestsKeptInMemory: 10,
redirectionLimit: 5,
numTestsKeptInMemory: 0,
redirectionLimit: 7,
experimentalRunAllSpecs: true,
trashAssetsBeforeRuns: true,
experimentalMemoryManagement: true,

View file

@ -1,6 +1,10 @@
Cypress.Commands.add(
"apiLogin",
(userEmail = "dev@tooljet.io", userPassword = "password", workspaceId = '') => {
(
userEmail = "dev@tooljet.io",
userPassword = "password",
workspaceId = ""
) => {
cy.request({
url: `http://localhost:3000/api/authenticate/${workspaceId}`,
method: "POST",
@ -138,4 +142,24 @@ Cypress.Commands.add(
// ]
// );
Cypress.Commands.add("apiCreateWorkspace", (workspaceName, workspaceSlug) => {
cy.getCookie("tj_auth_token").then((cookie) => {
cy.request(
{
method: "POST",
url: "http://localhost:3000/api/organizations",
headers: {
"Tj-Workspace-Id": Cypress.env("workspaceId"),
Cookie: `tj_auth_token=${cookie.value}`,
},
body: {
name: workspaceName,
slug: workspaceSlug,
},
},
{ log: false }
).then((response) => {
expect(response.status).to.equal(201);
});
});
});

View file

@ -327,10 +327,10 @@ export const commonWidgetSelector = {
modalHeader: '[data-cy="modal-header"]',
makePublicAppToggleLabel: '[data-cy="make-public-app-label"]',
shareableAppLink: '[data-cy="shareable-app-link-label"]',
copyAppLinkButton: '[data-cy="copy-app-link-button"]',
// iframeLinkLabel: '[data-cy="iframe-link-label"]',
// ifameLinkCopyButton: '[data-cy="iframe-link-copy-button"]',
},
copyAppLinkButton: '.input-group > :nth-child(3)',
makePublicAppToggle: '[data-cy="make-public-app-toggle"]',
appLink: '[data-cy="app-link"]',
appNameSlugInput: '[data-cy="app-name-slug-input"]',

View file

@ -164,9 +164,8 @@ export const commonText = {
shareModalElements: {
modalHeader: "Share",
makePublicAppToggleLabel: "Make application public?",
shareableAppLink: "Get shareable link for this application",
copyAppLinkButton: "copy",
makePublicAppToggleLabel: "Make application public",
shareableAppLink: "Shareable app link",
// iframeLinkLabel: "Get embeddable link for this application",
// ifameLinkCopyButton: "copy",
},

View file

@ -20,5 +20,5 @@ export const exportAppModalText = {
export const importText = {
importOption: "Import",
couldNotImportAppToastMessage: `Could not import: SyntaxError: Unexpected token`,
appImportedToastMessage: "Imported successfully.",
appImportedToastMessage: "App imported successfully.",
};

View file

@ -19,17 +19,16 @@ import {
} from "Texts/common";
describe("Editor- Global Settings", () => {
const data = {};
beforeEach(() => {
data.appName = `${fake.companyName}-App`;
cy.apiLogin();
cy.apiCreateApp();
cy.apiCreateApp(data.appName);
cy.openApp();
});
it("should verify global settings", () => {
const data = {};
data.backgroundColor = fake.randomRgba;
data.appName = `${fake.companyName}-App`;
cy.renameApp(data.appName);
cy.get("[data-cy='left-sidebar-settings-button']").click();
cy.get('[data-cy="label-global settings"]').verifyVisibleElement(

View file

@ -1,3 +1,4 @@
import { fake } from "Fixtures/fake";
import {
verifyMultipleComponentValuesFromInspector,
verifyComponentValueFromInspector,
@ -15,7 +16,7 @@ import { multipageSelector } from "Selectors/multipage";
describe("Editor- Inspector", () => {
beforeEach(() => {
cy.apiLogin();
cy.apiCreateApp();
cy.apiCreateApp(`${fake.companyName}-App`);
cy.openApp();
});

View file

@ -41,13 +41,12 @@ import {
describe("Multipage", () => {
beforeEach(() => {
cy.apiLogin();
cy.apiCreateApp();
cy.apiCreateApp(`${fake.companyName}-App`);
cy.openApp();
});
it("should verify the elements on multipage", () => {
const data = {};
data.appName = `${fake.companyName}-App`;
data.widgetName = fake.widgetName;
data.tooltipText = fake.randomSentence;
data.minimumLength = randomNumber(1, 4);

View file

@ -64,7 +64,7 @@ import { deleteDownloadsFolder } from "Support/utils/common";
describe("RunJS", () => {
beforeEach(() => {
cy.apiLogin();
cy.apiCreateApp();
cy.apiCreateApp(`${fake.companyName}-App`);
cy.openApp();
cy.viewport(1800, 1800);
cy.dragAndDropWidget("Button");

View file

@ -63,7 +63,7 @@ import { verifyNodeData, openNode, verifyValue } from "Support/utils/inspector";
describe("runpy", () => {
beforeEach(() => {
cy.apiLogin();
cy.apiCreateApp();
cy.apiCreateApp(`${fake.companyName}-App`);
cy.openApp();
cy.viewport(1800, 1800);
cy.dragAndDropWidget("Button");
@ -214,7 +214,10 @@ actions.unsetPageVariable('pageVar')`
cy.wait(200);
cy.waitForAutoSave();
query("run");
cy.get('[data-cy="sign-in-header"]').should("be.visible");
cy.get('[data-cy="sign-in-header"]', { timeout: 20000 }).should(
"be.visible"
);
});
it("should verify global and page data", () => {

View file

@ -56,7 +56,7 @@ import { resizeQueryPanel } from "Support/utils/dataSource";
describe("Table", () => {
beforeEach(() => {
cy.apiLogin();
cy.apiCreateApp();
cy.apiCreateApp(`${fake.companyName}-App`);
cy.openApp();
deleteDownloadsFolder();
cy.viewport(1400, 2200);

View file

@ -61,14 +61,16 @@ describe("App Import Functionality", () => {
cy.get(importSelectors.importOptionInput).selectFile(appFile, {
force: true,
});
cy.verifyToastMessage(
commonSelectors.toastMessage,
importText.appImportedToastMessage
);
cy.get('[data-cy="import-app-title"]').should("be.visible");
cy.get('[data-cy="Import app"]').click();
cy.get(".go3958317564")
.should("be.visible")
.and("have.text", importText.appImportedToastMessage);
cy.get(".driver-close-btn").click();
cy.get(commonSelectors.appNameInput).verifyVisibleElement(
"contain.value",
appData.name
appData.name.toLowerCase()
);
cy.modifyCanvasSize(900, 600);
cy.dragAndDropWidget(buttonText.defaultWidgetText);
@ -107,10 +109,12 @@ describe("App Import Functionality", () => {
cy.get(importSelectors.importOptionInput).selectFile(exportedFilePath, {
force: true,
});
cy.verifyToastMessage(
commonSelectors.toastMessage,
importText.appImportedToastMessage
);
cy.get('[data-cy="import-app-title"]').should("be.visible");
cy.get('[data-cy="Import app"]').click();
cy.get(".go3958317564")
.should("be.visible")
.and("have.text", importText.appImportedToastMessage);
cy.get(
`[data-cy="draggable-widget-${buttonText.defaultWidgetName}"]`
).should("be.visible");
@ -119,7 +123,7 @@ describe("App Import Functionality", () => {
cy.get(commonSelectors.appNameInput).verifyVisibleElement(
"contain.value",
exportedAppData.app[0].definition.appV2.name
exportedAppData.app[0].definition.appV2.name.toLowerCase()
);
cy.get(
appVersionSelectors.currentVersionField((currentVersion = "v1"))
@ -178,10 +182,11 @@ describe("App Import Functionality", () => {
force: true,
}
);
cy.verifyToastMessage(
commonSelectors.toastMessage,
importText.appImportedToastMessage
);
cy.get('[data-cy="import-app-title"]').should("be.visible");
cy.get('[data-cy="Import app"]').click();
cy.get(".go3958317564")
.should("be.visible")
.and("have.text", importText.appImportedToastMessage);
cy.get(appVersionSelectors.appVersionMenuField).click();
cy.get(appVersionSelectors.appVersionContentList).should(
"have.text",
@ -195,7 +200,7 @@ describe("App Import Functionality", () => {
cy.get(commonSelectors.appNameInput).verifyVisibleElement(
"contain.value",
exportedAppData.app[0].definition.appV2.name
exportedAppData.app[0].definition.appV2.name.toLowerCase()
);
cy.get(
appVersionSelectors.currentVersionField(

View file

@ -160,9 +160,11 @@ describe("Manage SSO for multi workspace", () => {
if (envVar === "Community") {
it("Should verify the workspace login page", () => {
data.workspaceName = fake.companyName;
common.createWorkspace(data.workspaceName);
data.workspaceName = fake.companyName.toLowerCase();
cy.apiLogin()
cy.apiCreateWorkspace(data.workspaceName, data.workspaceName)
cy.visit(data.workspaceName)
cy.wait(500)
common.navigateToManageSSO();
SSO.visitWorkspaceLoginPage();
SSO.workspaceLoginPageElements(data.workspaceName);
@ -243,10 +245,11 @@ describe("Manage SSO for multi workspace", () => {
cy.notVisible(commonSelectors.passwordInputField);
cy.notVisible(commonSelectors.loginButton);
data.workspaceName = fake.companyName;
cy.appUILogin();
common.createWorkspace(data.workspaceName);
cy.wait(300);
data.workspaceName = fake.companyName.toLowerCase();
cy.apiLogin()
cy.apiCreateWorkspace(data.workspaceName, data.workspaceName)
cy.visit(data.workspaceName)
cy.wait(500)
SSO.disableDefaultSSO();
cy.get(ssoSelector.passwordEnableToggle).uncheck();
cy.get(commonSelectors.buttonSelector("Yes")).click();

View file

@ -17,12 +17,16 @@ describe("App share functionality", () => {
beforeEach(() => {
cy.appUILogin();
});
before(() => {
cy.apiLogin();
cy.apiCreateApp(data.appName);
cy.visit('/')
logout();
})
if (envVar === "Community") {
it("Verify private and public app share funtionality", () => {
cy.apiLogin();
cy.apiCreateApp(data.appName);
cy.openApp();
cy.openApp(data.appName);
cy.dragAndDropWidget("Table", 250, 250);
cy.get(commonWidgetSelector.shareAppButton).click();
@ -35,7 +39,7 @@ describe("App share functionality", () => {
commonText.shareModalElements[elements]
);
}
cy.get(commonWidgetSelector.copyAppLinkButton).should("be.visible");
cy.get(commonWidgetSelector.makePublicAppToggle).should("be.visible");
cy.get(commonWidgetSelector.appLink).should("be.visible");
cy.get(commonWidgetSelector.appNameSlugInput).should("be.visible");

View file

@ -19,13 +19,12 @@ data.folderName = `${fake.companyName.toLowerCase()}-folder`;
describe("User permissions", () => {
before(() => {
cy.intercept("GET", "/api/apps?page=1&folder=&searchKey=").as("homePage");
cy.appUILogin();
cy.apiLogin();
cy.apiCreateApp(data.appName);
cy.visit('/')
permissions.reset();
cy.get(commonSelectors.homePageLogo).click();
cy.wait("@homePage");
cy.createApp(data.appName);
cy.dragAndDropWidget("Table", 250, 250);
cy.get(commonSelectors.editorPageLogo).click();
permissions.addNewUserMW(data.firstName, data.email);
common.logout();
});

View file

@ -207,6 +207,8 @@ export const createWorkspace = (workspaceName) => {
cy.get(commonSelectors.workspaceName).click();
cy.get(commonSelectors.addWorkspaceButton).click();
cy.clearAndType(commonSelectors.workspaceNameInput, workspaceName);
cy.clearAndType('[data-cy="workspace-slug-input-field"]', workspaceName);
cy.wait(1000)
cy.intercept("GET", "/api/apps?page=1&folder=&searchKey=").as("homePage");
cy.get(commonSelectors.createWorkspaceButton).click();
cy.wait("@homePage");

View file

@ -3,43 +3,47 @@ id: control-component
title: Control component (Component Specific Actions)
---
Control component action invokes the component specific actions. Component specific actions are the actions that are exclusive actions for a particular widget. Component specific actions can be triggered either through the event handlers or from the Run JavaScript code query.
Control component action invokes the component specific actions. Component specific actions are the actions that are exclusive actions for a particular component. Component specific actions can be triggered either through the event handlers or from the Run JavaScript code query.
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>
<summary>Currently, Component specific actions are supported only by the below listed components.</summary>
<div>
<ul>
<li><a href="/docs/widgets/button#component-specific-actions-csa">Button</a></li>
<li><a href="/docs/widgets/checkbox#component-specific-actions-csa">Checkbox</a></li>
<li><a href="/docs/widgets/color-picker#component-specific-actions-csa">Color Picker</a></li>
<li><a href="/docs/widgets/dropdown#component-specific-actions-csa">Dropdown</a></li>
<li><a href="/docs/widgets/file-picker#component-specific-actions-csa">File Picker</a></li>
<li><a href="/docs/widgets/form#component-specific-actions-csa">Form</a></li>
<li><a href="/docs/widgets/icon#component-specific-actions-csa">Icon</a></li>
<li><a href="/docs/widgets/kanban#component-specific-actions-csa">Kanban</a></li>
<li><a href="/docs/widgets/link#component-specific-actions-csa">Link</a></li>
<li><a href="/docs/widgets/map#component-specific-actions-csa">Map</a></li>
<li><a href="/docs/widgets/modal#component-specific-actions-csa">Modal</a></li>
<li><a href="/docs/widgets/multiselect#component-specific-actions-csa">Multiselect</a></li>
<li><a href="/docs/widgets/radio-button#component-specific-actions-csa">Radio button</a></li>
<li><a href="/docs/widgets/table#component-specific-actions-csa">Table</a></li>
<li><a href="/docs/widgets/tabs#component-specific-actions-csa">Tabs</a></li>
<li><a href="/docs/widgets/text-input#component-specific-actions-csa">Text Input</a></li>
<li><a href="/docs/widgets/text#component-specific-actions-csa">Text</a></li>
<li><a href="/docs/widgets/textarea#component-specific-actions-csa">Text Area</a></li>
</ul>
</div>
</details>
:::info
Check out the **[live demo](https://youtu.be/JIhSH3YeM3E)** of Component specific actions demonstrated in one of our community call.
:::
## Available Component Specific Actions
| Widget | Component Specific Actions |
|--------|---------------------------|
| Button | Click, Set label, Disable, Visibility, Loading |
| Checkbox | Set checked |
| Color picker | Set color |
| Dropdown | Select option |
| File picker | Clear files |
| Kanban | Add card, Delete card, Move card, Update card data |
| Map | Set location |
| Modal | Show, Close |
| Multiselect | Select option, Deselect option, Clear selection |
| Radio button | Select option |
| Tabs | Set tab |
| Table | Set page, Select row, Deselect Row, Discard changes |
| Text | Set text, Set Visibility |
| Text Area | Set text, Clear |
| Text Input | Set text, Clear, Set Focus, Set Blur, Disable, Visibility |
:::info
Currently, Component specific actions are supported only by the above listed widgets. We are working on bringing component specific actions for the remaining widgets.
Check out the **[demo](https://youtu.be/JIhSH3YeM3E)** of Component specific actions demonstrated in one of our community call.
:::
## Using Component Specific Actions
### Set a value for text input widget using button's event handler
### Set a value for text input component using button's event handler
- Drag a **Text Input** and a **Button** widget onto the canvas.
- Drag a **Text Input** and a **Button** component onto the canvas.
- Go to the **Inspector** on the left sidebar to check the exposed variables available for the `textinput1` widget under the `components`. You'll see that the variable `value` is an empty string because the field value of the text input widget is empty right now.
- Go to the **Inspector** on the left sidebar to check the exposed variables available for the `textinput1` component under the `components`. You'll see that the variable `value` is an empty string because the field value of the text input component is empty right now.
<div style={{textAlign: 'center'}}>
@ -47,7 +51,7 @@ Currently, Component specific actions are supported only by the above listed wid
</div>
- Now enter some value in the text input widget and you'll see that the `value` in inspector has been updated.
- Now enter some value in the text input component and you'll see that the `value` in inspector has been updated.
<div style={{textAlign: 'center'}}>
@ -55,7 +59,7 @@ Currently, Component specific actions are supported only by the above listed wid
</div>
- Now, click on the button's widget handler to open up its properties in the right sidebar and then add a event handler for **On Click** event to trigger **Control Component** action. Select `textinput1` in component dropdown, `Set text` as Action, and in `Text` field enter the text that you want to update in the field value.
- Now, click on the button's component handler to open up its properties in the right sidebar and then add a event handler for **On Click** event to trigger **Control Component** action. Select `textinput1` in component dropdown, `Set text` as Action, and in `Text` field enter the text that you want to update in the field value.
<div style={{textAlign: 'center'}}>
@ -63,7 +67,7 @@ Currently, Component specific actions are supported only by the above listed wid
</div>
- Now when you'll click on the button you'll see that the field value of the text input widget has been updated with value that you set.
- Now when you'll click on the button you'll see that the field value of the text input component has been updated with value that you set.
<div style={{textAlign: 'center'}}>
@ -72,7 +76,7 @@ Currently, Component specific actions are supported only by the above listed wid
</div>
### Clear value of text input widget using JavaScript query
### Clear value of text input component using JavaScript query
- Let's clear the value that we set in the previous section, using Run JavaScript code. Create a new Run JavaScript Code query and call the component and the CSA that component provides.
@ -94,5 +98,5 @@ await components.textinput1.clear()
</div>
- Finally, hit the **save and run** query button to fire up the query, and you'll see that the field value of the text input widget has been cleared.
- Finally, hit the **save and run** query button to fire up the query, and you'll see that the field value of the text input component has been cleared.

View file

@ -64,15 +64,17 @@ 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>/`
- **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**.
- **Max width of canvas**: Modify the width of the canvas in **px** or **%**. The default width is 1292 px.
- **Max height of canvas**: Modify the width of the canvas in **px** or **%**. The default height is 2400 px and currently it is the maximum height limit.
- **Max width of canvas**: Modify the width of the canvas in **px** or **%**. The default width is `1292` px.
- **Background color of canvas**: Enter the hex color code or choose a color from the picker to change the background color of the canvas. You can also click on the **Fx** to programmatically set the value.
- **Export app**: Click on the [Export app](/docs/dashboard/#export-app) button to export the application as a JSON file. You can import this JSON file in any other workspace to use the application.
<div style={{textAlign: 'center'}}>
<img className="screenshot-full" src="/img/v2-beta/app-builder/leftsidebar/globalnew.png" alt="App Builder: Left-sidebar"/>
<img className="screenshot-full" src="/img/v2-beta/app-builder/leftsidebar/globalsettings.png" alt="App Builder: Left-sidebar"/>
</div>

View file

@ -7,7 +7,7 @@ ToolJet apps offer two sharing options: they can either be shared privately with
<div style={{textAlign: 'center'}}>
<img className="screenshot-full" src="/img/v2-beta/app-builder/share/sharenew.png" alt="Share modal" width='700'/>
<img className="screenshot-full" src="/img/v2-beta/app-builder/share/sharenew1.png" alt="Share modal" width='700'/>
</div>
@ -17,7 +17,7 @@ To share the app with external end users and make it accessible to anyone on the
<div style={{textAlign: 'center'}}>
<img className="screenshot-full" src="/img/v2-beta/app-builder/share/publicnew.png" alt="Share modal" width='700'/>
<img className="screenshot-full" src="/img/v2-beta/app-builder/share/publicnew1.png" alt="Share modal" width='700'/>
</div>
@ -27,7 +27,7 @@ By default, ToolJet will generate a unique URL for your application. However, yo
<div style={{textAlign: 'center'}}>
<img className="screenshot-full" src="/img/v2-beta/app-builder/share/edit.png" alt="Share modal" width='700'/>
<img className="screenshot-full" src="/img/v2-beta/app-builder/share/edit1.png" alt="Share modal" width='700'/>
</div>

View file

@ -15,9 +15,7 @@ Furthermore, the dashboard serves as a gateway to various essential sections, su
## Workspace Manager
The workspace manager is located on the top left corner of the dashboard. Clicking on the workspace manager will open a dropdown menu with a list of all the workspaces you are a part of. You can switch between workspaces by clicking on the workspace name from the dropdown menu.
You can also create a new workspace by clicking on the `Add new workspace` button on the bottom of the dropdown menu. Clicking on this button will open a modal, enter the name of the workspace and click on the `Create Workspace` button to create a new workspace. Workspaces can be **renamed** by clicking on the `edit` icon on the right side of the workspace name.
The workspace manager is located on the bottom left corner of the dashboard. Clicking on the workspace manager will open a dropdown menu with a list of all the workspaces you are a part of. You can switch between workspaces by clicking on the workspace name from the dropdown menu.
<div style={{textAlign: 'center'}}>
@ -25,19 +23,46 @@ You can also create a new workspace by clicking on the `Add new workspace` butto
</div>
## Create a new app
### Add new workspace
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 instantly create a new app and open the **[app builder](/docs/next/app-builder/overview)**.
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 className="screenshot-full" src="/img/dashboard/newapp.gif" alt="Dashboard"/>
<img className="screenshot-full" src="/img/dashboard/newworkmodal.png" alt="Dashboard"/>
</div>
### 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.
## 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/newappmodal.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)**
### 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.
@ -76,7 +101,8 @@ When the app(JSON file) that includes the table schema is imported, and the tabl
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`.
## Create a new folder
## Folders
### 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.
@ -103,6 +129,20 @@ Folders can be searched by clicking on the search icon on the left drawer of the
</div>
### 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/appurl.png" alt="Dashboard"/>
</div>
## 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.

View file

@ -5,22 +5,15 @@ title: Airtable
# Airtable
ToolJet can connect to your Airtable account to read and write data. **Airtable API key** is required to create an Airtable data source on ToolJet. You can generate API key by visiting [Airtable account page](https://airtable.com/account).
ToolJet can connect to your Airtable account to read and write data.Airtable Personal Access Token is required to connect to the Airtable data source on ToolJet. You can generate the PAT by visiting [Developer Hub from your Airtable profile](https://support.airtable.com/docs/creating-and-using-api-keys-and-access-tokens#understanding-personal-access-token-basic-actions).
<img className="screenshot-full" src="/img/datasource-reference/airtable/add_creds.gif" alt="irtable record"/>
:::info
Airtable API has a rate limit, and at the time of writing this documentation, the limit is five(5) requests per second per base. You can read more about rate limits here **[Airtable API]( https://airtable.com/api )**.
Airtable API has a rate limit, and at the time of writing this documentation, the limit is five(5) requests per second per base. You can read more about rate limits here **[Airtable API](https://airtable.com/api)**.
:::
:::tip
This guide assumes that you have already gone through [Adding a data source](/docs/tutorial/adding-a-datasource) tutorial.
:::
## Supported queries
## Supported Operations
- **[Listing records](#listing-records)**
- **[Retrieving a record](#retrieving-a-record)**
@ -30,113 +23,106 @@ This guide assumes that you have already gone through [Adding a data source](/do
### Listing records
This query lists all the records in a table. The results are paginated and each page can have up to 100 records.
This query lists all the records in a table. The results are paginated and each page can have up to 100 records.
#### Required parameters:
#### Required parameters:
- **Base ID:** To find the Base ID, first visit **airtable.com/api**. Select from the list of bases the base whose ID you'd like to find out. Example Base ID: `appDT3UCPffPiSmFd`
- **Table name:** Enter the table name whose data you want to fetch.
#### Optional parameters:
#### Optional parameters:
- **Page size:** The number of records returned in each request. Must be less than or equal to 100. Default is 100.
- **offset:** If there are more records, the response will contain an offset. To fetch the next page of records, include offset in the next request's parameters.
<img className="screenshot-full" src="/img/datasource-reference/airtable/listv2.png" alt="List airtable record" />
Example response from Airtable:
Example response from Airtable:
```json
{
"records": [
{
"id": "recu9xMnUdr2n2cw8",
"fields": {
"Notes": "sdfdsf",
"Name": "dsfdsf"
},
"createdTime": "2021-05-12T14:30:33.000Z"
},
{
"id": "recyIdR7bVdQvmKXa",
"fields": {
"Notes": "sdfdsf",
"Name": "dfds"
},
"createdTime": "2021-05-12T14:30:33.000Z"
},
{
"id": "recAOzdIHaRpvRaGE",
"fields": {
"Notes": "sdfsdfsd",
"Name": "sdfdsf"
},
"createdTime": "2021-05-12T14:30:33.000Z"
}
],
"offset": "recAOzdIHaRpvRaGE"
"records": [
{
"id": "recu9xMnUdr2n2cw8",
"fields": {
"Notes": "sdfdsf",
"Name": "dsfdsf"
},
"createdTime": "2021-05-12T14:30:33.000Z"
},
{
"id": "recyIdR7bVdQvmKXa",
"fields": {
"Notes": "sdfdsf",
"Name": "dfds"
},
"createdTime": "2021-05-12T14:30:33.000Z"
},
{
"id": "recAOzdIHaRpvRaGE",
"fields": {
"Notes": "sdfsdfsd",
"Name": "sdfdsf"
},
"createdTime": "2021-05-12T14:30:33.000Z"
}
],
"offset": "recAOzdIHaRpvRaGE"
}
```
### Retrieving a record
#### Required parameters:
#### Required parameters:
- **Base ID**
- **Table name**
- **Table name**
- **Record ID**
<img className="screenshot-full" src="/img/datasource-reference/airtable/retv2.png" alt="Retrieve airtable record" />
Example response from Airtable:
Example response from Airtable:
```json
{
"id": "recu9xMnUdr2n2cw8",
"fields": {
"Notes": "sdfdsf",
"Name": "dsfdsf"
},
"createdTime": "2021-05-12T14:30:33.000Z"
"id": "recu9xMnUdr2n2cw8",
"fields": {
"Notes": "sdfdsf",
"Name": "dsfdsf"
},
"createdTime": "2021-05-12T14:30:33.000Z"
}
```
### Creating a record
#### Required parameters:
- **Base ID**
- **Table name**
- **Records**
<img className="screenshot-full" src="/img/datasource-reference/airtable/createv2.png" alt="Create airtable record" />
#### Example Records:
```json
[
{
"fields": {
"Notes": "sdfdsf",
"Name": "dsfdsf"
}
},
{
"fields": {
"Notes": "note1",
"Name": "dsfdsf"
}
{
"fields": {
"Notes": "sdfdsf",
"Name": "dsfdsf"
}
},
{
"fields": {
"Notes": "note1",
"Name": "dsfdsf"
}
}
]
```
Click on the `run` button to run the query.
:::info
@ -144,37 +130,38 @@ NOTE: Query must be saved before running.
:::
Example response from Airtable:
```json
{
"records": [
{
"id": "rec5RuZ1COoZGtGDY",
"fields": {
"Notes": "sdfdsf",
"Name": "dsfdsf"
},
"createdTime": "2022-02-07T20:25:27.000Z"
},
{
"id": "recaYbFPonNNu6Cwj",
"fields": {
"Notes": "note1",
"Name": "dsfdsf"
},
"createdTime": "2022-02-07T20:25:27.000Z"
}
]
"records": [
{
"id": "rec5RuZ1COoZGtGDY",
"fields": {
"Notes": "sdfdsf",
"Name": "dsfdsf"
},
"createdTime": "2022-02-07T20:25:27.000Z"
},
{
"id": "recaYbFPonNNu6Cwj",
"fields": {
"Notes": "note1",
"Name": "dsfdsf"
},
"createdTime": "2022-02-07T20:25:27.000Z"
}
]
}
```
### Updating a record
#### Required parameters:
- **Base ID**
- **Table name**
- **Record ID**
<img className="screenshot-full" src="/img/datasource-reference/airtable/updv2.png" alt="Update airtable record"/>
#### Example body:
@ -192,27 +179,28 @@ NOTE: Query must be saved before running.
:::
Example response from Airtable:
```json
{
"id": "recu9xMnUdr2n2cw8",
"fields": {
"Notes": "Example Notes",
"Name": "change"
},
"createdTime": "2021-08-08T17:27:17.000Z"
"id": "recu9xMnUdr2n2cw8",
"fields": {
"Notes": "Example Notes",
"Name": "change"
},
"createdTime": "2021-08-08T17:27:17.000Z"
}
```
### Deleting a record
#### Required parameters:
- **Base ID**
- **Table name**
- **Record ID**
<img className="screenshot-full" src="/img/datasource-reference/airtable/delv2.png" alt="Delete airtable record" />
Click on the `run` button to run the query.
:::info
@ -226,4 +214,4 @@ Example response from Airtable:
deleted: true
id: "recIKsyZgqI4zoqS7"
}
```
```

View file

@ -9,6 +9,8 @@ ToolJet can connect to Amazon Athena which is an interactive query service that
## 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.
ToolJet requires the following to connect to your Athena.
- **Database**
@ -29,14 +31,8 @@ You can also configure for **[additional optional parameters](https://github.com
- Click on `+` button of the query manager at the bottom panel of the editor and select the database added in the previous step as the datasource. Query manager then can be used to write SQL queries.
<img className="screenshot-full" src="/img/datasource-reference/athena/athena-query.png" alt="Athena query" />
- Click on the `run` button to run the query.
**NOTE:** Query should be saved before running.
:::tip
**Refer amazon athena docs here for more info:** [link](https://docs.aws.amazon.com/athena/latest/ug/what-is.html)
:::

View file

@ -7,9 +7,9 @@ ToolJet offers the capability to establish a connection with Azure Blob storage
## Connection
To connect ToolJet with the Azure Blob global datasource, you have two options:
1. Click on the `+Add new global datasource` button in the query panel.
2. Go to the **[Global Datasources](/docs/data-sources/overview)** page on the ToolJet dashboard.
To connect ToolJet with the Azure Blob data source, you have two options:
1. Click on the `+Add new data source` button in the query panel.
2. Go to the **[Data Sources](/docs/data-sources/overview)** page on the ToolJet dashboard.
<div style={{textAlign: 'center'}}>
@ -20,15 +20,15 @@ To connect ToolJet with the Azure Blob global datasource, you have two options:
To successfully establish the connection, ToolJet requires the following details:
- **Connection String**: The connection string can be found on the dashboard of Azure Blob Storage.
Once you have entered the connection string, click on the **Test connection** button to verify the connection's success. To save the datasource, click on the **Save** button.
Once you have entered the connection string, click on the **Test connection** button to verify the connection's success. To save the data source, click on the **Save** button.
## Querying Azure Blob
Once you have connected to the Azure Blob global datasource, follow these steps to create queries and interact with a Azure Blob storage from the ToolJet application:
Once you have connected to the Azure Blob data source, follow these steps to create queries and interact with Azure Blob storage from the ToolJet application:
1. Open the ToolJet application and navigate to the query panel at the bottom of the app builder.
2. Click the `+Add` button to open the list of available `local` and `global datasources`.
3. Select **Azure Blob** from the global datasource section.
2. Click the `+Add` button to open the list of available `local` and `data sources`.
3. Select **Azure Blob** from the data source section.
4. Select the desired **operation** from the dropdown and enter the required **parameters**.
5. **Rename**(optional) and **Create** the query.
6. Click **Preview** to view the data returned from the query or click **Run** to execute the query.
@ -43,21 +43,21 @@ Query results can be transformed using Transformation. For more information on t
</div>
## Supported operations
## Supported Operations
1. **[Create container](#create-container)**
2. **[List containers](#list-containers)**
3. **[List blobs](#list-blobs)**
4. **[Upload blob](#upload-blob)**
5. **[Read blob](#read-blob)**
6. **[Delete blob](#delete-blob)**
1. **[Create Container](#create-container)**
2. **[List Containers](#list-containers)**
3. **[List Blobs](#list-blobs)**
4. **[Upload Blob](#upload-blob)**
5. **[Read Blob](#read-blob)**
6. **[Delete Blob](#delete-blob)**
### Create container
### Create Container
The create container operation enables the creation of new containers within Azure Blob storage. Containers serve as logical units for organizing and managing blob data. Users can provide a unique name for the container. Once created, the container is available for use in storing and organizing blob data. If the container with the same name already exists, the operation fails.
#### Required parameters:
#### Required Parameters:
- **Container Name:** Name of the container that you want to create.
@ -67,7 +67,7 @@ The create container operation enables the creation of new containers within Azu
</div>
### List containers
### List Containers
The list container operation allows you to retrieve a list of containers within Azure Blob storage.
@ -77,16 +77,16 @@ The list container operation allows you to retrieve a list of containers within
</div>
### List blobs
### List Blobs
The list blobs operation enables you to retrieve a list of blobs within a specific container in Azure Blob storage.
#### Required parameter:
#### Required Parameter:
- **Container:** Specify the name of the container from which you wish to retrieve a list of blobs.
- **Page Size:** Specify the maximum number of blobs to be returned per page or request.
#### Optional parameters:
#### Optional Parameters:
- **Prefix:** Filter the list of blobs based on a specific prefix or prefix pattern, allowing you to narrow down the results to blobs with names that start with the specified prefix.
- **Continuation Token:** A marker or token used to retrieve the next page of results when there are more blobs available beyond the initial page.
@ -97,11 +97,11 @@ The list blobs operation enables you to retrieve a list of blobs within a specif
</div>
### Upload blob
### Upload Blob
The upload blob operation allows you to upload a new blob or update an existing blob in Azure Blob storage. It provides a convenient way to store data such as files, images, or documents in the specified container.
#### Required parameters:
#### Required Parameters:
- **Container**: Specify the name of the container where the blob will be uploaded or updated.
- **Blob Name**: Provide a unique name for the blob. This name is used to identify and access the blob within the specified container.
@ -109,11 +109,11 @@ The upload blob operation allows you to upload a new blob or update an existing
- **Upload Data**: Select or provide the data to be uploaded as the content of the blob. This can be a file from your local system, binary data, or text content. You can also get the data from the exposed variable of the file picker component.
- **Encoding**: Choose the encoding format for the uploaded data if applicable. This parameter determines how the data is encoded before being stored as the blob content. If the value is left blank then it takes **UTF-8** by default.
### Read blob
### Read Blob
The read blob operation allows you to retrieve the content of a specific blob stored in Azure Blob storage. It enables you to access and retrieve the data stored within the blob for further processing or display.
#### Required parameters:
#### Required Parameters:
- **Container**: Specify the name of the container where the blob is located.
- **Blob Name**: Provide the unique name of the blob you want to read. This identifies the specific blob within the specified container
@ -124,11 +124,11 @@ The read blob operation allows you to retrieve the content of a specific blob st
</div>
### Delete blob
### Delete Blob
The delete blob operation allows you to remove a specific blob from Azure Blob storage. This operation permanently deletes the blob and its associated data, freeing up storage space and removing the blob from the container.
#### Required parameters:
#### Required Parameters:
- **Container**: Specify the name of the container from which you want to delete the blob.
- **Blob Name**: Provide the unique name of the blob you want to delete. This identifies the specific blob within the specified container.

View file

@ -5,24 +5,22 @@ title: Baserow
# Baserow
ToolJet can connect to your Baserow account to read and write data.
## Connection
ToolJet can connect to your Baserow account to read and write data.
Select the hosted version of Baserow or the self-host option.
To connect to Baserow, you need to provide the following details:
For [**self-hosted**](https://baserow.io/docs/index#installation) option, base URL is required to connect.
- **API token**: You can create an API token from your Baserow dashboard. You can follow the steps to create API token from [this link](https://baserow.io/user-docs/personal-api-tokens).
- **Host**: You can either select the Baserow Cloud or Self-hosted option.
- **Base URL**: If you select the self-hosted option, you need to provide the base URL of your Baserow instance.
Baserow API token is required to create an Baserow data source on ToolJet. You can follow the steps to create API token from [this link](https://baserow.io/api-docs).
<img className="screenshot-full" src="/img/datasource-reference/baserow/baserow-intro.png" alt="Baserow intro" />
:::tip
This guide assumes that you have already gone through [Adding a data source](/docs/tutorial/adding-a-datasource) tutorial.
:::
## Supported queries
## Supported Operations
- [List fields](#list-fields)
- [List rows](#list-rows)

View file

@ -9,7 +9,7 @@ ToolJet can trigger n8n workflows using webhook URLs. Please refer [this](https:
## Connection
Go to the data source manager on the left sidebar and click on `+` button to add new data source. Select n8n from the list of available data sources in the modal that pops-up.
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.
n8n webhooks can be called with or without an **Authentication**. You can keep the `Authentication type` as `none` if your webhook didn't have one or if it has one then you can choose the one from the dropdown and provide credentials:

View file

@ -9,6 +9,8 @@ ToolJet can connect to Oracle databases to read and write data.
## Connection
To establish a connection with the Oracle DB data source, click on the `+Add new` 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.
A Oracle DB can be connected with the following credentails:
- **Host**
- **Port**
@ -38,7 +40,6 @@ Once you have added a Oracle DB data source, click on `+` button of the query ma
SQL mode can be used to write raw SQL queries. Select SQL mode from the dropdown and enter the SQL query in the editor. Click on the `run` button to run the query.
**NOTE**: Query should be saved before running.
#### GUI mode
@ -50,4 +51,4 @@ Click on the **run** button to run the query. **NOTE**: Query should be saved be
:::tip
Query results can be transformed using transformations. Read our transformations documentation to see how: **[link](/docs/tutorial/transformations)**
:::
:::

View file

@ -121,7 +121,7 @@ module.exports = {
// Please change this to your repo.
editUrl: 'https://github.com/ToolJet/Tooljet/blob/develop/docs/',
includeCurrentVersion: false,
lastVersion: '2.19.0',
lastVersion: '2.22.0',
},
theme: {
customCss: require.resolve('./src/css/custom.css'),

View file

@ -14,10 +14,10 @@
"write-heading-ids": "docusaurus write-heading-ids"
},
"dependencies": {
"@docusaurus/core": "^2.4.0",
"@docusaurus/plugin-google-gtag": "^2.4.0",
"@docusaurus/plugin-sitemap": "^2.4.0",
"@docusaurus/preset-classic": "^2.4.0",
"@docusaurus/core": "^2.4.3",
"@docusaurus/plugin-google-gtag": "^2.4.3",
"@docusaurus/plugin-sitemap": "^2.4.3",
"@docusaurus/preset-classic": "^2.4.3",
"@mdx-js/react": "^1.6.22",
"clsx": "^1.2.1",
"react": "^17.0.2",

BIN
docs/static/img/dashboard/appurl.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 156 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 236 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 278 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

View file

@ -3,43 +3,47 @@ id: control-component
title: Control component (Component Specific Actions)
---
Control component action invokes the component specific actions. Component specific actions are the actions that are exclusive actions for a particular widget. Component specific actions can be triggered either through the event handlers or from the Run JavaScript code query.
Control component action invokes the component specific actions. Component specific actions are the actions that are exclusive actions for a particular component. Component specific actions can be triggered either through the event handlers or from the Run JavaScript code query.
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>
<summary>Currently, Component specific actions are supported only by the below listed components.</summary>
<div>
<ul>
<li><a href="/docs/widgets/button#component-specific-actions-csa">Button</a></li>
<li><a href="/docs/widgets/checkbox#component-specific-actions-csa">Checkbox</a></li>
<li><a href="/docs/widgets/color-picker#component-specific-actions-csa">Color Picker</a></li>
<li><a href="/docs/widgets/dropdown#component-specific-actions-csa">Dropdown</a></li>
<li><a href="/docs/widgets/file-picker#component-specific-actions-csa">File Picker</a></li>
<li><a href="/docs/widgets/form#component-specific-actions-csa">Form</a></li>
<li><a href="/docs/widgets/icon#component-specific-actions-csa">Icon</a></li>
<li><a href="/docs/widgets/kanban#component-specific-actions-csa">Kanban</a></li>
<li><a href="/docs/widgets/link#component-specific-actions-csa">Link</a></li>
<li><a href="/docs/widgets/map#component-specific-actions-csa">Map</a></li>
<li><a href="/docs/widgets/modal#component-specific-actions-csa">Modal</a></li>
<li><a href="/docs/widgets/multiselect#component-specific-actions-csa">Multiselect</a></li>
<li><a href="/docs/widgets/radio-button#component-specific-actions-csa">Radio button</a></li>
<li><a href="/docs/widgets/table#component-specific-actions-csa">Table</a></li>
<li><a href="/docs/widgets/tabs#component-specific-actions-csa">Tabs</a></li>
<li><a href="/docs/widgets/text-input#component-specific-actions-csa">Text Input</a></li>
<li><a href="/docs/widgets/text#component-specific-actions-csa">Text</a></li>
<li><a href="/docs/widgets/textarea#component-specific-actions-csa">Text Area</a></li>
</ul>
</div>
</details>
:::info
Check out the **[live demo](https://youtu.be/JIhSH3YeM3E)** of Component specific actions demonstrated in one of our community call.
:::
## Available Component Specific Actions
| Widget | Component Specific Actions |
|--------|---------------------------|
| Button | Click, Set label, Disable, Visibility, Loading |
| Checkbox | Set checked |
| Color picker | Set color |
| Dropdown | Select option |
| File picker | Clear files |
| Kanban | Add card, Delete card, Move card, Update card data |
| Map | Set location |
| Modal | Show, Close |
| Multiselect | Select option, Deselect option, Clear selection |
| Radio button | Select option |
| Tabs | Set tab |
| Table | Set page, Select row, Deselect Row, Discard changes |
| Text | Set text, Set Visibility |
| Text Area | Set text, Clear |
| Text Input | Set text, Clear, Set Focus, Set Blur, Disable, Visibility |
:::info
Currently, Component specific actions are supported only by the above listed widgets. We are working on bringing component specific actions for the remaining widgets.
Check out the **[demo](https://youtu.be/JIhSH3YeM3E)** of Component specific actions demonstrated in one of our community call.
:::
## Using Component Specific Actions
### Set a value for text input widget using button's event handler
### Set a value for text input component using button's event handler
- Drag a **Text Input** and a **Button** widget onto the canvas.
- Drag a **Text Input** and a **Button** component onto the canvas.
- Go to the **Inspector** on the left sidebar to check the exposed variables available for the `textinput1` widget under the `components`. You'll see that the variable `value` is an empty string because the field value of the text input widget is empty right now.
- Go to the **Inspector** on the left sidebar to check the exposed variables available for the `textinput1` component under the `components`. You'll see that the variable `value` is an empty string because the field value of the text input component is empty right now.
<div style={{textAlign: 'center'}}>
@ -47,7 +51,7 @@ Currently, Component specific actions are supported only by the above listed wid
</div>
- Now enter some value in the text input widget and you'll see that the `value` in inspector has been updated.
- Now enter some value in the text input component and you'll see that the `value` in inspector has been updated.
<div style={{textAlign: 'center'}}>
@ -55,7 +59,7 @@ Currently, Component specific actions are supported only by the above listed wid
</div>
- Now, click on the button's widget handler to open up its properties in the right sidebar and then add a event handler for **On Click** event to trigger **Control Component** action. Select `textinput1` in component dropdown, `Set text` as Action, and in `Text` field enter the text that you want to update in the field value.
- Now, click on the button's component handler to open up its properties in the right sidebar and then add a event handler for **On Click** event to trigger **Control Component** action. Select `textinput1` in component dropdown, `Set text` as Action, and in `Text` field enter the text that you want to update in the field value.
<div style={{textAlign: 'center'}}>
@ -63,7 +67,7 @@ Currently, Component specific actions are supported only by the above listed wid
</div>
- Now when you'll click on the button you'll see that the field value of the text input widget has been updated with value that you set.
- Now when you'll click on the button you'll see that the field value of the text input component has been updated with value that you set.
<div style={{textAlign: 'center'}}>
@ -72,7 +76,7 @@ Currently, Component specific actions are supported only by the above listed wid
</div>
### Clear value of text input widget using JavaScript query
### Clear value of text input component using JavaScript query
- Let's clear the value that we set in the previous section, using Run JavaScript code. Create a new Run JavaScript Code query and call the component and the CSA that component provides.
@ -94,5 +98,5 @@ await components.textinput1.clear()
</div>
- Finally, hit the **save and run** query button to fire up the query, and you'll see that the field value of the text input widget has been cleared.
- Finally, hit the **save and run** query button to fire up the query, and you'll see that the field value of the text input component has been cleared.

View file

@ -3,43 +3,47 @@ id: control-component
title: Control component (Component Specific Actions)
---
Control component action invokes the component specific actions. Component specific actions are the actions that are exclusive actions for a particular widget. Component specific actions can be triggered either through the event handlers or from the Run JavaScript code query.
Control component action invokes the component specific actions. Component specific actions are the actions that are exclusive actions for a particular component. Component specific actions can be triggered either through the event handlers or from the Run JavaScript code query.
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>
<summary>Currently, Component specific actions are supported only by the below listed components.</summary>
<div>
<ul>
<li><a href="/docs/widgets/button#component-specific-actions-csa">Button</a></li>
<li><a href="/docs/widgets/checkbox#component-specific-actions-csa">Checkbox</a></li>
<li><a href="/docs/widgets/color-picker#component-specific-actions-csa">Color Picker</a></li>
<li><a href="/docs/widgets/dropdown#component-specific-actions-csa">Dropdown</a></li>
<li><a href="/docs/widgets/file-picker#component-specific-actions-csa">File Picker</a></li>
<li><a href="/docs/widgets/form#component-specific-actions-csa">Form</a></li>
<li><a href="/docs/widgets/icon#component-specific-actions-csa">Icon</a></li>
<li><a href="/docs/widgets/kanban#component-specific-actions-csa">Kanban</a></li>
<li><a href="/docs/widgets/link#component-specific-actions-csa">Link</a></li>
<li><a href="/docs/widgets/map#component-specific-actions-csa">Map</a></li>
<li><a href="/docs/widgets/modal#component-specific-actions-csa">Modal</a></li>
<li><a href="/docs/widgets/multiselect#component-specific-actions-csa">Multiselect</a></li>
<li><a href="/docs/widgets/radio-button#component-specific-actions-csa">Radio button</a></li>
<li><a href="/docs/widgets/table#component-specific-actions-csa">Table</a></li>
<li><a href="/docs/widgets/tabs#component-specific-actions-csa">Tabs</a></li>
<li><a href="/docs/widgets/text-input#component-specific-actions-csa">Text Input</a></li>
<li><a href="/docs/widgets/text#component-specific-actions-csa">Text</a></li>
<li><a href="/docs/widgets/textarea#component-specific-actions-csa">Text Area</a></li>
</ul>
</div>
</details>
:::info
Check out the **[live demo](https://youtu.be/JIhSH3YeM3E)** of Component specific actions demonstrated in one of our community call.
:::
## Available Component Specific Actions
| Widget | Component Specific Actions |
|--------|---------------------------|
| Button | Click, Set label, Disable, Visibility, Loading |
| Checkbox | Set checked |
| Color picker | Set color |
| Dropdown | Select option |
| File picker | Clear files |
| Kanban | Add card, Delete card, Move card, Update card data |
| Map | Set location |
| Modal | Show, Close |
| Multiselect | Select option, Deselect option, Clear selection |
| Radio button | Select option |
| Tabs | Set tab |
| Table | Set page, Select row, Deselect Row, Discard changes |
| Text | Set text, Set Visibility |
| Text Area | Set text, Clear |
| Text Input | Set text, Clear, Set Focus, Set Blur, Disable, Visibility |
:::info
Currently, Component specific actions are supported only by the above listed widgets. We are working on bringing component specific actions for the remaining widgets.
Check out the **[demo](https://youtu.be/JIhSH3YeM3E)** of Component specific actions demonstrated in one of our community call.
:::
## Using Component Specific Actions
### Set a value for text input widget using button's event handler
### Set a value for text input component using button's event handler
- Drag a **Text Input** and a **Button** widget onto the canvas.
- Drag a **Text Input** and a **Button** component onto the canvas.
- Go to the **Inspector** on the left sidebar to check the exposed variables available for the `textinput1` widget under the `components`. You'll see that the variable `value` is an empty string because the field value of the text input widget is empty right now.
- Go to the **Inspector** on the left sidebar to check the exposed variables available for the `textinput1` component under the `components`. You'll see that the variable `value` is an empty string because the field value of the text input component is empty right now.
<div style={{textAlign: 'center'}}>
@ -47,7 +51,7 @@ Currently, Component specific actions are supported only by the above listed wid
</div>
- Now enter some value in the text input widget and you'll see that the `value` in inspector has been updated.
- Now enter some value in the text input component and you'll see that the `value` in inspector has been updated.
<div style={{textAlign: 'center'}}>
@ -55,7 +59,7 @@ Currently, Component specific actions are supported only by the above listed wid
</div>
- Now, click on the button's widget handler to open up its properties in the right sidebar and then add a event handler for **On Click** event to trigger **Control Component** action. Select `textinput1` in component dropdown, `Set text` as Action, and in `Text` field enter the text that you want to update in the field value.
- Now, click on the button's component handler to open up its properties in the right sidebar and then add a event handler for **On Click** event to trigger **Control Component** action. Select `textinput1` in component dropdown, `Set text` as Action, and in `Text` field enter the text that you want to update in the field value.
<div style={{textAlign: 'center'}}>
@ -63,7 +67,7 @@ Currently, Component specific actions are supported only by the above listed wid
</div>
- Now when you'll click on the button you'll see that the field value of the text input widget has been updated with value that you set.
- Now when you'll click on the button you'll see that the field value of the text input component has been updated with value that you set.
<div style={{textAlign: 'center'}}>
@ -72,7 +76,7 @@ Currently, Component specific actions are supported only by the above listed wid
</div>
### Clear value of text input widget using JavaScript query
### Clear value of text input component using JavaScript query
- Let's clear the value that we set in the previous section, using Run JavaScript code. Create a new Run JavaScript Code query and call the component and the CSA that component provides.
@ -94,5 +98,5 @@ await components.textinput1.clear()
</div>
- Finally, hit the **save and run** query button to fire up the query, and you'll see that the field value of the text input widget has been cleared.
- Finally, hit the **save and run** query button to fire up the query, and you'll see that the field value of the text input component has been cleared.

View file

@ -3,43 +3,47 @@ id: control-component
title: Control component (Component Specific Actions)
---
Control component action invokes the component specific actions. Component specific actions are the actions that are exclusive actions for a particular widget. Component specific actions can be triggered either through the event handlers or from the Run JavaScript code query.
Control component action invokes the component specific actions. Component specific actions are the actions that are exclusive actions for a particular component. Component specific actions can be triggered either through the event handlers or from the Run JavaScript code query.
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>
<summary>Currently, Component specific actions are supported only by the below listed components.</summary>
<div>
<ul>
<li><a href="/docs/widgets/button#component-specific-actions-csa">Button</a></li>
<li><a href="/docs/widgets/checkbox#component-specific-actions-csa">Checkbox</a></li>
<li><a href="/docs/widgets/color-picker#component-specific-actions-csa">Color Picker</a></li>
<li><a href="/docs/widgets/dropdown#component-specific-actions-csa">Dropdown</a></li>
<li><a href="/docs/widgets/file-picker#component-specific-actions-csa">File Picker</a></li>
<li><a href="/docs/widgets/form#component-specific-actions-csa">Form</a></li>
<li><a href="/docs/widgets/icon#component-specific-actions-csa">Icon</a></li>
<li><a href="/docs/widgets/kanban#component-specific-actions-csa">Kanban</a></li>
<li><a href="/docs/widgets/link#component-specific-actions-csa">Link</a></li>
<li><a href="/docs/widgets/map#component-specific-actions-csa">Map</a></li>
<li><a href="/docs/widgets/modal#component-specific-actions-csa">Modal</a></li>
<li><a href="/docs/widgets/multiselect#component-specific-actions-csa">Multiselect</a></li>
<li><a href="/docs/widgets/radio-button#component-specific-actions-csa">Radio button</a></li>
<li><a href="/docs/widgets/table#component-specific-actions-csa">Table</a></li>
<li><a href="/docs/widgets/tabs#component-specific-actions-csa">Tabs</a></li>
<li><a href="/docs/widgets/text-input#component-specific-actions-csa">Text Input</a></li>
<li><a href="/docs/widgets/text#component-specific-actions-csa">Text</a></li>
<li><a href="/docs/widgets/textarea#component-specific-actions-csa">Text Area</a></li>
</ul>
</div>
</details>
:::info
Check out the **[live demo](https://youtu.be/JIhSH3YeM3E)** of Component specific actions demonstrated in one of our community call.
:::
## Available Component Specific Actions
| Widget | Component Specific Actions |
|--------|---------------------------|
| Button | Click, Set label, Disable, Visibility, Loading |
| Checkbox | Set checked |
| Color picker | Set color |
| Dropdown | Select option |
| File picker | Clear files |
| Kanban | Add card, Delete card, Move card, Update card data |
| Map | Set location |
| Modal | Show, Close |
| Multiselect | Select option, Deselect option, Clear selection |
| Radio button | Select option |
| Tabs | Set tab |
| Table | Set page, Select row, Deselect Row, Discard changes |
| Text | Set text, Set Visibility |
| Text Area | Set text, Clear |
| Text Input | Set text, Clear, Set Focus, Set Blur, Disable, Visibility |
:::info
Currently, Component specific actions are supported only by the above listed widgets. We are working on bringing component specific actions for the remaining widgets.
Check out the **[demo](https://youtu.be/JIhSH3YeM3E)** of Component specific actions demonstrated in one of our community call.
:::
## Using Component Specific Actions
### Set a value for text input widget using button's event handler
### Set a value for text input component using button's event handler
- Drag a **Text Input** and a **Button** widget onto the canvas.
- Drag a **Text Input** and a **Button** component onto the canvas.
- Go to the **Inspector** on the left sidebar to check the exposed variables available for the `textinput1` widget under the `components`. You'll see that the variable `value` is an empty string because the field value of the text input widget is empty right now.
- Go to the **Inspector** on the left sidebar to check the exposed variables available for the `textinput1` component under the `components`. You'll see that the variable `value` is an empty string because the field value of the text input component is empty right now.
<div style={{textAlign: 'center'}}>
@ -47,7 +51,7 @@ Currently, Component specific actions are supported only by the above listed wid
</div>
- Now enter some value in the text input widget and you'll see that the `value` in inspector has been updated.
- Now enter some value in the text input component and you'll see that the `value` in inspector has been updated.
<div style={{textAlign: 'center'}}>
@ -55,7 +59,7 @@ Currently, Component specific actions are supported only by the above listed wid
</div>
- Now, click on the button's widget handler to open up its properties in the right sidebar and then add a event handler for **On Click** event to trigger **Control Component** action. Select `textinput1` in component dropdown, `Set text` as Action, and in `Text` field enter the text that you want to update in the field value.
- Now, click on the button's component handler to open up its properties in the right sidebar and then add a event handler for **On Click** event to trigger **Control Component** action. Select `textinput1` in component dropdown, `Set text` as Action, and in `Text` field enter the text that you want to update in the field value.
<div style={{textAlign: 'center'}}>
@ -63,7 +67,7 @@ Currently, Component specific actions are supported only by the above listed wid
</div>
- Now when you'll click on the button you'll see that the field value of the text input widget has been updated with value that you set.
- Now when you'll click on the button you'll see that the field value of the text input component has been updated with value that you set.
<div style={{textAlign: 'center'}}>
@ -72,7 +76,7 @@ Currently, Component specific actions are supported only by the above listed wid
</div>
### Clear value of text input widget using JavaScript query
### Clear value of text input component using JavaScript query
- Let's clear the value that we set in the previous section, using Run JavaScript code. Create a new Run JavaScript Code query and call the component and the CSA that component provides.
@ -94,5 +98,5 @@ await components.textinput1.clear()
</div>
- Finally, hit the **save and run** query button to fire up the query, and you'll see that the field value of the text input widget has been cleared.
- Finally, hit the **save and run** query button to fire up the query, and you'll see that the field value of the text input component has been cleared.

View file

@ -5,22 +5,15 @@ title: Airtable
# Airtable
ToolJet can connect to your Airtable account to read and write data. **Airtable API key** is required to create an Airtable data source on ToolJet. You can generate API key by visiting [Airtable account page](https://airtable.com/account).
ToolJet can connect to your Airtable account to read and write data. Airtable Personal Access Token is required to connect to the Airtable data source on ToolJet. You can generate the PAT by visiting [Developer Hub from your Airtable profile](https://support.airtable.com/docs/creating-and-using-api-keys-and-access-tokens#understanding-personal-access-token-basic-actions).
<img className="screenshot-full" src="/img/datasource-reference/airtable/add_creds.gif" alt="irtable record"/>
:::info
Airtable API has a rate limit, and at the time of writing this documentation, the limit is five(5) requests per second per base. You can read more about rate limits here **[Airtable API]( https://airtable.com/api )**.
Airtable API has a rate limit, and at the time of writing this documentation, the limit is five(5) requests per second per base. You can read more about rate limits here **[Airtable API](https://airtable.com/api)**.
:::
:::tip
This guide assumes that you have already gone through [Adding a data source](/docs/tutorial/adding-a-datasource) tutorial.
:::
## Supported queries
## Supported Operations
- **[Listing records](#listing-records)**
- **[Retrieving a record](#retrieving-a-record)**
@ -30,113 +23,106 @@ This guide assumes that you have already gone through [Adding a data source](/do
### Listing records
This query lists all the records in a table. The results are paginated and each page can have up to 100 records.
This query lists all the records in a table. The results are paginated and each page can have up to 100 records.
#### Required parameters:
#### Required parameters:
- **Base ID:** To find the Base ID, first visit **airtable.com/api**. Select from the list of bases the base whose ID you'd like to find out. Example Base ID: `appDT3UCPffPiSmFd`
- **Table name:** Enter the table name whose data you want to fetch.
#### Optional parameters:
#### Optional parameters:
- **Page size:** The number of records returned in each request. Must be less than or equal to 100. Default is 100.
- **offset:** If there are more records, the response will contain an offset. To fetch the next page of records, include offset in the next request's parameters.
<img className="screenshot-full" src="/img/datasource-reference/airtable/listv2.png" alt="List airtable record" />
Example response from Airtable:
Example response from Airtable:
```json
{
"records": [
{
"id": "recu9xMnUdr2n2cw8",
"fields": {
"Notes": "sdfdsf",
"Name": "dsfdsf"
},
"createdTime": "2021-05-12T14:30:33.000Z"
},
{
"id": "recyIdR7bVdQvmKXa",
"fields": {
"Notes": "sdfdsf",
"Name": "dfds"
},
"createdTime": "2021-05-12T14:30:33.000Z"
},
{
"id": "recAOzdIHaRpvRaGE",
"fields": {
"Notes": "sdfsdfsd",
"Name": "sdfdsf"
},
"createdTime": "2021-05-12T14:30:33.000Z"
}
],
"offset": "recAOzdIHaRpvRaGE"
"records": [
{
"id": "recu9xMnUdr2n2cw8",
"fields": {
"Notes": "sdfdsf",
"Name": "dsfdsf"
},
"createdTime": "2021-05-12T14:30:33.000Z"
},
{
"id": "recyIdR7bVdQvmKXa",
"fields": {
"Notes": "sdfdsf",
"Name": "dfds"
},
"createdTime": "2021-05-12T14:30:33.000Z"
},
{
"id": "recAOzdIHaRpvRaGE",
"fields": {
"Notes": "sdfsdfsd",
"Name": "sdfdsf"
},
"createdTime": "2021-05-12T14:30:33.000Z"
}
],
"offset": "recAOzdIHaRpvRaGE"
}
```
### Retrieving a record
#### Required parameters:
#### Required parameters:
- **Base ID**
- **Table name**
- **Table name**
- **Record ID**
<img className="screenshot-full" src="/img/datasource-reference/airtable/retv2.png" alt="Retrieve airtable record" />
Example response from Airtable:
Example response from Airtable:
```json
{
"id": "recu9xMnUdr2n2cw8",
"fields": {
"Notes": "sdfdsf",
"Name": "dsfdsf"
},
"createdTime": "2021-05-12T14:30:33.000Z"
"id": "recu9xMnUdr2n2cw8",
"fields": {
"Notes": "sdfdsf",
"Name": "dsfdsf"
},
"createdTime": "2021-05-12T14:30:33.000Z"
}
```
### Creating a record
#### Required parameters:
- **Base ID**
- **Table name**
- **Records**
<img className="screenshot-full" src="/img/datasource-reference/airtable/createv2.png" alt="Create airtable record" />
#### Example Records:
```json
[
{
"fields": {
"Notes": "sdfdsf",
"Name": "dsfdsf"
}
},
{
"fields": {
"Notes": "note1",
"Name": "dsfdsf"
}
{
"fields": {
"Notes": "sdfdsf",
"Name": "dsfdsf"
}
},
{
"fields": {
"Notes": "note1",
"Name": "dsfdsf"
}
}
]
```
Click on the `run` button to run the query.
:::info
@ -144,37 +130,38 @@ NOTE: Query must be saved before running.
:::
Example response from Airtable:
```json
{
"records": [
{
"id": "rec5RuZ1COoZGtGDY",
"fields": {
"Notes": "sdfdsf",
"Name": "dsfdsf"
},
"createdTime": "2022-02-07T20:25:27.000Z"
},
{
"id": "recaYbFPonNNu6Cwj",
"fields": {
"Notes": "note1",
"Name": "dsfdsf"
},
"createdTime": "2022-02-07T20:25:27.000Z"
}
]
"records": [
{
"id": "rec5RuZ1COoZGtGDY",
"fields": {
"Notes": "sdfdsf",
"Name": "dsfdsf"
},
"createdTime": "2022-02-07T20:25:27.000Z"
},
{
"id": "recaYbFPonNNu6Cwj",
"fields": {
"Notes": "note1",
"Name": "dsfdsf"
},
"createdTime": "2022-02-07T20:25:27.000Z"
}
]
}
```
### Updating a record
#### Required parameters:
- **Base ID**
- **Table name**
- **Record ID**
<img className="screenshot-full" src="/img/datasource-reference/airtable/updv2.png" alt="Update airtable record"/>
#### Example body:
@ -192,27 +179,28 @@ NOTE: Query must be saved before running.
:::
Example response from Airtable:
```json
{
"id": "recu9xMnUdr2n2cw8",
"fields": {
"Notes": "Example Notes",
"Name": "change"
},
"createdTime": "2021-08-08T17:27:17.000Z"
"id": "recu9xMnUdr2n2cw8",
"fields": {
"Notes": "Example Notes",
"Name": "change"
},
"createdTime": "2021-08-08T17:27:17.000Z"
}
```
### Deleting a record
#### Required parameters:
- **Base ID**
- **Table name**
- **Record ID**
<img className="screenshot-full" src="/img/datasource-reference/airtable/delv2.png" alt="Delete airtable record" />
Click on the `run` button to run the query.
:::info
@ -226,4 +214,4 @@ Example response from Airtable:
deleted: true
id: "recIKsyZgqI4zoqS7"
}
```
```

View file

@ -9,6 +9,8 @@ ToolJet can connect to Amazon Athena which is an interactive query service that
## 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.
ToolJet requires the following to connect to your Athena.
- **Database**
@ -29,14 +31,8 @@ You can also configure for **[additional optional parameters](https://github.com
- Click on `+` button of the query manager at the bottom panel of the editor and select the database added in the previous step as the datasource. Query manager then can be used to write SQL queries.
<img className="screenshot-full" src="/img/datasource-reference/athena/athena-query.png" alt="Athena query" />
- Click on the `run` button to run the query.
**NOTE:** Query should be saved before running.
:::tip
**Refer amazon athena docs here for more info:** [link](https://docs.aws.amazon.com/athena/latest/ug/what-is.html)
:::

View file

@ -7,9 +7,9 @@ ToolJet offers the capability to establish a connection with Azure Blob storage
## Connection
To connect ToolJet with the Azure Blob global datasource, you have two options:
1. Click on the `+Add new global datasource` button in the query panel.
2. Go to the **[Global Datasources](/docs/data-sources/overview)** page on the ToolJet dashboard.
To connect ToolJet with the Azure Blob data source, you have two options:
1. Click on the `+Add new data source` button in the query panel.
2. Go to the **[Data Sources](/docs/data-sources/overview)** page on the ToolJet dashboard.
<div style={{textAlign: 'center'}}>
@ -20,15 +20,15 @@ To connect ToolJet with the Azure Blob global datasource, you have two options:
To successfully establish the connection, ToolJet requires the following details:
- **Connection String**: The connection string can be found on the dashboard of Azure Blob Storage.
Once you have entered the connection string, click on the **Test connection** button to verify the connection's success. To save the datasource, click on the **Save** button.
Once you have entered the connection string, click on the **Test connection** button to verify the connection's success. To save the data source, click on the **Save** button.
## Querying Azure Blob
Once you have connected to the Azure Blob global datasource, follow these steps to create queries and interact with a Azure Blob storage from the ToolJet application:
Once you have connected to the Azure Blob data source, follow these steps to create queries and interact with Azure Blob storage from the ToolJet application:
1. Open the ToolJet application and navigate to the query panel at the bottom of the app builder.
2. Click the `+Add` button to open the list of available `local` and `global datasources`.
3. Select **Azure Blob** from the global datasource section.
2. Click the `+Add` button to open the list of available `local` and `data sources`.
3. Select **Azure Blob** from the data source section.
4. Select the desired **operation** from the dropdown and enter the required **parameters**.
5. **Rename**(optional) and **Create** the query.
6. Click **Preview** to view the data returned from the query or click **Run** to execute the query.
@ -43,21 +43,21 @@ Query results can be transformed using Transformation. For more information on t
</div>
## Supported operations
## Supported Operations
1. **[Create container](#create-container)**
2. **[List containers](#list-containers)**
3. **[List blobs](#list-blobs)**
4. **[Upload blob](#upload-blob)**
5. **[Read blob](#read-blob)**
6. **[Delete blob](#delete-blob)**
1. **[Create Container](#create-container)**
2. **[List Containers](#list-containers)**
3. **[List Blobs](#list-blobs)**
4. **[Upload Blob](#upload-blob)**
5. **[Read Blob](#read-blob)**
6. **[Delete Blob](#delete-blob)**
### Create container
### Create Container
The create container operation enables the creation of new containers within Azure Blob storage. Containers serve as logical units for organizing and managing blob data. Users can provide a unique name for the container. Once created, the container is available for use in storing and organizing blob data. If the container with the same name already exists, the operation fails.
#### Required parameters:
#### Required Parameters:
- **Container Name:** Name of the container that you want to create.
@ -67,7 +67,7 @@ The create container operation enables the creation of new containers within Azu
</div>
### List containers
### List Containers
The list container operation allows you to retrieve a list of containers within Azure Blob storage.
@ -77,16 +77,16 @@ The list container operation allows you to retrieve a list of containers within
</div>
### List blobs
### List Blobs
The list blobs operation enables you to retrieve a list of blobs within a specific container in Azure Blob storage.
#### Required parameter:
#### Required Parameter:
- **Container:** Specify the name of the container from which you wish to retrieve a list of blobs.
- **Page Size:** Specify the maximum number of blobs to be returned per page or request.
#### Optional parameters:
#### Optional Parameters:
- **Prefix:** Filter the list of blobs based on a specific prefix or prefix pattern, allowing you to narrow down the results to blobs with names that start with the specified prefix.
- **Continuation Token:** A marker or token used to retrieve the next page of results when there are more blobs available beyond the initial page.
@ -97,11 +97,11 @@ The list blobs operation enables you to retrieve a list of blobs within a specif
</div>
### Upload blob
### Upload Blob
The upload blob operation allows you to upload a new blob or update an existing blob in Azure Blob storage. It provides a convenient way to store data such as files, images, or documents in the specified container.
#### Required parameters:
#### Required Parameters:
- **Container**: Specify the name of the container where the blob will be uploaded or updated.
- **Blob Name**: Provide a unique name for the blob. This name is used to identify and access the blob within the specified container.
@ -109,11 +109,11 @@ The upload blob operation allows you to upload a new blob or update an existing
- **Upload Data**: Select or provide the data to be uploaded as the content of the blob. This can be a file from your local system, binary data, or text content. You can also get the data from the exposed variable of the file picker component.
- **Encoding**: Choose the encoding format for the uploaded data if applicable. This parameter determines how the data is encoded before being stored as the blob content. If the value is left blank then it takes **UTF-8** by default.
### Read blob
### Read Blob
The read blob operation allows you to retrieve the content of a specific blob stored in Azure Blob storage. It enables you to access and retrieve the data stored within the blob for further processing or display.
#### Required parameters:
#### Required Parameters:
- **Container**: Specify the name of the container where the blob is located.
- **Blob Name**: Provide the unique name of the blob you want to read. This identifies the specific blob within the specified container
@ -124,11 +124,11 @@ The read blob operation allows you to retrieve the content of a specific blob st
</div>
### Delete blob
### Delete Blob
The delete blob operation allows you to remove a specific blob from Azure Blob storage. This operation permanently deletes the blob and its associated data, freeing up storage space and removing the blob from the container.
#### Required parameters:
#### Required Parameters:
- **Container**: Specify the name of the container from which you want to delete the blob.
- **Blob Name**: Provide the unique name of the blob you want to delete. This identifies the specific blob within the specified container.

View file

@ -5,25 +5,22 @@ title: Baserow
# Baserow
ToolJet can connect to your Baserow account to read and write data.
## Connection
ToolJet can connect to your Baserow account to read and write data.
Select the hosted version of Baserow or the self-host option.
To connect to Baserow, you need to provide the following details:
For [**self-hosted**](https://baserow.io/docs/index#installation) option, base URL is required to connect.
- **API token**: You can create an API token from your Baserow dashboard. You can follow the steps to create API token from [this link](https://baserow.io/user-docs/personal-api-tokens).
- **Host**: You can either select the Baserow Cloud or Self-hosted option.
- **Base URL**: If you select the self-hosted option, you need to provide the base URL of your Baserow instance.
Baserow API token is required to create an Baserow data source on ToolJet. You can follow the steps to create API token from [this link](https://baserow.io/api-docs).
<img className="screenshot-full" src="/img/datasource-reference/baserow/baserow-intro.png" alt="Baserow intro" />
:::tip
This guide assumes that you have already gone through [Adding a data source](/docs/tutorial/adding-a-datasource) tutorial.
:::
## Supported queries
## Supported Operations
- [List fields](#list-fields)
- [List rows](#list-rows)
- [Get row](#get-row)

View file

@ -9,7 +9,7 @@ ToolJet can trigger n8n workflows using webhook URLs. Please refer [this](https:
## Connection
Go to the data source manager on the left sidebar and click on `+` button to add new data source. Select n8n from the list of available data sources in the modal that pops-up.
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.
n8n webhooks can be called with or without an **Authentication**. You can keep the `Authentication type` as `none` if your webhook didn't have one or if it has one then you can choose the one from the dropdown and provide credentials:

View file

@ -9,6 +9,8 @@ ToolJet can connect to Oracle databases to read and write data.
## Connection
To establish a connection with the Oracle DB data source, click on the `+Add new` 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.
A Oracle DB can be connected with the following credentails:
- **Host**
- **Port**
@ -38,8 +40,6 @@ Once you have added a Oracle DB data source, click on `+` button of the query ma
SQL mode can be used to write raw SQL queries. Select SQL mode from the dropdown and enter the SQL query in the editor. Click on the `run` button to run the query.
**NOTE**: Query should be saved before running.
#### GUI mode
GUI mode can be used to query Oracle database without writing queries. Select GUI mode from the dropdown and then choose the operation **Bulk update using primary key**. Enter the **Table** name and **Primary key column** name. Now, in the editor enter the records in the form of an array of objects.
@ -50,4 +50,4 @@ Click on the **run** button to run the query. **NOTE**: Query should be saved be
:::tip
Query results can be transformed using transformations. Read our transformations documentation to see how: **[link](/docs/tutorial/transformations)**
:::
:::

View file

@ -3,43 +3,47 @@ id: control-component
title: Control component (Component Specific Actions)
---
Control component action invokes the component specific actions. Component specific actions are the actions that are exclusive actions for a particular widget. Component specific actions can be triggered either through the event handlers or from the Run JavaScript code query.
Control component action invokes the component specific actions. Component specific actions are the actions that are exclusive actions for a particular component. Component specific actions can be triggered either through the event handlers or from the Run JavaScript code query.
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>
<summary>Currently, Component specific actions are supported only by the below listed components.</summary>
<div>
<ul>
<li><a href="/docs/widgets/button#component-specific-actions-csa">Button</a></li>
<li><a href="/docs/widgets/checkbox#component-specific-actions-csa">Checkbox</a></li>
<li><a href="/docs/widgets/color-picker#component-specific-actions-csa">Color Picker</a></li>
<li><a href="/docs/widgets/dropdown#component-specific-actions-csa">Dropdown</a></li>
<li><a href="/docs/widgets/file-picker#component-specific-actions-csa">File Picker</a></li>
<li><a href="/docs/widgets/form#component-specific-actions-csa">Form</a></li>
<li><a href="/docs/widgets/icon#component-specific-actions-csa">Icon</a></li>
<li><a href="/docs/widgets/kanban#component-specific-actions-csa">Kanban</a></li>
<li><a href="/docs/widgets/link#component-specific-actions-csa">Link</a></li>
<li><a href="/docs/widgets/map#component-specific-actions-csa">Map</a></li>
<li><a href="/docs/widgets/modal#component-specific-actions-csa">Modal</a></li>
<li><a href="/docs/widgets/multiselect#component-specific-actions-csa">Multiselect</a></li>
<li><a href="/docs/widgets/radio-button#component-specific-actions-csa">Radio button</a></li>
<li><a href="/docs/widgets/table#component-specific-actions-csa">Table</a></li>
<li><a href="/docs/widgets/tabs#component-specific-actions-csa">Tabs</a></li>
<li><a href="/docs/widgets/text-input#component-specific-actions-csa">Text Input</a></li>
<li><a href="/docs/widgets/text#component-specific-actions-csa">Text</a></li>
<li><a href="/docs/widgets/textarea#component-specific-actions-csa">Text Area</a></li>
</ul>
</div>
</details>
:::info
Check out the **[live demo](https://youtu.be/JIhSH3YeM3E)** of Component specific actions demonstrated in one of our community call.
:::
## Available Component Specific Actions
| Widget | Component Specific Actions |
|--------|---------------------------|
| Button | Click, Set label, Disable, Visibility, Loading |
| Checkbox | Set checked |
| Color picker | Set color |
| Dropdown | Select option |
| File picker | Clear files |
| Kanban | Add card, Delete card, Move card, Update card data |
| Map | Set location |
| Modal | Show, Close |
| Multiselect | Select option, Deselect option, Clear selection |
| Radio button | Select option |
| Tabs | Set tab |
| Table | Set page, Select row, Deselect Row, Discard changes |
| Text | Set text, Set Visibility |
| Text Area | Set text, Clear |
| Text Input | Set text, Clear, Set Focus, Set Blur, Disable, Visibility |
:::info
Currently, Component specific actions are supported only by the above listed widgets. We are working on bringing component specific actions for the remaining widgets.
Check out the **[demo](https://youtu.be/JIhSH3YeM3E)** of Component specific actions demonstrated in one of our community call.
:::
## Using Component Specific Actions
### Set a value for text input widget using button's event handler
### Set a value for text input component using button's event handler
- Drag a **Text Input** and a **Button** widget onto the canvas.
- Drag a **Text Input** and a **Button** component onto the canvas.
- Go to the **Inspector** on the left sidebar to check the exposed variables available for the `textinput1` widget under the `components`. You'll see that the variable `value` is an empty string because the field value of the text input widget is empty right now.
- Go to the **Inspector** on the left sidebar to check the exposed variables available for the `textinput1` component under the `components`. You'll see that the variable `value` is an empty string because the field value of the text input component is empty right now.
<div style={{textAlign: 'center'}}>
@ -47,7 +51,7 @@ Currently, Component specific actions are supported only by the above listed wid
</div>
- Now enter some value in the text input widget and you'll see that the `value` in inspector has been updated.
- Now enter some value in the text input component and you'll see that the `value` in inspector has been updated.
<div style={{textAlign: 'center'}}>
@ -55,7 +59,7 @@ Currently, Component specific actions are supported only by the above listed wid
</div>
- Now, click on the button's widget handler to open up its properties in the right sidebar and then add a event handler for **On Click** event to trigger **Control Component** action. Select `textinput1` in component dropdown, `Set text` as Action, and in `Text` field enter the text that you want to update in the field value.
- Now, click on the button's component handler to open up its properties in the right sidebar and then add a event handler for **On Click** event to trigger **Control Component** action. Select `textinput1` in component dropdown, `Set text` as Action, and in `Text` field enter the text that you want to update in the field value.
<div style={{textAlign: 'center'}}>
@ -63,7 +67,7 @@ Currently, Component specific actions are supported only by the above listed wid
</div>
- Now when you'll click on the button you'll see that the field value of the text input widget has been updated with value that you set.
- Now when you'll click on the button you'll see that the field value of the text input component has been updated with value that you set.
<div style={{textAlign: 'center'}}>
@ -72,7 +76,7 @@ Currently, Component specific actions are supported only by the above listed wid
</div>
### Clear value of text input widget using JavaScript query
### Clear value of text input component using JavaScript query
- Let's clear the value that we set in the previous section, using Run JavaScript code. Create a new Run JavaScript Code query and call the component and the CSA that component provides.
@ -94,5 +98,5 @@ await components.textinput1.clear()
</div>
- Finally, hit the **save and run** query button to fire up the query, and you'll see that the field value of the text input widget has been cleared.
- Finally, hit the **save and run** query button to fire up the query, and you'll see that the field value of the text input component has been cleared.

View file

@ -5,22 +5,15 @@ title: Airtable
# Airtable
ToolJet can connect to your Airtable account to read and write data. **Airtable API key** is required to create an Airtable data source on ToolJet. You can generate API key by visiting [Airtable account page](https://airtable.com/account).
ToolJet can connect to your Airtable account to read and write data. Airtable Personal Access Token is required to connect to the Airtable data source on ToolJet. You can generate the PAT by visiting [Developer Hub from your Airtable profile](https://support.airtable.com/docs/creating-and-using-api-keys-and-access-tokens#understanding-personal-access-token-basic-actions).
<img className="screenshot-full" src="/img/datasource-reference/airtable/add_creds.gif" alt="irtable record"/>
:::info
Airtable API has a rate limit, and at the time of writing this documentation, the limit is five(5) requests per second per base. You can read more about rate limits here **[Airtable API]( https://airtable.com/api )**.
Airtable API has a rate limit, and at the time of writing this documentation, the limit is five(5) requests per second per base. You can read more about rate limits here **[Airtable API](https://airtable.com/api)**.
:::
:::tip
This guide assumes that you have already gone through [Adding a data source](/docs/tutorial/adding-a-datasource) tutorial.
:::
## Supported queries
## Supported Operations
- **[Listing records](#listing-records)**
- **[Retrieving a record](#retrieving-a-record)**
@ -30,113 +23,106 @@ This guide assumes that you have already gone through [Adding a data source](/do
### Listing records
This query lists all the records in a table. The results are paginated and each page can have up to 100 records.
This query lists all the records in a table. The results are paginated and each page can have up to 100 records.
#### Required parameters:
#### Required parameters:
- **Base ID:** To find the Base ID, first visit **airtable.com/api**. Select from the list of bases the base whose ID you'd like to find out. Example Base ID: `appDT3UCPffPiSmFd`
- **Table name:** Enter the table name whose data you want to fetch.
#### Optional parameters:
#### Optional parameters:
- **Page size:** The number of records returned in each request. Must be less than or equal to 100. Default is 100.
- **offset:** If there are more records, the response will contain an offset. To fetch the next page of records, include offset in the next request's parameters.
<img className="screenshot-full" src="/img/datasource-reference/airtable/listv2.png" alt="List airtable record" />
Example response from Airtable:
Example response from Airtable:
```json
{
"records": [
{
"id": "recu9xMnUdr2n2cw8",
"fields": {
"Notes": "sdfdsf",
"Name": "dsfdsf"
},
"createdTime": "2021-05-12T14:30:33.000Z"
},
{
"id": "recyIdR7bVdQvmKXa",
"fields": {
"Notes": "sdfdsf",
"Name": "dfds"
},
"createdTime": "2021-05-12T14:30:33.000Z"
},
{
"id": "recAOzdIHaRpvRaGE",
"fields": {
"Notes": "sdfsdfsd",
"Name": "sdfdsf"
},
"createdTime": "2021-05-12T14:30:33.000Z"
}
],
"offset": "recAOzdIHaRpvRaGE"
"records": [
{
"id": "recu9xMnUdr2n2cw8",
"fields": {
"Notes": "sdfdsf",
"Name": "dsfdsf"
},
"createdTime": "2021-05-12T14:30:33.000Z"
},
{
"id": "recyIdR7bVdQvmKXa",
"fields": {
"Notes": "sdfdsf",
"Name": "dfds"
},
"createdTime": "2021-05-12T14:30:33.000Z"
},
{
"id": "recAOzdIHaRpvRaGE",
"fields": {
"Notes": "sdfsdfsd",
"Name": "sdfdsf"
},
"createdTime": "2021-05-12T14:30:33.000Z"
}
],
"offset": "recAOzdIHaRpvRaGE"
}
```
### Retrieving a record
#### Required parameters:
#### Required parameters:
- **Base ID**
- **Table name**
- **Table name**
- **Record ID**
<img className="screenshot-full" src="/img/datasource-reference/airtable/retv2.png" alt="Retrieve airtable record" />
Example response from Airtable:
Example response from Airtable:
```json
{
"id": "recu9xMnUdr2n2cw8",
"fields": {
"Notes": "sdfdsf",
"Name": "dsfdsf"
},
"createdTime": "2021-05-12T14:30:33.000Z"
"id": "recu9xMnUdr2n2cw8",
"fields": {
"Notes": "sdfdsf",
"Name": "dsfdsf"
},
"createdTime": "2021-05-12T14:30:33.000Z"
}
```
### Creating a record
#### Required parameters:
- **Base ID**
- **Table name**
- **Records**
<img className="screenshot-full" src="/img/datasource-reference/airtable/createv2.png" alt="Create airtable record" />
#### Example Records:
```json
[
{
"fields": {
"Notes": "sdfdsf",
"Name": "dsfdsf"
}
},
{
"fields": {
"Notes": "note1",
"Name": "dsfdsf"
}
{
"fields": {
"Notes": "sdfdsf",
"Name": "dsfdsf"
}
},
{
"fields": {
"Notes": "note1",
"Name": "dsfdsf"
}
}
]
```
Click on the `run` button to run the query.
:::info
@ -144,37 +130,38 @@ NOTE: Query must be saved before running.
:::
Example response from Airtable:
```json
{
"records": [
{
"id": "rec5RuZ1COoZGtGDY",
"fields": {
"Notes": "sdfdsf",
"Name": "dsfdsf"
},
"createdTime": "2022-02-07T20:25:27.000Z"
},
{
"id": "recaYbFPonNNu6Cwj",
"fields": {
"Notes": "note1",
"Name": "dsfdsf"
},
"createdTime": "2022-02-07T20:25:27.000Z"
}
]
"records": [
{
"id": "rec5RuZ1COoZGtGDY",
"fields": {
"Notes": "sdfdsf",
"Name": "dsfdsf"
},
"createdTime": "2022-02-07T20:25:27.000Z"
},
{
"id": "recaYbFPonNNu6Cwj",
"fields": {
"Notes": "note1",
"Name": "dsfdsf"
},
"createdTime": "2022-02-07T20:25:27.000Z"
}
]
}
```
### Updating a record
#### Required parameters:
- **Base ID**
- **Table name**
- **Record ID**
<img className="screenshot-full" src="/img/datasource-reference/airtable/updv2.png" alt="Update airtable record"/>
#### Example body:
@ -192,27 +179,28 @@ NOTE: Query must be saved before running.
:::
Example response from Airtable:
```json
{
"id": "recu9xMnUdr2n2cw8",
"fields": {
"Notes": "Example Notes",
"Name": "change"
},
"createdTime": "2021-08-08T17:27:17.000Z"
"id": "recu9xMnUdr2n2cw8",
"fields": {
"Notes": "Example Notes",
"Name": "change"
},
"createdTime": "2021-08-08T17:27:17.000Z"
}
```
### Deleting a record
#### Required parameters:
- **Base ID**
- **Table name**
- **Record ID**
<img className="screenshot-full" src="/img/datasource-reference/airtable/delv2.png" alt="Delete airtable record" />
Click on the `run` button to run the query.
:::info
@ -226,4 +214,4 @@ Example response from Airtable:
deleted: true
id: "recIKsyZgqI4zoqS7"
}
```
```

View file

@ -9,6 +9,8 @@ ToolJet can connect to Amazon Athena which is an interactive query service that
## 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.
ToolJet requires the following to connect to your Athena.
- **Database**
@ -29,14 +31,8 @@ You can also configure for **[additional optional parameters](https://github.com
- Click on `+` button of the query manager at the bottom panel of the editor and select the database added in the previous step as the datasource. Query manager then can be used to write SQL queries.
<img className="screenshot-full" src="/img/datasource-reference/athena/athena-query.png" alt="Athena query" />
- Click on the `run` button to run the query.
**NOTE:** Query should be saved before running.
:::tip
**Refer amazon athena docs here for more info:** [link](https://docs.aws.amazon.com/athena/latest/ug/what-is.html)
:::

View file

@ -7,9 +7,9 @@ ToolJet offers the capability to establish a connection with Azure Blob storage
## Connection
To connect ToolJet with the Azure Blob global datasource, you have two options:
1. Click on the `+Add new global datasource` button in the query panel.
2. Go to the **[Global Datasources](/docs/data-sources/overview)** page on the ToolJet dashboard.
To connect ToolJet with the Azure Blob data source, you have two options:
1. Click on the `+Add new data source` button in the query panel.
2. Go to the **[Data Sources](/docs/data-sources/overview)** page on the ToolJet dashboard.
<div style={{textAlign: 'center'}}>
@ -20,15 +20,15 @@ To connect ToolJet with the Azure Blob global datasource, you have two options:
To successfully establish the connection, ToolJet requires the following details:
- **Connection String**: The connection string can be found on the dashboard of Azure Blob Storage.
Once you have entered the connection string, click on the **Test connection** button to verify the connection's success. To save the datasource, click on the **Save** button.
Once you have entered the connection string, click on the **Test connection** button to verify the connection's success. To save the data source, click on the **Save** button.
## Querying Azure Blob
Once you have connected to the Azure Blob global datasource, follow these steps to create queries and interact with a Azure Blob storage from the ToolJet application:
Once you have connected to the Azure Blob data source, follow these steps to create queries and interact with Azure Blob storage from the ToolJet application:
1. Open the ToolJet application and navigate to the query panel at the bottom of the app builder.
2. Click the `+Add` button to open the list of available `local` and `global datasources`.
3. Select **Azure Blob** from the global datasource section.
2. Click the `+Add` button to open the list of available `local` and `data sources`.
3. Select **Azure Blob** from the data source section.
4. Select the desired **operation** from the dropdown and enter the required **parameters**.
5. **Rename**(optional) and **Create** the query.
6. Click **Preview** to view the data returned from the query or click **Run** to execute the query.
@ -43,21 +43,21 @@ Query results can be transformed using Transformation. For more information on t
</div>
## Supported operations
## Supported Operations
1. **[Create container](#create-container)**
2. **[List containers](#list-containers)**
3. **[List blobs](#list-blobs)**
4. **[Upload blob](#upload-blob)**
5. **[Read blob](#read-blob)**
6. **[Delete blob](#delete-blob)**
1. **[Create Container](#create-container)**
2. **[List Containers](#list-containers)**
3. **[List Blobs](#list-blobs)**
4. **[Upload Blob](#upload-blob)**
5. **[Read Blob](#read-blob)**
6. **[Delete Blob](#delete-blob)**
### Create container
### Create Container
The create container operation enables the creation of new containers within Azure Blob storage. Containers serve as logical units for organizing and managing blob data. Users can provide a unique name for the container. Once created, the container is available for use in storing and organizing blob data. If the container with the same name already exists, the operation fails.
#### Required parameters:
#### Required Parameters:
- **Container Name:** Name of the container that you want to create.
@ -67,7 +67,7 @@ The create container operation enables the creation of new containers within Azu
</div>
### List containers
### List Containers
The list container operation allows you to retrieve a list of containers within Azure Blob storage.
@ -77,16 +77,16 @@ The list container operation allows you to retrieve a list of containers within
</div>
### List blobs
### List Blobs
The list blobs operation enables you to retrieve a list of blobs within a specific container in Azure Blob storage.
#### Required parameter:
#### Required Parameter:
- **Container:** Specify the name of the container from which you wish to retrieve a list of blobs.
- **Page Size:** Specify the maximum number of blobs to be returned per page or request.
#### Optional parameters:
#### Optional Parameters:
- **Prefix:** Filter the list of blobs based on a specific prefix or prefix pattern, allowing you to narrow down the results to blobs with names that start with the specified prefix.
- **Continuation Token:** A marker or token used to retrieve the next page of results when there are more blobs available beyond the initial page.
@ -97,11 +97,11 @@ The list blobs operation enables you to retrieve a list of blobs within a specif
</div>
### Upload blob
### Upload Blob
The upload blob operation allows you to upload a new blob or update an existing blob in Azure Blob storage. It provides a convenient way to store data such as files, images, or documents in the specified container.
#### Required parameters:
#### Required Parameters:
- **Container**: Specify the name of the container where the blob will be uploaded or updated.
- **Blob Name**: Provide a unique name for the blob. This name is used to identify and access the blob within the specified container.
@ -109,11 +109,11 @@ The upload blob operation allows you to upload a new blob or update an existing
- **Upload Data**: Select or provide the data to be uploaded as the content of the blob. This can be a file from your local system, binary data, or text content. You can also get the data from the exposed variable of the file picker component.
- **Encoding**: Choose the encoding format for the uploaded data if applicable. This parameter determines how the data is encoded before being stored as the blob content. If the value is left blank then it takes **UTF-8** by default.
### Read blob
### Read Blob
The read blob operation allows you to retrieve the content of a specific blob stored in Azure Blob storage. It enables you to access and retrieve the data stored within the blob for further processing or display.
#### Required parameters:
#### Required Parameters:
- **Container**: Specify the name of the container where the blob is located.
- **Blob Name**: Provide the unique name of the blob you want to read. This identifies the specific blob within the specified container
@ -124,11 +124,11 @@ The read blob operation allows you to retrieve the content of a specific blob st
</div>
### Delete blob
### Delete Blob
The delete blob operation allows you to remove a specific blob from Azure Blob storage. This operation permanently deletes the blob and its associated data, freeing up storage space and removing the blob from the container.
#### Required parameters:
#### Required Parameters:
- **Container**: Specify the name of the container from which you want to delete the blob.
- **Blob Name**: Provide the unique name of the blob you want to delete. This identifies the specific blob within the specified container.

View file

@ -5,24 +5,21 @@ title: Baserow
# Baserow
ToolJet can connect to your Baserow account to read and write data.
## Connection
ToolJet can connect to your Baserow account to read and write data.
Select the hosted version of Baserow or the self-host option.
To connect to Baserow, you need to provide the following details:
For [**self-hosted**](https://baserow.io/docs/index#installation) option, base URL is required to connect.
Baserow API token is required to create an Baserow data source on ToolJet. You can follow the steps to create API token from [this link](https://baserow.io/api-docs).
- **API token**: You can create an API token from your Baserow dashboard. You can follow the steps to create API token from [this link](https://baserow.io/user-docs/personal-api-tokens).
- **Host**: You can either select the Baserow Cloud or Self-hosted option.
- **Base URL**: If you select the self-hosted option, you need to provide the base URL of your Baserow instance.
<img className="screenshot-full" src="/img/datasource-reference/baserow/baserow-intro.png" alt="Baserow intro" />
:::tip
This guide assumes that you have already gone through [Adding a data source](/docs/tutorial/adding-a-datasource) tutorial.
:::
## Supported queries
## Supported Operations
- [List fields](#list-fields)
- [List rows](#list-rows)

View file

@ -9,7 +9,7 @@ ToolJet can trigger n8n workflows using webhook URLs. Please refer [this](https:
## Connection
Go to the data source manager on the left sidebar and click on `+` button to add new data source. Select n8n from the list of available data sources in the modal that pops-up.
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.
n8n webhooks can be called with or without an **Authentication**. You can keep the `Authentication type` as `none` if your webhook didn't have one or if it has one then you can choose the one from the dropdown and provide credentials:

View file

@ -9,6 +9,8 @@ ToolJet can connect to Oracle databases to read and write data.
## Connection
To establish a connection with the Oracle DB data source, click on the `+Add new` 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.
A Oracle DB can be connected with the following credentails:
- **Host**
- **Port**
@ -38,7 +40,6 @@ Once you have added a Oracle DB data source, click on `+` button of the query ma
SQL mode can be used to write raw SQL queries. Select SQL mode from the dropdown and enter the SQL query in the editor. Click on the `run` button to run the query.
**NOTE**: Query should be saved before running.
#### GUI mode
@ -50,4 +51,4 @@ Click on the **run** button to run the query. **NOTE**: Query should be saved be
:::tip
Query results can be transformed using transformations. Read our transformations documentation to see how: **[link](/docs/tutorial/transformations)**
:::
:::

View file

@ -0,0 +1,5 @@
{
"label": "Enterprise",
"position": 9,
"collapsed": true
}

View file

@ -0,0 +1,93 @@
---
id: audit_logs
title: Audit logs
---
<div className='badge badge--primary heading-badge'>Available on: Paid plans</div>
The audit log is the report of all the activities done in your ToolJet account. It will capture and display events automatically by recording who performed an activity, what when, and where the activity was performed, along with other information such as IP address.
<div style={{textAlign: 'center'}}>
<img className="screenshot-full" src="/img/enterprise/audit_logs/logsnew.png" alt="Audit logs" />
</div>
### Date Range
Retrieve the log of events that occurred within the specified date and time range using the range picker. By default, the system loads 24-hour logs for the initial view. The maximum duration that can be specified for the "from" and "to" dates is 30 days.
:::info
Pagination at the bottom allows navigation through the pages, with each page displaying a maximum of 7 logs.
:::
<div style={{textAlign: 'center'}}>
<img className="screenshot-full" src="/img/enterprise/audit_logs/filtersnew.png" alt="Audit logs" />
</div>
### Filter Audit Logs
You can apply filters to the audited events based on the following criteria.
#### Select Users
Choose a specific user from the dropdown list to view all their activities.
#### Select Apps
The dropdown will display all the apps associated with your account. Select an app to filter the logs related to that particular app.
#### Select Resources
| Resources | description |
| ----------- | ----------- |
| User | Filter all the User events like `USER_LOGIN`, `USER_SIGNUP`, `USER_INVITE`, AND `USER_INVITE_REDEEM`. |
| App | Filter all the App events like `APP_CREATE`, `APP_UPDATE`,`APP_VIEW`,`APP_DELETE`,`APP_IMPORT`,`APP_EXPORT`,`APP_CLONE`. |
| Data Query | Filters the events associated with Data Query like `DATA_QUERY_RUN`. |
| Group Permission | All the events associated with Group Permissions will be filtered. Group Permissions include `GROUP_CREATE`, `GROUP_UPDATE`, `GROUP_DELETE`. |
| App Group Permission | Within each group, you can set apps for read or edit privileges. These events get recorded as App Group Permissions. |
#### Select Actions
| Actions | description |
| ----------- | ----------- |
| USER_LOGIN | This event is recorded everytime a user logins. |
| USER_SIGNUP | This event is recorded everytime a new signup is made. |
| USER_INVITE | You can invite users to your account from `Manage Users` section and an event is audited everytime an invite is sent. |
| USER_INVITE_REDEEM | This event is recorded whenever an invite is redeemed. |
| APP_CREATE | This event is recorded when a user creates a new app. |
| APP_UPDATE | This event is recorded whenever actions like renaming the app, making the app public, editing shareable link, or deploying the app are made. |
| APP_VIEW | This event is logged when someone views the launched app. (public apps aren't accounted for) |
| APP_DELETE | This event is recorded whenever a user deletes an app from the dashboard. |
| APP_IMPORT | This event is recorded whenever a user imports an app. |
| APP_EXPORT | This event is recorded whenever an app is exported. |
| APP_CLONE | This event is recorded whenever a clone of the existing app is created. |
| DATA_QUERY_RUN | This event is logged whenever a data source is added, a query is created, or whenever a query is run either from the query editor or from the launched app. |
| GROUP_PERMISSION_CREATE | This event is recorded whenever a group is created. |
| GROUP_PERMISSION_UPDATE | This event is recorded whenever an app or user is added to or removed from a group, or the permissions for a group are updated. |
| GROUP_PERMISSION_DELETE | This event is recorded whenever a user group is deleted from an account. |
| APP_GROUP_PERMISSION_UPDATE | For every app added in to user group, you can set privileges like `View` or `Edit` and whenever these privileges are updated this event is recorded. By default, the permission of an app for a user group is set to `View`. |
### Understanding Log Information
<div style={{textAlign: 'center'}}>
<img className="screenshot-full" src="/img/enterprise/audit_logs/readinglogv2.png" alt="Audit logs" />
</div>
| Property | Description |
| ----------- | ----------- |
| action_type | This indicates the type of action that was logged in the event. Refer to [this](#select-actions) for more information on actions. |
| created_at | Shows the date and time when the event was logged. |
| id | Each logged event is assigned a unique event ID. |
| ip_address | Displays the IP address from which the event was logged. |
| metadata | The metadata includes two sub-properties: `tooljet_version` and `user_agent`. `tooljet_version` shows the version of ToolJet used for the event, while `user_agent` contains information about the device and browser used. |
| organization_id | Every organization in ToolJet has a unique ID associated with it, which is recorded when an event occurs. |
| resource_id | Different [resources](#select-resources) have their respective IDs associated with them. These IDs are assigned when the resources are created. |
| resource_name | Shows the name of the [resources](#select-resources) that were involved in the logged event. For example, if an app was created or deleted, it will display the name of that app. |
| resource_type | Indicates the type of the [resources](#select-resources) involved in the logged event. |
| user_id | Each user account in ToolJet has a unique ID associated with it, which is recorded when an event occurs. |

View file

@ -0,0 +1,158 @@
---
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.
## How is Super Admin different from Admin
| Privilege | 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#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-setting-groupsssoworkspace-constants) | ❌ | ✅ |
| [Manage all users from all the workspaces in the instance](#manage-all-users-in-the-instance) | ❌ | ✅ |
| [Make any user Super Admin](#make-the-user-super-admin) | ❌ | ✅ |
| [Restrict creation of personal workspace of users](#restrict-creation-of-personal-workspace-of-users) | ❌ | ✅ |
| [Enable Multiplayer editing](#enable-multiplayer-editing) | ❌ | ✅ |
| [Implement White Labelling](#white-labelling) | ❌ | ✅ |
<div style={{textAlign: 'center'}}>
<img className="screenshot-full" src="/img/enterprise/superadmin/instanceset.png" alt="Super Admin: Enterprise" />
</div>
## Super Admin features
### Access any workspace
If a user has Super Admin privileges, 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 className="screenshot-full" src="/img/enterprise/superadmin/workspaceswitcher.png" alt="Super Admin: Enterprise" />
</div>
### Create, Edit or Delete apps from any user's personal workspace
Once the Super Admin accesses 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 className="screenshot-full" src="/img/enterprise/superadmin/unarchivesa.png" alt="Super Admin: Enterprise" />
</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
## Instance Settings
Only Super Admins can access the Instance Settings:
- **All Users**
- **Manage Instance Settings**
- **License**
- **White labelling**
## All Users
### Manage all users in the instance
**All Users** page can be used to check the list of all the users 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 from this page.
<div style={{textAlign: 'center'}}>
<img className="screenshot-full" src="/img/enterprise/superadmin/allusersa.png" alt="Super Admin: Enterprise" />
</div>
### Archiving a user from workspace
Super Admins have the privilege to remove any user from any workspace to which they belong.
Super Admins can go to **All Users** page, Under the **Workspaces** column they'll see the number of workspaces a user belongs to. Click on the **`View(n)`**, a modal will pop up that will have the list of **`n`** number the workspaces, click on the **Archive/Unarchive** button next to the workspace name to remove the user from the workspace.
<div style={{textAlign: 'center'}}>
<img className="screenshot-full" src="/img/enterprise/superadmin/archivesa.png" alt="Super Admin: Enterprise" />
</div>
### Make the user super admin
Super Admins can make any user as Super Admin or remove any Super Admin from the **Manage All Users** in the Instance Settings page.
Click on the **Edit** button next to any user, **Enable** the **Make the user Super Admin** option, and then **Save** it.
The user will become Super Admin and the Type column will update from **`workspace`** to **`instance`**.
<div style={{textAlign: 'center'}}>
<img className="screenshot-full" src="/img/enterprise/superadmin/saset.png" alt="Super Admin: Enterprise" />
</div>
## Manage Instance Settings
<div style={{textAlign: 'center'}}>
<img className="screenshot-full" src="/img/enterprise/superadmin/instancesett.png" alt="Super Admin: Enterprise" />
</div>
### 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 Instance 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.
### Enable multiplayer editing
Super Admins can enable multiplayer editing from the Manage Instance Settings page. Once enabled, users will be able to edit the same app simultaneously resulting in real-time collaboration.
## License
Manage the instance license via the **Instance Settings** page. Super Admins have the capability to update the instance's license key from this page.
Check out the [License](/docs/licensing) page for more details.
## 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.

View file

@ -0,0 +1,48 @@
---
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 className="screenshot-full" src="/img/enterprise/white-label/newdash.png" alt="ToolJet - Enterprise - White label"/>
</div>
- **Favicon**: The small icon associated with your application.
<div style={{textAlign: 'center'}}>
<img className="screenshot-full" src="/img/enterprise/white-label/newfav.png" alt="ToolJet - Enterprise - White label"/>
</div>
- **Page Title**: This is the text displayed next to the Favicon.
<div style={{textAlign: 'center'}}>
<img className="screenshot-full" src="/img/enterprise/white-label/title.png" alt="ToolJet - Enterprise - White label" />
</div>
## Configuration
To enable white labelling, you'll need to go to the **Instance Settings** from the Dashboard and 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 className="screenshot-full" src="/img/enterprise/white-label/whitelabelsettings.png" alt="ToolJet - Enterprise - White label" />
</div>

View file

@ -0,0 +1,5 @@
{
"label": "Actions Reference",
"position": 7,
"collapsed": true
}

View file

@ -0,0 +1,19 @@
---
id: close-modal
title: Close modal
---
Use this action to close the modal that is already shown.
Debounce field is empty by default, you can enter a numerical value to specify the time in milliseconds after which the action will be performed. ex: `300`
:::info
You can also trigger actions from the **JavaScript code**. Check it out [here](/docs/how-to/run-actions-from-runjs).
:::
<div style={{textAlign: 'center'}}>
<img className="screenshot-full" src="/img/actions/closemodal/closemodal2.png" alt="ToolJet - Action reference - Close modal" width="700" />
</div>

View file

@ -0,0 +1,102 @@
---
id: control-component
title: Control component (Component Specific Actions)
---
Control component action invokes the component specific actions. Component specific actions are the actions that are exclusive actions for a particular component. Component specific actions can be triggered either through the event handlers or from the Run JavaScript code query.
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>
<summary>Currently, Component specific actions are supported only by the below listed components.</summary>
<div>
<ul>
<li><a href="/docs/widgets/button#component-specific-actions-csa">Button</a></li>
<li><a href="/docs/widgets/checkbox#component-specific-actions-csa">Checkbox</a></li>
<li><a href="/docs/widgets/color-picker#component-specific-actions-csa">Color Picker</a></li>
<li><a href="/docs/widgets/dropdown#component-specific-actions-csa">Dropdown</a></li>
<li><a href="/docs/widgets/file-picker#component-specific-actions-csa">File Picker</a></li>
<li><a href="/docs/widgets/form#component-specific-actions-csa">Form</a></li>
<li><a href="/docs/widgets/icon#component-specific-actions-csa">Icon</a></li>
<li><a href="/docs/widgets/kanban#component-specific-actions-csa">Kanban</a></li>
<li><a href="/docs/widgets/link#component-specific-actions-csa">Link</a></li>
<li><a href="/docs/widgets/map#component-specific-actions-csa">Map</a></li>
<li><a href="/docs/widgets/modal#component-specific-actions-csa">Modal</a></li>
<li><a href="/docs/widgets/multiselect#component-specific-actions-csa">Multiselect</a></li>
<li><a href="/docs/widgets/radio-button#component-specific-actions-csa">Radio button</a></li>
<li><a href="/docs/widgets/table#component-specific-actions-csa">Table</a></li>
<li><a href="/docs/widgets/tabs#component-specific-actions-csa">Tabs</a></li>
<li><a href="/docs/widgets/text-input#component-specific-actions-csa">Text Input</a></li>
<li><a href="/docs/widgets/text#component-specific-actions-csa">Text</a></li>
<li><a href="/docs/widgets/textarea#component-specific-actions-csa">Text Area</a></li>
</ul>
</div>
</details>
:::info
Check out the **[demo](https://youtu.be/JIhSH3YeM3E)** of Component specific actions demonstrated in one of our community call.
:::
## Using Component Specific Actions
### Set a value for text input component using button's event handler
- Drag a **Text Input** and a **Button** component onto the canvas.
- Go to the **Inspector** on the left sidebar to check the exposed variables available for the `textinput1` component under the `components`. You'll see that the variable `value` is an empty string because the field value of the text input component is empty right now.
<div style={{textAlign: 'center'}}>
![ToolJet - Action reference - Control Component](/img/actions/controlcomponent/inspector.png)
</div>
- Now enter some value in the text input component and you'll see that the `value` in inspector has been updated.
<div style={{textAlign: 'center'}}>
![ToolJet - Action reference - Control Component](/img/actions/controlcomponent/updated.png)
</div>
- Now, click on the button's component handler to open up its properties in the right sidebar and then add a event handler for **On Click** event to trigger **Control Component** action. Select `textinput1` in component dropdown, `Set text` as Action, and in `Text` field enter the text that you want to update in the field value.
<div style={{textAlign: 'center'}}>
![ToolJet - Action reference - Control Component](/img/actions/controlcomponent/button.png)
</div>
- Now when you'll click on the button you'll see that the field value of the text input component has been updated with value that you set.
<div style={{textAlign: 'center'}}>
![ToolJet - Action reference - Control Component](/img/actions/controlcomponent/set.png)
</div>
### Clear value of text input component using JavaScript query
- Let's clear the value that we set in the previous section, using Run JavaScript code. Create a new Run JavaScript Code query and call the component and the CSA that component provides.
**Syntax:**
```js
await components.textinput1.clear()
```
<div style={{textAlign: 'center'}}>
![ToolJet - Action reference - Control Component](/img/actions/controlcomponent/jsoption.png)
</div>
<div style={{textAlign: 'center'}}>
![ToolJet - Action reference - Control Component](/img/actions/controlcomponent/clear.png)
</div>
- Finally, hit the **save and run** query button to fire up the query, and you'll see that the field value of the text input component has been cleared.

View file

@ -0,0 +1,18 @@
---
id: copy-to-clipboard
title: Copy to clipboard
---
Use this action to copy the text to the clipboard.
Debounce field is empty by default, you can enter a numerical value to specify the time in milliseconds after which the action will be performed. ex: `300`
:::info
You can also trigger actions from the **JavaScript code**. Check it out [here](/docs/how-to/run-actions-from-runjs).
:::
<div style={{textAlign: 'center'}}>
<img className="screenshot-full" src="/img/actions/copytoclipboard/copy2.png" alt="ToolJet - Action reference - Copy to clipboard" width="700" />
</div>

View file

@ -0,0 +1,56 @@
---
id: generate-file
title: Generate file
---
# Generate file
This action allows you to construct files on the fly and let users download it.
## Options
| Option | Description |
|--------|-------------|
| Type | Type of file to be generated. Types: `CSV`, `Text` and `PDF` |
| File name | Name of the file to be generated |
| Data | Data that will be used to construct the file. Its format will depend on the file type, as specified in the following section |
| Debounce | Debounce field is empty by default, you can enter a numerical value to specify the time in milliseconds after which the action will be performed. ex: `300` |
:::tip
Check how to run **[generate file action using RunJS](/docs/how-to/run-actions-from-runjs/#generate-file)**.
:::
### CSV Data Format
To use the `CSV` file format, the data field should contain an array of objects. ToolJet assumes that the keys in each object are the same and represent the column headers of the CSV file.
Example:
```javascript
{{
[
{ name: 'John', email: 'john@tooljet.com' },
{ name: 'Sarah', email: 'sarah@tooljet.com' },
]
}}
```
Using the above code snippet will generate a CSV file with the following content:
```csv
name,email
John,john@tooljet.com
Sarah,sarah@tooljet.com
```
### Text Data Format
To use the `Text` file format, the data field should contain a string.
If you want to generate a text file based on an array of objects, you need to stringify the data before providing it.
For example, if you are using the table component to provide the data, you can enter **`{{JSON.stringify(components.table1.currentPageData)}}`** in the Data field.
### PDF data format
The PDF data format supports two types of input: either a `string` or an `array of objects`. When using an array of objects, the resulting PDF will display the data in a tabular format with columns and rows. On the other hand, if a string is provided, the generated PDF will consist of plain text.

View file

@ -0,0 +1,20 @@
---
id: go-to-app
title: Go to app
---
This action allows you to open any ToolJet application when an event occurs.
Debounce field is empty by default, you can enter a numerical value to specify the time in milliseconds after which the action will be performed. ex: `300`
:::info
You can also trigger actions from the **JavaScript code**. Check it out [here](/docs/how-to/run-actions-from-runjs).
:::
<div style={{textAlign: 'center'}}>
<img className="screenshot-full" src="/img/actions/gotoapp/gotoapp2.png" alt="ToolJet - Action reference - Open webpage" width="700" />
</div>

View file

@ -0,0 +1,18 @@
---
id: logout
title: Logout
---
This action allows you to log out of the application (ToolJet).
Debounce field is empty by default, you can enter a numerical value to specify the time in milliseconds after which the action will be performed. ex: `300`
:::info
You can also trigger actions from the **JavaScript code**. Check it out [here](/docs/how-to/run-actions-from-runjs).
:::
<div style={{textAlign: 'center'}}>
<img className="screenshot-full" src="/img/actions/logout/logout2.png" alt="ToolJet - Action reference - Logout" width="700" />
</div>

View file

@ -0,0 +1,18 @@
---
id: open-webpage
title: Open webpage
---
You can use this action to open a webpage(on a new tab) for any event.
Debounce field is empty by default, you can enter a numerical value to specify the time in milliseconds after which the action will be performed. ex: `300`
:::info
You can also trigger actions from the **JavaScript code**. Check it out [here](/docs/how-to/run-actions-from-runjs).
:::
<div style={{textAlign: 'center'}}>
<img className="screenshot-full" src="/img/actions/open-webpage/open2.png" alt="ToolJet - Action reference - Open webpage" width="700" />
</div>

View file

@ -0,0 +1,18 @@
---
id: run-query
title: Run Query
---
This action allows you to fire queries when an event occurs.
Debounce field is empty by default, you can enter a numerical value to specify the time in milliseconds after which the action will be performed. ex: `300`
:::info
You can also trigger actions from the **JavaScript code**. Check it out [here](/docs/how-to/run-actions-from-runjs).
:::
<div style={{textAlign: 'center'}}>
<img className="screenshot-full" src="/img/actions/run-query/run-query2.png" alt="ToolJet - Action reference - Run Query" width="700" />
</div>

View file

@ -0,0 +1,59 @@
---
id: set-localstorage
title: Set localStorage
---
# Set localStorage
This action allows you to specify a `key` and its corresponding `value` to be stored in localStorage.
## Example: App that stores a name in localStorage and displays it on reload
1. Add an input field, button and a text as shown
<div style={{textAlign: 'center'}}>
![ToolJet - Action reference -Set local storage sample app](/img/actions/localstorage/1.png)
</div>
2. Select the button and add a `Set localStorage` action with `key` set to `name` and value pointing at the value of the text field
<div style={{textAlign: 'center'}}>
![ToolJet - Action reference -Set local storage sample app](/img/actions/localstorage/2.png)
</div>
3. Select the text label we've added and set its value to the name item from localStorage.
:::info
Debounce field is empty by default, you can enter a numerical value to specify the time in milliseconds after which the action will be performed. ex: `300`
:::
<div style={{textAlign: 'center'}}>
![ToolJet - Action reference -Set local storage sample app](/img/actions/localstorage/debounce.png)
</div>
4. Now save the application, this is important as we're about to reload the page.
5. Type in anything you wish on the input box and click on the button
<div style={{textAlign: 'center'}}>
![ToolJet - Action reference -Set local storage sample app](/img/actions/localstorage/5.png)
</div>
6. Reload the page, you'll see that the value stored in local storage is persisted and it is displayed on screen!
<div style={{textAlign: 'center'}}>
![ToolJet - Action reference -Set local storage sample app](/img/actions/localstorage/6.png)
</div>

View file

@ -0,0 +1,36 @@
---
id: set-page-variable
title: Set page variable
---
Page variables are restricted to the page where they are created and cannot be accessed throughout the entire application like regular variables.
Use this action to establish a variable and assign a value to it within the [Multipage Apps](/docs/tutorial/pages).
By default, the debounce field is left empty. However, you can input a numeric value to indicate the time in milliseconds before the action is executed. For example, `300`.
<div style={{textAlign: 'center'}}>
<img className="screenshot-full" src="/img/actions/page/setpagevar2.png" alt="ToolJet - Action reference - Switch page" width="600"/>
</div>
## Using RunJS query to set page variable
Alternatively, the set page variable action can be triggered via a RunJS query using the following syntax:
```js
await actions.setPageVariable('<variablekey>',<variablevalue>)
```
`variablekey` must be provided as a string (enclosed in quotes), while the `variablevalue` does not require quotation marks if it is a numerical value.
<div style={{textAlign: 'center'}}>
<img className="screenshot-full" src="/img/actions/page/setpagevar33.png" alt="ToolJet - Action reference - Switch page" />
</div>
:::info
For instructions on how to run actions from a RunJS query, refer to the how-to guide [Running Actions from RunJS Query](/docs/how-to/run-actions-from-runjs).
:::

View file

@ -0,0 +1,24 @@
---
id: set-table-page
title: Set Table Page
---
Use this action to change the page index in the table widget.
## Options
| Option | Description |
|--------|-------------|
| Table | Select table from the dropdown |
| Page Index | Numerical value for the page index. ex: `{{2}}` |
| Debounce | Debounce field is empty by default, you can enter a numerical value to specify the time in milliseconds after which the action will be performed. ex: `300` |
:::info
You can also trigger actions from the **JavaScript code**. Check it out [here](/docs/how-to/run-actions-from-runjs).
:::
<div style={{textAlign: 'center'}}>
<img className="screenshot-full" src="/img/actions/settablepage/page2.png" alt="ToolJet - Action reference - Open webpage" width="700" />
</div>

View file

@ -0,0 +1,24 @@
---
id: set-variable
title: Set variable
---
This action allows you to create a variable and assign a `value` to it.
## Options
| Option | Description |
|--------|-------------|
| Key | Name(String) of the variable through which you can access the value |
| Value | A value can be a string, number, boolean expression, array, or object |
| Debounce | Debounce field is empty by default, you can enter a numerical value to specify the time in milliseconds after which the action will be performed. ex: `300` |
:::info
You can also trigger actions from the **JavaScript code**. Check it out [here](/docs/how-to/run-actions-from-runjs).
:::
<div style={{textAlign: 'center'}}>
<img className="screenshot-full" src="/img/actions/setvar/setvar2.png" alt="ToolJet - Action reference -Set variable" width="700" />
</div>

View file

@ -0,0 +1,23 @@
---
id: show-alert
title: Show alert
---
This action allows you to display an alert message.
You can set a custom **message** for the alert and choose a particular alert type.
There are 4 types of alert messages - **Info**, **Success**, **Warning**, and **Error**.
Debounce field is empty by default, you can enter a numerical value to specify the time in milliseconds after which the action will be performed. ex: `300`
:::info
You can also trigger actions from the **JavaScript code**. Check it out [here](/docs/how-to/run-actions-from-runjs).
:::
<div style={{textAlign: 'center'}}>
<img className="screenshot-full" src="/img/actions/show-alert/alert2.png" alt="ToolJet - Action reference - Show Alert" width="700" />
</div>

View file

@ -0,0 +1,18 @@
---
id: show-modal
title: Show modal
---
Use this action to show the modal for an event.
Debounce field is empty by default, you can enter a numerical value to specify the time in milliseconds after which the action will be performed. ex: `300`
:::info
You can also trigger actions from the **JavaScript code**. Check it out [here](/docs/how-to/run-actions-from-runjs).
:::
<div style={{textAlign: 'center'}}>
<img className="screenshot-full" src="/img/actions/showmodal/showmodal2.png" alt="ToolJet - Action reference - Show modal" width="700" />
</div>

View file

@ -0,0 +1,55 @@
---
id: switch-page
title: Switch Page
---
Utilize this action with various event handler to transition to a different page within the [Multipage App](/docs/tutorial/pages).
By default, the debounce field is left empty. However, you can input a numeric value to indicate the time in milliseconds before the action is executed. For example, `300`.
<div style={{textAlign: 'center'}}>
<img className="screenshot-full" src="/img/actions/page/switchpage2.png" alt="ToolJet - Action Reference - Page Switching" width="500"/>
</div>
## Query Params
Query parameters can be passed through action such as `Switch Page`. The parameters are appended to the end of the application URL and are preceded by a question mark (`?`).
Query parameters are composed of key-value pairs, where the `key` and `value` are separated by an equals sign (`=`). Multiple query parameters can be included by clicking on the `+` button.
<div style={{textAlign: 'center'}}>
<img className="screenshot-full" src="/img/actions/page/queryparam1.png" alt="ToolJet - Action Reference - Page Switching"/>
</div>
In the above screenshot, we have provided the `username` as the key and the value is `{{globals.currentUser.email}}` which gets the email of the signed in user dynamically. When the button is clicked to trigger the `Switch Page` event handler attached to it then the URL on the switched page will have the parameters.
They are commonly used to provide additional information to the server or to modify the behavior of a web page. They can be used for filtering search results, pagination, sorting, and various other purposes.
<div style={{textAlign: 'center'}}>
<img className="screenshot-full" src="/img/actions/page/queryparam2.png" alt="ToolJet - Action Reference - Page Switching"/>
</div>
## Using RunJS query to switch page
Alternatively, the switch page action can be activated via a RunJS query using the following syntax:
```js
await actions.switchPage('<page-handle>')
```
:::info
For instructions on how to run actions from a RunJS query, refer to the how-to guide [Running Actions from RunJS Query](/docs/how-to/run-actions-from-runjs).
:::
### Switch page with query params
The switch page action can also be triggered along with query parameters using the following syntax:
```js
actions.switchPage('<pageHandle>', [['param1', 'value1'], ['param2', 'value2']])
```

View file

@ -0,0 +1,27 @@
---
id: unset-page-variable
title: Unset page variable
---
Utilize this action to clear a variable that was established using the [set page variable action](/docs/actions/set-page-variable).
By default, the debounce field is left empty. However, you can input a numeric value to indicate the time in milliseconds before the action is executed. For example, `300`.
<div style={{textAlign: 'center'}}>
<img className="screenshot-full" src="/img/actions/page/unsetpagevar2.png" alt="ToolJet - Action reference - Switch page" width="600"/>
</div>
## Using RunJS query to unset variable
Alternatively, the unset page variable action can be triggered via a RunJS query using the following syntax:
```js
await actions.unsetPageVariable('<variablename>')
```
`variablename` is the key of the variable that was provided while creating the variable.
:::info
For instructions on how to run actions from a RunJS query, refer to the how-to guide [Running Actions from RunJS Query](/docs/how-to/run-actions-from-runjs).
:::

View file

@ -0,0 +1,23 @@
---
id: unset-variable
title: Unset variable
---
This action allows you to remove the variable variable that was created using the set variable action.
## Options
| Option | Description |
|--------|-------------|
| Key | Name(String) of the variable through which you can access the value |
| Debounce | Debounce field is empty by default, you can enter a numerical value to specify the time in milliseconds after which the action will be performed. ex: `300` |
:::info
You can also trigger actions from the **JavaScript code**. Check it out [here](/docs/how-to/run-actions-from-runjs).
:::
<div style={{textAlign: 'center'}}>
<img className="screenshot-full" src="/img/actions/unsetvar/unsetvar2.png" alt="ToolJet - Action reference -Unset variable" width="700" />
</div>

View file

@ -0,0 +1,67 @@
---
id: canvas
title: Canvas
---
Canvas is the center area of the ToolJet app builder where the application is built. You arrange the **components** by dragging them from the Components library(right-sidebar).
<div style={{textAlign: 'center'}}>
<img className="screenshot-full" src="/img/v2-beta/app-builder/canvas/canvasnew.png" alt="App Builder: Canvas"/>
</div>
<br/>
:::info
- The Canvas height and width can be adjusted from the [Global Settings](/docs/app-builder/left-sidebar#global-settings).
- When the [Pages drawer](/docs/tutorial/pages) on the left is opened or pinned, the canvas becomes horizontally scrollable.
<div style={{textAlign: 'center'}}>
<img className="screenshot-full" src="/img/v2-beta/app-builder/canvas/scrollnew.gif" alt="App Builder: Canvas"/>
</div>
:::
### Arrange Components
All the components are fully interactive in editor mode - to prevent interaction you can **click and hold** the **Component Handle** to change component's position.
<div style={{textAlign: 'center'}}>
<img className="screenshot-full" src="/img/v2-beta/app-builder/canvas/handlenew.png" alt="App Builder: Canvas"/>
</div>
### Resize Components
Components on the canvas can be resized from the edges.
You can precisely set the position of selected components using keyboard arrow keys after clicking the component handle.
<div style={{textAlign: 'center'}}>
<img className="screenshot-full" src="/img/v2-beta/app-builder/canvas/resize.gif" alt="App Builder: Canvas"/>
</div>
### Group Components
ToolJet comes with flexible components to group other components together, such as **[Container](/docs/widgets/container/)** and **[Form](/docs/widgets/form/)**. When you drag and drop components in containers/forms they create a group of nested components. All components can be nested in this way.
### Hide or Disable Components
Hide or Disable a component by setting its **Visibility** or **Disabled** property to `true`. Click on the component handle to open **config inspector** on right side. These values can also evaluate to true based on a truthy value. For example, you can use the property of one component to toggle the Visibility property of another component dynamically, you just need to write a conditional statement.
For example: We want to disable a button when a checkbox is checked so we can simple use `{{components.checkbox1.value}}` in **Disable** property of the button. `{{components.checkbox1.value}}` evaluates to `true` when the checkbox is checked, and false when unchecked.
<div style={{textAlign: 'center'}}>
<img className="screenshot-full" src="/img/v2-beta/app-builder/canvas/hide.gif" alt="App Builder: Canvas"/>
</div>
### Clone Components
You can clone existing components on the canvas by **cmd/ctrl + d**. Check other **[Keyboard Shortcuts](/docs/tutorial/keyboard-shortcuts)**.

View file

@ -0,0 +1,56 @@
---
id: customstyles
title: Custom Styles
---
<div className='badge badge--primary heading-badge'>Available on: Paid plans</div>
Custom Styles feature enables the implementation of theming on ToolJet apps, allowing users to inject their own CSS styling to override the default app styling. This feature fulfills the requirement of allowing users to easily customize the appearance of their apps.
Custom Styles helps in maintaining consistent themes across the ToolJet apps, alleviating the repetitive burden of styling components whenever a new app is created. By enabling users to apply standardized styles, this feature ensures that each app adheres to a unified theme without the need to manually restyle the components from scratch. As a result, the ToolJet app development process becomes more efficient, and the visual coherence of the apps is preserved, providing users with a seamless experience across all applications.
<div style={{textAlign: 'center'}}>
<img className="screenshot-full" src="/img/v2-beta/app-builder/customcss/customcss.gif" alt="Custom CSS" />
</div>
## Applying Custom Styles
To add Custom Styles to ToolJet apps, users should follow these steps:
1. Go to the **Custom Styles** Page, accessible under **Workspace Settings** from the ToolJet dashboard.
<div style={{textAlign: 'center'}}>
<img className="screenshot-full" src="/img/v2-beta/app-builder/customcss/settings.png" alt="Custom CSS" />
</div>
2. When creating a new app on ToolJet, the default button color is **blue**. If you wish to change the default button color to **red**, you must identify the class of the button component, which follows the format `_tooljet-<component>`.
- The browser's inspector can also help you find the class of the component. Classes are added for both **pages** and **components**, and there are two types of selectors for classes: **Common** (`_tooljet-<component>`) and **Individual** (`_tooljet-<defaultComponentName>`).
<div style={{textAlign: 'center'}}>
<img className="screenshot-full" src="/img/v2-beta/app-builder/customcss/selectors.png" alt="Custom CSS" />
</div>
3. Once the class (**`_tooljet-Button`**) is identified, navigate to the Custom Styles page and apply the desired CSS changes for that class, as shown in the following CSS code:
```css
._tooljet-Button button {
background: red !important;
}
._tooljet-Button button:hover {
background: green !important;
}
```
4. By applying this custom styles, all future instances of the app will have buttons with a red default color, and they will turn green on hover. This eliminates the need for users to individually edit button properties, streamlining the customization process.
:::info
Custom Styles are injected at the workspace level, ensuring consistent theming across all apps within the workspace.
:::
<div style={{textAlign: 'center'}}>
<img className="screenshot-full" src="/img/v2-beta/app-builder/customcss/styledapp.gif" alt="Custom CSS" />
</div>

View file

@ -0,0 +1,101 @@
---
id: left-sidebar
title: Left-sidebar
---
Left-sidebar has the following options:
- **[Pages](#pages)**
- **[Inspector](#inspector)**
- **[Debugger](#debugger)**
- **[Global Settings](#global-settings)**
- **[Comments](#comments)**
- **[Theme switch](#theme-switch)**
<div style={{textAlign: 'center'}}>
<img className="screenshot-full" src="/img/v2-beta/app-builder/leftsidebar/leftnew.png" alt="App Builder: Left-sidebar"/>
</div>
## Pages
Pages allows you to have multiple pages in a single application, making your ToolJet applications more robust and user-friendly.
Check the detailed documentation for **[Pages](/docs/tutorial/pages)**.
<div style={{textAlign: 'center'}}>
<img className="screenshot-full" src="/img/v2-beta/app-builder/leftsidebar/pagesnew.png" alt="App Builder: Left-sidebar"/>
</div>
## Inspector
The Inspector can be used to inspect the data of the **queries**, properties and values of the **components** that are there on the canvas, ToolJet's global variables and the variables that have been set by the user.
Check the detailed guide on **[using Inspector](/docs/how-to/use-inspector)**.
<div style={{textAlign: 'center'}}>
<img className="screenshot-full" src="/img/v2-beta/app-builder/leftsidebar/inspectornew.png" alt="App Builder: Left-sidebar"/>
</div>
## Debugger
Debugger records any errors that occur during the execution of queries. For instance, if a database query fails because the database is unavailable or if a REST API query fails due to an incorrect URL, the errors will be captured and shown in the debugger. Additionally, the debugger provides pertinent information associated with the error alongside the error message.
If you wish to prevent the debugger from closing, you can simply click on the pin icon located in the top-right corner. By doing so, the debugger will stay open until you decide to unpin it.
Debugger consists of two main sections:
1. **All Log:** In this section, you can view a comprehensive list of all the logs generated during the execution of the application. These logs may include various types of messages, such as success messages, warning, and error messages.
2. **Errors:** This section specifically focuses on displaying the error messages that occurred during the program's execution. These error messages indicate issues or problems that need attention, as they may lead to unexpected behaviors of the application.
<div style={{textAlign: 'center'}}>
<img className="screenshot-full" src="/img/v2-beta/app-builder/leftsidebar/newdebugger.gif" alt="App Builder: Left-sidebar"/>
</div>
## Global Settings
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>/`
- **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**.
- **Max width of canvas**: Modify the width of the canvas in **px** or **%**. The default width is `1292` px.
- **Background color of canvas**: Enter the hex color code or choose a color from the picker to change the background color of the canvas. You can also click on the **Fx** to programmatically set the value.
- **Export app**: Click on the [Export app](/docs/dashboard/#export-app) button to export the application as a JSON file. You can import this JSON file in any other workspace to use the application.
<div style={{textAlign: 'center'}}>
<img className="screenshot-full" src="/img/v2-beta/app-builder/leftsidebar/globalsettings.png" alt="App Builder: Left-sidebar"/>
</div>
## Comments
Comment anywhere on the canvas and collaborate with other users in the workspace. Click on the comments button to enable it and then drop comment anywhere on the canvas.
<div style={{textAlign: 'center'}}>
<img className="screenshot-full" src="/img/v2-beta/app-builder/leftsidebar/commentnew.png" alt="App Builder: Left-sidebar"/>
</div>
## Theme Switch
Use the theme switch button to toggle ToolJet between light and dark modes.
While developers can access the current theme's value through global variables using `{{globals.theme.name}}`, it is not currently feasible to change the theme programmatically.
<div style={{textAlign: 'center'}}>
<img className="screenshot-full" src="/img/v2-beta/app-builder/leftsidebar/theme.png" alt="App Builder: Left-sidebar"/>
</div>

View file

@ -0,0 +1,20 @@
---
id: overview
title: Overview
---
# App-Builder: Overview
ToolJet's App Builder allows you to build applications. ToolJet's app builder has the following major components:
- **[Topbar](/docs/app-builder/topbar)**: configure app settings
- **[Canvas](/docs/app-builder/canvas)**: Arrange the components to build the interface of app
- **[Left-sidebar](/docs/app-builder/left-sidebar)**: Add **[pages](/docs/tutorial/pages)**, **[inspect](/docs/how-to/use-inspector)** the components, queries or variables, and **[debug](#debugger)** the errors.
- **[Components library](/docs/app-builder/components-library)**(right sidebar): Drag any component or modify the property or styling
- **[Query Panel](/docs/app-builder/query-panel)**: Create, edit or manage the queries from the **[datasources](/docs/data-sources/overview)**
<div style={{textAlign: 'center'}}>
<img className="screenshot-full" src="/img/v2-beta/app-builder/appbuilderui2.png" alt="App Builder: Overview"/>
</div>

View file

@ -0,0 +1,218 @@
---
id: query-panel
title: Query Panel
---
The Query Panel, located at the bottom of the app-builder, allows you to create and manage queries for interacting with connected **Default** and **Global** datasources. 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 right side, which displays a list of all the created queries.
- The **[Query Editor](#query-editor)**, used to configure the selected query.
<div style={{textAlign: 'center'}}>
<img className="screenshot-full" src="/img/v2-beta/app-builder/querypanel/newui2/querypanel.png" alt="App Builder: Query Panel"/>
</div>
## Query Manager
Query Manager will list all the queries that has been created in the application. Query Manager helps in managing the queries that have been created, you can **add**, **edit**, **delete**, **duplicate**, **search**, **sort** and **filter** through them.
<div style={{textAlign: 'center'}}>
<img className="screenshot-full" src="/img/v2-beta/app-builder/querypanel/newui2/querymanager.png" alt="App Builder: Query Panel"/>
</div>
### Add
Add button is used to add new query in the application. When Add button is clicked, a menu will open with a list of options for creating a query from **Default** datasources such as **Rest API**, **ToolJet Database**, **JavaScript Code**, **Python Code** or from connected **Global Datasources**.
<div style={{textAlign: 'center'}}>
<img className="screenshot-full" src="/img/v2-beta/app-builder/querypanel/newui2/addquery.gif" alt="App Builder: Query Panel"/>
</div>
### Sort/Filter
On the top of Query Manager, there is button to Sort or Filter queries. The following options are there:
**Filter:**
- By Datasource
**Sort:**
- Name: A-Z
- Name: Z-A
- Type: A-Z
- Type: Z-A
- Last modified: oldest first
- Last modified: newest First
<div style={{textAlign: 'center'}}>
<img className="screenshot-full" src="/img/v2-beta/app-builder/querypanel/newui2/sortfilter.gif" alt="App Builder: Query Panel"/>
</div>
### Search
On the top of the query manager is search box that can be used to search for a specific query.
<div style={{textAlign: 'center'}}>
<img className="screenshot-full" src="/img/v2-beta/app-builder/querypanel/newui2/search.gif" alt="App Builder: Query Panel"/>
</div>
### Delete
Delete button will delete the selected query, the button will only show up when you hover over the query name. When you click on the delete button, a confirmation dialog will open to confirm the deletion of the query.
<div style={{textAlign: 'center'}}>
<img className="screenshot-full" src="/img/v2-beta/app-builder/querypanel/newui2/delete.png" alt="App Builder: Query Panel"/>
</div>
### Duplicate
Duplicate button will duplicate the selected query, the button will only show up when you hover over the query name. The duplicate query will be named as `<query name>_copy`.
<div style={{textAlign: 'center'}}>
<img className="screenshot-full" src="/img/v2-beta/app-builder/querypanel/newui2/duplicate.png" alt="App Builder: Query Panel"/>
</div>
### Rename
Rename button is used to rename the selected query, the button will only show up when you hover over the query name. When you click on the rename button, the query name becomes editable and you can change the name of the query.
<div style={{textAlign: 'center'}}>
<img className="screenshot-full" src="/img/v2-beta/app-builder/querypanel/newui2/rename.png" alt="App Builder: Query Panel"/>
</div>
## Query Editor
Query editor used to configure the query parameters, preview or transform the data return by the query.
:::info
The changes made in the query panel will be saved automatically.
:::
<div style={{textAlign: 'center'}}>
<img className="screenshot-full" src="/img/v2-beta/app-builder/querypanel/newui2/editor.png" alt="App Builder: Query Panel"/>
</div>
### Topbar
On the top of the query panel there are a few options:
#### Query Name
The name of query is displayed on the top of the query panel. You can click on it to make it editable and change the name of the query.
<div style={{textAlign: 'center'}}>
<img className="screenshot-full" src="/img/v2-beta/app-builder/querypanel/newui2/renameeditor.gif" alt="App Builder: Query Panel"/>
</div>
#### Preview
Preview button is used to preview the data returned by the query. The data will be displayed on the preview section present at the bottom of the query panel. This helps in debugging the query and see the data returned by the query without triggering the query in the app.
The Preview of data is returned in two different formats: **Raw** & **JSON**. You can click on the clear button to clear the preview data.
<div style={{textAlign: 'center'}}>
<img className="screenshot-full" src="/img/v2-beta/app-builder/querypanel/newui2/preview.gif" alt="App Builder: Query Panel"/>
</div>
#### Run
Run is used to trigger the query, running the query will interact with the application unlike `Preview`.
<div style={{textAlign: 'center'}}>
<img className="screenshot-full" src="/img/v2-beta/app-builder/querypanel/newui2/run.gif" alt="App Builder: Query Panel"/>
</div>
### Query Parameters
Query Parameters are essential values that must be provided in a query for the server to generate a response. These parameters encompass **endpoints**, **methods**, or **operations**. It's important to note that the specific set of Query Parameters varies for each datasource.
<div style={{textAlign: 'center'}}>
<img className="screenshot-full" src="/img/v2-beta/app-builder/querypanel/newui2/params.png" alt="App Builder: Query Panel"/>
</div>
#### Datasource
The primary and default parameter found in all queries is **Datasource**. This option allows you to choose the appropriate datasource for your query.
In cases where multiple datasources of the same type are connected, you can easily switch the query's datasource using the dropdown menu.
<div style={{textAlign: 'center'}}>
<img className="screenshot-full" src="/img/v2-beta/app-builder/querypanel/newui2/switch.png" alt="App Builder: Query Panel"/>
</div>
### Transformation
Transformations can be enabled on queries to transform the query results. ToolJet allows you to transform the query results using two programming languages JavaScript & Python. Check the detailed documentation on **[Transformations](/docs/tutorial/transformations)**.
<div style={{textAlign: 'center'}}>
<img className="screenshot-full" src="/img/v2-beta/app-builder/querypanel/newui2/transform.gif" alt="App Builder: Query Panel"/>
</div>
### Settings
<div style={{textAlign: 'center'}}>
<img className="screenshot-full" src="/img/v2-beta/app-builder/querypanel/newui2/settings.png" alt="App Builder: Query Panel"/>
</div>
#### Run this query on application load?
Enabling this option will execute the query every time the app is loaded.
#### Request confirmation before running the query?
Enabling this option show a confirmation modal to confirm `Yes` or `No` if you want to fire that query.
#### Show notification on success?
Enabling this option show a success toast notification when the query is successfully triggered.
You can provide a custom **success message** and **notification duration** in milliseconds.
### Events
Event handlers can be added to queries for the following events:
- **Query Success**
- **Query Failure**
:::info
Learn more about [Event Handlers and Actions](/docs/widgets/overview#component-event-handlers).
:::
<div style={{textAlign: 'center'}}>
<img className="screenshot-full" src="/img/v2-beta/app-builder/querypanel/newui2/events.png" alt="App Builder: Query Panel"/>
</div>

View file

@ -0,0 +1,29 @@
---
id: components-library
title: Components Library
---
The **Components Library** on the right sidebar contains all of the available components. Use this to drag-and-drop a component from the library to the canvas. It organizes components into sections and you can enter a search term to quickly find a component you need.
<div style={{textAlign: 'center'}}>
<img className="screenshot-full" src="/img/v2-beta/app-builder/rightsidebar/librarynew.png" alt="App Builder: Component library- right sidebar"/>
</div>
:::tip
Check the **[Components Catalog](/docs/widgets/overview)** to know more about specific component.
:::
## Component Config Inspector
The Component Config Inspector is also called as component inspector. It contains all the available settings for the selected component and is where you **set values**, **update component names**, and **create event handlers**. The Component Inspector organizes settings into different sections, such as **Property** and **Styles**.
To open the Component Config Inspector, click on the **[component handle](/docs/app-builder/canvas#arrange-components)** that is present on the top of the component including **⚙️ + Component Name** and the component inspector will open up on the right side:
<div style={{textAlign: 'center'}}>
<img className="screenshot-full" src="/img/v2-beta/app-builder/rightsidebar/configinspector.gif" alt="App Builder: Component library- right sidebar"/>
</div>

View file

@ -0,0 +1,52 @@
---
id: share
title: Share
---
ToolJet apps offer two sharing options: they can either be shared privately with workspace users or publicly by generating a shareable link. To obtain the shareable URL, you can easily do so by clicking on the Share button located on the top bar of the App builder.
<div style={{textAlign: 'center'}}>
<img className="screenshot-full" src="/img/v2-beta/app-builder/share/sharenew1.png" alt="Share modal" width='700'/>
</div>
### Making the app public
To share the app with external end users and make it accessible to anyone on the internet without requiring a ToolJet login, you can toggle on the Switch for "Make the application public?" in the Share modal.
<div style={{textAlign: 'center'}}>
<img className="screenshot-full" src="/img/v2-beta/app-builder/share/publicnew1.png" alt="Share modal" width='700'/>
</div>
### Customizing the app URL
By default, ToolJet will generate a unique URL for your application. However, you also have the option to edit the slug of the URL to make it more customized and user-friendly.
<div style={{textAlign: 'center'}}>
<img className="screenshot-full" src="/img/v2-beta/app-builder/share/edit1.png" alt="Share modal" width='700'/>
</div>
### Embedding ToolJet Apps
ToolJet apps can be directly shared with end users and embedded into web apps using `iframes`. If you want to make your application public, you can use the Share modal to obtain the embeddable link.
:::info
For embedding private ToolJet apps, you'll need to set an environment variable in the `.env` file.
| Variable | Description |
|:-------------- |:------------------------------------ |
| ENABLE_PRIVATE_APP_EMBED | `true` or `false` |
You can learn more [here](/docs/setup/env-vars#enabling-embedding-of-private-apps).
:::
<div style={{textAlign: 'center'}}>
<img className="screenshot-full" src="/img/v2-beta/app-builder/share/embeddtj.gif" alt="Share modal" />
</div>

View file

@ -0,0 +1,135 @@
---
id: topbar
title: Topbar
---
Topbar is present at the top of the app-builder, and is used to configure the app settings.
<div style={{textAlign: 'center'}}>
<img className="screenshot-full" src="/img/v2-beta/app-builder/toolbar/topbarnew.png" alt="App Builder: Topbar"/>
</div>
### App name
The App name can be modified by selecting the application name located on the left side of the topbar.
Upon the creation of a new app, it is automatically assigned a unique app name.
<div style={{textAlign: 'center'}}>
<img className="screenshot-full" src="/img/v2-beta/app-builder/toolbar/appnamenew.png" alt="App Builder: Topbar"/>
</div>
### Desktop or Mobile layout
Switch the canvas mode in Mobile or Desktop layout from the topbar.
#### Showing component on mobile layout
Click on the component handle to open [component config inspector](/docs/app-builder/components-library#component-config-inspector) on the right sidebar. Scroll down to the **Layout** section and toggle on the Mobile Layout option. The width of the components will be adjusted to fit the Mobile Layout.
#### Adding a new component to mobile layout
Switch the canvas to mobile layout by clicking the mobile icon on the topbar. Drag and drop a new component to the canvas. This component will not be visible on the desktop layout unless **Show on desktop** is enabled from the component config inspector.
:::info
Width of the component will be automatically adjusted to fit the screen while viewing the application in app viewer.
:::
<div style={{textAlign: 'center'}}>
<img className="screenshot-full" src="/img/v2-beta/app-builder/toolbar/canvasmodes.gif" alt="App Builder: Topbar"/>
</div>
### Changes saved indicator
Whenever a change is made on the component or the query panel/queries, the changes are saved automatically. The changes saved indicator will be displayed on the topbar. This helps the developer to know if the changes are saved or not.
<div style={{textAlign: 'center'}}>
<img className="screenshot-full" src="/img/v2-beta/app-builder/toolbar/changessaved.png" alt="App Builder: Topbar"/>
</div>
### Developer Details
This will show a profile picture of the developer who is currently working on the application. Hovering over the profile picture will show the name of the developer. If there is no profile picture, then the first letter of the first name and last name will be displayed.
<div style={{textAlign: 'center'}}>
<img className="screenshot-full" src="/img/v2-beta/app-builder/toolbar/profile.png" alt="App Builder: Topbar"/>
</div>
### Version Manager
**Add** or **remove** versions of an application from the Version Manager. Click on the `edit` icon next to version name to rename the version.
When many developers are working on an app, **Versioning** allows them to save their own version of the app. This also prevents developers from overwriting the other developer's work.
:::tip
Versioning is also helpful when working with **[multiple environments](/docs/release-management/multi-environment/)** like development, staging and production.
:::
<div style={{textAlign: 'center'}}>
<img className="screenshot-full" src="/img/v2-beta/app-builder/toolbar/versionsnew.png" alt="App Builder: Topbar"/>
</div>
### Undo or Redo
Undo or Redo any action performed on the canvas.
You can also use **[Keyboard Shortcuts](/docs/tutorial/keyboard-shortcuts)** to perform such actions.
<div style={{textAlign: 'center'}}>
<img className="screenshot-full" src="/img/v2-beta/app-builder/toolbar/undonew.png" alt="App Builder: Topbar"/>
</div>
### Share
Share your applications with a unique URL generated automatically or edit the URL slug to personalize it.
- When **Make the application public** is off and URL is shared then the users will have to login to ToolJet to use the application. Toggle on the option then anyone on the internet will be able to access the application without logging in to ToolJet.
- ToolJet generates the **Embedded link** which can be used to embed application on the webpages.
:::tip
Learn more about **[Sharing](/docs/app-builder/share)** your tooljet applications.
:::
<div style={{textAlign: 'center'}}>
<img className="screenshot-full" src="/img/v2-beta/app-builder/toolbar/sharenew.png" alt="App Builder: Topbar"/>
</div>
### Preview
Clicking on **Preview** button will open up the currently opened version of the app in the new tab. This is really handy when the app developer wants to immediately check the app preview in production.
<div style={{textAlign: 'center'}}>
<img className="screenshot-full" src="/img/v2-beta/app-builder/toolbar/previewnew.png" alt="App Builder: Topbar"/>
</div>
### Release
Release the app to publish the current version of the app and push the changes into the production.
:::caution
ToolJet will block editing of the Released version of an app and will display a prompt to create a new version to make the changes. This is to prevent accidentally pushing an unfinished app to the live version.
:::
<div style={{textAlign: 'center'}}>
<img className="screenshot-full" src="/img/v2-beta/app-builder/toolbar/releasenew.png" alt="App Builder: Topbar"/>
</div>

View file

@ -0,0 +1,5 @@
{
"label": "Contributing Guide",
"position": 11,
"collapsed": true
}

View file

@ -0,0 +1,81 @@
---
id: code-of-conduct
title: Contributor Code of Conduct
---
# Contributor Covenant Code of Conduct
## Our Pledge
In the interest of fostering an open and welcoming environment, we as
contributors and maintainers pledge to make participation in our project and
our community a harassment-free experience for everyone, regardless of age, body
size, disability, ethnicity, sex characteristics, gender identity and expression,
level of experience, education, socio-economic status, nationality, personal
appearance, race, religion, or sexual identity and orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment
include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or
advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic
address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable
behavior and are expected to take appropriate and fair corrective action in
response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct, or to ban temporarily or
permanently any contributor for other behaviors that they deem inappropriate,
threatening, offensive, or harmful.
## Scope
This Code of Conduct applies within all project spaces, and it also applies when
an individual is representing the project or its community in public spaces.
Examples of representing a project or community include using an official
project e-mail address, posting via an official social media account, or acting
as an appointed representative at an online or offline event. Representation of
a project may be further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting the project team at hello@tooljet.com . All
complaints will be reviewed and investigated and will result in a response that
is deemed necessary and appropriate to the circumstances. The project team is
obligated to maintain confidentiality with regard to the reporter of an incident.
Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good
faith may face temporary or permanent repercussions as determined by other
members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see
https://www.contributor-covenant.org/faq

View file

@ -0,0 +1,69 @@
---
id: l10n
title: Localization
---
Welcome to ToolJet Localization Guide. The goal of the Localization is to make ToolJet easy to use and close to all countries, languages, and general cultural groups. On this page, you will find instructions on how to contribute to ToolJet through Localization and make a more friendly ToolJet for all regions.
## Adding Translations
- For adding the translations of your language in ToolJet, you'll need to create a new **languagecode.json** file which will include all the translations for the keywords in your language, and then list the language in the **languages.json** file for the language to be listed in the dashboard of the ToolJet.
- Go to the **frontend** directory which is at the root of ToolJet, then go to the **assets** and inside assets, you'll find the **translations** directory. You have created a new json file with the **language code** as the file name. The language code should follow [ISO 639-1 Code](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes).
```
\frontend
|--\assets
|--\--\translations
|--\--\--\languages.json
|--\--\--\en.json
```
<div style={{textAlign: 'center'}}>
<img className="screenshot-full" src="/img/l10n/files.png" alt="files" />
</div>
- Let's localize ToolJet in the **French** language. Create a new json file inside the translations directory and name it **fr.json**. `fr` is the language code for French.
- After creating the new file, open the **en.json** file and copy all the contents of the file to the newly created **fr.json**.
<div style={{textAlign: 'center'}}>
<img className="screenshot-full" src="/img/l10n/en.png" alt="files" />
</div>
- Once copied, you can now start adding the translations for the keywords in the french language.
- After completing the translation, all you need to do is list the language in **languages.json** file. You'll need to add an object with three key-value pairs. **lang** - the name of the language that you added, **code** - the language code, and the **nativeLang** - name of language in the native.
```js
{
"languageList":
[
{ "lang": "English", "code": "en", "nativeLang": "English" },
{ "lang": "French", "code": "fr", "nativeLang": "Français" }
]
}
```
<!--
- Once you list the language in the `language.json` file, you'll be able to see it in the **dashboard**.
<div style={{textAlign: 'center'}}>
<img className="screenshot-full" src="/img/l10n/list.png" alt="files" />
</div>
:::info
ToolJet will automatically detect your browser's default language and will switch to it. If your browser's default language translation is not available in ToolJet then it will set English as the default language.
:::
-->
:::note
Feel free to reach us on [Slack](https://tooljet.com/slack) for any help related to Localization.
:::

View file

@ -0,0 +1,390 @@
---
id: creating-a-plugin
title: 'Marketplace: Creating plugins'
---
# Marketplace: Creating plugins
## What are plugins
ToolJets 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.
This guide will provide step-by-step instructions for creating ToolJet plugins using the `tooljet` CLI.
The `tooljet` CLI is a user-friendly command-line tool designed to simplify the plugin building process. As part of this guide, we will create a basic plugin for GitHub.
## Step 1: Creating a New Plugin - GitHub Plugin
The first step is to bootstrap a new plugin for the ToolJet marketplace. The plugin will authenticate users with a GitHub Personal Access Token and include fundamental operations such as fetching user details, repositories, issues, and pull requests.
If you have completed the **[Setup](/docs/contributing-guide/marketplace/marketplace-setup)** guide, you can begin developing the plugin using the `tooljet` CLI. To initiate plugin development, enter the following command in the terminal:
```bash
# create a new plugin
tooljet plugin create github
```
When prompted, enter the **plugin name** and select the **plugin type**, which is api in this case. Additionally, select **yes** when prompted to create a new plugin for the marketplace.
If your plugin is hosted on GitHub, please provide the **repository URL** when prompted. Otherwise, leave it blank.
When a plugin is created using the `ToolJet` CLI, an object is added to the **plugins.json** file in the **`ToolJet/server/src/assets/marketplace/`** directory. This object includes metadata about the plugin, such as its name, description, version, author, and other relevant details.
The plugins.json file serves as a registry of all available plugins for use in ToolJet. When the ToolJet server starts up, it reads the plugins.json file and loads all plugins that are listed in it.
:::info
It is important to note that the plugins.json file should not be manually edited, as it is automatically generated by the `ToolJet CLI`. Making changes to this file can result in issues with the proper functioning of the plugins in the system.
:::
All marketplace plugins are stored in the **`/marketplace`** directory of the ToolJet repository. You can find the GitHub plugin **[here](https://github.com/ToolJet/ToolJet/tree/develop/marketplace/plugins/github)**.
The structure of a typical ToolJet plugin directory appears as follows:
```bash
github/
package.json
lib/
icon.svg
index.ts
operations.json
manifest.json
```
In this structure, the file **manifest.json** contains information about the plugin's name, description, and other details. The file **operations.json** contains metadata about all the operations that the plugin supports. The main file, **index.ts**, creates a QueryService for the plugin, which handles queries, connection testing, caching, and more. The **icon.svg** file serves as the plugin's icon, while **package.json** is automatically generated by the CLI.
:::info
**Why do we need a manifest.json file or a operations.json file?**
The manifest.json file is used by a React component to create a dynamic UI for connection forms. It defines the schema of an API or data source, including its name, type, and any exposed variables, as well as options for authentication and other customizable properties. The properties section specifies the required fields and their types for connecting to the API or data source. By reading the manifest.json file, the React component generates the necessary UI components based on the schema, such as text inputs, dropdowns, checkboxes, and other elements.
On the other hand, the operations.json file contains a schema definition for a specific data source, like Github. It describes the available operations and their parameters that can be used to query the data source. A React component uses this schema to create queries in ToolJet applications, generating a UI that allows users to select the desired operation and provide the required parameters. The component uses the properties defined in the operations.json file to create various UI elements, such as dropdowns and input fields, and handle user interactions to create the final query. Once the user fills in the required parameters, the component uses them to generate a query that can be executed against the data source and return the results to the user.
Overall, *manifest.json* and *operations.json* files are essential for creating dynamic UI components in ToolJet applications. They define the schema for data sources and available operations, which React components then use to generate user-friendly UI elements. By utilizing these files, ToolJet enables users to easily connect to various APIs and data sources, perform queries, and retrieve data in an intuitive and efficient manner.
:::
## Step 2: Defining the manifest.json file
To construct the connection form, it's important to include the necessary options in the manifest.json file. Here's an example of how to do it:
```json
"properties": {
"credentials": {
"label": "Authentication",
"key": "auth_type",
"type": "dropdown-component-flip",
"description": "A single select dropdown to choose credentials",
"list": [
{
"value": "personal_access_token",
"name": "Use Personal Access Token"
}
]
},
"personal_access_token": {
"token": {
"label": "Token",
"key": "personal_token",
"type": "password",
"description": "Enter your personal access token",
"hint": "You can generate a personal access token from your Github account settings."
}
}
}
```
This manifest.json file includes information about authentication options, specifically a dropdown to choose a type of credentials and a field to enter a personal access token. The label, key, type, description, and hint properties are used to define the specific fields and their types required for connecting to the API or data source.
In this particular code, there are two main properties defined: **`credentials`** and **`personal_access_token`**.
The **`credentials`** property specifies the authentication method to be used. It contains several keys:
- **`label`**: a user-friendly label for the authentication method, set to "Authentication"
- **`key`**: a unique identifier for the authentication method, set to "auth_type"
- **`type`**: the type of the authentication method, set to "dropdown-component-flip"
- **`description`**: a description of the authentication method, set to "A single select dropdown to choose credentials"
- **`list`**: an array of objects representing the different authentication methods available. In this case, there is only one method available: a personal access token. The `value` key in the object is set to "personal_access_token" and the `name` key is set to "Use Personal Access Token".
The **`personal_access_token`** property specifies the details of the personal access token authentication method. It contains a `token` key, which specifies the actual personal access token to be used. The `token` key contains several keys:
- **`label`**: a user-friendly label for the personal access token, set to "Token"
- **`key`**: a unique identifier for the personal access token, set to "personal_token"
- **`type`**: the type of the personal access token, set to "password"
- **`description`**: a description of the personal access token, set to "Enter your personal access token"
- **`hint`**: a hint for the personal access token, set to "You can generate a personal access token from your Github account settings."
The available `type` options are:
However, based on the code you provided, the available **`type`** options are:
- **`password`**: used to input a secret value, such as a password or an access token.
- **`dropdown-component-flip`**: used to create a dropdown menu that flips its position relative to the component that triggers it.
- **`text`**: used to input a single line of text.
- **`textarea`**: used to input multiple lines of text.
- **`toggle`**: used to create a simple on/off switch.
- **`react-component-headers`**: used to display headers for React components.
- **`codehinter`**: is a specialized input field used for entering code and has additional functionality, such as resolving JavaScript code within double curly braces`{{}}`.
:::tip
The **manifest.json** file is utilized by the connection modal component, which appears to prompt users to enter their datasource credentials. Meanwhile, the **operations.json** file is used by the query manager when users generate a specific query for a connected datasource. **Both files utilize a similar schema**.
:::
## Step 3: Defining the operations.json file
```json
"properties": {
"operation": {
"label": "Operation",
"key": "operation",
"type": "dropdown-component-flip",
"description": "Single select dropdown for operation",
"list": [
{
"value": "get_user_info",
"name": "Get user info"
},
{
"value": "get_repo",
"name": "Get repository"
},
{
"value": "get_repo_issues",
"name": "Get repository issues"
},
{
"value": "get_repo_pull_requests",
"name": "Get repository pull requests"
}
]
},
"get_user_info": {
"username": {
"label": "Username",
"key": "username",
"type": "codehinter",
"lineNumbers": false,
"description": "Enter username",
"width": "320px",
"height": "36px",
"className": "codehinter-plugins",
"placeholder": "Enter username"
}
},
"get_repo": {
"owner": {
"label": "Owner",
"key": "owner",
"type": "codehinter",
"lineNumbers": false,
"description": "Enter owner name",
"width": "320px",
"height": "36px",
"className": "codehinter-plugins",
"placeholder": "developer"
},
"repo": {
"label": "Repository",
"key": "repo",
"type": "codehinter",
"lineNumbers": false,
"description": "Enter repository name",
"width": "320px",
"height": "36px",
"className": "codehinter-plugins",
"placeholder": "tooljet"
}
},
"get_repo_issues": {
"owner": {
"label": "Owner",
"key": "owner",
"type": "codehinter",
"lineNumbers": false,
"description": "Enter owner name",
"width": "320px",
"height": "36px",
"className": "codehinter-plugins",
"placeholder": "developer"
},
"repo": {
"label": "Repository",
"key": "repo",
"type": "codehinter",
"lineNumbers": false,
"description": "Enter repository name",
"width": "320px",
"height": "36px",
"className": "codehinter-plugins",
"placeholder": "tooljet"
},
"state": {
"label": "State",
"key": "state",
"className": "codehinter-plugins col-4",
"type": "dropdown",
"description": "Single select dropdown for choosing state",
"list": [
{
"value": "open",
"name": "Open"
},
{
"value": "closed",
"name": "Closed"
},
{
"value": "all",
"name": "All"
}
]
}
},
"get_repo_pull_requests": {
"owner": {
"label": "Owner",
"key": "owner",
"type": "codehinter",
"lineNumbers": false,
"description": "Enter owner name",
"width": "320px",
"height": "36px",
"className": "codehinter-plugins",
"placeholder": "developer"
},
"repo": {
"label": "Repository",
"key": "repo",
"type": "codehinter",
"lineNumbers": false,
"description": "Enter repository name",
"width": "320px",
"height": "36px",
"className": "codehinter-plugins",
"placeholder": "tooljet"
},
"state": {
"label": "State",
"key": "state",
"type": "dropdown",
"className": "codehinter-plugins col-4",
"description": "Single select dropdown for choosing state",
"list": [
{
"value": "open",
"name": "Open"
},
{
"value": "closed",
"name": "Closed"
},
{
"value": "all",
"name": "All"
}
]
}
}
}
```
The operations.json file specifies the available operations that can be executed on the data source. It provides details about the operation type, required fields to execute the operation, and the data type of each field. The label, key, type, description, and hint properties are used to define the specific fields and their types required to establish a connection with the API or data source.
## Step 4: Add the npm package of Gitub to the plugin dependencies
- Change directory to the plugin directory where the npm package needs to be installed and then install the package
```bash
# change directory to the plugin directory and install the npm package
npm i octokit --workspace=@tooljet-marketplace/github
```
:::info
Steps to install npm package to a plugin
```bash
npm i <npm-package-name> --workspace=<plugin-name-in-package-json>
```
The command `npm i <npm-package-name> --workspace=<plugin-name-in-package-json>` is used to install a specific npm package into a particular workspace of a multi-package repository.
The *--workspace* flag is used to specify the workspace where the package should be installed. In this case, we are installing the package in the *@tooljet-marketplace/github* workspace.
:::
## Step 5: Implement the query execution logic in index.ts
In index.ts, the query execution logic needs to be implemented for the Github plugin's QueryService. The QueryService is responsible for handling the process of running queries and receives information about the data source, including credentials, configurations, and query parameters.
For the Github data source, the sourceOptions will contain the necessary authentication credentials, like the personal access token, while the queryOptions will include the configurations and parameters specific to the query, like obtaining a list of repositories for a particular user.
Using this information, the QueryService will create and execute API requests against the Github API. The resulting data will be returned to the caller for further processing as needed.
Create a new file **query_operations.ts** in the **plugins/github/src** directory and add the following code to it.
```typescript
import { Octokit } from 'octokit'
import { QueryOptions } from './types'
export async function getUserInfo(octokit: Octokit, options: QueryOptions): Promise<object> {
const { data } = await octokit.request(
'GET /users/{username}',
{
username: options.username
}
);
return data;
}
export async function getRepo(octokit: Octokit, options: QueryOptions): Promise<object> {
const { data } = await octokit.request(
'GET /repos/{owner}/{repo}',
{
owner: options.owner,
repo: options.repo
}
);
return data;
}
export async function getRepoIssues(octokit: Octokit, options: QueryOptions): Promise<object> {
const { data } = await octokit.request(
'GET /repos/{owner}/{repo}/issues',
{
owner: options.owner,
repo: options.repo,
state: options.state || 'all'
}
);
return data;
}
export async function getRepoPullRequests(octokit: Octokit, options: QueryOptions): Promise<object> {
const { data } = await octokit.request(
'GET /repos/{owner}/{repo}/pulls',
{
owner: options.owner,
repo: options.repo,
state: options.state || 'all'
}
);
return data;
}
```
The query_operations.ts file comprises functions that will execute the queries and will be called by the QueryService in index.ts.
The GitHub class has three methods:
- **run**: This method executes a query and is invoked by passing sourceOptions and queryOptions as input, representing the source metadata and query configuration, respectively. The run method utilizes the octokit library to send API requests to the GitHub API and returns the query result in a QueryResult object.
- **testConnection**: When adding a new data source to a ToolJet application, the connection can be tested. The testConnection method is used to test the connection, and it takes in sourceOptions as input, which represents the source metadata. The method tests the connection by trying to fetch the authenticated user and returns a ConnectionTestResult object indicating whether the connection was successful.
:::note
Not all data sources may support testing connections. If it's not applicable for your data source, you can disable the test connection feature by adding "customTesting": true to your plugin's manifest.json.
:::
- **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.
## Delete a plugin
To delete a plugin, enter the following command:
```bash
tooljet plugin delete PLUGIN_NAME
```
The CLI will prompt users to verify if the plugin to be deleted is a marketplace plugin before proceeding with the deletion.
## Publish a plugin
To release a plugin, submit a pull request on ToolJet's GitHub Repository after creating it. The ToolJet team will review the pull request, and if approved, the plugin will be included and published in the next release.

View file

@ -0,0 +1,65 @@
---
id: marketplace-setup
title: 'Marketplace: Development Setup'
---
The Marketplace offers custom plugins that can be installed in your ToolJet instance. This guide aims to assist you in creating a new plugin for the ToolJet marketplace.
## Requirements
- [Node.js](https://nodejs.org/en/download/) **(v18.3.0)**
- [npm](https://www.npmjs.com/get-npm) **(v8.11.0)**
## Getting started
### Step 1. Setup ToolJet locally
To obtain the ToolJet repository via git, use the command:
```bash
git clone https://github.com/ToolJet/ToolJet.git
```
Next, refer to the appropriate guide for your development environment to follow the Setup instructions:
- **[MacOS](/docs/contributing-guide/setup/macos)**
- **[Docker](/docs/contributing-guide/setup/docker)**
- **[Ubuntu](/docs/contributing-guide/setup/ubuntu)**
### 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
Use this environment variable to enable/disable the feature that allows users to use the marketplace.
| variable | value |
| -------------------------- | ----------------- |
| ENABLE_MARKETPLACE_FEATURE | `true` or `false` |
#### 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.
| variable | value |
| -------------------------- | ----------------- |
| ENABLE_MARKETPLACE_DEV_MODE | `true` or `false` |
Please note that the marketplace is not enabled by default. After updating the variable, restart your ToolJet instance.
For information on running ToolJet on your local machine, please refer to the instructions provided **[here](/docs/category/contributing-guide)**. You can access the marketplace by navigating to the **'/integrations'** route.
### Step 3: 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
npm install -g @tooljet/cli
# Ensure the installation was successful
tooljet --version
```
Having completed the environment setup for Marketplace Developer mode, we can proceed to the next section and commence with [developing the first plugin](/docs/contributing-guide/marketplace/creating-a-plugin).

View file

@ -0,0 +1,5 @@
{
"label": "Setup",
"position": 1,
"collapsed": true
}

View file

@ -0,0 +1,25 @@
---
id: architecture
title: Architecture
---
# Introduction
ToolJet has two main components: **ToolJet Server** and **ToolJet Client**.
### 1. ToolJet Server
ToolJet server is a Node.js API application. Server is responsible for authentication, authorization, persisting application definitions, running queries, storing data source credentials securely and more.
**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.
### 2. ToolJet Client
ToolJet client is a ReactJS application. Client is responsible for visually editing the applications, building & editing queries, rendering applications, executing events and their trigger, etc.
## Requirements
1. **Node version 18.3.0**
2. **npm version 8.11.0**

View file

@ -0,0 +1,184 @@
---
id: docker
title: Docker
---
:::warning
The following guide is intended for contributors to set-up ToolJet locally. If you're interested in **self-hosting** ToolJet, please refer to the **[Setup](/docs/setup/)** section.
:::
Docker compose is the easiest way to setup ToolJet server and client locally.
:::info
If you rather want to try out ToolJet locally with docker, you can follow the steps [here](https://docs.tooljet.com/docs/setup/docker-local).
:::
## Prerequisites
Make sure you have the latest version of `docker` and `docker-compose` installed.
[Official docker installation guide](https://docs.docker.com/desktop/)
[Official docker-compose installation guide](https://docs.docker.com/compose/install/)
We recommend:
```bash
docker --version
Docker version 19.03.12, build 48a66213fe
docker-compose --version
docker-compose version 1.26.2, build eefe0d31
```
## Setting up
:::warning
If you are setting up on a Windows machine, we advise you to setup Docker desktop with WSL2.
Please find more information [here](https://docs.docker.com/desktop/windows/wsl/).
:::
1. Clone the repository
```bash
git clone https://github.com/tooljet/tooljet.git
```
2. Create a `.env` file by copying `.env.example`. More information on the variables that can be set is given in the [environment variables reference](/docs/setup/env-vars)
```bash
cp .env.example .env
cp .env.example .env.test
```
3. Populate the keys in the `.env` and `.env.test` file
:::info
`SECRET_KEY_BASE` requires a 64 byte key. (If you have `openssl` installed, run `openssl rand -hex 64` to create a 64 byte secure random key)
`LOCKBOX_MASTER_KEY` requires a 32 byte key. (Run `openssl rand -hex 32` to create a 32 byte secure random key)
:::
:::warning
If you are setting up on a Windows machine. Please make sure that .env file line endings to be LF as it will be CRLF by default unless configured for Windows machine.
:::
Example:
```bash
cat .env
TOOLJET_HOST=http://localhost:8082
LOCKBOX_MASTER_KEY=13c9b8364ae71f714774c82498ba328813069e48d80029bb29f49d0ada5a8e40
SECRET_KEY_BASE=ea85064ed42ad02cfc022e66d8bccf452e3fa1142421cbd7a13592d91a2cbb866d6001060b73a98a65be57e65524357d445efae00a218461088a706decd62dcb
NODE_ENV=development
# DATABASE CONFIG
PG_HOST=postgres
PG_PORT=5432
PG_USER=postgres
PG_PASS=postgres
PG_DB=tooljet_development
ORM_LOGGING=all
```
```bash
cat .env.test
TOOLJET_HOST=http://localhost:8082
LOCKBOX_MASTER_KEY=13c9b8364ae71f714774c82498ba328813069e48d80029bb29f49d0ada5a8e40
SECRET_KEY_BASE=ea85064ed42ad02cfc022e66d8bccf452e3fa1142421cbd7a13592d91a2cbb866d6001060b73a98a65be57e65524357d445efae00a218461088a706decd62dcb
NODE_ENV=test
# DATABASE CONFIG
PG_HOST=postgres
PG_PORT=5432
PG_USER=postgres
PG_PASS=postgres
PG_DB=tooljet_test
ORM_LOGGING=error
```
4. Build docker images
```bash
docker-compose build
docker-compose run --rm plugins npm run build:plugins
```
5. Run ToolJet
```bash
docker-compose up
```
ToolJet should now be served locally at `http://localhost:8082`.
8. To shut down the containers,
```bash
docker-compose stop
```
## Making changes to the codebase
If you make any changes to the codebase/pull the latest changes from upstream, the tooljet server container would hot reload the application without you doing anything.
Caveat:
1. If the changes include database migrations or new npm package additions in the package.json, you would need to restart the ToolJet server container by running `docker-compose restart server`.
2. If you need to add a new binary or system library to the container itself, you would need to add those dependencies in `docker/server.Dockerfile.dev` and then rebuild the ToolJet server image. You can do that by running `docker-compose build server`. Once that completes you can start everything normally with `docker-compose up`.
Example:
Let's say you need to install the `imagemagick` binary in your ToolJet server's container. You'd then need to make sure that `apt` installs `imagemagick` while building the image. The Dockerfile at `docker/server.Dockerfile.dev` for the server would then look something like this:
```
FROM node:18.3.0-buster AS builder
RUN apt update && apt install -y \
build-essential \
postgresql \
freetds-dev \
imagemagick
RUN mkdir -p /app
WORKDIR /app
COPY ./server/package.json ./server/package-lock.json ./
RUN npm install
ENV NODE_ENV=development
COPY ./server/ ./
COPY ./docker/ ./docker/
COPY ./.env ../.env
RUN ["chmod", "755", "entrypoint.sh"]
```
Once you've updated the Dockerfile, rebuild the image by running `docker-compose build server`. After building the new image, start the services by running `docker-compose up`.
## Running tests
Test config picks up config from `.env.test` file at the root of the project.
Run the following command to create and migrate data for test db
```bash
docker-compose run --rm -e NODE_ENV=test server npm run db:create
docker-compose run --rm -e NODE_ENV=test server npm run db:migrate
```
To run the unit tests
```bash
docker-compose run --rm server npm run --prefix server test
```
To run e2e tests
```bash
docker-compose run --rm server npm run --prefix server test:e2e
```
To run a specific unit test
```bash
docker-compose run --rm server npm --prefix server run test <path-to-file>
```
## Troubleshooting
Please open a new issue at https://github.com/ToolJet/ToolJet/issues or join our [Slack Community](https://tooljet.com/slack) if you encounter any issues when trying to run ToolJet locally.

View file

@ -0,0 +1,141 @@
---
id: macos
title: Mac OS
---
:::warning
The following guide is intended for contributors to set-up ToolJet locally. If you're interested in **self-hosting** ToolJet, please refer to the **[Setup](/docs/setup/)** section.
:::
Follow these steps to setup and run ToolJet on macOS for development purposes. Open terminal and run the commands below. We recommend reading our guide on [architecture](/docs/contributing-guide/setup/architecture) of ToolJet before proceeding.
## Setting up
1. Set up the environment
1.1 Install Homebrew
```bash
/bin/bash -c "(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"
```
1.2 Install Node.js ( version: v18.3.0 ) and npm (version: v8.11.0)
```bash
brew install nvm
export NVM_DIR=~/.nvm
source $(brew --prefix nvm)/nvm.sh
nvm install 18.3.0
nvm use 18.3.0
npm install -g npm@8.11.0
```
1.3 Install Postgres
:::tip
ToolJet uses a postgres database as the persistent storage for storing data related to users and apps. We do not plan to support other databases such as MySQL.
:::
```bash
brew install postgresql
```
1.4 Install PostgREST(optional)
:::info
Required only if Tooljet Database is being used.
Please use PostgREST version 10.1.1.x
:::
```bash
brew install postgrest --version 10.1.1.20221215
```
1.5 Clone the repository
```bash
git clone https://github.com/tooljet/tooljet.git
```
2. Set up environment variables
Create a `.env` file by copying `.env.example`. More information on the variables that can be set is given in the [environment variables reference](/docs/setup/env-vars)
```bash
cp .env.example .env
```
3. Populate the keys in the env file
:::info
`SECRET_KEY_BASE` requires a 64 byte key. (If you have `openssl` installed, run `openssl rand -hex 64` to create a 64 byte secure random key)
`LOCKBOX_MASTER_KEY` requires a 32 byte key. (Run `openssl rand -hex 32` to create a 32 byte secure random key)
:::
Example:
```bash
cat .env
TOOLJET_HOST=http://localhost:8082
LOCKBOX_MASTER_KEY=1d291a926ddfd221205a23adb4cc1db66cb9fcaf28d97c8c1950e3538e3b9281
SECRET_KEY_BASE=4229d5774cfe7f60e75d6b3bf3a1dbb054a696b6d21b6d5de7b73291899797a222265e12c0a8e8d844f83ebacdf9a67ec42584edf1c2b23e1e7813f8a3339041
NODE_ENV=development
# DATABASE CONFIG
PG_HOST=postgres
PG_PORT=5432
PG_USER=postgres
PG_PASS=postgres
PG_DB=tooljet_development
ORM_LOGGING=all
```
4. Install and build dependencies
```bash
npm install
npm install --prefix server
npm install --prefix frontend
npm run build:plugins
```
5. Set up database
```bash
npm run --prefix server db:create
npm run --prefix server db:reset
```
:::info
If at any point you need to reset the database, use this command `npm run --prefix server db:reset`
:::
6. Run plugins compilation in watch mode
```bash
cd ./plugins && npm start
```
7. Run the server
```bash
cd ./server && npm run start:dev
```
8. Run the client
```bash
cd ./frontend && npm start
```
The client will start on the port 8082, you can access the client by visiting: [https://localhost:8082](https://localhost:8082)
9. Create login credentials
Visiting [https://localhost:8082](https://localhost:8082) should redirect you to the login page, click on the signup link and enter your email. The emails sent by the server in development environment are captured and are opened in your default browser. Click the invitation link in the email preview to setup the account.
## Running tests
Test config requires the presence of `.env.test` file at the root of the project.
To run the unit tests
```bash
npm run --prefix server test
```
To run e2e tests
```bash
npm run --prefix server test:e2e
```
To run a specific unit test
```bash
npm run --prefix server test <path-to-file>
```

View file

@ -0,0 +1,133 @@
---
id: ubuntu
title: Ubuntu
---
:::warning
The following guide is intended for contributors to set-up ToolJet locally. If you're interested in **self-hosting** ToolJet, please refer to the **[Setup](/docs/setup/)** section.
:::
Follow these steps to setup and run ToolJet on Ubuntu. Open terminal and run the commands below.
## Setting up
1. Set up the environment
1.1 Install NVM
```bash
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.3/install.sh | bash
```
Close and reopen your terminal to start using nvm
```bash
nvm install 18.3.0
```
Ensure you have the correct version of npm, or it will cause an error about fsevents.
```bash
npm i -g npm@8.11.0
```
1.2 Install Postgres
```bash
sudo apt install postgresql postgresql-contrib
sudo apt-get install libpq-dev
```
1.3 Install PostgREST (optional)
:::info
Required only if Tooljet Database is being used.
Please use PostgREST version 10.1.1.x
:::
Please follow the installation [PostgREST](https://postgrest.org/en/stable/install.html) guide
**Note:** Clone the GitHub repo locally using:
```bash
git clone https://github.com/ToolJet/ToolJet.git
```
2. Set up environment variables
Create a `.env` file by copying `.env.example`. More information on the variables that can be set is given in the [environment variables reference](/docs/setup/env-vars)
```bash
cp .env.example .env
```
3. Populate the keys in the env file
:::info
`SECRET_KEY_BASE` requires a 64 byte key. (If you have `openssl` installed, run `openssl rand -hex 64` to create a 64 byte secure random key)
`LOCKBOX_MASTER_KEY` requires a 32 byte key. (Run `openssl rand -hex 32` to create a 32 byte secure random key)
:::
Example:
```bash
cat .env
TOOLJET_HOST=http://localhost:8082
LOCKBOX_MASTER_KEY=1d291a926ddfd221205a23adb4cc1db66cb9fcaf28d97c8c1950e3538e3b9281
SECRET_KEY_BASE=4229d5774cfe7f60e75d6b3bf3a1dbb054a696b6d21b6d5de7b73291899797a222265e12c0a8e8d844f83ebacdf9a67ec42584edf1c2b23e1e7813f8a3339041
```
4. Install and build dependencies
```bash
npm install
npm install --prefix server
npm install --prefix frontend
npm run build:plugins
```
5. Set up database
```bash
npm run --prefix server db:create
npm run --prefix server db:reset
```
:::info
If at any point you need to reset the database, use this command `npm run --prefix server db:reset`
:::
6. Run plugins compilation in watch mode
```bash
cd ./plugins && npm start
```
7. Run the server
```bash
cd ./server && npm run start:dev
```
8. Run the client
```bash
cd ./frontend && npm start
```
The client will start running on the port 8082, you can access the client by visiting: [https://localhost:8082](https://localhost:8082)
9. Create login credentials
Visiting https://localhost:8082 should redirect you to the login page, click on the signup link and enter your email. The emails sent by the server in development environment are captured and are opened in your default browser. Click the invitation link in the email preview to setup the account.
## Running tests
Test config requires the presence of `.env.test` file at the root of the project.
To run the unit tests
```bash
npm run --prefix server test
```
To run e2e tests
```bash
npm run --prefix server test:e2e
```
To run a specific unit test
```bash
npm run --prefix server test <path-to-file>
```

View file

@ -0,0 +1,18 @@
---
id: windows
title: Windows
---
To run ToolJet, please install it in an Ubuntu environment using **[Windows Subsystem for Linux 2](https://learn.microsoft.com/en-us/windows/wsl/install-manual#step-2---check-requirements-for-running-wsl-2)**. You can obtain the Ubuntu environment from the **Microsoft Store** by visiting this [link](https://apps.microsoft.com/store/detail/ubuntu-22042-lts/9PN20MSR04DW).
After successfully installing the Ubuntu environment, you will have access to a terminal window similar to the one shown below:
<div style={{textAlign: 'center'}}>
<img className="screenshot-full" src="/img/contributing-guide/windows/wsl2.png" alt="Windows setup" />
</div>
:::warning
If you are setting up ToolJet on a Windows machine, ensure that the line endings in the **.env** file are changed to LF. By default, they may be set to CRLF, which is not compatible unless configured specifically for Windows machines.
:::
Once the environment is set up, you can proceed with the steps outlined in the Ubuntu documentation at **[Contributing Guide - Ubuntu Setup](/docs/contributing-guide/setup/ubuntu)**.

View file

@ -0,0 +1,90 @@
---
id: slackcoc
title: Slack Code of Conduct
---
# Slack Code of Conduct
This code of conduct governs ToolJet's Slack Community events and discussions.
---
## Introduction
- Diversity and inclusion make our community strong. We encourage participation from the most varied and diverse backgrounds possible and want to be very clear about where we stand.
- Our goal is to maintain a safe, helpful and friendly community for everyone, regardless of experience, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, religion, nationality, or other defining characteristic.
- This code and related procedures apply to unacceptable behavior occurring in all community venues, including behavior outside the scope of community activities — online and in-person— as well as in all one-on-one communications, and anywhere such behavior has the potential to adversely affect the safety and well-being of community members.
## Expected behavior
- Be welcoming.
- Be kind.
- Look out for each other.
## Unacceptable Behavior
- Conduct or speech which might be considered sexist, racist, homophobic, transphobic, ableist or otherwise discriminatory or offensive in nature.
- Do not use unwelcome, suggestive, derogatory or inappropriate nicknames or terms.
- Do not show disrespect towards others. (Jokes, innuendo, dismissive attitudes.)
- Intimidation or harassment (online or in-person).
- Disrespect towards differences of opinion.
- Inappropriate attention or contact. Be aware of how your actions affect others. If it makes someone uncomfortable, stop.
- Not understanding the differences between constructive criticism and disparagement.
- Sustained disruptions.
- Violence, threats of violence or violent language.
## Where does the Code of Conduct apply?
This Code of Conduct applies to all spaces managed by ToolJet. This includes:
- Conferences (including social events and peripheral activities)
- Unconferences and sprints
- Meetups, including their discussion boards
- Workshops
- Presentation materials used in talks or sessions
- Slack
- GitHub
- Twitter hashtag and mentions
- Any forums created by the ToolJet which the community uses for communication.
The Code of Conduct does not exclusively apply to slack or events on an official agenda. For example, if after a scheduled social event you go to a bar with a group of fellow participants, and someone harasses you there, we would still treat that as a CoC violation. Similarly, harassment in Twitter direct messages related to ToolJet can still be covered under this Code of Conduct.
In addition, violations of this code outside our spaces may affect a persons ability to participate in them.
## Enforcement
- Understand that speech and actions have consequences, and unacceptable behavior will not be tolerated.
- If you are the subject of, or witness to any violations of this Code of Conduct, please contact us via email at hello@tooljet.com or dm @navaneeth on slack.
- If violations occur, organizers will take any action they deem appropriate for the infraction, up to and including expulsion.
:::info
Portions derived from the [Django Code of Conduct](https://www.djangoproject.com/conduct/), [The Rust Code of Conduct](https://www.rust-lang.org/conduct.html) and [The Ada Initiative](https://adainitiative.org) under a Creative Commons Attribution-ShareAlike license.
:::
---
## Etiquettes to follow
#### 1. Be nice to everyone
#### 2. Check off your resolved questions
If you have received a useful reply to your question, please drop a ✅ reaction or a reply for affirmation.
#### 3. Try not to repost question
If you have asked a question and have not got a response in 24hrs, please review your question for clarity and revise it. If you still feel you haven't received adequate response, feel free to ping @navaneeth.
#### 4. Post in public
Please don't direct message any individual member of ToolJet community without their explicit permission, independent of reason. Your question might be helpful for other community members.
#### 5. Don't spam tags
ToolJet's community of volunteer is very active and helpful, generally avoid tagging members unless it is urgent.
#### 6. Use threads for discussion
To keep the main channel area clear, we request to use threads to keep an ongoing conversation organized.

View file

@ -0,0 +1,57 @@
---
id: testing
title: Testing
---
Follow the steps below to setup and run the test specifications using Cypress. We recommend [setting up ToolJet locally](/docs/contributing-guide/setup/macos) before proceeding.
## Setting up
- Navigate to the `cypress-tests` directory and enter the following command:
```bash
npm install
```
## 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 -- --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)
:::

View file

@ -0,0 +1,46 @@
---
id: eslint
title: EsLint
---
# ESLint
ESLint as a code quality tool is a tool that checks your code for errors and helps you to fix them and enforces a coding style.
## Setup
1. Install the [ESLint extension](https://eslint.org/docs/latest/user-guide/integrations) for your code editor.
2. Set your editor's default formatter to `ESLint`.
:::tip
For VSCode users, you can set the formatter to `ESLint` in the [**settings.json**](https://code.visualstudio.com/docs/getstarted/settings#_settingsjson).
:::
3. Install the dependencies.
```bash
npm install
npm install --prefix server
npm install --prefix frontend
```
4. Run the linter.
```bash
npm run --prefix server lint
npm run --prefix frontend lint
```
5. Fix the ESlint errors and warnings.
```bash
npm run --prefix server format
npm run --prefix frontend format
```
## Requirements
1. **Node version 18.3.0**
2. **npm version 8.11.0**
:::tip
It is recommended to check the VSCode **Setting.json**(Press `ctrl/cmnd + P` and search `>Settings (JSON)`) file to ensure there are no overrides to the eslint config rules. Comment the following rules for eslint: **eslint.options: {...}**.
:::

Some files were not shown because too many files have changed in this diff Show more