Merge pull request #8113 from ToolJet/release/marketplace-1.5

Release: Marketplace 1.5
This commit is contained in:
Akshay 2023-12-08 20:18:28 +05:30 committed by GitHub
commit d075143fba
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
749 changed files with 73570 additions and 15497 deletions

View file

@ -1 +1 @@
2.24.5
2.25.0

View file

@ -114,15 +114,13 @@ the community.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 2.0, available at
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
This Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org), [version 2.0](https://www.contributor-covenant.org/version/2/0/code_of_conduct.html).
Community Impact Guidelines were inspired by [Mozilla's code of conduct
enforcement ladder](https://github.com/mozilla/diversity).
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see the FAQ at
https://www.contributor-covenant.org/faq. Translations are available at
- For answers to common questions about this code of conduct, see the FAQs at
https://www.contributor-covenant.org/faq.
- Translations are available at
https://www.contributor-covenant.org/translations.

View file

@ -8,9 +8,9 @@ We love your input! We want to make contributing to this project as easy and tra
## Setup
[Mac OS](https://docs.tooljet.io/docs/contributing-guide/setup/macos)
[Docker](https://docs.tooljet.io/docs/contributing-guide/setup/docker)
[Ubuntu](https://docs.tooljet.io/docs/contributing-guide/setup/ubuntu)
- [Mac OS](https://docs.tooljet.io/docs/contributing-guide/setup/macos)
- [Docker](https://docs.tooljet.io/docs/contributing-guide/setup/docker)
- [Ubuntu](https://docs.tooljet.io/docs/contributing-guide/setup/ubuntu)
## We Develop with GitHub
We use GitHub to host code, to track issues and feature requests, as well as accept pull requests.
@ -51,4 +51,4 @@ We use GitHub issues to track public bugs. Report a bug by [opening a new issue]
By contributing, you agree that your contributions will be licensed under its AGPL v3 License.
## Questions?
Contact us on [Slack](https://tooljet.com/slack) or mail us at [hello@tooljet.io](mailto:hello@tooljet.io).
Contact us [on Slack](https://tooljet.com/slack) or [email us at hello@tooljet.io](mailto:hello@tooljet.io).

View file

@ -1,52 +1,26 @@
ToolJet is an **open-source low-code framework** to build and deploy internal tools with minimal engineering effort. ToolJet's drag-and-drop frontend builder allows you to create complex, responsive frontends within minutes. Additionally, you can integrate various data sources, including databases like PostgreSQL, MongoDB, and Elasticsearch; API endpoints with OpenAPI spec and OAuth2 support; SaaS tools such as Stripe, Slack, Google Sheets, Airtable, and Notion; as well as object storage services like S3, GCS, and Minio, to fetch and write data.
If you find ToolJet useful, please consider giving us a star on GitHub! Your support helps us continue to innovate and deliver exciting features.
:star: If you find ToolJet useful, please consider giving us a star on GitHub! Your support helps us continue to innovate and deliver exciting features.
![Docker Cloud Build Status](https://img.shields.io/docker/cloud/build/tooljet/tooljet-ce)
![GitHub contributors](https://img.shields.io/github/contributors/tooljet/tooljet)
[![GitHub issues](https://img.shields.io/github/issues/ToolJet/ToolJet)](https://github.com/ToolJet/ToolJet/issues)
[![GitHub stars](https://img.shields.io/github/stars/ToolJet/ToolJet)](https://github.com/ToolJet/ToolJet/stargazers)
![GitHub closed issues](https://img.shields.io/github/issues-closed/tooljet/tooljet)
![GitHub pull requests](https://img.shields.io/github/issues-pr-raw/tooljet/tooljet)
![GitHub release (latest by date)](https://img.shields.io/github/v/release/tooljet/tooljet)
![Number of GitHub contributors](https://img.shields.io/github/contributors/tooljet/tooljet)
[![Number of GitHub issues that are open](https://img.shields.io/github/issues/ToolJet/ToolJet)](https://github.com/ToolJet/ToolJet/issues)
[![Number of GitHub stars](https://img.shields.io/github/stars/ToolJet/ToolJet)](https://github.com/ToolJet/ToolJet/stargazers)
![Number of GitHub closed issues](https://img.shields.io/github/issues-closed/tooljet/tooljet)
![Number of GitHub pull requests that are open](https://img.shields.io/github/issues-pr-raw/tooljet/tooljet)
![GitHub release; latest by date](https://img.shields.io/github/v/release/tooljet/tooljet)
![GitHub commit activity](https://img.shields.io/github/commit-activity/m/tooljet/tooljet)
[![GitHub license](https://img.shields.io/github/license/ToolJet/ToolJet)](https://github.com/ToolJet/ToolJet)
[![Twitter Follow](https://img.shields.io/twitter/follow/ToolJet?style=social)](https://twitter.com/ToolJet)
[![GitHub license which is APGL license](https://img.shields.io/github/license/ToolJet/ToolJet)](https://github.com/ToolJet/ToolJet)
[![Follow us on X, formerly Twitter](https://img.shields.io/twitter/follow/ToolJet?style=social)](https://twitter.com/ToolJet)
<p align="center">
<img src="https://user-images.githubusercontent.com/7828962/211444352-4d6d2e4a-13c9-4980-9e16-4aed4af9811b.png"/>
<img src="https://user-images.githubusercontent.com/7828962/211444352-4d6d2e4a-13c9-4980-9e16-4aed4af9811b.png" alt="Tooljet dashboard showing inventory and orders"/>
</p>
<p align="center">
<img src="https://github.com/ToolJet/ToolJet/assets/25361949/0e711f3a-edb7-496b-8833-107de3826933"/>
</p>
<p align="center">
<kbd>
<img src="https://user-images.githubusercontent.com/7828962/202402863-2851a072-9dca-4b8b-9473-0d044373928b.png"/>
</kbd>
</p>
<p align="center">
<kbd>
<img src="https://user-images.githubusercontent.com/7828962/211364385-10714e24-f1ac-4e72-a2a1-ec7dc2d412ab.png"/>
</kbd>
</p>
<p align="center">
<kbd>
<img src="https://user-images.githubusercontent.com/7828962/202402422-8f1df2a4-5c07-4125-9c2e-5450b90f464c.png"/>
</kbd>
</p>
<p align="center">
<kbd>
<img src="https://user-images.githubusercontent.com/7828962/202402574-7cd7c606-d751-4de1-ba56-abbedba54b13.png"/>
</kbd>
</p>
## All features
- **Visual App Builder:** 40+ built-in responsive components, including Tables, Charts, Lists, Forms, and Progress Bars.
@ -62,7 +36,7 @@ ToolJet is an **open-source low-code framework** to build and deploy internal to
- **Run JS & Python code:** Execute custom JavaScript and Python snippets.
- **Granular access control:** Set permissions at both group and app levels.
- **Low-code:** Use JS code almost anywhere within the builder, such as setting text color based on status with
`status === 'success' ? 'green' : 'red`.
`status === 'success' ? 'green' : 'red'`.
- **No-code query editors:** Query Editors are available for all supported data sources.
- **Join and transform data:** Transform query results using JavaScript or Python code.
- **Secure:** All the credentials are securely encrypted using `aes-256-gcm`.
@ -136,7 +110,7 @@ For general help using ToolJet, please refer to the official [documentation](htt
- [Slack](https://tooljet.com/slack) - Discussions with the community and the team.
- [GitHub](https://github.com/ToolJet/ToolJet/issues) - For bug reports and feature requests.
- [Twitter](https://twitter.com/ToolJet) - Get the product updates quickly.
- [𝕏 (Twitter)](https://twitter.com/ToolJet) - Get the product updates quickly.
## Roadmap
Check out our [roadmap](https://github.com/ToolJet/ToolJet/projects/2) to stay updated on recently released features and learn about what's coming next.
@ -154,4 +128,4 @@ Kindly read our [Contributing Guide](CONTRIBUTING.md) to familiarize yourself wi
</a>
## License
ToolJet © 2022, ToolJet Solutions Inc - Released under the GNU Affero General Public License v3.0.
ToolJet © 2023, ToolJet Solutions Inc - Released under the GNU Affero General Public License v3.0.

View file

@ -2,4 +2,4 @@
## Reporting a Vulnerability
If you notice a security vulnerability, please let the team know by sending an email to `security@tooljet.com`.
If you notice a security vulnerability, please let the team know by [sending an email to security@tooljet.com](mailto:security@tooljet.com).

View file

@ -79,7 +79,7 @@ module.exports = defineConfig({
"cypress/e2e/selfHost/*.cy.js",
"cypress/e2e/authentication/*.cy.js",
"cypress/e2e/workspace/*.cy.js",
"cypress/e2e/globalDataSources/*.cy.js",
"cypress/e2e/ce/**/*.cy.js",
"cypress/e2e/editor/app-version/version.cy.js"
],
numTestsKeptInMemory: 1,

View file

@ -180,4 +180,27 @@ Cypress.Commands.add("logoutApi", () => {
expect(response.status).to.equal(200);
});
});
});
});
Cypress.Commands.add("userInviteApi", (userName, userEmail) => {
cy.getCookie("tj_auth_token").then((cookie) => {
cy.request(
{
method: "POST",
url: "http://localhost:3000/api/organization_users",
headers: {
"Tj-Workspace-Id": Cypress.env("workspaceId"),
Cookie: `tj_auth_token=${cookie.value}`,
},
body: {
first_name: userName,
email: userEmail,
groups: [],
},
},
{ log: false }
).then((response) => {
expect(response.status).to.equal(201);
});
});
});

View file

@ -57,7 +57,7 @@ Cypress.Commands.add("createApp", (appName) => {
cy.get("body").then(($title) => {
cy.get(getAppButtonSelector($title)).click();
cy.clearAndType('[data-cy="app-name-input"]', appName);
cy.get('[data-cy="+ Create app"]').click();
cy.get('[data-cy="+-create-app"]').click();
});
cy.waitForAppLoad();
cy.skipEditorPopover();
@ -298,3 +298,10 @@ Cypress.Commands.add("hideTooltip", () => {
}
});
});
Cypress.Commands.add("defaultWorkspaceLogin", () => {
cy.apiLogin();
cy.visit('/my-workspace');
cy.get(commonSelectors.homePageLogo, { timeout: 10000 })
})

View file

@ -59,7 +59,6 @@ export const commonSelectors = {
filterButton: '[data-cy="filter-button"]',
copyIcon: '[data-cy="copy-icon"]',
addWorkspaceButton: '[data-cy="add-new-workspace-link"]',
workspaceNameInput: '[data-cy="workspace-name-input-field"]',
createWorkspaceButton: '[data-cy="create-workspace-button"]',
workspaceLoginUrl: "[data-cy=workspace-login-url]",
workspaceName: '[data-cy="workspace-name"]',
@ -166,6 +165,7 @@ export const commonSelectors = {
emptyAppCreateButton: "[data-cy='button-new-app-from-scratch']",
globalDataSourceIcon: '[data-cy="icon-global-datasources"]',
addNewDataSourceButton: '[data-cy="add-new-data-source-button"]',
saveButton: '[data-cy="save-button"]',
onboardingRadioButton: (radioButtonText) => {
return `[data-cy="${cyParamName(radioButtonText)}-radio-button"]`;
@ -226,6 +226,24 @@ export const commonSelectors = {
nameErrorText: '[data-cy="name-error-text"]',
valueErrorText: '[data-cy="value-error-text"]',
releaseButton: '[data-cy="button-release"]',
leftSideBarSettingsButton: '[data-cy="left-sidebar-settings-button"]',
modalHeader: '[data-cy="modal-header"]',
modalDescription: '[data-cy="modal-description"]',
backToHomeButton: '[data-cy="back-to-home-button"]',
createAppTitle: '[data-cy="create-app-title"]',
appNameLabel: '[data-cy="app-name-label"]',
appNameInput: '[data-cy="app-name-input"]',
appNameInfoLabel: '[data-cy="app-name-info-label"]',
createAppButton: '[data-cy="+-create-app"]',
renameApptitle: '[data-cy="rename-app-title"]',
renameAppButton: '[data-cy="rename-app"]',
cloneAppTitle: '[data-cy="clone-app-title"]',
cloneAppButton: '[data-cy="clone-app"]',
appNameErrorLabel: '[data-cy="app-name-error-label"]',
importAppTitle: '[data-cy="import-app-title"]',
importAppButton: '[data-cy="import-app"]',
chooseFromTemplateButton: '[data-cy="choose-from-template-button"]',
CreateAppFromTemplateButton: '[data-cy="create-new-app-from-template-title"]',
};
export const commonWidgetSelector = {
@ -331,10 +349,19 @@ export const commonWidgetSelector = {
// iframeLinkLabel: '[data-cy="iframe-link-label"]',
// ifameLinkCopyButton: '[data-cy="iframe-link-copy-button"]',
},
copyAppLinkButton: '.input-group > :nth-child(3)',
copyAppLinkButton: '[data-cy="copy-app-link-button"]',
makePublicAppToggle: '[data-cy="make-public-app-toggle"]',
appLink: '[data-cy="app-link"]',
appNameSlugInput: '[data-cy="app-name-slug-input"]',
// iframeLink: '[data-cy="iframe-link"]',
iframeLink: '[data-cy="iframe-link"]',
modalCloseButton: '[data-cy="modal-close-button"]',
iframeLinkLabel: '[data-cy="iframe-link-label"]',
ifameLinkCopyButton: '[data-cy="iframe-link-copy-button"]',
appSlugLabel: '[data-cy="app-slug-label"]',
appSlugInput: '[data-cy="app-slug-input-field"]',
appSlugInfoLabel: '[data-cy="app-slug-info-label"]',
appLinkLabel: '[data-cy="app-link-label"]',
appLinkField: '[data-cy="app-link-field"]',
appSlugErrorLabel: '[data-cy="app-slug-error-label"]',
appLinkSucessLabel: '[data-cy="app-link-success-label"]',
};

View file

@ -41,4 +41,19 @@ export const dashboardSelector = {
folderName: (folderName) => {
return `[data-cy="${cyParamName(folderName)}-name"]`;
},
createWorkspaceTitle: '[data-cy="create-workspace-title"]',
workspaceNameLabel: '[data-cy="workspace-name-label"]',
workspaceNameInfoLabel: '[data-cy="workspace-name-info-label"]',
slugNameInputLabel: '[data-cy="slug-input-label"]',
workspaceSlugInputField: '[data-cy="workspace-slug-input-field"]',
slugInfoLabel: '[data-cy="slug-info-label"]',
workspaceLinkLabel: '[data-cy="workspace-link-label"]',
slugField: '[data-cy="slug-field"]',
createWorkspaceButton: '[data-cy="create-workspace-button"]',
workspaceErrorLabel: '[data-cy="workspace-error-label"]',
inputLabelError: '[data-cy="input-label-error"]',
slugSuccessLabel: '[data-cy="slug-sucess-label"]',
slugErrorLabel: '[data-cy="slug-error-label"]',
editWorkspaceTitle: '[data-cy="edit-workspace-title"]',
};

View file

@ -23,6 +23,7 @@ export const databaseSelectors = {
tableKebabIcon: '[data-cy="table-kebab-icon"]',
tableEditOption: '[data-cy="edit-option"]',
tableExportOption: '[data-cy="export-table-option"]',
tableDeleteOption: '[data-cy="delete-option"]',
editTableHeader: '[data-cy="edit-table-header"]',
@ -32,19 +33,25 @@ export const databaseSelectors = {
deleteRecordButton: '[data-cy="delete-row-records-button"]',
nameInputField: (value) => {
return `[data-cy="name-input-field-${value}"]`
return `[data-cy="name-input-field-${value}"]`;
},
currentTable: (tableName) => {
return `[data-cy="${String(tableName).toLowerCase().replace(/\s+/g, "-")}-table"]`;
return `[data-cy="${String(tableName)
.toLowerCase()
.replace(/\s+/g, "-")}-table"]`;
},
currentTableName: (tableName) => {
return `[data-cy="${String(tableName).toLowerCase().replace(/\s+/g, "-")}-table-name"]`;
return `[data-cy="${String(tableName)
.toLowerCase()
.replace(/\s+/g, "-")}-table-name"]`;
},
columnHeader: (columnName) => {
return `[data-cy="${String(columnName).toLowerCase().replace(/\s+/g, "-")}-column-header"]`;
return `[data-cy="${String(columnName)
.toLowerCase()
.replace(/\s+/g, "-")}-column-header"]`;
},
checkboxCell: (idColumn) => {
return `[data-cy="${idColumn}-checkbox-table-cell"]> div > input`
return `[data-cy="${idColumn}-checkbox-table-cell"]> div > input`;
},
};
@ -66,12 +73,15 @@ export const createNewRowSelectors = {
serialDataTypeLabel: '[data-cy="integer-data-type-label"]',
idColumnInputField: '[data-cy="id-input-field"]',
columnNameLabel: (columnName) => {
return `[data-cy="${String(columnName).toLowerCase().replace(/\s+/g, "-")}-column-name-label"]`;
return `[data-cy="${String(columnName)
.toLowerCase()
.replace(/\s+/g, "-")}-column-name-label"]`;
},
columnNameInputField: (columnName) => {
return `[data-cy="${String(columnName).toLowerCase().replace(/\s+/g, "-")}-input-field"]`;
return `[data-cy="${String(columnName)
.toLowerCase()
.replace(/\s+/g, "-")}-input-field"]`;
},
};
@ -98,6 +108,20 @@ export const editRowSelectors = {
idColumnNameLabel: '[data-cy="id-column-name-label"]',
selectRowDropdown: '[data-cy="select-row-dropdown"]',
getRowData: (rowNumber, columnName) => {
return `[data-cy="id-${String(rowNumber).toLowerCase().replace(/\s+/g, "-")}-column-${String(columnName).toLowerCase().replace(/\s+/g, "-")}-table-cell"]`
}
};
return `[data-cy="id-${String(rowNumber)
.toLowerCase()
.replace(/\s+/g, "-")}-column-${String(columnName)
.toLowerCase()
.replace(/\s+/g, "-")}-table-cell"]`;
},
};
export const bulkUploadDataSelectors = {
bulkUploadDataButton: '[data-cy="bulk-upload-data-button"]',
bulkUploadbuttonText: '[data-cy="bulk-upload-button-text"]',
bulkUploadDataHeaderText: '[data-cy="bulk-upload-data-header"]',
templateHelperText: '[data-cy="helper-text-bulk-upload"]',
templateDownloadButton: '[data-cy="button-download-template"]',
bulkUploadInputField: '[data-cy="input-field-bulk-upload"]',
uploadDataButton: '[data-cy="upload-data-button"]',
};

View file

@ -39,4 +39,6 @@ export const importSelectors = {
importAnApplication: '[data-cy="import-an-application"]',
importOptionLabel: '[data-cy="import-option-label"]',
importOptionInput: '[data-cy="import-option-input"]',
importAppTitle: '[data-cy="import-app-title"]',
importAppButton: '[data-cy="import-app"]',
};

View file

@ -1,8 +1,8 @@
export const buttonText = {
defaultWidgetText: "Button",
defaultWidgetName: "button1",
buttonTextLabel: "Button Text",
loadingState: "Loading State",
buttonTextLabel: "Button text",
loadingState: "Loading state",
buttonDocumentationLink: "Read documentation for Button",
backgroundColor: "Background Color",
textColor: "Text color",

View file

@ -175,6 +175,12 @@ export const commonText = {
"Constant name should start with a letter or underscore and can only contain letters, numbers and underscores",
constantsValueError:
"Value should be less than 10000 characters and cannot be empty",
createApp: "Create app",
appName: "App Name",
enterAppName: "Enter app name",
appNameInfoLabel: "App name must be unique and max 50 characters",
renameApp: "Rename app",
};
export const commonWidgetText = {
@ -190,13 +196,13 @@ export const commonWidgetText = {
parameterShowOnMobile: "Show on mobile",
parameterVisibility: "Visibility",
parameterDisable: "Disable",
parameterBorderRadius: "Border Radius",
parameterBorderRadius: "Border radius",
borderRadiusInput: ["{{", "20}}"],
parameterOptionLabels: "Option labels",
parameterBoxShadow: "Box Shadow",
parameterBoxShadow: "Box shadow",
boxShadowDefaultValue: "#00000040",
parameterOptionvalues: "Option values",
boxShadowColor: "Box Shadow Color",
boxShadowColor: "Box shadow Color",
boxShadowFxValue: "-5px 6px 5px 8px #ee121240",
codeMirrorLabelTrue: "{{true}}",
@ -207,7 +213,7 @@ export const commonWidgetText = {
addEventHandlerLink: "New event handler",
inspectorComponentLabel: "components",
componentValueLabel: "Value",
labelDefaultValue: "Default Value",
labelDefaultValue: "Default value",
parameterLabel: "Label",
labelMinimumValue: "Minimum value",
labelMaximumValue: "Maximum value",

View file

@ -81,3 +81,9 @@ export const editRowText = {
selectRowToEditText: "Select a row to edit",
rowEditedSuccessfullyToast: "Row edited successfully",
};
export const bulkUploadDataText = {
bulkUploadbuttonText: "Bulk upload data",
templateHelperText:
"Download the template to add your data or format your file in the same as the template. ToolJet wont be able to recognise files in any other format.",
};

View file

@ -7,7 +7,7 @@ export const datePickerText = {
},
datepicker1: "datepicker1",
labelDefaultValue: "Default Value",
labelDefaultValue: "Default value",
labelformat: "Format",
labelEnableDateSection: "Enable date selection?",
labelEnableTimeSection: "Enable time selection?",

View file

@ -5,5 +5,5 @@ export const multiselectText = {
noEventsMessage: "No event handlers",
dropdwonOptionSelectAll: "Select All",
enableSelectAllOptions: "Enable select All option",
enableSelectAllOptions: "Enable select all option",
};

View file

@ -12,7 +12,7 @@ describe("Password reset functionality", () => {
let passwordResetLink = "";
before(() => {
cy.appUILogin();
cy.defaultWorkspaceLogin();
addNewUserMW(data.firstName, data.email);
logout();
});

View file

@ -5,34 +5,129 @@ import { commonText } from "Texts/common";
import { addNewUserMW } from "Support/utils/userPermissions";
import { userSignUp } from "Support/utils/onboarding";
describe("App share functionality", () => {
describe("App slug", () => {
const data = {};
data.appName = `${fake.companyName} App`;
data.firstName = fake.firstName;
data.lastName = fake.lastName.replaceAll("[^A-Za-z]", "");
data.email = fake.email.toLowerCase();
const slug = data.appName.toLowerCase().replace(/\s+/g, "-");
const firstUserEmail = data.email
const envVar = Cypress.env("environment");
// beforeEach(() => {
// cy.appUILogin();
// });
data.slug = `${fake.companyName.toLowerCase()}-app`;
beforeEach(() => {
cy.defaultWorkspaceLogin();
})
before(() => {
cy.apiLogin();
cy.apiCreateApp(data.appName);
// cy.visit('/')
// logout();
cy.logoutApi()
})
it("", () => {
cy.openApp(data.appName);
it("Verify app slug cases in global settings", () => {
navigateToAppEditor(data.appName);
cy.get('[data-cy="left-sidebar-settings-button"]').click();
cy.get('[data-cy="app-slug-label"]').verifyVisibleElement("have.text", "Unique app slug");
cy.get('[data-cy="app-slug-input-field"]').verifyVisibleElement("have.value", Cypress.env("appId"));
cy.get('[data-cy="app-slug-info-label"]').verifyVisibleElement("have.text", "URL-friendly 'slug' consists of lowercase letters, numbers, and hyphens");
cy.get('[data-cy="app-link-label"]').verifyVisibleElement("have.text", "App link");
cy.get('[data-cy="app-link-field"]').verifyVisibleElement("have.text", `http://localhost:8082/my-workspace/apps/${Cypress.env("appId")}`)
cy.get(commonSelectors.leftSideBarSettingsButton).click();
cy.get(commonWidgetSelector.appSlugLabel).verifyVisibleElement("have.text", "Unique app slug");
cy.get(commonWidgetSelector.appSlugInput).verifyVisibleElement("have.value", Cypress.env("appId"));
cy.get(commonWidgetSelector.appSlugInfoLabel).verifyVisibleElement("have.text", "URL-friendly 'slug' consists of lowercase letters, numbers, and hyphens");
cy.get(commonWidgetSelector.appLinkLabel).verifyVisibleElement("have.text", "App link");
cy.get(commonWidgetSelector.appLinkField).verifyVisibleElement("have.text", `http://localhost:8082/my-workspace/apps/${Cypress.env("appId")}`)
cy.wait(500)
cy.get(commonWidgetSelector.appSlugInput).clear();
cy.get(commonWidgetSelector.appSlugErrorLabel).verifyVisibleElement("have.text", "App slug can't be empty")
cy.clearAndType(commonWidgetSelector.appSlugInput, "_2#");
cy.get(commonWidgetSelector.appSlugErrorLabel).verifyVisibleElement("have.text", "Special characters are not accepted.");
cy.clearAndType(commonWidgetSelector.appSlugInput, "t ");
cy.get(commonWidgetSelector.appSlugErrorLabel).verifyVisibleElement("have.text", "Cannot contain spaces")
cy.clearAndType(commonWidgetSelector.appSlugInput, "T");
cy.get(commonWidgetSelector.appSlugErrorLabel).verifyVisibleElement("have.text", "Only lowercase letters are accepted.")
cy.get(commonWidgetSelector.appSlugInput).clear()
cy.clearAndType(commonWidgetSelector.appSlugInput, data.slug);
cy.get(commonWidgetSelector.appSlugErrorLabel).verifyVisibleElement("have.text", "Slug accepted!")
cy.get(commonWidgetSelector.appLinkSucessLabel).verifyVisibleElement("have.text", "Link updated successfully!");
cy.get(commonWidgetSelector.appLinkField).verifyVisibleElement("have.text", `http://localhost:8082/my-workspace/apps/${data.slug}`)
cy.url().should('eq', `http://localhost:8082/my-workspace/apps/${data.slug}/home`);
releaseApp();
cy.openInCurrentTab(commonWidgetSelector.previewButton);
cy.wait(1000);
cy.url().should('eq', `http://localhost:8082/applications/${data.slug}/home?version=v1`);
cy.visit('/my-workspace');
cy.wait(500);
cy.visit(`/applications/${data.slug}`);
cy.url().should('eq', `http://localhost:8082/applications/${data.slug}`);
cy.visit('/my-workspace');
cy.wait(500);
cy.apiCreateApp(data.slug);
cy.openApp(data.slug);
cy.get(commonSelectors.leftSideBarSettingsButton).click();
cy.get(commonWidgetSelector.appSlugInput).clear()
cy.clearAndType(commonWidgetSelector.appSlugInput, data.slug);
cy.get(commonWidgetSelector.appSlugErrorLabel).verifyVisibleElement("have.text", "This app slug is already taken.")
})
it("Verify app slug cases in share modal", () => {
data.slug = `${fake.companyName.toLowerCase()}-app`;
data.appName = `${fake.companyName} App`;
cy.apiCreateApp(data.appName);
cy.visit('/')
navigateToAppEditor(data.appName);
cy.get(commonSelectors.leftSideBarSettingsButton).click();
cy.get(commonWidgetSelector.appSlugInput).clear()
cy.clearAndType(commonWidgetSelector.appSlugInput, data.slug);
releaseApp();
cy.get(commonWidgetSelector.shareAppButton).click()
cy.get(commonWidgetSelector.appNameSlugInput).should("have.value", data.slug);
cy.get(commonWidgetSelector.appNameSlugInput).clear();
cy.get(commonWidgetSelector.appSlugErrorLabel).verifyVisibleElement("have.text", "App slug can't be empty")
cy.clearAndType(commonWidgetSelector.appNameSlugInput, "_2#");
cy.get(commonWidgetSelector.appSlugErrorLabel).verifyVisibleElement("have.text", "Special characters are not accepted.");
cy.clearAndType(commonWidgetSelector.appNameSlugInput, "t ");
cy.get(commonWidgetSelector.appSlugErrorLabel).verifyVisibleElement("have.text", "Cannot contain spaces")
cy.clearAndType(commonWidgetSelector.appNameSlugInput, "T");
cy.get(commonWidgetSelector.appSlugErrorLabel).verifyVisibleElement("have.text", "Only lowercase letters are accepted.")
data.slug = `${fake.companyName.toLowerCase()}-app`;
cy.get(commonWidgetSelector.appNameSlugInput).clear()
cy.clearAndType(commonWidgetSelector.appNameSlugInput, data.slug);
cy.get(commonWidgetSelector.appSlugErrorLabel).verifyVisibleElement("have.text", "Slug accepted!");
cy.get(1000);
cy.get(commonWidgetSelector.modalCloseButton).click();
cy.url().should('eq', `http://localhost:8082/my-workspace/apps/${data.slug}/home`);
cy.openInCurrentTab(commonWidgetSelector.previewButton);
cy.wait(1000);
cy.url().should('eq', `http://localhost:8082/applications/${data.slug}/home?version=v1`);
cy.visit('/my-workspace');
cy.wait(500);
cy.visit(`/applications/${data.slug}`);
cy.url().should('eq', `http://localhost:8082/applications/${data.slug}`);
cy.visit('/my-workspace');
cy.wait(500);
cy.apiCreateApp(data.slug);
cy.openApp(data.slug);
releaseApp();
cy.get(commonWidgetSelector.shareAppButton).click()
cy.clearAndType(commonWidgetSelector.appNameSlugInput, data.slug);
cy.get(commonWidgetSelector.appSlugErrorLabel).verifyVisibleElement("have.text", "This app slug is already taken.")
})

View file

@ -34,9 +34,8 @@ data.appName = `${fake.companyName}-App`;
describe("Global Datasource Manager", () => {
beforeEach(() => {
cy.apiLogin();
cy.defaultWorkspaceLogin();
cy.viewport(1200, 1300);
cy.visit('/')
});
before(() => {
cy.apiLogin();
@ -204,7 +203,6 @@ describe("Global Datasource Manager", () => {
navigateToAppEditor(data.appName);
pinInspector();
// cy.get(".tooltip-inner").invoke("hide");
addQuery(
"table_preview",
@ -267,7 +265,7 @@ describe("Global Datasource Manager", () => {
it("Should validate the user's global data source permissions on apps created by admin", () => {
logout();
cy.apiLogin(data.email, "password");
cy.visit('/')
cy.visit('/my-workspace')
cy.get(commonSelectors.globalDataSourceIcon).should("not.exist");
@ -279,7 +277,6 @@ describe("Global Datasource Manager", () => {
);
pinInspector();
// cy.get(".tooltip-inner").invoke("hide");
cy.get(dataSourceSelector.queryCreateAndRunButton).click();
verifyValueOnInspector("table_preview", "7 items ");
@ -302,7 +299,7 @@ describe("Global Datasource Manager", () => {
data.appName = `${fake.companyName}-App`;
logout();
cy.apiLogin(data.email, "password");
cy.visit('/')
cy.visit('/my-workspace')
cy.apiCreateApp(data.appName);
cy.openApp();
cy.dragAndDropWidget("Table", 250, 250);
@ -319,7 +316,6 @@ describe("Global Datasource Manager", () => {
);
pinInspector();
// cy.get(".tooltip-inner").invoke("hide");
cy.get(dataSourceSelector.queryCreateAndRunButton).click();
verifyValueOnInspector("table_preview", "7 items ");

View file

@ -0,0 +1,168 @@
import { commonSelectors, commonWidgetSelector } from "Selectors/common";
import { fake } from "Fixtures/fake";
import {
logout,
navigateToAppEditor,
verifyTooltip,
releaseApp,
} from "Support/utils/common";
import { commonText } from "Texts/common";
import { addNewUserMW } from "Support/utils/userPermissions";
import { userSignUp } from "Support/utils/onboarding";
describe("App share functionality", () => {
const data = {};
data.appName = `${fake.companyName} App`;
data.firstName = fake.firstName;
data.lastName = fake.lastName.replaceAll("[^A-Za-z]", "");
data.email = fake.email.toLowerCase();
const slug = data.appName.toLowerCase().replace(/\s+/g, "-");
const firstUserEmail = data.email;
const envVar = Cypress.env("environment");
beforeEach(() => {
cy.defaultWorkspaceLogin();
});
before(() => {
cy.apiLogin();
cy.apiCreateApp(data.appName);
cy.logoutApi();
});
it("Verify private and public app share funtionality", () => {
cy.openApp(data.appName);
cy.dragAndDropWidget("Table", 250, 250);
verifyTooltip(
commonWidgetSelector.shareAppButton,
"Share URL is unavailable until current version is released"
);
cy.get('[data-cy="share-button-link"]>span').should(
"have.class",
"share-disabled"
);
releaseApp();
cy.get(commonWidgetSelector.shareAppButton).click();
for (const elements in commonWidgetSelector.shareModalElements) {
cy.get(
commonWidgetSelector.shareModalElements[elements]
).verifyVisibleElement(
"have.text",
commonText.shareModalElements[elements]
);
}
cy.get(commonWidgetSelector.copyAppLinkButton).should("be.visible");
cy.get(commonWidgetSelector.makePublicAppToggle).should("be.visible");
cy.get(commonWidgetSelector.appLink).should("be.visible");
cy.get(commonWidgetSelector.appNameSlugInput).should("be.visible");
// cy.get(commonWidgetSelector.iframeLink).should("be.visible");
cy.get(commonWidgetSelector.modalCloseButton).should("be.visible");
cy.clearAndType(commonWidgetSelector.appNameSlugInput, `${slug}`);
cy.wait(2000);
cy.get(commonWidgetSelector.modalCloseButton).click();
cy.forceClickOnCanvas();
cy.get(commonSelectors.editorPageLogo).click();
logout();
cy.wait(2500);
cy.visit(`/applications/${slug}`);
cy.wait(2500);
cy.get(commonSelectors.loginButton, { timeout: 10000 }).should(
"be.visible"
);
cy.clearAndType(commonSelectors.workEmailInputField, "dev@tooljet.io");
cy.clearAndType(commonSelectors.passwordInputField, "password");
cy.get(commonSelectors.loginButton).click();
cy.wait(500);
cy.get('[data-cy="draggable-widget-table1"]').should("be.visible");
cy.get(commonSelectors.viewerPageLogo).click();
cy.openApp(Cypress.env("appId"), '[data-cy="draggable-widget-table1"]');
cy.get(commonWidgetSelector.shareAppButton).click();
cy.get(commonWidgetSelector.makePublicAppToggle).check();
cy.get(commonWidgetSelector.modalCloseButton).click();
cy.get(commonSelectors.editorPageLogo).click();
logout();
cy.wait(2500);
cy.visit(`/applications/${slug}`);
cy.wait(2500);
cy.get('[data-cy="draggable-widget-table1"]').should("be.visible");
});
it("Verify app private and public app visibility for the same workspace user", () => {
cy.openApp(Cypress.env("appId"), '[data-cy="draggable-widget-table1"]');
cy.wait(2000);
cy.get(commonWidgetSelector.shareAppButton).click();
cy.get("body").then(($el) => {
if (!$el.text().includes("Embedded app link", { timeout: 2000 })) {
cy.get(commonWidgetSelector.makePublicAppToggle).check();
}
});
cy.get(commonWidgetSelector.modalCloseButton).click();
cy.get(commonSelectors.editorPageLogo).click();
addNewUserMW(data.firstName, data.email);
logout();
cy.visit(`/applications/${slug}`);
cy.get('[data-cy="draggable-widget-table1"]').should("be.visible");
cy.defaultWorkspaceLogin();
cy.openApp(Cypress.env("appId"), '[data-cy="draggable-widget-table1"]');
cy.wait(2000);
cy.get(commonWidgetSelector.shareAppButton).click();
cy.get(commonWidgetSelector.makePublicAppToggle).uncheck();
cy.get(commonWidgetSelector.modalCloseButton).click();
cy.get(commonSelectors.editorPageLogo).click();
logout();
cy.visit(`/applications/${slug}`);
cy.login(data.email, "password");
cy.get(commonSelectors.allApplicationLink).verifyVisibleElement(
"have.text",
commonText.allApplicationLink
);
});
it("Verify app private and public app visibility for the same instance user", () => {
data.firstName = fake.firstName;
data.email = fake.email.toLowerCase();
cy.logoutApi();
userSignUp(data.firstName, data.email, "Test");
cy.visit(`/applications/${slug}`);
cy.wait(1000);
cy.clearAndType(commonSelectors.workEmailInputField, data.email);
cy.clearAndType(commonSelectors.passwordInputField, "password");
cy.get(commonSelectors.signInButton).click();
cy.wait(1000);
cy.get(`[data-cy="workspace-sign-in-sub-header"]`).verifyVisibleElement(
"have.text",
"Sign in to your workspace - My workspace"
);
cy.visit("/");
cy.wait(2000);
logout();
cy.defaultWorkspaceLogin();
cy.openApp(Cypress.env("appId"), '[data-cy="draggable-widget-table1"]');
cy.wait(2000);
cy.get(commonWidgetSelector.shareAppButton).click();
cy.get(commonWidgetSelector.makePublicAppToggle).check();
cy.get(commonWidgetSelector.modalCloseButton).click();
cy.get(commonSelectors.editorPageLogo).click();
logout();
cy.visit(`/applications/${slug}`);
cy.get('[data-cy="draggable-widget-table1"]').should("be.visible");
cy.get(commonSelectors.viewerPageLogo).click();
});
});

View file

@ -0,0 +1,340 @@
import { commonSelectors, commonWidgetSelector } from "Selectors/common";
import { fake } from "Fixtures/fake";
import { workspaceConstantsSelectors } from "Selectors/workspaceConstants";
import { workspaceConstantsText } from "Texts/workspaceConstants";
import { commonText, commonWidgetText } from "Texts/common";
import * as common from "Support/utils/common";
import {
contantsNameValidation,
AddNewconstants,
} from "Support/utils/workspaceConstants";
import { buttonText } from "Texts/button";
import {
verifyAndModifyParameter,
editAndVerifyWidgetName,
} from "Support/utils/commonWidget";
import { verifypreview } from "Support/utils/dataSource";
import {
selectQueryFromLandingPage,
query,
addInputOnQueryField,
} from "Support/utils/queries";
const data = {};
data.constName = fake.firstName.toLowerCase().replaceAll("[^A-Za-z]", "");
data.newConstvalue = `New ${data.constName}`;
data.constantsName = fake.firstName.toLowerCase().replaceAll("[^A-Za-z]", "");
data.constantsValue = "dJ_8Q~BcaMPd";
data.appName = `${fake.companyName}-App`;
data.slug = data.appName.toLowerCase().replace(/\s+/g, "-");
describe("Workspace constants", () => {
const envVar = Cypress.env("environment");
beforeEach(() => {
cy.defaultWorkspaceLogin();
cy.intercept("GET", "/api/library_apps").as("homePage");
});
it("Verify workspace constants UI and CRUD operations", () => {
cy.get(commonSelectors.workspaceSettingsIcon).click();
cy.get(commonSelectors.workspaceConstantsOption)
.should(($el) => {
expect($el.contents().first().text().trim()).to.eq(
"Workspace constants"
);
})
.click();
cy.get(commonSelectors.breadcrumbTitle).should(($el) => {
expect($el.contents().first().text().trim()).to.eq("Workspace settings");
});
cy.get(commonSelectors.breadcrumbPageTitle).verifyVisibleElement(
"have.text",
" Workspace constants"
);
cy.get(
workspaceConstantsSelectors.workspaceConstantsHelperText
).verifyVisibleElement(
"have.text",
workspaceConstantsText.workspaceConstantsHelperText
);
cy.get(commonSelectors.documentationLink).verifyVisibleElement(
"have.text",
commonText.documentationLink
);
cy.get("body").then(($body) => {
if ($body.find(workspaceConstantsSelectors.emptyStateImage).length > 0) {
cy.get(workspaceConstantsSelectors.emptyStateImage).should(
"be.visible"
);
cy.get(
workspaceConstantsSelectors.emptyStateHeader
).verifyVisibleElement(
"have.text",
workspaceConstantsText.emptyStateHeader
);
cy.get(workspaceConstantsSelectors.emptyStateText).verifyVisibleElement(
"have.text",
workspaceConstantsText.emptyStateText
);
cy.get(
workspaceConstantsSelectors.addNewConstantButton
).verifyVisibleElement(
"have.text",
workspaceConstantsText.addNewConstantButton
);
}
});
cy.get(workspaceConstantsSelectors.addNewConstantButton).click();
cy.get(workspaceConstantsSelectors.contantFormTitle).verifyVisibleElement(
"have.text",
workspaceConstantsText.addConstatntText
);
cy.get(commonSelectors.nameLabel).verifyVisibleElement("have.text", "Name");
cy.get(commonSelectors.nameInputField)
.invoke("attr", "placeholder")
.should("eq", "Enter Constant Name");
cy.get(commonSelectors.nameInputField).should("be.visible");
cy.get(commonSelectors.valueLabel).verifyVisibleElement(
"have.text",
"Value"
);
cy.get(commonSelectors.valueInputField)
.invoke("attr", "placeholder")
.should("eq", "Enter Value");
cy.get(commonSelectors.valueInputField).should("be.visible");
cy.get(commonSelectors.cancelButton).verifyVisibleElement(
"have.text",
"Cancel"
);
cy.get(workspaceConstantsSelectors.addConstantButton).verifyVisibleElement(
"have.text",
"Add constant"
);
cy.get(workspaceConstantsSelectors.addConstantButton).should("be.disabled");
contantsNameValidation(" ", commonText.constantsNameError);
contantsNameValidation("9", commonText.constantsNameError);
contantsNameValidation("%", commonText.constantsNameError);
contantsNameValidation(
"ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`a",
"Maximum length has been reached"
);
contantsNameValidation(
"ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`afgg",
"Constant name should be between 1 and 32 characters"
);
cy.clearAndType(commonSelectors.valueInputField, " ");
cy.get(commonSelectors.valueErrorText).verifyVisibleElement(
"have.text",
commonText.constantsValueError
);
cy.get(workspaceConstantsSelectors.addConstantButton).should("be.disabled");
cy.get(commonSelectors.cancelButton).click();
cy.get(workspaceConstantsSelectors.addNewConstantButton).click();
cy.clearAndType(commonSelectors.nameInputField, data.constName);
cy.clearAndType(commonSelectors.valueInputField, data.constName);
cy.get(workspaceConstantsSelectors.addConstantButton).should("be.enabled");
cy.get(commonSelectors.cancelButton).click();
cy.get(workspaceConstantsSelectors.constantName(data.constName)).should(
"not.exist"
);
cy.get(workspaceConstantsSelectors.addNewConstantButton).click();
cy.clearAndType(commonSelectors.nameInputField, data.constName);
cy.clearAndType(commonSelectors.valueInputField, data.constName);
cy.get(workspaceConstantsSelectors.addConstantButton).click();
cy.verifyToastMessage(
commonSelectors.toastMessage,
workspaceConstantsText.constantCreatedToast
);
cy.get(workspaceConstantsSelectors.addNewConstantButton).click();
contantsNameValidation(
data.constName,
"Constant with this name already exists in Production environment"
);
cy.get(commonSelectors.cancelButton).click();
cy.get(workspaceConstantsSelectors.envName).verifyVisibleElement(
"have.text",
"Production"
);
cy.get(
workspaceConstantsSelectors.addNewConstantButton
).verifyVisibleElement("have.text", "Create new constant");
cy.get(
workspaceConstantsSelectors.constantsTableNameHeader
).verifyVisibleElement("have.text", "Name");
cy.get(
workspaceConstantsSelectors.constantsTableValueHeader
).verifyVisibleElement("have.text", "Value");
cy.get(
workspaceConstantsSelectors.constantName(data.constName)
).verifyVisibleElement("have.text", data.constName);
cy.get(
workspaceConstantsSelectors.constantValue(data.constName)
).verifyVisibleElement("have.text", data.constName);
cy.get(
workspaceConstantsSelectors.constEditButton(data.constName)
).verifyVisibleElement("have.text", "Edit");
cy.get(
workspaceConstantsSelectors.constDeleteButton(data.constName)
).verifyVisibleElement("have.text", "Delete");
cy.get(commonSelectors.pagination).should("be.visible");
cy.get(workspaceConstantsSelectors.constEditButton(data.constName)).click();
cy.get(workspaceConstantsSelectors.contantFormTitle).verifyVisibleElement(
"have.text",
"Update constant in production "
);
cy.get(commonSelectors.nameLabel).verifyVisibleElement("have.text", "Name");
cy.get(commonSelectors.nameInputField).should("have.value", data.constName);
cy.get(commonSelectors.nameInputField)
.should("be.visible")
.and("be.disabled");
cy.get(commonSelectors.valueLabel).verifyVisibleElement(
"have.text",
"Value"
);
cy.get(commonSelectors.valueInputField)
.should("be.visible")
.and("have.value", data.constName);
cy.get(commonSelectors.cancelButton).verifyVisibleElement(
"have.text",
"Cancel"
);
cy.get(workspaceConstantsSelectors.addConstantButton).verifyVisibleElement(
"have.text",
"Update"
);
cy.get(workspaceConstantsSelectors.addConstantButton).should("be.disabled");
cy.clearAndType(commonSelectors.valueInputField, data.newConstvalue);
cy.get(workspaceConstantsSelectors.addConstantButton).should("be.enabled");
cy.get(commonSelectors.cancelButton).click();
cy.get(
workspaceConstantsSelectors.constantValue(data.constName)
).verifyVisibleElement("have.text", data.constName);
cy.get(workspaceConstantsSelectors.constEditButton(data.constName)).click();
cy.clearAndType(commonSelectors.valueInputField, data.newConstvalue);
cy.get(workspaceConstantsSelectors.addConstantButton).click();
cy.verifyToastMessage(
commonSelectors.toastMessage,
"Constant updated successfully"
);
cy.get(
workspaceConstantsSelectors.constantValue(data.constName)
).verifyVisibleElement("have.text", data.newConstvalue);
cy.get(
workspaceConstantsSelectors.constDeleteButton(data.constName)
).click();
cy.get(commonSelectors.modalMessage).verifyVisibleElement(
"have.text",
`Are you sure you want to delete ${data.constName} from production?`
);
cy.get(commonSelectors.cancelButton).verifyVisibleElement(
"have.text",
"Cancel"
);
cy.get(commonSelectors.yesButton).verifyVisibleElement("have.text", "Yes");
cy.get(commonSelectors.cancelButton).click();
cy.get(
workspaceConstantsSelectors.constantValue(data.constName)
).verifyVisibleElement("have.text", data.newConstvalue);
cy.get(
workspaceConstantsSelectors.constDeleteButton(data.constName)
).click();
cy.get(commonSelectors.yesButton).click();
cy.get(workspaceConstantsSelectors.constantValue(data.constName)).should(
"not.exist"
);
cy.verifyToastMessage(
commonSelectors.toastMessage,
"Constant deleted successfully"
);
});
it("should verify the constants resolving value on components and query", () => {
common.navigateToworkspaceConstants();
AddNewconstants(data.constantsName, data.constantsValue);
cy.get(
workspaceConstantsSelectors.constantName(data.constantsName)
).verifyVisibleElement("have.text", data.constantsName);
cy.get(
workspaceConstantsSelectors.constantValue(data.constantsName)
).verifyVisibleElement("have.text", data.constantsValue);
cy.get(commonSelectors.homePageLogo).click();
cy.wait("@homePage");
cy.createApp(data.appName);
selectQueryFromLandingPage("runjs", "JavaScript");
addInputOnQueryField("runjs", `return constants.${data.constantsName}`);
query("preview");
verifypreview("raw", "dJ_8Q~BcaMPd");
cy.dragAndDropWidget("Text", 550, 350);
editAndVerifyWidgetName(data.constantsName);
cy.waitForAutoSave();
verifyAndModifyParameter("Text", `{{constants.${data.constantsName}`);
cy.forceClickOnCanvas();
cy.waitForAutoSave();
common.pinInspector();
cy.get(".tooltip-inner").invoke("hide");
cy.get(commonWidgetSelector.sidebarinspector).click();
cy.get(commonWidgetSelector.inspectorNodeComponents).click();
cy.get(commonWidgetSelector.nodeComponent(data.constantsName)).click();
cy.get('[data-cy="inspector-node-text"] > .mx-2').verifyVisibleElement(
"have.text",
`"dJ_8Q~BcaMPd"`
);
cy.get('[data-cy="inspector-node-constants"] > .node-key').click();
cy.get(`[data-cy="inspector-node-${data.constantsName}"] > .node-key`)
.eq(1)
.verifyVisibleElement("have.text", data.constantsName);
cy.get(
`[data-cy="inspector-node-${data.constantsName}"] > .mx-2`
).verifyVisibleElement("have.text", `"dJ_8Q~BcaMPd"`);
cy.get('[data-cy="button-release"]').click();
cy.get('[data-cy="yes-button"]').click();
cy.verifyToastMessage(commonSelectors.toastMessage, "Version v1 released");
cy.get(commonWidgetSelector.shareAppButton).click();
cy.clearAndType(commonWidgetSelector.appNameSlugInput, `${data.slug}`);
cy.wait(1500);
cy.get(commonWidgetSelector.modalCloseButton).click();
cy.forceClickOnCanvas();
cy.waitForAutoSave();
cy.wait(500);
cy.openInCurrentTab(commonWidgetSelector.previewButton);
cy.wait(4000);
cy.get(
commonWidgetSelector.draggableWidget(data.constantsName)
).verifyVisibleElement("have.text", "dJ_8Q~BcaMPd");
cy.get('[data-cy="viewer-page-logo"]').click();
cy.wait("@homePage");
cy.visit(`/applications/${data.slug}`);
cy.wait(4000);
cy.get(
commonWidgetSelector.draggableWidget(data.constantsName)
).verifyVisibleElement("have.text", "dJ_8Q~BcaMPd");
});
});

View file

@ -1,4 +1,8 @@
import { filterSelectors, sortSelectors } from "Selectors/database";
import {
databaseSelectors,
filterSelectors,
sortSelectors,
} from "Selectors/database";
import { databaseText, filterText, sortText } from "Texts/database";
import { navigateToDatabase } from "Support/utils/common";
import {
@ -15,6 +19,8 @@ import {
deleteRowAndVerify,
editRowWithInvalidData,
editRowAndVerify,
exportTableAndVerify,
bulkUploadDataTemplateDownloadAndVerify,
} from "Support/utils/database";
import { fake } from "Fixtures/fake";
import { randomNumber } from "Support/utils/commonWidget";
@ -75,7 +81,9 @@ describe("Database Functionality", () => {
let column1 = columnDetails();
let column2 = columnDetails();
navigateToDatabase();
verifyAllElementsOfPage();
cy.get(databaseSelectors.allTablesSection).should("be.visible");
cy.get(databaseSelectors.allTableSubheader).should("be.visible");
cy.get(databaseSelectors.addTableButton).should("be.visible");
createTableAndVerifyToastMessage(data.tableName1, false);
createTableAndVerifyToastMessage(
data.tableName2,
@ -85,6 +93,7 @@ describe("Database Functionality", () => {
true,
[column1.defaultValueVarchar, column1.defaultValueInt]
);
verifyAllElementsOfPage();
});
it("Verify all operations of table", () => {
const data = {};
@ -183,5 +192,15 @@ describe("Database Functionality", () => {
[databaseText.idColumnName, column1.name, column2.name],
[row4.varcharData, row4.intData]
);
exportTableAndVerify(data.tableName, [
databaseText.idColumnName,
column1.name,
column2.name,
]);
bulkUploadDataTemplateDownloadAndVerify(data.tableName, [
databaseText.idColumnName,
column1.name,
column2.name,
]);
});
});

View file

@ -138,7 +138,7 @@ describe("Data sources MySql", () => {
fillDataSourceTextField(
postgreSqlText.labelDbName,
postgreSqlText.placeholderNameOfDB,
"testdb"
"testdv"
);
fillDataSourceTextField(
postgreSqlText.labelUserName,
@ -205,7 +205,7 @@ describe("Data sources MySql", () => {
fillConnectionForm({
Host: Cypress.env("mysql_host"),
Port: Cypress.env("mysql_port"),
"Database Name": "testdb",
"Database Name": "testdv",
Username: Cypress.env("mysql_user"),
Password: Cypress.env("mysql_password"),
});
@ -383,7 +383,7 @@ describe("Data sources MySql", () => {
fillConnectionForm({
Host: Cypress.env("mysql_host"),
Port: Cypress.env("mysql_port"),
"Database Name": "testdb",
"Database Name": "testdv",
Username: Cypress.env("mysql_user"),
Password: Cypress.env("mysql_password"),
});
@ -416,7 +416,7 @@ describe("Data sources MySql", () => {
cy.get(".p-3").should(
"have.text",
`[{"Tables_in_testdb (${dbName})":"${dbName}"}]`
`[{"Tables_in_testdv (${dbName})":"${dbName}"}]`
);
// addQuery(
@ -458,7 +458,7 @@ describe("Data sources MySql", () => {
fillConnectionForm({
Host: Cypress.env("mysql_host"),
Port: "3318",
"Database Name": "testdb",
"Database Name": "testdv",
Username: Cypress.env("mysql_user"),
Password: Cypress.env("mysql_password"),
});

View file

@ -82,9 +82,14 @@ describe("Editor- Inspector", () => {
cy.get('[data-cy="switch-page-label-and-input"] > .select-search')
.click()
.type("home{enter}");
cy.get('[data-cy="button-add-query-param"]').click();
cy.wait(1000);
cy.get('[data-cy="button-add-query-param"]').click();
cy.wait(3000);
cy.get("body").then(($body) => {
if ($body.find('[data-cy="query-param-key-input-field"]').length == 0) {
cy.get('[data-cy="button-add-query-param"]').click();
}
});
addSupportCSAData("query-param-key", "key");
addSupportCSAData("query-param-value", "value");

View file

@ -326,7 +326,7 @@ describe("Modal", () => {
);
cy.get("#inspector-tab-properties").click();
typeOnFx("Loading State", "{{components.toggleswitch3.value");
typeOnFx("Loading state", "{{components.toggleswitch3.value");
cy.get("[data-cy='modal-header']").realClick();
typeOnFx("Hide title bar", "{{components.toggleswitch4.value");

View file

@ -262,7 +262,7 @@ describe("Table", () => {
cy.get('[data-cy="label-action-button-text"]').verifyVisibleElement(
"have.text",
"Button Text"
"Button text"
);
cy.get('[data-cy="action-button-text-input-field"]').type(
"{selectAll}{backspace}FakeName1"
@ -273,7 +273,7 @@ describe("Table", () => {
);
cy.get('[data-cy="label-action-button-position"]').verifyVisibleElement(
"have.text",
"Button Position"
"Button position"
); // dropdown_type
cy.forceClickOnCanvas();
cy.waitForAutoSave();
@ -351,7 +351,7 @@ describe("Table", () => {
cy.get('[data-index="0"]>.select-search-option:eq(1)').realClick();
verifyAndEnterColumnOptionInput("key", "name");
verifyAndEnterColumnOptionInput("Text color", "red");
verifyAndEnterColumnOptionInput("Cell Background Color", "yellow");
verifyAndEnterColumnOptionInput("Cell Background color", "yellow");
cy.get(
'[data-cy="input-and-label-cell-background-color"] > .form-label'
).click();
@ -647,7 +647,7 @@ describe("Table", () => {
// cy.get("[data-cy='border-radius-fx-button']:eq(1)").click();
verifyAndModifyParameter(
"Action Button Radius",
"Action button radius",
commonWidgetText.borderRadiusInput
);
@ -668,7 +668,7 @@ describe("Table", () => {
cy.get(commonWidgetSelector.buttonStylesEditorSideBar).click();
verifyAndModifyParameter(
"Border Radius",
"Border radius",
commonWidgetText.borderRadiusInput
);
cy.get(commonWidgetSelector.buttonCloseEditorSideBar).click();
@ -844,7 +844,7 @@ describe("Table", () => {
// cy.get('[data-cy="show-search-box-toggle-button"]').click();
// verifyAndModifyToggleFx("Server-side search", " ", true);
verifyAndModifyToggleFx("Loading State", "{{false}}", true);
verifyAndModifyToggleFx("Loading state", "{{false}}", true);
});
it("should verify download", () => {

View file

@ -66,8 +66,8 @@ describe("App Import Functionality", () => {
cy.get(importSelectors.importOptionInput).eq(0).selectFile(appFile, {
force: true,
});
cy.get('[data-cy="import-app-title"]').should("be.visible");
cy.get('[data-cy="Import app"]').click();
cy.get(importSelectors.importAppTitle).should("be.visible");
cy.get(importSelectors.importAppButton).click();
cy.get(".go3958317564")
.should("be.visible")
.and("have.text", importText.appImportedToastMessage);
@ -116,8 +116,8 @@ describe("App Import Functionality", () => {
force: true,
});
cy.get('[data-cy="import-app-title"]').should("be.visible");
cy.get('[data-cy="Import app"]').click();
cy.get(importSelectors.importAppTitle).should("be.visible");
cy.get(importSelectors.importAppButton).click();
cy.get(".go3958317564")
.should("be.visible")
.and("have.text", importText.appImportedToastMessage);
@ -188,8 +188,8 @@ describe("App Import Functionality", () => {
force: true,
}
);
cy.get('[data-cy="import-app-title"]').should("be.visible");
cy.get('[data-cy="Import app"]').click();
cy.get(importSelectors.importAppTitle).should("be.visible");
cy.get(importSelectors.importAppButton).click();
cy.get(".go3958317564")
.should("be.visible")
.and("have.text", importText.appImportedToastMessage);

View file

@ -0,0 +1,314 @@
import { commonSelectors, commonWidgetSelector } from "Selectors/common";
import { fake } from "Fixtures/fake";
import { viewAppCardOptions } from "Support/utils/common";
import { commonText } from "Texts/common";
import { importSelectors } from "Selectors/exportImport";
import { importText } from "Texts/exportImport";
describe("App creation", () => {
const data = {};
data.appName = `${fake.companyName}-App`;
data.rename = `New-${data.appName}`;
data.cloneAppName = `cloned-${data.appName}`;
const appFile = "cypress/fixtures/templates/test-app.json";
beforeEach(() => {
cy.defaultWorkspaceLogin();
});
it("Should verify create, rename and clone app flow", () => {
cy.get(commonSelectors.appCreateButton).click();
cy.get(commonSelectors.createAppTitle).verifyVisibleElement(
"have.text",
commonText.createApp
);
cy.get(commonSelectors.appNameLabel).verifyVisibleElement(
"have.text",
commonText.appName
);
cy.get(commonSelectors.appNameInput).verifyVisibleElement(
"have.attr",
"placeholder",
commonText.enterAppName
);
cy.get(commonSelectors.appNameInfoLabel).verifyVisibleElement(
"have.text",
commonText.appNameInfoLabel
);
cy.get(commonSelectors.cancelButton).verifyVisibleElement(
"have.text",
commonText.cancelButton
);
cy.get(commonSelectors.createAppButton).verifyVisibleElement(
"have.text",
"+ Create app"
);
cy.get(commonSelectors.createAppButton).should("be.disabled");
cy.get(commonWidgetSelector.modalCloseButton).should("be.visible");
cy.clearAndType(commonSelectors.appNameInput, data.appName);
cy.get(commonWidgetSelector.modalCloseButton).click();
cy.get(commonSelectors.appCreateButton).click();
cy.get(commonSelectors.appNameInput).verifyVisibleElement(
"have.attr",
"placeholder",
commonText.enterAppName
);
cy.clearAndType(commonSelectors.appNameInput, data.appName);
cy.get(commonSelectors.cancelButton).click();
cy.get(commonSelectors.appCreateButton).click();
cy.get(commonSelectors.appNameInput).verifyVisibleElement(
"have.attr",
"placeholder",
commonText.enterAppName
);
cy.clearAndType(commonSelectors.appNameInput, data.appName);
cy.get(commonSelectors.createAppButton).should("be.enabled").click();
cy.go("back");
cy.visit("/my-workspace");
cy.wait(1000);
viewAppCardOptions(data.appName);
cy.get(commonSelectors.appCardOptions("Rename app")).verifyVisibleElement(
"have.text",
commonText.renameApp
);
cy.get(commonSelectors.appCardOptions("Rename app")).click();
cy.get(commonSelectors.renameApptitle).verifyVisibleElement(
"have.text",
commonText.renameApp
);
cy.get(commonSelectors.appNameLabel).verifyVisibleElement(
"have.text",
commonText.appName
);
cy.get(commonSelectors.appNameInput).verifyVisibleElement(
"have.value",
data.appName
);
cy.get(commonSelectors.appNameInfoLabel).verifyVisibleElement(
"have.text",
commonText.appNameInfoLabel
);
cy.get(commonSelectors.cancelButton).verifyVisibleElement(
"have.text",
commonText.cancelButton
);
cy.get(commonSelectors.renameAppButton).verifyVisibleElement(
"have.text",
commonText.renameApp
);
cy.get(commonSelectors.renameAppButton).should("be.disabled");
cy.get(commonWidgetSelector.modalCloseButton).should("be.visible");
cy.clearAndType(commonSelectors.appNameInput, data.rename);
cy.get(commonWidgetSelector.modalCloseButton).click();
viewAppCardOptions(data.appName);
cy.get(commonSelectors.appCardOptions("Rename app")).click();
cy.get(commonSelectors.appNameInput).verifyVisibleElement(
"have.value",
data.appName
);
cy.clearAndType(commonSelectors.appNameInput, data.rename);
cy.get(commonSelectors.cancelButton).click();
viewAppCardOptions(data.appName);
cy.get(commonSelectors.appCardOptions("Rename app")).click();
cy.get(commonSelectors.appNameInput).verifyVisibleElement(
"have.value",
data.appName
);
cy.clearAndType(commonSelectors.appNameInput, data.rename);
cy.get(commonSelectors.renameAppButton).should("be.enabled").click();
cy.verifyToastMessage(
commonSelectors.toastMessage,
"App name has been updated!"
);
viewAppCardOptions(data.rename);
cy.get(commonSelectors.appCardOptions(commonText.cloneAppOption)).click();
cy.get(commonSelectors.cloneAppTitle).verifyVisibleElement(
"have.text",
commonText.cloneAppOption
);
cy.get(commonSelectors.appNameLabel).verifyVisibleElement(
"have.text",
commonText.appName
);
cy.get(commonSelectors.appNameInput).verifyVisibleElement(
"have.value",
`${data.rename}_Copy`
);
cy.get(commonSelectors.appNameInfoLabel).verifyVisibleElement(
"have.text",
commonText.appNameInfoLabel
);
cy.get(commonSelectors.cancelButton).verifyVisibleElement(
"have.text",
commonText.cancelButton
);
cy.get(commonSelectors.cloneAppButton).verifyVisibleElement(
"have.text",
commonText.cloneAppOption
);
cy.get(commonSelectors.cloneAppButton).should("be.enabled");
cy.get(commonWidgetSelector.modalCloseButton).should("be.visible");
cy.clearAndType(commonSelectors.appNameInput, data.rename);
cy.get(commonWidgetSelector.modalCloseButton).click();
viewAppCardOptions(data.rename);
cy.get(commonSelectors.appCardOptions(commonText.cloneAppOption)).click();
cy.get(commonSelectors.appNameInput).verifyVisibleElement(
"have.value",
`${data.rename}_Copy`
);
cy.clearAndType(commonSelectors.appNameInput, data.cloneAppName);
cy.get(commonSelectors.cancelButton).click();
viewAppCardOptions(data.rename);
cy.get(commonSelectors.appCardOptions(commonText.cloneAppOption)).click();
cy.get(commonSelectors.appNameInput).verifyVisibleElement(
"have.value",
`${data.rename}_Copy`
);
cy.clearAndType(commonSelectors.appNameInput, data.cloneAppName);
cy.get(commonSelectors.cloneAppButton).should("be.enabled").click();
cy.go("back");
cy.visit("/my-workspace");
cy.get(commonSelectors.appCreateButton).click();
cy.clearAndType(commonSelectors.appNameInput, data.rename);
cy.get(commonSelectors.createAppButton).click();
cy.get(commonSelectors.appNameErrorLabel).verifyVisibleElement(
"have.text",
"App name already exists"
);
cy.get(commonSelectors.createAppButton).should("be.disabled");
});
it("Should verify the import app flow", () => {
cy.get(importSelectors.dropDownMenu).click();
cy.get(importSelectors.importOptionInput).eq(0).selectFile(appFile, {
force: true,
});
cy.get(commonSelectors.importAppTitle).verifyVisibleElement(
"have.text",
"Import app"
);
cy.get(commonSelectors.appNameLabel).verifyVisibleElement(
"have.text",
commonText.appName
);
cy.get(commonSelectors.appNameInput).verifyVisibleElement(
"have.value",
"test-app"
);
cy.get(commonSelectors.appNameInfoLabel).verifyVisibleElement(
"have.text",
commonText.appNameInfoLabel
);
cy.get(commonSelectors.cancelButton).verifyVisibleElement(
"have.text",
commonText.cancelButton
);
cy.get(commonSelectors.importAppButton).verifyVisibleElement(
"have.text",
"Import app"
);
cy.get(commonSelectors.importAppButton).should("be.enabled");
cy.get(commonWidgetSelector.modalCloseButton).should("be.visible");
cy.clearAndType(commonSelectors.appNameInput, data.appName);
cy.get(commonWidgetSelector.modalCloseButton).click();
cy.get(importSelectors.dropDownMenu).click();
cy.get(importSelectors.importOptionInput).eq(0).selectFile(appFile, {
force: true,
});
cy.get(commonSelectors.appNameInput).verifyVisibleElement(
"have.value",
"test-app"
);
cy.clearAndType(commonSelectors.appNameInput, data.appName);
cy.get(commonSelectors.cancelButton).click();
cy.get(importSelectors.dropDownMenu).click();
cy.get(importSelectors.importOptionInput).eq(0).selectFile(appFile, {
force: true,
});
cy.get(commonSelectors.appNameInput).verifyVisibleElement(
"have.value",
"test-app"
);
cy.clearAndType(commonSelectors.appNameInput, data.appName);
cy.get(commonSelectors.importAppButton).should("be.enabled").click();
cy.get(".go3958317564")
.should("be.visible")
.and("have.text", importText.appImportedToastMessage);
cy.go("back");
cy.visit("/my-workspace");
});
it("should verify the templates app creation", () => {
data.appName = `${fake.companyName}-App`;
cy.get(importSelectors.dropDownMenu).click();
cy.get(commonSelectors.chooseFromTemplateButton).click();
cy.get(".d-flex > .tj-primary-btn").click();
cy.get(commonSelectors.CreateAppFromTemplateButton).verifyVisibleElement(
"have.text",
"Create new app from template"
);
cy.get(commonSelectors.appNameLabel).verifyVisibleElement(
"have.text",
commonText.appName
);
cy.get(commonSelectors.appNameInput).verifyVisibleElement(
"have.value",
"Customer dashboard"
);
cy.get(commonSelectors.appNameInfoLabel).verifyVisibleElement(
"have.text",
commonText.appNameInfoLabel
);
cy.get(commonSelectors.cancelButton).verifyVisibleElement(
"have.text",
commonText.cancelButton
);
cy.get(commonSelectors.createAppButton).verifyVisibleElement(
"have.text",
"+ Create app"
);
cy.get(commonSelectors.createAppButton).should("be.enabled");
cy.get(commonWidgetSelector.modalCloseButton).should("be.visible");
cy.clearAndType(commonSelectors.appNameInput, data.appName);
cy.get(commonWidgetSelector.modalCloseButton).click();
cy.get(importSelectors.dropDownMenu).click();
cy.get(commonSelectors.chooseFromTemplateButton).click();
cy.get(".d-flex > .tj-primary-btn").click();
cy.get(commonSelectors.appNameInput).verifyVisibleElement(
"have.attr",
"placeholder",
commonText.enterAppName
);
cy.clearAndType(commonSelectors.appNameInput, data.appName);
cy.get(commonSelectors.cancelButton).click();
cy.get(importSelectors.dropDownMenu).click();
cy.get(commonSelectors.chooseFromTemplateButton).click();
cy.get(".d-flex > .tj-primary-btn").click();
cy.get(commonSelectors.appNameInput).verifyVisibleElement(
"have.attr",
"placeholder",
commonText.enterAppName
);
cy.clearAndType(commonSelectors.appNameInput, data.appName);
cy.get(commonSelectors.createAppButton).should("be.enabled").click();
});
});

View file

@ -48,12 +48,12 @@ describe("dashboard", () => {
installed_version: "2.9.2",
version_ignored: false,
}).as("version");
login();
cy.defaultWorkspaceLogin();
cy.wait("@emptyDashboard");
cy.wait("@folders");
cy.wait("@version");
// deleteDownloadsFolder();
cy.visitTheWorkspace('My workspace')
cy.visit('/my-workspace')
});
@ -274,7 +274,7 @@ describe("dashboard", () => {
viewAppCardOptions(data.appName);
cy.get(commonSelectors.appCardOptions(commonText.cloneAppOption)).click();
cy.get('[data-cy="Clone app"]').click();
cy.get('[data-cy="clone-app"]').click();
cy.get('.go3958317564').should('be.visible').and('have.text', dashboardText.appClonedToast)
cy.wait(3000);
cy.renameApp(data.cloneAppName);
@ -331,7 +331,7 @@ describe("dashboard", () => {
it("Should verify the app CRUD operation", () => {
data.appName = `${fake.companyName}-App`;
cy.appUILogin();
cy.defaultWorkspaceLogin();
cy.createApp(data.appName);
cy.dragAndDropWidget("Button", 450, 450);
@ -357,7 +357,7 @@ describe("dashboard", () => {
it("Should verify the folder CRUD operation", () => {
data.appName = `${fake.companyName}-App`;
cy.appUILogin();
cy.defaultWorkspaceLogin();
cy.createApp(data.appName);
cy.dragAndDropWidget("Button", 100, 100);

View file

@ -0,0 +1,174 @@
import { commonSelectors, commonWidgetSelector } from "Selectors/common";
import { groupsSelector } from "Selectors/manageGroups";
import { fake } from "Fixtures/fake";
import {
logout,
navigateToAppEditor,
navigateToManageGroups,
releaseApp,
} from "Support/utils/common";
import { commonText } from "Texts/common";
import { inviteUser } from "Support/utils/manageUsers";
import { userSignUp } from "Support/utils/onboarding";
describe("Redirection error pages", () => {
const data = {};
data.appName = `${fake.companyName} App`;
data.firstName = fake.firstName;
data.email = fake.email.toLowerCase();
data.slug = data.appName.toLowerCase().replace(/\s+/g, "-");
beforeEach(() => {
cy.apiLogin();
});
before(() => {
cy.apiLogin();
inviteUser(data.firstName, data.email);
logout();
});
it("Verify error modal in case of invalid app URL", () => {
cy.visit(`/applications/${data.lastName}`);
cy.get(commonSelectors.modalHeader).verifyVisibleElement(
"have.text",
"Invalid link"
);
cy.get(commonSelectors.modalDescription).verifyVisibleElement(
"have.text",
"The link you provided is invalid. Please check the link and try again."
);
cy.get(commonSelectors.backToHomeButton).verifyVisibleElement(
"have.text",
"Back to home page"
);
cy.get(commonSelectors.backToHomeButton).click();
cy.get(commonSelectors.pageSectionHeader).should("be.visible");
cy.logoutApi();
cy.visit(`/applications/${data.lastName}`);
cy.get(commonSelectors.backToHomeButton).click();
cy.get(commonSelectors.workEmailLabel).should("be.visible");
cy.apiLogin(data.email, "password");
cy.visit(`/applications/${data.lastName}`);
});
it("Verify error message in case of restricted access", () => {
data.appName = `${fake.companyName} App`;
cy.apiCreateApp(data.appName);
cy.openApp();
releaseApp();
cy.get(commonWidgetSelector.shareAppButton).click();
cy.clearAndType(commonWidgetSelector.appNameSlugInput, data.slug);
cy.wait(1000);
cy.logoutApi();
cy.apiLogin(data.email, "password");
cy.visit(`/applications/${data.slug}`);
cy.get(commonSelectors.modalHeader).verifyVisibleElement(
"have.text",
"Restricted access"
);
cy.get(commonSelectors.modalDescription).verifyVisibleElement(
"have.text",
"You dont have access to this app. Kindly contact admin to know more."
);
cy.get(commonSelectors.backToHomeButton).verifyVisibleElement(
"have.text",
"Back to home page"
);
cy.url().should("eq", "http://localhost:8082/error/restricted");
cy.get(commonSelectors.backToHomeButton).click();
cy.get(commonSelectors.pageSectionHeader).should("be.visible");
});
it("Verify error modal for app url of unreleased apps", () => {
data.appName = `${fake.companyName} App`;
data.slug = data.appName.toLowerCase().replace(/\s+/g, "-");
cy.apiCreateApp(data.appName);
cy.openApp();
cy.get(commonSelectors.leftSideBarSettingsButton).click();
cy.get(commonWidgetSelector.appSlugInput).clear();
cy.clearAndType(commonWidgetSelector.appSlugInput, data.slug);
cy.wait(1000);
cy.visit(`http://localhost:8082/applications/${data.slug}`);
cy.get(commonSelectors.modalHeader).verifyVisibleElement(
"have.text",
"URL unavailable"
);
cy.get(commonSelectors.modalDescription).verifyVisibleElement(
"have.text",
"This URL is not accessible because it has not been released yet. Please either release it or contact admin for access."
);
cy.get(commonSelectors.backToHomeButton).verifyVisibleElement(
"have.text",
"Back to home page"
);
cy.url().should("eq", "http://localhost:8082/error/url-unavailable");
cy.get(commonSelectors.backToHomeButton).click();
cy.get(commonSelectors.pageSectionHeader).should("be.visible");
cy.logoutApi();
cy.apiLogin(data.email, "password");
cy.wait(500);
cy.visit(`http://localhost:8082/applications/${data.slug}`);
cy.get(commonSelectors.modalHeader).verifyVisibleElement(
"have.text",
"Restricted access"
);
cy.get(commonSelectors.modalDescription).verifyVisibleElement(
"have.text",
"You dont have access to this app. Kindly contact admin to know more."
);
cy.get(commonSelectors.backToHomeButton).verifyVisibleElement(
"have.text",
"Back to home page"
);
cy.url().should("eq", "http://localhost:8082/error/restricted");
cy.get(commonSelectors.backToHomeButton).click();
cy.get(commonSelectors.pageSectionHeader).should("be.visible");
logout();
cy.defaultWorkspaceLogin();
navigateToManageGroups();
cy.wait(1000);
cy.get(groupsSelector.appSearchBox).click();
cy.wait(500);
cy.get(groupsSelector.searchBoxOptions).contains(data.appName).click();
cy.get(groupsSelector.selectAddButton).click();
cy.get("table").contains("td", data.appName);
cy.contains("td", data.appName)
.parent()
.within(() => {
cy.get("td input").eq(1).check();
});
cy.logoutApi();
cy.apiLogin(data.email, "password");
cy.wait(500);
cy.visit(`http://localhost:8082/applications/${data.slug}`);
cy.get(commonSelectors.modalHeader).verifyVisibleElement(
"have.text",
"URL unavailable"
);
cy.get(commonSelectors.modalDescription).verifyVisibleElement(
"have.text",
"This URL is not accessible because it has not been released yet. Please either release it or contact admin for access."
);
cy.get(commonSelectors.backToHomeButton).verifyVisibleElement(
"have.text",
"Back to home page"
);
cy.url().should("eq", "http://localhost:8082/error/url-unavailable");
cy.get(commonSelectors.backToHomeButton).click();
cy.get(commonSelectors.pageSectionHeader).should("be.visible");
});
});

View file

@ -11,7 +11,7 @@ const newGroupname = `New ${groupName}`;
describe("Manage Groups", () => {
before(() => {
cy.appUILogin();
cy.defaultWorkspaceLogin();
permissions.reset();
});
it("Should verify the elements and functionalities on manage groups page", () => {

View file

@ -11,6 +11,7 @@ describe("Manage SSO for multi workspace", () => {
const envVar = Cypress.env("environment");
beforeEach(() => {
cy.appUILogin();
cy.visit('/my-workspace');
});
it("Should verify General settings page elements", () => {
common.navigateToManageSSO();

View file

@ -17,7 +17,7 @@ data.groupName = fake.firstName.replaceAll("[^A-Za-z]", "");
describe("Manage Users", () => {
beforeEach(() => {
cy.appUILogin();
cy.defaultWorkspaceLogin();
});
let invitationToken,
organizationToken,
@ -74,7 +74,9 @@ describe("Manage Users", () => {
it("Should verify the confirm invite page and new user account", () => {
common.navigateToManageUsers();
users.inviteUser(data.firstName, data.email);
users.fillUserInviteForm(data.firstName, data.email);
cy.get(usersSelector.buttonInviteUsers).click();
users.fetchAndVisitInviteLink(data.email)
users.confirmInviteElements();
cy.clearAndType(commonSelectors.passwordInputField, "pass");
@ -89,7 +91,7 @@ describe("Manage Users", () => {
updateWorkspaceName(data.email);
common.logout();
cy.appUILogin();
cy.defaultWorkspaceLogin();
common.navigateToManageUsers();
common.searchUser(data.email);
cy.contains("td", data.email)
@ -120,7 +122,7 @@ describe("Manage Users", () => {
});
common.logout();
cy.visit('/');
cy.visit("/");
cy.clearAndType(commonSelectors.workEmailInputField, data.email);
cy.clearAndType(commonSelectors.passwordInputField, usersText.password);
cy.get(commonSelectors.loginButton).click();
@ -130,7 +132,7 @@ describe("Manage Users", () => {
cy.contains("My workspace").should("not.exist");
common.logout();
cy.appUILogin();
cy.defaultWorkspaceLogin();
common.navigateToManageUsers();
common.searchUser(data.email);
cy.contains("td", data.email)
@ -186,7 +188,7 @@ describe("Manage Users", () => {
cy.verifyToastMessage(commonSelectors.toastMessage, usersText.inviteToast);
cy.url().should("include", path.loginPath);
cy.appUILogin();
cy.defaultWorkspaceLogin();
common.navigateToManageUsers();
common.searchUser(data.email);
cy.contains("td", data.email)
@ -196,13 +198,19 @@ describe("Manage Users", () => {
});
});
it.skip("Should verify the user onboarding with groups", () => {
it("Should verify the user onboarding with groups", () => {
data.firstName = fake.firstName;
data.email = fake.email.toLowerCase().replaceAll("[^A-Za-z]", "");
common.navigateToManageUsers();
users.fillUserInviteForm(data.firstName, data.email);
cy.get(".dropdown-heading-value > .gray").click();
cy.wait(1500);
cy.get(".dropdown-heading-value > .gray").dblclick();
cy.get("body").then(($body) => {
if (!$body.find(".search > input").length > 0) {
cy.get(".dropdown-heading-value > .gray").click();
}
});
cy.clearAndType(".search > input", "Test");
cy.get(".no-options").verifyVisibleElement("have.text", "No options");
users.selectUserGroup("Admin");
@ -239,7 +247,8 @@ describe("Manage Users", () => {
cy.get(groupsSelector.createGroupButton).click();
cy.verifyToastMessage(
commonSelectors.toastMessage,
groupsText.groupCreatedToast)
groupsText.groupCreatedToast
);
common.navigateToManageUsers();
users.inviteUserWithUserGroup(
@ -248,9 +257,9 @@ describe("Manage Users", () => {
"All users",
data.groupName
);
common.logout()
common.logout();
cy.appUILogin()
cy.defaultWorkspaceLogin();
common.navigateToManageGroups();
cy.get(groupsSelector.groupLink(data.groupName)).click();
cy.get(groupsSelector.usersLink).click();

View file

@ -11,7 +11,7 @@ describe("Profile Settings", () => {
const randomLastName = fake.lastName;
const avatarImage = "cypress/fixtures/Image/tooljet.png";
beforeEach(() => {
cy.appUILogin();
cy.defaultWorkspaceLogin();
common.navigateToProfile();
});
@ -38,13 +38,6 @@ describe("Profile Settings", () => {
profileText.firstNameErrorToast
);
// cy.clearAndType(profileSelector.firstNameInput, profileText.firstName);
// cy.get(profileSelector.updateButton).click();
// cy.verifyToastMessage(
// commonSelectors.toastMessage,
// profileText.lastNameNameErrorToast
// );
cy.clearAndType(profileSelector.firstNameInput, randomFirstName);
cy.clearAndType(profileSelector.lastNameInput, randomLastName);
cy.get(profileSelector.updateButton).click();

View file

@ -1,161 +0,0 @@
import { commonSelectors, commonWidgetSelector } from "Selectors/common";
import { fake } from "Fixtures/fake";
import { logout, navigateToAppEditor, verifyTooltip, releaseApp } from "Support/utils/common";
import { commonText } from "Texts/common";
import { addNewUserMW } from "Support/utils/userPermissions";
import { userSignUp } from "Support/utils/onboarding";
describe("App share functionality", () => {
const data = {};
data.appName = `${fake.companyName} App`;
data.firstName = fake.firstName;
data.lastName = fake.lastName.replaceAll("[^A-Za-z]", "");
data.email = fake.email.toLowerCase();
const slug = data.appName.toLowerCase().replace(/\s+/g, "-");
const firstUserEmail = data.email
const envVar = Cypress.env("environment");
beforeEach(() => {
cy.appUILogin();
});
before(() => {
cy.apiLogin();
cy.apiCreateApp(data.appName);
cy.visit('/')
logout();
})
if (envVar === "Community") {
it("Verify private and public app share funtionality", () => {
cy.openApp(data.appName);
cy.dragAndDropWidget("Table", 250, 250);
verifyTooltip(commonWidgetSelector.shareAppButton, "Share URL is unavailable until current version is released")
cy.get('[data-cy="share-button-link"]>span').should("have.class", "share-disabled");
releaseApp();
cy.get(commonWidgetSelector.shareAppButton).click();
for (const elements in commonWidgetSelector.shareModalElements) {
cy.get(
commonWidgetSelector.shareModalElements[elements]
).verifyVisibleElement(
"have.text",
commonText.shareModalElements[elements]
);
}
cy.get(commonWidgetSelector.copyAppLinkButton).should("be.visible");
cy.get(commonWidgetSelector.makePublicAppToggle).should("be.visible");
cy.get(commonWidgetSelector.appLink).should("be.visible");
cy.get(commonWidgetSelector.appNameSlugInput).should("be.visible");
// cy.get(commonWidgetSelector.iframeLink).should("be.visible");
cy.get(commonWidgetSelector.modalCloseButton).should("be.visible");
cy.clearAndType(commonWidgetSelector.appNameSlugInput, `${slug}`);
cy.wait(2000);
cy.get(commonWidgetSelector.modalCloseButton).click();
cy.forceClickOnCanvas()
cy.get(commonSelectors.editorPageLogo).click();
logout();
cy.wait(2500);
cy.visit(`/applications/${slug}`);
cy.wait(2500);
cy.get(commonSelectors.loginButton).should("be.visible");
cy.clearAndType(commonSelectors.workEmailInputField, "dev@tooljet.io");
cy.clearAndType(commonSelectors.passwordInputField, "password");
cy.get(commonSelectors.loginButton).click();
cy.wait(500);
cy.get('[data-cy="draggable-widget-table1"]').should("be.visible");
cy.get(commonSelectors.viewerPageLogo).click();
navigateToAppEditor(data.appName);
cy.get(commonWidgetSelector.shareAppButton).click();
cy.get(commonWidgetSelector.makePublicAppToggle).check();
cy.get(commonWidgetSelector.modalCloseButton).click();
cy.get(commonSelectors.editorPageLogo).click();
logout();
cy.wait(2500);
cy.visit(`/applications/${slug}`);
cy.wait(2500);
cy.get('[data-cy="draggable-widget-table1"]').should("be.visible");
});
it("Verify app private and public app visibility for the same workspace user", () => {
navigateToAppEditor(data.appName);
cy.wait(2000);
cy.get(commonWidgetSelector.shareAppButton).click();
cy.get("body").then(($el) => {
if (!$el.text().includes("Embedded app link", { timeout: 2000 })) {
cy.get(commonWidgetSelector.makePublicAppToggle).check();
}
});
cy.get(commonWidgetSelector.modalCloseButton).click();
cy.get(commonSelectors.editorPageLogo).click();
addNewUserMW(data.firstName, data.email);
logout();
cy.visit(`/applications/${slug}`);
cy.get('[data-cy="draggable-widget-table1"]').should("be.visible");
cy.appUILogin();
navigateToAppEditor(data.appName);
cy.wait(2000);
cy.skipEditorPopover();
cy.get(commonWidgetSelector.shareAppButton).click();
cy.get(commonWidgetSelector.makePublicAppToggle).uncheck();
cy.get(commonWidgetSelector.modalCloseButton).click();
cy.get(commonSelectors.editorPageLogo).click();
logout();
cy.visit(`/applications/${slug}`);
cy.login(data.email, "password");
cy.get(commonSelectors.allApplicationLink).verifyVisibleElement(
"have.text",
commonText.allApplicationLink
);
});
it("Verify app private and public app visibility for the same instance user", () => {
data.firstName = fake.firstName;
data.email = fake.email.toLowerCase();
logout();
userSignUp(data.firstName, data.email, "Test");
cy.visit(`/applications/${slug}`);
cy.wait(1000);
cy.clearAndType(commonSelectors.workEmailInputField, data.email);
cy.clearAndType(commonSelectors.passwordInputField, "password");
cy.get(commonSelectors.signInButton).click();
cy.wait(1000);
cy.get(`[data-cy="workspace-sign-in-sub-header"]`).verifyVisibleElement(
"have.text",
"Sign in to your workspace - My workspace"
);
cy.visit("/");
cy.wait(2000);
logout();
cy.appUILogin();
navigateToAppEditor(data.appName);
cy.wait(2000);
cy.skipEditorPopover();
cy.get(commonWidgetSelector.shareAppButton).click();
cy.get(commonWidgetSelector.makePublicAppToggle).check();
cy.get(commonWidgetSelector.modalCloseButton).click();
cy.get(commonSelectors.editorPageLogo).click();
logout();
cy.visit(`/applications/${slug}`);
cy.get('[data-cy="draggable-widget-table1"]').should("be.visible");
cy.get(commonSelectors.viewerPageLogo).click();
});
}
});

View file

@ -29,8 +29,7 @@ describe("User permissions", () => {
cy.logoutApi();
});
beforeEach(() => {
cy.apiLogin();
cy.visit("/my-workspace");
cy.defaultWorkspaceLogin();
});
it("Should verify the create new app permission", () => {
@ -48,6 +47,7 @@ describe("User permissions", () => {
it("Should verify the View and Edit permission", () => {
common.navigateToManageGroups();
cy.wait(1000);
cy.get(groupsSelector.appSearchBox).click();
cy.get(groupsSelector.searchBoxOptions).contains(data.appName).click();
cy.get(groupsSelector.selectAddButton).click();
@ -58,7 +58,7 @@ describe("User permissions", () => {
cy.get("td input").first().should("be.checked");
});
common.logout();
cy.logoutApi();
cy.apiLogin(data.email, usersText.password);
cy.visit("/my-workspace");
cy.wait(500)
@ -78,9 +78,9 @@ describe("User permissions", () => {
});
common.logout();
cy.apiLogin();
cy.visit("/my-workspace");
cy.defaultWorkspaceLogin();
common.navigateToManageGroups();
cy.wait(500)
cy.contains("tr", data.appName)
.parent()
.within(() => {
@ -91,7 +91,7 @@ describe("User permissions", () => {
"App permissions updated"
);
common.logout();
cy.logoutApi();
cy.apiLogin(data.email, usersText.password);
cy.visit("/my-workspace");
cy.wait(500)
@ -122,7 +122,7 @@ describe("User permissions", () => {
it("Should verify the Create and Delete app permission", () => {
data.appName = `${fake.companyName}-App`;
cy.apiCreateApp(data.appName);
cy.visit('/my-workspace')
// cy.visit('/my-workspace')
cy.wait(500);
common.navigateToManageGroups();
@ -149,8 +149,7 @@ describe("User permissions", () => {
cy.contains("Delete app").should("exist");
common.logout();
cy.apiLogin();
cy.visit("/my-workspace");
cy.defaultWorkspaceLogin();
common.navigateToManageGroups();
cy.get(groupsSelector.permissionsLink).click();
cy.get(groupsSelector.appsDeleteCheck).uncheck();
@ -172,8 +171,7 @@ describe("User permissions", () => {
cy.get(commonSelectors.buttonSelector("Yes")).click();
common.logout
cy.apiLogin();
cy.visit("/my-workspace");
cy.defaultWorkspaceLogin();
common.navigateToManageGroups();
cy.get(groupsSelector.permissionsLink).click();
cy.get(groupsSelector.appsCreateCheck).uncheck();
@ -211,8 +209,7 @@ describe("User permissions", () => {
cy.get(commonSelectors.buttonSelector("Yes")).click();
common.logout();
cy.apiLogin();
cy.visit("/my-workspace");
cy.defaultWorkspaceLogin();
common.navigateToManageGroups();
cy.get(groupsSelector.permissionsLink).click();
cy.get(groupsSelector.foldersCreateCheck).uncheck();
@ -222,8 +219,7 @@ describe("User permissions", () => {
cy.visit("/my-workspace");
cy.wait(500)
cy.apiLogin();
cy.visit("/my-workspace");
cy.defaultWorkspaceLogin();
common.navigateToManageGroups();
cy.contains("td", data.appName)
.parent()

View file

@ -0,0 +1,304 @@
import { fake } from "Fixtures/fake";
import { commonSelectors, commonWidgetSelector } from "Selectors/common";
import { dashboardSelector } from "Selectors/dashboard";
import { inviteUser } from "Support/utils/manageUsers";
const data = {};
data.firstName = fake.firstName;
data.workspaceName = `${fake.firstName}-workspace`;
data.workspaceSlug = `${data.workspaceName.toLowerCase()}-slug`;
describe("Workspace", () => {
before(() => {
cy.appUILogin();
});
it("Should verify create and edit workspace modal and flow", () => {
cy.get(commonSelectors.workspaceName).click();
cy.get(commonSelectors.addWorkspaceButton).click();
cy.get(dashboardSelector.createWorkspaceTitle).verifyVisibleElement(
"have.text",
"Create workspace"
);
cy.get(commonWidgetSelector.modalCloseButton).should("be.visible");
cy.get(dashboardSelector.workspaceNameLabel).verifyVisibleElement(
"have.text",
"Workspace name"
);
cy.get(commonSelectors.workspaceNameInputField).verifyVisibleElement(
"have.attr",
"placeholder",
"Workspace name"
);
cy.get(dashboardSelector.workspaceNameInfoLabel).verifyVisibleElement(
"have.text",
"Name must be unique and max 50 characters"
);
cy.get(dashboardSelector.slugNameInputLabel).verifyVisibleElement(
"have.text",
"Unique workspace slug"
);
cy.get(dashboardSelector.workspaceSlugInputField).verifyVisibleElement(
"have.attr",
"placeholder",
"Unique workspace slug"
);
cy.get(dashboardSelector.slugInfoLabel).verifyVisibleElement(
"have.text",
"URL-friendly 'slug' consists of lowercase letters, numbers, and hyphens"
);
cy.get(dashboardSelector.workspaceLinkLabel).verifyVisibleElement(
"have.text",
"Workspace link"
);
cy.get(dashboardSelector.slugField).verifyVisibleElement(
"have.text",
"http://localhost:8082/<workspace-slug>"
);
cy.get(commonSelectors.cancelButton).verifyVisibleElement(
"have.text",
"Cancel"
);
cy.get(dashboardSelector.createWorkspaceButton).verifyVisibleElement(
"have.text",
"Create workspace"
);
cy.get(dashboardSelector.createWorkspaceButton).should("be.disabled");
cy.get(commonWidgetSelector.modalCloseButton).click();
cy.get(commonSelectors.workspaceName).click();
cy.get(commonSelectors.addWorkspaceButton).click();
cy.get(commonSelectors.workspaceNameInputField).type(" ").clear();
cy.get(dashboardSelector.workspaceErrorLabel).verifyVisibleElement(
"have.text",
"Workspace name can't be empty"
);
cy.clearAndType(commonSelectors.workspaceNameInputField, "My workspace");
cy.get(dashboardSelector.workspaceErrorLabel).verifyVisibleElement(
"have.text",
"Name must be unique"
);
cy.clearAndType(
commonSelectors.workspaceNameInputField,
data.workspaceName
);
cy.get(dashboardSelector.createWorkspaceButton).should("be.disabled");
cy.get(commonSelectors.workspaceNameInputField).clear();
cy.get(dashboardSelector.workspaceSlugInputField).type(" ").clear();
cy.get(dashboardSelector.inputLabelError).verifyVisibleElement(
"have.text",
"Workspace slug can't be empty"
);
cy.clearAndType(dashboardSelector.workspaceSlugInputField, " test");
cy.get(dashboardSelector.inputLabelError).verifyVisibleElement(
"have.text",
"Cannot contain spaces"
);
cy.clearAndType(dashboardSelector.workspaceSlugInputField, "!@#$%_^");
cy.get(dashboardSelector.inputLabelError).verifyVisibleElement(
"have.text",
"Special characters are not accepted."
);
cy.clearAndType(dashboardSelector.workspaceSlugInputField, "my-workspace");
cy.get(dashboardSelector.inputLabelError).verifyVisibleElement(
"have.text",
"Slug must be unique"
);
cy.clearAndType(
dashboardSelector.workspaceSlugInputField,
data.workspaceSlug
);
cy.get(dashboardSelector.slugSuccessLabel).verifyVisibleElement(
"have.text",
"Slug accepted!"
);
cy.get(dashboardSelector.slugField).verifyVisibleElement(
"have.text",
`http://localhost:8082/${data.workspaceSlug}`
);
cy.get(dashboardSelector.slugErrorLabel).verifyVisibleElement(
"have.text",
"Link updated successfully!"
);
cy.get(dashboardSelector.createWorkspaceButton).should("be.disabled");
cy.clearAndType(dashboardSelector.workspaceSlugInputField, "my-workspace");
cy.wait(1000);
cy.clearAndType(
commonSelectors.workspaceNameInputField,
data.workspaceName
);
cy.wait(1000);
cy.get(commonSelectors.cancelButton).click();
cy.wait(2000);
cy.get(commonSelectors.workspaceName).click();
cy.get(commonSelectors.addWorkspaceButton).click();
cy.get(commonSelectors.workspaceNameInputField).verifyVisibleElement(
"have.attr",
"placeholder",
"Workspace name"
);
cy.get(dashboardSelector.workspaceSlugInputField).verifyVisibleElement(
"have.attr",
"placeholder",
"Unique workspace slug"
);
cy.get(dashboardSelector.createWorkspaceButton).should("be.disabled");
cy.wait(1000);
cy.get(commonSelectors.workspaceNameInputField)
.clear()
.type(data.workspaceName);
cy.wait(1000);
cy.get(dashboardSelector.workspaceSlugInputField)
.clear()
.type(data.workspaceSlug);
cy.wait(4000);
cy.get(dashboardSelector.createWorkspaceButton)
.should("be.enabled")
.click();
cy.wait(1000);
cy.get(commonSelectors.workspaceName).verifyVisibleElement(
"have.text",
data.workspaceName
);
cy.url().should("eq", `http://localhost:8082/${data.workspaceSlug}`);
cy.get(commonSelectors.workspaceName).click();
cy.get(commonSelectors.editRectangleIcon).click();
cy.get(dashboardSelector.editWorkspaceTitle).verifyVisibleElement(
"have.text",
"Edit workspace"
);
cy.get(commonWidgetSelector.modalCloseButton).should("be.visible");
cy.get(dashboardSelector.workspaceNameLabel).verifyVisibleElement(
"have.text",
"Workspace name"
);
cy.get(commonSelectors.workspaceNameInputField).verifyVisibleElement(
"have.value",
data.workspaceName
);
cy.get(dashboardSelector.workspaceNameInfoLabel).verifyVisibleElement(
"have.text",
"Name must be unique and max 50 characters"
);
cy.get(dashboardSelector.slugNameInputLabel).verifyVisibleElement(
"have.text",
"Unique workspace slug"
);
cy.get(dashboardSelector.workspaceSlugInputField).verifyVisibleElement(
"have.value",
data.workspaceSlug
);
cy.get(dashboardSelector.slugInfoLabel).verifyVisibleElement(
"have.text",
"URL-friendly 'slug' consists of lowercase letters, numbers, and hyphens"
);
cy.get(dashboardSelector.workspaceLinkLabel).verifyVisibleElement(
"have.text",
"Workspace link"
);
cy.get(dashboardSelector.slugField).verifyVisibleElement(
"have.text",
`http://localhost:8082/${data.workspaceSlug}`
);
cy.get(commonSelectors.cancelButton).verifyVisibleElement(
"have.text",
"Cancel"
);
cy.get(commonSelectors.saveButton).verifyVisibleElement(
"have.text",
"Save"
);
cy.get(commonSelectors.saveButton).should("be.disabled");
cy.get(commonSelectors.workspaceNameInputField).clear();
cy.get(dashboardSelector.workspaceErrorLabel).verifyVisibleElement(
"have.text",
"Workspace name can't be empty"
);
cy.clearAndType(commonSelectors.workspaceNameInputField, "My workspace");
cy.get(dashboardSelector.workspaceErrorLabel).verifyVisibleElement(
"have.text",
"Name must be unique"
);
cy.get(dashboardSelector.workspaceSlugInputField).clear();
cy.get(dashboardSelector.inputLabelError).verifyVisibleElement(
"have.text",
"Workspace slug can't be empty"
);
cy.clearAndType(dashboardSelector.workspaceSlugInputField, " test");
cy.get(dashboardSelector.inputLabelError).verifyVisibleElement(
"have.text",
"Cannot contain spaces"
);
cy.clearAndType(dashboardSelector.workspaceSlugInputField, "!@#$%_^");
cy.get(dashboardSelector.inputLabelError).verifyVisibleElement(
"have.text",
"Special characters are not accepted."
);
cy.clearAndType(dashboardSelector.workspaceSlugInputField, "my-workspace");
cy.get(dashboardSelector.inputLabelError).verifyVisibleElement(
"have.text",
"Slug must be unique"
);
cy.get(dashboardSelector.workspaceSlugInputField).clear();
cy.get(commonSelectors.cancelButton).click();
cy.wait(3000);
cy.get(commonSelectors.workspaceName).click();
cy.get(commonSelectors.editRectangleIcon).click();
cy.get(commonWidgetSelector.modalCloseButton).click();
cy.get(commonSelectors.workspaceName).click();
cy.get(commonSelectors.editRectangleIcon).click();
cy.get(commonSelectors.workspaceNameInputField).verifyVisibleElement(
"have.value",
data.workspaceName
);
cy.get(dashboardSelector.workspaceSlugInputField).verifyVisibleElement(
"have.value",
data.workspaceSlug
);
cy.get(commonSelectors.saveButton).should("be.disabled");
data.workspaceName = `${fake.firstName}-workspace`;
data.workspaceSlug = `${data.workspaceName.toLowerCase()}-slug`;
cy.clearAndType(
commonSelectors.workspaceNameInputField,
data.workspaceName
);
cy.wait(1000);
cy.clearAndType(
dashboardSelector.workspaceSlugInputField,
data.workspaceSlug
);
cy.wait(1500);
cy.get(commonSelectors.saveButton).should("be.enabled").click();
cy.wait(1000);
cy.get(commonSelectors.workspaceName).verifyVisibleElement(
"have.text",
data.workspaceName
);
cy.url().should("eq", `http://localhost:8082/${data.workspaceSlug}`);
});
});

View file

@ -1,372 +0,0 @@
import { commonSelectors, commonWidgetSelector } from "Selectors/common";
import { fake } from "Fixtures/fake";
import { workspaceConstantsSelectors } from "Selectors/workspaceConstants";
import { workspaceConstantsText } from "Texts/workspaceConstants";
import { commonText, commonWidgetText } from "Texts/common";
import * as common from "Support/utils/common";
import {
contantsNameValidation,
AddNewconstants,
} from "Support/utils/workspaceConstants";
import { buttonText } from "Texts/button";
import {
verifyAndModifyParameter,
editAndVerifyWidgetName,
} from "Support/utils/commonWidget";
import { verifypreview } from "Support/utils/dataSource";
import {
selectQueryFromLandingPage,
query,
addInputOnQueryField,
} from "Support/utils/queries";
const data = {};
data.constName = fake.firstName.toLowerCase().replaceAll("[^A-Za-z]", "");
data.newConstvalue = `New ${data.constName}`;
data.constantsName = fake.firstName.toLowerCase().replaceAll("[^A-Za-z]", "");
data.constantsValue = "dJ_8Q~BcaMPd";
data.appName = `${fake.companyName}-App`;
data.slug = data.appName.toLowerCase().replace(/\s+/g, "-");
describe("Workspace constants", () => {
const envVar = Cypress.env("environment");
beforeEach(() => {
cy.appUILogin();
cy.intercept("GET", "/api/library_apps").as("homePage");
});
if (envVar === "Community") {
it("Verify workspace constants UI and CRUD operations", () => {
cy.get(commonSelectors.workspaceSettingsIcon).click();
cy.get(commonSelectors.workspaceConstantsOption)
.should(($el) => {
expect($el.contents().first().text().trim()).to.eq(
"Workspace constants"
);
})
.click();
cy.get(commonSelectors.breadcrumbTitle).should(($el) => {
expect($el.contents().first().text().trim()).to.eq(
"Workspace settings"
);
});
cy.get(commonSelectors.breadcrumbPageTitle).verifyVisibleElement(
"have.text",
" Workspace constants"
);
cy.get(
workspaceConstantsSelectors.workspaceConstantsHelperText
).verifyVisibleElement(
"have.text",
workspaceConstantsText.workspaceConstantsHelperText
);
cy.get(commonSelectors.documentationLink).verifyVisibleElement(
"have.text",
commonText.documentationLink
);
cy.get("body").then(($body) => {
if (
$body.find(workspaceConstantsSelectors.emptyStateImage).length > 0
) {
cy.get(workspaceConstantsSelectors.emptyStateImage).should(
"be.visible"
);
cy.get(
workspaceConstantsSelectors.emptyStateHeader
).verifyVisibleElement(
"have.text",
workspaceConstantsText.emptyStateHeader
);
cy.get(
workspaceConstantsSelectors.emptyStateText
).verifyVisibleElement(
"have.text",
workspaceConstantsText.emptyStateText
);
cy.get(
workspaceConstantsSelectors.addNewConstantButton
).verifyVisibleElement(
"have.text",
workspaceConstantsText.addNewConstantButton
);
}
});
cy.get(workspaceConstantsSelectors.addNewConstantButton).click();
cy.get(workspaceConstantsSelectors.contantFormTitle).verifyVisibleElement(
"have.text",
workspaceConstantsText.addConstatntText
);
cy.get(commonSelectors.nameLabel).verifyVisibleElement(
"have.text",
"Name"
);
cy.get(commonSelectors.nameInputField)
.invoke("attr", "placeholder")
.should("eq", "Enter Constant Name");
cy.get(commonSelectors.nameInputField).should("be.visible");
cy.get(commonSelectors.valueLabel).verifyVisibleElement(
"have.text",
"Value"
);
cy.get(commonSelectors.valueInputField)
.invoke("attr", "placeholder")
.should("eq", "Enter Value");
cy.get(commonSelectors.valueInputField).should("be.visible");
cy.get(commonSelectors.cancelButton).verifyVisibleElement(
"have.text",
"Cancel"
);
cy.get(
workspaceConstantsSelectors.addConstantButton
).verifyVisibleElement("have.text", "Add constant");
cy.get(workspaceConstantsSelectors.addConstantButton).should(
"be.disabled"
);
contantsNameValidation(" ", commonText.constantsNameError);
contantsNameValidation("9", commonText.constantsNameError);
contantsNameValidation("%", commonText.constantsNameError);
contantsNameValidation(
"ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`a",
"Maximum length has been reached"
);
contantsNameValidation(
"ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`afgg",
"Constant name should be between 1 and 32 characters"
);
cy.clearAndType(commonSelectors.valueInputField, " ");
cy.get(commonSelectors.valueErrorText).verifyVisibleElement(
"have.text",
commonText.constantsValueError
);
cy.get(workspaceConstantsSelectors.addConstantButton).should(
"be.disabled"
);
cy.get(commonSelectors.cancelButton).click();
cy.get(workspaceConstantsSelectors.addNewConstantButton).click();
cy.clearAndType(commonSelectors.nameInputField, data.constName);
cy.clearAndType(commonSelectors.valueInputField, data.constName);
cy.get(workspaceConstantsSelectors.addConstantButton).should(
"be.enabled"
);
cy.get(commonSelectors.cancelButton).click();
cy.get(workspaceConstantsSelectors.constantName(data.constName)).should(
"not.exist"
);
cy.get(workspaceConstantsSelectors.addNewConstantButton).click();
cy.clearAndType(commonSelectors.nameInputField, data.constName);
cy.clearAndType(commonSelectors.valueInputField, data.constName);
cy.get(workspaceConstantsSelectors.addConstantButton).click();
cy.verifyToastMessage(
commonSelectors.toastMessage,
workspaceConstantsText.constantCreatedToast
);
cy.get(workspaceConstantsSelectors.addNewConstantButton).click();
contantsNameValidation(
data.constName,
"Constant with this name already exists in Production environment"
);
cy.get(commonSelectors.cancelButton).click();
cy.get(workspaceConstantsSelectors.envName).verifyVisibleElement(
"have.text",
"Production"
);
cy.get(
workspaceConstantsSelectors.addNewConstantButton
).verifyVisibleElement("have.text", "Create new constant");
cy.get(
workspaceConstantsSelectors.constantsTableNameHeader
).verifyVisibleElement("have.text", "Name");
cy.get(
workspaceConstantsSelectors.constantsTableValueHeader
).verifyVisibleElement("have.text", "Value");
cy.get(
workspaceConstantsSelectors.constantName(data.constName)
).verifyVisibleElement("have.text", data.constName);
cy.get(
workspaceConstantsSelectors.constantValue(data.constName)
).verifyVisibleElement("have.text", data.constName);
cy.get(
workspaceConstantsSelectors.constEditButton(data.constName)
).verifyVisibleElement("have.text", "Edit");
cy.get(
workspaceConstantsSelectors.constDeleteButton(data.constName)
).verifyVisibleElement("have.text", "Delete");
cy.get(commonSelectors.pagination).should("be.visible");
cy.get(
workspaceConstantsSelectors.constEditButton(data.constName)
).click();
cy.get(workspaceConstantsSelectors.contantFormTitle).verifyVisibleElement(
"have.text",
"Update constant in production "
);
cy.get(commonSelectors.nameLabel).verifyVisibleElement(
"have.text",
"Name"
);
cy.get(commonSelectors.nameInputField).should(
"have.value",
data.constName
);
cy.get(commonSelectors.nameInputField)
.should("be.visible")
.and("be.disabled");
cy.get(commonSelectors.valueLabel).verifyVisibleElement(
"have.text",
"Value"
);
cy.get(commonSelectors.valueInputField)
.should("be.visible")
.and("have.value", data.constName);
cy.get(commonSelectors.cancelButton).verifyVisibleElement(
"have.text",
"Cancel"
);
cy.get(
workspaceConstantsSelectors.addConstantButton
).verifyVisibleElement("have.text", "Update");
cy.get(workspaceConstantsSelectors.addConstantButton).should(
"be.disabled"
);
cy.clearAndType(commonSelectors.valueInputField, data.newConstvalue);
cy.get(workspaceConstantsSelectors.addConstantButton).should(
"be.enabled"
);
cy.get(commonSelectors.cancelButton).click();
cy.get(
workspaceConstantsSelectors.constantValue(data.constName)
).verifyVisibleElement("have.text", data.constName);
cy.get(
workspaceConstantsSelectors.constEditButton(data.constName)
).click();
cy.clearAndType(commonSelectors.valueInputField, data.newConstvalue);
cy.get(workspaceConstantsSelectors.addConstantButton).click();
cy.verifyToastMessage(
commonSelectors.toastMessage,
"Constant updated successfully"
);
cy.get(
workspaceConstantsSelectors.constantValue(data.constName)
).verifyVisibleElement("have.text", data.newConstvalue);
cy.get(
workspaceConstantsSelectors.constDeleteButton(data.constName)
).click();
cy.get(commonSelectors.modalMessage).verifyVisibleElement(
"have.text",
`Are you sure you want to delete ${data.constName} from production?`
);
cy.get(commonSelectors.cancelButton).verifyVisibleElement(
"have.text",
"Cancel"
);
cy.get(commonSelectors.yesButton).verifyVisibleElement(
"have.text",
"Yes"
);
cy.get(commonSelectors.cancelButton).click();
cy.get(
workspaceConstantsSelectors.constantValue(data.constName)
).verifyVisibleElement("have.text", data.newConstvalue);
cy.get(
workspaceConstantsSelectors.constDeleteButton(data.constName)
).click();
cy.get(commonSelectors.yesButton).click();
cy.get(workspaceConstantsSelectors.constantValue(data.constName)).should(
"not.exist"
);
cy.verifyToastMessage(
commonSelectors.toastMessage,
"Constant deleted successfully"
);
});
}
it("should verify the constants resolving value on components and query", () => {
common.navigateToworkspaceConstants();
AddNewconstants(data.constantsName, data.constantsValue);
cy.get(
workspaceConstantsSelectors.constantName(data.constantsName)
).verifyVisibleElement("have.text", data.constantsName);
cy.get(
workspaceConstantsSelectors.constantValue(data.constantsName)
).verifyVisibleElement("have.text", data.constantsValue);
cy.get(commonSelectors.homePageLogo).click();
cy.wait("@homePage");
cy.createApp(data.appName);
selectQueryFromLandingPage("runjs", "JavaScript");
addInputOnQueryField("runjs", `return constants.${data.constantsName}`);
query("preview");
verifypreview("raw", "dJ_8Q~BcaMPd");
cy.dragAndDropWidget("Text", 550, 350);
editAndVerifyWidgetName(data.constantsName);
cy.waitForAutoSave();
verifyAndModifyParameter("Text", `{{constants.${data.constantsName}`);
cy.forceClickOnCanvas();
cy.waitForAutoSave();
common.pinInspector();
cy.get(".tooltip-inner").invoke("hide");
cy.get(commonWidgetSelector.sidebarinspector).click();
cy.get(commonWidgetSelector.inspectorNodeComponents).click();
cy.get(commonWidgetSelector.nodeComponent(data.constantsName)).click();
cy.get('[data-cy="inspector-node-text"] > .mx-2').verifyVisibleElement(
"have.text",
`"dJ_8Q~BcaMPd"`
);
cy.get('[data-cy="inspector-node-constants"] > .node-key').click();
cy.get(`[data-cy="inspector-node-${data.constantsName}"] > .node-key`)
.eq(1)
.verifyVisibleElement("have.text", data.constantsName);
cy.get(
`[data-cy="inspector-node-${data.constantsName}"] > .mx-2`
).verifyVisibleElement("have.text", `"dJ_8Q~BcaMPd"`);
cy.get('[data-cy="button-release"]').click();
cy.get('[data-cy="yes-button"]').click();
cy.verifyToastMessage(commonSelectors.toastMessage, "Version v1 released");
cy.get(commonWidgetSelector.shareAppButton).click();
cy.clearAndType(commonWidgetSelector.appNameSlugInput, `${data.slug}`);
cy.wait(1500);
cy.get(commonWidgetSelector.modalCloseButton).click();
cy.forceClickOnCanvas();
cy.waitForAutoSave();
cy.wait(500)
cy.openInCurrentTab(commonWidgetSelector.previewButton);
cy.wait(4000);
cy.get(
commonWidgetSelector.draggableWidget(data.constantsName)
).verifyVisibleElement("have.text", "dJ_8Q~BcaMPd");
cy.get('[data-cy="viewer-page-logo"]').click();
cy.wait("@homePage");
cy.visit(`/applications/${data.slug}`);
cy.wait(4000);
cy.get(
commonWidgetSelector.draggableWidget(data.constantsName)
).verifyVisibleElement("have.text", "dJ_8Q~BcaMPd");
});
});

View file

@ -1,3 +1,4 @@
import { deleteDownloadsFolder } from "Support/utils/common";
import {
databaseSelectors,
createNewColumnSelectors,
@ -5,12 +6,14 @@ import {
filterSelectors,
sortSelectors,
editRowSelectors,
bulkUploadDataSelectors,
} from "Selectors/database";
import {
databaseText,
createNewColumnText,
createNewRowText,
editRowText,
bulkUploadDataText,
} from "Texts/database";
import { commonSelectors } from "Selectors/common";
import { commonText } from "Texts/common";
@ -28,6 +31,10 @@ export const verifyAllElementsOfPage = () => {
//cy.get(databaseSelectors.searchTableInputField).should("be.visible");
cy.get(databaseSelectors.allTablesSection).should("be.visible");
cy.get(databaseSelectors.allTableSubheader).should("be.visible");
cy.get(createNewColumnSelectors.addNewColumnButton).should("be.visible");
cy.get(createNewRowSelectors.addNewRowButton).should("be.visible");
cy.get(editRowSelectors.editRowbutton).should("be.visible");
cy.get(bulkUploadDataSelectors.bulkUploadDataButton).should("be.visible");
};
export const navigateToTable = (tableName) => {
cy.get(databaseSelectors.currentTable(tableName))
@ -74,16 +81,22 @@ export const createTableAndVerifyToastMessage = (
databaseText.noRecordsText
);
};
export const editTableNameAndVerifyToastMessage = (tableName, newTableName) => {
export const selectTableOperationOption = (tableName, operationOption) => {
navigateToTable(tableName);
cy.get(databaseSelectors.currentTable(tableName))
.find(databaseSelectors.tableKebabIcon)
.invoke("show")
.trigger("mouseover")
.trigger("mouseover")
.trigger("mousemove")
.trigger("mousedown")
.trigger("mouseup")
.click();
cy.get(databaseSelectors.tableEditOption).click();
cy.get(operationOption).click();
cy.wait(500);
};
export const editTableNameAndVerifyToastMessage = (tableName, newTableName) => {
selectTableOperationOption(tableName, databaseSelectors.tableEditOption);
cy.get(databaseSelectors.editTableHeader).verifyVisibleElement(
"have.text",
databaseText.editTableHeader
@ -111,18 +124,11 @@ export const editTableNameAndVerifyToastMessage = (tableName, newTableName) => {
);
};
export const deleteTableAndVerifyToastMessage = (tableName) => {
cy.get(databaseSelectors.currentTable(tableName))
.find(databaseSelectors.tableKebabIcon)
.invoke("show")
.trigger("mouseover")
.trigger("mousemove")
.trigger("mousedown")
.trigger("mouseup")
.click();
cy.get(databaseSelectors.tableDeleteOption).click();
selectTableOperationOption(tableName, databaseSelectors.tableDeleteOption);
// cy.on('window:confirm', (ConfirmAlertText) => {
// expect(ConfirmAlertText).to.contains(`Are you sure you want to delete the table "${tableName}"?`);
// });
cy.wait(500);
cy.verifyToastMessage(
commonSelectors.toastMessage,
databaseText.tableDeletedSuccessfullyToast(tableName)
@ -491,7 +497,6 @@ export const editRowAndVerify = (
);
verifyRowData(rowNumber, columnName, rowFieldData);
};
export const editRowWithInvalidData = (
tableName,
rowNumber,
@ -540,3 +545,73 @@ export const editRowWithInvalidData = (
);
cy.get(commonSelectors.buttonSelector(commonText.cancelButton)).click();
};
export const exportTableAndVerify = (tableName, columnName) => {
deleteDownloadsFolder();
cy.reload();
selectTableOperationOption(tableName, databaseSelectors.tableExportOption);
verifyDownloadedTableSchema(tableName, columnName);
cy.exec("cd ./cypress/downloads/ && rm -rf *");
};
export const verifyDownloadedTableSchema = (tableName, columnName) => {
cy.exec("ls ./cypress/downloads/").then((result) => {
const downloadedExportTableFileName = result.stdout.split("\n")[0];
let exportedTableFilePath = `cypress/downloads/${downloadedExportTableFileName}`;
cy.readFile(exportedTableFilePath).then((table) => {
let exportedTableData = table;
expect(downloadedExportTableFileName).to.contain.string(
tableName.toLowerCase()
);
for (let i = 0; i <= columnName.length - 1; i++) {
cy.get(databaseSelectors.columnHeader(columnName[i])).each(($el) => {
cy.wrap($el)
.should("be.visible")
.and(
"contain.text",
exportedTableData.tooljet_database[0].schema.columns[
i
].column_name.toLowerCase()
);
});
}
});
});
};
export const bulkUploadDataTemplateDownloadAndVerify = (
tableName,
columnName
) => {
deleteDownloadsFolder();
cy.reload();
cy.intercept("GET", "api/tooljet_db/organizations/**").as("dbLoad");
navigateToTable(tableName);
cy.wait(1000);
cy.get(bulkUploadDataSelectors.bulkUploadbuttonText).verifyVisibleElement(
"have.text",
bulkUploadDataText.bulkUploadbuttonText
);
cy.get(bulkUploadDataSelectors.bulkUploadDataButton)
.should("be.visible")
.click();
cy.get(bulkUploadDataSelectors.bulkUploadDataHeaderText).verifyVisibleElement(
"have.text",
bulkUploadDataText.bulkUploadbuttonText
);
cy.get(bulkUploadDataSelectors.templateHelperText).verifyVisibleElement(
"have.text",
bulkUploadDataText.templateHelperText
);
cy.get(bulkUploadDataSelectors.templateDownloadButton)
.should("be.visible")
.click();
cy.readFile(`cypress/downloads/${tableName}.csv`, "utf-8").then((table) => {
let exportedTableData = table.split(",");
cy.log(exportedTableData);
for (let i = 0; i <= columnName.length - 1; i++) {
cy.get(databaseSelectors.columnHeader(columnName[i])).each(($el) => {
cy.wrap($el)
.should("be.visible")
.and("contain.text", exportedTableData[i].toLowerCase());
});
}
});
};

View file

@ -132,14 +132,10 @@ export const manageUsersElements = () => {
};
export const inviteUser = (firstName, email) => {
fillUserInviteForm(firstName, email);
cy.get(usersSelector.buttonInviteUsers).click();
// cy.verifyToastMessage(
// commonSelectors.toastMessage,
// usersText.userCreatedToast
// );
cy.wait(1000)
cy.userInviteApi(firstName, email);
fetchAndVisitInviteLink(email);
cy.clearAndType(commonSelectors.passwordInputField, "password");
cy.get(commonSelectors.acceptInviteButton).click();
};
export const confirmInviteElements = () => {
@ -233,8 +229,8 @@ export const inviteUserWithUserGroup = (firstName, email, group1, group2) => {
usersText.userCreatedToast
);
// copyInvitationLink(firstName, email);
cy.wait(1000)
fetchAndVisitInviteLink(email)
cy.wait(1000);
fetchAndVisitInviteLink(email);
cy.clearAndType(commonSelectors.passwordInputField, "password");
cy.get(commonSelectors.acceptInviteButton).click();
};
@ -266,14 +262,16 @@ export const fillUserInviteForm = (firstName, email) => {
};
export const selectUserGroup = (groupName) => {
cy.wait(500)
cy.wait(1500);
cy.get("body").then(($body) => {
if (!$body.find(".search > input").length > 0) {
cy.get(".dropdown-heading-value > .gray").click();
cy.clearAndType(".search > input", groupName);
cy.wait(500);
cy.get("li > .select-item > .item-renderer").last().click();
} else {
cy.clearAndType(".search > input", groupName);
cy.wait(500);
cy.get("li > .select-item > .item-renderer").last().click();
}
});
@ -311,11 +309,11 @@ export const fetchAndVisitInviteLink = (email) => {
organizationToken = resp.rows[1].invitation_token;
url = `/invitations/${invitationToken}/workspaces/${organizationToken}?oid=${workspaceId}`;
common.logout();
cy.logoutApi();
cy.wait(1000);
cy.visit(url);
});
});
});
});
};
};

View file

@ -10,8 +10,7 @@ import { dashboardSelector } from "Selectors/dashboard";
export const adminLogin = () => {
common.logout();
cy.appUILogin();
cy.wait(2000);
cy.defaultWorkspaceLogin();
common.navigateToManageGroups();
};
@ -47,8 +46,6 @@ export const reset = () => {
export const addNewUserMW = (firstName, email, companyName) => {
common.navigateToManageUsers();
users.inviteUser(firstName, email);
cy.clearAndType(commonSelectors.passwordInputField, usersText.password);
cy.get(commonSelectors.acceptInviteButton).click();
cy.get(commonSelectors.workspaceName).verifyVisibleElement(
"have.text",
"My workspace"

View file

@ -8,7 +8,7 @@ SECRET_KEY_BASE= #replace_with_secret_key_base
# DATABASE CONFIG
ORM_LOGGING=all
PG_DB= # Databse name
PG_DB= # Database name
PG_USER= # Postgres database username
PG_HOST= # Postgres database host
PG_PASS= # Postgres database password

View file

@ -90,4 +90,52 @@ The dropdown will display all the apps associated with your account. Select an a
| resource_id | Different [resources](#select-resources) have their respective IDs associated with them. These IDs are assigned when the resources are created. |
| resource_name | Shows the name of the [resources](#select-resources) that were involved in the logged event. For example, if an app was created or deleted, it will display the name of that app. |
| resource_type | Indicates the type of the [resources](#select-resources) involved in the logged event. |
| user_id | Each user account in ToolJet has a unique ID associated with it, which is recorded when an event occurs. |
| user_id | Each user account in ToolJet has a unique ID associated with it, which is recorded when an event occurs. |
### 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.
#### Log Rotation
The log file is configured to rotate on a daily basis. This means that a new log file will be created every day, ensuring efficient management and organization of audit data.
#### Log File Path
The path for the log file is defined using the `LOG_FILE_PATH` variable in the environment. It's important to understand that this path is relative to the home directory of the machine. For instance, if `LOG_FILE_PATH` is set to `hsbc/dashboard/log`, the resulting log file path will be structured as follows:
```
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 |
| -------- | --------------------------------------------------------------------------- |
| LOG_FILE_PATH | the path where the log file will be created ( eg: tooljet/log/tooljet-audit.log) |
<details>
<summary>Example Log file data</summary>
```bash
{
level: 'info',
message: 'PERFORM APP_CREATE OF awdasdawdwd APP',
timestamp: '2023-11-02 17:12:40',
auditLog: {
userId: '0ad48e21-e7a2-4597-9568-c4535aedf687',
organizationId: 'cf8e132f-a68a-4c81-a0d4-3617b79e7b17',
resourceId: 'eac02f79-b8e2-495a-bffe-82633416c829',
resourceType: 'APP',
actionType: 'APP_CREATE',
resourceName: 'awdasdawdwd',
ipAddress: '::1',
metadata: {
userAgent: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36',
tooljetVersion: '2.22.2-ee2.8.3'
}
},
label: 'APP'
}
```
</details>

View file

@ -81,12 +81,12 @@ 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
## Instance Settings
## Settings
Only Super Admins can access the Instance Settings:
Only Super Admins can access the Settings:
- **All Users**
- **Manage Instance Settings**
- **Manage Settings**
- **License**
- **White labelling**
@ -116,7 +116,7 @@ Super Admins can go to **All Users** page, Under the **Workspaces** column they'
### Make the user super admin
Super Admins can make any user as Super Admin or remove any Super Admin from the **Manage All Users** in the Instance Settings page.
Super Admins can make any user as Super Admin or remove any Super Admin from the **Manage All Users** in the Settings page.
Click on the **Edit** button next to any user, **Enable** the **Make the user Super Admin** option, and then **Save** it.
@ -128,7 +128,7 @@ The user will become Super Admin and the Type column will update from **`workspa
</div>
## Manage Instance Settings
## Manage Settings
<div style={{textAlign: 'center'}}>
@ -140,15 +140,15 @@ The user will become Super Admin and the Type column will update from **`workspa
When a user joins a workspace, they are provided with their own personal workspace and option to create new workspaces.
Super Admins can **control** this behavior from the Manage Instance Settings page, they can **toggle off** the option to **Allow personal workspace**. Now whenever a user joins a workspace they won't be provided a personal workspace nor they will be able to create a new workspace in the instance.
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
Super Admins can enable multiplayer editing from the Manage Instance Settings page. Once enabled, users will be able to edit the same app simultaneously resulting in real-time collaboration.
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.
## License
Manage the instance license via the **Instance Settings** page. Super Admins have the capability to update the instance's license key from this page.
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.

View file

@ -35,7 +35,7 @@ With this feature, you gain the ability to rebrand the following key elements:
## Configuration
To enable white labelling, you'll need to go to the **Instance Settings** from the Dashboard and click on the `White labelling` tab. On the White labelling page, you'll be able to configure the following:
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:
- **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`.

View file

@ -0,0 +1,117 @@
---
id: codespaces
title: GitHub Codespaces
---
Follow the steps below to set up ToolJet on GitHub Codespaces. We recommend reading our guide on [architecture](https://docs.tooljet.com/docs/contributing-guide/setup/architecture) of ToolJet before proceeding.
Open the terminal and run the commands below.
## Setting up
### 1. Set up the environment
1. Install Node.js ( version: v18.3.0 ) and npm (version: v8.11.0)
```
nvm install 18.3.0
nvm use 18.3.0
npm install -g npm@8.11.0
```
2. Install Postgres
```
sudo sh -c 'echo "deb [http://apt.postgresql.org/pub/repos/apt](http://apt.postgresql.org/pub/repos/apt) $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list'
wget --quiet -O - [https://www.postgresql.org/media/keys/ACCC4CF8.asc](https://www.postgresql.org/media/keys/ACCC4CF8.asc) | sudo apt-key add -
sudo apt-get update
sudo apt-get install postgresql-13 postgresql-contrib-13
```
To start the postgresql service run the below command:
```
sudo service postgresql start
```
If you wish to change the password of the installed postresql service run the below commands:
```
sudo su
sudo -u postgres psql
\password postgres
\q
```
### 2. Set up environment variables
Create a `.env` file by running the command `touch .env`. More information on the variables that can be set is given in the [environment variables reference](https://docs.tooljet.com/docs/setup/env-vars)
**For basic set-up you add the below env variables:**
```
TOOLJET_HOST=http://localhost:3000
LOCKBOX_MASTER_KEY=
SECRET_KEY_BASE=
PG_USER=postgres
PG_HOST=localhost
PG_PASS=postgres
PG_DB=tooljet_prod
SUB_PATH=/apps/tooljet/
NODE_ENV=production
SERVE_CLIENT=true
```
> `SECRET_KEY_BASE` requires a 64 byte key. (If you have `openssl` installed, run `openssl rand -hex 64` to create a 64 byte secure random key)
>
> `LOCKBOX_MASTER_KEY` requires a 32 byte key. (Run `openssl rand -hex 32` to create a 32 byte secure random key)
### 3. Install and build dependencies
Make sure node version is set to 18.3.0 before running the below command:
```
npm install
npm install --prefix server
npm install --prefix frontend
npm run build:plugins
```
### 4. Set up database
```
npm run --prefix server db:create
npm run --prefix server db:mirgate
```
If at any point you need to reset the database, use this command `npm run --prefix server db:reset`
### 5. Build client
```
cd ./frontend && NODE=production npm run build
```
### 6. Run server
```
cd ./server && npm run start:prod
```
The client will start on the **port 3000**, you can access the client by visiting the url created by codespace - `https://<url>/apps/tooljet`

View file

@ -5,7 +5,7 @@ title: Dashboard
The ToolJet Dashboard is the initial landing page that you see upon logging into your workspace. This interface serves as a central hub where you can access a variety of features. Primarily, it displays all the applications you've created within ToolJet. Moreover, you have the capability to create new workspaces and applications directly from this dashboard. Additionally, it provides an option to create folders for categorizing and managing applications for easier organization, access control, and workflow management.
Furthermore, the dashboard serves as a gateway to various essential sections, such as **[Workflows](/docs/workflows/overview)**, **[ToolJet Database](/docs/tooljet-database)**, **[Data Sources](/docs/data-sources/overview)**, **[Marketplace](/docs/marketplace/marketplace-overview)**, **[Workspace Settings](/docs/tutorial/manage-users-groups)**, **[Instance Settings](/docs/enterprise/superadmin/#instance-settings)**, and **[Audit logs](/docs/enterprise/audit_logs/)**. You can effortlessly navigate to these sections directly from the dashboard.
Furthermore, the dashboard serves as a gateway to various essential sections, such as **[Workflows](/docs/workflows/overview)**, **[ToolJet Database](/docs/tooljet-database)**, **[Data Sources](/docs/data-sources/overview)**, **[Marketplace](/docs/marketplace/marketplace-overview)**, **[Workspace Settings](/docs/tutorial/manage-users-groups)**, **[Settings](/docs/enterprise/superadmin/#settings)**, and **[Audit logs](/docs/enterprise/audit_logs/)**. You can effortlessly navigate to these sections directly from the dashboard.
<div style={{textAlign: 'center'}}>
@ -207,7 +207,7 @@ This option allows you to select a specific version of the app to export or expo
#### Export ToolJet table schema
Selecting this option will inclue 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.
@ -245,4 +245,4 @@ The current version of ToolJet is displayed on the top right corner of the dashb
<img className="screenshot-full" src="/img/dashboard/currentversion.png" alt="Dashboard"/>
</div>
</div>

View file

@ -13,7 +13,7 @@ ToolJet uses this [NodeJS](https://github.com/TimonKK/clickhouse) client for Cli
## Connection
To add a new ClickHouse datasource, Go to the **Datasource Manager** on the left sidebar of the app editor and click on `Add datasource` button. Select **ClickHouse** from the modal that pops up.
To establish a connection with the Clickhouse data source, you can either click on the `+Add new data source` button located on the query panel or navigate to the **[Data Sources](/docs/data-sources/overview)** page through the ToolJet dashboard.
ToolJet requires the following to connect to your ClickHouse Database:
@ -33,7 +33,7 @@ ToolJet requires the following to connect to your ClickHouse Database:
## Querying ClickHouse
After setting up the ClickHouse datasource, you can click on the `+` button of the query manager and select the ClickHouse datasource that you added in the previous step to create a new query.
After setting up the ClickHouse data source, you can click on the `+` button of the query manager and select the ClickHouse data source that you added in the previous step to create a new query.
:::info
For more details on clickhouse visit [Clickhouse docs](https://clickhouse.com/docs/en/quick-start).

View file

@ -7,11 +7,11 @@ title: MongoDB
ToolJet can connect to MongoDB to read and write data.
## Connection
## Manual Connection
Please make sure the host/ip of the database is accessible from your VPC if you have self-hosted ToolJet. If you are using ToolJet cloud, please whitelist our IP.
To establish a connection with the MongoDB data source, click on the `+Add new data source` button located on the query panel or navigate to the [Data Sources](https://docs.tooljet.com/docs/data-sources/overview) page from the ToolJet dashboard.
To establish a manual connection with the MongoDB data source, click on the `+Add new data source` button located on the query panel or navigate to the [Data Sources](https://docs.tooljet.com/docs/data-sources/overview) page from the ToolJet dashboard.
ToolJet requires the following to connect to your MongoDB.
@ -26,6 +26,20 @@ It is recommended to create a new MongoDB user so that you can control the acces
Click on 'Test connection' button to verify if the credentials are correct and that the database is accessible to ToolJet server. Click on 'Save' button to save the data source.
## Connect Using Connecting String
You can also use a **Connection String** by switching the method from the dropdown. You will be prompted to enter the details of your MongoDB connection.
The primary piece of information you need here is your MongoDB connection string. The connection string typically looks like this:
`mongodb+srv://${username}:${password}@${cluster}/{database}`.
For example: `mongodb+srv://tooljettest:fakepassword@cluster0.urul7.mongodb.net/hrms`
<img className="screenshot-full" src="/img/datasource-reference/mongo-db/mongodb-connection-string.png" alt="ToolJet - Mongo connection" height="250"/>
Make sure to replace username, password, cluster, and database with your actual MongoDB details. If your MongoDB instance requires additional connection options, you can usually append these options to the connection string.
## Querying MongoDB
Click on `+` button of the query manager at the bottom panel of the editor and select the database added in the previous step as the data source. Select the operation that you want to perform and click 'Save' to save the query.

View file

@ -1,6 +1,6 @@
---
id: restapi
title: REST API
title: REST API
---
ToolJet can establish a connection with any available REST API endpoint and create queries to interact with it.
@ -61,11 +61,32 @@ ToolJet supports the REST HTTP methods **GET**, **POST**, **PUT**, **PATCH**, an
<img className="screenshot-full" src="/img/datasource-reference/rest-api/restquery.png" alt="ToolJet - Data source - REST API" />
</div>
<br/>
## Additional header
Whenever a request is made to the REST API, a **tj-x-forwarded-for** header is added to the request, the value of the header will be the IP address of the user who is logged in to the ToolJet application. This header can be used to identify the user who is making the request to the REST API.
<div style={{textAlign: 'center'}}>
<img className="screenshot-full" src="/img/datasource-reference/rest-api/header.png" alt="ToolJet - Data source - REST API" width='500'/>
</div>
## Request types
The plugin will send a **JSON** formatted body by default. If a file object from a [`FilePicker` widget](/docs/widgets/file-picker) is set as a value, the body is automatically converted to be sent as a `multipart/form-data` request.
<div style={{textAlign: 'center'}}>
<img className="screenshot-full" src="/img/datasource-reference/rest-api/multipart-form-data.png" alt="ToolJet - Data source - REST API" />
</div>
## Response types
REST APIs can return data in a variety of formats, including **JSON** and **Base64**. JSON is a common format used for data exchange in REST APIs, while Base64 is often used for encoding binary data, such as images or video, within a JSON response.
REST APIs can return data in a variety of formats, including **JSON** and **Base64**. JSON is a common format used for data exchange in REST APIs, while Base64 is often used for encoding binary data, such as images or video, within a JSON response.
When the response `content-type` is **image**, the response will be a `base64` string.
### Example JSON response

View file

@ -5,56 +5,62 @@ title: Bulk update multiple rows in table
# Bulk update multiple rows in table
Currently, the datasources in ToolJet have operation for **bulk update(GUI mode)** but that only works for changes made in the single row. We will soon be adding a new operation for bulk updating the multiple rows but for now we can bulk update multiple rows by creating a Custom JS query.
Currently, the data sources in ToolJet have operation for **bulk update(GUI mode)** but that only works for changes made in the single row. We will soon be adding a new operation for bulk updating the multiple rows but for now we can bulk update multiple rows by creating a Custom JS query.
In this guide, We have assumed that you have successfully connected the data source. For this guide, we will be using the PostgreSQL data source as an example database, currently, this workaround can be used only for PostgreSQL and MySQL.
In this guide, We have assumed that you have successfully connected the data source. For this guide, we will be using the PostgreSQL data source as an example database. Currently, this workaround can be used only for PostgreSQL and MySQL.
## 1. Create a query to get the data from the database
Let's create the query that will be getting the data from the database:
- Create a postgresql query in **SQL mode** and enter
```sql
SELECT * FROM tooljet // replace tooljet with your table name
```
- Hit **Run** to fetch the data from the database
<div style={{textAlign: 'center'}}>
![ToolJet - How To - Bulk update multiple rows in table](/img/how-to/bulk-update-multiple/postgres1.png)
![ToolJet - How To - Bulk update multiple rows in table](/img/how-to/bulk-update-multiple/new/data.png)
</div>
## 2. Display the data on the table
- Drag a **Table** widget on the canvas and click on its handle to open the properties on the left sidebar
- Edit the **Table data** field value and enter **`{{queries.postgresql1.data}}`**
- Go to the **Components** library on the right and drag a **Table** component onto the canvas
- Click on the handle of the **Table** component to open its properties on the right sidebar
- Populate the table with the data from the query by entering **`{{queries.<queryname>.data}}`** in the **Data** field
<div style={{textAlign: 'center'}}>
![ToolJet - How To - Bulk update multiple rows in table](/img/how-to/bulk-update-multiple/showData.png)
![ToolJet - How To - Bulk update multiple rows in table](/img/how-to/bulk-update-multiple/new/populate.png)
</div>
## 3. Make the columns editable
- Go to the **Columns**, Add or edit columns section and enter the **Column Name** that you want to display on the table and the **Key** name. Key is the name of the column in your database.
- Enable the toggle for **Make editable** for the columns that you want to be 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'}}>
![ToolJet - How To - Bulk update multiple rows in table](/img/how-to/bulk-update-multiple/columns.png)
![ToolJet - How To - Bulk update multiple rows in table](/img/how-to/bulk-update-multiple/new/editable.png)
</div>
## 4. Enable bulk update options for table widget
## 4. Enable Multiple Row Selection
- Go to the **Options** section and enable the **Show update buttons**. Enabling this will add two buttons - **Save Changes** and **Discard Changes** at the bottom of the table, only when any cell in the table is edited.
- You can also enable highlight selected row.(**Optional**)
- Under the **Row Selection** accordion, enable the **Allow Selection**, **Highlight Selected Row**, and **Bulk Selection** option
<div style={{textAlign: 'center'}}>
![ToolJet - How To - Bulk update multiple rows in table](/img/how-to/bulk-update-multiple/options.png)
![ToolJet - How To - Bulk update multiple rows in table](/img/how-to/bulk-update-multiple/new/rowselect.png)
</div>
## 5. Create a Custom JS query
We will create a new Custom JS query(**runjs1**) that will generate SQL query for updating multiple rows.
- Create a new Run Javascript query and use the code below to generate the SQL query for updating multiple rows.
```js
const uniqueIdentifier = "id"
@ -81,36 +87,47 @@ Update **table1** with the name of the table you are using.
:::
<div style={{textAlign: 'center'}}>
![ToolJet - How To - Bulk update multiple rows in table](/img/how-to/bulk-update-multiple/runjs1.png)
![ToolJet - How To - Bulk update multiple rows in table](/img/how-to/bulk-update-multiple/new/runjs1.png)
</div>
## 6. Create an Update query
Let's create a new PostgreSQL query and name it `update`. In **SQL mode**, enter `{{queries.runjs1.data.join(' ')}}` and **Save** it.
- Create a postgresql query in **SQL mode** and rename it as **update**:
```sql
{{queries.runjs1.data.join(' ')}}
```
- This query will run the SQL query generated by the runjs1 query.
<div style={{textAlign: 'center'}}>
![ToolJet - How To - Bulk update multiple rows in table](/img/how-to/bulk-update-multiple/update.png)
![ToolJet - How To - Bulk update multiple rows in table](/img/how-to/bulk-update-multiple/new/update.png)
</div>
## 7. Creating a flow for queries
## 7. Adding event handlers to execute queries in sequence
- Click on the handle of the **Table** widget to open its properties
- Go to the **Events**, and add a handler
- Select **Bulk Update** in Events, **Run Query** in Actions, and then select the **runjs1** query in Query. Now whenever a user will edit the table and hit the **Save Changes** button runjs1 will run.
- Edit the **Table** component and add the 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.
- Add **loading state** to table so that whenever the **users** or **update** query is running the table will show a loading state.
```js
{{queries.users.isLoading || queries.update.isLoading}} // add this in the loading state field of the table
```
<div style={{textAlign: 'center'}}>
![ToolJet - How To - Bulk update multiple rows in table](/img/how-to/bulk-update-multiple/event.png)
![ToolJet - How To - Bulk update multiple rows in table](/img/how-to/bulk-update-multiple/new/savechanges.png)
</div>
- Now, go to the **Advanced** tab of **runjs1** and add a handler to run update query for **Query Success** Event. Now whenever the runjs1 query will be run - the update operation will be performed on the database.
- Now, go to the **runjs1** query and add a **Event** to run update query for **Query Success** Event. This will run the update query whenever the runjs1 query will be run.
<div style={{textAlign: 'center'}}>
![ToolJet - How To - Bulk update multiple rows in table](/img/how-to/bulk-update-multiple/success.png)
![ToolJet - How To - Bulk update multiple rows in table](/img/how-to/bulk-update-multiple/new/querysuccess.png)
</div>
</div>
- Finally, go to the **update** query and add a **Event** to run the users query for **Query Success** Event. This will refresh the table whenever the update query will be run.

View file

@ -24,9 +24,9 @@ Let's look into three types of licenses:
If you are an existing user and wish to update your trial license key, follow these steps:
1. Set up the instance and log in as a **[Super Admin](/docs/Enterprise/superadmin)**.
2. Navigate to the instance settings page.
2. Navigate to the Settings page.
3. In the license key tab, make the necessary updates to the provided license key.
4. Within the license tab of the instance settings page, you can access the limit tab, which displays the current status of available super admins, builders, and end users.
4. Within the license tab of the Settings page, you can access the limit tab, which displays the current status of available super admins, builders, and end users.
:::caution Note
The trial license key will be valid for 14 days. To fully enjoy ToolJet, we recommend upgrading to premium plans within this period. If you wish to upgrade from the trial to the business or enterprise edition, you can click the **Upgrade or Renew** button or contact our team via **[Slack](https://tooljet.com/slack)**. Upon expiration, access to premium features like OpenID SSO login and Audit logs will be restricted, ensuring no data loss occurs. However, don't worry! You can still upgrade to any of our premium plans and enjoy the benefits of ToolJet.
@ -65,9 +65,9 @@ The business license key will be valid for 3 months only. You can renew it to co
**To update the license key, follow these steps:**
1. Log in as a **[Super Admin](/docs/Enterprise/superadmin)**, ensuring that you are on the correct instance URL.
2. Go to the Instance settings page.
2. Go to the Settings page.
3. In the license key tab, update the provided license key.
4. Within the license tab of the instance settings page, you can access the limit tab, which provides details about available super admins, builders, and end users.
4. Within the license tab of the Settings page, you can access the limit tab, which provides details about available super admins, builders, and end users.
:::info Note
As a super admin, you can conveniently view the remaining days of your enterprise edition period on the dashboard. (Refer to screenshots below)
@ -101,7 +101,7 @@ If your business or enterprise edition license key is nearing expiration, please
**Ref: Screenshot addressing upgrade/renew CTAs. Note that there are a couple of other pages which will display banners or CTAs, from where you can upgrade/renew.**
### 2) What is the duration of my license's validity?
If you have an active license, you can find its validity period in the instance settings. Generally, the duration of your license varies based on the type:
If you have an active license, you can find its validity period in the Settings. Generally, the duration of your license varies based on the type:
- Trial licenses are valid for 14 days.
- Business licenses are valid for 3 months.
- Enterprise licenses can be customized to suit your needs.

View file

@ -5,7 +5,7 @@ title: 'Workspace: Overview'
# Workspace: Overview
User can create their own workspaces, user who created workspace will be having admin privileges for the workspace.
The user who creates the workspace will automatically be assigned as its administrator.
<div style={{textAlign: 'center'}}>
@ -27,16 +27,15 @@ User can create their own workspaces, user who created workspace will be having
Please check the detailed doc on **[Permissions](/docs/org-management/permissions)**.
:::
- The administrator can manage [users and groups](/docs/tutorial/manage-users-groups) of each workspace
- Applications and settings can not be shared between workspaces
- A user authorised to login to ToolJet will not have access to all workspaces, Users should be invited or signed up to a workspace to log-in to it.
- When Multi-Workspace feature is enabled, user should login with username and password to log in to Tooljet.
- Administrator can configure authentication methods for their workspaces.
- Administrators can manage [users and groups](/docs/tutorial/manage-users-groups) of each workspace.
- Applications and settings cannot be shared between workspaces.
- Users authorised to login to ToolJet will not have access to all workspaces. Users must be invited to or sign up for a workspace before they can log in.
- When the Multi-Workspace feature is enabled, users must log in with a username and password.
- Administrators can configure authentication methods for their workspaces.
- If password login is enabled, switching to the workspace will happen without any other authorization since the user is already authorized with password login.
- User logged in to Tooljet and trying to switch to a workspace where SSO is enabled and password login is disabled, will be redirected to workspace login page and enabled SSO options will be shown
- User can directly login to a workspace using workspace login URL, Administrator can view the URL **Manage SSO -> General Settings -> Login URL**.
- If a user is logged into ToolJet and switches to a workspace that only uses Single Sign-On (SSO), the user will be sent to a login page to select an SSO option.
- Users can directly login to a workspace using workspace login URL. Administrators can view the URL in the Workspace Settings under **SSO -> General Settings -> Login URL**.
### When disabled (Super Admin)
### Disabling Workspace Creation (Super Admin)
- Only **[Super Admins](/docs/Enterprise/superadmin#restrict-creation-of-personal-workspace-of-users)** can disable the option for creating personal workspaces for a user.
- If creating personal workspaces is disabled, Create workspace feature wont be available.
- No separate login page for workspace and SSO configured for the workspace will be reflected to the main login page/login.
- If the option to make personal workspaces is turned off for a user, the user won't be able to create new workspaces.

View file

@ -68,3 +68,20 @@ Please note that you need to set up a PostgreSQL database manually to be used by
</div>
You can access ToolJet via the application URL provided in the overview tab.
## Upgrading to v2.24.3-ee2.10.2
Version v2.24.3-ee2.10.2 includes architectural changes and, hence, comes with new migrations.
If this is a new installation of the application, you may start directly with version v2.24.3-ee2.10.2. This guide is not required for new installations.
#### Prerequisites for Upgrading to the Latest Version:
- It is **crucial to perform a comprehensive backup of your database** before starting the upgrade process to prevent data loss.
- Ensure that your current version is v2.23.3-ee2.10.2 before upgrading.
- Users on versions earlier than v2.23.3-ee2.10.2 must first upgrade to this version before proceeding to v2.24.3-ee2.10.2.
For specific issues or questions, refer to our **[Slack](https://tooljet.slack.com/join/shared_invite/zt-25438diev-mJ6LIZpJevG0LXCEcL0NhQ#)**.

View file

@ -96,3 +96,19 @@ Summarising the steps below:
```bash
cd tooljet-assets && gcloud app deploy
```
## Upgrading to v2.24.3-ee2.10.2
Version v2.24.3-ee2.10.2 includes architectural changes and, hence, comes with new migrations.
If this is a new installation of the application, you may start directly with version v2.24.3-ee2.10.2. This guide is not required for new installations.
#### Prerequisites for Upgrading to the Latest Version:
- It is **crucial to perform a comprehensive backup of your database** before starting the upgrade process to prevent data loss.
- Ensure that your current version is v2.23.3-ee2.10.2 before upgrading.
- Users on versions earlier than v2.23.3-ee2.10.2 must first upgrade to this version before proceeding to v2.24.3-ee2.10.2.
For specific issues or questions, refer to our **[Slack](https://tooljet.slack.com/join/shared_invite/zt-25438diev-mJ6LIZpJevG0LXCEcL0NhQ#)**.

View file

@ -107,3 +107,19 @@ Follow the steps below to deploy ToolJet Database on DigitalOcean:
4. Add your newly created PostgREST app to the trusted sources of your managed or separate database.
5. Update your existing ToolJet application deployment with [environment variables](/docs/setup/env-vars#enable-tooljet-database--optional-) required for PostgREST.
## Upgrading to v2.24.3-ee2.10.2
Version v2.24.3-ee2.10.2 includes architectural changes and, hence, comes with new migrations.
If this is a new installation of the application, you may start directly with version v2.24.3-ee2.10.2. This guide is not required for new installations.
#### Prerequisites for Upgrading to the Latest Version:
- It is **crucial to perform a comprehensive backup of your database** before starting the upgrade process to prevent data loss.
- Ensure that your current version is v2.23.3-ee2.10.2 before upgrading.
- Users on versions earlier than v2.23.3-ee2.10.2 must first upgrade to this version before proceeding to v2.24.3-ee2.10.2.
For specific issues or questions, refer to our **[Slack](https://tooljet.slack.com/join/shared_invite/zt-25438diev-mJ6LIZpJevG0LXCEcL0NhQ#)**.

View file

@ -128,11 +128,29 @@ Confused about which setup to select? Feel free to ask the community via Slack:
`sudo docker-compose up -d`
iv. Setup docker to run without root privileges by following the instructions written here https://docs.docker.com/engine/install/linux-postinstall/
:::
:::
</TabItem>
</TabItem>
</Tabs>
## Upgrading to v2.24.3-ee2.10.2
Version v2.24.3-ee2.10.2 includes architectural changes and, hence, comes with new migrations.
If this is a new installation of the application, you may start directly with version v2.24.3-ee2.10.2. This guide is not required for new installations.
#### Prerequisites for Upgrading to the Latest Version:
- It is **crucial to perform a comprehensive backup of your database** before starting the upgrade process to prevent data loss.
- Ensure that your current version is v2.23.3-ee2.10.2 before upgrading.
- Users on versions earlier than v2.23.3-ee2.10.2 must first upgrade to this version before proceeding to v2.24.3-ee2.10.2.
For specific issues or questions, refer to our **[Slack](https://tooljet.slack.com/join/shared_invite/zt-25438diev-mJ6LIZpJevG0LXCEcL0NhQ#)**.

View file

@ -11,6 +11,13 @@ You should setup a PostgreSQL database manually to be used by the ToolJet server
*If you have any questions feel free to join our [Slack Community](https://tooljet.com/slack) or send us an email at hello@tooljet.com.*
You can effortlessly deploy Amazon Elastic Compute Cloud Service (EC2) by utilizing a **CloudFormation template**. This template will deploy all the services required to run ToolJet on AWS EC2 instances.
To deploy all the services at once, simply employ the following template:
```
curl -LO https://tooljet-deployments.s3.us-west-1.amazonaws.com/cloudformation/EC2-cloudfomration.yml
```
Follow the steps below to deploy ToolJet on AWS EC2 instances.
1. Setup a PostgreSQL database and make sure that the database is accessible from the EC2 instance.
@ -77,4 +84,26 @@ Follow the steps below to deploy ToolJet on AWS EC2 instances.
ToolJet AMI comes inbuilt with PostgREST. If you intend to use this feature, you'd only have to setup the environment variables in `~/app/.env` file and run `./setup_app` script.
You can learn more about this feature [here](/docs/tooljet-database).
You can learn more about this feature [here](/docs/tooljet-database).
## Upgrading to v2.24.3-ee2.10.2
Version v2.24.3-ee2.10.2 includes architectural changes and, hence, comes with new migrations.
If this is a new installation of the application, you may start directly with version v2.24.3-ee2.10.2. This guide is not required for new installations.
#### Prerequisites for Upgrading to the Latest Version:
- It is **crucial to perform a comprehensive backup of your database** before starting the upgrade process to prevent data loss.
- Ensure that your current version is v2.23.3-ee2.10.2 before upgrading.
- Users on versions earlier than v2.23.3-ee2.10.2 must first upgrade to this version before proceeding to v2.24.3-ee2.10.2.
For specific issues or questions, refer to our **[Slack](https://tooljet.slack.com/join/shared_invite/zt-25438diev-mJ6LIZpJevG0LXCEcL0NhQ#)**.

View file

@ -225,6 +225,21 @@ Follow the steps below to deploy PostgREST on a ECS cluster.
</div>
Update ToolJet deployment with the appropriate env variables [here](https://docs.tooljet.com/docs/setup/env-vars/#enable-tooljet-database--optional-) and apply the changes.
## Upgrading to v2.24.3-ee2.10.2
Version v2.24.3-ee2.10.2 includes architectural changes and, hence, comes with new migrations.
If this is a new installation of the application, you may start directly with version v2.24.3-ee2.10.2. This guide is not required for new installations.
#### Prerequisites for Upgrading to the Latest Version:
- It is **crucial to perform a comprehensive backup of your database** before starting the upgrade process to prevent data loss.
- Ensure that your current version is v2.23.3-ee2.10.2 before upgrading.
- Users on versions earlier than v2.23.3-ee2.10.2 must first upgrade to this version before proceeding to v2.24.3-ee2.10.2.
For specific issues or questions, refer to our **[Slack](https://tooljet.slack.com/join/shared_invite/zt-25438diev-mJ6LIZpJevG0LXCEcL0NhQ#)**.

View file

@ -63,7 +63,7 @@ Self-hosted version of ToolJet pings our server to fetch the latest product upda
### Comment feature enable ( optional )
Use this environment variable to enable/disable the feature that allows you to add comments on the canvas. To configure this environment variable, ensure that multiplayer editing is enabled in the instance settings.
Use this environment variable to enable/disable the feature that allows you to add comments on the canvas. To configure this environment variable, ensure that multiplayer editing is enabled in the Settings.
| variable | value |
| ---------------------- | ----------------- |
@ -305,6 +305,14 @@ If this parameter is not specified then PostgREST refuses authentication request
Please make sure that DB_URI is given in the format `postgrest://[USERNAME]:[PASSWORD]@[HOST]:[PORT]/[DATABASE]`
:::
## Log file path ( Optional )
If a log file path is specified in environment variables, a log file containing all the data from audit logs will be created at the specified path. The file will be updated every time a new audit log is created.
| Variable | Description |
| -------- | --------------------------------------------------------------------------- |
| LOG_FILE_PATH | the path where the log file will be created ( eg: tooljet/log/tooljet-audit.log) |
## ToolJet Apps
### Enabling embedding of private apps

View file

@ -151,3 +151,20 @@ Once the Service is created and live, to make the Cloud Service URL public. Ple
<div style={{textAlign: 'center'}}>
<img className="screenshot-full" src="/img/cloud-run/env-for-tooljet.png" alt="env-for-tooljet" />
</div>
## Upgrading to v2.24.3-ee2.10.2
Version v2.24.3-ee2.10.2 includes architectural changes and, hence, comes with new migrations.
If this is a new installation of the application, you may start directly with version v2.24.3-ee2.10.2. This guide is not required for new installations.
#### Prerequisites for Upgrading to the Latest Version:
- It is **crucial to perform a comprehensive backup of your database** before starting the upgrade process to prevent data loss.
- Ensure that your current version is v2.23.3-ee2.10.2 before upgrading.
- Users on versions earlier than v2.23.3-ee2.10.2 must first upgrade to this version before proceeding to v2.24.3-ee2.10.2.
For specific issues or questions, refer to our **[Slack](https://tooljet.slack.com/join/shared_invite/zt-25438diev-mJ6LIZpJevG0LXCEcL0NhQ#)**.

View file

@ -33,4 +33,20 @@ For more information about the ToolJet database, you can visit [here](/docs/tool
If you plan to use this feature, you need to set up and deploy the PostgREST server, which facilitates querying the ToolJet Database.
To enable the ToolJet database, please set the environment variable `ENABLE_TOOLJET_DB` to true in the `values.yaml` file.
To enable the ToolJet database, please set the environment variable `ENABLE_TOOLJET_DB` to true in the `values.yaml` file.
## Upgrading to v2.24.3-ee2.10.2
Version v2.24.3-ee2.10.2 includes architectural changes and, hence, comes with new migrations.
If this is a new installation of the application, you may start directly with version v2.24.3-ee2.10.2. This guide is not required for new installations.
#### Prerequisites for Upgrading to the Latest Version:
- It is **crucial to perform a comprehensive backup of your database** before starting the upgrade process to prevent data loss.
- Ensure that your current version is v2.23.3-ee2.10.2 before upgrading.
- Users on versions earlier than v2.23.3-ee2.10.2 must first upgrade to this version before proceeding to v2.24.3-ee2.10.2.
For specific issues or questions, refer to our **[Slack](https://tooljet.slack.com/join/shared_invite/zt-25438diev-mJ6LIZpJevG0LXCEcL0NhQ#)**.

View file

@ -53,3 +53,19 @@ If you intend to use this feature, you'd have to set up and deploy PostgREST ser
```
2. Update ToolJet deployment with the appropriate env variables [here](https://tooljet-deployments.s3.us-west-1.amazonaws.com/kubernetes/AKS/deployment.yaml) and apply the changes.
## Upgrading to v2.24.3-ee2.10.2
Version v2.24.3-ee2.10.2 includes architectural changes and, hence, comes with new migrations.
If this is a new installation of the application, you may start directly with version v2.24.3-ee2.10.2. This guide is not required for new installations.
#### Prerequisites for Upgrading to the Latest Version:
- It is **crucial to perform a comprehensive backup of your database** before starting the upgrade process to prevent data loss.
- Ensure that your current version is v2.23.3-ee2.10.2 before upgrading.
- Users on versions earlier than v2.23.3-ee2.10.2 must first upgrade to this version before proceeding to v2.24.3-ee2.10.2.
For specific issues or questions, refer to our **[Slack](https://tooljet.slack.com/join/shared_invite/zt-25438diev-mJ6LIZpJevG0LXCEcL0NhQ#)**.

View file

@ -79,3 +79,19 @@ If you intend to use this feature, you'd have to set up and deploy PostgREST ser
```
2. Update ToolJet deployment with the appropriate env variables [here](https://tooljet-deployments.s3.us-west-1.amazonaws.com/kubernetes/GKE/deployment.yaml) and apply the changes.
## Upgrading to v2.24.3-ee2.10.2
Version v2.24.3-ee2.10.2 includes architectural changes and, hence, comes with new migrations.
If this is a new installation of the application, you may start directly with version v2.24.3-ee2.10.2. This guide is not required for new installations.
#### Prerequisites for Upgrading to the Latest Version:
- It is **crucial to perform a comprehensive backup of your database** before starting the upgrade process to prevent data loss.
- Ensure that your current version is v2.23.3-ee2.10.2 before upgrading.
- Users on versions earlier than v2.23.3-ee2.10.2 must first upgrade to this version before proceeding to v2.24.3-ee2.10.2.
For specific issues or questions, refer to our **[Slack](https://tooljet.slack.com/join/shared_invite/zt-25438diev-mJ6LIZpJevG0LXCEcL0NhQ#)**.

View file

@ -62,3 +62,19 @@ If you intend to use this feature, you'd have to set up and deploy PostgREST ser
```
2. Update ToolJet deployment with the appropriate env variables [here](https://tooljet-deployments.s3.us-west-1.amazonaws.com/kubernetes/deployment.yaml) and apply the changes.
## Upgrading to v2.24.3-ee2.10.2
Version v2.24.3-ee2.10.2 includes architectural changes and, hence, comes with new migrations.
If this is a new installation of the application, you may start directly with version v2.24.3-ee2.10.2. This guide is not required for new installations.
#### Prerequisites for Upgrading to the Latest Version:
- It is **crucial to perform a comprehensive backup of your database** before starting the upgrade process to prevent data loss.
- Ensure that your current version is v2.23.3-ee2.10.2 before upgrading.
- Users on versions earlier than v2.23.3-ee2.10.2 must first upgrade to this version before proceeding to v2.24.3-ee2.10.2.
For specific issues or questions, refer to our **[Slack](https://tooljet.slack.com/join/shared_invite/zt-25438diev-mJ6LIZpJevG0LXCEcL0NhQ#)**.

View file

@ -68,3 +68,19 @@ If you intend to use this feature, you'd have to set up and deploy PostgREST ser
```
https://tooljet-deployments.s3.us-west-1.amazonaws.com/openshift/postgrest.yaml
```
## Upgrading to v2.24.3-ee2.10.2
Version v2.24.3-ee2.10.2 includes architectural changes and, hence, comes with new migrations.
If this is a new installation of the application, you may start directly with version v2.24.3-ee2.10.2. This guide is not required for new installations.
#### Prerequisites for Upgrading to the Latest Version:
- It is **crucial to perform a comprehensive backup of your database** before starting the upgrade process to prevent data loss.
- Ensure that your current version is v2.23.3-ee2.10.2 before upgrading.
- Users on versions earlier than v2.23.3-ee2.10.2 must first upgrade to this version before proceeding to v2.24.3-ee2.10.2.
For specific issues or questions, refer to our **[Slack](https://tooljet.slack.com/join/shared_invite/zt-25438diev-mJ6LIZpJevG0LXCEcL0NhQ#)**.

View file

@ -20,4 +20,20 @@ You'll need to setup the following environment variables if ToolJet installation
See all **[Environment Variables](/docs/setup/env-vars)** here.
:::
## Upgrading to v2.24.3-ee2.10.2
Version v2.24.3-ee2.10.2 includes architectural changes and, hence, comes with new migrations.
If this is a new installation of the application, you may start directly with version v2.24.3-ee2.10.2. This guide is not required for new installations.
#### Prerequisites for Upgrading to the Latest Version:
- It is **crucial to perform a comprehensive backup of your database** before starting the upgrade process to prevent data loss.
- Ensure that your current version is v2.23.3-ee2.10.2 before upgrading.
- Users on versions earlier than v2.23.3-ee2.10.2 must first upgrade to this version before proceeding to v2.24.3-ee2.10.2.
For specific issues or questions, refer to our **[Slack](https://tooljet.slack.com/join/shared_invite/zt-25438diev-mJ6LIZpJevG0LXCEcL0NhQ#)**.

View file

@ -10,10 +10,11 @@ title: Try ToolJet
You can run the command below to have ToolJet up and running right away.
```bash
docker run \
docker run -d \
--name tooljet \
--restart unless-stopped \
-p 80:80 \
--platform linux/amd64 \
-v tooljet_data:/var/lib/postgresql/13/main \
tooljet/try:latest
```

View file

@ -5,118 +5,18 @@ title: Keyboard Shortcuts
# Keyboard Shortcuts
You can perform operations like undo, redo, clone, or removing the widget directly using the keyboard shortcuts.
You can perform operations like copying and pasting components, cloning components, deleting components, undo, redo, and more using keyboard shortcuts.
## Copy
You can copy the component on the visual app editor using the following shortcut keys:
| Action | Mac Shortcut | Linux/Windows Shortcut |
|:------------|:-------------------|:-----------------------|
| Copy component | `cmd + c` | `ctrl + c` |
| Cut component | `cmd + x` | `ctrl + x` |
| Paste component | `cmd + v` | `ctrl + v` |
| Undo | `cmd + z` | `ctrl + z` |
| Redo | `cmd + shift + z` | `ctrl + shift + z` |
| Clone component | `cmd + d` | `ctrl + d` |
| Remove component | `delete` | `backspace` |
| Deselect component | `esc` | `esc` |
**On Mac:** `cmd + c`
**On Linux/Windows:** `ctrl + c`
<div style={{textAlign: 'center'}}>
<img className="screenshot-full" src="/img/tutorial/keyboard-shortcuts/Ctrl+C.gif" alt="Copy" />
</div>
## Cut
You can cut the component on the visual app editor using the following shortcut keys:
**On Mac:** `cmd + x`
**On Linux/Windows:** `ctrl + x`
<div style={{textAlign: 'center'}}>
<img className="screenshot-full" src="/img/tutorial/keyboard-shortcuts/Ctrl+X.gif" alt="Cut" />
</div>
## Paste
You can paste the selected component using the following shortcut keys:
**On Mac:** `cmd + v`
**On Linux/Windows:** `ctrl + v`
<div style={{textAlign: 'center'}}>
<img className="screenshot-full" src="/img/tutorial/keyboard-shortcuts/Ctrl+V.gif" alt="Paste" />
</div>
:::caution
There are few edge cases when copy-paste commands might not work:
- The URL should be `https` and it won't work on http on many browsers
- Recent Firefox versions has some issue with copy functionality
:::
## Undo
You can undo any operation performed on the visual app editor using the following shortcut keys:
**On Mac:** `cmd + z`
**On Linux/Windows:** `ctrl + z`
<div style={{textAlign: 'center'}}>
<img className="screenshot-full" src="/img/tutorial/keyboard-shortcuts/Ctrl+Z.gif" alt="Undo" />
</div>
## Redo
If you have `undo` an operation and want to redo that again than you can use the following shortcut keys:
**On Mac:** `cmd + shift + z`
**On Linux/Windows:** `ctrl + shift + z`
<div style={{textAlign: 'center'}}>
<img className="screenshot-full" src="/img/tutorial/keyboard-shortcuts/Ctrl+Shift+Z.gif" alt="Redo" />
</div>
## Clone
Now you can create multiple clones of any widget without having to drag and drop the widget again from the sidebar. Just select any widget that you want to create a clone and use the following shortcut keys:
**On Mac:** `cmd + d`
**On Linux/Windows:** `ctrl + d`
<div style={{textAlign: 'center'}}>
<img className="screenshot-full" src="/img/tutorial/keyboard-shortcuts/Ctrl+D.gif" alt="Clone" />
</div>
## Remove widget
Now you can delete a selected widget by using the following shortcut keys:
**On Mac:** `delete`
**On Linux/Windows:** `backspace`
<div style={{textAlign: 'center'}}>
<img className="screenshot-full" src="/img/tutorial/keyboard-shortcuts/bkspc.gif" alt="Remove" />
</div>
## Unselect the selected widget
You can quickly deselect a widget using the `esc` key.
<div style={{textAlign: 'center'}}>
<img className="screenshot-full" src="/img/tutorial/keyboard-shortcuts/esc.gif" alt="Unselect" />
</div>
To choose several components at once within the app-builder, simply hold down the shift key while clicking on each component you want to select.

View file

@ -45,7 +45,7 @@ Once you have released a version of your app, you can share the app with others
</div>
- You can also `Embedd` your application using the embeddable link
- You can also `Embed` your application using the embeddable link
<div style={{textAlign: 'center'}}>

View file

@ -76,7 +76,7 @@ The maximum accepted number of files The default value is `2`.
### Accept file types
By providing types, you can make the dropzone accept specific file types and reject the others.
By providing types, you can make the dropzone accept specific file types and reject the others. Example: `{{"image/*,application/pdf,application/msword"}}`
### Max size limit

View file

@ -121,7 +121,7 @@ module.exports = {
// Please change this to your repo.
editUrl: 'https://github.com/ToolJet/Tooljet/blob/develop/docs/',
includeCurrentVersion: false,
lastVersion: '2.22.0',
lastVersion: '2.23.0',
},
theme: {
customCss: require.resolve('./src/css/custom.css'),
@ -137,5 +137,6 @@ module.exports = {
],
plugins: [
devServerPlugin,
'plugin-image-zoom'
],
};

83
docs/package-lock.json generated
View file

@ -13,6 +13,7 @@
"@docusaurus/plugin-sitemap": "^2.4.3",
"@docusaurus/preset-classic": "^2.4.3",
"clsx": "^1.2.1",
"plugin-image-zoom": "github:flexanalytics/plugin-image-zoom",
"react": "^17.0.2",
"react-dom": "^17.0.2"
}
@ -3602,9 +3603,9 @@
}
},
"node_modules/@types/unist": {
"version": "2.0.7",
"resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.7.tgz",
"integrity": "sha512-cputDpIbFgLUaGQn6Vqg3/YsJwxUwHLO13v3i5ouxT4lat0khip9AEWxtERujXV9wxIB1EyF97BSJFt6vpdI8g=="
"version": "2.0.9",
"resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.9.tgz",
"integrity": "sha512-zC0iXxAv1C1ERURduJueYzkzZ2zaGyc+P2c95hgkikHPr3z8EdUZOlgEQ5X0DRmwDZn+hekycQnoeiiRVrmilQ=="
},
"node_modules/@types/ws": {
"version": "8.5.3",
@ -3995,9 +3996,9 @@
}
},
"node_modules/autoprefixer": {
"version": "10.4.14",
"resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.14.tgz",
"integrity": "sha512-FQzyfOsTlwVzjHxKEqRIAdJx9niO6VCBCoEwax/VLSoQF29ggECcPuBqUMZ+u8jCZOPSy8b8/8KnuFbp0SaFZQ==",
"version": "10.4.16",
"resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.16.tgz",
"integrity": "sha512-7vd3UC6xKp0HLfua5IjZlcXvGAGy7cBAXTg2lyQ/8WpNhd6SiZ8Be+xm3FyBSYJx5GKcpRCzBh7RH4/0dnY+uQ==",
"funding": [
{
"type": "opencollective",
@ -4006,12 +4007,16 @@
{
"type": "tidelift",
"url": "https://tidelift.com/funding/github/npm/autoprefixer"
},
{
"type": "github",
"url": "https://github.com/sponsors/ai"
}
],
"dependencies": {
"browserslist": "^4.21.5",
"caniuse-lite": "^1.0.30001464",
"fraction.js": "^4.2.0",
"browserslist": "^4.21.10",
"caniuse-lite": "^1.0.30001538",
"fraction.js": "^4.3.6",
"normalize-range": "^0.1.2",
"picocolors": "^1.0.0",
"postcss-value-parser": "^4.2.0"
@ -6454,8 +6459,7 @@
"tapable": "^1.0.0"
},
"engines": {
"node": ">=10",
"yarn": ">=1.0.0"
"node": ">=10"
},
"peerDependencies": {
"eslint": ">= 6",
@ -6557,15 +6561,15 @@
}
},
"node_modules/fraction.js": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.2.0.tgz",
"integrity": "sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==",
"version": "4.3.7",
"resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz",
"integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==",
"engines": {
"node": "*"
},
"funding": {
"type": "patreon",
"url": "https://www.patreon.com/infusion"
"url": "https://github.com/sponsors/rawify"
}
},
"node_modules/fresh": {
@ -8077,6 +8081,11 @@
"node": ">= 0.6"
}
},
"node_modules/medium-zoom": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/medium-zoom/-/medium-zoom-1.0.8.tgz",
"integrity": "sha512-CjFVuFq/IfrdqesAXfg+hzlDKu6A2n80ZIq0Kl9kWjoHh9j1N9Uvk5X0/MmN0hOfm5F9YBswlClhcwnmtwz7gA=="
},
"node_modules/memfs": {
"version": "3.4.7",
"resolved": "https://registry.npmjs.org/memfs/-/memfs-3.4.7.tgz",
@ -8812,6 +8821,14 @@
"node": ">=4"
}
},
"node_modules/plugin-image-zoom": {
"version": "1.1.0",
"resolved": "git+ssh://git@github.com/flexanalytics/plugin-image-zoom.git#8e1b866c79ed6d42cefc4c52f851f1dfd1d0c7de",
"license": "MIT",
"dependencies": {
"medium-zoom": "^1.0.8"
}
},
"node_modules/postcss": {
"version": "8.4.31",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz",
@ -14832,9 +14849,9 @@
}
},
"@types/unist": {
"version": "2.0.7",
"resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.7.tgz",
"integrity": "sha512-cputDpIbFgLUaGQn6Vqg3/YsJwxUwHLO13v3i5ouxT4lat0khip9AEWxtERujXV9wxIB1EyF97BSJFt6vpdI8g=="
"version": "2.0.9",
"resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.9.tgz",
"integrity": "sha512-zC0iXxAv1C1ERURduJueYzkzZ2zaGyc+P2c95hgkikHPr3z8EdUZOlgEQ5X0DRmwDZn+hekycQnoeiiRVrmilQ=="
},
"@types/ws": {
"version": "8.5.3",
@ -15162,13 +15179,13 @@
"integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg=="
},
"autoprefixer": {
"version": "10.4.14",
"resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.14.tgz",
"integrity": "sha512-FQzyfOsTlwVzjHxKEqRIAdJx9niO6VCBCoEwax/VLSoQF29ggECcPuBqUMZ+u8jCZOPSy8b8/8KnuFbp0SaFZQ==",
"version": "10.4.16",
"resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.16.tgz",
"integrity": "sha512-7vd3UC6xKp0HLfua5IjZlcXvGAGy7cBAXTg2lyQ/8WpNhd6SiZ8Be+xm3FyBSYJx5GKcpRCzBh7RH4/0dnY+uQ==",
"requires": {
"browserslist": "^4.21.5",
"caniuse-lite": "^1.0.30001464",
"fraction.js": "^4.2.0",
"browserslist": "^4.21.10",
"caniuse-lite": "^1.0.30001538",
"fraction.js": "^4.3.6",
"normalize-range": "^0.1.2",
"picocolors": "^1.0.0",
"postcss-value-parser": "^4.2.0"
@ -16949,9 +16966,9 @@
"integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow=="
},
"fraction.js": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.2.0.tgz",
"integrity": "sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA=="
"version": "4.3.7",
"resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz",
"integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew=="
},
"fresh": {
"version": "0.5.2",
@ -18043,6 +18060,11 @@
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
"integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ=="
},
"medium-zoom": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/medium-zoom/-/medium-zoom-1.0.8.tgz",
"integrity": "sha512-CjFVuFq/IfrdqesAXfg+hzlDKu6A2n80ZIq0Kl9kWjoHh9j1N9Uvk5X0/MmN0hOfm5F9YBswlClhcwnmtwz7gA=="
},
"memfs": {
"version": "3.4.7",
"resolved": "https://registry.npmjs.org/memfs/-/memfs-3.4.7.tgz",
@ -18552,6 +18574,13 @@
}
}
},
"plugin-image-zoom": {
"version": "git+ssh://git@github.com/flexanalytics/plugin-image-zoom.git#8e1b866c79ed6d42cefc4c52f851f1dfd1d0c7de",
"from": "plugin-image-zoom@github:flexanalytics/plugin-image-zoom",
"requires": {
"medium-zoom": "^1.0.8"
}
},
"postcss": {
"version": "8.4.31",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz",

View file

@ -19,6 +19,7 @@
"@docusaurus/plugin-sitemap": "^2.4.3",
"@docusaurus/preset-classic": "^2.4.3",
"clsx": "^1.2.1",
"plugin-image-zoom": "github:flexanalytics/plugin-image-zoom",
"react": "^17.0.2",
"react-dom": "^17.0.2"
},

View file

@ -384,6 +384,7 @@ const sidebars = {
'type': 'category',
'label': 'Setup',
'items': [
'contributing-guide/setup/codespaces',
'contributing-guide/setup/macos',
'contributing-guide/setup/docker',
'contributing-guide/setup/ubuntu',

Binary file not shown.

After

Width:  |  Height:  |  Size: 111 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 107 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 179 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 156 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 118 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 150 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 136 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

View file

@ -65,3 +65,19 @@ Please note that you need to set up a PostgreSQL database manually to be used by
</div>
You can access ToolJet via the application URL provided in the overview tab.
## Upgrading to v2.24.3-ee2.10.2
Version v2.24.3-ee2.10.2 includes architectural changes and, hence, comes with new migrations.
If this is a new installation of the application, you may start directly with version v2.24.3-ee2.10.2. This guide is not required for new installations.
#### Prerequisites for Upgrading to the Latest Version:
- It is **crucial to perform a comprehensive backup of your database** before starting the upgrade process to prevent data loss.
- Ensure that your current version is v2.23.3-ee2.10.2 before upgrading.
- Users on versions earlier than v2.23.3-ee2.10.2 must first upgrade to this version before proceeding to v2.24.3-ee2.10.2.
For specific issues or questions, refer to our **[Slack](https://tooljet.slack.com/join/shared_invite/zt-25438diev-mJ6LIZpJevG0LXCEcL0NhQ#)**.

View file

@ -96,3 +96,19 @@ Summarising the steps below:
```bash
cd tooljet-assets && gcloud app deploy
```
## Upgrading to v2.24.3-ee2.10.2
Version v2.24.3-ee2.10.2 includes architectural changes and, hence, comes with new migrations.
If this is a new installation of the application, you may start directly with version v2.24.3-ee2.10.2. This guide is not required for new installations.
#### Prerequisites for Upgrading to the Latest Version:
- It is **crucial to perform a comprehensive backup of your database** before starting the upgrade process to prevent data loss.
- Ensure that your current version is v2.23.3-ee2.10.2 before upgrading.
- Users on versions earlier than v2.23.3-ee2.10.2 must first upgrade to this version before proceeding to v2.24.3-ee2.10.2.
For specific issues or questions, refer to our **[Slack](https://tooljet.slack.com/join/shared_invite/zt-25438diev-mJ6LIZpJevG0LXCEcL0NhQ#)**.

View file

@ -42,4 +42,20 @@ Now you can quickly deploy ToolJet using the Deploy to DigitalOcean button.
:::tip
ToolJet server and client can be deployed as standalone applications. If you do not want to deploy the client on DigitalOcean, modify `package.json` accordingly. We have a [guide](/docs/setup/client) on deploying ToolJet client using services such as Firebase.
:::
:::
## Upgrading to v2.24.3-ee2.10.2
Version v2.24.3-ee2.10.2 includes architectural changes and, hence, comes with new migrations.
If this is a new installation of the application, you may start directly with version v2.24.3-ee2.10.2. This guide is not required for new installations.
#### Prerequisites for Upgrading to the Latest Version:
- It is **crucial to perform a comprehensive backup of your database** before starting the upgrade process to prevent data loss.
- Ensure that your current version is v2.23.3-ee2.10.2 before upgrading.
- Users on versions earlier than v2.23.3-ee2.10.2 must first upgrade to this version before proceeding to v2.24.3-ee2.10.2.
For specific issues or questions, refer to our **[Slack](https://tooljet.slack.com/join/shared_invite/zt-25438diev-mJ6LIZpJevG0LXCEcL0NhQ#)**.

View file

@ -126,11 +126,29 @@ Confused about which setup to select? Feel free to ask the community via Slack:
`sudo docker-compose up -d`
iv. Setup docker to run without root privileges by following the instructions written here https://docs.docker.com/engine/install/linux-postinstall/
:::
:::
</TabItem>
</TabItem>
</Tabs>
## Upgrading to v2.24.3-ee2.10.2
Version v2.24.3-ee2.10.2 includes architectural changes and, hence, comes with new migrations.
If this is a new installation of the application, you may start directly with version v2.24.3-ee2.10.2. This guide is not required for new installations.
#### Prerequisites for Upgrading to the Latest Version:
- It is **crucial to perform a comprehensive backup of your database** before starting the upgrade process to prevent data loss.
- Ensure that your current version is v2.23.3-ee2.10.2 before upgrading.
- Users on versions earlier than v2.23.3-ee2.10.2 must first upgrade to this version before proceeding to v2.24.3-ee2.10.2.
For specific issues or questions, refer to our **[Slack](https://tooljet.slack.com/join/shared_invite/zt-25438diev-mJ6LIZpJevG0LXCEcL0NhQ#)**.

View file

@ -72,3 +72,19 @@ Follow the steps below to deploy ToolJet on AWS EC2 instances.
10. If you've set a custom domain for `TOOLJET_HOST`, add a `A record` entry in your DNS settings to point to the IP address of the EC2 instance.
12. You're all done, ToolJet client would now be served at the value you've set in `TOOLJET_HOST`.
## Upgrading to v2.24.3-ee2.10.2
Version v2.24.3-ee2.10.2 includes architectural changes and, hence, comes with new migrations.
If this is a new installation of the application, you may start directly with version v2.24.3-ee2.10.2. This guide is not required for new installations.
#### Prerequisites for Upgrading to the Latest Version:
- It is **crucial to perform a comprehensive backup of your database** before starting the upgrade process to prevent data loss.
- Ensure that your current version is v2.23.3-ee2.10.2 before upgrading.
- Users on versions earlier than v2.23.3-ee2.10.2 must first upgrade to this version before proceeding to v2.24.3-ee2.10.2.
For specific issues or questions, refer to our **[Slack](https://tooljet.slack.com/join/shared_invite/zt-25438diev-mJ6LIZpJevG0LXCEcL0NhQ#)**.

View file

@ -94,3 +94,19 @@ The setup above is just a template. Feel free to update the task definition and
6. Click on run task to have this task seed the database with user having following credentials:
- email: `dev@tooljet.io`
- password: `password`
## Upgrading to v2.24.3-ee2.10.2
Version v2.24.3-ee2.10.2 includes architectural changes and, hence, comes with new migrations.
If this is a new installation of the application, you may start directly with version v2.24.3-ee2.10.2. This guide is not required for new installations.
#### Prerequisites for Upgrading to the Latest Version:
- It is **crucial to perform a comprehensive backup of your database** before starting the upgrade process to prevent data loss.
- Ensure that your current version is v2.23.3-ee2.10.2 before upgrading.
- Users on versions earlier than v2.23.3-ee2.10.2 must first upgrade to this version before proceeding to v2.24.3-ee2.10.2.
For specific issues or questions, refer to our **[Slack](https://tooljet.slack.com/join/shared_invite/zt-25438diev-mJ6LIZpJevG0LXCEcL0NhQ#)**.

View file

@ -142,3 +142,19 @@ The deployment will fail as it only runs a seed script. Check logs to see that d
```
The default username of the admin is `dev@tooljet.io` and the password is `password`.
## Upgrading to v2.24.3-ee2.10.2
Version v2.24.3-ee2.10.2 includes architectural changes and, hence, comes with new migrations.
If this is a new installation of the application, you may start directly with version v2.24.3-ee2.10.2. This guide is not required for new installations.
#### Prerequisites for Upgrading to the Latest Version:
- It is **crucial to perform a comprehensive backup of your database** before starting the upgrade process to prevent data loss.
- Ensure that your current version is v2.23.3-ee2.10.2 before upgrading.
- Users on versions earlier than v2.23.3-ee2.10.2 must first upgrade to this version before proceeding to v2.24.3-ee2.10.2.
For specific issues or questions, refer to our **[Slack](https://tooljet.slack.com/join/shared_invite/zt-25438diev-mJ6LIZpJevG0LXCEcL0NhQ#)**.

View file

@ -33,4 +33,20 @@ For more information about the ToolJet database, you can visit [here](/docs/tool
If you plan to use this feature, you need to set up and deploy the PostgREST server, which facilitates querying the ToolJet Database.
To enable the ToolJet database, please set the environment variable `ENABLE_TOOLJET_DB` to true in the `values.yaml` file.
To enable the ToolJet database, please set the environment variable `ENABLE_TOOLJET_DB` to true in the `values.yaml` file.
## Upgrading to v2.24.3-ee2.10.2
Version v2.24.3-ee2.10.2 includes architectural changes and, hence, comes with new migrations.
If this is a new installation of the application, you may start directly with version v2.24.3-ee2.10.2. This guide is not required for new installations.
#### Prerequisites for Upgrading to the Latest Version:
- It is **crucial to perform a comprehensive backup of your database** before starting the upgrade process to prevent data loss.
- Ensure that your current version is v2.23.3-ee2.10.2 before upgrading.
- Users on versions earlier than v2.23.3-ee2.10.2 must first upgrade to this version before proceeding to v2.24.3-ee2.10.2.
For specific issues or questions, refer to our **[Slack](https://tooljet.slack.com/join/shared_invite/zt-25438diev-mJ6LIZpJevG0LXCEcL0NhQ#)**.

View file

@ -61,3 +61,19 @@ The one click deployment will create a **free dyno** and a **free postgresql dat
:::tip
ToolJet server and client can be deployed as standalone applications. If you do not want to deploy the client on Heroku, modify `package.json` accordingly. We have a [guide](/docs/setup/client) on deploying ToolJet client using services such as Firebase.
:::
## Upgrading to v2.24.3-ee2.10.2
Version v2.24.3-ee2.10.2 includes architectural changes and, hence, comes with new migrations.
If this is a new installation of the application, you may start directly with version v2.24.3-ee2.10.2. This guide is not required for new installations.
#### Prerequisites for Upgrading to the Latest Version:
- It is **crucial to perform a comprehensive backup of your database** before starting the upgrade process to prevent data loss.
- Ensure that your current version is v2.23.3-ee2.10.2 before upgrading.
- Users on versions earlier than v2.23.3-ee2.10.2 must first upgrade to this version before proceeding to v2.24.3-ee2.10.2.
For specific issues or questions, refer to our **[Slack](https://tooljet.slack.com/join/shared_invite/zt-25438diev-mJ6LIZpJevG0LXCEcL0NhQ#)**.

View file

@ -49,3 +49,19 @@ This seeds the database with a default user with the following credentials:
**email**: `dev@tooljet.io`
**password**: `password`
## Upgrading to v2.24.3-ee2.10.2
Version v2.24.3-ee2.10.2 includes architectural changes and, hence, comes with new migrations.
If this is a new installation of the application, you may start directly with version v2.24.3-ee2.10.2. This guide is not required for new installations.
#### Prerequisites for Upgrading to the Latest Version:
- It is **crucial to perform a comprehensive backup of your database** before starting the upgrade process to prevent data loss.
- Ensure that your current version is v2.23.3-ee2.10.2 before upgrading.
- Users on versions earlier than v2.23.3-ee2.10.2 must first upgrade to this version before proceeding to v2.24.3-ee2.10.2.
For specific issues or questions, refer to our **[Slack](https://tooljet.slack.com/join/shared_invite/zt-25438diev-mJ6LIZpJevG0LXCEcL0NhQ#)**.

View file

@ -74,3 +74,19 @@ This seeds the database with a default user with the following credentials:
**emai**: `dev@tooljet.io`
**password**: `password`
## Upgrading to v2.24.3-ee2.10.2
Version v2.24.3-ee2.10.2 includes architectural changes and, hence, comes with new migrations.
If this is a new installation of the application, you may start directly with version v2.24.3-ee2.10.2. This guide is not required for new installations.
#### Prerequisites for Upgrading to the Latest Version:
- It is **crucial to perform a comprehensive backup of your database** before starting the upgrade process to prevent data loss.
- Ensure that your current version is v2.23.3-ee2.10.2 before upgrading.
- Users on versions earlier than v2.23.3-ee2.10.2 must first upgrade to this version before proceeding to v2.24.3-ee2.10.2.
For specific issues or questions, refer to our **[Slack](https://tooljet.slack.com/join/shared_invite/zt-25438diev-mJ6LIZpJevG0LXCEcL0NhQ#)**.

View file

@ -48,4 +48,20 @@ If there are self signed HTTPS endpoints that Tooljet needs to connect to, pleas
:::tip
If you want to serve ToolJet client from services such as Firebase or Netlify, please read the client Setup documentation **[here](/docs/setup/client)**.
:::
:::
## Upgrading to v2.24.3-ee2.10.2
Version v2.24.3-ee2.10.2 includes architectural changes and, hence, comes with new migrations.
If this is a new installation of the application, you may start directly with version v2.24.3-ee2.10.2. This guide is not required for new installations.
#### Prerequisites for Upgrading to the Latest Version:
- It is **crucial to perform a comprehensive backup of your database** before starting the upgrade process to prevent data loss.
- Ensure that your current version is v2.23.3-ee2.10.2 before upgrading.
- Users on versions earlier than v2.23.3-ee2.10.2 must first upgrade to this version before proceeding to v2.24.3-ee2.10.2.
For specific issues or questions, refer to our **[Slack](https://tooljet.slack.com/join/shared_invite/zt-25438diev-mJ6LIZpJevG0LXCEcL0NhQ#)**.

View file

@ -20,4 +20,20 @@ You'll need to setup the following environment variables if ToolJet installation
See all **[Environment Variables](/docs/setup/env-vars)** here.
:::
## Upgrading to v2.24.3-ee2.10.2
Version v2.24.3-ee2.10.2 includes architectural changes and, hence, comes with new migrations.
If this is a new installation of the application, you may start directly with version v2.24.3-ee2.10.2. This guide is not required for new installations.
#### Prerequisites for Upgrading to the Latest Version:
- It is **crucial to perform a comprehensive backup of your database** before starting the upgrade process to prevent data loss.
- Ensure that your current version is v2.23.3-ee2.10.2 before upgrading.
- Users on versions earlier than v2.23.3-ee2.10.2 must first upgrade to this version before proceeding to v2.24.3-ee2.10.2.
For specific issues or questions, refer to our **[Slack](https://tooljet.slack.com/join/shared_invite/zt-25438diev-mJ6LIZpJevG0LXCEcL0NhQ#)**.

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