mirror of
https://github.com/ToolJet/ToolJet
synced 2026-05-23 17:08:34 +00:00
Merge branch 'feat/grid-appbuilder-improvement' into builder-performance-platform-part/release
This commit is contained in:
commit
2c90827a15
2048 changed files with 224577 additions and 20076 deletions
4
.github/workflows/docs-pr-app.yml
vendored
4
.github/workflows/docs-pr-app.yml
vendored
|
|
@ -40,11 +40,11 @@ jobs:
|
|||
},
|
||||
{
|
||||
"key": "NODE_VERSION",
|
||||
"value": "16.18.1"
|
||||
"value": "18.18.2"
|
||||
},
|
||||
{
|
||||
"key": "NPM_VERSION",
|
||||
"value": "8.19.2"
|
||||
"value": "9.8.1"
|
||||
},
|
||||
{
|
||||
"key": "GTM",
|
||||
|
|
|
|||
91
.github/workflows/maketplace-plugins-deploy.yml
vendored
Normal file
91
.github/workflows/maketplace-plugins-deploy.yml
vendored
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
name: Maketplace plugin build
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
types: [labeled, unlabeled, closed]
|
||||
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
PR_NUMBER: ${{ github.event.number }}
|
||||
BRANCH_NAME: ${{ github.head_ref || github.ref_name }}
|
||||
|
||||
|
||||
jobs:
|
||||
deploy-marketplace-plugin:
|
||||
if: ${{ github.event.action == 'labeled' && github.event.label.name == 'deploy-marketplace-plugin' }}
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
|
||||
- name: Sync repo
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Check if PR is from the same repo
|
||||
id: check_repo
|
||||
run: echo "::set-output name=is_fork::$(if [[ '${{ github.event.pull_request.head.repo.full_name }}' != '${{ github.event.pull_request.base.repo.full_name }}' ]]; then echo true; else echo false; fi)"
|
||||
|
||||
- name: Fetch the remote branch if it's a forked PR
|
||||
if: steps.check_repo.outputs.is_fork == 'true'
|
||||
run: |
|
||||
git fetch origin pull/${{ github.event.number }}/head:${{ env.BRANCH_NAME }}
|
||||
git checkout ${{ env.BRANCH_NAME }}
|
||||
|
||||
- name: Checkout
|
||||
if: steps.check_repo.outputs.is_fork == 'false'
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.ref }}
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: 18.18.2
|
||||
|
||||
- name: Configure AWS Credentials
|
||||
uses: aws-actions/configure-aws-credentials@v4
|
||||
with:
|
||||
aws-access-key-id: ${{ secrets.AWS_ACCESS_MAR_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_SECRET_MAR_ACCESS_KEY }}
|
||||
aws-region: us-east-2
|
||||
|
||||
- name: Install and build dependencies
|
||||
run: |
|
||||
cd marketplace && npm install && npm run build --workspaces
|
||||
|
||||
- name: Build marketplace plugins
|
||||
run: |
|
||||
cd marketplace && AWS_BUCKET=tooljet-plugins-stage node scripts/upload-to-s3.js
|
||||
|
||||
- name: Comment deployment URL
|
||||
uses: actions/github-script@v5
|
||||
with:
|
||||
github-token: ${{secrets.GITHUB_TOKEN}}
|
||||
script: |
|
||||
github.rest.issues.createComment({
|
||||
issue_number: context.issue.number,
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
body: 'Marketplace Plugin added to stage bucket'
|
||||
})
|
||||
|
||||
- uses: actions/github-script@v6
|
||||
with:
|
||||
script: |
|
||||
try {
|
||||
await github.rest.issues.removeLabel({
|
||||
issue_number: context.issue.number,
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
name: 'deploy-marketplace-plugin'
|
||||
})
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
}
|
||||
|
||||
await github.rest.issues.addLabels({
|
||||
issue_number: context.issue.number,
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
labels: ['marketplace-plugin-deployed']
|
||||
})
|
||||
4
.github/workflows/render-preview-deploy.yml
vendored
4
.github/workflows/render-preview-deploy.yml
vendored
|
|
@ -132,6 +132,10 @@ jobs:
|
|||
{
|
||||
"key": "ENABLE_MARKETPLACE_FEATURE",
|
||||
"value": "true"
|
||||
},
|
||||
{
|
||||
"key": "TOOLJET_MARKETPLACE_URL",
|
||||
"value": "${{ secrets.MARKETPLACE_BUCKET }}"
|
||||
}
|
||||
],
|
||||
"serviceDetails": {
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ jobs:
|
|||
- name: Send Slack Notification
|
||||
run: |
|
||||
if [[ "${{ job.status }}" == "success" ]]; then
|
||||
message="Job '${{ env.JOB_NAME }}' succeeded! tooljet/tooljet-ce:${{ github.event.release.tag_name }}"
|
||||
message="ToolJet community image published:\n\`tooljet/tooljet-ce:${{ github.event.release.tag_name }}\`"
|
||||
else
|
||||
message="Job '${{ env.JOB_NAME }}' failed! tooljet/tooljet-ce:${{ github.event.release.tag_name }}"
|
||||
fi
|
||||
|
|
|
|||
3
.version
3
.version
|
|
@ -1 +1,2 @@
|
|||
2.33.1
|
||||
2.40.0
|
||||
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@ module.exports = defineConfig({
|
|||
experimentalRunAllSpecs: true,
|
||||
baseUrl: "http://localhost:8082",
|
||||
specPattern: [
|
||||
"cypress/e2e/happyPath/platform/ceTestcases/appSlug.cy.js",
|
||||
"cypress/e2e/happyPath/platform/ceTestcases/editor/appSlug.cy.js",
|
||||
"cypress/e2e/happyPath/platform/commonTestcases/**/*.cy.js",
|
||||
"cypress/e2e/happyPath/platform/ceTestcases/**/!(*appSlug).cy.js"
|
||||
],
|
||||
|
|
|
|||
|
|
@ -3,7 +3,8 @@ Cypress.Commands.add(
|
|||
(
|
||||
userEmail = "dev@tooljet.io",
|
||||
userPassword = "password",
|
||||
workspaceId = ""
|
||||
workspaceId = "",
|
||||
redirection = "/"
|
||||
) => {
|
||||
cy.request({
|
||||
url: `http://localhost:3000/api/authenticate/${workspaceId}`,
|
||||
|
|
@ -11,6 +12,7 @@ Cypress.Commands.add(
|
|||
body: {
|
||||
email: userEmail,
|
||||
password: userPassword,
|
||||
redirectTo: redirection
|
||||
},
|
||||
})
|
||||
.its("body")
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@ export const dataSourceText = {
|
|||
labelDataSources: "Datasources",
|
||||
labelAddDataSource: "+ add data source",
|
||||
|
||||
allDataSources: "All data sources (41)",
|
||||
allDatabase: "Databases (17)",
|
||||
allDataSources: "All data sources (42)",
|
||||
allDatabase: "Databases (18)",
|
||||
allApis: "APIs (20)",
|
||||
allCloudStorage: "Cloud Storages (4)",
|
||||
pluginsLabelAndCount: "Plugins (0)",
|
||||
|
|
|
|||
|
|
@ -2,6 +2,6 @@ export const elasticsearchText = {
|
|||
elasticSearch: "Elasticsearch",
|
||||
cypressElasticsearch: "cypress-elasticsearch",
|
||||
|
||||
errorConnectionRefused: "connect ECONNREFUSED ::1:9200",
|
||||
errorConnectionRefused: "connect ECONNREFUSED 127.0.0.1:9200",
|
||||
errorGetAddrInfoNotFound: "getaddrinfo ENOTFOUND elasticsearch_host",
|
||||
};
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ export const exportAppModalText = {
|
|||
};
|
||||
|
||||
export const importText = {
|
||||
importOption: "Import",
|
||||
importOption: "Import from device",
|
||||
couldNotImportAppToastMessage: `Could not import: SyntaxError: Unexpected token`,
|
||||
appImportedToastMessage: "App imported successfully.",
|
||||
};
|
||||
|
|
|
|||
|
|
@ -4,13 +4,13 @@ export const postgreSqlText = {
|
|||
|
||||
allDataSources: () => {
|
||||
return Cypress.env("marketplace_action")
|
||||
? "All data sources (43)"
|
||||
: "All data sources (41)";
|
||||
? "All data sources (44)"
|
||||
: "All data sources (42)";
|
||||
},
|
||||
allDatabase: () => {
|
||||
return Cypress.env("marketplace_action")
|
||||
? "Databases (19)"
|
||||
: "Databases (17)";
|
||||
? "Databases (20)"
|
||||
: "Databases (18)";
|
||||
},
|
||||
allApis: "APIs (20)",
|
||||
allCloudStorage: "Cloud Storages (4)",
|
||||
|
|
|
|||
|
|
@ -241,7 +241,7 @@ describe("Table", () => {
|
|||
openAccordion("Action buttons");
|
||||
cy.get('[data-cy="no-items-banner-action-button"]').should(
|
||||
"have.text",
|
||||
"There are no action buttons"
|
||||
"No action buttons"
|
||||
);
|
||||
cy.get('[data-cy="button-add-new-action-button"]')
|
||||
.should("have.text", "New action button")
|
||||
|
|
|
|||
|
|
@ -108,7 +108,7 @@ describe("Data source MongoDB", () => {
|
|||
);
|
||||
cy.get('[data-cy="connection-alert-text"]').verifyVisibleElement(
|
||||
"have.text",
|
||||
"connect ECONNREFUSED ::1:27017"
|
||||
mongoDbText.errorConnectionRefused
|
||||
);
|
||||
cy.get('[data-cy="query-select-dropdown"]').type(
|
||||
mongoDbText.optionConnectUsingConnectionString
|
||||
|
|
@ -149,7 +149,11 @@ describe("Data source MongoDB", () => {
|
|||
cy.get(postgreSqlSelector.buttonSave)
|
||||
.verifyVisibleElement("have.text", postgreSqlText.buttonTextSave)
|
||||
.click();
|
||||
|
||||
cy.verifyToastMessage(
|
||||
commonSelectors.toastMessage,
|
||||
postgreSqlText.toastDSSaved
|
||||
);
|
||||
cy.wait(1000);
|
||||
deleteDatasource(`cypress-${data.dataSourceName}-mongodb`);
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -120,11 +120,11 @@ describe("Data sources", () => {
|
|||
postgreSqlText.placeholderEnterHost,
|
||||
Cypress.env("sqlserver_host")
|
||||
);
|
||||
fillDataSourceTextField(
|
||||
"Instance",
|
||||
"Enter the name of the database instance",
|
||||
Cypress.env("sqlserver_instance")
|
||||
);
|
||||
// fillDataSourceTextField(
|
||||
// "Instance",
|
||||
// "Enter the name of the database instance",
|
||||
// Cypress.env("sqlserver_instance")
|
||||
// );
|
||||
fillDataSourceTextField(
|
||||
postgreSqlText.labelPort,
|
||||
postgreSqlText.placeholderEnterPort,
|
||||
|
|
|
|||
|
|
@ -37,18 +37,16 @@ describe("App Version Functionality", () => {
|
|||
let currentVersion = "";
|
||||
let newVersion = [];
|
||||
let versionFrom = "";
|
||||
before(() => {
|
||||
cy.apiLogin();
|
||||
cy.apiCreateApp(data.appName);
|
||||
cy.logoutApi();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
cy.apiLogin();
|
||||
cy.visit('/my-workspace')
|
||||
cy.defaultWorkspaceLogin();
|
||||
cy.skipWalkthrough();
|
||||
})
|
||||
|
||||
it("Verify the elements of the version module", () => {
|
||||
navigateToAppEditor(data.appName);
|
||||
data.appName = `${fake.companyName}-App`;
|
||||
cy.apiCreateApp(data.appName);
|
||||
cy.openApp()
|
||||
cy.get(appVersionSelectors.appVersionLabel).should("be.visible");
|
||||
cy.get(commonSelectors.appNameInput).verifyVisibleElement(
|
||||
"have.value",
|
||||
|
|
@ -68,9 +66,10 @@ describe("App Version Functionality", () => {
|
|||
});
|
||||
|
||||
it("Verify all functionality for the app version", () => {
|
||||
navigateToAppEditor(data.appName);
|
||||
data.appName = `${fake.companyName}-App`;
|
||||
cy.apiCreateApp(data.appName);
|
||||
cy.openApp()
|
||||
cy.get('[data-cy="widget-list-box-table"]').should("be.visible");
|
||||
cy.skipEditorPopover();
|
||||
|
||||
cy.dragAndDropWidget("Toggle Switch", 50, 50);
|
||||
verifyComponent("toggleswitch1");
|
||||
|
|
|
|||
|
|
@ -11,10 +11,13 @@ describe("Manage SSO for multi workspace", () => {
|
|||
const envVar = Cypress.env("environment");
|
||||
beforeEach(() => {
|
||||
cy.defaultWorkspaceLogin();
|
||||
SSO.setSSOStatus("My workspace", "google", false);
|
||||
SSO.setSSOStatus("My workspace", "git", false);
|
||||
SSO.deleteOrganisationSSO("My workspace", ["google", "git"]);
|
||||
});
|
||||
it("Should verify General settings page elements", () => {
|
||||
SSO.resetDomain();
|
||||
SSO.setSignupStatus(false);
|
||||
SSO.defaultSSO(true);
|
||||
|
||||
common.navigateToManageSSO();
|
||||
cy.get(commonSelectors.breadcrumbTitle).should(($el) => {
|
||||
expect($el.contents().first().text().trim()).to.eq(
|
||||
|
|
@ -83,7 +86,7 @@ describe("Manage SSO for multi workspace", () => {
|
|||
.verifyVisibleElement("have.text", ssoText.saveButton);
|
||||
|
||||
SSO.googleSSOPageElements();
|
||||
SSO.defaultSSO("My workspace", false);
|
||||
SSO.defaultSSO(false);
|
||||
cy.logoutApi();
|
||||
cy.visit("/login/my-workspace");
|
||||
cy.get(ssoSelector.googleIcon).should("be.visible");
|
||||
|
|
@ -94,7 +97,7 @@ describe("Manage SSO for multi workspace", () => {
|
|||
});
|
||||
|
||||
it("Should verify Git SSO page elements", () => {
|
||||
SSO.defaultSSO("My workspace", true);
|
||||
SSO.defaultSSO(true);
|
||||
|
||||
common.navigateToManageSSO();
|
||||
|
||||
|
|
@ -139,7 +142,7 @@ describe("Manage SSO for multi workspace", () => {
|
|||
.verifyVisibleElement("have.text", ssoText.saveButton);
|
||||
|
||||
SSO.gitSSOPageElements();
|
||||
SSO.defaultSSO("My workspace", false);
|
||||
SSO.defaultSSO(false);
|
||||
cy.logoutApi();
|
||||
cy.visit("/login/my-workspace");
|
||||
|
||||
|
|
@ -149,107 +152,4 @@ describe("Manage SSO for multi workspace", () => {
|
|||
ssoText.gitSignInText
|
||||
);
|
||||
});
|
||||
|
||||
if (envVar === "Community") {
|
||||
it.skip("Should verify the workspace login page", () => {
|
||||
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);
|
||||
|
||||
SSO.workspaceLogin(data.workspaceName);
|
||||
SSO.disableDefaultSSO();
|
||||
SSO.visitWorkspaceLoginPage();
|
||||
cy.notVisible(ssoSelector.googleSSOText);
|
||||
cy.notVisible(ssoSelector.gitSSOText);
|
||||
SSO.passwordLoginVisible();
|
||||
|
||||
SSO.workspaceLogin(data.workspaceName);
|
||||
common.navigateToManageSSO();
|
||||
cy.get(ssoSelector.google).should("be.visible").click();
|
||||
|
||||
cy.get(ssoSelector.googleEnableToggle).check();
|
||||
cy.get(ssoSelector.statusLabel).verifyVisibleElement(
|
||||
"have.text",
|
||||
ssoText.enabledLabel
|
||||
);
|
||||
SSO.visitWorkspaceLoginPage();
|
||||
cy.get(ssoSelector.googleSSOText).verifyVisibleElement(
|
||||
"have.text",
|
||||
ssoText.googleSSOText
|
||||
);
|
||||
cy.notVisible(ssoSelector.gitSSOText);
|
||||
SSO.passwordLoginVisible();
|
||||
|
||||
SSO.workspaceLogin(data.workspaceName);
|
||||
common.navigateToManageSSO();
|
||||
cy.get(ssoSelector.google).should("be.visible").click();
|
||||
cy.get(ssoSelector.googleEnableToggle).uncheck();
|
||||
cy.get(ssoSelector.statusLabel).verifyVisibleElement(
|
||||
"have.text",
|
||||
ssoText.disabledLabel
|
||||
);
|
||||
|
||||
cy.get(ssoSelector.git).should("be.visible").click();
|
||||
cy.get(ssoSelector.gitEnableToggle).check();
|
||||
cy.get(ssoSelector.statusLabel).verifyVisibleElement(
|
||||
"have.text",
|
||||
ssoText.enabledLabel
|
||||
);
|
||||
SSO.visitWorkspaceLoginPage();
|
||||
cy.get(ssoSelector.gitSSOText).verifyVisibleElement(
|
||||
"have.text",
|
||||
ssoText.gitSignInText
|
||||
);
|
||||
SSO.passwordLoginVisible();
|
||||
|
||||
SSO.workspaceLogin(data.workspaceName);
|
||||
common.navigateToManageSSO();
|
||||
cy.get(ssoSelector.google).should("be.visible").click();
|
||||
|
||||
cy.get(ssoSelector.googleEnableToggle).check();
|
||||
cy.get(ssoSelector.statusLabel).verifyVisibleElement(
|
||||
"have.text",
|
||||
ssoText.enabledLabel
|
||||
);
|
||||
SSO.visitWorkspaceLoginPage();
|
||||
SSO.workspaceLoginPageElements(data.workspaceName);
|
||||
|
||||
SSO.workspaceLogin(data.workspaceName);
|
||||
common.navigateToManageSSO();
|
||||
cy.get(ssoSelector.passwordEnableToggle).uncheck();
|
||||
cy.get(commonSelectors.buttonSelector("Yes")).click();
|
||||
|
||||
SSO.visitWorkspaceLoginPage();
|
||||
cy.get(ssoSelector.googleSSOText).verifyVisibleElement(
|
||||
"have.text",
|
||||
ssoText.googleSSOText
|
||||
);
|
||||
cy.get(ssoSelector.gitSSOText).verifyVisibleElement(
|
||||
"have.text",
|
||||
ssoText.gitSignInText
|
||||
);
|
||||
cy.notVisible(commonSelectors.workEmailInputField);
|
||||
cy.notVisible(commonSelectors.passwordInputField);
|
||||
cy.notVisible(commonSelectors.loginButton);
|
||||
|
||||
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();
|
||||
SSO.visitWorkspaceLoginPage();
|
||||
cy.get(ssoSelector.noLoginMethodWarning).verifyVisibleElement(
|
||||
"have.text",
|
||||
ssoText.noLoginMethodWarning
|
||||
);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
import { commonSelectors } from "Selectors/common";
|
||||
import { commonText } from "Texts/common";
|
||||
import { SignUpPageElements } from "Support/utils/manageSSO";
|
||||
import { SignUpPageElements } from "Support/utils/onboarding";
|
||||
import { fake } from "Fixtures/fake";
|
||||
import {
|
||||
verifyConfirmEmailPage,
|
||||
|
|
@ -49,7 +49,9 @@ describe("User signup", () => {
|
|||
verifyOnboardingQuestions(data.fullName, data.workspaceName);
|
||||
});
|
||||
it("Verify invalid invitation link", () => {
|
||||
cy.log(invitationLink)
|
||||
cy.visit(invitationLink);
|
||||
cy.pause()
|
||||
verifyInvalidInvitationLink();
|
||||
cy.get(commonSelectors.backtoSignUpButton).click();
|
||||
cy.get(commonSelectors.SignUpSectionHeader).should("be.visible");
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ describe("dashboard", () => {
|
|||
cy.get(commonSelectors.editRectangleIcon).should("be.visible");
|
||||
cy.get(commonSelectors.appCreateButton).verifyVisibleElement(
|
||||
"have.text",
|
||||
"Create new app"
|
||||
"Create an app"
|
||||
);
|
||||
cy.get(dashboardSelector.folderLabel).should("be.visible");
|
||||
cy.get(dashboardSelector.folderLabel).should(($el) => {
|
||||
|
|
|
|||
|
|
@ -2,14 +2,25 @@ import { commonSelectors } from "Selectors/common";
|
|||
import { fake } from "Fixtures/fake";
|
||||
import { usersText } from "Texts/manageUsers";
|
||||
import { usersSelector } from "Selectors/manageUsers";
|
||||
import * as users from "Support/utils/manageUsers";
|
||||
import * as common from "Support/utils/common";
|
||||
import { path } from "Texts/common";
|
||||
import { dashboardSelector } from "Selectors/dashboard";
|
||||
import {
|
||||
manageUsersElements,
|
||||
fillUserInviteForm,
|
||||
confirmInviteElements,
|
||||
selectUserGroup,
|
||||
inviteUserWithUserGroups,
|
||||
fetchAndVisitInviteLink,
|
||||
} from "Support/utils/manageUsers";
|
||||
import {
|
||||
navigateToManageUsers,
|
||||
logout,
|
||||
searchUser,
|
||||
navigateToManageGroups,
|
||||
} from "Support/utils/common";
|
||||
import { updateWorkspaceName } from "Support/utils/userPermissions";
|
||||
import { groupsSelector } from "Selectors/manageGroups";
|
||||
import { groupsText } from "Texts/manageGroups";
|
||||
import { addNewUser } from "Support/utils/onboarding";
|
||||
import { addNewUser, visitWorkspaceInvitation } from "Support/utils/onboarding";
|
||||
import { commonText } from "Texts/common";
|
||||
|
||||
const data = {};
|
||||
data.groupName = fake.firstName.replaceAll("[^A-Za-z]", "");
|
||||
|
|
@ -26,9 +37,9 @@ describe("Manage Users", () => {
|
|||
it("Should verify the Manage users page", () => {
|
||||
data.firstName = fake.firstName;
|
||||
data.email = fake.email.toLowerCase().replaceAll("[^A-Za-z]", "");
|
||||
common.navigateToManageUsers();
|
||||
navigateToManageUsers();
|
||||
|
||||
users.manageUsersElements();
|
||||
manageUsersElements();
|
||||
|
||||
cy.get(commonSelectors.cancelButton).click();
|
||||
cy.get(usersSelector.usersPageTitle).should("be.visible");
|
||||
|
|
@ -78,28 +89,51 @@ describe("Manage Users", () => {
|
|||
data.email = fake.email.toLowerCase().replaceAll("[^A-Za-z]", "");
|
||||
cy.removeAssignedApps();
|
||||
|
||||
common.navigateToManageUsers();
|
||||
users.fillUserInviteForm(data.firstName, data.email);
|
||||
navigateToManageUsers();
|
||||
fillUserInviteForm(data.firstName, data.email);
|
||||
cy.get(usersSelector.buttonInviteUsers).click();
|
||||
cy.wait(2000);
|
||||
users.fetchAndVisitInviteLink(data.email);
|
||||
users.confirmInviteElements();
|
||||
fetchAndVisitInviteLink(data.email);
|
||||
confirmInviteElements(data.email);
|
||||
|
||||
cy.clearAndType(commonSelectors.passwordInputField, "pass");
|
||||
cy.get(commonSelectors.acceptInviteButton).should("be.disabled");
|
||||
cy.get(commonSelectors.signUpButton).should("be.disabled");
|
||||
cy.clearAndType(commonSelectors.passwordInputField, usersText.password);
|
||||
cy.get(commonSelectors.acceptInviteButton).should("not.be.disabled");
|
||||
cy.get(commonSelectors.acceptInviteButton).click();
|
||||
cy.get(commonSelectors.signUpButton).should("not.be.disabled");
|
||||
cy.get(commonSelectors.signUpButton).click();
|
||||
|
||||
cy.get(commonSelectors.invitePageHeader).verifyVisibleElement(
|
||||
"have.text",
|
||||
commonText.invitePageHeader
|
||||
);
|
||||
cy.get(commonSelectors.invitePageSubHeader).verifyVisibleElement(
|
||||
"have.text",
|
||||
commonText.invitePageSubHeader
|
||||
);
|
||||
cy.verifyLabel("Name");
|
||||
cy.get(commonSelectors.invitedUserName).verifyVisibleElement(
|
||||
"have.text",
|
||||
data.firstName
|
||||
);
|
||||
cy.verifyLabel("Email");
|
||||
|
||||
cy.get(commonSelectors.invitedUserEmail).verifyVisibleElement(
|
||||
"have.text",
|
||||
data.email
|
||||
);
|
||||
cy.get(commonSelectors.acceptInviteButton)
|
||||
.verifyVisibleElement("have.text", commonText.acceptInviteButton)
|
||||
.click();
|
||||
cy.get(commonSelectors.workspaceName).verifyVisibleElement(
|
||||
"have.text",
|
||||
"My workspace"
|
||||
);
|
||||
updateWorkspaceName(data.email);
|
||||
|
||||
common.logout();
|
||||
logout();
|
||||
cy.defaultWorkspaceLogin();
|
||||
common.navigateToManageUsers();
|
||||
common.searchUser(data.email);
|
||||
navigateToManageUsers();
|
||||
searchUser(data.email);
|
||||
cy.contains("td", data.email)
|
||||
.parent()
|
||||
.within(() => {
|
||||
|
|
@ -115,8 +149,8 @@ describe("Manage Users", () => {
|
|||
cy.logoutApi();
|
||||
|
||||
cy.defaultWorkspaceLogin();
|
||||
common.navigateToManageUsers();
|
||||
common.searchUser(data.email);
|
||||
navigateToManageUsers();
|
||||
searchUser(data.email);
|
||||
cy.wait(1000);
|
||||
cy.get(usersSelector.userActionButton).click();
|
||||
cy.get('[data-cy="archive-button"]').click();
|
||||
|
|
@ -131,7 +165,7 @@ describe("Manage Users", () => {
|
|||
cy.get("td small").should("have.text", usersText.archivedStatus);
|
||||
});
|
||||
|
||||
common.logout();
|
||||
logout();
|
||||
cy.visit("/");
|
||||
cy.clearAndType(commonSelectors.workEmailInputField, data.email);
|
||||
cy.clearAndType(commonSelectors.passwordInputField, usersText.password);
|
||||
|
|
@ -140,11 +174,11 @@ describe("Manage Users", () => {
|
|||
updateWorkspaceName(data.email);
|
||||
cy.get(commonSelectors.workspaceName).click();
|
||||
cy.contains("My workspace").should("not.exist");
|
||||
common.logout();
|
||||
logout();
|
||||
|
||||
cy.defaultWorkspaceLogin();
|
||||
common.navigateToManageUsers();
|
||||
common.searchUser(data.email);
|
||||
navigateToManageUsers();
|
||||
searchUser(data.email);
|
||||
cy.wait(1000);
|
||||
cy.get(usersSelector.userActionButton).click();
|
||||
cy.get('[data-cy="archive-button"]').click();
|
||||
|
|
@ -153,52 +187,17 @@ describe("Manage Users", () => {
|
|||
usersText.unarchivedToast
|
||||
);
|
||||
|
||||
cy.task("updateId", {
|
||||
dbconfig: Cypress.env("app_db"),
|
||||
sql: `select invitation_token from users where email='${data.email}';`,
|
||||
}).then((resp) => {
|
||||
invitationToken = resp.rows[0].invitation_token;
|
||||
|
||||
cy.task("updateId", {
|
||||
dbconfig: Cypress.env("app_db"),
|
||||
sql: "select id from organizations where name='My workspace';",
|
||||
}).then((resp) => {
|
||||
workspaceId = resp.rows[0].id;
|
||||
|
||||
cy.task("updateId", {
|
||||
dbconfig: Cypress.env("app_db"),
|
||||
sql: `select id from users where email='${data.email}';`,
|
||||
}).then((resp) => {
|
||||
userId = resp.rows[0].id;
|
||||
|
||||
cy.task("updateId", {
|
||||
dbconfig: Cypress.env("app_db"),
|
||||
sql: `select invitation_token from organization_users where user_id='${userId}';`,
|
||||
}).then((resp) => {
|
||||
organizationToken = resp.rows[1].invitation_token;
|
||||
|
||||
url = `/invitations/${invitationToken}/workspaces/${organizationToken}?oid=${workspaceId}`;
|
||||
|
||||
cy.contains("td", data.email)
|
||||
.parent()
|
||||
.within(() => {
|
||||
cy.get("td small").should("have.text", usersText.invitedStatus);
|
||||
});
|
||||
common.logout();
|
||||
cy.wait(500);
|
||||
cy.visit(url);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
visitWorkspaceInvitation(data.email, "My workspace");
|
||||
|
||||
cy.clearAndType(commonSelectors.workEmailInputField, data.email);
|
||||
cy.clearAndType(commonSelectors.passwordInputField, "password");
|
||||
cy.get(commonSelectors.signInButton).click();
|
||||
cy.get(usersSelector.acceptInvite).click();
|
||||
cy.verifyToastMessage(commonSelectors.toastMessage, usersText.inviteToast);
|
||||
cy.url().should("include", path.loginPath);
|
||||
|
||||
logout();
|
||||
cy.defaultWorkspaceLogin();
|
||||
common.navigateToManageUsers();
|
||||
common.searchUser(data.email);
|
||||
navigateToManageUsers();
|
||||
searchUser(data.email);
|
||||
cy.contains("td", data.email)
|
||||
.parent()
|
||||
.within(() => {
|
||||
|
|
@ -211,9 +210,9 @@ describe("Manage Users", () => {
|
|||
data.email = fake.email.toLowerCase().replaceAll("[^A-Za-z]", "");
|
||||
const groupNames = ["All users", "Admin"];
|
||||
|
||||
common.navigateToManageUsers();
|
||||
navigateToManageUsers();
|
||||
|
||||
users.fillUserInviteForm(data.firstName, data.email);
|
||||
fillUserInviteForm(data.firstName, data.email);
|
||||
cy.wait(1500);
|
||||
cy.get('[data-cy="user-group-select"]>>>>>').dblclick();
|
||||
cy.get("body").then(($body) => {
|
||||
|
|
@ -229,7 +228,7 @@ describe("Manage Users", () => {
|
|||
cy.get(commonSelectors.cancelButton).click();
|
||||
|
||||
cy.get(usersSelector.buttonAddUsers).click();
|
||||
users.selectUserGroup("Admin");
|
||||
selectUserGroup("Admin");
|
||||
cy.get(".selected-value").verifyVisibleElement("have.text", "Admin");
|
||||
cy.get(commonSelectors.cancelButton).click();
|
||||
|
||||
|
|
@ -240,14 +239,9 @@ describe("Manage Users", () => {
|
|||
);
|
||||
cy.get(commonSelectors.cancelButton).click();
|
||||
|
||||
users.inviteUserWithUserGroups(
|
||||
data.firstName,
|
||||
data.email,
|
||||
"All users",
|
||||
"Admin"
|
||||
);
|
||||
inviteUserWithUserGroups(data.firstName, data.email, "All users", "Admin");
|
||||
|
||||
common.navigateToManageGroups();
|
||||
navigateToManageGroups();
|
||||
cy.get(groupsSelector.groupLink("Admin")).click();
|
||||
cy.get(groupsSelector.usersLink).click();
|
||||
cy.get(groupsSelector.userRow(data.email)).should("be.visible");
|
||||
|
|
@ -263,17 +257,17 @@ describe("Manage Users", () => {
|
|||
groupsText.groupCreatedToast
|
||||
);
|
||||
|
||||
common.navigateToManageUsers();
|
||||
users.inviteUserWithUserGroups(
|
||||
navigateToManageUsers();
|
||||
inviteUserWithUserGroups(
|
||||
data.firstName,
|
||||
data.email,
|
||||
"All users",
|
||||
data.groupName
|
||||
);
|
||||
common.logout();
|
||||
logout();
|
||||
|
||||
cy.defaultWorkspaceLogin();
|
||||
common.navigateToManageGroups();
|
||||
navigateToManageGroups();
|
||||
cy.get(groupsSelector.groupLink(data.groupName)).click();
|
||||
cy.get(groupsSelector.usersLink).click();
|
||||
cy.get(groupsSelector.userRow(data.email)).should("be.visible");
|
||||
|
|
@ -287,8 +281,8 @@ describe("Manage Users", () => {
|
|||
cy.logoutApi();
|
||||
|
||||
cy.defaultWorkspaceLogin();
|
||||
common.navigateToManageUsers();
|
||||
common.searchUser(data.email);
|
||||
navigateToManageUsers();
|
||||
searchUser(data.email);
|
||||
cy.get(usersSelector.userActionButton).click();
|
||||
cy.get(usersSelector.editUserDetailsButton).verifyVisibleElement(
|
||||
"have.text",
|
||||
|
|
@ -352,7 +346,42 @@ describe("Manage Users", () => {
|
|||
"User has been updated"
|
||||
);
|
||||
|
||||
common.searchUser(data.email);
|
||||
searchUser(data.email);
|
||||
cy.get(usersSelector.groupChip).eq(1).should("have.text", "Admin");
|
||||
});
|
||||
|
||||
it("Should verify exisiting user invite flow", () => {
|
||||
data.firstName = fake.firstName;
|
||||
data.email = fake.email.toLowerCase().replaceAll("[^A-Za-z]", "");
|
||||
const workspaceName = data.firstName.toLowerCase();
|
||||
|
||||
addNewUser(data.firstName, data.email);
|
||||
logout();
|
||||
|
||||
cy.defaultWorkspaceLogin();
|
||||
cy.apiCreateWorkspace(workspaceName, workspaceName);
|
||||
cy.visit(workspaceName);
|
||||
|
||||
navigateToManageUsers();
|
||||
fillUserInviteForm(data.firstName, data.email);
|
||||
cy.get(usersSelector.buttonInviteUsers).click();
|
||||
cy.wait(2000);
|
||||
visitWorkspaceInvitation(data.email, workspaceName);
|
||||
|
||||
cy.clearAndType(commonSelectors.workEmailInputField, data.email);
|
||||
cy.clearAndType(commonSelectors.passwordInputField, "password");
|
||||
cy.get(commonSelectors.signInButton).click();
|
||||
cy.get(usersSelector.acceptInvite).click();
|
||||
cy.verifyToastMessage(commonSelectors.toastMessage, usersText.inviteToast);
|
||||
logout();
|
||||
|
||||
cy.defaultWorkspaceLogin();
|
||||
navigateToManageUsers();
|
||||
searchUser(data.email);
|
||||
cy.contains("td", data.email)
|
||||
.parent()
|
||||
.within(() => {
|
||||
cy.get("td small").should("have.text", usersText.activeStatus);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -206,12 +206,11 @@ describe("User permissions", () => {
|
|||
it("Should verify Create/Update/Delete workspace variable permission", () => {
|
||||
common.navigateToWorkspaceVariable();
|
||||
cy.get('[data-cy="alert-info-text"]>>.text-muted').verifyVisibleElement(
|
||||
"have.text",
|
||||
"There are no Workspace variables. Workspace variables are being deprecated soon, so please use Workspace constants instead."
|
||||
"have.text", "Can't add or edit workspace variables as we are deprecating them soon. Please use Workspace constant instead."
|
||||
);
|
||||
cy.get(
|
||||
'[data-cy="go-to-workspace-constants-option-button"]'
|
||||
).verifyVisibleElement("have.text", "Go to workspace constants");
|
||||
).verifyVisibleElement("have.text", "Go to Workspace constants");
|
||||
cy.logoutApi();
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -317,57 +317,6 @@ export const signInPageElements = () => {
|
|||
});
|
||||
};
|
||||
|
||||
export const SignUpPageElements = () => {
|
||||
cy.get(commonSelectors.pageLogo).should("be.visible");
|
||||
cy.get(commonSelectors.SignUpSectionHeader).verifyVisibleElement(
|
||||
"have.text",
|
||||
commonText.SignUpSectionHeader
|
||||
);
|
||||
cy.get(commonSelectors.signUpButton).verifyVisibleElement(
|
||||
"have.text",
|
||||
commonText.getStartedButton
|
||||
);
|
||||
cy.get(commonSelectors.signInRedirectText).should(($el) => {
|
||||
expect($el.contents().first().text().trim()).to.eq(
|
||||
commonText.signInRedirectText
|
||||
);
|
||||
});
|
||||
cy.get(commonSelectors.signInRedirectLink).verifyVisibleElement(
|
||||
"have.text",
|
||||
commonText.signInRedirectLink
|
||||
);
|
||||
cy.get(commonSelectors.signUpTermsHelperText).should(($el) => {
|
||||
expect($el.contents().first().text().trim()).to.eq(
|
||||
commonText.signUpTermsHelperText
|
||||
);
|
||||
});
|
||||
cy.get(commonSelectors.termsOfServiceLink)
|
||||
.verifyVisibleElement("have.text", commonText.termsOfServiceLink)
|
||||
.and("have.attr", "href")
|
||||
.and("equal", "https://www.tooljet.com/terms");
|
||||
cy.get(commonSelectors.privacyPolicyLink)
|
||||
.verifyVisibleElement("have.text", commonText.privacyPolicyLink)
|
||||
.and("have.attr", "href")
|
||||
.and("equal", "https://www.tooljet.com/privacy");
|
||||
cy.get("body").then(($el) => {
|
||||
if ($el.text().includes("Google")) {
|
||||
cy.get(ssoSelector.googleSSOText).verifyVisibleElement(
|
||||
"have.text",
|
||||
ssoText.googleSignUpText
|
||||
);
|
||||
cy.get(ssoSelector.gitSSOText).verifyVisibleElement(
|
||||
"have.text",
|
||||
ssoText.gitSignUpText
|
||||
);
|
||||
cy.get(commonSelectors.onboardingSeperator).should("be.visible");
|
||||
cy.get(commonSelectors.onboardingSeperatorText).verifyVisibleElement(
|
||||
"have.text",
|
||||
commonText.onboardingSeperatorText
|
||||
);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export const loginbyGoogle = (email, password) => {
|
||||
cy.session([email, password], () => {
|
||||
cy.visit("/");
|
||||
|
|
@ -584,10 +533,77 @@ export const setSSOStatus = (workspaceName, ssoType, enabled) => {
|
|||
});
|
||||
};
|
||||
|
||||
export const defaultSSO = (workspaceName, enabled) => {
|
||||
cy.task("updateId", {
|
||||
dbconfig: Cypress.env("app_db"),
|
||||
sql: `UPDATE organizations SET inherit_sso = ${enabled ? "true" : "false"
|
||||
} WHERE name = '${workspaceName}'`,
|
||||
export const defaultSSO = (enable) => {
|
||||
cy.getCookie("tj_auth_token").then((cookie) => {
|
||||
cy.request(
|
||||
{
|
||||
method: "PATCH",
|
||||
url: "http://localhost:3000/api/organizations",
|
||||
headers: {
|
||||
"Tj-Workspace-Id": Cypress.env("workspaceId"),
|
||||
Cookie: `tj_auth_token=${cookie.value}`,
|
||||
},
|
||||
body: { inheritSSO: enable },
|
||||
},
|
||||
{ log: false }
|
||||
).then((response) => {
|
||||
expect(response.status).to.equal(200);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
export const setSignupStatus = (enable) => {
|
||||
cy.getCookie("tj_auth_token").then((cookie) => {
|
||||
cy.request(
|
||||
{
|
||||
method: "PATCH",
|
||||
url: "http://localhost:3000/api/organizations",
|
||||
headers: {
|
||||
"Tj-Workspace-Id": Cypress.env("workspaceId"),
|
||||
Cookie: `tj_auth_token=${cookie.value}`,
|
||||
},
|
||||
body: { enableSignUp: enable },
|
||||
},
|
||||
{ log: false }
|
||||
).then((response) => {
|
||||
expect(response.status).to.equal(200);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
export const deleteOrganisationSSO = (workspaceName, services) => {
|
||||
let workspaceId;
|
||||
cy.task("updateId", {
|
||||
dbconfig: Cypress.env("app_db"),
|
||||
sql: `select id from organizations where name='${workspaceName}';`,
|
||||
}).then((resp) => {
|
||||
workspaceId = resp.rows[0].id;
|
||||
|
||||
cy.task("updateId", {
|
||||
dbconfig: Cypress.env("app_db"),
|
||||
sql: `DELETE FROM sso_configs WHERE organization_id = '${workspaceId}' AND sso IN (${services
|
||||
.map((service) => `'${service}'`)
|
||||
.join(",")});`,
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
export const resetDomain = () => {
|
||||
cy.getCookie("tj_auth_token").then((cookie) => {
|
||||
cy.request(
|
||||
{
|
||||
method: "PATCH",
|
||||
url: "http://localhost:3000/api/organizations",
|
||||
headers: {
|
||||
"Tj-Workspace-Id": Cypress.env("workspaceId"),
|
||||
Cookie: `tj_auth_token=${cookie.value}`,
|
||||
},
|
||||
body: { domain: "" },
|
||||
},
|
||||
{ log: false }
|
||||
).then((response) => {
|
||||
expect(response.status).to.equal(200);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
|
@ -68,6 +68,7 @@ export const manageUsersElements = () => {
|
|||
"have.text",
|
||||
usersText.buttonUploadCsvFile
|
||||
);
|
||||
|
||||
cy.get(usersSelector.addUsersCardTitle).verifyVisibleElement(
|
||||
"have.text",
|
||||
usersText.addUsersCardTitle
|
||||
|
|
@ -121,6 +122,15 @@ export const manageUsersElements = () => {
|
|||
"have.text",
|
||||
usersText.buttonDownloadTemplate
|
||||
);
|
||||
|
||||
cy.exec("cd ./cypress/downloads/ && rm -rf *");
|
||||
cy.get(usersSelector.buttonDownloadTemplate).click();
|
||||
cy.wait(4000)
|
||||
cy.exec("ls ./cypress/downloads/").then((result) => {
|
||||
const downloadedAppExportFileName = result.stdout.split("\n")[0];
|
||||
expect(downloadedAppExportFileName).to.contain.string("sample_upload.csv");
|
||||
});
|
||||
|
||||
cy.get(usersSelector.iconBulkUpload).should("be.visible");
|
||||
cy.get(usersSelector.helperTextSelectFile).verifyVisibleElement(
|
||||
"have.text",
|
||||
|
|
@ -144,43 +154,17 @@ export const inviteUser = (firstName, email) => {
|
|||
cy.get(commonSelectors.acceptInviteButton).click();
|
||||
};
|
||||
|
||||
export const confirmInviteElements = () => {
|
||||
cy.get(commonSelectors.invitePageHeader).verifyVisibleElement(
|
||||
"have.text",
|
||||
commonText.invitePageHeader
|
||||
);
|
||||
cy.get(commonSelectors.invitePageSubHeader).verifyVisibleElement(
|
||||
"have.text",
|
||||
commonText.invitePageSubHeader
|
||||
);
|
||||
cy.get(commonSelectors.userNameInputLabel).verifyVisibleElement(
|
||||
"have.text",
|
||||
commonText.userNameInputLabel
|
||||
);
|
||||
cy.get(commonSelectors.invitedUserName).should("be.visible");
|
||||
cy.get(commonSelectors.emailInputLabel).verifyVisibleElement(
|
||||
"have.text",
|
||||
commonText.emailInputLabel
|
||||
);
|
||||
cy.get(commonSelectors.invitedUserEmail).should("be.visible");
|
||||
export const confirmInviteElements = (email) => {
|
||||
|
||||
cy.get("body").then(($el) => {
|
||||
if ($el.text().includes(commonText.passwordLabel)) {
|
||||
cy.get(commonSelectors.passwordLabel).verifyVisibleElement(
|
||||
"have.text",
|
||||
commonText.passwordLabel
|
||||
);
|
||||
cy.get(commonSelectors.passwordInputField).should("be.visible");
|
||||
cy.get(commonSelectors.acceptInviteButton)
|
||||
.verifyVisibleElement("have.text", commonText.acceptInviteButton)
|
||||
.should("be.disabled");
|
||||
}
|
||||
});
|
||||
cy.get(commonSelectors.SignUpSectionHeader).verifyVisibleElement(
|
||||
"have.text", "Sign up");
|
||||
cy.get('[data-cy="workspace-signup-header"]').verifyVisibleElement(
|
||||
"have.text", "Sign up to the workspace - My workspace");
|
||||
|
||||
cy.get(commonSelectors.acceptInviteButton).verifyVisibleElement(
|
||||
"have.text",
|
||||
commonText.acceptInviteButton
|
||||
);
|
||||
cy.verifyLabel("Email")
|
||||
cy.verifyLabel("Create a password")
|
||||
cy.get(commonSelectors.invitedUserEmail).verifyVisibleElement(
|
||||
"have.text", email);
|
||||
|
||||
cy.get(commonSelectors.signUpTermsHelperText).should(($el) => {
|
||||
expect($el.contents().first().text().trim()).to.eq(
|
||||
|
|
@ -310,6 +294,9 @@ export const inviteUserWithUserGroups = (
|
|||
cy.wait(1000);
|
||||
fetchAndVisitInviteLink(email);
|
||||
cy.clearAndType(commonSelectors.passwordInputField, "password");
|
||||
cy.intercept('GET', '/api/organizations').as('org')
|
||||
cy.get(commonSelectors.signUpButton).click();
|
||||
cy.wait('@org');
|
||||
cy.get(commonSelectors.acceptInviteButton).click();
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,9 @@ import {
|
|||
verifyandModifyUserRole,
|
||||
verifyandModifySizeOftheCompany,
|
||||
} from "Support/utils/selfHostSignUp";
|
||||
import { navigateToManageUsers } from "Support/utils/common";
|
||||
import { navigateToManageUsers, logout } from "Support/utils/common";
|
||||
import { ssoSelector } from "Selectors/manageSSO";
|
||||
import { ssoText } from "Texts/manageSSO";
|
||||
|
||||
export const verifyConfirmEmailPage = (email) => {
|
||||
cy.get(commonSelectors.pageLogo).should("be.visible");
|
||||
|
|
@ -208,9 +210,12 @@ export const fetchAndVisitInviteLink = (email) => {
|
|||
export const inviteUser = (firstName, email) => {
|
||||
cy.userInviteApi(firstName, email);
|
||||
fetchAndVisitInviteLink(email);
|
||||
cy.wait(1000)
|
||||
cy.get(commonSelectors.passwordInputField).should("be.visible")
|
||||
cy.wait(1000);
|
||||
cy.get(commonSelectors.passwordInputField).should("be.visible");
|
||||
cy.clearAndType(commonSelectors.passwordInputField, "password");
|
||||
cy.intercept("GET", "/api/organizations").as("org");
|
||||
cy.get(commonSelectors.signUpButton).click();
|
||||
cy.wait("@org");
|
||||
cy.get(commonSelectors.acceptInviteButton).click();
|
||||
};
|
||||
|
||||
|
|
@ -264,3 +269,95 @@ export const updateWorkspaceName = (email, workspaceName = email) => {
|
|||
});
|
||||
});
|
||||
};
|
||||
|
||||
export const visitWorkspaceInvitation = (email, workspaceName) => {
|
||||
let workspaceId, userId, url, organizationToken;
|
||||
|
||||
cy.task("updateId", {
|
||||
dbconfig: Cypress.env("app_db"),
|
||||
sql: `select id from organizations where name='${workspaceName}';`,
|
||||
}).then((resp) => {
|
||||
workspaceId = resp.rows[0].id;
|
||||
|
||||
cy.task("updateId", {
|
||||
dbconfig: Cypress.env("app_db"),
|
||||
sql: `select id from users where email='${email}';`,
|
||||
}).then((resp) => {
|
||||
userId = resp.rows[0].id;
|
||||
|
||||
cy.task("updateId", {
|
||||
dbconfig: Cypress.env("app_db"),
|
||||
sql: `select invitation_token from organization_users where organization_id= '${workspaceId}' AND user_id='${userId}';`,
|
||||
}).then((resp) => {
|
||||
if (resp.rows.length === 1) {
|
||||
organizationToken = resp.rows[0].invitation_token;
|
||||
url = `/organization-invitations/${organizationToken}?oid=${workspaceId}`;
|
||||
|
||||
cy.contains("td", email)
|
||||
.parent()
|
||||
.within(() => {
|
||||
cy.get("td small").should("have.text", "invited");
|
||||
});
|
||||
|
||||
logout();
|
||||
cy.visit(url);
|
||||
} else {
|
||||
// Handle case where user belongs to multiple organizations with the same workspaceId
|
||||
// For example, you might display an error message or log a warning
|
||||
console.warn(`User '${email}' belongs to multiple organizations with workspaceId '${workspaceId}'.`);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
export const SignUpPageElements = () => {
|
||||
cy.get(commonSelectors.pageLogo).should("be.visible");
|
||||
cy.get(commonSelectors.SignUpSectionHeader).verifyVisibleElement(
|
||||
"have.text",
|
||||
"Sign up"
|
||||
);
|
||||
cy.get(commonSelectors.signUpButton).verifyVisibleElement(
|
||||
"have.text",
|
||||
commonText.getStartedButton
|
||||
);
|
||||
cy.get(commonSelectors.signInRedirectText).should(($el) => {
|
||||
expect($el.contents().first().text().trim()).to.eq(
|
||||
commonText.signInRedirectText
|
||||
);
|
||||
});
|
||||
cy.get(commonSelectors.signInRedirectLink).verifyVisibleElement(
|
||||
"have.text",
|
||||
commonText.signInRedirectLink
|
||||
);
|
||||
cy.get(commonSelectors.signUpTermsHelperText).should(($el) => {
|
||||
expect($el.contents().first().text().trim()).to.eq(
|
||||
commonText.signUpTermsHelperText
|
||||
);
|
||||
});
|
||||
cy.get(commonSelectors.termsOfServiceLink)
|
||||
.verifyVisibleElement("have.text", commonText.termsOfServiceLink)
|
||||
.and("have.attr", "href")
|
||||
.and("equal", "https://www.tooljet.com/terms");
|
||||
cy.get(commonSelectors.privacyPolicyLink)
|
||||
.verifyVisibleElement("have.text", commonText.privacyPolicyLink)
|
||||
.and("have.attr", "href")
|
||||
.and("equal", "https://www.tooljet.com/privacy");
|
||||
cy.get("body").then(($el) => {
|
||||
if ($el.text().includes("Google")) {
|
||||
cy.get(ssoSelector.googleSSOText).verifyVisibleElement(
|
||||
"have.text",
|
||||
ssoText.googleSignUpText
|
||||
);
|
||||
cy.get(ssoSelector.gitSSOText).verifyVisibleElement(
|
||||
"have.text",
|
||||
ssoText.gitSignUpText
|
||||
);
|
||||
cy.get(commonSelectors.onboardingSeperator).should("be.visible");
|
||||
cy.get(commonSelectors.onboardingSeperatorText).verifyVisibleElement(
|
||||
"have.text",
|
||||
commonText.onboardingSeperatorText
|
||||
);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
|
|
|||
1
docs/.nvmrc
Normal file
1
docs/.nvmrc
Normal file
|
|
@ -0,0 +1 @@
|
|||
v18.18.2
|
||||
|
|
@ -10,10 +10,12 @@ The audit log is the report of all the activities done in your ToolJet account.
|
|||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/enterprise/audit_logs/logsnew.png" alt="Audit logs" />
|
||||
<img style={{ width:'100%', border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/enterprise/audit_logs/logsnew-v2.png" alt="Audit logs" />
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
### 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.
|
||||
|
|
@ -24,10 +26,14 @@ Pagination at the bottom allows navigation through the pages, with each page dis
|
|||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/enterprise/audit_logs/filtersnew.png" alt="Audit logs" />
|
||||
<img style={{ width:'100%', border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/enterprise/audit_logs/filtersnew-v2.png" alt="Audit logs" />
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
### Filter Audit Logs
|
||||
|
||||
You can apply filters to the audited events based on the following criteria.
|
||||
|
|
@ -42,7 +48,7 @@ The dropdown will display all the apps associated with your account. Select an a
|
|||
|
||||
#### Select Resources
|
||||
|
||||
| Resources | description |
|
||||
| <div style={{ width:"100px"}}> Resources </div> | <div style={{ width:"100px"}}> Description </div> |
|
||||
| ----------- | ----------- |
|
||||
| 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`. |
|
||||
|
|
@ -52,7 +58,7 @@ The dropdown will display all the apps associated with your account. Select an a
|
|||
|
||||
#### Select Actions
|
||||
|
||||
| Actions | description |
|
||||
| <div style={{ width:"100px"}}> Actions </div> | <div style={{ width:"100px"}}> Description </div>|
|
||||
| ----------- | ----------- |
|
||||
| USER_LOGIN | This event is recorded everytime a user logins. |
|
||||
| USER_SIGNUP | This event is recorded everytime a new signup is made. |
|
||||
|
|
@ -71,6 +77,10 @@ The dropdown will display all the apps associated with your account. Select an a
|
|||
| 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`. |
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
### Understanding Log Information
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
|
@ -79,7 +89,7 @@ The dropdown will display all the apps associated with your account. Select an a
|
|||
|
||||
</div>
|
||||
|
||||
| Property | Description |
|
||||
| <div style={{ width:"100px"}}> Property </div> | <div style={{ width:"100px"}}> Description </div>|
|
||||
| ----------- | ----------- |
|
||||
| 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. |
|
||||
|
|
@ -92,7 +102,11 @@ The dropdown will display all the apps associated with your account. Select an a
|
|||
| 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. |
|
||||
|
||||
### Log file
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
### Log File
|
||||
|
||||
The file will contain all the data from audit logs. The log file can be created by specifying the path in the [environment variables](/docs/setup/env-vars). The log file is rotated on a daily basis and is updated dynamically every time a new audit log is generated.
|
||||
|
||||
|
|
@ -110,7 +124,7 @@ homepath/hsbc/dashboard/log/tooljet_log/{process_id}-{date}/audit.log
|
|||
```
|
||||
Here, `{process_id}` is a placeholder for the unique process identifier, and `{date}` represents the current date. This structured path ensures that audit logs are organized by both process and date, facilitating easy traceability and analysis.
|
||||
|
||||
| Variable | Description |
|
||||
| <div style={{ width:"100px"}}> Variable </div>| <div style={{ width:"100px"}}> Description </div> |
|
||||
| -------- | --------------------------------------------------------------------------- |
|
||||
| LOG_FILE_PATH | the path where the log file will be created ( eg: tooljet/log/tooljet-audit.log) |
|
||||
|
||||
|
|
@ -141,3 +155,5 @@ Here, `{process_id}` is a placeholder for the unique process identifier, and `{d
|
|||
|
||||
</details>
|
||||
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -9,9 +9,11 @@ A Super Admin is the user who has full access to all the Workspaces, Users, and
|
|||
|
||||
The user details entered while setting up ToolJet will have Super Admin privileges.
|
||||
|
||||
## How Super Admin is different from Admin
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
| Privilege | Admin | Super Admin |
|
||||
## How Super Admin is Different from Admin
|
||||
|
||||
| <div style={{ width:"100px"}}>Privilege </div>| Admin | Super Admin |
|
||||
| --------- | ----- | ----------- |
|
||||
| Manage Users in their workspace (Invite/Archive/Unarchive) | ✅ | ✅ |
|
||||
| Manage Groups in their workspace (Create Group/Add or Delete Users from groups/ Modify Group Permissions) | ✅ | ✅ |
|
||||
|
|
@ -30,9 +32,14 @@ The user details entered while setting up ToolJet will have Super Admin privileg
|
|||
| [Make any user Super Admin](#make-the-user-super-admin) | ❌ | ✅ |
|
||||
| [Manage all workspaces in the instance(Archive/Unarchive)](#all-workspaces) | ❌ | ✅ |
|
||||
| [Restrict creation of personal workspace of users](#restrict-creation-of-personal-workspace-of-users) | ❌ | ✅ |
|
||||
| [Configure instance level login](#instance-login) | ❌ | ✅ |
|
||||
| [Enable Multiplayer editing](#enable-multiplayer-editing) | ❌ | ✅ |
|
||||
| [Implement White Labelling](#white-labelling) | ❌ | ✅ |
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## Super Admin features
|
||||
|
||||
### Access any workspace
|
||||
|
|
@ -75,6 +82,10 @@ Super Admins have all the privileges that an Admin of a workspace have, Super Ad
|
|||
- **✅ Copilot**: Enabling or disabling Copilot
|
||||
- **✅ Custom Styles**: Adding or modifying custom styles
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## Settings
|
||||
|
||||
Only Super Admins can access the Settings. To access the Settings page, click on the **⚙️** button and select **Settings** from the dropdown.
|
||||
|
|
@ -86,12 +97,16 @@ Only Super Admins can access the Settings. To access the Settings page, click on
|
|||
- **[White labelling](#white-labelling)**
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/enterprise/superadmin/settings.png" alt="Superadmin: settings" />
|
||||
<img style={{ border:'0', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/enterprise/superadmin/settings.png" alt="Superadmin: settings" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## All Users
|
||||
|
||||
### Manage all users in the instance
|
||||
### Manage all Users in the Instance
|
||||
|
||||
**All Users** settings can be used to check the list of all the users available on all the workspaces in the instance. Super Admins can also promote/demote any user to/from Super Admin from this page. They can also archive/unarchive any user at an instance level from this setting.
|
||||
|
||||
|
|
@ -99,14 +114,14 @@ Only Super Admins can access the Settings. To access the Settings page, click on
|
|||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/enterprise/superadmin/allusers1.png" alt="Superadmin: settings" />
|
||||
</div>
|
||||
|
||||
### Archiving a user from all the workspaces (Instance level)
|
||||
### Archiving a User from all the Workspaces (Instance Level)
|
||||
|
||||
Super Admins have the authority to deactivate any user at instance level. This will remove the user from all the workspaces in the instance.
|
||||
|
||||
To archive a user, go to the **All Users** settings, click on the kebab menu next to the user that is to be archived and select **Archive** option. Once the user is archived, the status will change from **Active** to **Archived**. The user will not be able to login to any workspace in the instance.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/enterprise/superadmin/archiveinstance.png" alt="Superadmin: settings" />
|
||||
<img style={{ border:'0', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/enterprise/superadmin/archiveinstance.png" alt="Superadmin: settings" />
|
||||
</div>
|
||||
|
||||
<br/>
|
||||
|
|
@ -119,11 +134,11 @@ To archive a user, go to the **All Users** settings, click on the kebab menu nex
|
|||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/enterprise/superadmin/unarchiveinstance.png" alt="Superadmin: settings" />
|
||||
</div>
|
||||
|
||||
### Reset password of any user
|
||||
### Reset Password of any User
|
||||
|
||||
Super Admins can reset the password of any user from the **All Users** settings. To reset the password, click on the kebab menu next to the user and select **Reset Password** option. A pop-up will appear asking either to auto-generate a password or to enter a new password.
|
||||
|
||||
### Edit user details
|
||||
### Edit User Details
|
||||
|
||||
Super Admins can edit the details of any user from the **All Users** settings. To edit the details, click on the kebab menu next to the user and select **Edit user details** option.
|
||||
|
||||
|
|
@ -139,24 +154,40 @@ From the **Edit user details** drawer, Super Admins can make any user as Super A
|
|||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/enterprise/superadmin/edituserdetailsinstance.png" alt="Superadmin: settings" />
|
||||
</div>
|
||||
|
||||
## All workspaces
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## All Workspaces
|
||||
|
||||
The All Workspaces tab provides a comprehensive view of all workspaces within the ToolJet instance. Super Admins can use this functionality to monitor and manage workspaces collectively, ensuring efficient administration and organization-wide oversight.
|
||||
|
||||
Super Admins have the authority to **archive** or **unarchive** workspaces of any user in the instance as needed. Archiving a workspace essentially sets it to an inactive state, removing it from active use. Conversely, unarchiving reactivates a previously archived workspace, making it accessible once again.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/enterprise/superadmin/workspaces1.png" alt="Superadmin: settings" />
|
||||
<img style={{ border:'0', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/enterprise/superadmin/workspaces1.png" alt="Superadmin: settings" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
### Current Workspace
|
||||
|
||||
The **Current Workspace** label will be displayed next to the workspace that the Super Admin has currently opened. If the Super Admin archives the current workspace, they will be prompted to switch to another active workspace to ensure continuous accessibility.
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
### Open Active Workspaces
|
||||
|
||||
In the list of active workspaces, there is an option to open the workspace directly. This feature helps superadmins to quickly navigate to the workspace on the new tab of the browser and manage the workspace.
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
### Archive Workspaces
|
||||
|
||||
The **Archive** button on the right of the workspace name allows Super Admins to archive the workspace. Once archived, the workspace will be moved to the **Archived Workspaces** section.
|
||||
|
|
@ -165,41 +196,125 @@ The **Archive** button on the right of the workspace name allows Super Admins to
|
|||
- The apps on the archived workspace won't be accessable through the URL
|
||||
- Users will be logged out if they don't have access to any active workspace
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
### Archived Workspaces
|
||||
|
||||
The **Archived** section displays a list of all archived workspaces. Super Admins can unarchive any workspace from this section by clicking the **Unarchive** button.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/enterprise/superadmin/workspaces2.png" alt="Superadmin: settings" />
|
||||
<img style={{ border:'0', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/enterprise/superadmin/workspaces2.png" alt="Superadmin: settings" />
|
||||
</div>
|
||||
|
||||
## Manage instance settings
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## Manage Instance Settings
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/enterprise/superadmin/instanceoptions.png" alt="Superadmin: settings" />
|
||||
<img style={{ border:'0', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/enterprise/superadmin/instanceoptions.png" alt="Superadmin: settings" />
|
||||
</div>
|
||||
|
||||
### Restrict creation of personal workspace of users
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
### Restrict Creation of Personal Workspace of Users
|
||||
|
||||
When a user joins a workspace, they are provided with their own personal workspace and option to create new workspaces.
|
||||
|
||||
Super Admins can **control** this behavior from the Manage Settings page, they can **toggle off** the option to **Allow personal workspace**. Now whenever a user joins a workspace they won't be provided a personal workspace nor they will be able to create a new workspace in the instance.
|
||||
|
||||
### Enable multiplayer editing
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
### Enable Multiplayer Editing
|
||||
|
||||
Super Admins can enable multiplayer editing from the Manage Settings page. Once enabled, users will be able to edit the same app simultaneously resulting in real-time collaboration.
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
### Comments
|
||||
|
||||
Super Admins can enable comments from the Manage Settings page. Once enabled, users will be able to collaborate by adding comments anywhere on the canvas.
|
||||
|
||||
## White labelling
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## White Labelling
|
||||
This feature allows you to customize the ToolJet instance with your own branding. You can change the logo, favicon, and the name of the instance.
|
||||
|
||||
Check out the [White labelling](/docs/enterprise/white-label/) page for more details.
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## Instance Login
|
||||
|
||||
Instance login configuration at the Settings level allows super admins to set up and manage the default login method for all workspaces within the instance. This ensures a standardized login experience unless individual workspace admins choose to configure a different method for their specific workspace.
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
### Access and Permissions
|
||||
|
||||
Only super admins have the authority to configure **Instance login** settings. This ensures centralized control over the default login method across the entire instance.
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
### Super Admin URL
|
||||
|
||||
This URL serves as a fail-safe in scenarios where password login is disabled, SSO is not configured, or a paid plan expires. Importantly, this URL exclusively supports password login and is accessible only by the super admin, preventing any unauthorized access.
|
||||
|
||||
The default URL for super admin login is `https://<domain>/login/super-admin`. This URL can be accessed by the super admin to log in to the instance and manage the settings.
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
### Enable sign-up
|
||||
|
||||
The "Enable Sign Up" option allows users to sign up without being invited. It is important to note that this feature includes both password login and SSO, providing a seamless onboarding experience for users.
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
### Password login
|
||||
|
||||
Super admins can enable or disable password login for the entire instance. This setting ensures that all workspaces within the instance adhere to the same login method, unless individual workspace admins choose to configure a different method for their specific workspace.
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
### Enable Workspace Configuration
|
||||
|
||||
Turning off this option restricts workspace admins from configuring the login method for their workspace. This configuration hides the Workspace Login option from the workspace settings tab.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img style={{ border:'0', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/enterprise/superadmin/instancelogin.png" alt="Superadmin: settings" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## License
|
||||
|
||||
Manage the instance license via the **Settings** page. Super Admins have the capability to update the instance's license key from this page.
|
||||
|
||||
Check out the [License](/docs/licensing) page for more details.
|
||||
Check out the [License](/docs/licensing) page for more details.
|
||||
|
||||
</div>
|
||||
|
|
@ -12,45 +12,47 @@ With this feature, you gain the ability to rebrand the following key elements:
|
|||
- **Application Logo**: This includes the logo displayed on the login screen, dashboard, and app-editor.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img style={{ marginBottom:'15px'}} className="screenshot-full" src="/img/enterprise/white-label/newdash.png" alt="ToolJet - Enterprise - White label" />
|
||||
<img style={{ border:'0', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/enterprise/white-label/whitelabeln1.png" alt="ToolJet - Enterprise - White label" />
|
||||
</div>
|
||||
|
||||
- **Favicon**: The small icon associated with your application.
|
||||
- **Favicon**: The small icon associated with your application. It is displayed in the browser tab.
|
||||
|
||||
- **Page Title**: This is the text displayed in the browser tab.
|
||||
|
||||
Example, we have set a favicon image and page title as `Bon Ton` in the below image.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img style={{ marginBottom:'15px'}} className="screenshot-full" src="/img/enterprise/white-label/newfav.png" alt="ToolJet - Enterprise - White label" />
|
||||
<img style={{ border:'0', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/enterprise/white-label/title-and-favicon.png" alt="ToolJet - Enterprise - White label" />
|
||||
</div>
|
||||
|
||||
- **Page Title**: This is the text displayed next to the Favicon.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img style={{ marginBottom:'15px'}} className="screenshot-full" src="/img/enterprise/white-label/title.png" alt="ToolJet - Enterprise - White label" />
|
||||
</div>
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## Configuration
|
||||
|
||||
To enable white labelling, you'll need to go to the **Settings** from the Dashboard and click on the `White labelling` tab. On the White labelling page, you'll be able to configure the following:
|
||||
To enable white labelling, click on the gear icon on the bottom left of the dashboard and select `Settings`. From the settings page, click on the `White labelling` tab. On the White labelling page, you'll be able to configure the following:
|
||||
|
||||
- **Application Logo**: Add the URL of the image you want to use as your application logo. Preferred dimensions of the logo are: width `130px` and height `26px`.
|
||||
- **Favicon**: Enter the URL of the image you want to use as your application's favicon. Preferred dimensions of the favicon are: width `32px` and height `32px` or `16px` and height `16px`.
|
||||
- **Page Title**: Enter the text you want to display as your application's title. Preferred title length are 50-60 characters.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img style={{ marginBottom:'15px'}} className="screenshot-full" src="/img/enterprise/white-label/whitelabelsettings.png" alt="ToolJet - Enterprise - White label" />
|
||||
<img style={{ border:'0', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/enterprise/white-label/settings.png" alt="ToolJet - Enterprise - White label" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## ToolJet Cloud
|
||||
|
||||
If you are using ToolJet Cloud, you can enable white labelling by going to the **Settings** from the Dashboard and clicking on the `White labelling` tab. On the White labelling page, you'll be able to configure the following:
|
||||
If you are using ToolJet Cloud, click on the gear icon on the bottom left of the dashboard and select `Settings`. From the settings page, click on the `White labelling` tab. On the White labelling page, you'll be able to configure the following:
|
||||
|
||||
- **Application Logo**: Add the URL of the image you want to use as your application logo. Preferred dimensions of the logo are: width `130px` and height `26px`.
|
||||
- **Page Title**: Enter the text you want to display as your application's title. Preferred title length are 50-60 characters.
|
||||
- **Favicon**: Enter the URL of the image you want to use as your application's favicon. Preferred dimensions of the favicon are: width `32px` and height `32px` or `16px` and height `16px`.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img style={{ marginBottom:'15px'}} className="screenshot-full" src="/img/enterprise/white-label/whitecloud.png" alt="Whitelabel Cloud" />
|
||||
<img style={{ border:'0', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/enterprise/white-label/cloud1.png" alt="ToolJet - Enterprise - White label" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ id: unset-variable
|
|||
title: Unset variable
|
||||
---
|
||||
|
||||
This action allows you to remove the variable variable that was created using the set variable action.
|
||||
This action allows you to remove the variable that was created using the set variable action.
|
||||
|
||||
## Options
|
||||
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ Custom Styles helps in maintaining consistent themes across the ToolJet apps, al
|
|||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/v2-beta/app-builder/customcss/customcss.gif" alt="Custom CSS" />
|
||||
<img className="screenshot-full" src="/img/v2-beta/app-builder/customcss/customcss-v2.gif" alt="Custom CSS" />
|
||||
|
||||
</div>
|
||||
|
||||
|
|
@ -22,7 +22,7 @@ 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" />
|
||||
<img className="screenshot-full" src="/img/v2-beta/app-builder/customcss/settings-v2.png" alt="Custom CSS" />
|
||||
|
||||
</div>
|
||||
|
||||
|
|
@ -51,6 +51,6 @@ To add Custom Styles to ToolJet apps, users should follow these steps:
|
|||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/v2-beta/app-builder/customcss/styledapp.gif" alt="Custom CSS" />
|
||||
<img className="screenshot-full" src="/img/v2-beta/app-builder/customcss/styledapp-v2.gif" alt="Custom CSS" />
|
||||
|
||||
</div>
|
||||
|
|
@ -14,14 +14,14 @@ This documentation explains the process of exporting and importing applications
|
|||
- Click on the **Export app** button.
|
||||
|
||||
<div style={{textAlign: 'center', marginBottom:'15px'}}>
|
||||
<img className="screenshot-full" src="/img/v2-beta/app-builder/import-export-apps/export-app-button.png" alt="Export App Button" />
|
||||
<img className="screenshot-full" src="/img/v2-beta/app-builder/import-export-apps/export-app-button-v2.png" alt="Export App Button" />
|
||||
</div>
|
||||
|
||||
- If you select `Export All`, all the versions of the application will be exported in JSON format. If you select `Export selected version`, only the selected version will be exported in JSON format.
|
||||
- Ticking the `Export ToolJet table schema` checkbox will also export the related ToolJet Database table schemas with your application. In this case, when you import the application in a workspace, the related ToolJet Database tables will also be created.
|
||||
|
||||
<div style={{textAlign: 'center', marginBottom:'15px'}}>
|
||||
<img className="screenshot-full" src="/img/v2-beta/app-builder/import-export-apps/export-options.png" alt="Export App Options" />
|
||||
<img className="screenshot-full" src="/img/v2-beta/app-builder/import-export-apps/export-options-v2.png" alt="Export App Options" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
|
@ -34,7 +34,7 @@ This documentation explains the process of exporting and importing applications
|
|||
- Click on the ellipses on the **Create new app** button and select `Import`.
|
||||
|
||||
<div style={{textAlign: 'center', marginBottom:'15px'}}>
|
||||
<img className="screenshot-full" src="/img/v2-beta/app-builder/import-export-apps/import-button.png" alt="Import App Button" />
|
||||
<img className="screenshot-full" src="/img/v2-beta/app-builder/import-export-apps/import-button-v2.png" alt="Import App Button" />
|
||||
</div>
|
||||
|
||||
- After clicking on `Import`, choose the relevant JSON file that you previously downloaded during the application export process.
|
||||
|
|
|
|||
|
|
@ -3,127 +3,117 @@ id: topbar
|
|||
title: Topbar
|
||||
---
|
||||
|
||||
Topbar is present at the top of the app-builder, and is used to configure the app settings.
|
||||
The Topbar of the app-builder interface serves as a central hub for configuring app settings.
|
||||
|
||||
### App name
|
||||
### Application 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.
|
||||
To modify the app name, click on the application name on the left side of the topbar.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/v2-beta/app-builder/toolbar/appnamenew.png" alt="App Builder: Topbar"/>
|
||||
|
||||
<img className="screenshot-full" src="/img/v2-beta/app-builder/toolbar/appnamenew-v2.png" alt="App Builder: App Name"/>
|
||||
</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.
|
||||
:::
|
||||
Toggle between Mobile and Desktop views directly from the topbar to switch the canvas mode.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/v2-beta/app-builder/toolbar/canvasmodes.gif" alt="App Builder: Topbar"/>
|
||||
|
||||
<img className="screenshot-full" src="/img/v2-beta/app-builder/toolbar/mobiledesktopswitch.png" alt="App Builder: Mobile and Desktop Mode"/>
|
||||
</div>
|
||||
|
||||
### Changes saved indicator
|
||||
#### Showing Components on Mobile or Desktop layout
|
||||
|
||||
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.
|
||||
Select a component and navigate to its Properties Panel on the right. Scroll down to the **Devices** section and toggle on the `Show on mobile` option. This will ensure that the component is visible in Mobile view.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img className="screenshot-full" src="/img/v2-beta/app-builder/toolbar/showonmobile.png" alt="App Builder: Show On Mobile Icon"/>
|
||||
</div>
|
||||
|
||||
<img className="screenshot-full" src="/img/v2-beta/app-builder/toolbar/changessaved.png" alt="App Builder: Topbar"/>
|
||||
Similarly, you can toggle on the `Show on desktop` option to make the component visible in the Desktop view.
|
||||
|
||||
### Changes Saved Indicator
|
||||
|
||||
Whenever changes are made in the application, they are saved automatically. The topbar's `Changes Saved` indicator shows the save status.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img className="screenshot-full" src="/img/v2-beta/app-builder/toolbar/changessaved-v2.png" alt="App Builder: Changes Saved Indicator"/>
|
||||
</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.
|
||||
The Developer Details icon will show a profile picture of the currently active developer. Hovering over this picture reveals the developer's name. If no picture is set, initials are displayed.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img className="screenshot-full" src="/img/v2-beta/app-builder/toolbar/profile-v2.png" alt="App Builder: Developer Details"/>
|
||||
</div>
|
||||
|
||||
<img className="screenshot-full" src="/img/v2-beta/app-builder/toolbar/profile.png" alt="App Builder: Topbar"/>
|
||||
### App Environment
|
||||
|
||||
You can use the Env dropdown menu to select an environment for your app: Development, Staging, or Production. This feature facilitates seamless transition through the app development cycle.
|
||||
|
||||
:::tip
|
||||
Learn more about multi-environment configuration **[here](/docs/release-management/multi-environment/)**.
|
||||
:::
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img className="screenshot-full" src="/img/v2-beta/app-builder/toolbar/multienv.png" alt="App Builder: App Env"/>
|
||||
</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.
|
||||
You can manage application versions through the Version Manager. You can use this dropdown to edit a version name or adding/removing versions.
|
||||
|
||||
:::tip
|
||||
Versioning is also helpful when working with **[multiple environments](/docs/release-management/multi-environment/)** like development, staging and production.
|
||||
:::
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/v2-beta/app-builder/toolbar/versionsnew.png" alt="App Builder: Topbar"/>
|
||||
|
||||
<img className="screenshot-full" src="/img/v2-beta/app-builder/toolbar/versionsnew-v2.png" alt="App Builder: Version Manager"/>
|
||||
</div>
|
||||
|
||||
|
||||
### Gitsync
|
||||
The `Gitsync` icon next to the versions dropdown allows you to sync your application with your GitHub repository.
|
||||
|
||||
Read more about Gitsync **[here](/docs/gitsync)**.
|
||||
### Undo or Redo
|
||||
|
||||
Undo or Redo any action performed on the canvas.
|
||||
You can Undo or Redo any action performed on the canvas using the Undo and Redo buttons.
|
||||
|
||||
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"/>
|
||||
|
||||
<img className="screenshot-full" src="/img/v2-beta/app-builder/toolbar/undo-v3.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 application public** toggle is off and **Shareable app link** is shared then the users will have to login to ToolJet to use the application. Toggle on to make the application public and accessible to anyone on the internet without requiring a ToolJet login. Only released apps can be accessed using the **Shareable app link**.
|
||||
- ToolJet generates the **Embedded link** which can be used to embed application on the webpages.
|
||||
The Share button allows you to share your applications with a unique URL generated automatically or edit the URL slug to personalize it. The share button will only be active when your application is released.
|
||||
|
||||
:::tip
|
||||
Learn more about **[Sharing](/docs/app-builder/share)** your tooljet applications.
|
||||
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"/>
|
||||
|
||||
<img className="screenshot-full" src="/img/v2-beta/app-builder/toolbar/sharenew-v2.png" alt="App Builder: Share"/>
|
||||
</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.
|
||||
The Preview button allows you to view the current app version in a new tab, facilitating immediate feedback on changes.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/v2-beta/app-builder/toolbar/previewnew.png" alt="App Builder: Topbar"/>
|
||||
|
||||
<img className="screenshot-full" src="/img/v2-beta/app-builder/toolbar/previewnew-v2.png" alt="App Builder: Preview"/>
|
||||
</div>
|
||||
|
||||
### Release
|
||||
|
||||
Release the app to publish the current version of the app and push the changes into the production.
|
||||
Use the Release button on the right to publish the current app version. The Release button, used to publish the current app version, becomes visible only in the Production environment, ensuring that only finalized versions are made public.
|
||||
|
||||
:::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"/>
|
||||
|
||||
<img className="screenshot-full" src="/img/v2-beta/app-builder/toolbar/releasenew-v2.png" alt="App Builder: Topbar"/>
|
||||
</div>
|
||||
|
|
@ -279,7 +279,7 @@ The **manifest.json** file is utilized by the connection modal component, which
|
|||
```
|
||||
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
|
||||
## Step 4: Add the npm package of GitHub to the plugin dependencies
|
||||
|
||||
- Change directory to the plugin directory where the npm package needs to be installed and then install the package
|
||||
```bash
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ If you rather want to try out ToolJet locally with docker, you can follow the st
|
|||
|
||||
## Prerequisites
|
||||
|
||||
Make sure you have the latest version of `docker` and `docker-compose` installed.
|
||||
Make sure you have the latest version of `docker` and `docker compose` installed.
|
||||
|
||||
[Official docker installation guide](https://docs.docker.com/desktop/)
|
||||
|
||||
|
|
@ -27,8 +27,8 @@ We recommend:
|
|||
docker --version
|
||||
Docker version 19.03.12, build 48a66213fe
|
||||
|
||||
docker-compose --version
|
||||
docker-compose version 1.26.2, build eefe0d31
|
||||
docker compose --version
|
||||
docker compose version 1.26.2, build eefe0d31
|
||||
```
|
||||
|
||||
## Setting up
|
||||
|
|
@ -94,20 +94,20 @@ Please find more information [here](https://docs.docker.com/desktop/windows/wsl/
|
|||
4. Build docker images
|
||||
|
||||
```bash
|
||||
docker-compose build
|
||||
docker-compose run --rm plugins npm run build:plugins
|
||||
docker compose build
|
||||
docker compose run --rm plugins npm run build:plugins
|
||||
```
|
||||
|
||||
5. Run ToolJet
|
||||
|
||||
```bash
|
||||
docker-compose up
|
||||
docker compose up
|
||||
```
|
||||
ToolJet should now be served locally at `http://localhost:8082`.
|
||||
|
||||
8. To shut down the containers,
|
||||
```bash
|
||||
docker-compose stop
|
||||
docker compose stop
|
||||
```
|
||||
|
||||
## Making changes to the codebase
|
||||
|
|
@ -116,9 +116,9 @@ If you make any changes to the codebase/pull the latest changes from upstream, t
|
|||
|
||||
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`.
|
||||
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`.
|
||||
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:
|
||||
|
|
@ -150,7 +150,7 @@ 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`.
|
||||
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
|
||||
|
||||
|
|
@ -159,24 +159,24 @@ 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
|
||||
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
|
||||
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
|
||||
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>
|
||||
docker compose run --rm server npm --prefix server run test <path-to-file>
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
|
|
|||
|
|
@ -15,8 +15,9 @@ Follow these steps to setup and run ToolJet on macOS for development purposes. O
|
|||
|
||||
1.1 Install Homebrew
|
||||
```bash
|
||||
/bin/bash -c "(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"
|
||||
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"
|
||||
```
|
||||
|
||||
1.2 Install Node.js ( version: v18.18.2 ) and npm (version: v9.8.1)
|
||||
```bash
|
||||
brew install nvm
|
||||
|
|
|
|||
|
|
@ -42,5 +42,5 @@ For VSCode users, you can set the formatter to `ESLint` in the [**settings.json*
|
|||
2. **npm version 9.8.1**
|
||||
|
||||
:::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: {...}**.
|
||||
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: `{...}`**.
|
||||
:::
|
||||
|
|
@ -11,6 +11,8 @@ ToolJet Copilot is currently in private beta for **Business** and **Enterprise**
|
|||
|
||||
**ToolJet Copilot** helps you write your queries faster. It uses OpenAI to suggest queries based on your data.
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## Activating Copilot
|
||||
|
||||
To gain access to Copilot, all users, including administrators, can individually sign up for the waitlist program. Upon successful sign up, each user will be issued a distinctive API key linked to their account. However, the exclusive authority to activate Copilot within the workspace settings lies solely with administrators. Administrators can proceed to the Copilot section in the workspace settings, where they can utilize their respective API key to set the "Enable Copilot" toggle option.
|
||||
|
|
@ -23,20 +25,32 @@ You can join the waitlist here: **https://tooljet.com/copilot**
|
|||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/copilot/enable.png" alt="ToolJet Copilot" />
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/copilot/enable.png" alt="ToolJet Copilot" />
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## Using Copilot
|
||||
|
||||
Once activated, the Copilot feature can be accessed while editing any query within the transformations section in the query editor.
|
||||
|
||||
Copilot's functionality relies on the provision of clear and concise plain English prompts. It possesses the capability to interact with and retrieve information from various components, enabling it to generate code specific to the desired actions associated with those components. This capability is facilitated by Copilot's comprehensive understanding of the application's present state.
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
### Token Limit per Workspace
|
||||
|
||||
A token is a unit of text that language models like ChatGPT process, such as a word or a character. To ensure fair usage and resource allocation among workspaces, a token limit is implemented. Currently, the token limit is set to **400**. If the token limit is surpassed, the request is declined with the message **"Unable to process request. Max tokens exceeded."**
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
### Rate-Limiting
|
||||
|
||||
To prevent abuse or excessive usage of the Copilot API, rate-limiting measures are in place. The following rules apply:
|
||||
|
|
@ -49,6 +63,10 @@ To prevent abuse or excessive usage of the Copilot API, rate-limiting measures a
|
|||
When generating an API key, if a workspace has 5 editors, the daily request limit will be 500 (100 requests per editor). Even if the workspace later expands to 10 editors after a week, the maximum number of requests allowed per day will still be 500.
|
||||
:::
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
### Example: Generating a SQL statement
|
||||
|
||||
This example demonstrates the usage of copilot by generating a SQL query to fetch the order details from a PostgreSQL database based on the key provided in the REST API data.
|
||||
|
|
@ -56,42 +74,44 @@ This example demonstrates the usage of copilot by generating a SQL query to fetc
|
|||
- Create a RESTAPI query using this mock api endpoint: https://fakestoreapi.com/users/1
|
||||
- Enable transformation on the query editor
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/copilot/query.png" alt="ToolJet Copilot" />
|
||||
<img className="screenshot-full" src="/img/copilot/query.png" alt="ToolJet Copilot" />
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
- To generate a SQL query using Copilot, first enter the desired prompt within comments in the transformations code editor. Once the prompt has been entered, simply click the **Generate Code** button, and Copilot will generate the corresponding SQL query.
|
||||
|
||||
- Assuming that a PostgreSQL data source is already connected and there are two tables in it, namely `customer` and `orders`, enter the provided prompt in the code editor:
|
||||
|
||||
```bash
|
||||
/*
|
||||
Assume the data is an object which has email key.
|
||||
assume we have a database with two tables: "customer" and "orders." The "customer" table has columns such as "customer_id," "customer_name," and "country." The "orders" table has columns such as "order_id," "customer_id," "order_date," and "total_amount."
|
||||
return a SQL query to retrieve the total order amounts for customers from the email key retrieved from the data, who have placed more than three orders.*/
|
||||
```
|
||||
```bash
|
||||
/*
|
||||
Assume the data is an object which has email key.
|
||||
assume we have a database with two tables: "customer" and "orders." The "customer" table has columns such as "customer_id," "customer_name," and "country." The "orders" table has columns such as "order_id," "customer_id," "order_date," and "total_amount."
|
||||
return a SQL query to retrieve the total order amounts for customers from the email key retrieved from the data, who have placed more than three orders.*/
|
||||
```
|
||||
|
||||
- Click on the "Generate Code" button to generate the SQL query.
|
||||
|
||||
- Once the code is generated, add a return statement below the code to return the generated SQL query. The variable name for the query might be different in your generated code.
|
||||
|
||||
```bash
|
||||
return query //the variable might be different in your generated code
|
||||
```
|
||||
```bash
|
||||
return query //the variable might be different in your generated code
|
||||
```
|
||||
|
||||
- Preview the returned SQL statement in the preview block to check if it is correct. Then click on the "Run" button to trigger the query.
|
||||
|
||||
- Once the query is executed, create a new PostgreSQL query in SQL mode and use JavaScript to get the data query data dynamically:
|
||||
|
||||
```js
|
||||
{{queries.restapi1.data}}
|
||||
```
|
||||
```js
|
||||
{{queries.restapi1.data}}
|
||||
```
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/copilot/copilot1.gif" alt="ToolJet Copilot" />
|
||||
<img className="screenshot-full" src="/img/copilot/copilot1.gif" alt="ToolJet Copilot" />
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
|
@ -100,3 +120,4 @@ While using ToolJet Copilot, it is important to note that the accuracy of the ou
|
|||
:::
|
||||
|
||||
If you have feedback or questions about ToolJet Copilot, feel free to join our **[slack community](https://tooljet.com/slack)**.
|
||||
|
||||
|
|
|
|||
|
|
@ -9,21 +9,27 @@ Furthermore, the dashboard serves as a gateway to various essential sections, su
|
|||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/dashboard/dashboardoptions.png" alt="App menu options"/>
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/dashboard/dashboardoptions-v2.png" alt="App menu options"/>
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## Workspace Manager
|
||||
|
||||
The workspace manager is located on the bottom left corner of the dashboard. Clicking on the workspace manager will open a dropdown menu 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.
|
||||
The workspace manager is located on the bottom left corner of the dashboard. Clicking on the workspace manager will open a dropdown menu listing all the workspaces you belong to. You can switch between workspaces by clicking on the workspace name from the dropdown menu.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/dashboard/workspacemenu.png" alt="Dashboard"/>
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/dashboard/workspacemenu-v2.png" alt="Dashboard"/>
|
||||
|
||||
</div>
|
||||
|
||||
### Add new workspace
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
### Add New Workspace
|
||||
|
||||
On clicking the `Add new workspace` button, a modal will open where you can enter the name of the workspace, enter the unique workspace slug, and can see the preview of the workspace URL. Click on the `+ Create Workspace` button to create a new workspace.
|
||||
|
||||
|
|
@ -39,21 +45,29 @@ Previously, the workspace slug was an automatically generated workspace ID, like
|
|||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/dashboard/newworkmodal.png" alt="Dashboard"/>
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/dashboard/new-workspace-modal-v2.png" alt="Dashboard"/>
|
||||
|
||||
</div>
|
||||
|
||||
### Edit workspace
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
### Edit Workspace
|
||||
|
||||
Similar to the `Add new workspace` button, clicking on the `Edit workspace` button will open a modal where you can edit the name of the workspace and the workspace slug. Click on the `Save` button to update the changes.
|
||||
|
||||
## Create a new app
|
||||
</div>
|
||||
|
||||
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={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## Create a New App
|
||||
|
||||
To create a new app, click on the `Create new app` button on the top left corner of the dashboard. Clicking on this button will open a modal where you can enter the name of the app and then click on the `+ Create app` button to create a new app.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/dashboard/newappmodal.png" alt="Dashboard"/>
|
||||
<img className="screenshot-full" src="/img/dashboard/new-app-modal-v2.png" alt="Dashboard"/>
|
||||
|
||||
</div>
|
||||
<br/>
|
||||
|
|
@ -63,49 +77,76 @@ There are three dots on the right side of the `Create new app` button. Clicking
|
|||
- **[Choose from templates](#choose-from-templates)**
|
||||
- **[Import](#import)**
|
||||
|
||||
### Choose from templates
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
### Choose from Templates
|
||||
|
||||
This option will open a modal with a list of pre-built templates. You can choose any template from this list to create a new app.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/dashboard/choosefromtemplate.gif" alt="Dashboard"/>
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/dashboard/choosefromtemplate-v2.gif" alt="Dashboard"/>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
### Import
|
||||
|
||||
This option will open a file picker to import a JSON file. This JSON file should be the app exported from ToolJet.
|
||||
This option will open a file picker to import a JSON file. This JSON file should contain the app data exported from ToolJet.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/dashboard/import.gif" alt="Dashboard"/>
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/dashboard/import-app-v2.gif" alt="Dashboard"/>
|
||||
|
||||
</div>
|
||||
|
||||
### Importing app connected to marketplace plugins
|
||||
</div>
|
||||
|
||||
When importing an app with marketplace plugins, the marketplace plugin should be installed in the tooljet workspace where the app is being imported. If the marketplace plugin is not installed, the app will be imported without the queries for that plugin.
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
#### When marketplace plugin is installed
|
||||
### Importing an App Connected to Marketplace Plugins
|
||||
|
||||
If marketplace plugin is installed in the tooljet workspace where the app is being imported, the queries connected to the marketplace plugin will be available in the imported application. The queries will be linked to the data source with the same name if it is already present. If the data source is not present, a new data source will be created of that marketplace plugin and linked to the queries.
|
||||
When importing an app with Marketplace plugins, the Marketplace plugin should be installed in the ToolJet workspace where the app is being imported. If the Marketplace plugin is not installed, the app will be imported without the queries for that plugin.
|
||||
|
||||
#### When marketplace plugin is not installed
|
||||
#### When Marketplace plugin is installed
|
||||
|
||||
If you have an app with a query linked to a marketplace plugin, and you import that app in a tooljet workspace where the marketplace plugin is not installed as the data source, the queries will be not be available in the imported application.
|
||||
If Marketplace plugin is installed in the ToolJet workspace where the app is being imported, the queries connected to the Marketplace plugin will be available in the imported application. The queries will be linked to the data source with the same name if it is already present. If the data source is not present, a new data source will be created of that Marketplace plugin and linked to the queries.
|
||||
|
||||
### Importing app connected to tooljet table
|
||||
#### When Marketplace plugin is not installed
|
||||
|
||||
When the app(JSON file) that includes the table schema is imported, and the table is not present in the tooljet database of the workspace where the app is being imported, a new table will be created in the tooljet database with the same name as the table in the imported app.
|
||||
If you have an app with a query linked to a Marketplace plugin, and you import that app in a ToolJet workspace where the Marketplace plugin is not installed as the data source, the queries will be not be available in the imported application.
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
### Importing App Connected to ToolJet Table
|
||||
|
||||
When the app(JSON file) that includes the table schema is imported, and the table is not present in the ToolJet database of the workspace where the app is being imported, a new table will be created in the ToolJet database with the same name as the table in the imported app.
|
||||
|
||||
If the table with the same name is already present in the workspace, the new table will be created with the name `<table name>_<unix timestamp>`. Example: `<tablename>_1627980000`.
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## Folders
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
### Create a new folder
|
||||
|
||||
Folders can be created to organize your apps. To create a new folder, click on the `+` button on the left drawer of the dashboard. Clicking on this button will open a modal, enter the name of the folder and click on the `Create Folder` button to create a new folder.
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
### Delete or Edit Folder
|
||||
|
||||
A folder can be **deleted** or **renamed**. To delete or rename a folder, click on the kebab menu on the right side of the folder name. Clicking on kebab menu will open a dropdown menu with two options:
|
||||
|
|
@ -115,48 +156,67 @@ A folder can be **deleted** or **renamed**. To delete or rename a folder, click
|
|||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/dashboard/newfolder.gif" alt="Dashboard"/>
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/dashboard/newfolder-v2.gif" alt="Dashboard"/>
|
||||
|
||||
</div>
|
||||
|
||||
### Search folders
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
### Search Folders
|
||||
|
||||
Folders can be searched by clicking on the search icon on the left drawer of the dashboard. Clicking on the search icon will open a search bar, enter the name of the folder to search.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/dashboard/search.png" alt="Dashboard"/>
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/dashboard/search-v2.png" alt="Dashboard"/>
|
||||
|
||||
</div>
|
||||
|
||||
### Slug for folders
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
### Slug for Folders
|
||||
|
||||
The folder's URL slug is generated automatically from its name, providing direct access to the folder using the slug.
|
||||
|
||||
To get the URL of a specific folder, the user will have to select that folder and then copy the URL from the address bar of the browser. The copied URL can be used to share with other users of the workspace.
|
||||
|
||||
Example: If the name of the folder is `customer support`, The folder can be accessed directly from the URL `https://tooljet.com/<workspace-name>?folder=customer%20support`.
|
||||
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"/>
|
||||
<img className="screenshot-full" src="/img/dashboard/app-url-v2.png" alt="Dashboard"/>
|
||||
|
||||
</div>
|
||||
|
||||
## App cards
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## App Cards
|
||||
|
||||
The dashboard displays all the apps created in the workspace as cards. These cards are displayed in a grid layout. The app cards display the **name of the app**, the **name of the creator**, and the **date of creation**. The app cards also display the app **icon**, which can be changed by clicking on the `Change Icon` option from the app menu.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/dashboard/appcard.png" alt="Dashboard"/>
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/dashboard/appcard-v2.png" alt="Dashboard"/>
|
||||
|
||||
</div>
|
||||
|
||||
## App menu
|
||||
</div>
|
||||
|
||||
The app menu is located on the top right corner of the app card. Clicking on the app menu will open a dropdown menu with a list of options. These options are:
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## App Menu
|
||||
|
||||
The app menu is located on the top right corner of the app card. Clicking on the app menu will open a dropdown menu containing various options. These options are:
|
||||
|
||||
- **[Rename app](#rename-app)**
|
||||
- **[Change Icon](#change-icon)**
|
||||
- **[Add to folder](#add-to-folder)**
|
||||
- **[Clone app](#clone-app)**
|
||||
|
|
@ -165,84 +225,128 @@ The app menu is located on the top right corner of the app card. Clicking on the
|
|||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/dashboard/appmenu.gif" alt="Dashboard"/>
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/dashboard/app-menu-v2.gif" alt="Dashboard"/>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
### Rename App
|
||||
|
||||
This option will open a modal that will allow you to rename your app.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/dashboard/rename-app.png" alt="Dashboard"/>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
### Change Icon
|
||||
|
||||
This option will open a modal with a list of icons. You can choose any icon from this list to change the app icon.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/dashboard/changeicon.png" alt="Dashboard"/>
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/dashboard/change-icon-v2.png" alt="Dashboard"/>
|
||||
|
||||
</div>
|
||||
|
||||
### Add to folder
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
### Add to Folder
|
||||
|
||||
This option will open a modal with a list of folders. You can choose any folder from this list to add the app to the folder.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/dashboard/addtofolder.png" alt="Dashboard"/>
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/dashboard/add-to-folder-v2.png" alt="Dashboard"/>
|
||||
|
||||
</div>
|
||||
|
||||
### Clone app
|
||||
</div>
|
||||
|
||||
Selecting this option will immediately open the cloned app in the app builder with the same configuration as the original app. The new app will be named as `<original app name>` followed by unix timestamp. Example: `<original app name> 1627980000`.
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
### Clone App
|
||||
|
||||
Selecting this option will open a modal where you can enter the desired name for the cloned app. After providing the desired name, click on the Clone app button. This will immediately open the cloned app in the app builder with the same configuration as the original app.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/dashboard/cloneapp.gif" alt="Dashboard"/>
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/dashboard/clone-app-v2.gif" alt="Dashboard"/>
|
||||
|
||||
</div>
|
||||
|
||||
### Export app
|
||||
</div>
|
||||
|
||||
This option will download a JSON file of the application. This JSON file can be [imported](#import) to ToolJet to create a new app. The exported app will include all the queries connected to global data sources including the data source created from Marketplace plugins.
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
### Export App
|
||||
|
||||
This option downloads a JSON file containing the application data. This JSON file can be [imported](#import) to ToolJet to create a new app. The exported app will include all the queries connected to global data sources including the data source created from Marketplace plugins.
|
||||
|
||||
This option allows you to select a specific version of the app to export or export all the versions of the app. To export a specific version of the app, select a version from the list of available versions in the modal and click on the `Export selected version` and to export all the versions of the app, click on the `Export All` button.
|
||||
|
||||
#### Export ToolJet table schema
|
||||
|
||||
Selecting this option will include the schema of the tooljet table connected to that application in the exported JSON file. This option is available for all the apps on ToolJet however only the apps with a tooljet table connected(includes tjdb query) will have the schema included in the exported JSON file.
|
||||
Selecting this option will include the schema of the ToolJet table connected to that application in the exported JSON file. This option is available for all the apps on ToolJet however only the apps with a ToolJet table connected(includes tjdb query) will have the schema included in the exported JSON file.
|
||||
|
||||
This JSON file can be used to [import](#importing-app-connected-to-tooljet-table) the application to ToolJet along with the table schema that was connected to the application.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/dashboard/exportapp.png" alt="Dashboard"/>
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/dashboard/export-app-v2.png" alt="Dashboard"/>
|
||||
|
||||
</div>
|
||||
|
||||
### Delete app
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
### Delete App
|
||||
|
||||
This option will open a confirmation modal to delete the app. Click on the `Delete` button to delete the app.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/dashboard/deleteapp.png" alt="Dashboard"/>
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/dashboard/delete-app-v2.png" alt="Dashboard"/>
|
||||
|
||||
</div>
|
||||
|
||||
## App search
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## App Search
|
||||
|
||||
Apps can be searched by clicking on the search bar on the center of the dashboard. Click on the search bar and enter the name of the app to search.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/dashboard/searchapp.png" alt="Dashboard"/>
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/dashboard/search-app-v2.png" alt="Dashboard"/>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## Current ToolJet Version
|
||||
|
||||
The current version of ToolJet is displayed on the top right corner of the dashboard.
|
||||
The current version of ToolJet is displayed on the top right corner of the dashboard.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/dashboard/currentversion.png" alt="Dashboard"/>
|
||||
<img className="screenshot-full" src="/img/dashboard/current-version-v2.png" alt="Dashboard"/>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
|
@ -8,7 +8,7 @@ title: Airtable
|
|||
ToolJet can connect to your Airtable account to read and write data. **Personal Access Token** is required to connect to the Airtable data source on ToolJet. You can generate the Personal Access Token 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).
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/datasource-reference/airtable/airtableconnect.gif" alt="Airtable Data Source Connection" />
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/datasource-reference/airtable/airtableconnect-v2.gif" alt="Airtable Data Source Connection" />
|
||||
</div>
|
||||
|
||||
<br/>
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ To connect ToolJet with the Azure Blob data source, you have two options:
|
|||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/datasource-reference/azureblob/gdsazure.gif" alt="Azure Blob - ToolJet" />
|
||||
<img className="screenshot-full" src="/img/datasource-reference/azureblob/gdsazure-v2.png" alt="Azure Blob - ToolJet" />
|
||||
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ To connect to Baserow, you need to provide the following details:
|
|||
|
||||
|
||||
|
||||
<img className="screenshot-full" src="/img/datasource-reference/baserow/baserow-intro.png" alt="Baserow intro" />
|
||||
<img className="screenshot-full" src="/img/datasource-reference/baserow/baserow-intro-v2.png" alt="Baserow intro" />
|
||||
|
||||
|
||||
## Supported Operations
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ ToolJet requires the following to connect to your ClickHouse Database:
|
|||
- **Debug**
|
||||
- **Raw**
|
||||
|
||||
<img className="screenshot-full" src="/img/datasource-reference/clickhouse/connection.png" alt="ClickHouse connection" />
|
||||
<img className="screenshot-full" src="/img/datasource-reference/clickhouse/connection-v2.png" alt="ClickHouse connection" />
|
||||
|
||||
## Querying ClickHouse
|
||||
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ You can find the endpoint and key in the **[Azure Portal](https://portal.azure.c
|
|||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||

|
||||

|
||||
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ When the query is triggered the alert will show the parameters value.
|
|||
|
||||
Let's demonstrate how to utilize parameters in RunJS queries and call one query from another by providing custom parameter values:
|
||||
|
||||
1. Begin by creating a new RunJS query named `multiply`. In this query, add the following parameters: **num1** with a default value of `10` and **num2** with a default value of `2`. To display the result, place a text component on the canvas and set its text to **{{queries.multiply.data}}**. Save and Run the query.
|
||||
1. Begin by creating a new RunJS query named `multiply`. In this query, add the following parameters: **num1** with a default value of `10` and **num2** with a default value of `2`. To display the result, place a text component on the canvas and set its text to `{{queries.multiply.data}}`. Save and Run the query.
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/datasource-reference/custom-javascript/multiply.png" alt="Run JavaScript code" />
|
||||
|
|
|
|||
132
docs/docs/data-sources/databricks.md
Normal file
132
docs/docs/data-sources/databricks.md
Normal file
|
|
@ -0,0 +1,132 @@
|
|||
---
|
||||
id: databricks
|
||||
title: Databricks
|
||||
---
|
||||
|
||||
# Databricks
|
||||
|
||||
Databricks is a cloud-based platform for data processing, analytics, and machine learning. ToolJet connects to Databricks, allowing your applications to access and update your data in your Databricks Warehouses directly using SQL queries.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/datasource-reference/databricks/install.gif" alt="Install Databricks" />
|
||||
</div>
|
||||
|
||||
## Configuration
|
||||
|
||||
ToolJet's Databricks integration relies on a configuration form that supports the following parameters:
|
||||
|
||||
#### Required Parameters
|
||||
|
||||
- **Server hostname**: The server hostname or the IP address of your Databricks Warehouse. For example, `62596234423488486.6.gcp.databricks.com`.
|
||||
- **HTTP Path**: The API endpoint path for the Databricks resource you want to access. For example, `/sql/1.0/warehouses/44899g7346c19m95`.
|
||||
- **Personal access token**: Personal access tokens are used for secure authentication to the Databricks API instead of passwords. For example, `dapi783c7d155d138d8cf14`.
|
||||
|
||||
#### Optional Parameters
|
||||
|
||||
- **Port**: The port number of your Databricks Warehouse. The default port number is `443`.
|
||||
- **Default Catalog**: The default catalog to use for the connection.
|
||||
- **Default Schema**: The default schema to use for the connection.
|
||||
|
||||
### Setup
|
||||
|
||||
- Navigate to your Databricks workspace, select the desired SQL Warehouse, and find **Server Hostname** and **HTTP Path** within the connection details tab.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/datasource-reference/databricks/connection-details.png" alt="Databricks: Connection Details" />
|
||||
</div>
|
||||
|
||||
- To generate a personal access token, access your Databricks User Settings, select the Developer tab, click Manage under Access Tokens, and then click on the **Generate New Token** button.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/datasource-reference/databricks/generate-token.png" alt="Databricks: Access Tokens" />
|
||||
</div>
|
||||
|
||||
- Navigate to the Databricks datasource configuration form in ToolJet, fill in the required parameters, and click the **Save** button. You can test the connection by clicking the **Test Connection** button.
|
||||
|
||||
:::note
|
||||
Ensure your Databricks Warehouse is running and has been granted the necessary permissions prior to clicking **Test Connection** or running any queries.
|
||||
:::
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/datasource-reference/databricks/setup-parameters.png" alt="Databricks: Setup Paramaters" />
|
||||
</div>
|
||||
|
||||
## Querying Databricks
|
||||
|
||||
- To perform queries on Databricks in ToolJet, click the **+ Add** button in the query manager located at the bottom panel of the editor.
|
||||
- Select the previously configured Databricks datasource.
|
||||
- In the second Data Source dropdown, select **SQL mode** as the query type. ToolJet currently supports only SQL mode for Databricks interactions.
|
||||
- Selecting SQL mode will open a dedicated SQL editor where you can write your SQL queries.
|
||||
- After writing the query, click the **Run** button to execute the query.
|
||||
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/datasource-reference/databricks/add-query.gif" alt="Databricks: Query Setup" />
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
:::tip
|
||||
You can apply transformations to the query results. Refer to our transformations documentation for more information: [link](/docs/tutorial/transformations)
|
||||
:::
|
||||
|
||||
## Supported Queries
|
||||
|
||||
Databricks supports standard SQL commands for data manipulation tasks.
|
||||
|
||||
### Read Data
|
||||
|
||||
The following example demonstrates how to read data from a table. The query selects all the columns from the `customers` table.
|
||||
|
||||
```sql
|
||||
SELECT * FROM customers
|
||||
```
|
||||
|
||||
### Write Data
|
||||
|
||||
The following example demonstrates how to write data to a table. The query inserts a new row into the `customers` table.
|
||||
|
||||
```sql
|
||||
INSERT INTO customers (
|
||||
customer_id,
|
||||
first_name,
|
||||
last_name,
|
||||
email,
|
||||
phone,
|
||||
city,
|
||||
state,
|
||||
zip_code,
|
||||
country
|
||||
) VALUES (
|
||||
'1001'
|
||||
'Tom',
|
||||
'Hudson',
|
||||
'tom.hudson@example.com',
|
||||
'50493552',
|
||||
'San Clemente',
|
||||
'CA',
|
||||
'92673',
|
||||
'USA'
|
||||
);
|
||||
```
|
||||
|
||||
### Update Data
|
||||
|
||||
The following example demonstrates how to update data in a table. The query updates the `first_name` and `email` column of the `customers` table.
|
||||
|
||||
```sql
|
||||
UPDATE customer
|
||||
SET first_name = 'John',
|
||||
email = 'john.hudson@example.com'
|
||||
WHERE customer_id = 1001;
|
||||
```
|
||||
|
||||
### Delete Data
|
||||
|
||||
The following example demonstrates how to delete data from a table. The query deletes a row from the `customers` table.
|
||||
|
||||
```sql
|
||||
DELETE FROM customer
|
||||
WHERE customer_id = 1001;
|
||||
```
|
||||
|
|
@ -2,6 +2,7 @@
|
|||
id: dynamodb
|
||||
title: DynamoDB
|
||||
---
|
||||
|
||||
# DynamoDB
|
||||
|
||||
DynamoDB is a managed non-relational database service provided by Amazon. ToolJet has the capability to connect to DynamoDB for reading and writing data.
|
||||
|
|
@ -12,7 +13,7 @@ To establish a connection with the DynamoDB data source, you can either click on
|
|||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/datasource-reference/dynamoDB/dynamogds.gif" alt="DynamoDB" />
|
||||
<img className="screenshot-full" src="/img/datasource-reference/dynamodb/dynamogds-v2.png" alt="DynamoDB" />
|
||||
|
||||
</div>
|
||||
|
||||
|
|
@ -96,10 +97,12 @@ Returns an array of table names associated with the current account and endpoint
|
|||
Retrieves a single item from a table. You must specify the primary key for the item that you want. You can retrieve the entire item, or just a subset of its attributes.
|
||||
|
||||
**Required parameters:**
|
||||
|
||||
- **Table**
|
||||
- **Key name**
|
||||
|
||||
Syntax for Key name:
|
||||
|
||||
```json
|
||||
{
|
||||
"Key": {
|
||||
|
|
@ -123,23 +126,25 @@ Syntax for Key name:
|
|||
Retrieves all items that have a specific partition key. You must specify the partition key value. You can retrieve entire items, or just a subset of their attributes. Optionally, you can apply a condition to the sort key values so that you only retrieve a subset of the data that has the same partition key. You can use this operation on a table, provided that the table has both a partition key and a sort key. You can also use this operation on an index, provided that the index has both a partition key and a sort key.
|
||||
|
||||
**Required parameters:**
|
||||
|
||||
- **Query condition**
|
||||
|
||||
Syntax for Query condition:
|
||||
|
||||
```json
|
||||
{
|
||||
"TableName": "Reply",
|
||||
"IndexName": "PostedBy-Index",
|
||||
"Limit": 3,
|
||||
"ConsistentRead": true,
|
||||
"ProjectionExpression": "Id, PostedBy, ReplyDateTime",
|
||||
"KeyConditionExpression": "Id = :v1 AND PostedBy BETWEEN :v2a AND :v2b",
|
||||
"ExpressionAttributeValues": {
|
||||
":v1": {"S": "Amazon DynamoDB#DynamoDB Thread 1"},
|
||||
":v2a": {"S": "User A"},
|
||||
":v2b": {"S": "User C"}
|
||||
},
|
||||
"ReturnConsumedCapacity": "TOTAL"
|
||||
"TableName": "Reply",
|
||||
"IndexName": "PostedBy-Index",
|
||||
"Limit": 3,
|
||||
"ConsistentRead": true,
|
||||
"ProjectionExpression": "Id, PostedBy, ReplyDateTime",
|
||||
"KeyConditionExpression": "Id = :v1 AND PostedBy BETWEEN :v2a AND :v2b",
|
||||
"ExpressionAttributeValues": {
|
||||
":v1": { "S": "Amazon DynamoDB#DynamoDB Thread 1" },
|
||||
":v2a": { "S": "User A" },
|
||||
":v2b": { "S": "User C" }
|
||||
},
|
||||
"ReturnConsumedCapacity": "TOTAL"
|
||||
}
|
||||
```
|
||||
|
||||
|
|
@ -154,12 +159,13 @@ Syntax for Query condition:
|
|||
Retrieves all items in the specified table or index. You can retrieve entire items, or just a subset of their attributes. Optionally, you can apply a filtering condition to return only the values that you are interested in and discard the rest.
|
||||
|
||||
**Required parameters:**
|
||||
|
||||
- **Scan condition**
|
||||
|
||||
Syntax for Scan condition:
|
||||
|
||||
```json
|
||||
{"TableName": "<table_name>"}
|
||||
{ "TableName": "<table_name>" }
|
||||
```
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
|
@ -173,22 +179,24 @@ Syntax for Scan condition:
|
|||
Deletes a single item from a table. You must specify the primary key for the item that you want to delete.
|
||||
|
||||
**Required parameters:**
|
||||
|
||||
- **Table**
|
||||
- **Key Name**
|
||||
|
||||
Syntax for Key name:
|
||||
|
||||
```json
|
||||
{
|
||||
"Key": {
|
||||
"ForumName": {
|
||||
"S": "Amazon DynamoDB"
|
||||
},
|
||||
"Subject": {
|
||||
"S": "How do I update multiple items?"
|
||||
}
|
||||
"Key": {
|
||||
"ForumName": {
|
||||
"S": "Amazon DynamoDB"
|
||||
},
|
||||
"ConditionExpression": "attribute_not_exists(Replies)",
|
||||
"ReturnValues": "ALL_OLD"
|
||||
"Subject": {
|
||||
"S": "How do I update multiple items?"
|
||||
}
|
||||
},
|
||||
"ConditionExpression": "attribute_not_exists(Replies)",
|
||||
"ReturnValues": "ALL_OLD"
|
||||
}
|
||||
```
|
||||
|
||||
|
|
@ -203,16 +211,18 @@ Syntax for Key name:
|
|||
Update an item in DynamoDB by specifying the primary key and providing new attribute values. If the primary key does not exist in the table then instead of updating it will insert a new row.
|
||||
|
||||
**Required parameters:**
|
||||
|
||||
- **Update Condition**
|
||||
|
||||
Syntax for Update Condition:
|
||||
|
||||
```json
|
||||
{
|
||||
"TableName": "USER_DETAILS_with_local",
|
||||
"Key": {
|
||||
"USER_ID": 1,
|
||||
"USER_NAME": "Nick"
|
||||
},
|
||||
"USER_ID": 1,
|
||||
"USER_NAME": "Nick"
|
||||
},
|
||||
"UpdateExpression": "set USER_AGE = :age, USER_FEE = :fee",
|
||||
"ExpressionAttributeValues": {
|
||||
":age": 40,
|
||||
|
|
@ -232,6 +242,7 @@ Syntax for Update Condition:
|
|||
This operation in DynamoDB retrieves metadata and configuration details about a specific table. It provides information such as the table's name, primary key schema, provisioned throughput settings, and any secondary indexes defined on the table.
|
||||
|
||||
**Required parameters:**
|
||||
|
||||
- **Table**
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
|
@ -242,49 +253,50 @@ This operation in DynamoDB retrieves metadata and configuration details about a
|
|||
|
||||
### Create Table
|
||||
|
||||
This operation in DynamoDB enables you to create a new table by specifying its name, primary key schema, and optional configurations.
|
||||
This operation in DynamoDB enables you to create a new table by specifying its name, primary key schema, and optional configurations.
|
||||
|
||||
**Required parameters:**
|
||||
|
||||
- **Table Parameters**
|
||||
|
||||
Syntax for Table Parameters:
|
||||
|
||||
```json
|
||||
{
|
||||
"AttributeDefinitions": [
|
||||
"AttributeDefinitions": [
|
||||
{
|
||||
"AttributeName": "USER_ID",
|
||||
"AttributeName": "USER_ID",
|
||||
"AttributeType": "N"
|
||||
},
|
||||
{
|
||||
"AttributeName": "USER_FEE",
|
||||
"AttributeName": "USER_FEE",
|
||||
"AttributeType": "N"
|
||||
}
|
||||
],
|
||||
"KeySchema": [
|
||||
{
|
||||
|
||||
"AttributeName": "USER_ID",
|
||||
"KeyType": "HASH"
|
||||
}
|
||||
],
|
||||
{
|
||||
"AttributeName": "USER_ID",
|
||||
"KeyType": "HASH"
|
||||
}
|
||||
],
|
||||
"LocalSecondaryIndexes": [
|
||||
{
|
||||
"IndexName": "USER_FEE",
|
||||
"KeySchema": [
|
||||
{
|
||||
"IndexName": "USER_FEE",
|
||||
"KeySchema": [
|
||||
{
|
||||
"AttributeName": "USER_ID",
|
||||
"KeyType": "HASH"
|
||||
},
|
||||
{
|
||||
"AttributeName": "USER_FEE",
|
||||
"KeyType": "RANGE"
|
||||
}
|
||||
],
|
||||
"Projection": {
|
||||
"ProjectionType": "KEYS_ONLY"
|
||||
}
|
||||
"AttributeName": "USER_ID",
|
||||
"KeyType": "HASH"
|
||||
},
|
||||
{
|
||||
"AttributeName": "USER_FEE",
|
||||
"KeyType": "RANGE"
|
||||
}
|
||||
],
|
||||
],
|
||||
"Projection": {
|
||||
"ProjectionType": "KEYS_ONLY"
|
||||
}
|
||||
}
|
||||
],
|
||||
"ProvisionedThroughput": {
|
||||
"ReadCapacityUnits": 1,
|
||||
"WriteCapacityUnits": 1
|
||||
|
|
@ -307,17 +319,19 @@ Syntax for Table Parameters:
|
|||
This operation allows you to create or replace an item in a table. It enables you to specify the table name, provide the attribute values for the new item, and define the primary key attributes to uniquely identify the item.
|
||||
|
||||
**Required parameters:**
|
||||
|
||||
- **New Item Details**
|
||||
|
||||
Syntax for New Item Details:
|
||||
|
||||
```json
|
||||
{
|
||||
"TableName": "USER_DETAILS_with_localS",
|
||||
"Item": {
|
||||
"USER_ID": 1,
|
||||
"USER_ID": 1,
|
||||
"USER_NAME": "NICK",
|
||||
"USER_AGE": 34,
|
||||
"USER_FEE": 1234.56,
|
||||
"USER_FEE": 1234.56
|
||||
}
|
||||
}
|
||||
```
|
||||
|
|
@ -326,4 +340,4 @@ Syntax for New Item Details:
|
|||
|
||||
<img className="screenshot-full" src="/img/datasource-reference/dynamodb/updateitem.png" alt="ToolJet - DynamoDB operations" />
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ Once you have the key, open it in a text editor and copy the contents. Paste the
|
|||
Click on **Test connection** button to verify if the key is valid. Click on **Save** button to save the data source.
|
||||
|
||||
|
||||
<img className="screenshot-full" src="/img/datasource-reference/firestore/add-ds-firestore.gif" alt="firestore add ds"/>
|
||||
<img className="screenshot-full" src="/img/datasource-reference/firestore/add-ds-firestore-v2.png" alt="firestore add ds"/>
|
||||
|
||||
|
||||
## Querying Firestore
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ When connecting to a Google Sheets datasource, you can choose between two permis
|
|||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/datasource-reference/google-sheets/sheetconnect.gif" alt="Google Sheet" />
|
||||
<img className="screenshot-full" src="/img/datasource-reference/google-sheets/sheetconnect-v2.png" alt="Google Sheet" />
|
||||
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ To establish a connection with the GraphQL global datasource, you can either cli
|
|||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/datasource-reference/graphql/graphgds.gif" alt="ToolJet - Data source - REST API" />
|
||||
<img className="screenshot-full" src="/img/datasource-reference/graphql/graphgds-v2.png" alt="ToolJet - Data source - REST API" />
|
||||
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ For generating API Token visit [InfluxDB docs](https://docs.influxdata.com/influ
|
|||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||

|
||||

|
||||
|
||||
</div>
|
||||
|
||||
|
|
@ -51,7 +51,7 @@ For generating API Token visit [InfluxDB docs](https://docs.influxdata.com/influ
|
|||
- [Delete a bucket](#delete-a-bucket)
|
||||
|
||||
|
||||
<img className="screenshot-full" src="/img/datasource-reference/influxdb/operations.png" alt="influx operations" />
|
||||
<img className="screenshot-full" src="/img/datasource-reference/influxdb/operations-v2.png" alt="influx operations" />
|
||||
|
||||
|
||||
### Write data
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ title: Mailgun
|
|||
|
||||
ToolJet can connect to your Mailgun account to send emails.
|
||||
|
||||
<img class="screenshot-full" src="/img/datasource-reference/mailgun/mailgun-datasource.png" alt="ToolJet - Data source - Mailgun" height="420" />
|
||||
<img class="screenshot-full" src="/img/datasource-reference/mailgun/mailgun-datasource-v2.png" alt="ToolJet - Data source - Mailgun" height="420" />
|
||||
|
||||
:::info
|
||||
The Mailgun API Datasource supports for interaction with the mail endpoint of the [Mailgun API](https://documentation.mailgun.com/en/latest/api-intro.html#authentication-1).
|
||||
|
|
@ -42,8 +42,6 @@ Optional parameters:
|
|||
|
||||
- Body as HTML
|
||||
|
||||
<img class="screenshot-full" src="/img/datasource-reference/MailGun/mailgun_query_body.png" alt="ToolJet - Query Mailgun" height="420"/>
|
||||
|
||||
:::info
|
||||
**Send mail to** - accepts a single email id.
|
||||
For example:
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ To establish a connection with the MariaDB global datasource, you can either cli
|
|||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/datasource-reference/mariadb/gdsmaria.gif" alt="MariaDB" />
|
||||
<img className="screenshot-full" src="/img/datasource-reference/mariadb/gdsmaria-v2.png" alt="MariaDB" />
|
||||
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -145,7 +145,7 @@ Delete many records based on the filter. [Reference](https://docs.mongodb.com/dr
|
|||
|
||||
Perform bulk operations. [Reference](https://docs.mongodb.com/drivers/node/v4.0/usage-examples/bulkWrite/)
|
||||
|
||||
### Dynamic Quries
|
||||
### Dynamic Queries
|
||||
|
||||
```javascript
|
||||
{ amount: { $lt: '{{ components.textinput1.value }}' }}
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ This operations retrieves a Database object using the ID specified.
|
|||
|
||||
- **Database ID**: You'll find the Database ID in the url. Suppose this is the example url: `https://www.notion.so/workspace/XXX?v=YYY&p=ZZZ` then `XXX` is the database ID, `YYY` is the view ID and `ZZZ` is the page ID.
|
||||
|
||||
<img className="screenshot-full" src="/img/datasource-reference/notion/db_retrieve.png" alt="notion db retreieve" />
|
||||
<img className="screenshot-full" src="/img/datasource-reference/notion/db_retrieve.png" alt="notion db retrieve" />
|
||||
|
||||
#### 2. Query a database
|
||||
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ OpenAPI datasource accepts specifications only in **JSON** and **YAML** formats.
|
|||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/datasource-reference/openapi/openapiconnect.gif" alt="OpenAPI" />
|
||||
<img className="screenshot-full" src="/img/datasource-reference/openapi/openapiconnect-v2.png" alt="OpenAPI" />
|
||||
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ A Oracle DB can be connected with the following credentials:
|
|||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||

|
||||

|
||||
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ Data Source page is available only on **ToolJet version 2.3.0 and above**.
|
|||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/datasource-reference/overview/overview.png" alt="Data Sources: Overview" width="600"/>
|
||||
<img className="screenshot-full" src="/img/datasource-reference/overview/overview-v2.png" alt="Data Sources: Overview" />
|
||||
|
||||
</div>
|
||||
|
||||
|
|
@ -26,19 +26,13 @@ Data Source page is available only on **ToolJet version 2.3.0 and above**.
|
|||
|
||||
</div>
|
||||
|
||||
Or you can directly go to the **Data Sources** page from the left sidebar of the dashboard
|
||||
|
||||
<div style={{textAlign: 'left'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/datasource-reference/newui/overview/newgds.png" alt="Data Sources: Overview" />
|
||||
|
||||
</div>
|
||||
Or you can directly go to the **Data Sources** page from the left sidebar of the dashboard.
|
||||
|
||||
2. Within the **Data Sources** page, you'll find various categories of data sources on the left side, including Databases, APIs, Cloud Storages, and plugins. Click on each category to view the list of accessible data sources. As you hover over the desired data source, an `Add` button will appear. Upon clicking this button, the selected data source will be integrated into the workspace.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/datasource-reference/newui/overview/gdsadd.gif" alt="Overview of Data Sources" />
|
||||
<img className="screenshot-full" src="/img/datasource-reference/newui/overview/gdsadd-v2.png" alt="Overview of Data Sources" />
|
||||
|
||||
</div>
|
||||
|
||||
|
|
@ -48,7 +42,7 @@ Data Source page is available only on **ToolJet version 2.3.0 and above**.
|
|||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/datasource-reference/newui/overview/connectinggds.gif" alt="Overview of Data Sources" />
|
||||
<img className="screenshot-full" src="/img/datasource-reference/newui/overview/connectinggds-v2.gif" alt="Overview of Data Sources" />
|
||||
|
||||
</div>
|
||||
|
||||
|
|
@ -97,7 +91,7 @@ To configure these permissions, navigate to **Workspace Settings** -> **Groups S
|
|||
| **Just Create** | Add new data sources and modify existing ones. Delete button will not be visible on hovering over the connected data source. |
|
||||
| **Just Delete** | Remove connected data sources from the workspace. Delete button will show up on hovering over the connected data source. |
|
||||
| **Both Create and Delete** | Add new data sources and remove connected data sources from the workspace. |
|
||||
| **Niether Create nor Delete** | No access to the Data Sources page from the Dashboard. Error toast will popup on trying to access the Data Sources page using URL. |
|
||||
| **Neither Create nor Delete** | No access to the Data Sources page from the Dashboard. Error toast will popup on trying to access the Data Sources page using URL. |
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
|
|
|
|||
|
|
@ -188,7 +188,7 @@ Google Cloud Platform provides access to more than 350 APIs and Services that ca
|
|||
2. Navigate to the **APIs and Services**, and then open the **OAuth consent screen** section from the left sidebar.
|
||||
3. Enter the Application details and select the appropriate scopes for your application. We will select the profile and the email scopes.
|
||||
4. Once you have created the OAuth consent screen, Create new credentials for the **OAuth client ID** from the **Credentials** section in the left sidebar.
|
||||
5. Select the application type, enter the application name, and then add the following URIs under Authorised Redirect URIs:
|
||||
5. Select the application type, enter the application name, and then add the following URIs under Authorized Redirect URIs:
|
||||
1. `https://app.tooljet.com/oauth2/authorize` (if you’re using ToolJet cloud)
|
||||
2. `http://localhost:8082/oauth2/authorize` (if you’re using ToolJet locally)
|
||||
6. Now save and then you’ll get the **Client ID and Client secret** for your application.
|
||||
|
|
|
|||
|
|
@ -53,44 +53,38 @@ queries.getSalesData.run()
|
|||
|
||||
To immediately access the data returned by a query in **Run Python code**, you can use the below functions:
|
||||
|
||||
#### Retrieve the latest data of a query:
|
||||
#### Trigger a query and retrieve its data:
|
||||
```py
|
||||
response = await queries.getSalesData.run()
|
||||
await queries.getSalesData.run()
|
||||
#replace getSalesData with your query name
|
||||
|
||||
value = queries.getSalesData.getData()
|
||||
#replace getSalesData with your query name
|
||||
|
||||
value
|
||||
```
|
||||
|
||||
#### Retrieve the latest raw data of a query:
|
||||
#### Trigger a query and retrieve its raw data:
|
||||
```py
|
||||
response = await queries.getCustomerData.run()
|
||||
await queries.getCustomerData.run()
|
||||
#replace getCustomerData with your query name
|
||||
|
||||
value = queries.getCustomerData.getRawData()
|
||||
#replace getCustomerData with your query name
|
||||
|
||||
value
|
||||
```
|
||||
|
||||
#### Retrieve the loading state of a query:
|
||||
#### Trigger a query and retrieve its loading state:
|
||||
```py
|
||||
response = await queries.getTodos.run()
|
||||
await queries.getTodos.run()
|
||||
#replace getTodos with your query name
|
||||
|
||||
value = queries.getTodos.getLoadingState()
|
||||
#replace getTodos with your query name
|
||||
|
||||
value
|
||||
```
|
||||
|
||||
## Get Variables
|
||||
|
||||
To immediately access a variable or page variable after setting it in the **Run Python code**, you can use the below functions.
|
||||
To immediately access a variable or page variable after setting it in the **Run Python code**, you can use the below functions:
|
||||
|
||||
#### Retrieve the current value of a variable:
|
||||
#### Set and retrieve a variable:
|
||||
```py
|
||||
actions.setVariable('mode','dark')
|
||||
#replace mode with your desired variable name
|
||||
|
|
@ -99,7 +93,7 @@ actions.getVariable('mode')
|
|||
#replace mode with your desired variable name
|
||||
```
|
||||
|
||||
#### Retrieve the current value of a page-specific variable:
|
||||
#### Set and retrieve a page-specific variable:
|
||||
```py
|
||||
actions.setPageVariable('number',1)
|
||||
#replace number with your desired variable name
|
||||
|
|
|
|||
|
|
@ -50,143 +50,65 @@ You can check out the some of the operations mentioned below. All the operations
|
|||
- **get,/v1/account**
|
||||
- **post,/v1/account**
|
||||
- **post,/v1/account/bank_accounts**
|
||||
- **delete,/v1/account/bank_accounts/{id}**
|
||||
- **get,/v1/account/bank_accounts/{id}**
|
||||
- **post,/v1/account/bank_accounts/{id}**
|
||||
- **delete,/v1/account/bank_accounts/`{id}`**
|
||||
- **get,/v1/account/bank_accounts/`{id}`**
|
||||
- **post,/v1/account/bank_accounts/`{id}`**
|
||||
- **get,/v1/account/capabilities**
|
||||
- **get,/v1/account/capabilities/{capability}**
|
||||
- **post,/v1/account/capabilities/{capability}**
|
||||
- **get,/v1/account/capabilities/`{capability}`**
|
||||
- **post,/v1/account/capabilities/`{capability}`**
|
||||
- **get,/v1/account/external_accounts**
|
||||
- **post,/v1/account/external_accounts**
|
||||
- **delete,/v1/account/external_accounts/{id}**
|
||||
- **get,/v1/account/external_accounts/{id}**
|
||||
- **post,/v1/account/external_accounts/{id}**
|
||||
- **delete,/v1/account/external_accounts/`{id}`**
|
||||
- **get,/v1/account/external_accounts/`{id}`**
|
||||
- **post,/v1/account/external_accounts/`{id}`**
|
||||
- **post,/v1/account/login_links**
|
||||
- **get,/v1/account/people**
|
||||
- **post,/v1/account/people**
|
||||
- **delete,/v1/account/people/{person}**
|
||||
- **get,/v1/account/people/{person}**
|
||||
- **delete,/v1/account/people/`{person}`**
|
||||
- **get,/v1/account/people/`{person}`**
|
||||
- **post,/v1/account/persons**
|
||||
- **delete,/v1/account/persons/{person}**
|
||||
- **get,/v1/account/persons/{person}**
|
||||
- **post,/v1/account/persons/{person}**
|
||||
- **delete,/v1/account/persons/`{person}`**
|
||||
- **get,/v1/account/persons/`{person}`**
|
||||
- **post,/v1/account/persons/`{person}`**
|
||||
- **post,/v1/account_links**
|
||||
- **get,/v1/accounts**
|
||||
- **post,/v1/accounts**
|
||||
- **delete,/v1/accounts/{account}**
|
||||
- **get,/v1/accounts/{account}**
|
||||
- **post,/v1/accounts/{account}**
|
||||
- **post,/v1/accounts/{account}/bank_accounts**
|
||||
- **delete,/v1/accounts/{account}/bank_accounts/{id}**
|
||||
- **get,/v1/accounts/{account}/bank_accounts/{id}**
|
||||
- **get,/v1/accounts/{account}/bank_accounts/{id}**
|
||||
- **get,/v1/accounts/{account}/capabilities**
|
||||
- **get,/v1/accounts/{account}/capabilities/{capability}**
|
||||
- **post,/v1/accounts/{account}/capabilities/{capability}**
|
||||
- **get,/v1/accounts/{account}/external_accounts**
|
||||
- **post,/v1/accounts/{account}/external_accounts**
|
||||
- **delete,/v1/accounts/{account}/external_accounts/{id}**
|
||||
- **get,/v1/accounts/{account}/external_accounts/{id}**
|
||||
- **get,/v1/accounts/{account}/external_accounts/{id}**
|
||||
- **post,/v1/accounts/{account}/login_links**
|
||||
- **get,/v1/accounts/{account}/people**
|
||||
- **post,/v1/accounts/{account}/people**
|
||||
- **delete,/v1/accounts/{account}/people/{person}**
|
||||
- **get,/v1/accounts/{account}/people/{person}**
|
||||
- **post,/v1/accounts/{account}/people/{person}**
|
||||
- **get,/v1/accounts/{account}/persons**
|
||||
- **post,/v1/accounts/{account}/persons**
|
||||
- **delete,/v1/accounts/{account}/persons/{person}**
|
||||
- **get,/v1/accounts/{account}/persons/{person}**
|
||||
- **post,/v1/accounts/{account}/persons/{person}**
|
||||
- **post,/v1/accounts/{account}/reject**
|
||||
- **delete,/v1/accounts/`{account}`**
|
||||
- **get,/v1/accounts/`{account}`**
|
||||
- **post,/v1/accounts/`{account}`**
|
||||
- **post,/v1/accounts/`{account}`/bank_accounts**
|
||||
- **delete,/v1/accounts/`{account}`/bank_accounts/`{id}`**
|
||||
- **get,/v1/accounts/`{account}`/bank_accounts/`{id}`**
|
||||
- **get,/v1/accounts/`{account}`/bank_accounts/`{id}`**
|
||||
- **get,/v1/accounts/`{account}`/capabilities**
|
||||
- **get,/v1/accounts/`{account}`/capabilities/`{capability}`**
|
||||
- **post,/v1/accounts/`{account}`/capabilities/`{capability}`**
|
||||
- **get,/v1/accounts/`{account}`/external_accounts**
|
||||
- **post,/v1/accounts/`{account}`/external_accounts**
|
||||
- **delete,/v1/accounts/`{account}`/external_accounts/`{id}`**
|
||||
- **get,/v1/accounts/`{account}`/external_accounts/`{id}`**
|
||||
- **get,/v1/accounts/`{account}`/external_accounts/`{id}`**
|
||||
- **post,/v1/accounts/`{account}`/login_links**
|
||||
- **get,/v1/accounts/`{account}`/people**
|
||||
- **post,/v1/accounts/`{account}`/people**
|
||||
- **delete,/v1/accounts/`{account}`/people/`{person}`**
|
||||
- **get,/v1/accounts/`{account}`/people/`{person}`**
|
||||
- **post,/v1/accounts/`{account}`/people/`{person}`**
|
||||
- **get,/v1/accounts/`{account}`/persons**
|
||||
- **post,/v1/accounts/`{account}`/persons**
|
||||
- **delete,/v1/accounts/`{account}`/persons/`{person}`**
|
||||
- **get,/v1/accounts/`{account}`/persons/`{person}`**
|
||||
- **post,/v1/accounts/`{account}`/persons/`{person}`**
|
||||
- **post,/v1/accounts/`{account}`/reject**
|
||||
- **get,/v1/apple_pay/domains**
|
||||
- **post,/v1/apple_pay/domains**
|
||||
- **delete,/v1/apple_pay/domains/{domain}**
|
||||
- **get,/v1/apple_pay/domains/{domain}**
|
||||
- **delete,/v1/apple_pay/domains/`{domain}`**
|
||||
- **get,/v1/apple_pay/domains/`{domain}`**
|
||||
- **get,/v1/application_fees**
|
||||
- **get,/v1/application_fees/{fee}/refunds/{id}**
|
||||
- **post,/v1/application_fees/{fee}/refunds/{id}**
|
||||
- **get,/v1/application_fees/{id}**
|
||||
- **post,/v1/application_fees/{id}/refund**
|
||||
- **get,/v1/application_fees/{id}/refunds**
|
||||
- **post,/v1/application_fees/{id}/refunds**
|
||||
- **get,/v1/application_fees/`{fee}`/refunds/`{id}`**
|
||||
- **post,/v1/application_fees/`{fee}`/refunds/`{id}`**
|
||||
- **get,/v1/application_fees/`{id}`**
|
||||
- **post,/v1/application_fees/`{id}`/refund**
|
||||
- **get,/v1/application_fees/`{id}`/refunds**
|
||||
- **post,/v1/application_fees/`{id}`/refunds**
|
||||
- **get,/v1/apps/secrets**
|
||||
|
||||
|
||||
<!--
|
||||
### delete,/v1/account
|
||||
|
||||
This operation can be used to delete the accounts that you manage in Stripe.
|
||||
|
||||
#### Required parameters:
|
||||
|
||||
- **account**: Enter the account id of account that you want to delete. example: `acct_1032D82eZvKYlo2C`
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
### get,/v1/account
|
||||
|
||||
This operation returns the basic account information such as account id, capabilities, currency, country etc.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
### post,/v1/account
|
||||
|
||||
This operation updates the connected account by setting the values of the parameters passed. Any parameters not provided are left unchanged.
|
||||
|
||||
### post,/v1/account/bank_accounts
|
||||
|
||||
This operation will create a bank account in your stripe account.
|
||||
|
||||
### delete,/v1/account/bank_accounts/{id}
|
||||
|
||||
This operation can be used to delete a specified external account for a given account.. You'll need to provide the **id** of the bank account in stripe.
|
||||
|
||||
### get,/v1/account/bank_accounts/{id}
|
||||
|
||||
This operation can be used to retrieve a specified external account whose **id** is provided in parameters.
|
||||
|
||||
### post,/v1/account/bank_accounts/{id}
|
||||
|
||||
This operation can be used to update the metadata, account holder name, account holder type of a bank account belonging to a Custom Account, and optionally sets it as the default for its currency. Other bank account details are not editable by design. You can re-enable a disabled bank account by performing an update call without providing any arguments or changes.
|
||||
|
||||
### get,/v1/account/capabilities
|
||||
|
||||
This operation returns a list of capabilities associated with the account. The capabilities are returned sorted by creation date, with the most recent capability appearing first.
|
||||
|
||||
### get,/v1/account/capabilities/{capability}
|
||||
|
||||
This operation retrieves information about the specified Account Capability.
|
||||
|
||||
### post,/v1/account/capabilities/{capability}
|
||||
|
||||
This operation updates an existing Account Capability.
|
||||
|
||||
### get,/v1/account/external_accounts
|
||||
|
||||
List external accounts for an account.
|
||||
|
||||
### post,/v1/account/external_accounts
|
||||
|
||||
This operation creates an external account for a given account.
|
||||
|
||||
### delete,/v1/account/external_accounts/{id}
|
||||
|
||||
This operation deletes a specified external account for a given account.
|
||||
|
||||
-->
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ To connect Zendesk datasource to your ToolJet application, go to the data source
|
|||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||

|
||||

|
||||
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -5,15 +5,10 @@ slug: /
|
|||
---
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
<!-- ## What is ToolJet?
|
||||
|
||||
ToolJet is a fast, secure, and user-friendly development platform to build custom internal tools. ToolJet streamlines the development process with seamless integrations, robust security, and a comprehensive suite of app-building tools. -->
|
||||
|
||||
## What is ToolJet?
|
||||
|
||||
ToolJet is a low-code platform that enables developers to rapidly build and deploy custom internal tools. It has a drag-and-drop app builder with 45 pre-built components, so developers can create complex applications in minutes. ToolJet also connects to most popular data sources and APIs out of the box, and it has a group-based permission system for easy user access management. ToolJet also comes with a lot of other features, but for now, let’s build a basic ToolJet app.
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
|
@ -21,7 +16,7 @@ ToolJet is a low-code platform that enables developers to rapidly build and depl
|
|||
## How ToolJet Works:
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/platform-overview/platform-overview-v2.jpg" alt="Platform Overview" />
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/platform-overview/platform-overview-v2.png" alt="Platform Overview" />
|
||||
</div>
|
||||
|
||||
**With ToolJet, you can streamline app development with 4 core steps:** <br/>
|
||||
|
|
@ -42,10 +37,9 @@ Below is a detailed overview of ToolJet's key functionalities, demonstrating how
|
|||
|
||||
### Visual App Builder
|
||||
Enables the creation of visually appealing front-ends with a drag-and-drop interface and pre-built components.
|
||||
<!-- It simplifies the app-development process, making it accessible even for non-technical users. -->
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img style={{ border:'0'}} className="screenshot-full" src="/img/platform-overview/app-builder.png" alt="App-Builder" />
|
||||
<img className="screenshot-full" src="/img/platform-overview/app-builder.png" alt="App-Builder" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
|
@ -54,10 +48,9 @@ Enables the creation of visually appealing front-ends with a drag-and-drop inter
|
|||
|
||||
### Integrations
|
||||
Offers seamless integration with a wide range of data sources, including over 50 applications, databases, and APIs.
|
||||
<!-- This feature facilitates easy data connectivity and aggregation from various systems. -->
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img style={{ border:'0'}} className="screenshot-full" src="/img/platform-overview/integrations.png" alt="Integrations" />
|
||||
<img style={{}} className="screenshot-full" src="/img/platform-overview/integrations-v2.png" alt="Integrations" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
|
@ -92,7 +85,7 @@ Designed with advanced security features and a scalable infrastructure to meet t
|
|||
<!-- This ensures the protection of sensitive data and the reliability of the platform in handling large-scale applications. -->
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img style={{ border:'0', borderRadius:'5px'}} className="screenshot-full" src="/img/platform-overview/security.png" alt="Security" />
|
||||
<img style={{ border:'0', borderRadius:'5px'}} className="screenshot-full" src="/img/platform-overview/security-v2.png" alt="Security" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
|
@ -102,10 +95,9 @@ Designed with advanced security features and a scalable infrastructure to meet t
|
|||
### SSO Support
|
||||
|
||||
Single Sign-On (SSO) capabilities, supporting a variety of providers including Okta, Google, Azure AD, and OpenID Connect.
|
||||
<!-- This enhances user authentication and bolsters overall security. -->
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img style={{ border:'0', borderRadius:'5px'}} className="screenshot-full" src="/img/platform-overview/sso.png" alt="SSO Support" />
|
||||
<img style={{ border:'0', borderRadius:'5px'}} className="screenshot-full" src="/img/platform-overview/sso-v2.png" alt="SSO Support" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -11,10 +11,16 @@ import TabItem from '@theme/TabItem';
|
|||
|
||||
The GitSync feature enables synchronization of workspace applications with a git repository, streamlining application management and version control on ToolJet.
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## Overview
|
||||
|
||||
ToolJet applications can be synchronized with a Git repository, offering the flexibility to tailor your application development and deployment processes across various environments while aligning with best practices for the application development lifecycle.
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
### Key Use-Cases:
|
||||
|
||||
#### Backup of Apps
|
||||
|
|
@ -31,9 +37,15 @@ Facilitating the movement of applications across different ToolJet deployments (
|
|||
|
||||
<br/>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="GitHub" label="Setting up GitSyncing with GitHub">
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## Setting up GitSyncing with GitHub
|
||||
|
||||
:::caution
|
||||
|
|
@ -61,12 +73,6 @@ Obtain the **SSH URL** of the repository. When a repository is created, GitHub s
|
|||
### Step 3: Configure the GitSync feature on ToolJet
|
||||
|
||||
Go to the **Workspace settings**, and click on the **Configure git** tab.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/gitsync/gitsync.png" alt="GitSync" />
|
||||
</div>
|
||||
<br/>
|
||||
|
||||
Enter the **SSH URL** of the repository (obtained in Step 2) in the **Git repository URL** field. Click on the **Generate SSH key** button, and copy the SSH key that is generated. The SSH key is used to authenticate ToolJet with the repository.
|
||||
|
||||
There are two types of generated SSH keys: **
|
||||
|
|
@ -74,7 +80,7 @@ There are two types of generated SSH keys: **
|
|||
- **RSA**: This is an older algorithm that is used for generating SSH keys. It is not recommended to use this key type. Older VCS providers like Bitbucket recommend using this key type.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/gitsync/ssh2.png" alt="GitSync" />
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/gitsync/ssh2-v2.png" alt="GitSync" />
|
||||
</div>
|
||||
|
||||
### Step 4: Deploy the SSH key to GitHub repository
|
||||
|
|
@ -96,11 +102,15 @@ Enter a title for the SSH key in the **Title** field. Paste the SSH key that you
|
|||
Go back to the **Configure git** tab on ToolJet, and click on the **Finalize setup** button. If the SSH key is configured correctly, you will see a success message.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/gitsync/git55.png" alt="GitSync" />
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/gitsync/finalize-ssh2-configuration-v2.png" alt="GitSync" />
|
||||
</div>
|
||||
<br/>
|
||||
|
||||
## Auto-commit on promoting environment
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## Auto-commit on Promoting Environment
|
||||
|
||||
When you promote an environment, from **Developement to Staging** or from **Staging to Production**, the changes will be automatically committed to the git repository. The commit message will be `<version_number> Version of <app_name> promoted from <source_environment> to <destination_environment>`. The author will be the user who promoted the environment.
|
||||
|
||||
|
|
@ -112,10 +122,14 @@ When you promote an environment, from **Developement to Staging** or from **Stag
|
|||
This option can be enabled or disabled from the **Configure git** tab on the **Workspace settings** page. By default, this option is disabled.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/gitsync/autocommit.png" alt="GitSync" />
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/gitsync/autocommit-v2.png" alt="GitSync" />
|
||||
</div>
|
||||
<br/>
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## Enable/Disable GitSync
|
||||
|
||||
To enable or disable the GitSync feature, go to the **Configure git** tab on the **Workspace settings** page, and toggle on/off the **Connect** switch. This is only available if the GitSync feature is configured.
|
||||
|
|
@ -129,11 +143,15 @@ On clicking the GitSync button, the users will be able to commit changes to the
|
|||
2. For admin users: The users will see a dialogue box with a link to configure the GitSync feature.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/gitsync/connect.png" alt="GitSync" />
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/gitsync/connect-v2.png" alt="GitSync" />
|
||||
</div>
|
||||
<br/>
|
||||
|
||||
## Delete GitSync configuration
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## Delete GitSync Configuration
|
||||
|
||||
To delete the GitSync configuration, go to the **Configure git** tab on the **Workspace settings** page, and click on the **Delete configuration** button. This will delete the SSH key from the ToolJet configuration and the GitSync feature will be disabled.
|
||||
|
||||
|
|
@ -141,11 +159,15 @@ To delete the GitSync configuration, go to the **Configure git** tab on the **Wo
|
|||
- Deleting the GitSync configuration will not delete the apps from the git repository. The apps will still be available in the git repository in the same state as they were before the GitSync configuration was deleted.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/gitsync/deleteconfig.png" alt="GitSync" />
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/gitsync/deleteconfig-v2.png" alt="GitSync" />
|
||||
</div>
|
||||
<br/>
|
||||
|
||||
## Git repo
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## Git Repo
|
||||
|
||||
Once the initial commit is made, you can see the app files in the git repository. The repository will have the individual app folders and a **.meta** folder. The app folders will be named as the app name and will have the respective **JSON** file of the application. The **.meta** folder will have the `meta.json` file that contains the meta information of each application synced to git repo.
|
||||
|
||||
|
|
@ -156,11 +178,15 @@ The **meta.json** file holds information about apps such as the **App name**, **
|
|||
</div>
|
||||
<br/>
|
||||
|
||||
## Pushing changes to git repo
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## Pushing Changes to Git Repo
|
||||
|
||||
Once the GitSync feature is configured, you can start pushing changes to the git repository.
|
||||
|
||||
### App creation
|
||||
### App Creation
|
||||
|
||||
When you create a new app, you will see an option to select the `Commit changes`. If you select the `commit changes` option, the changes will be committed to the git repository.
|
||||
|
||||
|
|
@ -169,7 +195,7 @@ If the app name is same as the name of the existing app in the git repo, it will
|
|||
:::
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/gitsync/commitchanges.png" alt="GitSync" />
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/gitsync/commitchanges-v2.png" alt="GitSync" />
|
||||
</div>
|
||||
<br/>
|
||||
|
||||
|
|
@ -180,7 +206,7 @@ Selecting the `Commit changes` option will create a new commit in the git reposi
|
|||
</div>
|
||||
<br/>
|
||||
|
||||
### App rename
|
||||
### App Rename
|
||||
|
||||
Whenever an app is renamed, the changes will be automatically committed to the git repository. The commit message will be `App is renamed` and the author will be the user who renamed the app.
|
||||
|
||||
|
|
@ -189,7 +215,7 @@ Whenever an app is renamed, the changes will be automatically committed to the g
|
|||
</div>
|
||||
<br/>
|
||||
|
||||
### App updates
|
||||
### App Updates
|
||||
|
||||
Whenever a user makes a change in an app, they can make a commit to the git repository by clicking on the **GitSync** button on the topbar. On clicking the **GitSync** button, a modal will open with the option to enter the commit message. The user can enter the commit message and click on the **Commit changes** button to commit the changes to the git repository. Along with the commit message, the user can also see the connnected **Git repo URL** and the **last commit details**.
|
||||
|
||||
|
|
@ -207,11 +233,11 @@ Once the changes are committed, the user can see the commit message, author, and
|
|||
</div>
|
||||
<br/>
|
||||
|
||||
### App deletion
|
||||
### App Deletion
|
||||
|
||||
Whenever a user deleted an app from the workspace, the app will not be deleted from the git repository. The app will be available in the git repository in the same state as it was before the app was deleted.
|
||||
|
||||
### App version update
|
||||
### App Version Update
|
||||
|
||||
Whenever a user creates a new app version and creates a commit to git repository, the **JSON** file in the app folder will be replaced with the new version of the app that was created. The **meta.json** file in the **.meta** folder will also be updated with the new version id and version name.
|
||||
|
||||
|
|
@ -220,14 +246,18 @@ Whenever a user creates a new app version and creates a commit to git repository
|
|||
</div>
|
||||
<br/>
|
||||
|
||||
## Pulling changes from git repo
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
## Pulling Changes from Git Repo
|
||||
|
||||
You can configure the GitSync feature on another workspace to pull the changes from the git repository. To configure the GitSync feature on another workspace, follow the steps mentioned in the [Setting up GitSyncing with GitHub](#setting-up-git-syncing-with-github) section.
|
||||
|
||||
Once the GitSync feature is configured, go to the ToolJet dashboard and click on the three dots on the right side of the **Create new app** button. Click on the **Import from git repository** option.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/gitsync/importgit.png" alt="GitSync" />
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/gitsync/importgit-v2.png" alt="GitSync" />
|
||||
</div>
|
||||
<br/>
|
||||
|
||||
|
|
@ -240,11 +270,11 @@ On clicking the **Import from git repository** option, a modal will open with th
|
|||
:::
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/gitsync/importmodal.png" alt="GitSync" />
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/gitsync/importmodal-v2.png" alt="GitSync" />
|
||||
</div>
|
||||
<br/>
|
||||
|
||||
### Checking for updates
|
||||
### Checking for Updates
|
||||
|
||||
You can check for updates in the git repository by clicking on the **GitSync** button on the topbar. On clicking the **GitSync** button, a modal will open with the option to **Check for updates**. Click on the **Check for updates** button to check for updates in the git repository. If there are any updates, you will see the details of the updates such as commit message, author, and the date in the modal. Click on the **Pull changes** button to pull the changes from the git repository.
|
||||
|
||||
|
|
|
|||
|
|
@ -2,9 +2,14 @@
|
|||
id: access-cellvalue-rowdata
|
||||
title: Dynamically Change Cell Colors in Table
|
||||
---
|
||||
<div style={{paddingBottom:'24px'}}>
|
||||
|
||||
This guide shows how to change the text color and background color of certain cells in a Table component based on specific conditions.
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## 1. Start by Creating a New Application and Setting up the Data Source
|
||||
- Create a new app and add a **[Table](/docs/widgets/table)** component to the canvas.
|
||||
- Open the Query Panel at the bottom and click on the `+ Add` button.
|
||||
|
|
@ -15,6 +20,10 @@ https://fakestoreapi.com/products
|
|||
```
|
||||
- To view the data that your query will return, click on the **Preview** button. Click on the **Run** button to execute the query and retrieve the data.
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## 2. Display Data on the Table
|
||||
|
||||
- Hide the Query Panel and click on the Table component to open its properties panel on the right.
|
||||
|
|
@ -23,9 +32,13 @@ https://fakestoreapi.com/products
|
|||
{{queries.restapi1.data}}
|
||||
```
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img style={{ border:'0' }} className="screenshot-full" src="/img/how-to/change-text-color/table-with-data.png" alt="Table Component With Data" />
|
||||
<img style={{ border:'0', marginBottom:'15px' }} className="screenshot-full" src="/img/how-to/change-text-color/table-with-data.png" alt="Table Component With Data" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## 3. Change Text Color Based on Cell Value
|
||||
|
||||
- Select the Table component and go to Columns.
|
||||
|
|
@ -43,6 +56,10 @@ Now, if the cell value is `electronics`, the text color will be red; otherwise,
|
|||
|
||||
<i>You can use also Hex color codes for more color options.</i>
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## 4. Change Text Color Using Row Data
|
||||
|
||||
- Under Cell Background Color for the `symbol` column, paste the below code:
|
||||
|
|
@ -59,4 +76,6 @@ Now if the value in the price column is lesser than 100, the cell background col
|
|||
<img style={{ border:'0', marginBottom:'15px' }} className="screenshot-full" src="/img/how-to/change-text-color/conditional-background-color.png" alt="Conditional Background Color" />
|
||||
</div>
|
||||
|
||||
You can use the above methods to change the text and background colors of a cell dynamically.
|
||||
You can use the above methods to change the text and background colors of a cell dynamically.
|
||||
|
||||
</div>
|
||||
|
|
@ -2,6 +2,7 @@
|
|||
id: access-currentuser
|
||||
title: Enable/Disable a Component Using Current User's Property
|
||||
---
|
||||
<div style={{paddingBottom:'24px'}}>
|
||||
|
||||
Let's take a look at the exposed variables of the currentUser property by clicking on the **[inspector](/docs/app-builder/left-sidebar/#inspector)** icon on the left sidebar:
|
||||
|
||||
|
|
@ -10,6 +11,10 @@ Let's take a look at the exposed variables of the currentUser property by clicki
|
|||
- **lastName** : The value can accessed using `{{globals.currentUser.lastName}}`
|
||||
- **groups**: The `groups` attribute is an array representing the groups a user belongs to. By default, every user, including admins, is part of the `all_users` group. Additionally, admins are also part of the `admin` group. To access a specific group name, you need to specify the array index, such as `[0]` for the first group, `[1]` for the second, and so on. For example, you can retrieve the name of the second group a user belongs to with `{{globals.currentUser.groups[1]}}`.
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
### Example: Disable a Button if a User is Not Admin
|
||||
|
||||
- Click on the **Button** handle to open its properties. On the **Styles** tab, go to the **Disable** property.
|
||||
|
|
@ -34,3 +39,4 @@ Let's take a look at the exposed variables of the currentUser property by clicki
|
|||
<img className="screenshot-full" width="100%" src="/img/how-to/access-currentuser/released.png" alt="Released button disabled when user is not admin" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
|
@ -1,7 +1,8 @@
|
|||
---
|
||||
id: access-users-location
|
||||
title: Accessing User Location with RunJS Query (Geolocation API)
|
||||
title: Accessing User Location with RunJS Query
|
||||
---
|
||||
<div style={{paddingBottom:'24px'}}>
|
||||
|
||||
In this step-by-step guide we will build a ToolJet application that harnesses the power of the **JavaScript Geolocation API** to retrieve the user's location. The Geolocation API offers access to various geographical data associated with a user's device, utilizing methods such as GPS, WIFI, IP Geolocation, and more.
|
||||
|
||||
|
|
@ -9,6 +10,8 @@ In this step-by-step guide we will build a ToolJet application that harnesses th
|
|||
To uphold user privacy, the Geolocation API requests permission before locating the device. Upon permission, you gain access to data like latitude, longitude, altitude, and speed.
|
||||
:::
|
||||
|
||||
</div>
|
||||
|
||||
1. Begin by creating a new application:
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/how-to/access-location/newapp.png" alt="How to: Access User's Location" />
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ ToolJet marketplace is a place where you can find custom plugins and install the
|
|||
## Getting started
|
||||
### 1. Enabling the marketplace for your instance
|
||||
To enable the marketplace for your instance, you need to set the `ENABLE_MARKETPLACE` environment variable to `true` in your `.env` file.
|
||||
Marketplacwe is disabled by default.
|
||||
Marketplace is disabled by default.
|
||||
Once you set the environment variable, restart your ToolJet instance. You can find the instructions to run ToolJet locally [here](/docs/setup/).
|
||||
Marketplace can be accessed from '/integrations' route.
|
||||
|
||||
|
|
@ -270,7 +270,7 @@ It includes information about authentication options, specifically a dropdown to
|
|||
```
|
||||
The operations.json file defines the operations that can be performed on the data source. It includes information about the operation type, the fields required to perform the operation, and the type of each field. 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.
|
||||
|
||||
### 6. Add the npm package of Gitub to the plugin dependencies
|
||||
### 6. Add the npm package of GitHub to the plugin dependencies
|
||||
|
||||
```bash
|
||||
# change directory to the plugin directory and install the npm package
|
||||
|
|
|
|||
|
|
@ -2,9 +2,13 @@
|
|||
id: bulk-update-multiple-rows
|
||||
title: Bulk Update Multiple Rows in Table
|
||||
---
|
||||
|
||||
<div style={{paddingBottom:'24px'}}>
|
||||
For the purpose of this guide, it's presumed that you've already established a successful connection to your data source. We'll use PostgreSQL for this example, but you can adjust the queries based on the SQL database that you are using.
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## 1. Create a Query to Get the Data
|
||||
|
||||
- Create a PostgreSQL query in SQL mode, rename it to *users* and enter the below code.
|
||||
|
|
@ -16,9 +20,12 @@ SELECT * FROM <table name> // *replace <table name> with your table name*
|
|||
- Click on the **Run** button to fetch the data from the database.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img style={{ border:'0' }} className="screenshot-full" src="/img/how-to/bulk-update-multiple/new/data.png" alt="Fetch the Data" />
|
||||
<img style={{ border:'0', marginBottom:'15px' }} className="screenshot-full" src="/img/how-to/bulk-update-multiple/new/data.png" alt="Fetch the Data" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## 2. Display the Data on the Table
|
||||
|
||||
|
|
@ -30,26 +37,38 @@ SELECT * FROM <table name> // *replace <table name> with your table name*
|
|||
```
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img style={{ border:'0' }} className="screenshot-full" src="/img/how-to/bulk-update-multiple/new/populate.png" alt="Display Data on the Table" />
|
||||
<img style={{ border:'0', marginBottom:'15px' }} className="screenshot-full" src="/img/how-to/bulk-update-multiple/new/populate.png" alt="Display Data on the Table" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## 3. Make the Columns Editable
|
||||
|
||||
- Under the Columns accordion, click on the column name that you want to make editable.
|
||||
- On clicking the column name, a new section will open. Enable the toggle for `Make editable` to make the column editable.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img style={{ border:'0' }} className="screenshot-full" src="/img/how-to/bulk-update-multiple/new/editable.png" alt="Make Column Editable" />
|
||||
<img style={{ border:'0', marginBottom:'15px' }} className="screenshot-full" src="/img/how-to/bulk-update-multiple/new/editable.png" alt="Make Column Editable" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## 4. Enable Multiple Row Selection
|
||||
|
||||
- Under the Row Selection accordion, enable the `Allow Selection`, `Highlight Selected Row`, and `Bulk Selection` option.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img style={{ border:'0' }} className="screenshot-full" src="/img/how-to/bulk-update-multiple/new/rowselect.png" alt="Multiple Row Selection" />
|
||||
<img style={{ border:'0', marginBottom:'15px' }} className="screenshot-full" src="/img/how-to/bulk-update-multiple/new/rowselect.png" alt="Multiple Row Selection" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## 5. Create a Custom JS query
|
||||
|
||||
- Create a new Run Javascript query and use the code below to generate the SQL query for updating multiple rows. The query will be named as *runjs1* by default.
|
||||
|
|
@ -76,9 +95,13 @@ return sql
|
|||
Here the unique identifier is **id** and Table component's name is **table1**. You can update the unique identifier if you are using a different column as a unique identifier. You can also update the Table name if you have renamed it, the default name is *table1*.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img style={{ border:'0' }} className="screenshot-full" src="/img/how-to/bulk-update-multiple/new/runjs1.png" alt="RunJS code to later the data" />
|
||||
<img style={{ border:'0', marginBottom:'15px' }} className="screenshot-full" src="/img/how-to/bulk-update-multiple/new/runjs1.png" alt="RunJS code to later the data" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## 6. Create an Update Query
|
||||
|
||||
- Create a PostgreSQL query in SQL mode and rename it to *update*:
|
||||
|
|
@ -90,9 +113,13 @@ Here the unique identifier is **id** and Table component's name is **table1**. Y
|
|||
- This query will run the SQL query generated by the *runjs1* query.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img style={{ border:'0' }} className="screenshot-full" src="/img/how-to/bulk-update-multiple/new/update.png" alt="Bulk Update Rows" />
|
||||
<img style={{ border:'0', marginBottom:'15px' }} className="screenshot-full" src="/img/how-to/bulk-update-multiple/new/update.png" alt="Bulk Update Rows" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## 7. Adding Event Handlers to Execute Queries in Sequence
|
||||
|
||||
- Edit the Table component and add an event handler for `Save Changes` event so that whenever a user will edit the Table and hit the Save Changes button the *runjs1* query will run.
|
||||
|
|
@ -118,4 +145,6 @@ The data needs to reload once the *update* query runs since we want the Table co
|
|||
- Select Query Success as the Event and Run Query as the Action.
|
||||
- Select *users* as Query.
|
||||
|
||||
This will refresh the table whenever the *update* query will be run.
|
||||
This will refresh the table whenever the *update* query will be run.
|
||||
|
||||
</div>
|
||||
|
|
@ -2,9 +2,14 @@
|
|||
id: conditionally-format-table
|
||||
title: Conditional Formatting in Table
|
||||
---
|
||||
<div style={{paddingBottom:'24px'}}>
|
||||
|
||||
Conditional formatting enhances the visual representation of data by allowing you to dynamically adjust the appearance of cells in table component based on specific conditions. This how-to guide will guide you through the process of implementing advanced conditional formatting for text color and background color in a Table component.
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## Create a New Application and Set Up Data Source
|
||||
|
||||
1. Create a new application and add a Table component to the canvas.
|
||||
|
|
@ -24,6 +29,10 @@ Conditional formatting enhances the visual representation of data by allowing yo
|
|||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/how-to/conditionally-format/query.png" alt="Table Component With Data" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## Display Data on the Table
|
||||
|
||||
1. Hide the Query Panel and click on the Table component to open its properties panel.
|
||||
|
|
@ -37,6 +46,10 @@ Conditional formatting enhances the visual representation of data by allowing yo
|
|||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/how-to/conditionally-format/tabledata.png" alt="Table Component With Data" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## Enabling Conditional Formatting
|
||||
|
||||
1. Go to the **Columns** property of the Table component.
|
||||
|
|
@ -51,8 +64,16 @@ Conditional formatting enhances the visual representation of data by allowing yo
|
|||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/how-to/conditionally-format/column.png" alt="Table Component With Data" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## Conditional Formatting using Cell Value
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
### Example 1: Changing Text Color Based on Cell Value
|
||||
|
||||
1. Select the `Rate` column which has a column type of `Default`/`String`. This column contains the rating of each product on a scale of 1 to 5.
|
||||
|
|
@ -69,6 +90,9 @@ Conditional formatting enhances the visual representation of data by allowing yo
|
|||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/how-to/conditionally-format/textcv.png" alt="Table Component With Data" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
### Example 2: Changing Cell Background Color Based on Cell Value
|
||||
|
||||
|
|
@ -84,8 +108,16 @@ Conditional formatting enhances the visual representation of data by allowing yo
|
|||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/how-to/conditionally-format/cellcv.png" alt="Table Component With Data" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## Conditional Formatting using Row Data
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
### Example 1: Changing Text Color Based on Row Data
|
||||
|
||||
- Select the `Title` column, enter the following condition under the **Text Color** property:
|
||||
|
|
@ -100,6 +132,10 @@ Conditional formatting enhances the visual representation of data by allowing yo
|
|||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/how-to/conditionally-format/textrd.png" alt="Table Component With Data" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
### Example 2: Changing Cell Background Color based on Row Data
|
||||
|
||||
- In this example, we will change the cell background color of the `Title` column based on the category of the product.
|
||||
|
|
@ -116,6 +152,8 @@ Conditional formatting enhances the visual representation of data by allowing yo
|
|||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/how-to/conditionally-format/cellrd.png" alt="Table Component With Data" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -2,9 +2,14 @@
|
|||
id: delete-multiple-rows
|
||||
title: Delete Multiple Rows in a Table
|
||||
---
|
||||
<div style={{paddingBottom:'24px'}}>
|
||||
|
||||
This guide explains how to delete multiple rows from a table, assuming you've already connected to a data source. We'll use PostgreSQL for this example, but you can adjust the queries based on the SQL database that you are using.
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## 1. Create a Query to Fetch the Data from the Database
|
||||
|
||||
- Create a new query and name it *getRecords*.
|
||||
|
|
@ -17,10 +22,12 @@ SELECT * FROM tooljet // replace tooljet with your table name
|
|||
- Enable the `Run the query on application load?` option to execute the query automatically when the application starts.
|
||||
|
||||
<div style={{textAlign: 'left'}}>
|
||||
<img className="screenshot-full" src="/img/how-to/delete-rows/getRecords.png" alt="How-to: Delete Multiple Rows in Table" />
|
||||
<img style={{ border:'0', marginBottom:'15px' }} className="screenshot-full" src="/img/how-to/delete-rows/getRecords.png" alt="How-to: Delete Multiple Rows in Table" />
|
||||
</div>
|
||||
|
||||
<br/>
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## 2. Populating the Table with Data
|
||||
|
||||
|
|
@ -29,10 +36,12 @@ SELECT * FROM tooljet // replace tooljet with your table name
|
|||
- Now if you run the *getRecords* query, the returned data will be loaded in the Table component.
|
||||
|
||||
<div style={{textAlign: 'left'}}>
|
||||
<img className="screenshot-full" src="/img/how-to/delete-rows/querydata.png" alt="How-to: Delete multiple rows in table" />
|
||||
<img style={{ border:'0', marginBottom:'15px' }} className="screenshot-full" src="/img/how-to/delete-rows/querydata.png" alt="How-to: Delete multiple rows in table" />
|
||||
</div>
|
||||
|
||||
<br/>
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## 3. Enable Bulk Row Selection on Table
|
||||
|
||||
|
|
@ -40,10 +49,12 @@ SELECT * FROM tooljet // replace tooljet with your table name
|
|||
- Enabling this option will allow you to select multiple rows on the table.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img className="screenshot-full" src="/img/how-to/delete-rows/bulkselection.png" alt="How-to: Delete multiple rows in table" />
|
||||
<img style={{ border:'0', marginBottom:'15px' }} className="screenshot-full" src="/img/how-to/delete-rows/bulkselection.png" alt="How-to: Delete multiple rows in table" />
|
||||
</div>
|
||||
|
||||
<br/>
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## 4. Create a Custom JavaScript Query
|
||||
|
||||
|
|
@ -67,7 +78,7 @@ The above code generates a SQL query that deletes rows from the database table w
|
|||
- Click on the **Preview** button to see the SQL statement generated by the query.
|
||||
|
||||
<div style={{textAlign: 'left'}}>
|
||||
<img className="screenshot-full" src="/img/how-to/delete-rows/runjs.png" alt="How-to: Delete multiple rows in table" />
|
||||
<img style={{ border:'0'}} className="screenshot-full" src="/img/how-to/delete-rows/runjs.png" alt="How-to: Delete multiple rows in table" />
|
||||
</div>
|
||||
|
||||
*If you're using a different column as the unique identifier, feel free to update the code accordingly. You can also update the Table name if you have renamed it, the default name is *table1*.*
|
||||
|
|
@ -75,10 +86,12 @@ The above code generates a SQL query that deletes rows from the database table w
|
|||
- Select a few rows on the Table component and then Preview the SQL query generated by the *runjs1* query.
|
||||
|
||||
<div style={{textAlign: 'left'}}>
|
||||
<img className="screenshot-full" src="/img/how-to/delete-rows/runjs1.png" alt="How-to: Delete multiple rows in table" />
|
||||
<img style={{ border:'0', marginBottom:'15px' }} className="screenshot-full" src="/img/how-to/delete-rows/runjs1.png" alt="How-to: Delete multiple rows in table" />
|
||||
</div>
|
||||
|
||||
<br/>
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## 5. Create a New Query to Delete the Rows
|
||||
|
||||
|
|
@ -91,10 +104,12 @@ The above code generates a SQL query that deletes rows from the database table w
|
|||
In this query, we are dynamically loading the SQL statement generated by the JavaScript query.
|
||||
|
||||
<div style={{textAlign: 'left'}}>
|
||||
<img className="screenshot-full" src="/img/how-to/delete-rows/delete.png" alt="How-to: Delete multiple rows in table" />
|
||||
<img style={{ border:'0', marginBottom:'15px' }} className="screenshot-full" src="/img/how-to/delete-rows/delete.png" alt="How-to: Delete multiple rows in table" />
|
||||
</div>
|
||||
|
||||
<br/>
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## 6. Add a Button to Delete the Selected Rows
|
||||
|
||||
|
|
@ -128,4 +143,6 @@ Now, whenever you click on the Button component, the *runjs1* query will run and
|
|||
<img className="screenshot-full" src="/img/how-to/delete-rows/eventdelete.png" alt="How-to: Delete multiple rows in table" />
|
||||
</div>
|
||||
|
||||
By implementing this, we are ensuring that every time rows are deleted, the Table component will automatically refresh to display the most recent data fetched from the database.
|
||||
By implementing this, we are ensuring that every time rows are deleted, the Table component will automatically refresh to display the most recent data fetched from the database.
|
||||
|
||||
</div>
|
||||
|
|
@ -1,29 +1,39 @@
|
|||
---
|
||||
id: import-external-libraries-using-runjs
|
||||
title: Import external libraries using RunJS
|
||||
title: Import External Libraries using RunJS
|
||||
---
|
||||
<div style={{paddingBottom:'24px'}}>
|
||||
|
||||
ToolJet allows you to integrate external JavaScript libraries into your application using RunJS queries. This guide walks you through the process of importing and utilizing these libraries effectively.
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## Choosing Libraries
|
||||
|
||||
You can import various JavaScript libraries using their Content Delivery Network (CDN) links. Find the CDN links for your desired open-source projects on [jsDelivr](https://www.jsdelivr.com/).
|
||||
|
||||
## Creating a new app and runJS query
|
||||
</div>
|
||||
|
||||
Start by creating a new application in ToolJet. Then, proceed to create a new RunJS query from the query panel.
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## Creating a New App and RunJS Query
|
||||
|
||||
- Create a new app from the ToolJet Dashboard.
|
||||
- Once the app is ready, choose ToolJet's deafult **JavaScript** Data Source from the query panel.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/how-to/import-js/neww.png" alt="reate a new RunJS query" />
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/how-to/import-js/create-new-query-v2.png" alt="Create a new RunJS query" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## Importing Libraries
|
||||
|
||||
Here's a step-by-step guide to importing libraries and displaying an alert upon successful import.
|
||||
Once the query is created, add the following code:
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
|
|
@ -55,27 +65,30 @@ try {
|
|||
|
||||
</div>
|
||||
|
||||
After creating and running the query, an alert should pop up with the message "Mathjs and Flatten imported."
|
||||
After adding the code, click on the **Run** button in the query panel, an alert should pop up with the message "Mathjs and Flatten imported."
|
||||
|
||||
:::tip
|
||||
Enable the **Run this query on application load?** option to make the libraries available throughout the application as soon as the app is loaded.
|
||||
:::
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/how-to/import-js/import-successful-v2.png" alt="Import Successful" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/how-to/import-js/importeds.png" alt="reate a new RunJS query" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
## Examples
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
### 1. Flattening JSON Objects using FlattenJS
|
||||
|
||||
Create a new RunJS query using the Flatten library (imported earlier) to flatten a JSON object.
|
||||
- Create a new *RunJS* query using the Flatten library (imported earlier) to flatten a JSON object.
|
||||
- In the code section of the query, add the following code:
|
||||
|
||||
```js
|
||||
return flatten({
|
||||
|
|
@ -89,10 +102,10 @@ return flatten({
|
|||
});
|
||||
```
|
||||
|
||||
Preview the output in the query manager or run the query to see the flattened JSON.
|
||||
- Preview the output in the query manager or click **Run** in the query panel to see the flattened JSON.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/how-to/import-js/flattens.png" alt="reate a new RunJS query" />
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/how-to/import-js/flatten-js-v2.png" alt="Use FlattenJS" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
|
@ -101,16 +114,17 @@ Preview the output in the query manager or run the query to see the flattened JS
|
|||
|
||||
### 2. Computation using MathJS
|
||||
|
||||
Create another RunJS query utilizing the MathJS library for a calculation.
|
||||
- Create another *RunJS* query utilizing the MathJS library for a calculation.
|
||||
- In the code section of the query, add the following code:
|
||||
|
||||
```js
|
||||
return math.atan2(3, -3) / math.pi;
|
||||
```
|
||||
|
||||
Preview the output, or Run the query to see the result of the calculation.
|
||||
- Preview the output in the query manager or click **Run** in the query panel to see the result of the calculation.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/how-to/import-js/mathjss.png" alt="reate a new RunJS query" />
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/how-to/import-js/math-js-v2.png" alt="Use MathJs" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -2,14 +2,19 @@
|
|||
id: import-external-libraries-using-runpy
|
||||
title: Import External Libraries Using RunPy
|
||||
---
|
||||
<div style={{paddingBottom:'24px'}}>
|
||||
|
||||
ToolJet allows you to utilize python packages in your app by importing them using the [RunPy query](/docs/data-sources/run-py).
|
||||
In this how-to guide, we will import a few packages and use them in the application.
|
||||
|
||||
</div>
|
||||
|
||||
:::caution Unsupported modules
|
||||
Modules with C/C++ extensions needing system libraries won't work in Pyodide, as it runs in a web browser without system library access. Pyodide, based on WebAssembly-compiled Python, also doesn't support certain system calls.
|
||||
:::
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
- Start by creating a new application in ToolJet.
|
||||
- From the Query Panel, add a new RunPy query - it will be named *runpy1* by default.
|
||||
|
||||
|
|
@ -31,6 +36,10 @@ await micropip.install('numpy')
|
|||
|
||||
- Enable `Run this query on application load?` to make these packages available every time the application loads.
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## Generating Random Numbers with NumPy
|
||||
|
||||
- Create a RunPy query using NumPy's random module to generate random numbers.
|
||||
|
|
@ -47,6 +56,10 @@ print(x)
|
|||
|
||||
*You can check the output on the browser's console.*
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## Parse CSV data
|
||||
|
||||
- Create a RunPy query to parse CSV data using `StringIO`, `csv`, and `Pandas` module.
|
||||
|
|
@ -84,4 +97,6 @@ print(df)
|
|||
<div style={{textAlign: 'center'}}>
|
||||
<img className="screenshot-full" src="/img/how-to/import-python/console.gif" alt="Import external libraries using RunPy"/>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
|
@ -2,9 +2,12 @@
|
|||
id: intentionally-fail-js-query
|
||||
title: Intentionally Throwing an Error in RunJS for Debugging
|
||||
---
|
||||
<div style={{paddingBottom:'24px'}}>
|
||||
|
||||
In this step-by-step guide, we'll walk you through the process of creating a RunJS query that intentionally throws an error for debugging purposes.
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
### Creating the Error-Throwing RunJS Query
|
||||
|
|
|
|||
|
|
@ -2,9 +2,14 @@
|
|||
id: loading-image-pdf-from-db
|
||||
title: Upload And View Images and PDFs Using Base64 String
|
||||
---
|
||||
<div style={{paddingBottom:'24px'}}>
|
||||
|
||||
This guide shows how to upload and view images and PDFs using the base64 string format.
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## 1. Start by Creating a New Table In ToolJet Database
|
||||
|
||||
- Create a new table named *testDB*.
|
||||
|
|
@ -18,6 +23,10 @@ This guide shows how to upload and view images and PDFs using the base64 string
|
|||
<img className="screenshot-full" src="/img/how-to/load-base64/create-new-table.png" alt="New Table" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## 2. Upload Files To The Database
|
||||
|
||||
- Create a new application and name it *Load PDF And Images Example*.
|
||||
|
|
@ -69,6 +78,10 @@ This guide shows how to upload and view images and PDFs using the base64 string
|
|||
|
||||
The upload process is now complete. Whenever files are selected in the Filepicker components and the *upload* button is clicked, the base64 strings of these files will be automatically written to the database.
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## 3. View Image and PDF Files
|
||||
|
||||
- Create a query named *getFiles* to retrieve base64 strings from testDB: Click on **+ Add** button in the query panel, select Tooljet as Database, `testDB` as Table name, and `List rows` as Operations.
|
||||
|
|
@ -110,4 +123,6 @@ You can also use transformations in the query response and concat `data:image/jp
|
|||
<br/>
|
||||
<br/>
|
||||
|
||||
Using the above logic, you can upload and view files in ToolJet using the base64 data.
|
||||
Using the above logic, you can upload and view files in ToolJet using the base64 data.
|
||||
|
||||
</div>
|
||||
|
|
@ -1,16 +1,21 @@
|
|||
---
|
||||
id: print-multi-tabs-report
|
||||
title: Print data from multiple tabs
|
||||
title: Print Data from Multiple Tabs
|
||||
---
|
||||
|
||||
<div style={{paddingBottom:'24px'}}>
|
||||
|
||||
In this guide, we will learn how to print data from multiple tabs in ToolJet. This will be useful when you want to print an invoice or a report from your ToolJet application. For example, a tooljet app that has a set of tabs for each invoice and you want to print all the tabs in one go.
|
||||
|
||||
</div>
|
||||
|
||||
## UI of the app
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## UI of the App
|
||||
|
||||
Build an app with a set of tabs for each record. Each tab will have a set of fields to display the invoice details. In the example below, we have tabs component and each tab has a set of fields to display the record details.
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
**Dropdown**: For selecting a specific patient whose data user want to load in the tabs.
|
||||
|
|
@ -19,32 +24,32 @@ Build an app with a set of tabs for each record. Each tab will have a set of fie
|
|||
|
||||
**Button**: Clicking on the button will print the data from all the tabs. The button has two events, the details for which we will share later in this guide.
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/how-to/print-multitabs/appui.png" alt="Print data from multiple tabs" />
|
||||
</div>
|
||||
|
||||
## Load data from database
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## Load Data from Database
|
||||
|
||||
For this app, we are using tooljet database with table name `patient_data`. We created a query called `getPatientList` to fetch data from the database.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/how-to/print-multitabs/data.png" alt="Print data from multiple tabs" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
Once the data is successfully loaded on the tabs and the app is working as expected, we can move to the next step.
|
||||
|
||||
## Printing data from multiple tabs
|
||||
|
||||
To print data from multiple tabs, we will create few javascript queries. Using event handlers, we will run these javascript queries in a sequence to print data from all the tabs.
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## Printing Data from Multiple Tabs
|
||||
|
||||
To print data from multiple tabs, we will create few javascript queries. Using event handlers, we will run these javascript queries in a sequence to print data from all the tabs.
|
||||
|
||||
Before we start creating the javascript queries, we need to add a few events to the button component:
|
||||
|
||||
| Event | Action | Description |
|
||||
|
|
@ -60,6 +65,8 @@ Before we start creating the javascript queries, we need to add a few events to
|
|||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
### viewTabs query
|
||||
|
||||
The `viewTabs` query is a javascript query that will run a loop to print data from all the tabs. The query will set a variable `tabIndex` that will store the id of the tab to print data from. he query will loop and increment the tabsIndex variable by 1, using the setVariable action, till the value is less than 5.
|
||||
|
|
@ -72,7 +79,7 @@ if ((variables?.tabIndex ?? undefined) == undefined) {
|
|||
}
|
||||
```
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
</div>
|
||||
|
||||
**This query will have 3 events:**
|
||||
|
||||
|
|
@ -84,8 +91,6 @@ For the first Query Success event, we will add a `Control component` action whic
|
|||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/how-to/print-multitabs/q1.png" alt="Print data from multiple tabs" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
#### 2. Query Success:
|
||||
|
|
@ -116,6 +121,8 @@ For the third Query Success event, we will select `Run Query` action which will
|
|||
|
||||
Now that we have created the `viewTabs` query, we can go to the [Download](/docs/how-to/print-multi-tabs-report#printing-data-from-multiple-tabs) button and add the `viewTabs` query to the `On click` event handler.
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
### getTabsHTML query
|
||||
|
||||
The `getTabsHTML` is javascript query that will get the html of the current tab and store it in a variable. The query will have a variable `tabsHtml` that will store the html of all the tabs in the form of an array.
|
||||
|
|
@ -136,6 +143,8 @@ actions.setVariable( // set tabsHtml variable
|
|||
);
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
**This query will have 1 event:**
|
||||
|
|
|
|||
|
|
@ -7,9 +7,9 @@ ToolJet allows you to execute various [actions](/docs/actions/show-alert) within
|
|||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## Run Query Action
|
||||
### Run Query
|
||||
|
||||
**Syntax:**
|
||||
To trigger a query, you can use the below functions:
|
||||
|
||||
```js
|
||||
queries.getSalesData.run()
|
||||
|
|
@ -23,117 +23,144 @@ await actions.runQuery('getSalesData')
|
|||
|
||||
**Example:**
|
||||
|
||||
In the following screenshot, we demonstrate triggering two different queries, `getCustomers` and `updateCustomers`, using the two available syntax options for the `Run Query` action.
|
||||
In the screenshot below, we are triggering two different queries using two different syntax available for `Run Query` action.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/how-to/run-actions-from-runjs/runqueryn.png" alt="Print data from multiple tabs" />
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/how-to/run-actions-from-runjs/runquery-v3.png" alt="Print data from multiple tabs" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## Set Variable Action
|
||||
### Get Query Data
|
||||
|
||||
In the previous section, we saw how we can trigger queries. Once the queries are triggered, if you want to immediately use the data returned by the query inside the RunJS query, you can use the `getData()`, `getRawData()` and `getLoadingState()` functions:
|
||||
|
||||
#### Trigger a query and retrieve its data:
|
||||
|
||||
```js
|
||||
await queries.getSalesData.run();
|
||||
// replace getSalesData with your query name
|
||||
|
||||
let value = queries.getSalesData.getData();
|
||||
// replace getSalesData with your query name
|
||||
```
|
||||
|
||||
#### Trigger a query and retrieve its raw data:
|
||||
|
||||
```js
|
||||
await queries.getCustomerData.run();
|
||||
//replace getCustomerData with your query name
|
||||
|
||||
let value = queries.getCustomerData.getRawData();
|
||||
// replace getCustomerData your with query name
|
||||
```
|
||||
|
||||
#### Trigger a query and retrieve its loading state:
|
||||
|
||||
```js
|
||||
await queries.getTodos.run()
|
||||
//replace getTodos with your query name
|
||||
|
||||
let value = queries.getTodos.getLoadingState();
|
||||
//replace getTodos with your query name
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
### Set Variables
|
||||
|
||||
To create a variable, you can use the below function:
|
||||
|
||||
```javascript
|
||||
actions.setVariable('<variableName>', `<variableValue>`)
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
### Unset Variable
|
||||
|
||||
To delete a created variable, you can use the below function:
|
||||
|
||||
**Syntax:**
|
||||
|
||||
```javascript
|
||||
actions.setVariable(variableName, variableValue);
|
||||
actions.unSetVariable('<variableName>')
|
||||
```
|
||||
|
||||
**Example:**
|
||||
|
||||
In this example, we set two variables, `test` and `test2`. Note that `test` contains a numerical value, so it is not wrapped in quotes, while `test2` is a string and is wrapped in quotes.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/how-to/run-actions-from-runjs/setvariablen.png" alt="Print data from multiple tabs" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## Unset Variable Action
|
||||
### Get Variables
|
||||
|
||||
**Syntax:**
|
||||
To access variables immediately after setting them in a RunJS query, you can use the `getVariable` and `getPageVariable` functions:
|
||||
|
||||
```javascript
|
||||
actions.unSetVariable(variableName);
|
||||
#### Set and retrieve a variable:
|
||||
|
||||
```js
|
||||
actions.setVariable('mode','dark');
|
||||
//replace mode with your desired variable name
|
||||
|
||||
return actions.getVariable('mode');
|
||||
```
|
||||
|
||||
**Example:**
|
||||
#### Set and retrieve a page-specific variable:
|
||||
```js
|
||||
actions.setPageVariable('number',1);
|
||||
//replace number with your desired variable name
|
||||
|
||||
In the following screenshot, we unset the variable `test2` that was created in the previous step.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/how-to/run-actions-from-runjs/unsetvarn.png" alt="Print data from multiple tabs" />
|
||||
</div>
|
||||
return actions.getPageVariable('number');
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## Logout Action
|
||||
### Logout
|
||||
|
||||
**Syntax:**
|
||||
To log out the current logged-in user from the ToolJet, use the below function:
|
||||
|
||||
```javascript
|
||||
actions.logout();
|
||||
```
|
||||
|
||||
**Example:**
|
||||
|
||||
Executing `actions.logout()` will log out the current user from ToolJet and redirect to the sign-in page.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/how-to/run-actions-from-runjs/logoutn.png" alt="Print data from multiple tabs" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## Show Modal Action
|
||||
### Show Modal
|
||||
|
||||
**Syntax:**
|
||||
To open a modal using RunJS query, use the below function:
|
||||
|
||||
```javascript
|
||||
actions.showModal('modalName');
|
||||
actions.showModal('<modalName>')
|
||||
```
|
||||
|
||||
**Example:**
|
||||
|
||||
In this example, a modal named `formModal` is present on the canvas, and we use a RunJS query to show the modal.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/how-to/run-actions-from-runjs/showmodaln.png" alt="Print data from multiple tabs" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## Close Modal Action
|
||||
### Close Modal
|
||||
|
||||
**Syntax:**
|
||||
To close a modal using RunJS query, use the below function:
|
||||
|
||||
```javascript
|
||||
actions.closeModal('modalName');
|
||||
actions.closeModal('<modalName>')
|
||||
```
|
||||
|
||||
**Example:**
|
||||
|
||||
Here, we use a RunJS query to close the modal that was shown in the previous step.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/how-to/run-actions-from-runjs/closemodaln.png" alt="Print data from multiple tabs" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## Set Local Storage Action
|
||||
### Set Local Storage
|
||||
|
||||
Set a value in local storage using the below code:
|
||||
|
||||
**Syntax:**
|
||||
|
||||
|
|
@ -141,166 +168,101 @@ Here, we use a RunJS query to close the modal that was shown in the previous ste
|
|||
actions.setLocalStorage('key', 'value');
|
||||
```
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/how-to/run-actions-from-runjs/setlocaln.png" alt="Print data from multiple tabs" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## Copy to Clipboard Action
|
||||
### Copy to Clipboard
|
||||
|
||||
**Syntax:**
|
||||
Use the below code to copy content to the clipboard:
|
||||
|
||||
```javascript
|
||||
actions.copyToClipboard('contentToCopy');
|
||||
actions.copyToClipboard('<contentToCopy>')
|
||||
```
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/how-to/run-actions-from-runjs/copytoclip.png" alt="Print data from multiple tabs" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## Generate File Action
|
||||
### Generate File
|
||||
|
||||
**Syntax:**
|
||||
The below action can be used to generate a file.
|
||||
|
||||
```js
|
||||
actions.generateFile('fileName', 'fileType', 'data');
|
||||
actions.generateFile('<fileName>', '<fileType>', '<data>')
|
||||
```
|
||||
|
||||
Example for generating a CSV file:
|
||||
`fileName` is the name that you want to give the file(string), `fileType` can be **csv**, **plaintext**, or **pdf** and `data` is the data that you want to store in the file.
|
||||
|
||||
Example for generating CSV file:
|
||||
|
||||
```js
|
||||
actions.generateFile('csvfile1', 'csv', '{{components.table1.currentPageData}}')
|
||||
actions.generateFile('csvfile1', 'csv', '{{components.table1.currentPageData}}') // generate a csv file named csvfile1 with the data from the current page of table
|
||||
```
|
||||
|
||||
Example for generating a Text file:
|
||||
Example for generating Text file:
|
||||
|
||||
```js
|
||||
actions.generateFile('textfile1', 'plaintext', '{{JSON.stringify(components.table1.currentPageData)}}');
|
||||
actions.generateFile('textfile1', 'plaintext', '{{JSON.stringify(components.table1.currentPageData)}}') // generate a text file named textfile1 with the data from the current page of table (stringified)
|
||||
```
|
||||
|
||||
Example for generating a PDF file:
|
||||
Example for generating PDF file:
|
||||
|
||||
```js
|
||||
actions.generateFile('Pdffile1', 'pdf', '{{components.table1.currentPageData}}');
|
||||
actions.generateFile('Pdffile1', 'pdf', '{{components.table1.currentPageData}}') // generate a text file named Pdffile1 with the data from the current page of table
|
||||
```
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/how-to/run-actions-from-runjs/generatefilen.png" alt="Print data from multiple tabs" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## Go to App Action
|
||||
### Go to App
|
||||
|
||||
**Syntax:**
|
||||
You can switch to a different application using the below action:
|
||||
|
||||
```javascript
|
||||
actions.goToApp('slug', queryparams)
|
||||
actions.goToApp('slug',queryparams)
|
||||
```
|
||||
|
||||
- `slug` can be found in the URL of the released app after the `application/`, or in the `Share` modal. You can also set a custom slug for the app in the `Share` modal or from the global settings in the app builder.
|
||||
- `queryparams` can be provided like this `[{"key":"value"}, {"key2":"value2"}]`.
|
||||
- Only the apps that are released can be accessed using this action.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/how-to/run-actions-from-runjs/gotoappn.png" alt="Print data from multiple tabs" />
|
||||
</div>
|
||||
- `slug` can be found in URL of the released app after `application/` or in the share modal that opens up when you click on the `Share` button on the top-right of the app-builder
|
||||
- `queryparams` can be provided in this format - `[{"key":"value"}, {"key2":"value2"}]`
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## Show Alert Action
|
||||
### Show Alert
|
||||
|
||||
**Syntax:**
|
||||
To show an alert using RunJS query, use the below code:
|
||||
|
||||
```js
|
||||
actions.showAlert(alertType, message); // alert types are info, success, warning, and error
|
||||
actions.showAlert('<alert type>' , '<message>' )
|
||||
```
|
||||
|
||||
**Example:**
|
||||
Available alert types are `info`, `success`, `warning`, and `danger`.
|
||||
|
||||
Example:
|
||||
```js
|
||||
actions.showAlert('error', 'This is an error')
|
||||
actions.showAlert('error' , 'This is an error' )
|
||||
```
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/how-to/run-actions-from-runjs/showalertn.png" alt="Print data from multiple tabs" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## Run Multiple Actions from RunJS Query
|
||||
### Run Multiple Actions From RunJS Query
|
||||
|
||||
To run multiple actions from a RunJS query, use **async-await** in the function. Here's an example code snippet for running queries and showing an alert at specific intervals:
|
||||
To run multiple actions from a RunJS query, you'll have to use **async-await** in the function.
|
||||
|
||||
Here is a example code snippet for running the queries and showing alert after specific intervals. Check the complete guide on running queries at specified intervals **[here](/docs/how-to/run-query-at-specified-intervals)**.
|
||||
|
||||
```js
|
||||
actions.setVariable('interval', setInterval(countdown, 5000));
|
||||
|
||||
async function countdown() {
|
||||
await queries.restapi1.run();
|
||||
await queries.restapi2.run();
|
||||
await actions.showAlert('info', 'This is an information');
|
||||
actions.setVariable('interval',setInterval(countdown, 5000));
|
||||
async function countdown(){
|
||||
await queries.restapi1.run()
|
||||
await queries.restapi2.run()
|
||||
await actions.showAlert('info','This is an information')
|
||||
}
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## Actions on pages
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
### Switch page
|
||||
|
||||
To switch to a page from the JavaScript query, use the following syntax:
|
||||
|
||||
```js
|
||||
await actions.switchPage('<page-handle>')
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
### Switch page with query parameters
|
||||
|
||||
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 (?). Multiple parameters are separated by an ampersand (&).
|
||||
|
||||
To switch to a page with query parameters from the JavaScript query, use the following syntax:
|
||||
|
||||
```js
|
||||
actions.switchPage('<pageHandle>', [['param1', 'value1'], ['param2', 'value2']])
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
### 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.
|
||||
|
||||
To set a page variable from the JavaScript query, use the following syntax:
|
||||
|
||||
```js
|
||||
await actions.setPageVariable('<variablekey>',<variablevalue>)
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
This enhanced guide provides a detailed walkthrough of executing various ToolJet actions from RunJS queries.
|
||||
|
|
@ -1,11 +1,16 @@
|
|||
---
|
||||
id: run-query-at-specified-intervals
|
||||
title: Run query at specified intervals
|
||||
title: Run Query at Specified Intervals
|
||||
---
|
||||
<div style={{paddingBottom:'24px'}}>
|
||||
|
||||
In this guide, we'll walk through the process of building a ToolJet application that automates data retrieval at specific intervals. By utilizing the RunJS queries, we can set up intervals for triggering queries, ensuring that the data is fetched dynamically and efficiently.
|
||||
|
||||
## Step 1: Create a new application
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## Step 1: Create a New Application
|
||||
|
||||
Begin by creating a new application in the ToolJet dashboard. Once the app builder opens, Drag a table component onto the canvas. This component will display the data fetched from the REST API query.
|
||||
|
||||
|
|
@ -13,6 +18,10 @@ Begin by creating a new application in the ToolJet dashboard. Once the app build
|
|||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/how-to/setinterval/table.png" alt="Table Component With Data" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## Step 2: Set Up a REST API Query
|
||||
|
||||
From the query panel, create a new REST API query. Utilize mock REST API data by choosing the 'GET' method and specifying the endpoint (e.g., `https://jsonplaceholder.typicode.com/posts`). Name the query 'post' and `Run` the query to ensure that the data is fetched successfully.
|
||||
|
|
@ -21,6 +30,10 @@ From the query panel, create a new REST API query. Utilize mock REST API data by
|
|||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/how-to/setinterval/queryprev.png" alt="Table Component With Data" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## Step 3: Configure Table Properties
|
||||
|
||||
In the Table properties, link the query data to the table by setting the 'table data' property to `{{queries.post.data}}`. This establishes the connection between the REST API query and the table component.
|
||||
|
|
@ -29,6 +42,10 @@ In the Table properties, link the query data to the table by setting the 'table
|
|||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/how-to/setinterval/queryp.png" alt="Table Component With Data" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## Step 4: Implement the RunJS Query
|
||||
|
||||
Create a RunJS query to set up intervals for triggering the REST API query. Use the following script:
|
||||
|
|
@ -52,6 +69,10 @@ async function countdown(){
|
|||
}
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## Step 5: Advanced Configuration
|
||||
|
||||
|
||||
|
|
@ -61,6 +82,10 @@ From the Settings section of the RunJS query, enable 'Run query on page load.' T
|
|||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/how-to/setinterval/settings.png" alt="Table Component With Data" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## Step 6: Prevent Indefinite Triggering
|
||||
|
||||
Create another RunJS query named 'clearInrternal' to stop the query from triggering indefinitely. Use the `clearInterval()` method to clear the interval. This method retrieves the value from the variable set in the 'setInterval' query.
|
||||
|
|
@ -69,6 +94,10 @@ Create another RunJS query named 'clearInrternal' to stop the query from trigger
|
|||
clearInterval(variables.interval);
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## Step 7: Add a Button
|
||||
|
||||
Drag a button on the canvas to act as a user-triggered stop mechanism. Attach an event handler to execute the 'clear' query when the button is clicked.
|
||||
|
|
@ -77,6 +106,8 @@ Drag a button on the canvas to act as a user-triggered stop mechanism. Attach an
|
|||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/how-to/setinterval/clearint.png" alt="Table Component With Data" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
By following these steps, your ToolJet application will dynamically fetch data at specified intervals, providing an efficient and automated user experience.
|
||||
|
|
|
|||
|
|
@ -1,18 +1,22 @@
|
|||
---
|
||||
id: s3-custom-endpoints
|
||||
title: Use custom endpoint for s3 hosts
|
||||
title: Use Custom Endpoint for S3 Hosts
|
||||
---
|
||||
<div style={{paddingBottom:'24px'}}>
|
||||
|
||||
In this how-to guide, we will see how we can connect to different **S3 compatible object storages** using the custom endpoint. In this guide, we are using Minio since it is an S3-compatible object storage.
|
||||
|
||||
- Go to the ToolJet dashboard, and create a new application
|
||||
- On the left-sidebar, go to the **Sources** and add a new AWS S3 datasource
|
||||
- Now the connection modal will pop-up
|
||||
<div style={{textAlign: 'center'}}>
|
||||
- Now the connection modal will pop-up.
|
||||
|
||||
<img className="screenshot-full" src="/img/how-to/s3-custom/connection.png" alt="Custom Endpoint - S3 hosts" width="500" />
|
||||
<div style={{textAlign: 'left'}}>
|
||||
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/how-to/s3-custom/connection.png" alt="Custom Endpoint - S3 hosts" width="500" />
|
||||
|
||||
</div>
|
||||
- To get the **Credentials** which is **Access Key** and **Secret Key**, you'll need to go to the Minio console to generate the keys
|
||||
- Enable the **Custom Endpoint** toggle switch, and enter the custom host URL i.e where your Minio server API is exposed
|
||||
- Once entered the details, you can click on the **Test Connection** button to check the connection
|
||||
- Once entered the details, you can click on the **Test Connection** button to check the connection
|
||||
|
||||
</div>
|
||||
|
|
@ -1,89 +1,92 @@
|
|||
---
|
||||
id: use-server-side-pagination
|
||||
title: Using server side pagination for efficient data handling in tables
|
||||
title: Using Server Side Pagination in Tables
|
||||
---
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
<div style={{paddingBottom:'24px'}}>
|
||||
|
||||
In this guide we will learn how to use server side pagination in table component. This will be helpful if you have a large data set and you want to load data in chunks. This will also help you to improve the performance of your application. This guide will be helpful if you are using data sources like MySQL, PostgreSQL, MSSQL, MongoDB, etc. in which you can use `limit` and `offset` to fetch data in chunks. We have also included an example to load data from Google Sheets in chunks.
|
||||
In this guide, we will implement server-side pagination for large datasets in a table component to enhance application performance. This guide is applicable for databases like MySQL, PostgreSQL, MSSQL, MongoDB, etc., supporting `limit` and `offset` for chunked data retrieval.
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
### Loading data from PostgreSQL in chunks
|
||||
### Loading Data from PostgreSQL in Chunks
|
||||
|
||||
- Let's say you have a table `users` in your PostgreSQL database and you want to load data from this table in chunks. You can use `limit` and `offset` to fetch data in chunks. Here is the SQL query to fetch data in chunks:
|
||||
```sql title="PostgreSQL query"
|
||||
SELECT *
|
||||
FROM users
|
||||
ORDER BY id
|
||||
LIMIT 100 OFFSET {{(components.table1.pageIndex-1)*100}};
|
||||
```
|
||||
To fetch data in chunks from a PostgreSQL table `users`, use `limit` and `offset` in the SQL query:
|
||||
|
||||
```sql title="PostgreSQL query"
|
||||
SELECT *
|
||||
FROM users
|
||||
ORDER BY id
|
||||
LIMIT 100 OFFSET {{(components.table1.pageIndex-1)*100}};
|
||||
```
|
||||
|
||||
The query will fetch 100 rows at a time from the postgresql users table, and the number of rows returned is determined by the current value of `pageIndex`(exposed variable) in the Table component.
|
||||
The query will fetch 100 rows at a time from the PostgreSQL users table, and the number of rows returned is determined by the current value of `pageIndex`(exposed variable) in the Table component.
|
||||
|
||||
The following is the breakdown of the above PostgreSQL query:
|
||||
|
||||
- `ORDER BY id`: Orders the result set by the id column.
|
||||
|
||||
- `LIMIT 100`: Limits rows returned to 100 per query.
|
||||
|
||||
- `OFFSET {{(components.table1.pageIndex-1)*100}}`: Determines the starting row number based on the current page index for pagination.
|
||||
|
||||
|
||||
To obtain the count of records in the users table, execute the following query:
|
||||
|
||||
1. `ORDER BY id`: This part of the query specifies the ordering of the result set. It orders the rows based on the `id` column. You can replace `id` with the appropriate column name based on how you want the rows to be ordered.
|
||||
|
||||
2. `LIMIT 100`: The `LIMIT` clause limits the number of rows returned to 100. This means that each time the query is executed, it will fetch 100 rows from the table.
|
||||
|
||||
3. `OFFSET {{(components.table1.pageIndex-1)*100}}`: The `OFFSET` clause determines where to start fetching rows from the result set. In this case, the offset value is calculated based on the `pageIndex`(exposed variable) in the Table component. The formula `(components.table1.pageIndex-1)*100` calculates the starting row number for the current page. Since the index is 1-based, we subtract 1 from `pageIndex` to convert it to a 0-based index. Then we multiply it by 100 to get the offset for the current page. For example, if `pageIndex` is 1, the offset will be 0, which means it will fetch rows from the first 100 rows. If `pageIndex` is 2, the offset will be 100, which means it will fetch rows from rows 101 to 200, and so on.
|
||||
```sql
|
||||
SELECT COUNT(*)
|
||||
FROM users;
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
- Create a new query that will return the count of the records on the `users` table in postgresql db. This query will be used to calculate the total number of pages in the Table component. Here is the SQL query to fetch the count of records:
|
||||
|
||||
```sql
|
||||
SELECT COUNT(*)
|
||||
FROM users;
|
||||
```
|
||||
|
||||
- Enable the option to run the query on page load so that the query is executed when the app loads.
|
||||
- Add an event handler to run the query that fetches data from the PostgreSQL table and then save the changes.
|
||||
- Once the count query is created, execute it to get the total number of records. You can dynamically access the count of records using `{{queries.<countquery>.data[0].count}}`.
|
||||
### Edit the Table Component
|
||||
|
||||
</div>
|
||||
**Follow the steps below to edit the properties of the Table component:**
|
||||
|
||||
### Edit the Table component
|
||||
- Drag the table component to the canvas from the components library and set the value of the **Data** property to `{{queries.<postgresquery>.data}}` to populate the table with the relevant data.
|
||||
|
||||
**Now, let's edit the properties of the Table component:**
|
||||
|
||||
- Set the value of the **Table data** property to `{{queries.<postgresquery>.data}}`
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/how-to/server-side/data.png" alt="Table data" />
|
||||
</div>
|
||||
|
||||
- Enable the **Server-side pagination** option
|
||||
- Enable the **Server-side pagination** option.
|
||||
- Click on the `Fx` next to **Enable previous page button** and set the value as below. This condition disables the previous page button when the current page is page `1`.
|
||||
|
||||
```js
|
||||
{{components.table1.pageIndex >=2 ? true : false}}
|
||||
```
|
||||
- Click on the `Fx` next to **Enable next page button** and set it's value as below. This condition disables the next page button when the current page is the last page.
|
||||
```js
|
||||
{{components.table1.pageIndex < queries.<countquery>.data[0].count/100 ? true : false}}
|
||||
```
|
||||
- Set the value of the **Total records server side** property as below. This will set the total number of records in the Table component.
|
||||
```js
|
||||
{{queries.<countquery>.data[0].count}}
|
||||
```
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/how-to/server-side/pagination.png" alt="Table data" />
|
||||
</div>
|
||||
|
||||
- Now, the last step is to set the **loading state** and add the **event handler**:
|
||||
- **Loading State**: This will show the loading indicator on the table component when the query is executing. Set the loading state property as:
|
||||
```js
|
||||
{{queries.<postgresquery>.isLoading}}
|
||||
```
|
||||
- **Event Handler**: Select the **Page changed** event and choose the **Run Query** action. Then, select the **Query** from the dropdown that fetches data from the PostgreSQL table
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/how-to/server-side/event.png" alt="Table data" />
|
||||
</div>
|
||||
- Click on the `Fx` next to **Enable next page button** and set it's value as below. This condition disables the next page button when the current page is the last page.
|
||||
```js
|
||||
{{components.table1.pageIndex < queries.<countquery>.data[0].count/100 ? true : false}}
|
||||
```
|
||||
|
||||
- Set the value of the **Total records server side** property as below. This will set the total number of records in the Table component.
|
||||
```js
|
||||
{{queries.<countquery>.data[0].count}}
|
||||
```
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img style={{ width:'100%', border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/how-to/server-side/pagination-v2.png" alt="Table data" />
|
||||
</div>
|
||||
|
||||
|
||||
- To add the loading indicator on the table component while executing the query, set the `Loading state` property as:
|
||||
|
||||
```js
|
||||
{{queries.<postgresquery>.isLoading}}
|
||||
```
|
||||
- Select the **Page changed** event and choose the **Run Query** action, after clicking the `New event handler`. Then, select the **Query** from the dropdown that fetches data from the PostgreSQL table.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img style={{ width: '100%', border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/how-to/server-side/event-v2.png" alt="Table data" />
|
||||
</div>
|
||||
|
||||
Now, whenever the page is changed, the query will be executed, and the data will be fetched from the PostgreSQL table in chunks.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/how-to/server-side/change.gif" alt="Table data" />
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/how-to/server-side/change-v2.gif" alt="Table data" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -2,9 +2,14 @@
|
|||
id: setup-rsyslog
|
||||
title: Setup Log File Generation (Rsyslog)
|
||||
---
|
||||
<div style={{paddingBottom:'24px'}}>
|
||||
|
||||
The log file serves as a comprehensive record of audit logs, capturing crucial information about various activities within the ToolJet. Follow the guide below to set up and utilize the log file feature effectively.
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## Activation and Configuration
|
||||
|
||||
### 1. Environment Variable Setup
|
||||
|
|
@ -27,6 +32,10 @@ The log file serves as a comprehensive record of audit logs, capturing crucial i
|
|||
|
||||
- This step ensures that the server recognizes the new configuration and begins recording audit logs.
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## Log Rotation and Organization
|
||||
|
||||
### 3. Daily Log Rotation
|
||||
|
|
@ -87,4 +96,6 @@ The log file feature automatically creates a folder in the home path with the sp
|
|||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/how-to/setup-rsyslog/folder.png" alt="Setup log file generation" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
|
@ -1,9 +1,8 @@
|
|||
---
|
||||
id: upload-files-aws
|
||||
title: Upload files on AWS S3 bucket
|
||||
title: Upload and Download Files on AWS S3 Bucket
|
||||
---
|
||||
|
||||
# Upload and download files on AWS S3 bucket
|
||||
<div style={{paddingBottom:'24px'}}>
|
||||
|
||||
This guide will help you in quickly building a basic UI for uploading or downloading files from AWS S3 buckets.
|
||||
|
||||
|
|
@ -22,6 +21,10 @@ Once you have successfully added the AWS data source, build a basic UI using the
|
|||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## Queries
|
||||
|
||||
We'll create the following queries:
|
||||
|
|
@ -31,6 +34,10 @@ We'll create the following queries:
|
|||
3. **uploadToS3**
|
||||
4. **download**
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
### getBuckets
|
||||
|
||||
This query will fetch the list of all the buckets in your S3. Just create a new query, select AWS S3 data source, and choose **List buckets** operation. Name the query **getBuckets** and click **Save**.
|
||||
|
|
@ -44,17 +51,21 @@ This query will fetch the list of all the buckets in your S3. Just create a new
|
|||
Now, let's edit the properties of **dropdown** widget.
|
||||
|
||||
- **Label**: Set the label as Bucket.
|
||||
- **Option values**: Set option values as `{{queries.getBuckets.data.Buckets.map(bucket => bucket['Name'])}}`. We're mapping the data returned by the query as the returned data is array of abjects.
|
||||
- **Option values**: Set option values as `{{queries.getBuckets.data.Buckets.map(bucket => bucket['Name'])}}`. We're mapping the data returned by the query as the returned data is array of objects.
|
||||
- **Option label**: Set option values as `{{queries.getBuckets.data.Buckets.map(bucket => bucket['Name'])}}`. This will display the same option label as option values.
|
||||
|
||||
You can later add an event handler for running the **listObject** query whenever an option is selected from the dropdown.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<div style={{textAlign: 'left'}}>
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
### listObjects
|
||||
|
||||
This query will list all the objects inside the selected Bucket in dropdown. Select **List objects in a bucket** operation, enter `{{components.dropdown1.value}}` in the Bucket field - this will dynamically get the field value from the selected option in dropdown.
|
||||
|
|
@ -79,6 +90,10 @@ Edit the properties of **table** widget:
|
|||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
### download
|
||||
|
||||
Create a new query and select **Signed URL for download** operation. In the Bucket field, enter `{{components.dropdown1.value}}` and in Key enter `{{components.table1.selectedRow.Key}}`.
|
||||
|
|
@ -91,11 +106,15 @@ Create a new query and select **Signed URL for download** operation. In the Buck
|
|||
|
||||
Edit the **properties** of the table, add a Event handler for running the `download` query for `Row clicked` event. This will generate a signed url for download every time a row is clicked on the table.
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
### uploadToS3
|
||||
|
||||
Create a new query, select the **Upload object** operation. Enter the following values in their respective fields:
|
||||
- **Bucket**: `{{components.dropdown1.value}}`
|
||||
- **Key**: {{ components.textinput1.value + '/' +components.filepicker1.file[0].name}}`
|
||||
- **Key**: `{{ components.textinput1.value + '/' +components.filepicker1.file[0].name}}`
|
||||
- **Content type**: `{{components.filepicker1.file[0].type}}`
|
||||
- **Upload data**: `{{components.filepicker1.file[0].base64Data}}`
|
||||
- **Encoding**: `base64`
|
||||
|
|
@ -106,7 +125,11 @@ Create a new query, select the **Upload object** operation. Enter the following
|
|||
|
||||
</div>
|
||||
|
||||
#### Configure the file picker:
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
#### Configure the File Picker:
|
||||
|
||||
Click on the widget handle to edit the file picker properties:
|
||||
|
||||
|
|
@ -128,10 +151,12 @@ Click on the widget handle to edit the file picker properties:
|
|||
To accept any/all file type(s), set `Accept file types` to an empty value.
|
||||
:::
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<div style={{textAlign: 'left'}}>
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
Final steps, go to the **Advanced** tab of the **uploadToS3** query and add a query to run **listObjects** query so that whenever a file is uploaded the tabled is refreshed.
|
||||
Final steps, go to the **Advanced** tab of the **uploadToS3** query and add a query to run **listObjects** query so that whenever a file is uploaded the tabled is refreshed.
|
||||
|
||||
</div>
|
||||
|
|
@ -1,15 +1,18 @@
|
|||
---
|
||||
id: upload-files-gcs
|
||||
title: Upload files using GCS
|
||||
title: Upload Files Using GCS
|
||||
---
|
||||
|
||||
# Upload files using GCS
|
||||
<div style={{paddingBottom:'24px'}}>
|
||||
|
||||
In this guide, we are going to create an interface to upload PDFs to Google Cloud Storage.
|
||||
|
||||
Before adding the new data source we will need to have a private key for our GCS bucket and make sure the key has the appropriate rights.
|
||||
|
||||
## Setting up Google Cloud Storage data source
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## Setting up Google Cloud Storage Data Source
|
||||
|
||||
1. Go to the data source manager on the left-sidebar and click on the `+` button.
|
||||
2. Add a new GCS data source from the **APIs** section in modal that pops up.
|
||||
|
|
@ -22,7 +25,11 @@ Before adding the new data source we will need to have a private key for our GCS
|
|||
|
||||
</div>
|
||||
|
||||
## Adding a file picker
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## Adding a File Picker
|
||||
|
||||
1. Drag and drop the **file picker** widget on the canvas
|
||||
2. Configure the file picker:
|
||||
|
|
@ -44,13 +51,17 @@ Before adding the new data source we will need to have a private key for our GCS
|
|||
To accept any/all file type(s), set `Accept file types` to an empty value.
|
||||
:::
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<div style={{textAlign: 'left'}}>
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
## Creating a query
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## Creating a Query
|
||||
|
||||
1. Click on the `+` button of the query manager at the bottom panel of the editor and select the GCS data source
|
||||
2. Select **Upload file** operation and enter the required parameters:
|
||||
|
|
@ -61,7 +72,11 @@ Before adding the new data source we will need to have a private key for our GCS
|
|||
- Encoding: `base64`
|
||||
3. Click on **Save** to create the query
|
||||
|
||||
## Running the query
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## Running the Query
|
||||
1. Add a **button** that will fire the query to upload the file
|
||||
2. Edit the properties of the button and add a **event handler** to **Run the query** on **On-Click** event.
|
||||
3. Click on **Button** to fire the query, this will upload the pdf file that you selected earlier through the file picker and will upload it on the GCS.
|
||||
|
|
@ -70,4 +85,6 @@ Before adding the new data source we will need to have a private key for our GCS
|
|||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
|
@ -2,9 +2,14 @@
|
|||
id: use-axios-in-runjs
|
||||
title: Use Axios in RunJS
|
||||
---
|
||||
<div style={{paddingBottom:'24px'}}>
|
||||
|
||||
ToolJet supports three libraries: **Moment.js**, **Lodash**, and **Axios**. This guide focuses on using the Axios library with RunJS queries. **[Axios](https://axios-http.com/docs/intro)** is a promise-based HTTP client for making requests to your own or external servers. It supports various request types like `GET`, `POST`, `PUT/PATCH`, and `DELETE`.
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## GET Requests
|
||||
|
||||
We'll use **[JSONPlaceholder](https://jsonplaceholder.typicode.com/)**, a free API, to demonstrate GET and PUT requests.
|
||||
|
|
@ -23,10 +28,14 @@ return data
|
|||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/how-to/use-axios/get.png" alt="Use Axios in RunJS"/>
|
||||
<img style={{ border:'0', marginBottom:'15px' }} className="screenshot-full" src="/img/how-to/use-axios/get.png" alt="Use Axios in RunJS"/>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## POST Requests
|
||||
|
||||
- Create a RunJS query and paste the code below:
|
||||
|
|
@ -56,3 +65,4 @@ To see Axios in action in a project, check out this tutorial:
|
|||
**[Build GitHub star history tracker](https://blog.tooljet.com/build-github-stars-history-app-in-5-minutes-using-low-code/)**.
|
||||
|
||||
|
||||
</div>
|
||||
|
|
@ -2,9 +2,12 @@
|
|||
id: use-custom-parameters
|
||||
title: Use Custom Parameters
|
||||
---
|
||||
<div style={{paddingBottom:'24px'}}>
|
||||
|
||||
Custom parameters in your queries offer a flexible way to introduce variables without directly modifying query parameters. This guide will walk you through creating, utilizing, and calling queries with custom parameters.
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
### Adding Custom Parameters
|
||||
|
|
@ -36,7 +39,7 @@ Use `parameters.<identifier>` in your query to employ custom parameters. Note th
|
|||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
### Example: Create row in ToolJetDB with Custom Parameters
|
||||
### Example: Create Row in ToolJetDB with Custom Parameters
|
||||
|
||||
Let's assume we have a ToolJetDB table with the following columns: `name`, `email`, and `contact`. We will create a new row in the table using custom parameters.
|
||||
|
||||
|
|
@ -47,13 +50,9 @@ Let's assume we have a ToolJetDB table with the following columns: `name`, `emai
|
|||
2. **name:** `email` and **value:** `shubh@email.com`
|
||||
3. **name:** `contact` and **value:** `4638563845`
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/how-to/custom-parameters/params1.png" alt="How to: use custom parameters" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
- Add the columns to the query and use the custom parameters to set the values.
|
||||
|
||||
|
|
@ -62,22 +61,18 @@ Let's assume we have a ToolJetDB table with the following columns: `name`, `emai
|
|||
| name | `{{parameters.name}}` |
|
||||
| email | `{{parameters.email}}` |
|
||||
| contact| `{{parameters.contact}}` |
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/how-to/custom-parameters/params2.png" alt="How to: use custom parameters" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
- Finally, execute the query to create a new row in the ToolJetDB table with the values provided in the custom parameters.
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
### Example: Providing Custom Parameters using Events
|
||||
### Example: Providing Custom Parameters Using Events
|
||||
|
||||
In this example, we will demonstrate how to use custom parameters in a query by providing values from an event. We will use execute a REST API query and on its success, we will execute the ToolJetDB query to create a new row with the response data.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,21 +1,33 @@
|
|||
---
|
||||
id: use-events-on-chart
|
||||
title: Use Events on Chart
|
||||
title: Use Events on Chart Created Through Custom Component
|
||||
---
|
||||
<div style={{paddingBottom:'24px'}}>
|
||||
|
||||
Currently, the chart component does not support events. However, you can use the Custom Component to create a chart using a third-party library that supports events. Plotly is one of the libraries that supports events. In this tutorial, we will build a chart using Plotly and add events to it.
|
||||
This guide will use the Custom Component to create a chart using a third-party library that supports events. Plotly is one of the libraries that supports events. In this tutorial, we will build a chart using Plotly and add events.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img style={{ border:'0'}} className="screenshot-full" src="/img/how-to/events-chart/plotly-chart.png" alt="Plotly Chart" />
|
||||
<img style={{ marginBottom:'15px', border:'0'}} className="screenshot-full" src="/img/how-to/events-chart/plotly-chart-v2.png" alt="Plotly Chart" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## Step 1: Add a Custom Component
|
||||
|
||||
Open the App Builder and add a Custom Component to the page. Then, click on the Custom Component to open the Properties panel.
|
||||
- Open the App Builder and add a Custom Component to the page.
|
||||
- Click on the Custom Component to open the Properties panel.
|
||||
|
||||
Note: If you are not familiar with the Custom Component, please read the [Custom Component](/docs/widgets/custom-component/) doc.
|
||||
Note: If you are not familiar with the Custom Component, please read the [Custom Component](/docs/widgets/custom-component/)documentation.
|
||||
|
||||
## Step 2: Add the code to the Custom Component
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## Step 2: Add the Code to the Custom Component
|
||||
|
||||
In the Code section of the `Custom Component` properties, add the following code:
|
||||
|
||||
```js
|
||||
import React from 'https://cdn.skypack.dev/react';
|
||||
|
|
@ -24,111 +36,98 @@ import { Button, Container } from 'https://cdn.skypack.dev/@material-ui/core';
|
|||
import Plotly from 'https://cdn.skypack.dev/plotly.js-basic-dist-min';
|
||||
import createPlotlyComponent from 'https://cdn.skypack.dev/react-plotly.js/factory';
|
||||
|
||||
const MyCustomComponent = ({data, updateData, runQuery}) => {
|
||||
const Plot = createPlotlyComponent(Plotly);
|
||||
// Define the custom component
|
||||
const MyCustomComponent = ({ data, updateData, runQuery }) => {
|
||||
// Create Plot component using Plotly
|
||||
const Plot = createPlotlyComponent(Plotly);
|
||||
|
||||
const barOnClick = ({points}) => {
|
||||
alert('A bar is clicked')
|
||||
}
|
||||
return (
|
||||
<Container>
|
||||
<Plot data={[
|
||||
{
|
||||
"name": "Inbound",
|
||||
"type": "bar",
|
||||
"x": [
|
||||
20,
|
||||
14,
|
||||
23,
|
||||
22,
|
||||
30,
|
||||
12,
|
||||
15,
|
||||
26,
|
||||
31,
|
||||
16,
|
||||
18,
|
||||
29
|
||||
],
|
||||
"y": [
|
||||
"Jan",
|
||||
"Feb",
|
||||
"Mar",
|
||||
"Apr",
|
||||
"May",
|
||||
"Jun",
|
||||
"Jul",
|
||||
"Aug",
|
||||
"Sep",
|
||||
"Oct",
|
||||
"Nov",
|
||||
"Dec"
|
||||
],
|
||||
"marker": {
|
||||
"line": {
|
||||
"color": "rgba(55, 128, 191, 1.0)",
|
||||
"width": 1
|
||||
},
|
||||
"color": "rgba(55, 128, 191, 0.6)"
|
||||
},
|
||||
"orientation": "h"
|
||||
},
|
||||
{
|
||||
"name": "Outbound",
|
||||
"type": "bar",
|
||||
"x": [
|
||||
12,
|
||||
18,
|
||||
29,
|
||||
22,
|
||||
14,
|
||||
23,
|
||||
15,
|
||||
23,
|
||||
26,
|
||||
13,
|
||||
27,
|
||||
12
|
||||
],
|
||||
"y": [
|
||||
"Jan",
|
||||
"Feb",
|
||||
"Mar",
|
||||
"Apr",
|
||||
"May",
|
||||
"Jun",
|
||||
"Jul",
|
||||
"Aug",
|
||||
"Sep",
|
||||
"Oct",
|
||||
"Nov",
|
||||
"Dec"
|
||||
],
|
||||
"marker": {
|
||||
"line": {
|
||||
"color": "rgba(255, 153, 51, 1.0)",
|
||||
"width": 1
|
||||
},
|
||||
"color": "rgba(255, 153, 51, 0.6)"
|
||||
},
|
||||
"orientation": "h"
|
||||
}
|
||||
]}
|
||||
layout={{
|
||||
width: 840,
|
||||
height: 800,
|
||||
title: "Tickets Resolved: Inbound & Outbound",
|
||||
showlegend: false,
|
||||
}}
|
||||
onClick={barOnClick}
|
||||
/>
|
||||
</Container>
|
||||
)}
|
||||
// Define onClick handler for bars
|
||||
const barOnClick = ({ points }) => {
|
||||
alert('A bar is clicked');
|
||||
};
|
||||
|
||||
// Render the component
|
||||
return (
|
||||
<Container>
|
||||
<Plot
|
||||
data={[
|
||||
{
|
||||
name: 'Inbound',
|
||||
type: 'bar',
|
||||
x: [20, 14, 23, 22, 30, 12, 15, 26, 31, 16, 18, 29],
|
||||
y: [
|
||||
'Jan',
|
||||
'Feb',
|
||||
'Mar',
|
||||
'Apr',
|
||||
'May',
|
||||
'Jun',
|
||||
'Jul',
|
||||
'Aug',
|
||||
'Sep',
|
||||
'Oct',
|
||||
'Nov',
|
||||
'Dec',
|
||||
],
|
||||
marker: {
|
||||
line: {
|
||||
color: 'rgba(55, 128, 191, 1.0)',
|
||||
width: 1,
|
||||
},
|
||||
color: 'rgba(55, 128, 191, 0.6)',
|
||||
},
|
||||
orientation: 'h',
|
||||
},
|
||||
{
|
||||
name: 'Outbound',
|
||||
type: 'bar',
|
||||
x: [12, 18, 29, 22, 14, 23, 15, 23, 26, 13, 27, 12],
|
||||
y: [
|
||||
'Jan',
|
||||
'Feb',
|
||||
'Mar',
|
||||
'Apr',
|
||||
'May',
|
||||
'Jun',
|
||||
'Jul',
|
||||
'Aug',
|
||||
'Sep',
|
||||
'Oct',
|
||||
'Nov',
|
||||
'Dec',
|
||||
],
|
||||
marker: {
|
||||
line: {
|
||||
color: 'rgba(255, 153, 51, 1.0)',
|
||||
width: 1,
|
||||
},
|
||||
color: 'rgba(255, 153, 51, 0.6)',
|
||||
},
|
||||
orientation: 'h',
|
||||
},
|
||||
]}
|
||||
layout={{
|
||||
width: 840,
|
||||
height: 800,
|
||||
title: 'Tickets Resolved: Inbound & Outbound',
|
||||
showlegend: false,
|
||||
}}
|
||||
onClick={barOnClick}
|
||||
/>
|
||||
</Container>
|
||||
);
|
||||
};
|
||||
|
||||
// Connect the component
|
||||
const ConnectedComponent = Tooljet.connectComponent(MyCustomComponent);
|
||||
|
||||
// Render the connected component to the DOM
|
||||
ReactDOM.render(<ConnectedComponent />, document.body);
|
||||
```
|
||||
|
||||
Let's understand the code above in detail. First, we imported the required libraries.
|
||||
**The steps to implement the above code is as follows:**
|
||||
|
||||
- Import the required libraries.
|
||||
|
||||
```js
|
||||
import React from 'https://cdn.skypack.dev/react'; // React library
|
||||
|
|
@ -139,7 +138,8 @@ import createPlotlyComponent from 'https://cdn.skypack.dev/react-plotly.js/facto
|
|||
```
|
||||
|
||||
|
||||
Then, we created a function component called `MyCustomComponent`. This component will render the chart. We use the `createPlotlyComponent` function to create a Plotly component. Then, we create a function called `barOnClick` that will be called when the user clicks on the bar. This function will display an alert message.
|
||||
- Create a function component called `MyCustomComponent`. This component will render the chart. The `createPlotlyComponent` function is used to create a Plotly component.
|
||||
- A function called `barOnClick` is created that will be called when the user clicks on the bar. This function will display an alert message.
|
||||
|
||||
```js
|
||||
const MyCustomComponent = ({data, updateData, runQuery}) => { // function component
|
||||
|
|
@ -150,113 +150,92 @@ const Plot = createPlotlyComponent(Plotly); // create a Plotly component
|
|||
}
|
||||
```
|
||||
|
||||
Next, we render the chart using the `Plot` component. We pass the data and layout to the `Plot` component. We also pass the `barOnClick` function to the `onClick` prop of the `Plot` component.
|
||||
- Render the chart using the `Plot` component. Pass the data and layout to the `Plot` component. Also pass the `barOnClick` function to the `onClick` prop of the `Plot` component.
|
||||
|
||||
```js
|
||||
return ( // return the Plot component
|
||||
<Container> // Material UI Container component
|
||||
<Plot data={[ // Plot component
|
||||
{ // data for the first bar
|
||||
"name": "Inbound",
|
||||
"type": "bar",
|
||||
"x": [
|
||||
20,
|
||||
14,
|
||||
23,
|
||||
22,
|
||||
30,
|
||||
12,
|
||||
15,
|
||||
26,
|
||||
31,
|
||||
16,
|
||||
18,
|
||||
29
|
||||
],
|
||||
"y": [
|
||||
"Jan",
|
||||
"Feb",
|
||||
"Mar",
|
||||
"Apr",
|
||||
"May",
|
||||
"Jun",
|
||||
"Jul",
|
||||
"Aug",
|
||||
"Sep",
|
||||
"Oct",
|
||||
"Nov",
|
||||
"Dec"
|
||||
],
|
||||
"marker": {
|
||||
"line": {
|
||||
"color": "rgba(55, 128, 191, 1.0)",
|
||||
"width": 1
|
||||
},
|
||||
"color": "rgba(55, 128, 191, 0.6)"
|
||||
},
|
||||
"orientation": "h"
|
||||
},
|
||||
{ // data for the second bar
|
||||
"name": "Outbound",
|
||||
"type": "bar",
|
||||
"x": [
|
||||
12,
|
||||
18,
|
||||
29,
|
||||
22,
|
||||
14,
|
||||
23,
|
||||
15,
|
||||
23,
|
||||
26,
|
||||
13,
|
||||
27,
|
||||
12
|
||||
],
|
||||
"y": [
|
||||
"Jan",
|
||||
"Feb",
|
||||
"Mar",
|
||||
"Apr",
|
||||
"May",
|
||||
"Jun",
|
||||
"Jul",
|
||||
"Aug",
|
||||
"Sep",
|
||||
"Oct",
|
||||
"Nov",
|
||||
"Dec"
|
||||
],
|
||||
"marker": {
|
||||
"line": {
|
||||
"color": "rgba(255, 153, 51, 1.0)",
|
||||
"width": 1
|
||||
},
|
||||
"color": "rgba(255, 153, 51, 0.6)"
|
||||
},
|
||||
"orientation": "h"
|
||||
}
|
||||
]}
|
||||
layout={{ // layout for the chart
|
||||
width: 840,
|
||||
height: 800,
|
||||
title: "Tickets Resolved: Inbound & Outbound",
|
||||
showlegend: false,
|
||||
}}
|
||||
onClick={barOnClick} // pass the barOnClick function to the onClick prop
|
||||
/>
|
||||
</Container>
|
||||
)}
|
||||
return (
|
||||
<Container>
|
||||
<Plot
|
||||
data={[
|
||||
{
|
||||
name: 'Inbound',
|
||||
type: 'bar',
|
||||
x: [20, 14, 23, 22, 30, 12, 15, 26, 31, 16, 18, 29],
|
||||
y: ['Jan',
|
||||
'Feb',
|
||||
'Mar',
|
||||
'Apr',
|
||||
'May',
|
||||
'Jun',
|
||||
'Jul',
|
||||
'Aug',
|
||||
'Sep',
|
||||
'Oct',
|
||||
'Nov',
|
||||
'Dec',
|
||||
],
|
||||
marker: {
|
||||
line: {
|
||||
color: 'rgba(55, 128, 191, 1.0)',
|
||||
width: 1,
|
||||
},
|
||||
color: 'rgba(55, 128, 191, 0.6)',
|
||||
},
|
||||
orientation: 'h',
|
||||
},
|
||||
{
|
||||
name: 'Outbound',
|
||||
type: 'bar',
|
||||
x: [12, 18, 29, 22, 14, 23, 15, 23, 26, 13, 27, 12],
|
||||
y: [
|
||||
'Jan',
|
||||
'Feb',
|
||||
'Mar',
|
||||
'Apr',
|
||||
'May',
|
||||
'Jun',
|
||||
'Jul',
|
||||
'Aug',
|
||||
'Sep',
|
||||
'Oct',
|
||||
'Nov',
|
||||
'Dec',
|
||||
],
|
||||
marker: {
|
||||
line: {
|
||||
color: 'rgba(255, 153, 51, 1.0)',
|
||||
width: 1,
|
||||
},
|
||||
color: 'rgba(255, 153, 51, 0.6)',
|
||||
},
|
||||
orientation: 'h',
|
||||
},
|
||||
]}
|
||||
layout={{
|
||||
width: 840,
|
||||
height: 800,
|
||||
title: 'Tickets Resolved: Inbound & Outbound',
|
||||
showlegend: false,
|
||||
}}
|
||||
onClick={barOnClick}
|
||||
/>
|
||||
</Container>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
Finally, we render the `MyCustomComponent` component using the `ReactDOM.render` function.
|
||||
- Render the `MyCustomComponent` component using the `ReactDOM.render` function.
|
||||
|
||||
```js
|
||||
const ConnectedComponent = Tooljet.connectComponent(MyCustomComponent); // connect the component to the Tooljet store
|
||||
ReactDOM.render(<ConnectedComponent />, document.body); // render the component
|
||||
```
|
||||
|
||||
## Step 3: Using events from the Custom Component
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## Step 3: Using Events from the Custom Component
|
||||
|
||||
In the code above, we created a function called `barOnClick` that will be called when the user clicks on the bar. This function holds the code that will be executed when the user clicks on the bar.
|
||||
|
||||
|
|
@ -274,4 +253,6 @@ const barOnClick = ({points}) => {
|
|||
}
|
||||
```
|
||||
|
||||
`runQuery` is a function which accepts a query name as a string used to run the query from the custom component. Learn more about the custom component [here](/docs/widgets/custom-component/).
|
||||
`runQuery` is a function which accepts a query name as a string used to run the query from the custom component. Learn more about the custom component [here](/docs/widgets/custom-component/).
|
||||
|
||||
</div>
|
||||
|
|
@ -2,18 +2,27 @@
|
|||
id: use-form-component
|
||||
title: Use Form Component
|
||||
---
|
||||
<div style={{paddingBottom:'24px'}}>
|
||||
|
||||
In this guide, we'll create a simple app that uses a **[Form](/docs/widgets/form)** component to add records to a database. We'll use **[ToolJet Database](/docs/tooljet-database)** as our data source.
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingBottom:'24px'}}>
|
||||
|
||||
## 1. Create a Table in ToolJet Database
|
||||
- Create a table named *products* in ToolJet Database.
|
||||
- Create three columns - `name`, `quantity` and `price`.
|
||||
- Add some sample data to the table.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img className="screenshot-full" src="/img/how-to/use-form/database-table.png" alt="Database Table" width="100%" />
|
||||
<img style={{ border:'0', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/how-to/use-form/database-table.png" alt="Database Table" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## 2. Create the UI
|
||||
- Create a new app and drag and drop a **[Table](/docs/widgets/table)** component on the canvas.
|
||||
- Drop a **[Form](/docs/widgets/form)** next to it.
|
||||
|
|
@ -21,10 +30,14 @@ In this guide, we'll create a simple app that uses a **[Form](/docs/widgets/form
|
|||
- Name the three input fields on the form as - *nameInput*, *quantityInput* and *priceInput*. Name the button as *submitButton*.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img className="screenshot-full" src="/img/how-to/use-form/user-interface.png" alt="User Interface" width="100%" />
|
||||
<img style={{ border:'0', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/how-to/use-form/user-interface.png" alt="User Interface" />
|
||||
</div>
|
||||
<i>Naming the components can help in easily identifying or referring individual components when there are a large number of components in the app</i>.
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## 3. Load the Table Component With Data
|
||||
|
||||
- Click on the Add button in the **[Query Panel](/docs/app-builder/query-panel/)**, select ToolJet Database
|
||||
|
|
@ -37,9 +50,13 @@ In this guide, we'll create a simple app that uses a **[Form](/docs/widgets/form
|
|||
{{queries.getProducts.data}}
|
||||
```
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img className="screenshot-full" src="/img/how-to/use-form/load-data.png" alt="Table with Data" width="100%" />
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/how-to/use-form/load-data.png" alt="Table with Data" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## 4. Write Data Using the Form Component
|
||||
- Click on the Add button in the Query Panel, select ToolJet Database
|
||||
- Select *products* as Table name, Create row as Operations
|
||||
|
|
@ -80,4 +97,6 @@ Now if you enter the product data on the form and click on Submit. The `addProdu
|
|||
</div>
|
||||
<br/>
|
||||
|
||||
In this how-to guide, we have explored a practical application of the Form component in ToolJet. You can apply the same principles for a variety of use cases that requires data input from the end-user.
|
||||
In this how-to guide, we have explored a practical application of the Form component in ToolJet. You can apply the same principles for a variety of use cases that requires data input from the end-user.
|
||||
|
||||
</div>
|
||||
|
|
@ -2,13 +2,18 @@
|
|||
id: use-inspector
|
||||
title: Use Inspector in App-Builder
|
||||
---
|
||||
<div style={{paddingBottom:'24px'}}>
|
||||
|
||||
This guide introduces **Inspector** in the app-builder, a feature that lets you view data related to queries, components, global variables, page-related variables, user-set variables and constants.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img className="screenshot-full" src="/img/how-to/use-inspector/use-inspector-preview.png" alt="Preview of Use Inspector" width="100%" />
|
||||
<img style={{ border:'0', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/how-to/use-inspector/use-inspector-preview.png" alt="Preview of Use Inspector" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## Sections
|
||||
|
||||
The Inspector panel has 6 main sections:
|
||||
|
|
@ -20,16 +25,26 @@ The Inspector panel has 6 main sections:
|
|||
- **[Page](#page)**
|
||||
- **[Constants](#constants)**
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
### Queries
|
||||
|
||||
Queries allow you to inspect the specifics of your queries. However, the data related to these queries will only be visible after they have been executed or triggered.
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
### Components
|
||||
|
||||
Under Components, you can view and analyze the properties and values of the components you've added to the canvas, providing insights into how each component functions within your app.
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
### Globals
|
||||
|
||||
Globals give you access to global information related to the app.
|
||||
|
|
@ -47,13 +62,25 @@ The globals selection consists of the following data:
|
|||
All the global variables can be accessed anywhere within ToolJet applications. Here's an **[example use-case](/docs/how-to/access-currentuser)** that demonstrates the usage of these variables.
|
||||
:::
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
### Variables
|
||||
|
||||
Variables shows user-defined variables in a key-value format. These variables, set through event handlers or queries, are accessible across the entire application. You can set variables from the [event handler](/docs/actions/set-variable) or using [JavaScript code](/docs/how-to/run-actions-from-runjs#set-variable).
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
### Page
|
||||
Page lets you view page-specific properties like page name, handle and variables. Page variables are restricted to their respective pages and are not accessible application-wide.
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
### Constants
|
||||
|
||||
Under **[Constants](/docs/org-management/workspaces/workspace_constants/)**, you can find the predefined values (usually tokens/secret keys/API keys) that can be used across your application to maintain consistency and facilitate easy updates.
|
||||
|
|
@ -61,3 +88,5 @@ Under **[Constants](/docs/org-management/workspaces/workspace_constants/)**, you
|
|||
:::info
|
||||
The **environment** and **mode** variables are only available in **ToolJet Enterprise Edition v2.2.3** and above.
|
||||
:::
|
||||
|
||||
</div>
|
||||
|
|
@ -1,173 +1,138 @@
|
|||
---
|
||||
id: use-s3-signed-url-to-upload-docs
|
||||
title: Use S3 signed URL to upload documents
|
||||
title: Use S3 Signed URL to Upload Documents
|
||||
---
|
||||
<div style={{paddingBottom:'24px'}}>
|
||||
|
||||
# Use S3 signed URL to upload documents
|
||||
In this how-to guide, we will upload documents to S3 buckets using the **S3 signed URL** from a ToolJet application.
|
||||
|
||||
In this how-to guide, you'll learn to upload documents to S3 buckets using the **S3 signed URL** from a ToolJet application.
|
||||
For this guide, we are going to use one of the existing templates on ToolJet: **S3 File explorer**
|
||||
|
||||
For this guide, We are going to use one of the existing templates on ToolJet: **S3 File explorer**
|
||||
</div>
|
||||
|
||||
:::info using Templates
|
||||
On ToolJet Dashboard, Click on the down arrow on the right of the **New App** button, from the dropdown choose the **Choose from template** option.
|
||||
:::
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
## Create an App Using Templates
|
||||
|
||||
<img className="screenshot-full" src="/img/how-to/uses3presignedurl/template.png" alt="Use S3 pre-signed URL to upload documents: Choose template" width="700"/>
|
||||
- On ToolJet Dashboard, click on the ellipses on the right of the **Create new app** button, from the dropdown choose the **Choose from template** option. Select **AWS S3 file explorer** and click on the **Create application from template**.
|
||||
|
||||
|
||||
<div style={{textAlign: 'left'}}>
|
||||
|
||||
<img style={{ border:'0', marginBottom:'15px' }} className="screenshot-full" src="/img/how-to/uses3presignedurl/template-v2.png" alt="Use S3 pre-signed URL to upload documents: Choose template" width="700"/>
|
||||
|
||||
</div>
|
||||
|
||||
- Once you've created a new app using the template, you'll be prompted to create a **new version** of the existing version. After creating a new version, you'll be able to make changes in the app.
|
||||
- Go to the **Data sources** on the left-sidebar; you'll find that the **AWS S3 data source** has already been added. All you need to do is update the data source credentials.
|
||||
|
||||
:::tip
|
||||
Check the [AWS S3 data source reference](/docs/data-sources/s3) to learn more about connnection and choosing your preferred authentication method.
|
||||
:::
|
||||
|
||||
<div style={{textAlign: 'left'}}>
|
||||
|
||||
<img style={{ border:'0', marginBottom:'15px' }} className="screenshot-full" src="/img/how-to/uses3presignedurl/s3connect-v2.png" alt="Use S3 pre-signed URL to upload documents: add datasource"/>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## Get the Buckets
|
||||
|
||||
- Once the data source is connected successfully, go to the query manager and **Run** the *getBuckets* query. The operation selected in the *getBuckets* query is **List buckets**, which will fetch an array of all the buckets.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/how-to/uses3presignedurl/newversion.png" alt="Use S3 pre-signed URL to upload documents: new version"/>
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/how-to/uses3presignedurl/getbuckets-v2.png" alt="Use S3 pre-signed URL to upload documents: getBuckets query"/>
|
||||
|
||||
</div>
|
||||
|
||||
- Go to the **datasource manager** on the left-sidebar, you'll find that the **AWS S3 datasource** is already added. All you need to do is update the datasource **credentials**.
|
||||
- Running the *getBuckets* query will load all the buckets in the app's left table.
|
||||
|
||||
|
||||
:::tip
|
||||
Check the [AWS S3 datasource reference](/docs/data-sources/s3) to learn more about connnection and choosing your preferred authentication method.
|
||||
:::
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/how-to/uses3presignedurl/s3connect.png" alt="Use S3 pre-signed URL to upload documents: add datasource"/>
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/how-to/uses3presignedurl/dropdown-v2.png" alt="Use S3 pre-signed URL to upload documents: loading buckets"/>
|
||||
|
||||
</div>
|
||||
|
||||
- Once the datasource is connected successfully, go to the query manager and **Run** the **getBuckets** query. The operation selected in the getBuckets query is **List Buckets** which will fetch an array of all the buckets.
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## Get the Objects Inside the Bucket
|
||||
|
||||
- To fetch the data inside a bucket, select the bucket from the buckets table, go to the query manager and choose the *getObjects* query. Choose the relevant data source in the **Data Source** section, and for the **Operation** parameter, choose `List objects in a bucket` option from the dropdown. Replace the **Bucket** parameter with, `{{components.table2.selectedRow.Name}}` and click on the **Run** to list all the files from the selected bucket on the table.
|
||||
|
||||
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/how-to/uses3presignedurl/getbuckets.png" alt="Use S3 pre-signed URL to upload documents: getBuckets query"/>
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/how-to/uses3presignedurl/fetchfiles-v2.png" alt="Use S3 pre-signed URL to upload documents: list objects in a bucket"/>
|
||||
|
||||
</div>
|
||||
|
||||
- Running the **getBuckets** query will load all the buckets in the dropdown in the app.
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## Get the Signed URL for Downlaod
|
||||
|
||||
The object owner can optionally share objects with others by creating a presigned URL, using their own security credentials, to grant time-limited permission to download the objects. For creating a presigned URL, in the query panel replace the parameters with the following:
|
||||
|
||||
- **Data Source**: Use the relevant data source.
|
||||
- **Operation**: Choose `Signed url for download` from the dropdown.
|
||||
- **Bucket**: `{{components.table2.selectedRow.Name}}` to select the buckets dynamically.
|
||||
- **Key**: `{{components.table3.selectedRow.Key}}`, this will get the file name from the filepickers exposed variables.
|
||||
- **Expires in**: This sets an expiration time of URL, by default its `3600` seconds (1 hour).
|
||||
|
||||
After setting up the parameters, click **Run** to run the query, and the URL can be accessed as shown in the screenshot.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/how-to/uses3presignedurl/dropdown.png" alt="Use S3 pre-signed URL to upload documents: loading buckets"/>
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/how-to/uses3presignedurl/get-signed-url.png" alt="Use S3 pre-signed URL to upload documents: get signed URL"/>
|
||||
|
||||
</div>
|
||||
|
||||
- Select a **bucket** from the dropdown and click on the **Fetch files** button to list all the files from the selected bucket on the table. The **Fetch files** button has the event handler added that triggers the **s32** query, the **s32** query uses the **List objects in a bucket** operation, and the bucket field in the query gets the value dynamically from the dropdown.
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## Upload Objects to the Bucket
|
||||
|
||||
The `Upload Object` operation allows users to select a bucket and then upload their chosen data into that bucket. To upload objects in a bucket, follow the steps below:
|
||||
|
||||
- In the query panel navigate to *uploadObject* query.
|
||||
- Choose your relevant data source in the **Data Source** section.
|
||||
- In the **Operation** section, choose `Upload Object` from the dropdown.
|
||||
- In the **Bucket** section, copy the code: `{{components.table2.selectedRow.Name}}`, to choose a bucket dynamically.
|
||||
- In the **Key** section, copy the code: `{{components.textinput2.value}}`.
|
||||
- In the **Content Type** section, copy: `{{components.filepicker1.file[0].type}}`.
|
||||
- In the **Upload data** section, copy: `{{components.filepicker1.file[0].dataURL}}`.
|
||||
|
||||
To make sure the image is uploaded successfully, we can create a new event from the **Events** section.
|
||||
- Under the `Events` section, click on **New event handler**.
|
||||
- From the `Event` dropdown, choose `Query Success`.
|
||||
- From the `Action` dropdown, choose `Show Alert`.
|
||||
- The `Message` can be of your choice, in this example lets write the message as: `Image uploaded successfully`.
|
||||
|
||||
Once the query has been created, choose the desired bucket, click on the **Upload file** button in the app, and upload your desired file to your bucket.
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## Access the Signed URL
|
||||
|
||||
After uploading the file to your bucket, in the files table, click on the **Copy signed URL** button from the **Actions** section of the table, which will copy the URL on the clipboard. You can go to another tab and paste the URL to open the file on the browser.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/how-to/uses3presignedurl/fetchfiles.png" alt="Use S3 pre-signed URL to upload documents: list objects in a bucket"/>
|
||||
<img style={{ border:'0', marginBottom:'15px' }} className="screenshot-full" src="/img/how-to/uses3presignedurl/access-signed-url.png" alt="Use S3 pre-signed URL to upload documents: access signed URL"/>
|
||||
|
||||
</div>
|
||||
|
||||
- Let's go to the **uploadToS3** query and update the field values:
|
||||
- **Operation**: Signed URL for upload
|
||||
- **Bucket**: `{{components.dropdown1.value}}` this will fetch the dynamic value from the dropdown
|
||||
- **Key**: `{{components.filepicker1.file[0].name}}` this will get the file name from the filepickers exposed variables
|
||||
- **Expires in:** This sets an expiration time of URL, by default its `3600` seconds (1 hour)
|
||||
- **Content Type**: `{{components.filepicker1.file[0].type}}` this will get the file type from the filepickers exposed variables
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/how-to/uses3presignedurl/upload.png" alt="Use S3 pre-signed URL to upload documents"/>
|
||||
|
||||
</div>
|
||||
|
||||
- Create two **RunJS** queries:
|
||||
- Create a **runjs1** query and copy-paste the code below. This query gets the **base64data** from the file picker and convert the file's `base64Data` to into `BLOB`, and returns the file object.
|
||||
```js
|
||||
const base64String = components.filepicker1.file[0].base64Data
|
||||
const decodedArray = new Uint8Array(atob(base64String).split('').map(c => c.charCodeAt(0)));
|
||||
const file = new Blob([decodedArray], { type: components.filepicker1.file[0].type });
|
||||
const fileName = components.filepicker1.file[0].name;
|
||||
const fileObj = new File([file], fileName);
|
||||
|
||||
return fileObj
|
||||
```
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/how-to/uses3presignedurl/runjs1.png" alt="Use S3 pre-signed URL to upload documents"/>
|
||||
|
||||
</div>
|
||||
|
||||
- Create another **runjs2** query and copy-paste the code below. This query gets the data(file object) returned by the first runjs query, the url returned by the **uploadToS3** query, and then makes PUT request.
|
||||
```js
|
||||
const file = queries.runjs2.data
|
||||
const url = queries.s31.data.url
|
||||
|
||||
fetch(url, {
|
||||
method: 'PUT',
|
||||
body: file,
|
||||
mode: 'cors',
|
||||
headers: {
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
})
|
||||
.then(response => console.log('Upload successful!'))
|
||||
.catch(error => console.error('Error uploading file:', error));
|
||||
```
|
||||
:::warning Enable Cross Origin Resource Sharing(CORS)
|
||||
- For the file to be uploaded successfully, you will need to add the CORS policies from the **Permissions** tab of your **Bucket** settings. Here's a sample CORS:
|
||||
```json
|
||||
[
|
||||
{
|
||||
"AllowedHeaders": [
|
||||
"*"
|
||||
],
|
||||
"AllowedMethods": [
|
||||
"GET",
|
||||
"PUT",
|
||||
"POST"
|
||||
],
|
||||
"AllowedOrigins": [
|
||||
"*"
|
||||
],
|
||||
"ExposeHeaders": []
|
||||
}
|
||||
]
|
||||
```
|
||||
:::
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/how-to/uses3presignedurl/runjs2.png" alt="Use S3 pre-signed URL to upload documents"/>
|
||||
|
||||
</div>
|
||||
|
||||
- Go to the **uploadToS3**, scroll down and add an event handler to the **uploadToS3** query. Select the **Query Success** event, **Run Query** as the action, and **runjs1** as the query to be triggered. **Save** the query.
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/how-to/uses3presignedurl/eventhandlerupload.png" alt="Use S3 pre-signed URL to upload documents"/>
|
||||
|
||||
</div>
|
||||
|
||||
- Let's go to the **runjs1** query and add the event handler to run a query on query success event, similar to how we did in the previous step. In the event handler, choose **runjs2** query. **Save** the query.
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/how-to/uses3presignedurl/eventhandlerrunjs2.png" alt="Use S3 pre-signed URL to upload documents"/>
|
||||
|
||||
</div>
|
||||
|
||||
- Now, let's go the final query **copySignedURL** that is connected to the table's action button. This query copy's the generated **Signed URL for download** onto the **clipboard**.
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/how-to/uses3presignedurl/copysigned.png" alt="Use S3 pre-signed URL to upload documents"/>
|
||||
|
||||
</div>
|
||||
|
||||
- Now that we have updated all the queries, and connected them through the event handlers. We can go ahead and pick a file from the file picker. Click on the file picker, select a file and then hit the **Upload file to S3** button.
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/how-to/uses3presignedurl/uploadbutton.png" alt="Use S3 pre-signed URL to upload documents"/>
|
||||
|
||||
</div>
|
||||
|
||||
- Once the button is clicked, the **uploadToS3** will triggered along with the **runjs1** and **runjs2** queries in sequence since we added them in the event handlers.
|
||||
|
||||
- You can go to the table and click on the **Copy signed URL** action button on the table, this will trigger the **copySignedURL** query and will copy the URL on the clipboard. You can go to another tab and paste the URL to open the file on the browser.
|
||||
|
||||
</div>
|
||||
|
|
@ -1,10 +1,15 @@
|
|||
---
|
||||
id: use-to-py-function-in-runpy
|
||||
title: "Utilize the to_py() Function in RunPy: Translating JavaScript Objects to Python"
|
||||
title: "Translating JavaScript Objects to Python in RunPy"
|
||||
---
|
||||
<div style={{paddingBottom:'24px'}}>
|
||||
|
||||
This guide demonstrates the utilization of the `to_py()` function in RunPy queries for converting JavaScript objects into their corresponding Python representations.
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## The to_py() Function
|
||||
|
||||
The **to_py()** function within the **Pyodide** library serves as the counterpart to the **to_js()** function. Its purpose is to transform JavaScript objects into their equivalent Python structures. This conversion becomes essential when handling JavaScript objects within the Pyodide environment and manipulating them using Python code.
|
||||
|
|
@ -13,6 +18,10 @@ Similar to **to_js()**, **to_py()** facilitates the mapping and conversion of da
|
|||
|
||||
**Note**: Refer to the **[RunPy](/docs/data-sources/run-py)** documentation for a more in-depth understanding.
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## Using the to_py() Function
|
||||
|
||||
Here's an example demonstrating the application of the to_py() function:
|
||||
|
|
@ -41,6 +50,10 @@ By leveraging to_py(), JavaScript objects can seamlessly transition into Python
|
|||
|
||||
Both **to_js()** and **to_py()** functions offer a convenient means to exchange data between Python and JavaScript in Pyodide, enabling the utilization of both languages' strengths in a unified environment.
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## Why the Use of to_py() is Essential?
|
||||
|
||||
When previewing results in a RunPy query, discrepancies between the JSON and Raw tabs may arise due to the conversion and display mechanisms in Pyodide. By default, **Python dictionaries** are converted to **JavaScript Map objects** in Pyodide, ensuring compatibility between the two languages.
|
||||
|
|
@ -53,4 +66,6 @@ To maintain consistency between JSON and Raw representations, the **to_js()** fu
|
|||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/how-to/to_py/topy.gif" alt="Print data from multiple tabs" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
|
@ -1,7 +1,8 @@
|
|||
---
|
||||
id: use-url-params-on-load
|
||||
title: Use URL Parameters on page load
|
||||
title: Use URL Parameters on Page Load
|
||||
---
|
||||
<div style={{paddingBottom:'24px'}}>
|
||||
|
||||
In this guide, we will learn how to use URL parameters at the time of page load. The URL parameters are used to pass data from one page to another. Currently, we can add URL parameters in the following ways:
|
||||
|
||||
|
|
@ -12,7 +13,11 @@ If a page is opened with URL parameters, you can access them using the `{{global
|
|||
|
||||
Let's take a look at an example below to understand how to use URL parameters on page load.
|
||||
|
||||
## Using URL parameters on page load to execute REST API queries
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## Using URL Parameters on Page Load to Execute REST API Queries
|
||||
|
||||
Create two pages, `Home` and `Dashboard`. When a new app is created, a page named `Home` is created by default. Create a new page named `Dashboard` from the Pages menu in the left sidebar.
|
||||
|
||||
|
|
@ -20,6 +25,10 @@ Create two pages, `Home` and `Dashboard`. When a new app is created, a page name
|
|||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/how-to/use-url-params/pages.png" alt="Use URL Parameters on page load" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## Home and Dashboard Pages
|
||||
|
||||
Add a form component to the `Home` page. The form component will have a text input fields and a button. The text input field will be used to enter the name and the button will be used to navigate to the `Dashboard` page. Let's name the text input field as `email` and the button as `Submit`.
|
||||
|
|
@ -40,11 +49,15 @@ Now, on clicking the `Submit` button, the `Dashboard` page will be opened with t
|
|||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/how-to/use-url-params/urlparams.png" alt="Use URL Parameters on page load" />
|
||||
</div>
|
||||
|
||||
## Queries and binding data
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## Queries and Binding Data
|
||||
|
||||
In the `Dashboard` page, add two table components. We will be loading the data from two different REST API queries on these tables.
|
||||
|
||||
### Query 1: Get products
|
||||
### Query 1: Get Products
|
||||
|
||||
- Create a new REST API query and name it as `products`. We will be using a mock REST API to fetch the data. The URL for the REST API is `https://fakestoreapi.com/products`. Run the query and check the preview to see the returned data.
|
||||
- Go to the `table1` properties, set the value of table data to `{{queries.products.data}}`. This will bind the data returned from the REST API query to the table.
|
||||
|
|
@ -53,7 +66,7 @@ In the `Dashboard` page, add two table components. We will be loading the data f
|
|||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/how-to/use-url-params/table1.png" alt="Use URL Parameters on page load" />
|
||||
</div>
|
||||
|
||||
### Query 2: Get user details
|
||||
### Query 2: Get User Details
|
||||
|
||||
- Create a new REST API query and name it as `users`. We will be using a mock REST API to fetch the data. The URL for the REST API is `https://jsonplaceholder.typicode.com/users`. Run the query and check the preview to see the returned data.
|
||||
- Go to the `table2` properties, set the value of table data to `{{queries.users.data}}`. This will bind the data returned from the REST API query to the table.
|
||||
|
|
@ -62,7 +75,7 @@ In the `Dashboard` page, add two table components. We will be loading the data f
|
|||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/how-to/use-url-params/table2.png" alt="Use URL Parameters on page load" />
|
||||
</div>
|
||||
|
||||
### Query 3: JavaScript code to use URL parameters
|
||||
### Query 3: JavaScript Code To Use URL Parameters
|
||||
|
||||
- Create a new JavaScript code query and name it as `urlparams`. We will be using this query to access the URL parameters and to check if the email parameter is present in the URL, then trigger the REST API queries.
|
||||
|
||||
|
|
@ -91,7 +104,11 @@ async function checkAndRunQuery(timeout) { // Check if URL parameters are availa
|
|||
checkAndRunQuery(5000); // Check if URL parameters are available and run the REST API queries after a timeout of 5 seconds
|
||||
```
|
||||
|
||||
## Dashboard page event handler
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## Dashboard Page Event Handler
|
||||
|
||||
- Finally, go to the Pages menu in the left sidebar and open the menu for the `Dashboard` page.
|
||||
- Select the option to add Event handler and add a new `On page load`, select the option to `Run query` and select the query `urlparams`. This will trigger the JavaScript code query to check if the email parameter is present in the URL and then run the REST API queries whenever the `Dashboard` page is loaded.
|
||||
|
|
@ -100,4 +117,6 @@ checkAndRunQuery(5000); // Check if URL parameters are available and run the RE
|
|||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/how-to/use-url-params/onpageload.png" alt="Use URL Parameters on page load" />
|
||||
</div>
|
||||
|
||||
Now, whenever the user will enter the email in the `Home` page and click the `Submit` button, the `Dashboard` page will be opened with the URL parameter `email` containing the value of the email input field. The JavaScript code query will check if the email parameter is present in the URL and then run the REST API queries to fetch the data. The data will be displayed in the tables on the `Dashboard` page.
|
||||
Now, whenever the user will enter the email in the `Home` page and click the `Submit` button, the `Dashboard` page will be opened with the URL parameter `email` containing the value of the email input field. The JavaScript code query will check if the email parameter is present in the URL and then run the REST API queries to fetch the data. The data will be displayed in the tables on the `Dashboard` page.
|
||||
|
||||
</div>
|
||||
|
|
@ -1,19 +1,19 @@
|
|||
---
|
||||
id: marketplace-overview
|
||||
title: 'Marketplace : Overview'
|
||||
title: 'Marketplace: Overview'
|
||||
---
|
||||
|
||||
# Marketplace : Overview
|
||||
# Marketplace: Overview
|
||||
|
||||
With ToolJet Marketplace, ToolJet users can conveniently add custom plugins (datasources) to their workspaces. This feature enables users to create plugins that cater to their specific needs and integrate them seamlessly with ToolJet.
|
||||
ToolJet Marketplace allows users to enhance their workspaces by adding custom plugins (data sources) tailored to their unique requirements. This functionality facilitates the seamless integration of user-created plugins with ToolJet.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/marketplace/overview/marketplace.png" alt="Marketplace" />
|
||||
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/marketplace/overview/marketplace-v2.png" alt="Marketplace Overview" />
|
||||
</div>
|
||||
|
||||
## Enabling the Marketplace
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## Enabling Marketplace
|
||||
|
||||
To **Enable** the marketplace feature, users need to add the following environment variable to their **[`.env`](/docs/setup/env-vars#marketplace)** file:
|
||||
|
||||
|
|
@ -21,77 +21,70 @@ To **Enable** the marketplace feature, users need to add the following environme
|
|||
ENABLE_MARKETPLACE_FEATURE=true
|
||||
```
|
||||
|
||||
Once the marketplace feature has been activated, a Marketplace icon will appear on the left-hand sidebar of the dashboard, providing users with access to the Marketplace.
|
||||
|
||||
When running ToolJet locally, ensure that all the plugins are available. Specifically, building the marketplace and then starting the server is mandatory.
|
||||
When running ToolJet locally, ensure that all the plugins are available by building marketplace before starting the server.
|
||||
|
||||
:::info Note
|
||||
The user logged-in should be the **Administrator** to access the marketplace page.
|
||||
The logged-in user should be an **Administrator** to access the marketplace page.
|
||||
:::
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/marketplace/overview/icon.png" alt="Marketplace" />
|
||||
|
||||
</div>
|
||||
|
||||
## Installing a plugin
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## Installing a Plugin
|
||||
|
||||
To navigate to the Marketplace page, click on the settings icon on the bottom left of the dashboard, and click on **Marketplace** from the selection menu.
|
||||
|
||||
The Marketplace page will contain two tabs: **Installed** and **Marketplace**.
|
||||
|
||||
Under the **Marketplace** tab, you will see a list of all the available plugins that can be installed on the workspace. To install a plugin, click on the **Install** button on the plugin's card. Once the installation is complete, the status will change from Install to **Installed**.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/marketplace/overview/allplugins.png" alt="Marketplace" />
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/marketplace/overview/allplugins-v2.png" alt="List of All Plugins" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
## Using Marketplace plugins
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## Using Marketplace Plugins
|
||||
|
||||
You can access any installed plugins by following these steps:
|
||||
|
||||
- Navigate to the **Global Datasources** Page.
|
||||
- Click on the **Add new datasource** button.
|
||||
- Open the **Plugins** tab in the modal that appears.
|
||||
- From here, you can connect to any of the plugins that were installed from the Marketplace.
|
||||
- Navigate to the **Data sources** tab in the dashboard.
|
||||
- Scroll down to **Plugins**.
|
||||
|
||||
You can now see the list of installed marketplace plugins that you can configure as data sources.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/marketplace/overview/gdsplugin.png" alt="Marketplace" />
|
||||
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/marketplace/overview/installed-plugins.png" alt="Installed plugins" />
|
||||
</div>
|
||||
|
||||
- After successfully connecting to a plugin, you can access it under the Global Datasource section when creating queries.
|
||||
- After successfully configuring a plugin, you can access it when trying to add a new query from the Query Panel.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/marketplace/overview/query.png" alt="Marketplace" />
|
||||
|
||||
</div>
|
||||
|
||||
## Removing a plugin
|
||||
## Removing a Plugin
|
||||
|
||||
:::caution
|
||||
If you remove a plugin, all the queries associated with it will be eliminated from all the applications.
|
||||
If you remove a plugin, all the queries associated with it will be eliminated from the applications.
|
||||
:::
|
||||
|
||||
To remove a plugin, follow these steps:
|
||||
- Go to the Marketplace page from the dashboard.
|
||||
- Go to the **Installed** tab and click on the **Remove** button next to the plugin that you want to remove.
|
||||
- By doing so, the plugin will be removed from the global datasource section, and no user will be able to establish a connection with it.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/marketplace/overview/remove.png" alt="Marketplace" />
|
||||
|
||||
</div>
|
||||
- Click on the settings icon on the bottom left of the dashboard, and click on `Marketplace` from the selection menu.
|
||||
- On the `Installed` page, click on the `Remove` button of the related plugin that you wish to remove.
|
||||
|
||||
## Available Plugins
|
||||
- **[AWS Redshift](/docs/marketplace/plugins/marketplace-plugin-redshift)**
|
||||
- **[AWS Textract](/docs/marketplace/plugins/marketplace-plugin-textract)**
|
||||
- **[AWS Lambda](/docs/marketplace/plugins/marketplace-plugin-aws-lambda)**
|
||||
- **[Engagespot](/docs/marketplace/plugins/marketplace-plugin-engagespot)**
|
||||
- **[GitHub](/docs/marketplace/plugins/marketplace-plugin-github)**
|
||||
- **[HarperDB](/docs/marketplace/plugins/marketplace-plugin-harperdb)**
|
||||
- **[OpenAI](/docs/marketplace/plugins/marketplace-plugin-openai)**
|
||||
- **[Plivo](/docs/marketplace/plugins/marketplace-plugin-plivo)**
|
||||
|
||||
- **[Pocketbase](/docs/marketplace/plugins/marketplace-plugin-pocketbase)**
|
||||
- **[Supabase](/docs/marketplace/plugins/marketplace-plugin-supabase)**
|
||||
:::info For Plugin Developers
|
||||
Refer to the **[Plugin Development guide](/docs/contributing-guide/marketplace/marketplace-setup)** to learn how to create plugins for the ToolJet Marketplace.
|
||||
:::
|
||||
:::
|
||||
|
||||
</div>
|
||||
119
docs/docs/marketplace/plugins/amazon-redshift.md
Normal file
119
docs/docs/marketplace/plugins/amazon-redshift.md
Normal file
|
|
@ -0,0 +1,119 @@
|
|||
---
|
||||
id: marketplace-plugin-redshift
|
||||
title: Amazon Redshift
|
||||
---
|
||||
|
||||
ToolJet can connect to Amazon Redshift, enabling your applications to query data directly from a Redshift cluster.
|
||||
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/marketplace/plugins/redshift/install.gif" alt="Marketplace Plugin: Amazon Redshift" />
|
||||
</div>
|
||||
|
||||
<br/>
|
||||
|
||||
**NOTE:** **Before following this guide, it is assumed that you have already completed the process of [Using Marketplace plugins](/docs/marketplace/marketplace-overview#using-marketplace-plugins)**.
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## Configuration
|
||||
|
||||
To connect to Amazon Redshift, you need to provide the following details:
|
||||
|
||||
#### Required Parameters
|
||||
|
||||
- **Region**: The region where your Redshift cluster is located. For example, `us-east-1`.
|
||||
- **Database Name**: The name of the database you want to connect to.
|
||||
- **Authentication Type**: The type of authentication you want to use to connect to the Redshift cluster. Currently, only **IAM** is supported.
|
||||
- **Access Key**: The access key of the user you want to use to connect to the Redshift cluster.
|
||||
- **Secret Key**: The secret key of the user you want to use to connect to the Redshift cluster.
|
||||
|
||||
#### Optional Parameters
|
||||
|
||||
- **Port**: The port number of the Redshift cluster. The default port number is `5439`.
|
||||
- **Workgroup name**: The name of the workgroup you want to use to connect to the Redshift cluster.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/marketplace/plugins/redshift/creds.png" alt="Marketplace Plugin: Amazon Redshift" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## Supported Queries
|
||||
|
||||
Redshift supports a comprehensive set of SQL commands. You can use the SQL editor to run any SQL query on the connected Redshift cluster. Refer to the [Redshift documentation](https://docs.aws.amazon.com/redshift/latest/dg/c_SQL_commands.html) for more information on the supported SQL commands.
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
### Read Data
|
||||
|
||||
The following example demonstrates how to read data from a table in the connected Redshift cluster. The query selects all the columns from the `employee` table.
|
||||
|
||||
```sql
|
||||
SELECT * FROM employee
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
### Write Data
|
||||
|
||||
The following example demonstrates how to write data to a table in the connected Redshift cluster. The query inserts a new row into the `employee` table.
|
||||
|
||||
```sql
|
||||
INSERT INTO employee (
|
||||
first_name,
|
||||
last_name,
|
||||
email,
|
||||
phone_number,
|
||||
hire_date,
|
||||
job_title,
|
||||
salary,
|
||||
department_id
|
||||
) VALUES (
|
||||
'Tom',
|
||||
'Hudson',
|
||||
'tom.hudson@example.com',
|
||||
'234843294323',
|
||||
'2024-01-01',
|
||||
'Test Automation Engineer',
|
||||
245000.00,
|
||||
12
|
||||
);
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
### Update Data
|
||||
|
||||
The following example demonstrates how to update data in a table in the connected Redshift cluster. The query updates the `first_name` and `last_name` columns of the `employee` table.
|
||||
|
||||
```sql
|
||||
UPDATE employee
|
||||
SET first_name = 'Glenn',
|
||||
last_name = 'Jacobs'
|
||||
WHERE employee_id = 8;
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
### Delete Data
|
||||
|
||||
The following example demonstrates how to delete data from a table in the connected Redshift cluster. The query deletes a row from the `employee` table.
|
||||
|
||||
```sql
|
||||
DELETE FROM employee
|
||||
WHERE employee_id = 7;
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
122
docs/docs/marketplace/plugins/engagespot.md
Normal file
122
docs/docs/marketplace/plugins/engagespot.md
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
---
|
||||
id: marketplace-plugin-engagespot
|
||||
title: Engagespot
|
||||
---
|
||||
|
||||
# Engagespot
|
||||
|
||||
ToolJet connects to your Engagespot account, allowing you to send notifications, create or update users from within your ToolJet application.
|
||||
|
||||
:::info
|
||||
**NOTE:** **Before following this guide, it is assumed that you have already completed the process of [Using Marketplace plugins](/docs/marketplace/marketplace-overview#using-marketplace-plugins)**.
|
||||
:::
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## Connection
|
||||
|
||||
- Establish a connection to Engagespot by either clicking `+Add new Data source` on the query panel or navigating to the [Data Sources](/docs/data-sources/overview/) page from the ToolJet dashboard.
|
||||
|
||||
- Enter your Engagespot API key and API secret into their designated fields. To generate user tokens directly from ToolJet, you can optionally provide a signing key.
|
||||
|
||||
- Click **Test Connection** to validate your credentials. Click **Save** to store the data source.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/marketplace/plugins/engagespot/engagespot_install.png" alt="Engagespot API Key" />
|
||||
</div>
|
||||
|
||||
|
||||
:::info
|
||||
You can change your Engagespot BaseURL by enable custom endpoint.
|
||||
:::
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## Querying Engagespot
|
||||
|
||||
Click on `+Add` button of the [query manager](/docs/app-builder/query-panel/#add) and select the data source added in the previous step as the data source. Select the operation that you want to perform, fill in the required parameters and click on **Run** button to run the query.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/marketplace/plugins/engagespot/engagespot_query.png" alt="engagespot query" />
|
||||
|
||||
</div>
|
||||
|
||||
<br/>
|
||||
|
||||
:::info
|
||||
Query results can be transformed using transformations. Read our [transformations documentation](/docs/tutorial/transformations).
|
||||
:::
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## Query Operations
|
||||
|
||||
You can create query for Engagespot data source to perform several actions such as:
|
||||
1. **[Create or Update User](#create-or-update-user)**
|
||||
2. **[Send Notification](#send-notification)**
|
||||
3. **[Generate User Token](#generate-user-token)**
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
### Create OR Update User
|
||||
|
||||
#### Required Parameters:
|
||||
- **User Identifier** - Unique user identifier.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img className="screenshot-full" src="/img/marketplace/plugins/engagespot/create_user.png" alt="engagespot create user" />
|
||||
</div>
|
||||
<br/>
|
||||
|
||||
:::info
|
||||
The user profile column accepts any key-value pairs in valid JSON object format.
|
||||
:::
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
### Send Notification
|
||||
|
||||
#### Required Parameters:
|
||||
- **Reciepient** - Unique user identifier.
|
||||
- **Notification Title** - The title for your notification.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/marketplace/plugins/engagespot/send_notification.png" alt="engagespot send notitication"/>
|
||||
</div>
|
||||
<br/>
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
### Generate User Token
|
||||
|
||||
#### Required Parameters:
|
||||
- **User Identifier** - Unique user identifier.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img className="screenshot-full" src="/img/marketplace/plugins/engagespot/generate_token.png" alt="engagespot generate token" />
|
||||
</div>
|
||||
<br/>
|
||||
|
||||
:::info
|
||||
To generate user tokens, ensure you provide a Signing Key when establishing a connection to your Engagespot data source.
|
||||
:::
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
### Adding the In-App Inbox element to your Tooljet app
|
||||
To set up an In-App Inbox element in your ToolJet application, refer to the [Adding In-App](https://docs.engagespot.co/docs/plugins/tooljet/adding-the-inbox-component) guide.
|
||||
|
||||
</div>
|
||||
|
|
@ -3,103 +3,63 @@ id: marketplace-plugin-github
|
|||
title: GitHub
|
||||
---
|
||||
|
||||
ToolJet can connect to GitHub account to read and write data. In order for ToolJet to access and manipulate data on GitHub, a **GitHub Personal Access Token** is necessary to authenticate and interact with the GitHub API.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/marketplace/plugins/github/githubadd.gif" alt="Marketplace: GitHub" />
|
||||
|
||||
</div>
|
||||
|
||||
:::note
|
||||
Before following this guide, it is assumed that you have already completed the process of **[Using Marketplace plugins](/docs/marketplace/marketplace-overview#using-marketplace-plugins)**.
|
||||
:::
|
||||
ToolJet offers seamless integration with GitHub. This connection allows you to directly interact with GitHub repositories and data.
|
||||
|
||||
## Connection
|
||||
|
||||
For connecting to GitHub, following credentials are required:
|
||||
- **Personal Access Token**: Generate a Personal Access Token from your **[GitHub Account Settings](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token)**
|
||||
To connect to GitHub, you need the following credential:
|
||||
- **Personal Access Token**: You can generate this token through your **[GitHub Account Settings](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token)**.
|
||||
|
||||
:::caution
|
||||
If a Personal Access Token is not provided, the data from the private repositories will not be retrieved via the GitHub Plugin. However, the public repositories data can still be retrieved.
|
||||
:::
|
||||
You'll need a Personal Access Token to access data from private repositories. Public repository data remains accessible without a Personal Access Token.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/marketplace/plugins/github/connection.png" alt="Marketplace: GitHub" />
|
||||
|
||||
<img className="screenshot-full" src="/img/marketplace/plugins/github/connection-v2.png" alt="Marketplace: GitHub" />
|
||||
</div>
|
||||
|
||||
## Supported queries
|
||||
## Supported Queries
|
||||
|
||||
- **[Get user info](#get-user-info)**
|
||||
- **[Get repository](#get-repository)**
|
||||
- **[Get repository issues](#get-repository-issues)**
|
||||
- **[Get repository pull requests](#get-repository-pull-requests)**
|
||||
|
||||
### Get User Info
|
||||
|
||||
This operation fetches details for a specified user.
|
||||
|
||||
#### Required Parameters:
|
||||
|
||||
- **Username**: Specify the GitHub username or organization to retrieve their details.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/marketplace/plugins/github/list.png" alt="Marketplace: GitHub" />
|
||||
|
||||
<img className="screenshot-full" src="/img/marketplace/plugins/github/getuserinfo-v2.png" alt="Marketplace: GitHub" />
|
||||
</div>
|
||||
|
||||
### Get user info
|
||||
### Get Repository
|
||||
|
||||
All the details regarding the user is retrieved by running this query.
|
||||
Fetches detailed information about a specific repository.
|
||||
|
||||
#### Required parameters:
|
||||
#### Required Parameters:
|
||||
|
||||
- **Username**: To obtain the details, the username of the user must be provided for this field. You can input the username of a GitHub organization or a user for this field.
|
||||
- **Owner**: Name of the repository's owner, which can be either a GitHub user or an organization.
|
||||
- **Repository**: The exact name of the repository.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
### Get Repository Issues
|
||||
|
||||
<img className="screenshot-full" src="/img/marketplace/plugins/github/getuserinfo.png" alt="Marketplace: GitHub" />
|
||||
Generates a list of issues associated with a repository, with options to filter them by their status.
|
||||
|
||||
</div>
|
||||
#### Required Parameters:
|
||||
|
||||
### Get repository
|
||||
- **Owner**: The name of the repository's owner. The owner can either be a GitHub organization or a user.
|
||||
- **Repository**: The repository name for which the issues are to be retrieved.
|
||||
- **State**: Filter the issues by their status: All, Open, or Closed.
|
||||
|
||||
All the details regarding the repository are retrieved by running this query.
|
||||
### Get Repository Pull Requests
|
||||
|
||||
#### Required parameters:
|
||||
Generates a list of pull requests from a repository, with options to filter them by their status.
|
||||
|
||||
- **Owner**: The owner's name of the repository is required for this field. The owner can either be a GitHub organization or a user.
|
||||
- **Repository**: Provide the name of the repository of which you want to retrieve the details.
|
||||
#### Required Parameters:
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/marketplace/plugins/github/getrepo.png" alt="Marketplace: GitHub" />
|
||||
|
||||
</div>
|
||||
|
||||
### Get repository issues
|
||||
|
||||
Running this query will retrieve a list of issues from a repository. You can select whether to obtain All, Open, or Closed issues.
|
||||
|
||||
#### Required parameters:
|
||||
|
||||
- **Owner**: The owner's name of the repository is required for this field. The owner can either be a GitHub organization or a user.
|
||||
- **Repository**: Provide the name of the repository of which you want to retrieve the issues.
|
||||
- **State**: Choose the state of the issues that you would like to retrieve: All, Open, or Closed.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/marketplace/plugins/github/getissues.png" alt="Marketplace: GitHub" />
|
||||
|
||||
</div>
|
||||
|
||||
### Get repository pull requests
|
||||
|
||||
Running this query will retrieve a list of pull requests from a repository. You can select whether to obtain All, Open, or Closed issues.
|
||||
|
||||
#### Required parameters:
|
||||
|
||||
- **Owner**: The owner's name of the repository is required for this field. The owner can either be a GitHub organization or a user.
|
||||
- **Repository**: Provide the name of the repository of which you want to retrieve the pull requests.
|
||||
- **State**: Choose the state of the pull requests that you would like to retrieve: All, Open, or Closed.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/marketplace/plugins/github/getpr.png" alt="Marketplace: GitHub" />
|
||||
|
||||
</div>
|
||||
- **Owner**: The name of the repository's owner. The owner can either be a GitHub organization or a user.
|
||||
- **Repository**: The repository name for which the pull requests are to be retrieved.
|
||||
- **State**: Filter the pull requests by their status: All, Open, or Closed.
|
||||
|
|
@ -7,7 +7,7 @@ HarperDB is a database and application development platform that is focused on p
|
|||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/marketplace/plugins/harperdb/harperconnect.gif" alt="Marketplace: HarperDB" />
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/marketplace/plugins/harperdb/harperconnect.gif" alt="Marketplace: HarperDB" />
|
||||
|
||||
</div>
|
||||
|
||||
|
|
@ -15,6 +15,8 @@ HarperDB is a database and application development platform that is focused on p
|
|||
Before following this guide, it is recommended to check the following doc: **[Using Marketplace plugins](/docs/marketplace/marketplace-overview#using-marketplace-plugins)**.
|
||||
:::
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## Connection
|
||||
|
||||
To establish a connection with HarperDB, you need the following credentials:
|
||||
|
|
@ -26,20 +28,28 @@ To establish a connection with HarperDB, you need the following credentials:
|
|||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/marketplace/plugins/harperdb/creds.png" alt="Marketplace: HarperDB" />
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/marketplace/plugins/harperdb/creds.png" alt="Marketplace: HarperDB" />
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## Querying HarperDB
|
||||
To perform queries on HarperDB, click the `+Add` button in the query manager located at the bottom panel of the app builder. Select the HarperDB from the Global Datasource section in the query editor.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/marketplace/plugins/harperdb/query.png" alt="Marketplace: HarperDB" />
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/marketplace/plugins/harperdb/query.png" alt="Marketplace: HarperDB" />
|
||||
|
||||
</div>
|
||||
|
||||
### SQL mode
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
### SQL Mode
|
||||
|
||||
SQL mode enables you to perform various operations on the database using SQL statements.
|
||||
|
||||
|
|
@ -58,7 +68,7 @@ SELECT * FROM sampleorg.people WHERE id = 1
|
|||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/marketplace/plugins/harperdb/select.png" alt="Marketplace: HarperDB" />
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/marketplace/plugins/harperdb/select.png" alt="Marketplace: HarperDB" />
|
||||
|
||||
</div>
|
||||
|
||||
|
|
@ -72,7 +82,7 @@ INSERT INTO sampleorg.people (id, name, age, country, hobby) VALUE (5, 'Shubh',
|
|||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/marketplace/plugins/harperdb/insert.png" alt="Marketplace: HarperDB" />
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/marketplace/plugins/harperdb/insert.png" alt="Marketplace: HarperDB" />
|
||||
|
||||
</div>
|
||||
|
||||
|
|
@ -86,7 +96,7 @@ UPDATE sampleorg.people SET hobby = 'chess' WHERE id = 5
|
|||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/marketplace/plugins/harperdb/update.png" alt="Marketplace: HarperDB" />
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/marketplace/plugins/harperdb/update.png" alt="Marketplace: HarperDB" />
|
||||
|
||||
</div>
|
||||
|
||||
|
|
@ -100,11 +110,15 @@ DELETE FROM sampleorg.people WHERE id = 5
|
|||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/marketplace/plugins/harperdb/delete.png" alt="Marketplace: HarperDB" />
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/marketplace/plugins/harperdb/delete.png" alt="Marketplace: HarperDB" />
|
||||
|
||||
</div>
|
||||
|
||||
### NoSQL mode
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
### NoSQL Mode
|
||||
|
||||
NoSQL mode enables you to perform schema-less storage and retrieval of JSON documents.
|
||||
|
||||
|
|
@ -119,7 +133,7 @@ NoSQL mode enables you to perform schema-less storage and retrieval of JSON docu
|
|||
|
||||
Insert operation allows to add one or more rows of data to a database table.
|
||||
|
||||
| Parameters | Description |
|
||||
| <div style={{ width:"100px"}}> Parameters </div> | <div style={{ width:"100px"}}> Description </div> |
|
||||
| ---------- | ----------- |
|
||||
| Schema (required) | schema where the table you are inserting records into lives |
|
||||
| Table (required) | table name where you want to insert records |
|
||||
|
|
@ -132,7 +146,7 @@ Insert operation allows to add one or more rows of data to a database table.
|
|||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/marketplace/plugins/harperdb/nosql_insert.png" alt="Marketplace: HarperDB" />
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/marketplace/plugins/harperdb/nosql_insert.png" alt="Marketplace: HarperDB" />
|
||||
|
||||
</div>
|
||||
|
||||
|
|
@ -140,7 +154,7 @@ Insert operation allows to add one or more rows of data to a database table.
|
|||
|
||||
The Update operation modifies the values of specified attributes in one or more rows of a database table based on the hash attribute(primary key) that identifies the rows.
|
||||
|
||||
| Parameters | Description |
|
||||
| <div style={{ width:"100px"}}> Parameters </div> | <div style={{ width:"100px"}}> Description </div> |
|
||||
| ---------- | ----------- |
|
||||
| Schema (required) | schema where the table you are updating records into lives |
|
||||
| Table (required) | table name where you want to update records |
|
||||
|
|
@ -153,7 +167,7 @@ The Update operation modifies the values of specified attributes in one or more
|
|||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/marketplace/plugins/harperdb/nosql_update.png" alt="Marketplace: HarperDB" />
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/marketplace/plugins/harperdb/nosql_update.png" alt="Marketplace: HarperDB" />
|
||||
|
||||
</div>
|
||||
|
||||
|
|
@ -161,7 +175,7 @@ The Update operation modifies the values of specified attributes in one or more
|
|||
|
||||
Removes one or more rows of data from a specified table.
|
||||
|
||||
| Parameters | Description |
|
||||
| <div style={{ width:"100px"}}> Parameters </div> | <div style={{ width:"100px"}}> Description </div> |
|
||||
| ---------- | ----------- |
|
||||
| Schema (required) | schema where the table you are deleting records into lives |
|
||||
| Table (required) | table name where you want to delete records |
|
||||
|
|
@ -174,7 +188,7 @@ Removes one or more rows of data from a specified table.
|
|||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/marketplace/plugins/harperdb/nosql_delete.png" alt="Marketplace: HarperDB" />
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/marketplace/plugins/harperdb/nosql_delete.png" alt="Marketplace: HarperDB" />
|
||||
|
||||
</div>
|
||||
|
||||
|
|
@ -182,7 +196,7 @@ Removes one or more rows of data from a specified table.
|
|||
|
||||
Returns data from a table for one or more hash values.
|
||||
|
||||
| Parameters | Description |
|
||||
| <div style={{ width:"100px"}}> Parameters </div> | <div style={{ width:"100px"}}> Description </div> |
|
||||
| ---------- | ----------- |
|
||||
| Schema (required) | schema where the table you are searching lives |
|
||||
| Table (required) | table you wish to search |
|
||||
|
|
@ -201,7 +215,7 @@ Returns data from a table for one or more hash values.
|
|||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/marketplace/plugins/harperdb/searchbyhash.png" alt="Marketplace: HarperDB" />
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/marketplace/plugins/harperdb/searchbyhash.png" alt="Marketplace: HarperDB" />
|
||||
|
||||
</div>
|
||||
|
||||
|
|
@ -209,7 +223,7 @@ Returns data from a table for one or more hash values.
|
|||
|
||||
Returns data from a table for a matching value.
|
||||
|
||||
| Parameters | Description |
|
||||
| <div style={{ width:"100px"}}> Parameters </div> | <div style={{ width:"100px"}}> Description </div> |
|
||||
| ---------- | ----------- |
|
||||
| Schema (required) | schema where the table you are searching lives |
|
||||
| Table (required) | table you wish to search |
|
||||
|
|
@ -237,7 +251,7 @@ Joh* // using wild card
|
|||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/marketplace/plugins/harperdb/searchbyvalue.png" alt="Marketplace: HarperDB" />
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/marketplace/plugins/harperdb/searchbyvalue.png" alt="Marketplace: HarperDB" />
|
||||
|
||||
</div>
|
||||
|
||||
|
|
@ -245,11 +259,11 @@ Joh* // using wild card
|
|||
|
||||
Returns data from a table for one or more matching conditions.
|
||||
|
||||
| Parameters | Description |
|
||||
| <div style={{ width:"100px"}}> Parameters </div> | <div style={{ width:"100px"}}> Description </div> |
|
||||
| ---------- | ----------- |
|
||||
| Schema (required) | schema where the table you are searching lives |
|
||||
| Table (required) | table you wish to search |
|
||||
| Operator inbetween each condition (optional) | the operator used between each condition - 'And', 'Or'. The default is 'And'. |
|
||||
| Operator in-between each condition (optional) | the operator used between each condition - 'And', 'Or'. The default is 'And'. |
|
||||
| Offset (optional) | the number of records that the query results will skip. The default is 0. |
|
||||
| Limit (optional) | the number of records that the query results will include. The default is null, resulting in no limit. |
|
||||
| Table Attributes (required) | define which attributes you want returned. |
|
||||
|
|
@ -267,6 +281,8 @@ Returns data from a table for one or more matching conditions.
|
|||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/marketplace/plugins/harperdb/searchbyconditions.png" alt="Marketplace: HarperDB" />
|
||||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/marketplace/plugins/harperdb/searchbyconditions.png" alt="Marketplace: HarperDB" />
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
|
@ -1,10 +1,12 @@
|
|||
---
|
||||
id: aws-lambda-plugin
|
||||
id: marketplace-plugin-aws-lambda
|
||||
title: AWS Lambda
|
||||
---
|
||||
|
||||
ToolJet can connect to AWS Lambda to run serverless functions.
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## Connection
|
||||
|
||||
To connect to AWS Lambda plugin, you need to provide the following details:
|
||||
|
|
@ -17,7 +19,11 @@ To connect to AWS Lambda plugin, you need to provide the following details:
|
|||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/marketplace/plugins/lambda/awslambdaconfig.png" alt="ToolJet database" />
|
||||
</div>
|
||||
|
||||
## Supported queries
|
||||
</div>
|
||||
|
||||
<div style={{paddingTop:'24px', paddingBottom:'24px'}}>
|
||||
|
||||
## Supported Queries
|
||||
|
||||
### Invoke Lambda Function
|
||||
|
||||
|
|
@ -30,3 +36,4 @@ This query is used to invoke a Lambda function. The following parameters are req
|
|||
<img style={{ border:'0', marginBottom:'15px', borderRadius:'5px', boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)' }} className="screenshot-full" src="/img/marketplace/plugins/lambda/lambdaquery.png" alt="ToolJet database" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
|
@ -3,13 +3,7 @@ id: marketplace-plugin-openai
|
|||
title: OpenAI
|
||||
---
|
||||
|
||||
ToolJet can connect to OpenAI and utilize two main services: Completions and Chat. With OpenAI's Completions service, ToolJet can generate text automatically based on an initial prompt or context. The Chat service allows users to interact with a chatbot powered by OpenAI's language model. In addition, ToolJet can also leverage the GPT-3 Turbo service from OpenAI, which provides faster and more responsive completions.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/marketplace/plugins/openai/openaiadd.gif" alt="Marketplace: openai" />
|
||||
|
||||
</div>
|
||||
ToolJet can integrate with OpenAI to access two main services: Completions and Chat. The Completions service enables ToolJet to produce text from a given prompt or context. Meanwhile, the Chat service facilitates user interaction with an AI-driven chatbot based on OpenAI's language models.
|
||||
|
||||
:::note
|
||||
Before following this guide, it is assumed that you have already completed the process of **[Using Marketplace plugins](/docs/marketplace/marketplace-overview#using-marketplace-plugins)**.
|
||||
|
|
@ -19,12 +13,10 @@ Before following this guide, it is assumed that you have already completed the p
|
|||
|
||||
For connecting to OpenAI, following credentials are required:
|
||||
- **API key**: API key for OpenAI can be generated here: https://platform.openai.com/account/api-keys
|
||||
- **Oganization ID**: Find the Organization ID here: https://platform.openai.com/account/org-settings
|
||||
- **Organization ID**: Find the Organization ID here: https://platform.openai.com/account/org-settings
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/marketplace/plugins/openai/connection.png" alt="Marketplace: openai" />
|
||||
|
||||
<img className="screenshot-full" src="/img/marketplace/plugins/openai/connection-v2.png" alt="Configuring OpenAI in ToolJet" />
|
||||
</div>
|
||||
|
||||
## Supported queries
|
||||
|
|
@ -33,14 +25,12 @@ For connecting to OpenAI, following credentials are required:
|
|||
- **[Chat](#chat)**
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/marketplace/plugins/openai/list.png" alt="Marketplace: openai" />
|
||||
|
||||
<img className="screenshot-full" src="/img/marketplace/plugins/openai/list-v2.png" alt="List of Supported Queries" />
|
||||
</div>
|
||||
|
||||
### Completions
|
||||
|
||||
The purpose of this query is to generate text completions that resemble human writing based on a given prompt.
|
||||
The purpose of this query is to generate text completions based on a given prompt.
|
||||
|
||||
#### Required parameters:
|
||||
|
||||
|
|
@ -48,17 +38,11 @@ The purpose of this query is to generate text completions that resemble human wr
|
|||
|
||||
#### Optional parameters:
|
||||
|
||||
- **Max Tokens**: This parameter that specifies the maximum number of tokens to generate in the text completion output. For example, if you set it to 50, then it will generate a text completion that contains up to 50 tokens.
|
||||
- **Temperature**: Temperature is used to control the creativity and randomness of the generated text. It ranges from 0 to 2, a higher value such as 0.8 will increase the randomness of the output, whereas a lower value such as 0.2 will make it more focused and deterministic.
|
||||
- **Stop sequence**: the "stop" parameter is used to specify when the API should stop generating text completions. This parameter is optional and can be used to customize the length and quality of the generated text.
|
||||
- **Max Tokens**: This parameter specifies the maximum number of tokens to generate in the text completion output. For example, if you set it to 50, then it will generate a text completion that contains up to 50 tokens.
|
||||
- **Temperature**: Temperature is used to control the creativity and randomness of the generated text. It ranges from 0 to 1, a higher value such as 0.8 will increase the randomness of the output, whereas a lower value such as 0.2 will make it more focused and deterministic.
|
||||
- **Stop sequence**: Stop sequence is used to specify when the API should stop generating text completions. This parameter is optional and can be used to customize the length and quality of the generated text.
|
||||
- **Suffix**: The suffix that follows the inserted text completion.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/marketplace/plugins/openai/completions.png" alt="Marketplace: openai" />
|
||||
|
||||
</div>
|
||||
|
||||
### Chat
|
||||
|
||||
The function of this query is to examine the user's input and generate a suitable response that simulates human-like conversation.
|
||||
|
|
@ -69,13 +53,7 @@ The function of this query is to examine the user's input and generate a suitabl
|
|||
|
||||
#### Optional parameters:
|
||||
|
||||
- **Max Tokens**: This parameter that specifies the maximum number of tokens to generate in the text completion output. For example, if you set it to 50, then it will generate a text completion that contains up to 50 tokens.
|
||||
- **Max Tokens**: This parameter specifies the maximum number of tokens to generate in the text completion output. For example, if you set it to 50, then it will generate a text completion that contains up to 50 tokens.
|
||||
- **Temperature**: Temperature is used to control the creativity and randomness of the generated text. It ranges from 0 to 2, a higher value such as 0.8 will increase the randomness of the output, whereas a lower value such as 0.2 will make it more focused and deterministic.
|
||||
- **Stop sequence**: the "stop" parameter is used to specify when the API should stop generating text completions. This parameter is optional and can be used to customize the length and quality of the generated text.
|
||||
- **Suffix**: The suffix that follows the inserted text completion.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
<img className="screenshot-full" src="/img/marketplace/plugins/openai/chat.png" alt="Marketplace: openai" />
|
||||
|
||||
</div>
|
||||
- **Stop sequence**: This Stop sequence/parameter is used to specify when the API should stop generating text completions. This parameter is optional and can be used to customize the length and quality of the generated text.
|
||||
- **Suffix**: The suffix that follows the inserted text completion.
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue