diff --git a/.github/workflows/cypress-appbuilder.yml b/.github/workflows/cypress-appbuilder.yml
index 3e9be3f560..67eb0ae432 100644
--- a/.github/workflows/cypress-appbuilder.yml
+++ b/.github/workflows/cypress-appbuilder.yml
@@ -2,7 +2,7 @@ name: Cypress App-Builder
on:
pull_request_target:
- types: [labeled, unlabeled, closed]
+ types: [labeled]
workflow_dispatch:
env:
@@ -12,22 +12,18 @@ env:
jobs:
Cypress-App-Builder:
runs-on: ubuntu-22.04
-
if: |
- github.event.action == 'labeled' &&
- (
- github.event.label.name == 'run-cypress' ||
- github.event.label.name == 'run-ce-app-builder' ||
- github.event.label.name == 'run-ee-app-builder'
- )
+ contains(github.event.pull_request.labels.*.name, 'run-ce-app-builder') ||
+ contains(github.event.pull_request.labels.*.name, 'run-ee-app-builder') ||
+ contains(github.event.pull_request.labels.*.name, 'run-cypress')
strategy:
matrix:
edition: >-
${{
- contains(github.event.pull_request.labels.*.name, 'run-cypress') && fromJson('["ce", "ee"]') ||
contains(github.event.pull_request.labels.*.name, 'run-ce-app-builder') && fromJson('["ce"]') ||
contains(github.event.pull_request.labels.*.name, 'run-ee-app-builder') && fromJson('["ee"]') ||
+ contains(github.event.pull_request.labels.*.name, 'run-cypress') && fromJson('["ce", "ee"]') ||
fromJson('[]')
}}
@@ -164,8 +160,8 @@ jobs:
Cypress-App-builder-Subpath:
runs-on: ubuntu-22.04
-
- if: ${{ github.event.action == 'labeled' && github.event.label.name == 'run-cypress-app-builder-subpath' }}
+ if: contains(github.event.pull_request.labels.*.name, 'run-cypress') ||
+ contains(github.event.pull_request.labels.*.name, 'run-cypress-app-builder-subpath')
steps:
- name: Checkout
@@ -173,82 +169,6 @@ jobs:
with:
ref: ${{ github.event.pull_request.head.ref }}
- # Create Docker Buildx builder with platform configuration
- - name: Set up Docker Buildx
- run: |
- mkdir -p ~/.docker/cli-plugins
- curl -SL https://github.com/docker/buildx/releases/download/v0.11.0/buildx-v0.11.0.linux-amd64 -o ~/.docker/cli-plugins/docker-buildx
- chmod a+x ~/.docker/cli-plugins/docker-buildx
- docker buildx create --name mybuilder --platform linux/arm64,linux/amd64,linux/amd64/v2,linux/riscv64,linux/ppc64le,linux/s390x,linux/386,linux/mips64le,linux/mips64,linux/arm/v7,linux/arm/v6
- docker buildx use mybuilder
-
- - name: Set DOCKER_CLI_EXPERIMENTAL
- run: echo "DOCKER_CLI_EXPERIMENTAL=enabled" >> $GITHUB_ENV
-
- - name: use mybuilder buildx
- run: docker buildx use mybuilder
-
- - name: Build docker image
- run: docker buildx build --platform=linux/amd64 -f docker/production.Dockerfile . -t tooljet/tj-osv:cypressplaform
-
- - name: Set up environment variables
- run: |
- echo "TOOLJET_HOST=http://localhost:3000" >> .env
- echo "LOCKBOX_MASTER_KEY=cd97331a419c09387bef49787f7da8d2a81d30733f0de6bed23ad8356d2068b2" >> .env
- echo "SECRET_KEY_BASE=7073b9a35a15dd20914ae17e36a693093f25b74b96517a5fec461fc901c51e011cd142c731bee48c5081ec8bac321c1f259ef097ef2a16f25df17a3798c03426" >> .env
- echo "PG_DB=tooljet_development" >> .env
- echo "PG_USER=postgres" >> .env
- echo "PG_HOST=postgres" >> .env
- echo "PG_PASS=postgres" >> .env
- echo "PG_PORT=5432" >> .env
- echo "ENABLE_TOOLJET_DB=true" >> .env
- echo "TOOLJET_DB=tooljet_db" >> .env
- echo "TOOLJET_DB_USER=postgres" >> .env
- echo "TOOLJET_DB_HOST=postgres" >> .env
- echo "TOOLJET_DB_PASS=postgres" >> .env
- echo "PGRST_JWT_SECRET=r9iMKoe5CRMgvJBBtp4HrqN7QiPpUToj" >> .env
- echo "PGRST_HOST=postgrest" >> .env
- echo "PGRST_DB_URI=postgres://postgres:postgres@postgres/tooljet_db" >> .env
- echo "SSO_GIT_OAUTH2_CLIENT_ID=dummy" >> .env
- echo "SSO_GIT_OAUTH2_CLIENT_SECRET=dummy" >> .env
- echo "SSO_GIT_OAUTH2_HOST=dummy" >> .env
- echo "SSO_GOOGLE_OAUTH2_CLIENT_ID=dummy" >> .env
- echo "SUB_PATH=/apps/tooljet/" >> .env
- echo "NODE_ENV=production" >> .env
- echo "SERVE_CLIENT=true" >> .env
- echo "ENABLE_PRIVATE_APP_EMBED=true" >> .env
-
- - name: Pulling the docker-compose file
- run: curl -LO https://tooljet-test.s3.us-west-1.amazonaws.com/docker-compose.yaml && mkdir postgres_data
-
- - name: Run docker-compose file
- run: docker-compose up -d
-
- - name: Checking containers
- run: docker ps -a
-
- - name: docker logs
- run: sudo docker logs Tooljet-app
-
- - name: Wait for the server to be ready
- run: |
- timeout 1500 bash -c '
- until curl --silent --fail http://localhost:80/apps/tooljet/; do
- sleep 5
- done'
-
- - name: Seeding (Setup Super Admin)
- run: |
- curl 'http://localhost:3000/api/onboarding/setup-super-admin' \
- -H 'Content-Type: application/json' \
- --data-raw '{
- "companyName": "ToolJet",,
- "name": "The Developer",
- "workspaceName": "Tooljet'\''s workspace",
- "email": "dev@tooljet.io",
- "password": "password"
- }'
-
- name: Create Cypress environment file
id: create-json
uses: jsdaniell/create-json@1.1.2
diff --git a/.github/workflows/cypress-marketplace.yml b/.github/workflows/cypress-marketplace.yml
index 19368195a6..4d34523219 100644
--- a/.github/workflows/cypress-marketplace.yml
+++ b/.github/workflows/cypress-marketplace.yml
@@ -2,7 +2,7 @@ name: Cypress Marketplace
on:
pull_request_target:
- types: [labeled, unlabeled, closed]
+ types: [labeled]
workflow_dispatch:
@@ -14,13 +14,9 @@ jobs:
Cypress-Marketplace:
runs-on: ubuntu-22.04
- if: |
- github.event.action == 'labeled' &&
- (
- github.event.label.name == 'run-cypress' ||
- github.event.label.name == 'run-ce-cypress-marketplace' ||
- github.event.label.name == 'run-ee-cypress-marketplace'
- )
+ if: contains(github.event.pull_request.labels.*.name, 'run-cypress') ||
+ contains(github.event.pull_request.labels.*.name, 'run-ce-cypress-marketplace') ||
+ contains(github.event.pull_request.labels.*.name, 'run-ee-cypress-marketplace')
strategy:
matrix:
@@ -44,7 +40,7 @@ jobs:
mkdir -p ~/.docker/cli-plugins
curl -SL https://github.com/docker/buildx/releases/download/v0.11.0/buildx-v0.11.0.linux-amd64 -o ~/.docker/cli-plugins/docker-buildx
chmod a+x ~/.docker/cli-plugins/docker-buildx
- docker buildx create --name mybuilder --platform linux/arm64,linux/amd64,linux/amd64/v2,linux/riscv64,linux/ppc64le,linux/s390x,linux/386,linux/mips64le,linux/mips64,linux/arm/v7,linux/arm/v6
+ docker buildx create --name mybuilder --platform linux/arm64,linux/amd64
docker buildx use mybuilder
- name: Set DOCKER_CLI_EXPERIMENTAL
@@ -189,7 +185,8 @@ jobs:
Cypress-Marketplace-Subpath:
runs-on: ubuntu-22.04
- if: ${{ github.event.action == 'labeled' && github.event.label.name == 'run-cypress-marketplace-subpath' }}
+ if: contains(github.event.pull_request.labels.*.name, 'run-cypress') ||
+ contains(github.event.pull_request.labels.*.name, 'run-cypress-marketplace-subpath')
steps:
- name: Checkout
diff --git a/.github/workflows/cypress-platform.yml b/.github/workflows/cypress-platform.yml
index 3dbacafc06..0480db39f9 100644
--- a/.github/workflows/cypress-platform.yml
+++ b/.github/workflows/cypress-platform.yml
@@ -2,7 +2,7 @@ name: Cypress Platform
on:
pull_request_target:
- types: [labeled, unlabeled, closed]
+ types: [labeled]
workflow_dispatch:
env:
@@ -12,14 +12,9 @@ env:
jobs:
Cypress-Platform:
runs-on: ubuntu-22.04
- if: |
- github.event.action == 'labeled' &&
- (
- github.event.label.name == 'run-cypress' ||
- github.event.label.name == 'run-ce-cypress-platform' ||
- github.event.label.name == 'run-ee-cypress-platform'
- )
-
+ if: contains(github.event.pull_request.labels.*.name, 'run-cypress') ||
+ contains(github.event.pull_request.labels.*.name, 'run-ce-cypress-platform') ||
+ contains(github.event.pull_request.labels.*.name, 'run-ee-cypress-platform')
strategy:
matrix:
edition: >-
diff --git a/.github/workflows/render-preview-deploy.yml b/.github/workflows/render-preview-deploy.yml
index 203ee88150..d1ca481d02 100644
--- a/.github/workflows/render-preview-deploy.yml
+++ b/.github/workflows/render-preview-deploy.yml
@@ -12,7 +12,7 @@ permissions:
jobs:
-# Community Edition
+# Community Edition CE
create-ce-review-app:
if: ${{ github.event.action == 'labeled' && (github.event.label.name == 'create-ce-review-app' || github.event.label.name == 'review-app') }}
runs-on: ubuntu-latest
@@ -72,7 +72,7 @@ jobs:
"envVars": [
{
"key": "PG_HOST",
- "value": "${{ secrets.RENDER_PG_HOST }}"
+ "value": "localhost"
},
{
"key": "PG_PORT",
@@ -80,11 +80,11 @@ jobs:
},
{
"key": "PG_USER",
- "value": "${{ secrets.RENDER_PG_USER }}"
+ "value": "tooljet"
},
{
"key": "PG_PASS",
- "value": "${{ secrets.RENDER_PG_PASS }}"
+ "value": "postgres"
},
{
"key": "PG_DB",
@@ -96,15 +96,15 @@ jobs:
},
{
"key": "TOOLJET_DB_HOST",
- "value": "${{ secrets.RENDER_PG_HOST }}"
+ "value": "localhost"
},
{
"key": "TOOLJET_DB_USER",
- "value": "${{ secrets.RENDER_PG_USER }}"
+ "value": "tooljet"
},
{
"key": "TOOLJET_DB_PASS",
- "value": "${{ secrets.RENDER_PG_PASS }}"
+ "value": "postgres"
},
{
"key": "TOOLJET_DB_PORT",
@@ -116,7 +116,7 @@ jobs:
},
{
"key": "PGRST_DB_URI",
- "value": "postgres://${{ secrets.RENDER_PG_USER }}:${{ secrets.RENDER_PG_PASS }}@${{ secrets.RENDER_PG_HOST }}/${{ env.PR_NUMBER }}-ce-tjdb"
+ "value": "postgres://tooljet:postgres@localhost/${{ env.PR_NUMBER }}-ce-tjdb"
},
{
"key": "PGRST_HOST",
@@ -162,18 +162,6 @@ jobs:
"key": "SMTP_PASSWORD",
"value": "${{ secrets.RENDER_SMTP_PASSWORD }}"
},
- {
- "key": "TEMPORAL_SERVER_ADDRESS",
- "value": "https://auto-setup-1-25-1.onrender.com"
- },
- {
- "key": "TEMPORAL_TASK_QUEUE_NAME_FOR_WORKFLOWS",
- "value": "tooljet-ce-pr-${{ env.PR_NUMBER }}"
- },
- {
- "key": "TOOLJET_WORKFLOWS_TEMPORAL_NAMESPACE",
- "value": "default"
- },
{
"key": "TOOLJET_MARKETPLACE_URL",
"value": "${{ secrets.MARKETPLACE_BUCKET }}"
@@ -424,7 +412,7 @@ jobs:
"envVars": [
{
"key": "PG_HOST",
- "value": "${{ secrets.RENDER_PG_HOST }}"
+ "value": "localhost"
},
{
"key": "PG_PORT",
@@ -432,11 +420,11 @@ jobs:
},
{
"key": "PG_USER",
- "value": "${{ secrets.RENDER_PG_USER }}"
+ "value": "tooljet"
},
{
"key": "PG_PASS",
- "value": "${{ secrets.RENDER_PG_PASS }}"
+ "value": "postgres"
},
{
"key": "PG_DB",
@@ -448,15 +436,15 @@ jobs:
},
{
"key": "TOOLJET_DB_HOST",
- "value": "${{ secrets.RENDER_PG_HOST }}"
+ "value": "localhost"
},
{
"key": "TOOLJET_DB_USER",
- "value": "${{ secrets.RENDER_PG_USER }}"
+ "value": "tooljet"
},
{
"key": "TOOLJET_DB_PASS",
- "value": "${{ secrets.RENDER_PG_PASS }}"
+ "value": "postgres"
},
{
"key": "TOOLJET_DB_PORT",
@@ -468,7 +456,7 @@ jobs:
},
{
"key": "PGRST_DB_URI",
- "value": "postgres://${{ secrets.RENDER_PG_USER }}:${{ secrets.RENDER_PG_PASS }}@${{ secrets.RENDER_PG_HOST }}/${{ env.PR_NUMBER }}-ee-tjdb"
+ "value": "postgres://tooljet:postgres@localhost/${{ env.PR_NUMBER }}-ee-tjdb"
},
{
"key": "PGRST_HOST",
@@ -1124,4 +1112,3 @@ jobs:
# } catch (e) {
# console.log(e)
# }
-
diff --git a/cypress-tests/cypress/commands/apiCommands.js b/cypress-tests/cypress/commands/apiCommands.js
index b5d91ff88d..e9891c962e 100644
--- a/cypress-tests/cypress/commands/apiCommands.js
+++ b/cypress-tests/cypress/commands/apiCommands.js
@@ -192,6 +192,7 @@ Cypress.Commands.add("apiCreateWorkspace", (workspaceName, workspaceSlug) => {
{ log: false }
).then((response) => {
expect(response.status).to.equal(201);
+ return response;
});
});
});
diff --git a/cypress-tests/cypress/e2e/happyPath/platform/commonTestcases/workspace/groups/permissions.cy.js b/cypress-tests/cypress/e2e/happyPath/platform/commonTestcases/workspace/groups/permissions.cy.js
index bdf3593e5c..22b6c6b6a5 100644
--- a/cypress-tests/cypress/e2e/happyPath/platform/commonTestcases/workspace/groups/permissions.cy.js
+++ b/cypress-tests/cypress/e2e/happyPath/platform/commonTestcases/workspace/groups/permissions.cy.js
@@ -522,10 +522,8 @@ describe("Manage Groups", () => {
commonSelectors.buttonSelector(exportAppModalText.exportSelectedVersion)
).click();
cy.exec("ls ./cypress/downloads/").then((result) => {
- cy.log(result);
const downloadedAppExportFileName = result.stdout.split("\n")[0];
exportedFilePath = `cypress/downloads/${downloadedAppExportFileName}`;
- cy.log(exportedFilePath);
cy.get(importSelectors.dropDownMenu).should("be.visible").click();
cy.get(importSelectors.importOptionInput).selectFile(exportedFilePath, {
force: true,
diff --git a/cypress-tests/cypress/e2e/happyPath/platform/externalApi/apiUsers.cy.js b/cypress-tests/cypress/e2e/happyPath/platform/externalApi/apiUsers.cy.js
new file mode 100644
index 0000000000..b95970d349
--- /dev/null
+++ b/cypress-tests/cypress/e2e/happyPath/platform/externalApi/apiUsers.cy.js
@@ -0,0 +1,382 @@
+import { fake } from "Fixtures/fake";
+import {
+ createUser, getAllUsers, getUser, updateUser, createGroup, validateUserInGroup, updateUserRole,
+ getAllWorkspaces, replaceUserWorkspace, replaceUserWorkspacesRelations
+} from 'Support/utils/api';
+import { groupsSelector } from "Selectors/manageGroups";
+import { commonSelectors } from 'Selectors/common';
+import { searchUser, navigateToManageUsers, logout, navigateToManageGroups } from 'Support/utils/common';
+describe("API Test", () => {
+
+ const sanitize = (str) => str.toLowerCase().replace(/[^A-Za-z]/g, "");
+ let userId;
+ let workspaceId;
+ const data = {
+ firstName: fake.firstName,
+ lastName: fake.lastName,
+ firstName1: fake.firstName,
+ lastName1: fake.lastName,
+ firstName2: fake.firstName,
+ lastName2: fake.lastName,
+ email: fake.email.toLowerCase().replaceAll("[^A-Za-z]", ""),
+ email1: fake.email.toLowerCase().replaceAll("[^A-Za-z]", ""),
+ email2: fake.email.toLowerCase().replaceAll("[^A-Za-z]", ""),
+ workspaceName: sanitize(fake.lastName),
+ workspaceSlug: sanitize(fake.lastName),
+ workspaceName1: sanitize(fake.firstName),
+ workspaceSlug1: sanitize(fake.firstName),
+ group1: sanitize(fake.firstName),
+ group2: sanitize(fake.firstName),
+ group3: sanitize(fake.firstName),
+ group4: sanitize(fake.firstName),
+ group5: sanitize(fake.firstName),
+ appName: fake.companyName
+ };
+
+ //user with all valid details
+ const userData = {
+ name: `${data.firstName} ${data.lastName}`,
+ email: data.email,
+ password: "password",
+ status: "active",
+ workspaces: [
+ {
+ name: "My workspace",
+ status: "active",
+ groups: [
+ { name: data.group1 },
+ { name: data.group2 }
+ ]
+ },
+ {
+ name: data.workspaceName,
+ status: "active",
+ role: "builder",
+ groups: [{ name: data.group3 }]
+ },
+ {
+ name: data.workspaceName1,
+ status: "archived",
+ role: "admin",
+ groups: [{ name: data.group4 }]
+ }
+ ]
+ };
+
+ beforeEach(() => {
+ cy.defaultWorkspaceLogin();
+ });
+
+ it("Create user with valid details", () => {
+ // create multiple groups in different workspaces
+ navigateToManageGroups();
+ [data.group1, data.group2, data.group5].forEach(createGroup);
+
+ //builder group
+ cy.get(groupsSelector.groupLink(data.group5)).click();
+ cy.get(groupsSelector.permissionsLink).click();
+ cy.get(groupsSelector.appsCreateCheck).check();
+
+ [
+ { name: data.workspaceName, slug: data.workspaceSlug, group: data.group3 },
+ { name: data.workspaceName1, slug: data.workspaceSlug1, group: data.group4 }
+ ].forEach(({ name, slug, group }) => {
+ cy.apiCreateWorkspace(name, slug);
+ cy.visit(slug);
+ navigateToManageGroups();
+ createGroup(group);
+ });
+
+ // Added valid user and logged-in in the workpsace
+ cy.visit("/my-workspace");
+ cy.wait(500);
+ createUser(userData).then((response) => {
+ expect(response.status).to.eq(201);
+ userId = response.body.id;
+ workspaceId = response.body.workspaces[0].id;
+ navigateToManageUsers();
+ searchUser(data.email);
+ cy.contains("td", data.email)
+ .parent()
+ .within(() => {
+ cy.get("td small").should("have.text", "active");
+ });
+
+ validateUserInGroup(data.email, "my-workspace", "end-user");
+ validateUserInGroup(data.email, data.workspaceSlug, "builder");
+ validateUserInGroup(data.email, data.workspaceSlug1, "admin", false);
+ cy.apiLogout();
+
+ cy.apiLogin(data.email, "password");
+ cy.visit("/my-workspace");
+ cy.get(commonSelectors.workspaceName).should("have.text", "My workspace");
+ logout();
+
+ //Retrieve all users, a specific user by ID, and all workspaces
+ cy.defaultWorkspaceLogin();
+ navigateToManageUsers();
+ let number = 0;
+ cy.get('[data-cy="title-users-page"]').invoke('text').then((text) => {
+ number = parseInt(text.match(/\d+/)[0], 10);
+ });
+
+ getAllUsers().then((response) => {
+ expect(response.status).to.eq(200);
+ //expect(response.body.length).to.eq(number); //error due to removal of user from instance
+ });
+
+ getUser(userId).then((response) => {
+ expect(response.status).to.eq(200);
+ expect(response.body.name).to.eq(`${data.firstName} ${data.lastName}`);
+ });
+
+ getAllWorkspaces().then((response) => {
+ expect(response.status).to.eq(200);
+ });
+ });
+ });
+
+ it('Handles user creation errors', () => {
+ const invalidUserData = [
+ { // Duplicate user
+ data: { ...userData },
+ expectedStatus: 422,
+ expectedMessage: 'Already exists!'
+ },
+ { // Invalid email and long password
+ data: {
+ ...userData,
+ name: `${data.firstName1} ${data.lastName1}`,
+ email: 'invalid-email',
+ password: 'a'.repeat(101)
+ },
+ expectedStatus: 400,
+ expectedMessages: ['email must be an email', 'password must be shorter than or equal to 100 characters']
+ },
+ { // Non-existing group
+ data: {
+ ...userData,
+ name: `${data.firstName1} ${data.lastName1}`,
+ email: `${data.email1}`,
+ workspaces: [{ name: 'My workspace', status: 'active', groups: [{ name: 'NonExistingGroup' }] }]
+ },
+ expectedStatus: 400,
+ expectedMessage: 'Group permission id or name not found:'
+ },
+ { // Non-existing workspace
+ data: {
+ ...userData,
+ name: `${data.firstName1} ${data.lastName1}`,
+ email: `${data.email1}`,
+ workspaces: [{ name: 'NonExistingWorkspace', status: 'active' }]
+ },
+ expectedStatus: 400,
+ expectedMessage: 'The workspaces id or name do not exist:'
+ }
+ ];
+
+ invalidUserData.forEach(({ data, expectedStatus, expectedMessages, expectedMessage }) => {
+ createUser(data).then((response) => {
+ expect(response.status).to.eq(expectedStatus);
+ if (expectedMessages) {
+ expectedMessages.forEach(msg => expect(response.body.message).to.include(msg));
+ } else {
+ expect(response.body.message).to.include(expectedMessage);
+ }
+ });
+ });
+ //Conflict permission
+ const enduserData = {
+ ...userData,
+ name: `${data.firstName1} ${data.lastName1}`,
+ email: `${data.email1}`,
+ workspaces: [{ name: 'My workspace', status: 'active', groups: [{ name: data.group5 }] }]
+ }
+ createUser(enduserData).then((response) => {
+ expect(response.status).to.eq(400);
+ expect(response.body.message.title).to.include("Conflicting permissions");
+ })
+ });
+
+ it("Update user details and workspaces relations", () => {
+ const updatedUserData = {
+ name: `${data.firstName1} ${data.lastName1}`,
+ email: data.email1,
+ password: "updatedpassword"
+ }
+ updateUser(userId, updatedUserData).then((response) => {
+ expect(response.status).to.eq(200);
+ })
+ cy.apiLogout();
+ cy.apiLogin(updatedUserData.email, updatedUserData.password);
+ cy.apiLogout();
+
+ // Replace user workspaces relations
+ cy.apiLogin();
+ validateUserInGroup(updatedUserData.email, "my-workspace", data.group2);
+ validateUserInGroup(updatedUserData.email, data.workspaceSlug, data.group3);
+ cy.visit(data.workspaceSlug1);
+ navigateToManageUsers();
+ searchUser(updatedUserData.email);
+ cy.contains("td", updatedUserData.email);
+
+ replaceUserWorkspacesRelations(userId, [
+ { name: "My workspace", status: "active", role: "end-user", groups: [{ name: data.group1 }] },
+ { name: data.workspaceName, status: "active", role: "builder", groups: [] }
+ ]).then((response) => {
+ expect(response.status).to.eq(200);
+ });
+ navigateToManageUsers();
+ validateUserInGroup(updatedUserData.email, "my-workspace", data.group2, false);
+ validateUserInGroup(updatedUserData.email, data.workspaceSlug, data.group3, false);
+
+ cy.visit(data.workspaceSlug1);
+ navigateToManageUsers();
+ searchUser(updatedUserData.email);
+ cy.get('[data-cy="text-no-result-found"]').contains("No result found");
+ replaceUserWorkspacesRelations(userId, []).then((response) => {
+ expect(response.status).to.eq(200);
+ });
+ cy.visit("my-workspace");
+ navigateToManageUsers();
+ searchUser(updatedUserData.email);
+ cy.get('[data-cy="text-no-result-found"]').contains("No result found");
+ });
+
+ it("update user role", () => {
+ const userData2 = {
+ name: `${data.firstName} ${data.lastName}`,
+ email: data.email,
+ password: "password",
+ status: "active",
+ workspaces: [
+ {
+ name: "My workspace",
+ status: "active"
+ }
+ ]
+ }
+ let userId1;
+ let workspaceId1;
+ createUser(userData2).then((response) => {
+ expect(response.status).to.eq(201);
+ userId1 = response.body.id;
+ workspaceId1 = response.body.workspaces[0].id;
+ //update role to builder and validate user in builder's group
+ updateUserRole(workspaceId1, { newRole: "builder", userId: userId1 })
+ .then((response) => {
+ expect(response.status).to.eq(200);
+ });
+ validateUserInGroup(userData2.email, "my-workspace", "builder");
+
+ //update role to end-user and validate user is removed from builder's group
+ updateUserRole(workspaceId1, { newRole: "end-user", userId: userId1 })
+ .then((response) => {
+ expect(response.status).to.eq(200);
+ });
+ validateUserInGroup(userData2.email, "my-workspace", data.group5, false);
+
+ // update role to builders and validate app's owner role can't be updated
+ updateUserRole(workspaceId1, { newRole: "builder", userId: userId1 })
+ .then((response) => {
+ expect(response.status).to.eq(200);
+ });
+ cy.apiLogout();
+ cy.apiLogin(userData2.email, userData2.password);
+ cy.apiCreateApp(data.appName);
+ cy.apiLogout();
+ cy.defaultWorkspaceLogin();
+ updateUserRole(workspaceId1, { newRole: "end-user", userId: userId1 })
+ .then((response) => {
+ expect(response.status).to.eq(400);
+ expect(response.body.message.title).to.include("Can not change user role");
+ });
+
+ });
+ });
+ const userData3 = {
+ name: `${data.firstName2} ${data.lastName2}`,
+ email: data.email2,
+ password: "password",
+ status: "active",
+ workspaces: [
+ {
+ name: "My workspace",
+ status: "active",
+ groups: [
+ { name: data.group1 },
+ { name: data.group2 }
+ ]
+ },
+ {
+ name: data.workspaceName,
+ status: "active",
+ role: "builder",
+ groups: [{ name: data.group3 }]
+ },
+ {
+ name: data.workspaceName1,
+ status: "archived",
+ role: "admin",
+ groups: [{ name: data.group4 }]
+ }
+ ]
+ };
+ it("Replace user workspace", () => {
+ let userId1, workspaceId1;
+ createUser(userData3).then((response) => {
+ expect(response.status).to.eq(201);
+ userId1 = response.body.id;
+ workspaceId1 = response.body.workspaces[0].id;
+
+ // Helper function to replace user workspace and validate response
+ const replaceAndValidate = (payload, expectedStatus = 200) => {
+ return replaceUserWorkspace(userId1, workspaceId1, payload).then((response) => {
+ expect(response.status).to.eq(expectedStatus);
+ });
+ };
+
+ // No change if empty request body
+ replaceAndValidate({}).then(() => {
+ validateUserInGroup(userData3.email, "my-workspace", data.group1);
+ validateUserInGroup(userData3.email, "my-workspace", data.group2);
+ });
+
+ // Archive the user and verify status
+ replaceAndValidate({ status: "archived" }).then(() => {
+ navigateToManageUsers();
+ searchUser(userData3.email);
+ cy.contains("td", userData3.email)
+ .parent()
+ .within(() => {
+ cy.get("td small").should("have.text", "archived");
+ });
+ });
+
+ // Reactivate user and validate groups
+ replaceAndValidate({ status: "active" }).then(() => {
+ validateUserInGroup(userData3.email, "my-workspace", data.group1);
+ validateUserInGroup(userData3.email, "my-workspace", data.group2);
+ });
+
+ // Update groups and validate removal
+ replaceAndValidate({ groups: [{ name: data.group1 }] }).then(() => {
+ validateUserInGroup(userData3.email, "my-workspace", data.group2, false);
+ });
+
+ //Empty group array, user removed from groups
+ replaceAndValidate({ groups: [] }).then(() => {
+ validateUserInGroup(userData3.email, "my-workspace", data.group1, false);
+ });
+
+ //Conflict permission
+ replaceAndValidate({ groups: [{ name: data.group5 }] }, 400);
+
+ //Add user in groups and validate
+ replaceAndValidate({ groups: [{ name: data.group1 }, { name: data.group2 }] });
+ validateUserInGroup(userData3.email, "my-workspace", data.group1);
+ validateUserInGroup(userData3.email, "my-workspace", data.group2);
+ });
+ });
+});
+
diff --git a/cypress-tests/cypress/e2e/happyPath/platform/externalApi/appImportAndExportAPI.cy.js b/cypress-tests/cypress/e2e/happyPath/platform/externalApi/appImportAndExportAPI.cy.js
new file mode 100644
index 0000000000..f2e522b22a
--- /dev/null
+++ b/cypress-tests/cypress/e2e/happyPath/platform/externalApi/appImportAndExportAPI.cy.js
@@ -0,0 +1,160 @@
+import { importApp, exportApp, allAppsDetails } from 'Support/utils/api';
+import { fake } from "Fixtures/fake";
+
+describe("Export and Import API ", () => {
+
+ const sanitize = (str) => str.toLowerCase().replace(/[^A-Za-z]/g, "");
+ const data = {
+ workspaceName: sanitize(fake.lastName),
+ workspaceSlug: sanitize(fake.lastName),
+ }
+
+ const fixtureFiles = {
+ requestData: "templates/import_unnamed_file.json",
+ requestData2: "templates/import_named_file.json",
+ requestData3: "templates/three-versions.json",
+ };
+ let requestData, requestData2, requestData3;
+
+ beforeEach(() => {
+ cy.defaultWorkspaceLogin();
+
+ const fixturePromises = Object.entries(fixtureFiles).map(([key, file]) =>
+ cy.fixture(file).then((data) => ({ key, data }))
+ );
+
+ // Assign loaded data to respective variables
+ return Promise.all(fixturePromises).then((results) => {
+ results.forEach(({ key, data }) => {
+ ({ requestData, requestData2, requestData3 }[key] = data);
+ });
+ });
+
+ });
+ it("Import App API", () => {
+ const workspaceId = Cypress.env("workspaceId");
+
+ importApp(workspaceId, requestData).then((response) => {
+ expect(response.status).to.eq(201);
+ expect(response.body.message).to.include("App imported successfully into workspace");
+ });
+
+ //Invalid access token and workspace
+ importApp(workspaceId, requestData, {
+ Authorization: "Basic xyz",
+ "Content-Type": "application/json"
+ }).then((response) => {
+ expect(response.status).to.eq(403);
+ });
+
+ importApp(workspaceId, requestData, {
+ Authorization: "",
+ "Content-Type": "application/json"
+ }).then((response) => {
+ expect(response.status).to.eq(403);
+ });
+
+ importApp(`${workspaceId}ee`, requestData).then((response) => {
+ expect(response.status).to.eq(400);
+ });
+
+ //Import named file
+ importApp(workspaceId, requestData2).then((response) => {
+ expect(response.status).to.eq(201);
+ expect(response.body.message).to.include("App imported successfully into workspace");
+ });
+ cy.reload();
+ cy.get('[data-cy="app_json-title"]').should("exist");
+
+ //duplicate app
+ importApp(workspaceId, requestData2).then((response) => {
+ expect(response.status).to.eq(409);
+ expect(response.body.message).to.include("App with app_json already exists in the workspace");
+ });
+ cy.deleteApp("app_json");
+ cy.get('[data-cy="app_json-title"]').should("not.exist");
+
+ //Import app in another workpsace
+ let newWorkspaceId;
+ cy.apiCreateWorkspace(data.workspaceName, data.workspaceSlug).then((res) => {
+ newWorkspaceId = res.body.organization_id;
+ cy.visit(data.workspaceSlug);
+
+ importApp(newWorkspaceId, requestData).then((response) => {
+ expect(response.status).to.eq(201);
+ expect(response.body.message).to.include("App imported successfully into workspace");
+ });
+ });
+ });
+
+ it("Export App API", () => {
+ const workspaceId = Cypress.env("workspaceId");
+ let appId;
+ importApp(workspaceId, requestData3).then((response) => {
+ expect(response.status).to.eq(201);
+ expect(response.body.message).to.include("App imported successfully into workspace");
+ }).then(() => {
+ cy.get('[data-cy^="import-export-app"]')
+ .first()
+ .find('[data-cy="edit-button"]')
+ .click({ force: true });
+ cy.skipWalkthrough();
+ });
+
+ cy.get('[data-cy="left-sidebar-settings-button"]').click();
+ cy.get('[data-cy="app-slug-input-field"]').invoke('val').then((value) => {
+ appId = value;
+
+ //export last created version
+ exportApp(workspaceId, appId, "").then((response) => {
+ expect(response.status).to.eq(201);
+ expect(response.body.app[0].definition.appV2.appVersions.length).to.eq(1);
+ expect(response.body.app[0].definition.appV2.appVersions[0].name).to.eq("v3");
+ });
+ //export specific versions
+ exportApp(workspaceId, appId, "?appVersion=v2").then((response) => {
+ expect(response.status).to.eq(201);
+ expect(response.body.app[0].definition.appV2.appVersions.length).to.eq(1);
+ expect(response.body.app[0].definition.appV2.appVersions[0].name).to.eq("v2");
+ });
+ //export all versions
+ exportApp(workspaceId, appId, "?exportAllVersions=true").then((response) => {
+ expect(response.status).to.eq(201);
+ expect(response.body.app[0].definition.appV2.appVersions.length).to.eq(3);
+ });
+
+ //Invalid access token and workspace
+ /* exportApp(workspaceId, appId, "", {
+ Authorization: "",
+ "Content-Type": "application/json"
+ }).then((response) => {
+ expect(response.status).to.eq(403);
+ });
+
+ exportApp(workspaceId, appId, "", {
+ Authorization: "",
+ "Content-Type": "application/json"
+ }).then((response) => {
+ expect(response.status).to.eq(403);
+ });
+
+ exportApp(`${workspaceId}ee`, appId, "").then((response) => {
+ expect(response.status).to.eq(400);
+ });
+ */
+ //with and without TJDB -x.tooljet_database
+ exportApp(workspaceId, appId, "?exportTJDB=false").then((response) => {
+ expect(response.status).to.eq(201);
+ expect(response.body).not.to.have.property("tooljet_database");
+ });
+ exportApp(workspaceId, appId, "?exportTJDB=true").then((response) => {
+ expect(response.status).to.eq(201);
+ expect(response.body).to.have.property("tooljet_database");
+ });
+ });
+ //All Apps details
+ allAppsDetails(workspaceId).then((response) => {
+ expect(response.status).to.eq(200);
+ });
+ });
+});
\ No newline at end of file
diff --git a/cypress-tests/cypress/fixtures/templates/import_named_file.json b/cypress-tests/cypress/fixtures/templates/import_named_file.json
new file mode 100644
index 0000000000..0636a8b3b3
--- /dev/null
+++ b/cypress-tests/cypress/fixtures/templates/import_named_file.json
@@ -0,0 +1,1198 @@
+{
+ "app": [
+ {
+ "definition": {
+ "appV2": {
+ "type": "front-end",
+ "id": "8819afae-57b6-447d-93dd-6dc108169bfe",
+ "name": "AI powered code explainer",
+ "slug": "8819afae-57b6-447d-93dd-6dc108169bfe",
+ "isPublic": false,
+ "isMaintenanceOn": false,
+ "icon": "apps",
+ "organizationId": "a51da635-3a28-4b10-a6f4-7ba34e254987",
+ "currentVersionId": null,
+ "userId": "988bb9f5-e577-4065-8d3c-4fcf731ee15d",
+ "workflowApiToken": null,
+ "workflowEnabled": false,
+ "createdAt": "2025-02-27T07:28:52.129Z",
+ "creationMode": "DEFAULT",
+ "updatedAt": "2025-02-27T07:28:52.281Z",
+ "editingVersion": {
+ "id": "430dd7d7-1cd1-4c36-975f-229a1aa7dcb8",
+ "name": "v1",
+ "definition": null,
+ "globalSettings": {
+ "hideHeader": true,
+ "appInMaintenance": false,
+ "canvasMaxWidth": 100,
+ "canvasMaxWidthType": "%",
+ "canvasMaxHeight": 2400,
+ "canvasBackgroundColor": "#edeff5",
+ "backgroundFxQuery": "",
+ "appMode": "auto"
+ },
+ "pageSettings": {
+ "properties": {
+ "disableMenu": {
+ "value": "{{true}}",
+ "fxActive": false
+ }
+ }
+ },
+ "showViewerNavigation": false,
+ "homePageId": "93c0473f-6ada-4f1d-9c05-8a4775466aab",
+ "appId": "8819afae-57b6-447d-93dd-6dc108169bfe",
+ "currentEnvironmentId": "4efb81aa-756a-4a8f-a017-e167f0720b85",
+ "promotedFrom": null,
+ "createdAt": "2025-02-27T07:28:52.144Z",
+ "updatedAt": "2025-02-27T07:28:52.274Z"
+ },
+ "components": [
+ {
+ "id": "7bf37542-4eaa-42d8-9827-1cf1f1649791",
+ "name": "container1",
+ "type": "Container",
+ "pageId": "93c0473f-6ada-4f1d-9c05-8a4775466aab",
+ "parent": null,
+ "properties": {},
+ "general": {},
+ "styles": {
+ "backgroundColor": {
+ "value": "#ffffffff"
+ },
+ "borderRadius": {
+ "value": "10"
+ },
+ "borderColor": {
+ "value": "#ffffff00",
+ "fxActive": false
+ }
+ },
+ "generalStyles": {},
+ "displayPreferences": {
+ "showOnDesktop": {
+ "value": "{{true}}"
+ },
+ "showOnMobile": {
+ "value": "{{false}}"
+ }
+ },
+ "validation": {},
+ "createdAt": "2025-02-27T07:28:52.148Z",
+ "updatedAt": "2025-02-27T07:28:52.148Z",
+ "layouts": [
+ {
+ "id": "7367ab91-9541-4bd9-96f7-32da8bb61cf5",
+ "type": "desktop",
+ "top": 20,
+ "left": 1,
+ "width": 41,
+ "height": 70,
+ "componentId": "7bf37542-4eaa-42d8-9827-1cf1f1649791",
+ "dimensionUnit": "count",
+ "updatedAt": "2025-02-27T07:28:52.148Z"
+ }
+ ]
+ },
+ {
+ "id": "9b1d3bec-c586-4f2b-acdf-09cea7addecc",
+ "name": "text1",
+ "type": "Text",
+ "pageId": "93c0473f-6ada-4f1d-9c05-8a4775466aab",
+ "parent": "7bf37542-4eaa-42d8-9827-1cf1f1649791",
+ "properties": {
+ "text": {
+ "value": "B R A N D"
+ }
+ },
+ "general": {},
+ "styles": {
+ "textColor": {
+ "value": "#000",
+ "fxActive": false
+ },
+ "textSize": {
+ "value": "{{24}}"
+ },
+ "fontWeight": {
+ "value": "bold"
+ },
+ "boxShadow": {
+ "value": "0px 0px 0px 0px #00000040"
+ },
+ "isScrollRequired": {
+ "value": "disabled"
+ }
+ },
+ "generalStyles": {},
+ "displayPreferences": {
+ "showOnDesktop": {
+ "value": "{{true}}"
+ },
+ "showOnMobile": {
+ "value": "{{false}}"
+ }
+ },
+ "validation": {},
+ "createdAt": "2025-02-27T07:28:52.148Z",
+ "updatedAt": "2025-02-27T07:28:52.148Z",
+ "layouts": [
+ {
+ "id": "8c07e506-b1f5-4715-ab02-718fcce9295b",
+ "type": "desktop",
+ "top": 10,
+ "left": 1,
+ "width": 6,
+ "height": 40,
+ "componentId": "9b1d3bec-c586-4f2b-acdf-09cea7addecc",
+ "dimensionUnit": "count",
+ "updatedAt": "2025-02-27T07:28:52.148Z"
+ }
+ ]
+ },
+ {
+ "id": "38100944-4325-49b7-8c70-de75cf5ce63d",
+ "name": "text2",
+ "type": "Text",
+ "pageId": "93c0473f-6ada-4f1d-9c05-8a4775466aab",
+ "parent": "7bf37542-4eaa-42d8-9827-1cf1f1649791",
+ "properties": {
+ "text": {
+ "value": "
AI Code Explainer
"
+ }
+ },
+ "general": {},
+ "styles": {
+ "textColor": {
+ "value": "#000",
+ "fxActive": false
+ },
+ "textSize": {
+ "value": "{{20}}"
+ },
+ "textAlign": {
+ "value": "right"
+ },
+ "boxShadow": {
+ "value": "0px 0px 0px 0px #00000040"
+ },
+ "isScrollRequired": {
+ "value": "disabled"
+ }
+ },
+ "generalStyles": {},
+ "displayPreferences": {
+ "showOnDesktop": {
+ "value": "{{true}}"
+ },
+ "showOnMobile": {
+ "value": "{{false}}"
+ }
+ },
+ "validation": {},
+ "createdAt": "2025-02-27T07:28:52.148Z",
+ "updatedAt": "2025-02-27T07:28:52.148Z",
+ "layouts": [
+ {
+ "id": "129e63b6-9456-4cb7-94b0-7379743fec88",
+ "type": "desktop",
+ "top": 10,
+ "left": 25,
+ "width": 17,
+ "height": 40,
+ "componentId": "38100944-4325-49b7-8c70-de75cf5ce63d",
+ "dimensionUnit": "count",
+ "updatedAt": "2025-02-27T07:28:52.148Z"
+ }
+ ]
+ },
+ {
+ "id": "2727cf8a-1856-41cb-b716-c25afc2a15ad",
+ "name": "container2",
+ "type": "Container",
+ "pageId": "93c0473f-6ada-4f1d-9c05-8a4775466aab",
+ "parent": null,
+ "properties": {},
+ "general": {},
+ "styles": {
+ "borderRadius": {
+ "value": "10"
+ }
+ },
+ "generalStyles": {},
+ "displayPreferences": {
+ "showOnDesktop": {
+ "value": "{{true}}"
+ },
+ "showOnMobile": {
+ "value": "{{false}}"
+ }
+ },
+ "validation": {},
+ "createdAt": "2025-02-27T07:28:52.148Z",
+ "updatedAt": "2025-02-27T07:28:52.148Z",
+ "layouts": [
+ {
+ "id": "14b7706c-cebf-45dc-a555-3a60fdf01f3b",
+ "type": "desktop",
+ "top": 110,
+ "left": 1,
+ "width": 41,
+ "height": 620,
+ "componentId": "2727cf8a-1856-41cb-b716-c25afc2a15ad",
+ "dimensionUnit": "count",
+ "updatedAt": "2025-02-27T07:28:52.148Z"
+ },
+ {
+ "id": "ef46f35d-bf64-4ea0-8c9b-c525b87d6120",
+ "type": "mobile",
+ "top": 110,
+ "left": 1,
+ "width": 5,
+ "height": 200,
+ "componentId": "2727cf8a-1856-41cb-b716-c25afc2a15ad",
+ "dimensionUnit": "count",
+ "updatedAt": "2025-02-27T07:28:52.148Z"
+ }
+ ]
+ },
+ {
+ "id": "fbdab782-4a3b-4811-9f43-35f6dfae8735",
+ "name": "text3",
+ "type": "Text",
+ "pageId": "93c0473f-6ada-4f1d-9c05-8a4775466aab",
+ "parent": "2727cf8a-1856-41cb-b716-c25afc2a15ad",
+ "properties": {
+ "text": {
+ "value": "Code to be explained"
+ }
+ },
+ "general": {},
+ "styles": {
+ "textSize": {
+ "value": "24"
+ },
+ "fontWeight": {
+ "value": "bold"
+ },
+ "isScrollRequired": {
+ "value": "disabled"
+ }
+ },
+ "generalStyles": {},
+ "displayPreferences": {
+ "showOnDesktop": {
+ "value": "{{true}}"
+ },
+ "showOnMobile": {
+ "value": "{{false}}"
+ }
+ },
+ "validation": {},
+ "createdAt": "2025-02-27T07:28:52.148Z",
+ "updatedAt": "2025-02-27T07:28:52.148Z",
+ "layouts": [
+ {
+ "id": "cfc25680-87fe-45d1-8431-f009ba351ae2",
+ "type": "desktop",
+ "top": 20,
+ "left": 1,
+ "width": 20,
+ "height": 40,
+ "componentId": "fbdab782-4a3b-4811-9f43-35f6dfae8735",
+ "dimensionUnit": "count",
+ "updatedAt": "2025-02-27T07:28:52.148Z"
+ },
+ {
+ "id": "bbb13f33-25ee-4c97-8c08-7d7df99ab431",
+ "type": "mobile",
+ "top": 20,
+ "left": 9,
+ "width": 13.953488372093023,
+ "height": 40,
+ "componentId": "fbdab782-4a3b-4811-9f43-35f6dfae8735",
+ "dimensionUnit": "count",
+ "updatedAt": "2025-02-27T07:28:52.148Z"
+ }
+ ]
+ },
+ {
+ "id": "dca350e6-c9f8-44aa-94d5-e6245cfb0ae2",
+ "name": "dropdown1",
+ "type": "DropDown",
+ "pageId": "93c0473f-6ada-4f1d-9c05-8a4775466aab",
+ "parent": "2727cf8a-1856-41cb-b716-c25afc2a15ad",
+ "properties": {
+ "label": {
+ "value": ""
+ },
+ "value": {
+ "value": ""
+ },
+ "values": {
+ "value": "{{queries.32ff6874-7da0-4b88-ae05-3c9cda4a07dc.data.models.map(item => item.name)}}"
+ },
+ "display_values": {
+ "value": "{{queries.32ff6874-7da0-4b88-ae05-3c9cda4a07dc.data.models.map(item => item.displayName)}}"
+ },
+ "loadingState": {
+ "value": "{{queries.32ff6874-7da0-4b88-ae05-3c9cda4a07dc.isLoading}}",
+ "fxActive": true
+ },
+ "placeholder": {
+ "value": "Select a model"
+ }
+ },
+ "general": {},
+ "styles": {
+ "borderRadius": {
+ "value": "5"
+ }
+ },
+ "generalStyles": {},
+ "displayPreferences": {
+ "showOnDesktop": {
+ "value": "{{true}}"
+ },
+ "showOnMobile": {
+ "value": "{{false}}"
+ }
+ },
+ "validation": {},
+ "createdAt": "2025-02-27T07:28:52.148Z",
+ "updatedAt": "2025-02-27T07:28:52.267Z",
+ "layouts": [
+ {
+ "id": "91cae02e-6d00-48ad-9750-1ae74bc9fd7f",
+ "type": "mobile",
+ "top": 10,
+ "left": 27,
+ "width": 18.6046511627907,
+ "height": 30,
+ "componentId": "dca350e6-c9f8-44aa-94d5-e6245cfb0ae2",
+ "dimensionUnit": "count",
+ "updatedAt": "2025-02-27T07:28:52.148Z"
+ },
+ {
+ "id": "bb56cbd1-57f7-4917-8a32-046a8e77ed33",
+ "type": "desktop",
+ "top": 480,
+ "left": 1,
+ "width": 20,
+ "height": 40,
+ "componentId": "dca350e6-c9f8-44aa-94d5-e6245cfb0ae2",
+ "dimensionUnit": "count",
+ "updatedAt": "2025-02-27T07:28:52.148Z"
+ }
+ ]
+ },
+ {
+ "id": "98a7f66e-d446-4be5-b2e8-6bde808e9461",
+ "name": "textarea1",
+ "type": "TextArea",
+ "pageId": "93c0473f-6ada-4f1d-9c05-8a4775466aab",
+ "parent": "2727cf8a-1856-41cb-b716-c25afc2a15ad",
+ "properties": {
+ "value": {
+ "value": "function addNumbers(a, b) {\n return a + b;\n}\n\nconst sum = addNumbers(5, 3);\nconsole.log(sum);"
+ },
+ "placeholder": {
+ "value": "function addNumbers(a, b) {\n return a + b;\n}\n\nconst sum = addNumbers(5, 3);\nconsole.log(sum);"
+ }
+ },
+ "general": {},
+ "styles": {
+ "borderRadius": {
+ "value": "{{5}}"
+ }
+ },
+ "generalStyles": {},
+ "displayPreferences": {
+ "showOnDesktop": {
+ "value": "{{true}}"
+ },
+ "showOnMobile": {
+ "value": "{{false}}"
+ }
+ },
+ "validation": {},
+ "createdAt": "2025-02-27T07:28:52.148Z",
+ "updatedAt": "2025-02-27T07:28:52.148Z",
+ "layouts": [
+ {
+ "id": "db411aca-2e7e-46ae-8bf6-75f664a636ea",
+ "type": "mobile",
+ "top": 100,
+ "left": 3,
+ "width": 13.953488372093023,
+ "height": 100,
+ "componentId": "98a7f66e-d446-4be5-b2e8-6bde808e9461",
+ "dimensionUnit": "count",
+ "updatedAt": "2025-02-27T07:28:52.148Z"
+ },
+ {
+ "id": "abdc0362-e37b-48d6-9cad-ccbdfcf6fd55",
+ "type": "desktop",
+ "top": 70,
+ "left": 1,
+ "width": 20,
+ "height": 270,
+ "componentId": "98a7f66e-d446-4be5-b2e8-6bde808e9461",
+ "dimensionUnit": "count",
+ "updatedAt": "2025-02-27T07:28:52.148Z"
+ }
+ ]
+ },
+ {
+ "id": "37fbb9ed-5ac6-439b-82cb-35e276c89f49",
+ "name": "button1",
+ "type": "Button",
+ "pageId": "93c0473f-6ada-4f1d-9c05-8a4775466aab",
+ "parent": "2727cf8a-1856-41cb-b716-c25afc2a15ad",
+ "properties": {
+ "text": {
+ "value": "Generate explanation >>"
+ },
+ "loadingState": {
+ "value": "{{false}}",
+ "fxActive": false
+ },
+ "disabledState": {
+ "value": "{{components.dca350e6-c9f8-44aa-94d5-e6245cfb0ae2.value == undefined || queries.getCodeExplanation.isLoading}}",
+ "fxActive": true
+ }
+ },
+ "general": {},
+ "styles": {
+ "backgroundColor": {
+ "value": "#ffffff00"
+ },
+ "textColor": {
+ "value": "#3e63ddff"
+ },
+ "loaderColor": {
+ "value": "#3e63ddff"
+ },
+ "borderRadius": {
+ "value": "{{5}}"
+ },
+ "borderColor": {
+ "value": "#3e63ddff"
+ }
+ },
+ "generalStyles": {},
+ "displayPreferences": {
+ "showOnDesktop": {
+ "value": "{{true}}"
+ },
+ "showOnMobile": {
+ "value": "{{false}}"
+ }
+ },
+ "validation": {},
+ "createdAt": "2025-02-27T07:28:52.148Z",
+ "updatedAt": "2025-02-27T07:28:52.267Z",
+ "layouts": [
+ {
+ "id": "c110426c-5994-4d04-901d-883aafb9d2eb",
+ "type": "mobile",
+ "top": 420,
+ "left": 7,
+ "width": 6.976744186046512,
+ "height": 30,
+ "componentId": "37fbb9ed-5ac6-439b-82cb-35e276c89f49",
+ "dimensionUnit": "count",
+ "updatedAt": "2025-02-27T07:28:52.148Z"
+ },
+ {
+ "id": "a6a6b92e-0984-4e21-87fc-462a307e06dd",
+ "type": "desktop",
+ "top": 550,
+ "left": 1,
+ "width": 20,
+ "height": 40,
+ "componentId": "37fbb9ed-5ac6-439b-82cb-35e276c89f49",
+ "dimensionUnit": "count",
+ "updatedAt": "2025-02-27T07:28:52.148Z"
+ }
+ ]
+ },
+ {
+ "id": "b56cb989-9b4f-4dcf-a6c4-70dcfe6aac1a",
+ "name": "dropdown2",
+ "type": "DropDown",
+ "pageId": "93c0473f-6ada-4f1d-9c05-8a4775466aab",
+ "parent": "2727cf8a-1856-41cb-b716-c25afc2a15ad",
+ "properties": {
+ "values": {
+ "value": "{{[\n \"\",\n \"C#\",\n \"C++\",\n \"Dart\",\n \"Elixir\",\n \"Erlang\",\n \"F#\",\n \"Go\",\n \"Groovy\",\n \"Haskell\",\n \"Java\",\n \"JavaScript\",\n \"Kotlin\",\n \"Lua\",\n \"MATLAB\",\n \"Objective-C\",\n \"Perl\",\n \"PHP\",\n \"Python\",\n \"R\",\n \"Ruby\",\n \"Rust\",\n \"Scala\",\n \"Shell\",\n \"SQL\",\n \"Swift\",\n \"TypeScript\"\n]}}"
+ },
+ "display_values": {
+ "value": "{{[\n \"Any language\",\n \"C#\",\n \"C++\",\n \"Dart\",\n \"Elixir\",\n \"Erlang\",\n \"F#\",\n \"Go\",\n \"Groovy\",\n \"Haskell\",\n \"Java\",\n \"JavaScript\",\n \"Kotlin\",\n \"Lua\",\n \"MATLAB\",\n \"Objective-C\",\n \"Perl\",\n \"PHP\",\n \"Python\",\n \"R\",\n \"Ruby\",\n \"Rust\",\n \"Scala\",\n \"Shell\",\n \"SQL\",\n \"Swift\",\n \"TypeScript\"\n]}}"
+ },
+ "value": {
+ "value": ""
+ },
+ "placeholder": {
+ "value": "Select a language"
+ },
+ "label": {
+ "value": ""
+ }
+ },
+ "general": {},
+ "styles": {},
+ "generalStyles": {},
+ "displayPreferences": {
+ "showOnDesktop": {
+ "value": "{{true}}"
+ },
+ "showOnMobile": {
+ "value": "{{false}}"
+ }
+ },
+ "validation": {},
+ "createdAt": "2025-02-27T07:28:52.148Z",
+ "updatedAt": "2025-02-27T07:28:52.148Z",
+ "layouts": [
+ {
+ "id": "553e50a3-c9d4-4ae7-9b8d-da129cb2f32d",
+ "type": "mobile",
+ "top": 420,
+ "left": 2,
+ "width": 8,
+ "height": 30,
+ "componentId": "b56cb989-9b4f-4dcf-a6c4-70dcfe6aac1a",
+ "dimensionUnit": "count",
+ "updatedAt": "2025-02-27T07:28:52.148Z"
+ },
+ {
+ "id": "abeda4d6-0111-4b9a-bfb1-234c986ee777",
+ "type": "desktop",
+ "top": 390,
+ "left": 1,
+ "width": 20,
+ "height": 40,
+ "componentId": "b56cb989-9b4f-4dcf-a6c4-70dcfe6aac1a",
+ "dimensionUnit": "count",
+ "updatedAt": "2025-02-27T07:28:52.148Z"
+ }
+ ]
+ },
+ {
+ "id": "7112d3b6-f7d5-4da8-84ad-f2db9ab962d8",
+ "name": "text6",
+ "type": "Text",
+ "pageId": "93c0473f-6ada-4f1d-9c05-8a4775466aab",
+ "parent": "2727cf8a-1856-41cb-b716-c25afc2a15ad",
+ "properties": {
+ "text": {
+ "value": "Language"
+ }
+ },
+ "general": {},
+ "styles": {
+ "fontWeight": {
+ "value": "bold"
+ }
+ },
+ "generalStyles": {},
+ "displayPreferences": {
+ "showOnDesktop": {
+ "value": "{{true}}"
+ },
+ "showOnMobile": {
+ "value": "{{false}}"
+ }
+ },
+ "validation": {},
+ "createdAt": "2025-02-27T07:28:52.148Z",
+ "updatedAt": "2025-02-27T07:28:52.148Z",
+ "layouts": [
+ {
+ "id": "3b6ce6c5-bb8b-4145-991b-b4dc659ac9ae",
+ "type": "desktop",
+ "top": 360,
+ "left": 1,
+ "width": 14,
+ "height": 30,
+ "componentId": "7112d3b6-f7d5-4da8-84ad-f2db9ab962d8",
+ "dimensionUnit": "count",
+ "updatedAt": "2025-02-27T07:28:52.148Z"
+ },
+ {
+ "id": "d907a75f-162c-4e89-8bef-8ad4a6b10f6a",
+ "type": "mobile",
+ "top": 70,
+ "left": 4,
+ "width": 13.953488372093023,
+ "height": 40,
+ "componentId": "7112d3b6-f7d5-4da8-84ad-f2db9ab962d8",
+ "dimensionUnit": "count",
+ "updatedAt": "2025-02-27T07:28:52.148Z"
+ }
+ ]
+ },
+ {
+ "id": "052d73d1-c415-4720-8963-36c94ce54b19",
+ "name": "text7",
+ "type": "Text",
+ "pageId": "93c0473f-6ada-4f1d-9c05-8a4775466aab",
+ "parent": "2727cf8a-1856-41cb-b716-c25afc2a15ad",
+ "properties": {
+ "text": {
+ "value": "{{`${queries.getCodeExplanation.data.candidates ? queries.getCodeExplanation.data.candidates[0].content.parts[0].text : \"
- Language: JavaScript
function addNumbers(a, b) {: Defines a function named addNumbers that takes two parameters a and b. return a + b;: The function returns the sum of a and b. }: Ends the function definition. const sum = addNumbers(5, 3);: Calls the addNumbers function with arguments 5 and 3, and assigns the result to the constant sum. console.log(sum);: Outputs the value of sum to the console, which is 8.
\"}
`}}"
+ },
+ "textFormat": {
+ "value": "html"
+ },
+ "loadingState": {
+ "fxActive": true,
+ "value": "{{queries.5774aa01-0931-4036-8bfa-4d12e0b6bc8b.isLoading}}"
+ }
+ },
+ "general": {},
+ "styles": {
+ "borderColor": {
+ "value": "#ddddddff"
+ },
+ "borderRadius": {
+ "value": "5"
+ },
+ "verticalAlignment": {
+ "value": "top"
+ }
+ },
+ "generalStyles": {},
+ "displayPreferences": {
+ "showOnDesktop": {
+ "value": "{{true}}"
+ },
+ "showOnMobile": {
+ "value": "{{false}}"
+ }
+ },
+ "validation": {},
+ "createdAt": "2025-02-27T07:28:52.148Z",
+ "updatedAt": "2025-02-27T07:28:52.267Z",
+ "layouts": [
+ {
+ "id": "388a36e0-95ac-49f3-a97b-ad413efafb3a",
+ "type": "desktop",
+ "top": 70,
+ "left": 22,
+ "width": 20,
+ "height": 520,
+ "componentId": "052d73d1-c415-4720-8963-36c94ce54b19",
+ "dimensionUnit": "count",
+ "updatedAt": "2025-02-27T07:28:52.148Z"
+ },
+ {
+ "id": "1f2da6ab-3493-4ace-b5ae-ceadbd3e2fb0",
+ "type": "mobile",
+ "top": 290,
+ "left": 23,
+ "width": 6,
+ "height": 40,
+ "componentId": "052d73d1-c415-4720-8963-36c94ce54b19",
+ "dimensionUnit": "count",
+ "updatedAt": "2025-02-27T07:28:52.148Z"
+ }
+ ]
+ },
+ {
+ "id": "3c5278e8-8cc5-442a-bc70-19d4cd72cec7",
+ "name": "text8",
+ "type": "Text",
+ "pageId": "93c0473f-6ada-4f1d-9c05-8a4775466aab",
+ "parent": "2727cf8a-1856-41cb-b716-c25afc2a15ad",
+ "properties": {
+ "text": {
+ "value": "Gemini Model"
+ }
+ },
+ "general": {},
+ "styles": {
+ "fontWeight": {
+ "value": "bold"
+ }
+ },
+ "generalStyles": {},
+ "displayPreferences": {
+ "showOnDesktop": {
+ "value": "{{true}}"
+ },
+ "showOnMobile": {
+ "value": "{{false}}"
+ }
+ },
+ "validation": {},
+ "createdAt": "2025-02-27T07:28:52.148Z",
+ "updatedAt": "2025-02-27T07:28:52.148Z",
+ "layouts": [
+ {
+ "id": "e41fd57d-29e6-49e2-b3ee-75b3769f6d27",
+ "type": "mobile",
+ "top": 70,
+ "left": 4,
+ "width": 13.953488372093023,
+ "height": 40,
+ "componentId": "3c5278e8-8cc5-442a-bc70-19d4cd72cec7",
+ "dimensionUnit": "count",
+ "updatedAt": "2025-02-27T07:28:52.148Z"
+ },
+ {
+ "id": "7a1d68a9-e9f5-496e-9947-3d6e12c55b0c",
+ "type": "desktop",
+ "top": 450,
+ "left": 1,
+ "width": 14,
+ "height": 30,
+ "componentId": "3c5278e8-8cc5-442a-bc70-19d4cd72cec7",
+ "dimensionUnit": "count",
+ "updatedAt": "2025-02-27T07:28:52.148Z"
+ }
+ ]
+ },
+ {
+ "id": "521f0268-02d8-4571-9efe-030c9816bdea",
+ "name": "text9",
+ "type": "Text",
+ "pageId": "93c0473f-6ada-4f1d-9c05-8a4775466aab",
+ "parent": "2727cf8a-1856-41cb-b716-c25afc2a15ad",
+ "properties": {
+ "text": {
+ "value": "Explanation"
+ }
+ },
+ "general": {},
+ "styles": {
+ "textSize": {
+ "value": "24"
+ },
+ "fontWeight": {
+ "value": "bold"
+ },
+ "isScrollRequired": {
+ "value": "disabled"
+ }
+ },
+ "generalStyles": {},
+ "displayPreferences": {
+ "showOnDesktop": {
+ "value": "{{true}}"
+ },
+ "showOnMobile": {
+ "value": "{{false}}"
+ }
+ },
+ "validation": {},
+ "createdAt": "2025-02-27T07:28:52.148Z",
+ "updatedAt": "2025-02-27T07:28:52.148Z",
+ "layouts": [
+ {
+ "id": "81f9d6a1-90c4-422c-8602-1675a76f6de4",
+ "type": "desktop",
+ "top": 20,
+ "left": 22,
+ "width": 20,
+ "height": 40,
+ "componentId": "521f0268-02d8-4571-9efe-030c9816bdea",
+ "dimensionUnit": "count",
+ "updatedAt": "2025-02-27T07:28:52.148Z"
+ },
+ {
+ "id": "da2abfa1-769b-4784-87fb-5020e6610fed",
+ "type": "mobile",
+ "top": 20,
+ "left": 9,
+ "width": 13.953488372093023,
+ "height": 40,
+ "componentId": "521f0268-02d8-4571-9efe-030c9816bdea",
+ "dimensionUnit": "count",
+ "updatedAt": "2025-02-27T07:28:52.148Z"
+ }
+ ]
+ }
+ ],
+ "pages": [
+ {
+ "id": "93c0473f-6ada-4f1d-9c05-8a4775466aab",
+ "name": "Home",
+ "handle": "home",
+ "index": 1,
+ "disabled": false,
+ "hidden": false,
+ "icon": null,
+ "createdAt": "2025-02-27T07:28:52.148Z",
+ "updatedAt": "2025-02-27T07:28:52.366Z",
+ "autoComputeLayout": true,
+ "appVersionId": "430dd7d7-1cd1-4c36-975f-229a1aa7dcb8",
+ "pageGroupIndex": 1,
+ "pageGroupId": null,
+ "isPageGroup": false
+ }
+ ],
+ "events": [
+ {
+ "id": "9417716e-b415-4532-aea4-8a2afa224f10",
+ "name": "onClick",
+ "index": 0,
+ "event": {
+ "eventId": "onClick",
+ "message": "Hello world!",
+ "queryId": "5774aa01-0931-4036-8bfa-4d12e0b6bc8b",
+ "actionId": "run-query",
+ "alertType": "info",
+ "queryName": "getCodeExplanation",
+ "parameters": {}
+ },
+ "sourceId": "37fbb9ed-5ac6-439b-82cb-35e276c89f49",
+ "target": "component",
+ "appVersionId": "430dd7d7-1cd1-4c36-975f-229a1aa7dcb8",
+ "createdAt": "2025-02-27T07:28:52.148Z",
+ "updatedAt": "2025-02-27T07:28:52.260Z"
+ }
+ ],
+ "dataQueries": [
+ {
+ "id": "5774aa01-0931-4036-8bfa-4d12e0b6bc8b",
+ "name": "getCodeExplanation",
+ "options": {
+ "method": "post",
+ "url": "https://generativelanguage.googleapis.com/v1beta/{{components.dropdown1.value}}:generateContent",
+ "url_params": [
+ [
+ "key",
+ "{{constants.GEMINI_API_KEY}}"
+ ],
+ [
+ "",
+ ""
+ ]
+ ],
+ "headers": [
+ [
+ "Content-Type",
+ "application/json"
+ ],
+ [
+ "",
+ ""
+ ]
+ ],
+ "body": [
+ [
+ "",
+ ""
+ ]
+ ],
+ "json_body": "{\n \"contents\": [\n {\n \"parts\": [\n {\n \"text\": \"{{components.textarea1.value.replaceAll('\\n','\\\\n')}} - Generate a point-wise line by line explanation of this code in html formatting only. Keep only the explanation, and nothing else. {{components.dropdown2.value ? `The code is in ${components.dropdown2.value} language.` : 'Also identify the language of the code.'}}\"\n }\n ]\n }\n ]\n}",
+ "body_toggle": true,
+ "transformationLanguage": "javascript",
+ "enableTransformation": false,
+ "arrayValuesChanged": false,
+ "transformation": "// write your code here\n// return value will be set as data and the original data will be available as rawData\nreturn data.filter(row => row.amount > 1000);\n "
+ },
+ "dataSourceId": "489072da-3239-4bd5-91b9-dee5f5da5335",
+ "appVersionId": "430dd7d7-1cd1-4c36-975f-229a1aa7dcb8",
+ "createdAt": "2025-02-27T07:28:52.148Z",
+ "updatedAt": "2025-02-27T07:28:52.148Z"
+ },
+ {
+ "id": "32ff6874-7da0-4b88-ae05-3c9cda4a07dc",
+ "name": "getGeminiModels",
+ "options": {
+ "method": "get",
+ "url": "https://generativelanguage.googleapis.com/v1beta/models?key={{constants.GEMINI_API_KEY}}",
+ "url_params": [
+ [
+ "",
+ ""
+ ]
+ ],
+ "headers": [
+ [
+ "",
+ ""
+ ]
+ ],
+ "body": [
+ [
+ "",
+ ""
+ ]
+ ],
+ "json_body": null,
+ "body_toggle": false,
+ "transformationLanguage": "javascript",
+ "enableTransformation": false,
+ "runOnPageLoad": true
+ },
+ "dataSourceId": "489072da-3239-4bd5-91b9-dee5f5da5335",
+ "appVersionId": "430dd7d7-1cd1-4c36-975f-229a1aa7dcb8",
+ "createdAt": "2025-02-27T07:28:52.148Z",
+ "updatedAt": "2025-02-27T07:28:52.983Z"
+ }
+ ],
+ "dataSources": [
+ {
+ "id": "489072da-3239-4bd5-91b9-dee5f5da5335",
+ "name": "restapidefault",
+ "kind": "restapi",
+ "type": "static",
+ "pluginId": null,
+ "appVersionId": "430dd7d7-1cd1-4c36-975f-229a1aa7dcb8",
+ "organizationId": null,
+ "scope": "local",
+ "createdAt": "2025-02-27T07:28:52.153Z",
+ "updatedAt": "2025-02-27T07:28:52.153Z"
+ },
+ {
+ "id": "c462a40f-c7fa-4d55-98fe-9bc445271cab",
+ "name": "runjsdefault",
+ "kind": "runjs",
+ "type": "static",
+ "pluginId": null,
+ "appVersionId": "430dd7d7-1cd1-4c36-975f-229a1aa7dcb8",
+ "organizationId": null,
+ "scope": "local",
+ "createdAt": "2025-02-27T07:28:52.163Z",
+ "updatedAt": "2025-02-27T07:28:52.163Z"
+ },
+ {
+ "id": "cc0b5feb-29ea-47c0-9a9a-62c0e0b89ccb",
+ "name": "runpydefault",
+ "kind": "runpy",
+ "type": "static",
+ "pluginId": null,
+ "appVersionId": "430dd7d7-1cd1-4c36-975f-229a1aa7dcb8",
+ "organizationId": null,
+ "scope": "local",
+ "createdAt": "2025-02-27T07:28:52.170Z",
+ "updatedAt": "2025-02-27T07:28:52.170Z"
+ },
+ {
+ "id": "907dde15-1ac2-4f53-ba72-8e4e1d066f0e",
+ "name": "tooljetdbdefault",
+ "kind": "tooljetdb",
+ "type": "static",
+ "pluginId": null,
+ "appVersionId": "430dd7d7-1cd1-4c36-975f-229a1aa7dcb8",
+ "organizationId": null,
+ "scope": "local",
+ "createdAt": "2025-02-27T07:28:52.176Z",
+ "updatedAt": "2025-02-27T07:28:52.176Z"
+ },
+ {
+ "id": "66ad4e35-f981-47a6-99cd-31e9e7bbd9b3",
+ "name": "workflowsdefault",
+ "kind": "workflows",
+ "type": "static",
+ "pluginId": null,
+ "appVersionId": "430dd7d7-1cd1-4c36-975f-229a1aa7dcb8",
+ "organizationId": null,
+ "scope": "local",
+ "createdAt": "2025-02-27T07:28:52.183Z",
+ "updatedAt": "2025-02-27T07:28:52.183Z"
+ }
+ ],
+ "appVersions": [
+ {
+ "id": "430dd7d7-1cd1-4c36-975f-229a1aa7dcb8",
+ "name": "v1",
+ "definition": null,
+ "globalSettings": {
+ "hideHeader": true,
+ "appInMaintenance": false,
+ "canvasMaxWidth": 100,
+ "canvasMaxWidthType": "%",
+ "canvasMaxHeight": 2400,
+ "canvasBackgroundColor": "#edeff5",
+ "backgroundFxQuery": "",
+ "appMode": "auto"
+ },
+ "pageSettings": {
+ "properties": {
+ "disableMenu": {
+ "value": "{{true}}",
+ "fxActive": false
+ }
+ }
+ },
+ "showViewerNavigation": false,
+ "homePageId": "93c0473f-6ada-4f1d-9c05-8a4775466aab",
+ "appId": "8819afae-57b6-447d-93dd-6dc108169bfe",
+ "currentEnvironmentId": "4efb81aa-756a-4a8f-a017-e167f0720b85",
+ "promotedFrom": null,
+ "createdAt": "2025-02-27T07:28:52.144Z",
+ "updatedAt": "2025-02-27T07:28:52.274Z"
+ }
+ ],
+ "appEnvironments": [
+ {
+ "id": "4efb81aa-756a-4a8f-a017-e167f0720b85",
+ "organizationId": "a51da635-3a28-4b10-a6f4-7ba34e254987",
+ "name": "development",
+ "isDefault": false,
+ "priority": 1,
+ "enabled": true,
+ "createdAt": "2025-02-27T07:28:36.425Z",
+ "updatedAt": "2025-02-27T07:28:36.425Z"
+ },
+ {
+ "id": "ed48a4ab-ef5c-47c0-b99c-453fec90b9ec",
+ "organizationId": "a51da635-3a28-4b10-a6f4-7ba34e254987",
+ "name": "staging",
+ "isDefault": false,
+ "priority": 2,
+ "enabled": true,
+ "createdAt": "2025-02-27T07:28:36.425Z",
+ "updatedAt": "2025-02-27T07:28:36.425Z"
+ },
+ {
+ "id": "eb006618-493c-48ac-8a4d-e80d208d29de",
+ "organizationId": "a51da635-3a28-4b10-a6f4-7ba34e254987",
+ "name": "production",
+ "isDefault": true,
+ "priority": 3,
+ "enabled": true,
+ "createdAt": "2025-02-27T07:28:36.425Z",
+ "updatedAt": "2025-02-27T07:28:36.425Z"
+ }
+ ],
+ "dataSourceOptions": [
+ {
+ "id": "98e3239b-e54b-4b59-992b-d9bbfb68d1e6",
+ "dataSourceId": "489072da-3239-4bd5-91b9-dee5f5da5335",
+ "environmentId": "4efb81aa-756a-4a8f-a017-e167f0720b85",
+ "options": null,
+ "createdAt": "2025-02-27T07:28:52.159Z",
+ "updatedAt": "2025-02-27T07:28:52.159Z"
+ },
+ {
+ "id": "c997ee43-2f17-46aa-bc35-32af668d546b",
+ "dataSourceId": "489072da-3239-4bd5-91b9-dee5f5da5335",
+ "environmentId": "ed48a4ab-ef5c-47c0-b99c-453fec90b9ec",
+ "options": null,
+ "createdAt": "2025-02-27T07:28:52.159Z",
+ "updatedAt": "2025-02-27T07:28:52.159Z"
+ },
+ {
+ "id": "01bbd244-59c9-4965-8024-401c8f1961fd",
+ "dataSourceId": "489072da-3239-4bd5-91b9-dee5f5da5335",
+ "environmentId": "eb006618-493c-48ac-8a4d-e80d208d29de",
+ "options": null,
+ "createdAt": "2025-02-27T07:28:52.159Z",
+ "updatedAt": "2025-02-27T07:28:52.159Z"
+ },
+ {
+ "id": "8a8096f7-6b6f-49ca-95de-596c5670c832",
+ "dataSourceId": "c462a40f-c7fa-4d55-98fe-9bc445271cab",
+ "environmentId": "4efb81aa-756a-4a8f-a017-e167f0720b85",
+ "options": null,
+ "createdAt": "2025-02-27T07:28:52.167Z",
+ "updatedAt": "2025-02-27T07:28:52.167Z"
+ },
+ {
+ "id": "1e2dcc6d-8944-4b5b-abd4-72f7201bf657",
+ "dataSourceId": "c462a40f-c7fa-4d55-98fe-9bc445271cab",
+ "environmentId": "ed48a4ab-ef5c-47c0-b99c-453fec90b9ec",
+ "options": null,
+ "createdAt": "2025-02-27T07:28:52.167Z",
+ "updatedAt": "2025-02-27T07:28:52.167Z"
+ },
+ {
+ "id": "24bfe83d-b2d3-4bf0-8730-1bd14d96cf7a",
+ "dataSourceId": "c462a40f-c7fa-4d55-98fe-9bc445271cab",
+ "environmentId": "eb006618-493c-48ac-8a4d-e80d208d29de",
+ "options": null,
+ "createdAt": "2025-02-27T07:28:52.167Z",
+ "updatedAt": "2025-02-27T07:28:52.167Z"
+ },
+ {
+ "id": "44600a77-04bf-4b30-8613-bd7a7bff6508",
+ "dataSourceId": "cc0b5feb-29ea-47c0-9a9a-62c0e0b89ccb",
+ "environmentId": "4efb81aa-756a-4a8f-a017-e167f0720b85",
+ "options": null,
+ "createdAt": "2025-02-27T07:28:52.174Z",
+ "updatedAt": "2025-02-27T07:28:52.174Z"
+ },
+ {
+ "id": "b70c436e-70e5-48d3-84d2-ca2c784c7425",
+ "dataSourceId": "cc0b5feb-29ea-47c0-9a9a-62c0e0b89ccb",
+ "environmentId": "ed48a4ab-ef5c-47c0-b99c-453fec90b9ec",
+ "options": null,
+ "createdAt": "2025-02-27T07:28:52.174Z",
+ "updatedAt": "2025-02-27T07:28:52.174Z"
+ },
+ {
+ "id": "7bd1351e-61b9-4ba6-9e57-8eca1a3a0df3",
+ "dataSourceId": "cc0b5feb-29ea-47c0-9a9a-62c0e0b89ccb",
+ "environmentId": "eb006618-493c-48ac-8a4d-e80d208d29de",
+ "options": null,
+ "createdAt": "2025-02-27T07:28:52.174Z",
+ "updatedAt": "2025-02-27T07:28:52.174Z"
+ },
+ {
+ "id": "f8268c18-8453-48ac-acf7-46c2d0c75c75",
+ "dataSourceId": "907dde15-1ac2-4f53-ba72-8e4e1d066f0e",
+ "environmentId": "4efb81aa-756a-4a8f-a017-e167f0720b85",
+ "options": null,
+ "createdAt": "2025-02-27T07:28:52.181Z",
+ "updatedAt": "2025-02-27T07:28:52.181Z"
+ },
+ {
+ "id": "cd59c697-6ac2-4594-b8f6-493676e8b3c7",
+ "dataSourceId": "907dde15-1ac2-4f53-ba72-8e4e1d066f0e",
+ "environmentId": "ed48a4ab-ef5c-47c0-b99c-453fec90b9ec",
+ "options": null,
+ "createdAt": "2025-02-27T07:28:52.181Z",
+ "updatedAt": "2025-02-27T07:28:52.181Z"
+ },
+ {
+ "id": "7270ef0a-f6d6-498e-9959-4b646a30d5d1",
+ "dataSourceId": "907dde15-1ac2-4f53-ba72-8e4e1d066f0e",
+ "environmentId": "eb006618-493c-48ac-8a4d-e80d208d29de",
+ "options": null,
+ "createdAt": "2025-02-27T07:28:52.181Z",
+ "updatedAt": "2025-02-27T07:28:52.181Z"
+ },
+ {
+ "id": "fe4824d5-57fa-42dc-9812-4af634737898",
+ "dataSourceId": "66ad4e35-f981-47a6-99cd-31e9e7bbd9b3",
+ "environmentId": "4efb81aa-756a-4a8f-a017-e167f0720b85",
+ "options": null,
+ "createdAt": "2025-02-27T07:28:52.189Z",
+ "updatedAt": "2025-02-27T07:28:52.189Z"
+ },
+ {
+ "id": "521a6d91-484b-45bc-af8f-aaceb0dc515c",
+ "dataSourceId": "66ad4e35-f981-47a6-99cd-31e9e7bbd9b3",
+ "environmentId": "ed48a4ab-ef5c-47c0-b99c-453fec90b9ec",
+ "options": null,
+ "createdAt": "2025-02-27T07:28:52.189Z",
+ "updatedAt": "2025-02-27T07:28:52.189Z"
+ },
+ {
+ "id": "f5955bf2-c148-4544-acd9-a9a92a943e5b",
+ "dataSourceId": "66ad4e35-f981-47a6-99cd-31e9e7bbd9b3",
+ "environmentId": "eb006618-493c-48ac-8a4d-e80d208d29de",
+ "options": null,
+ "createdAt": "2025-02-27T07:28:52.189Z",
+ "updatedAt": "2025-02-27T07:28:52.189Z"
+ }
+ ],
+ "schemaDetails": {
+ "multiPages": true,
+ "multiEnv": true,
+ "globalDataSources": true
+ }
+ }
+ }
+ }
+ ],
+ "tooljet_version": "3.5.3-ee-lts",
+ "appName": "app_json"
+}
\ No newline at end of file
diff --git a/cypress-tests/cypress/fixtures/templates/import_unnamed_file.json b/cypress-tests/cypress/fixtures/templates/import_unnamed_file.json
new file mode 100644
index 0000000000..93c2501a51
--- /dev/null
+++ b/cypress-tests/cypress/fixtures/templates/import_unnamed_file.json
@@ -0,0 +1,1197 @@
+{
+ "app": [
+ {
+ "definition": {
+ "appV2": {
+ "type": "front-end",
+ "id": "8819afae-57b6-447d-93dd-6dc108169bfe",
+ "name": "AI powered code explainer",
+ "slug": "8819afae-57b6-447d-93dd-6dc108169bfe",
+ "isPublic": false,
+ "isMaintenanceOn": false,
+ "icon": "apps",
+ "organizationId": "a51da635-3a28-4b10-a6f4-7ba34e254987",
+ "currentVersionId": null,
+ "userId": "988bb9f5-e577-4065-8d3c-4fcf731ee15d",
+ "workflowApiToken": null,
+ "workflowEnabled": false,
+ "createdAt": "2025-02-27T07:28:52.129Z",
+ "creationMode": "DEFAULT",
+ "updatedAt": "2025-02-27T07:28:52.281Z",
+ "editingVersion": {
+ "id": "430dd7d7-1cd1-4c36-975f-229a1aa7dcb8",
+ "name": "v1",
+ "definition": null,
+ "globalSettings": {
+ "hideHeader": true,
+ "appInMaintenance": false,
+ "canvasMaxWidth": 100,
+ "canvasMaxWidthType": "%",
+ "canvasMaxHeight": 2400,
+ "canvasBackgroundColor": "#edeff5",
+ "backgroundFxQuery": "",
+ "appMode": "auto"
+ },
+ "pageSettings": {
+ "properties": {
+ "disableMenu": {
+ "value": "{{true}}",
+ "fxActive": false
+ }
+ }
+ },
+ "showViewerNavigation": false,
+ "homePageId": "93c0473f-6ada-4f1d-9c05-8a4775466aab",
+ "appId": "8819afae-57b6-447d-93dd-6dc108169bfe",
+ "currentEnvironmentId": "4efb81aa-756a-4a8f-a017-e167f0720b85",
+ "promotedFrom": null,
+ "createdAt": "2025-02-27T07:28:52.144Z",
+ "updatedAt": "2025-02-27T07:28:52.274Z"
+ },
+ "components": [
+ {
+ "id": "7bf37542-4eaa-42d8-9827-1cf1f1649791",
+ "name": "container1",
+ "type": "Container",
+ "pageId": "93c0473f-6ada-4f1d-9c05-8a4775466aab",
+ "parent": null,
+ "properties": {},
+ "general": {},
+ "styles": {
+ "backgroundColor": {
+ "value": "#ffffffff"
+ },
+ "borderRadius": {
+ "value": "10"
+ },
+ "borderColor": {
+ "value": "#ffffff00",
+ "fxActive": false
+ }
+ },
+ "generalStyles": {},
+ "displayPreferences": {
+ "showOnDesktop": {
+ "value": "{{true}}"
+ },
+ "showOnMobile": {
+ "value": "{{false}}"
+ }
+ },
+ "validation": {},
+ "createdAt": "2025-02-27T07:28:52.148Z",
+ "updatedAt": "2025-02-27T07:28:52.148Z",
+ "layouts": [
+ {
+ "id": "7367ab91-9541-4bd9-96f7-32da8bb61cf5",
+ "type": "desktop",
+ "top": 20,
+ "left": 1,
+ "width": 41,
+ "height": 70,
+ "componentId": "7bf37542-4eaa-42d8-9827-1cf1f1649791",
+ "dimensionUnit": "count",
+ "updatedAt": "2025-02-27T07:28:52.148Z"
+ }
+ ]
+ },
+ {
+ "id": "9b1d3bec-c586-4f2b-acdf-09cea7addecc",
+ "name": "text1",
+ "type": "Text",
+ "pageId": "93c0473f-6ada-4f1d-9c05-8a4775466aab",
+ "parent": "7bf37542-4eaa-42d8-9827-1cf1f1649791",
+ "properties": {
+ "text": {
+ "value": "B R A N D"
+ }
+ },
+ "general": {},
+ "styles": {
+ "textColor": {
+ "value": "#000",
+ "fxActive": false
+ },
+ "textSize": {
+ "value": "{{24}}"
+ },
+ "fontWeight": {
+ "value": "bold"
+ },
+ "boxShadow": {
+ "value": "0px 0px 0px 0px #00000040"
+ },
+ "isScrollRequired": {
+ "value": "disabled"
+ }
+ },
+ "generalStyles": {},
+ "displayPreferences": {
+ "showOnDesktop": {
+ "value": "{{true}}"
+ },
+ "showOnMobile": {
+ "value": "{{false}}"
+ }
+ },
+ "validation": {},
+ "createdAt": "2025-02-27T07:28:52.148Z",
+ "updatedAt": "2025-02-27T07:28:52.148Z",
+ "layouts": [
+ {
+ "id": "8c07e506-b1f5-4715-ab02-718fcce9295b",
+ "type": "desktop",
+ "top": 10,
+ "left": 1,
+ "width": 6,
+ "height": 40,
+ "componentId": "9b1d3bec-c586-4f2b-acdf-09cea7addecc",
+ "dimensionUnit": "count",
+ "updatedAt": "2025-02-27T07:28:52.148Z"
+ }
+ ]
+ },
+ {
+ "id": "38100944-4325-49b7-8c70-de75cf5ce63d",
+ "name": "text2",
+ "type": "Text",
+ "pageId": "93c0473f-6ada-4f1d-9c05-8a4775466aab",
+ "parent": "7bf37542-4eaa-42d8-9827-1cf1f1649791",
+ "properties": {
+ "text": {
+ "value": "AI Code Explainer
"
+ }
+ },
+ "general": {},
+ "styles": {
+ "textColor": {
+ "value": "#000",
+ "fxActive": false
+ },
+ "textSize": {
+ "value": "{{20}}"
+ },
+ "textAlign": {
+ "value": "right"
+ },
+ "boxShadow": {
+ "value": "0px 0px 0px 0px #00000040"
+ },
+ "isScrollRequired": {
+ "value": "disabled"
+ }
+ },
+ "generalStyles": {},
+ "displayPreferences": {
+ "showOnDesktop": {
+ "value": "{{true}}"
+ },
+ "showOnMobile": {
+ "value": "{{false}}"
+ }
+ },
+ "validation": {},
+ "createdAt": "2025-02-27T07:28:52.148Z",
+ "updatedAt": "2025-02-27T07:28:52.148Z",
+ "layouts": [
+ {
+ "id": "129e63b6-9456-4cb7-94b0-7379743fec88",
+ "type": "desktop",
+ "top": 10,
+ "left": 25,
+ "width": 17,
+ "height": 40,
+ "componentId": "38100944-4325-49b7-8c70-de75cf5ce63d",
+ "dimensionUnit": "count",
+ "updatedAt": "2025-02-27T07:28:52.148Z"
+ }
+ ]
+ },
+ {
+ "id": "2727cf8a-1856-41cb-b716-c25afc2a15ad",
+ "name": "container2",
+ "type": "Container",
+ "pageId": "93c0473f-6ada-4f1d-9c05-8a4775466aab",
+ "parent": null,
+ "properties": {},
+ "general": {},
+ "styles": {
+ "borderRadius": {
+ "value": "10"
+ }
+ },
+ "generalStyles": {},
+ "displayPreferences": {
+ "showOnDesktop": {
+ "value": "{{true}}"
+ },
+ "showOnMobile": {
+ "value": "{{false}}"
+ }
+ },
+ "validation": {},
+ "createdAt": "2025-02-27T07:28:52.148Z",
+ "updatedAt": "2025-02-27T07:28:52.148Z",
+ "layouts": [
+ {
+ "id": "14b7706c-cebf-45dc-a555-3a60fdf01f3b",
+ "type": "desktop",
+ "top": 110,
+ "left": 1,
+ "width": 41,
+ "height": 620,
+ "componentId": "2727cf8a-1856-41cb-b716-c25afc2a15ad",
+ "dimensionUnit": "count",
+ "updatedAt": "2025-02-27T07:28:52.148Z"
+ },
+ {
+ "id": "ef46f35d-bf64-4ea0-8c9b-c525b87d6120",
+ "type": "mobile",
+ "top": 110,
+ "left": 1,
+ "width": 5,
+ "height": 200,
+ "componentId": "2727cf8a-1856-41cb-b716-c25afc2a15ad",
+ "dimensionUnit": "count",
+ "updatedAt": "2025-02-27T07:28:52.148Z"
+ }
+ ]
+ },
+ {
+ "id": "fbdab782-4a3b-4811-9f43-35f6dfae8735",
+ "name": "text3",
+ "type": "Text",
+ "pageId": "93c0473f-6ada-4f1d-9c05-8a4775466aab",
+ "parent": "2727cf8a-1856-41cb-b716-c25afc2a15ad",
+ "properties": {
+ "text": {
+ "value": "Code to be explained"
+ }
+ },
+ "general": {},
+ "styles": {
+ "textSize": {
+ "value": "24"
+ },
+ "fontWeight": {
+ "value": "bold"
+ },
+ "isScrollRequired": {
+ "value": "disabled"
+ }
+ },
+ "generalStyles": {},
+ "displayPreferences": {
+ "showOnDesktop": {
+ "value": "{{true}}"
+ },
+ "showOnMobile": {
+ "value": "{{false}}"
+ }
+ },
+ "validation": {},
+ "createdAt": "2025-02-27T07:28:52.148Z",
+ "updatedAt": "2025-02-27T07:28:52.148Z",
+ "layouts": [
+ {
+ "id": "cfc25680-87fe-45d1-8431-f009ba351ae2",
+ "type": "desktop",
+ "top": 20,
+ "left": 1,
+ "width": 20,
+ "height": 40,
+ "componentId": "fbdab782-4a3b-4811-9f43-35f6dfae8735",
+ "dimensionUnit": "count",
+ "updatedAt": "2025-02-27T07:28:52.148Z"
+ },
+ {
+ "id": "bbb13f33-25ee-4c97-8c08-7d7df99ab431",
+ "type": "mobile",
+ "top": 20,
+ "left": 9,
+ "width": 13.953488372093023,
+ "height": 40,
+ "componentId": "fbdab782-4a3b-4811-9f43-35f6dfae8735",
+ "dimensionUnit": "count",
+ "updatedAt": "2025-02-27T07:28:52.148Z"
+ }
+ ]
+ },
+ {
+ "id": "dca350e6-c9f8-44aa-94d5-e6245cfb0ae2",
+ "name": "dropdown1",
+ "type": "DropDown",
+ "pageId": "93c0473f-6ada-4f1d-9c05-8a4775466aab",
+ "parent": "2727cf8a-1856-41cb-b716-c25afc2a15ad",
+ "properties": {
+ "label": {
+ "value": ""
+ },
+ "value": {
+ "value": ""
+ },
+ "values": {
+ "value": "{{queries.32ff6874-7da0-4b88-ae05-3c9cda4a07dc.data.models.map(item => item.name)}}"
+ },
+ "display_values": {
+ "value": "{{queries.32ff6874-7da0-4b88-ae05-3c9cda4a07dc.data.models.map(item => item.displayName)}}"
+ },
+ "loadingState": {
+ "value": "{{queries.32ff6874-7da0-4b88-ae05-3c9cda4a07dc.isLoading}}",
+ "fxActive": true
+ },
+ "placeholder": {
+ "value": "Select a model"
+ }
+ },
+ "general": {},
+ "styles": {
+ "borderRadius": {
+ "value": "5"
+ }
+ },
+ "generalStyles": {},
+ "displayPreferences": {
+ "showOnDesktop": {
+ "value": "{{true}}"
+ },
+ "showOnMobile": {
+ "value": "{{false}}"
+ }
+ },
+ "validation": {},
+ "createdAt": "2025-02-27T07:28:52.148Z",
+ "updatedAt": "2025-02-27T07:28:52.267Z",
+ "layouts": [
+ {
+ "id": "91cae02e-6d00-48ad-9750-1ae74bc9fd7f",
+ "type": "mobile",
+ "top": 10,
+ "left": 27,
+ "width": 18.6046511627907,
+ "height": 30,
+ "componentId": "dca350e6-c9f8-44aa-94d5-e6245cfb0ae2",
+ "dimensionUnit": "count",
+ "updatedAt": "2025-02-27T07:28:52.148Z"
+ },
+ {
+ "id": "bb56cbd1-57f7-4917-8a32-046a8e77ed33",
+ "type": "desktop",
+ "top": 480,
+ "left": 1,
+ "width": 20,
+ "height": 40,
+ "componentId": "dca350e6-c9f8-44aa-94d5-e6245cfb0ae2",
+ "dimensionUnit": "count",
+ "updatedAt": "2025-02-27T07:28:52.148Z"
+ }
+ ]
+ },
+ {
+ "id": "98a7f66e-d446-4be5-b2e8-6bde808e9461",
+ "name": "textarea1",
+ "type": "TextArea",
+ "pageId": "93c0473f-6ada-4f1d-9c05-8a4775466aab",
+ "parent": "2727cf8a-1856-41cb-b716-c25afc2a15ad",
+ "properties": {
+ "value": {
+ "value": "function addNumbers(a, b) {\n return a + b;\n}\n\nconst sum = addNumbers(5, 3);\nconsole.log(sum);"
+ },
+ "placeholder": {
+ "value": "function addNumbers(a, b) {\n return a + b;\n}\n\nconst sum = addNumbers(5, 3);\nconsole.log(sum);"
+ }
+ },
+ "general": {},
+ "styles": {
+ "borderRadius": {
+ "value": "{{5}}"
+ }
+ },
+ "generalStyles": {},
+ "displayPreferences": {
+ "showOnDesktop": {
+ "value": "{{true}}"
+ },
+ "showOnMobile": {
+ "value": "{{false}}"
+ }
+ },
+ "validation": {},
+ "createdAt": "2025-02-27T07:28:52.148Z",
+ "updatedAt": "2025-02-27T07:28:52.148Z",
+ "layouts": [
+ {
+ "id": "db411aca-2e7e-46ae-8bf6-75f664a636ea",
+ "type": "mobile",
+ "top": 100,
+ "left": 3,
+ "width": 13.953488372093023,
+ "height": 100,
+ "componentId": "98a7f66e-d446-4be5-b2e8-6bde808e9461",
+ "dimensionUnit": "count",
+ "updatedAt": "2025-02-27T07:28:52.148Z"
+ },
+ {
+ "id": "abdc0362-e37b-48d6-9cad-ccbdfcf6fd55",
+ "type": "desktop",
+ "top": 70,
+ "left": 1,
+ "width": 20,
+ "height": 270,
+ "componentId": "98a7f66e-d446-4be5-b2e8-6bde808e9461",
+ "dimensionUnit": "count",
+ "updatedAt": "2025-02-27T07:28:52.148Z"
+ }
+ ]
+ },
+ {
+ "id": "37fbb9ed-5ac6-439b-82cb-35e276c89f49",
+ "name": "button1",
+ "type": "Button",
+ "pageId": "93c0473f-6ada-4f1d-9c05-8a4775466aab",
+ "parent": "2727cf8a-1856-41cb-b716-c25afc2a15ad",
+ "properties": {
+ "text": {
+ "value": "Generate explanation >>"
+ },
+ "loadingState": {
+ "value": "{{false}}",
+ "fxActive": false
+ },
+ "disabledState": {
+ "value": "{{components.dca350e6-c9f8-44aa-94d5-e6245cfb0ae2.value == undefined || queries.getCodeExplanation.isLoading}}",
+ "fxActive": true
+ }
+ },
+ "general": {},
+ "styles": {
+ "backgroundColor": {
+ "value": "#ffffff00"
+ },
+ "textColor": {
+ "value": "#3e63ddff"
+ },
+ "loaderColor": {
+ "value": "#3e63ddff"
+ },
+ "borderRadius": {
+ "value": "{{5}}"
+ },
+ "borderColor": {
+ "value": "#3e63ddff"
+ }
+ },
+ "generalStyles": {},
+ "displayPreferences": {
+ "showOnDesktop": {
+ "value": "{{true}}"
+ },
+ "showOnMobile": {
+ "value": "{{false}}"
+ }
+ },
+ "validation": {},
+ "createdAt": "2025-02-27T07:28:52.148Z",
+ "updatedAt": "2025-02-27T07:28:52.267Z",
+ "layouts": [
+ {
+ "id": "c110426c-5994-4d04-901d-883aafb9d2eb",
+ "type": "mobile",
+ "top": 420,
+ "left": 7,
+ "width": 6.976744186046512,
+ "height": 30,
+ "componentId": "37fbb9ed-5ac6-439b-82cb-35e276c89f49",
+ "dimensionUnit": "count",
+ "updatedAt": "2025-02-27T07:28:52.148Z"
+ },
+ {
+ "id": "a6a6b92e-0984-4e21-87fc-462a307e06dd",
+ "type": "desktop",
+ "top": 550,
+ "left": 1,
+ "width": 20,
+ "height": 40,
+ "componentId": "37fbb9ed-5ac6-439b-82cb-35e276c89f49",
+ "dimensionUnit": "count",
+ "updatedAt": "2025-02-27T07:28:52.148Z"
+ }
+ ]
+ },
+ {
+ "id": "b56cb989-9b4f-4dcf-a6c4-70dcfe6aac1a",
+ "name": "dropdown2",
+ "type": "DropDown",
+ "pageId": "93c0473f-6ada-4f1d-9c05-8a4775466aab",
+ "parent": "2727cf8a-1856-41cb-b716-c25afc2a15ad",
+ "properties": {
+ "values": {
+ "value": "{{[\n \"\",\n \"C#\",\n \"C++\",\n \"Dart\",\n \"Elixir\",\n \"Erlang\",\n \"F#\",\n \"Go\",\n \"Groovy\",\n \"Haskell\",\n \"Java\",\n \"JavaScript\",\n \"Kotlin\",\n \"Lua\",\n \"MATLAB\",\n \"Objective-C\",\n \"Perl\",\n \"PHP\",\n \"Python\",\n \"R\",\n \"Ruby\",\n \"Rust\",\n \"Scala\",\n \"Shell\",\n \"SQL\",\n \"Swift\",\n \"TypeScript\"\n]}}"
+ },
+ "display_values": {
+ "value": "{{[\n \"Any language\",\n \"C#\",\n \"C++\",\n \"Dart\",\n \"Elixir\",\n \"Erlang\",\n \"F#\",\n \"Go\",\n \"Groovy\",\n \"Haskell\",\n \"Java\",\n \"JavaScript\",\n \"Kotlin\",\n \"Lua\",\n \"MATLAB\",\n \"Objective-C\",\n \"Perl\",\n \"PHP\",\n \"Python\",\n \"R\",\n \"Ruby\",\n \"Rust\",\n \"Scala\",\n \"Shell\",\n \"SQL\",\n \"Swift\",\n \"TypeScript\"\n]}}"
+ },
+ "value": {
+ "value": ""
+ },
+ "placeholder": {
+ "value": "Select a language"
+ },
+ "label": {
+ "value": ""
+ }
+ },
+ "general": {},
+ "styles": {},
+ "generalStyles": {},
+ "displayPreferences": {
+ "showOnDesktop": {
+ "value": "{{true}}"
+ },
+ "showOnMobile": {
+ "value": "{{false}}"
+ }
+ },
+ "validation": {},
+ "createdAt": "2025-02-27T07:28:52.148Z",
+ "updatedAt": "2025-02-27T07:28:52.148Z",
+ "layouts": [
+ {
+ "id": "553e50a3-c9d4-4ae7-9b8d-da129cb2f32d",
+ "type": "mobile",
+ "top": 420,
+ "left": 2,
+ "width": 8,
+ "height": 30,
+ "componentId": "b56cb989-9b4f-4dcf-a6c4-70dcfe6aac1a",
+ "dimensionUnit": "count",
+ "updatedAt": "2025-02-27T07:28:52.148Z"
+ },
+ {
+ "id": "abeda4d6-0111-4b9a-bfb1-234c986ee777",
+ "type": "desktop",
+ "top": 390,
+ "left": 1,
+ "width": 20,
+ "height": 40,
+ "componentId": "b56cb989-9b4f-4dcf-a6c4-70dcfe6aac1a",
+ "dimensionUnit": "count",
+ "updatedAt": "2025-02-27T07:28:52.148Z"
+ }
+ ]
+ },
+ {
+ "id": "7112d3b6-f7d5-4da8-84ad-f2db9ab962d8",
+ "name": "text6",
+ "type": "Text",
+ "pageId": "93c0473f-6ada-4f1d-9c05-8a4775466aab",
+ "parent": "2727cf8a-1856-41cb-b716-c25afc2a15ad",
+ "properties": {
+ "text": {
+ "value": "Language"
+ }
+ },
+ "general": {},
+ "styles": {
+ "fontWeight": {
+ "value": "bold"
+ }
+ },
+ "generalStyles": {},
+ "displayPreferences": {
+ "showOnDesktop": {
+ "value": "{{true}}"
+ },
+ "showOnMobile": {
+ "value": "{{false}}"
+ }
+ },
+ "validation": {},
+ "createdAt": "2025-02-27T07:28:52.148Z",
+ "updatedAt": "2025-02-27T07:28:52.148Z",
+ "layouts": [
+ {
+ "id": "3b6ce6c5-bb8b-4145-991b-b4dc659ac9ae",
+ "type": "desktop",
+ "top": 360,
+ "left": 1,
+ "width": 14,
+ "height": 30,
+ "componentId": "7112d3b6-f7d5-4da8-84ad-f2db9ab962d8",
+ "dimensionUnit": "count",
+ "updatedAt": "2025-02-27T07:28:52.148Z"
+ },
+ {
+ "id": "d907a75f-162c-4e89-8bef-8ad4a6b10f6a",
+ "type": "mobile",
+ "top": 70,
+ "left": 4,
+ "width": 13.953488372093023,
+ "height": 40,
+ "componentId": "7112d3b6-f7d5-4da8-84ad-f2db9ab962d8",
+ "dimensionUnit": "count",
+ "updatedAt": "2025-02-27T07:28:52.148Z"
+ }
+ ]
+ },
+ {
+ "id": "052d73d1-c415-4720-8963-36c94ce54b19",
+ "name": "text7",
+ "type": "Text",
+ "pageId": "93c0473f-6ada-4f1d-9c05-8a4775466aab",
+ "parent": "2727cf8a-1856-41cb-b716-c25afc2a15ad",
+ "properties": {
+ "text": {
+ "value": "{{`${queries.getCodeExplanation.data.candidates ? queries.getCodeExplanation.data.candidates[0].content.parts[0].text : \"
- Language: JavaScript
function addNumbers(a, b) {: Defines a function named addNumbers that takes two parameters a and b. return a + b;: The function returns the sum of a and b. }: Ends the function definition. const sum = addNumbers(5, 3);: Calls the addNumbers function with arguments 5 and 3, and assigns the result to the constant sum. console.log(sum);: Outputs the value of sum to the console, which is 8.
\"}
`}}"
+ },
+ "textFormat": {
+ "value": "html"
+ },
+ "loadingState": {
+ "fxActive": true,
+ "value": "{{queries.5774aa01-0931-4036-8bfa-4d12e0b6bc8b.isLoading}}"
+ }
+ },
+ "general": {},
+ "styles": {
+ "borderColor": {
+ "value": "#ddddddff"
+ },
+ "borderRadius": {
+ "value": "5"
+ },
+ "verticalAlignment": {
+ "value": "top"
+ }
+ },
+ "generalStyles": {},
+ "displayPreferences": {
+ "showOnDesktop": {
+ "value": "{{true}}"
+ },
+ "showOnMobile": {
+ "value": "{{false}}"
+ }
+ },
+ "validation": {},
+ "createdAt": "2025-02-27T07:28:52.148Z",
+ "updatedAt": "2025-02-27T07:28:52.267Z",
+ "layouts": [
+ {
+ "id": "388a36e0-95ac-49f3-a97b-ad413efafb3a",
+ "type": "desktop",
+ "top": 70,
+ "left": 22,
+ "width": 20,
+ "height": 520,
+ "componentId": "052d73d1-c415-4720-8963-36c94ce54b19",
+ "dimensionUnit": "count",
+ "updatedAt": "2025-02-27T07:28:52.148Z"
+ },
+ {
+ "id": "1f2da6ab-3493-4ace-b5ae-ceadbd3e2fb0",
+ "type": "mobile",
+ "top": 290,
+ "left": 23,
+ "width": 6,
+ "height": 40,
+ "componentId": "052d73d1-c415-4720-8963-36c94ce54b19",
+ "dimensionUnit": "count",
+ "updatedAt": "2025-02-27T07:28:52.148Z"
+ }
+ ]
+ },
+ {
+ "id": "3c5278e8-8cc5-442a-bc70-19d4cd72cec7",
+ "name": "text8",
+ "type": "Text",
+ "pageId": "93c0473f-6ada-4f1d-9c05-8a4775466aab",
+ "parent": "2727cf8a-1856-41cb-b716-c25afc2a15ad",
+ "properties": {
+ "text": {
+ "value": "Gemini Model"
+ }
+ },
+ "general": {},
+ "styles": {
+ "fontWeight": {
+ "value": "bold"
+ }
+ },
+ "generalStyles": {},
+ "displayPreferences": {
+ "showOnDesktop": {
+ "value": "{{true}}"
+ },
+ "showOnMobile": {
+ "value": "{{false}}"
+ }
+ },
+ "validation": {},
+ "createdAt": "2025-02-27T07:28:52.148Z",
+ "updatedAt": "2025-02-27T07:28:52.148Z",
+ "layouts": [
+ {
+ "id": "e41fd57d-29e6-49e2-b3ee-75b3769f6d27",
+ "type": "mobile",
+ "top": 70,
+ "left": 4,
+ "width": 13.953488372093023,
+ "height": 40,
+ "componentId": "3c5278e8-8cc5-442a-bc70-19d4cd72cec7",
+ "dimensionUnit": "count",
+ "updatedAt": "2025-02-27T07:28:52.148Z"
+ },
+ {
+ "id": "7a1d68a9-e9f5-496e-9947-3d6e12c55b0c",
+ "type": "desktop",
+ "top": 450,
+ "left": 1,
+ "width": 14,
+ "height": 30,
+ "componentId": "3c5278e8-8cc5-442a-bc70-19d4cd72cec7",
+ "dimensionUnit": "count",
+ "updatedAt": "2025-02-27T07:28:52.148Z"
+ }
+ ]
+ },
+ {
+ "id": "521f0268-02d8-4571-9efe-030c9816bdea",
+ "name": "text9",
+ "type": "Text",
+ "pageId": "93c0473f-6ada-4f1d-9c05-8a4775466aab",
+ "parent": "2727cf8a-1856-41cb-b716-c25afc2a15ad",
+ "properties": {
+ "text": {
+ "value": "Explanation"
+ }
+ },
+ "general": {},
+ "styles": {
+ "textSize": {
+ "value": "24"
+ },
+ "fontWeight": {
+ "value": "bold"
+ },
+ "isScrollRequired": {
+ "value": "disabled"
+ }
+ },
+ "generalStyles": {},
+ "displayPreferences": {
+ "showOnDesktop": {
+ "value": "{{true}}"
+ },
+ "showOnMobile": {
+ "value": "{{false}}"
+ }
+ },
+ "validation": {},
+ "createdAt": "2025-02-27T07:28:52.148Z",
+ "updatedAt": "2025-02-27T07:28:52.148Z",
+ "layouts": [
+ {
+ "id": "81f9d6a1-90c4-422c-8602-1675a76f6de4",
+ "type": "desktop",
+ "top": 20,
+ "left": 22,
+ "width": 20,
+ "height": 40,
+ "componentId": "521f0268-02d8-4571-9efe-030c9816bdea",
+ "dimensionUnit": "count",
+ "updatedAt": "2025-02-27T07:28:52.148Z"
+ },
+ {
+ "id": "da2abfa1-769b-4784-87fb-5020e6610fed",
+ "type": "mobile",
+ "top": 20,
+ "left": 9,
+ "width": 13.953488372093023,
+ "height": 40,
+ "componentId": "521f0268-02d8-4571-9efe-030c9816bdea",
+ "dimensionUnit": "count",
+ "updatedAt": "2025-02-27T07:28:52.148Z"
+ }
+ ]
+ }
+ ],
+ "pages": [
+ {
+ "id": "93c0473f-6ada-4f1d-9c05-8a4775466aab",
+ "name": "Home",
+ "handle": "home",
+ "index": 1,
+ "disabled": false,
+ "hidden": false,
+ "icon": null,
+ "createdAt": "2025-02-27T07:28:52.148Z",
+ "updatedAt": "2025-02-27T07:28:52.366Z",
+ "autoComputeLayout": true,
+ "appVersionId": "430dd7d7-1cd1-4c36-975f-229a1aa7dcb8",
+ "pageGroupIndex": 1,
+ "pageGroupId": null,
+ "isPageGroup": false
+ }
+ ],
+ "events": [
+ {
+ "id": "9417716e-b415-4532-aea4-8a2afa224f10",
+ "name": "onClick",
+ "index": 0,
+ "event": {
+ "eventId": "onClick",
+ "message": "Hello world!",
+ "queryId": "5774aa01-0931-4036-8bfa-4d12e0b6bc8b",
+ "actionId": "run-query",
+ "alertType": "info",
+ "queryName": "getCodeExplanation",
+ "parameters": {}
+ },
+ "sourceId": "37fbb9ed-5ac6-439b-82cb-35e276c89f49",
+ "target": "component",
+ "appVersionId": "430dd7d7-1cd1-4c36-975f-229a1aa7dcb8",
+ "createdAt": "2025-02-27T07:28:52.148Z",
+ "updatedAt": "2025-02-27T07:28:52.260Z"
+ }
+ ],
+ "dataQueries": [
+ {
+ "id": "5774aa01-0931-4036-8bfa-4d12e0b6bc8b",
+ "name": "getCodeExplanation",
+ "options": {
+ "method": "post",
+ "url": "https://generativelanguage.googleapis.com/v1beta/{{components.dropdown1.value}}:generateContent",
+ "url_params": [
+ [
+ "key",
+ "{{constants.GEMINI_API_KEY}}"
+ ],
+ [
+ "",
+ ""
+ ]
+ ],
+ "headers": [
+ [
+ "Content-Type",
+ "application/json"
+ ],
+ [
+ "",
+ ""
+ ]
+ ],
+ "body": [
+ [
+ "",
+ ""
+ ]
+ ],
+ "json_body": "{\n \"contents\": [\n {\n \"parts\": [\n {\n \"text\": \"{{components.textarea1.value.replaceAll('\\n','\\\\n')}} - Generate a point-wise line by line explanation of this code in html formatting only. Keep only the explanation, and nothing else. {{components.dropdown2.value ? `The code is in ${components.dropdown2.value} language.` : 'Also identify the language of the code.'}}\"\n }\n ]\n }\n ]\n}",
+ "body_toggle": true,
+ "transformationLanguage": "javascript",
+ "enableTransformation": false,
+ "arrayValuesChanged": false,
+ "transformation": "// write your code here\n// return value will be set as data and the original data will be available as rawData\nreturn data.filter(row => row.amount > 1000);\n "
+ },
+ "dataSourceId": "489072da-3239-4bd5-91b9-dee5f5da5335",
+ "appVersionId": "430dd7d7-1cd1-4c36-975f-229a1aa7dcb8",
+ "createdAt": "2025-02-27T07:28:52.148Z",
+ "updatedAt": "2025-02-27T07:28:52.148Z"
+ },
+ {
+ "id": "32ff6874-7da0-4b88-ae05-3c9cda4a07dc",
+ "name": "getGeminiModels",
+ "options": {
+ "method": "get",
+ "url": "https://generativelanguage.googleapis.com/v1beta/models?key={{constants.GEMINI_API_KEY}}",
+ "url_params": [
+ [
+ "",
+ ""
+ ]
+ ],
+ "headers": [
+ [
+ "",
+ ""
+ ]
+ ],
+ "body": [
+ [
+ "",
+ ""
+ ]
+ ],
+ "json_body": null,
+ "body_toggle": false,
+ "transformationLanguage": "javascript",
+ "enableTransformation": false,
+ "runOnPageLoad": true
+ },
+ "dataSourceId": "489072da-3239-4bd5-91b9-dee5f5da5335",
+ "appVersionId": "430dd7d7-1cd1-4c36-975f-229a1aa7dcb8",
+ "createdAt": "2025-02-27T07:28:52.148Z",
+ "updatedAt": "2025-02-27T07:28:52.983Z"
+ }
+ ],
+ "dataSources": [
+ {
+ "id": "489072da-3239-4bd5-91b9-dee5f5da5335",
+ "name": "restapidefault",
+ "kind": "restapi",
+ "type": "static",
+ "pluginId": null,
+ "appVersionId": "430dd7d7-1cd1-4c36-975f-229a1aa7dcb8",
+ "organizationId": null,
+ "scope": "local",
+ "createdAt": "2025-02-27T07:28:52.153Z",
+ "updatedAt": "2025-02-27T07:28:52.153Z"
+ },
+ {
+ "id": "c462a40f-c7fa-4d55-98fe-9bc445271cab",
+ "name": "runjsdefault",
+ "kind": "runjs",
+ "type": "static",
+ "pluginId": null,
+ "appVersionId": "430dd7d7-1cd1-4c36-975f-229a1aa7dcb8",
+ "organizationId": null,
+ "scope": "local",
+ "createdAt": "2025-02-27T07:28:52.163Z",
+ "updatedAt": "2025-02-27T07:28:52.163Z"
+ },
+ {
+ "id": "cc0b5feb-29ea-47c0-9a9a-62c0e0b89ccb",
+ "name": "runpydefault",
+ "kind": "runpy",
+ "type": "static",
+ "pluginId": null,
+ "appVersionId": "430dd7d7-1cd1-4c36-975f-229a1aa7dcb8",
+ "organizationId": null,
+ "scope": "local",
+ "createdAt": "2025-02-27T07:28:52.170Z",
+ "updatedAt": "2025-02-27T07:28:52.170Z"
+ },
+ {
+ "id": "907dde15-1ac2-4f53-ba72-8e4e1d066f0e",
+ "name": "tooljetdbdefault",
+ "kind": "tooljetdb",
+ "type": "static",
+ "pluginId": null,
+ "appVersionId": "430dd7d7-1cd1-4c36-975f-229a1aa7dcb8",
+ "organizationId": null,
+ "scope": "local",
+ "createdAt": "2025-02-27T07:28:52.176Z",
+ "updatedAt": "2025-02-27T07:28:52.176Z"
+ },
+ {
+ "id": "66ad4e35-f981-47a6-99cd-31e9e7bbd9b3",
+ "name": "workflowsdefault",
+ "kind": "workflows",
+ "type": "static",
+ "pluginId": null,
+ "appVersionId": "430dd7d7-1cd1-4c36-975f-229a1aa7dcb8",
+ "organizationId": null,
+ "scope": "local",
+ "createdAt": "2025-02-27T07:28:52.183Z",
+ "updatedAt": "2025-02-27T07:28:52.183Z"
+ }
+ ],
+ "appVersions": [
+ {
+ "id": "430dd7d7-1cd1-4c36-975f-229a1aa7dcb8",
+ "name": "v1",
+ "definition": null,
+ "globalSettings": {
+ "hideHeader": true,
+ "appInMaintenance": false,
+ "canvasMaxWidth": 100,
+ "canvasMaxWidthType": "%",
+ "canvasMaxHeight": 2400,
+ "canvasBackgroundColor": "#edeff5",
+ "backgroundFxQuery": "",
+ "appMode": "auto"
+ },
+ "pageSettings": {
+ "properties": {
+ "disableMenu": {
+ "value": "{{true}}",
+ "fxActive": false
+ }
+ }
+ },
+ "showViewerNavigation": false,
+ "homePageId": "93c0473f-6ada-4f1d-9c05-8a4775466aab",
+ "appId": "8819afae-57b6-447d-93dd-6dc108169bfe",
+ "currentEnvironmentId": "4efb81aa-756a-4a8f-a017-e167f0720b85",
+ "promotedFrom": null,
+ "createdAt": "2025-02-27T07:28:52.144Z",
+ "updatedAt": "2025-02-27T07:28:52.274Z"
+ }
+ ],
+ "appEnvironments": [
+ {
+ "id": "4efb81aa-756a-4a8f-a017-e167f0720b85",
+ "organizationId": "a51da635-3a28-4b10-a6f4-7ba34e254987",
+ "name": "development",
+ "isDefault": false,
+ "priority": 1,
+ "enabled": true,
+ "createdAt": "2025-02-27T07:28:36.425Z",
+ "updatedAt": "2025-02-27T07:28:36.425Z"
+ },
+ {
+ "id": "ed48a4ab-ef5c-47c0-b99c-453fec90b9ec",
+ "organizationId": "a51da635-3a28-4b10-a6f4-7ba34e254987",
+ "name": "staging",
+ "isDefault": false,
+ "priority": 2,
+ "enabled": true,
+ "createdAt": "2025-02-27T07:28:36.425Z",
+ "updatedAt": "2025-02-27T07:28:36.425Z"
+ },
+ {
+ "id": "eb006618-493c-48ac-8a4d-e80d208d29de",
+ "organizationId": "a51da635-3a28-4b10-a6f4-7ba34e254987",
+ "name": "production",
+ "isDefault": true,
+ "priority": 3,
+ "enabled": true,
+ "createdAt": "2025-02-27T07:28:36.425Z",
+ "updatedAt": "2025-02-27T07:28:36.425Z"
+ }
+ ],
+ "dataSourceOptions": [
+ {
+ "id": "98e3239b-e54b-4b59-992b-d9bbfb68d1e6",
+ "dataSourceId": "489072da-3239-4bd5-91b9-dee5f5da5335",
+ "environmentId": "4efb81aa-756a-4a8f-a017-e167f0720b85",
+ "options": null,
+ "createdAt": "2025-02-27T07:28:52.159Z",
+ "updatedAt": "2025-02-27T07:28:52.159Z"
+ },
+ {
+ "id": "c997ee43-2f17-46aa-bc35-32af668d546b",
+ "dataSourceId": "489072da-3239-4bd5-91b9-dee5f5da5335",
+ "environmentId": "ed48a4ab-ef5c-47c0-b99c-453fec90b9ec",
+ "options": null,
+ "createdAt": "2025-02-27T07:28:52.159Z",
+ "updatedAt": "2025-02-27T07:28:52.159Z"
+ },
+ {
+ "id": "01bbd244-59c9-4965-8024-401c8f1961fd",
+ "dataSourceId": "489072da-3239-4bd5-91b9-dee5f5da5335",
+ "environmentId": "eb006618-493c-48ac-8a4d-e80d208d29de",
+ "options": null,
+ "createdAt": "2025-02-27T07:28:52.159Z",
+ "updatedAt": "2025-02-27T07:28:52.159Z"
+ },
+ {
+ "id": "8a8096f7-6b6f-49ca-95de-596c5670c832",
+ "dataSourceId": "c462a40f-c7fa-4d55-98fe-9bc445271cab",
+ "environmentId": "4efb81aa-756a-4a8f-a017-e167f0720b85",
+ "options": null,
+ "createdAt": "2025-02-27T07:28:52.167Z",
+ "updatedAt": "2025-02-27T07:28:52.167Z"
+ },
+ {
+ "id": "1e2dcc6d-8944-4b5b-abd4-72f7201bf657",
+ "dataSourceId": "c462a40f-c7fa-4d55-98fe-9bc445271cab",
+ "environmentId": "ed48a4ab-ef5c-47c0-b99c-453fec90b9ec",
+ "options": null,
+ "createdAt": "2025-02-27T07:28:52.167Z",
+ "updatedAt": "2025-02-27T07:28:52.167Z"
+ },
+ {
+ "id": "24bfe83d-b2d3-4bf0-8730-1bd14d96cf7a",
+ "dataSourceId": "c462a40f-c7fa-4d55-98fe-9bc445271cab",
+ "environmentId": "eb006618-493c-48ac-8a4d-e80d208d29de",
+ "options": null,
+ "createdAt": "2025-02-27T07:28:52.167Z",
+ "updatedAt": "2025-02-27T07:28:52.167Z"
+ },
+ {
+ "id": "44600a77-04bf-4b30-8613-bd7a7bff6508",
+ "dataSourceId": "cc0b5feb-29ea-47c0-9a9a-62c0e0b89ccb",
+ "environmentId": "4efb81aa-756a-4a8f-a017-e167f0720b85",
+ "options": null,
+ "createdAt": "2025-02-27T07:28:52.174Z",
+ "updatedAt": "2025-02-27T07:28:52.174Z"
+ },
+ {
+ "id": "b70c436e-70e5-48d3-84d2-ca2c784c7425",
+ "dataSourceId": "cc0b5feb-29ea-47c0-9a9a-62c0e0b89ccb",
+ "environmentId": "ed48a4ab-ef5c-47c0-b99c-453fec90b9ec",
+ "options": null,
+ "createdAt": "2025-02-27T07:28:52.174Z",
+ "updatedAt": "2025-02-27T07:28:52.174Z"
+ },
+ {
+ "id": "7bd1351e-61b9-4ba6-9e57-8eca1a3a0df3",
+ "dataSourceId": "cc0b5feb-29ea-47c0-9a9a-62c0e0b89ccb",
+ "environmentId": "eb006618-493c-48ac-8a4d-e80d208d29de",
+ "options": null,
+ "createdAt": "2025-02-27T07:28:52.174Z",
+ "updatedAt": "2025-02-27T07:28:52.174Z"
+ },
+ {
+ "id": "f8268c18-8453-48ac-acf7-46c2d0c75c75",
+ "dataSourceId": "907dde15-1ac2-4f53-ba72-8e4e1d066f0e",
+ "environmentId": "4efb81aa-756a-4a8f-a017-e167f0720b85",
+ "options": null,
+ "createdAt": "2025-02-27T07:28:52.181Z",
+ "updatedAt": "2025-02-27T07:28:52.181Z"
+ },
+ {
+ "id": "cd59c697-6ac2-4594-b8f6-493676e8b3c7",
+ "dataSourceId": "907dde15-1ac2-4f53-ba72-8e4e1d066f0e",
+ "environmentId": "ed48a4ab-ef5c-47c0-b99c-453fec90b9ec",
+ "options": null,
+ "createdAt": "2025-02-27T07:28:52.181Z",
+ "updatedAt": "2025-02-27T07:28:52.181Z"
+ },
+ {
+ "id": "7270ef0a-f6d6-498e-9959-4b646a30d5d1",
+ "dataSourceId": "907dde15-1ac2-4f53-ba72-8e4e1d066f0e",
+ "environmentId": "eb006618-493c-48ac-8a4d-e80d208d29de",
+ "options": null,
+ "createdAt": "2025-02-27T07:28:52.181Z",
+ "updatedAt": "2025-02-27T07:28:52.181Z"
+ },
+ {
+ "id": "fe4824d5-57fa-42dc-9812-4af634737898",
+ "dataSourceId": "66ad4e35-f981-47a6-99cd-31e9e7bbd9b3",
+ "environmentId": "4efb81aa-756a-4a8f-a017-e167f0720b85",
+ "options": null,
+ "createdAt": "2025-02-27T07:28:52.189Z",
+ "updatedAt": "2025-02-27T07:28:52.189Z"
+ },
+ {
+ "id": "521a6d91-484b-45bc-af8f-aaceb0dc515c",
+ "dataSourceId": "66ad4e35-f981-47a6-99cd-31e9e7bbd9b3",
+ "environmentId": "ed48a4ab-ef5c-47c0-b99c-453fec90b9ec",
+ "options": null,
+ "createdAt": "2025-02-27T07:28:52.189Z",
+ "updatedAt": "2025-02-27T07:28:52.189Z"
+ },
+ {
+ "id": "f5955bf2-c148-4544-acd9-a9a92a943e5b",
+ "dataSourceId": "66ad4e35-f981-47a6-99cd-31e9e7bbd9b3",
+ "environmentId": "eb006618-493c-48ac-8a4d-e80d208d29de",
+ "options": null,
+ "createdAt": "2025-02-27T07:28:52.189Z",
+ "updatedAt": "2025-02-27T07:28:52.189Z"
+ }
+ ],
+ "schemaDetails": {
+ "multiPages": true,
+ "multiEnv": true,
+ "globalDataSources": true
+ }
+ }
+ }
+ }
+ ],
+ "tooljet_version": "3.5.3-ee-lts"
+}
\ No newline at end of file
diff --git a/cypress-tests/cypress/support/utils/api.js b/cypress-tests/cypress/support/utils/api.js
new file mode 100644
index 0000000000..1ea37104f8
--- /dev/null
+++ b/cypress-tests/cypress/support/utils/api.js
@@ -0,0 +1,72 @@
+import { groupsSelector } from "Selectors/manageGroups";
+import { navigateToManageGroups } from 'Support/utils/common';
+export const apiRequest = (method, url, body = {}, headers = {}) => {
+ return cy.request({
+ method,
+ url,
+ body,
+ headers: {
+ Authorization: Cypress.env('AUTH_TOKEN'),
+ "Content-Type": "application/json",
+ ...headers,
+ },
+ failOnStatusCode: false
+ });
+};
+
+export const createUser = (userData) => {
+ return apiRequest("POST", `${Cypress.env('API_URL')}/ext/users`, userData);
+};
+
+export const getUser = (userId) => {
+ return apiRequest("GET", `${Cypress.env('API_URL')}/ext/user/${userId}`);
+};
+
+export const getAllUsers = () => {
+ return apiRequest("GET", `${Cypress.env('API_URL')}/ext/users`);
+};
+
+export const updateUser = (userId, userData) => {
+ return apiRequest("PATCH", `${Cypress.env('API_URL')}/ext/user/${userId}`, userData);
+};
+export const updateUserRole = (workspaceId, userData) => {
+ return apiRequest("PUT", `${Cypress.env('API_URL')}/ext/update-user-role/workspace/${workspaceId}`, userData);
+}
+
+export const replaceUserWorkspace = (userId, workspaceId, userData) => {
+ return apiRequest("PATCH", `${Cypress.env('API_URL')}/ext/user/${userId}/workspace/${workspaceId}`, userData);
+}
+
+export const replaceUserWorkspacesRelations = (userId, userData) => {
+ return apiRequest("PUT", `${Cypress.env('API_URL')}/ext/user/${userId}/workspaces`, userData);
+}
+
+export const getAllWorkspaces = () => {
+ return apiRequest("GET", `${Cypress.env('API_URL')}/ext/workspaces`);
+}
+
+export const importApp = (workspaceId, appData, headers) => {
+ return apiRequest("POST", `${Cypress.env('API_URL')}/ext/import/workspace/${workspaceId}/apps`, appData, headers);
+}
+
+export const exportApp = (workspaceId, appId, endpoint, headers) => {
+ return apiRequest("POST", `${Cypress.env('API_URL')}/ext/export/workspace/${workspaceId}/apps/${appId}${endpoint}`, headers);
+}
+
+export const allAppsDetails = (workspaceIds) => {
+ return apiRequest("GET", `${Cypress.env('API_URL')}/ext/workspace/${workspaceIds}/apps`);
+}
+
+export const createGroup = (groupName) => {
+ cy.get(groupsSelector.createNewGroupButton).click();
+ cy.clearAndType(groupsSelector.groupNameInput, groupName);
+ cy.get(groupsSelector.createGroupButton).click();
+}
+export const validateUserInGroup = (email, workspaceSlug, groupName, shouldExist = true) => {
+ if (workspaceSlug) cy.visit(workspaceSlug);
+ navigateToManageGroups();
+ cy.get(groupsSelector.groupLink(groupName)).click();
+ cy.get(groupsSelector.usersLink).click();
+ const userRow = `[data-cy="${email}-user-row"]`;
+ cy.get(userRow).should(shouldExist ? "exist" : "not.exist");
+};
\ No newline at end of file
diff --git a/cypress-tests/cypress/support/utils/manageGroups.js b/cypress-tests/cypress/support/utils/manageGroups.js
index dfda103d91..3f0c85d1cf 100644
--- a/cypress-tests/cypress/support/utils/manageGroups.js
+++ b/cypress-tests/cypress/support/utils/manageGroups.js
@@ -853,6 +853,9 @@ export const createGroupsAndAddUserInGroup = (groupName, email) => {
commonSelectors.toastMessage,
groupsText.groupCreatedToast
);
+ addUserInGroup(groupName, email);
+};
+export const addUserInGroup = (groupName, email) => {
cy.get(groupsSelector.groupLink(groupName)).click();
cy.clearAndType(groupsSelector.multiSelectSearchInput, email);
cy.wait(2000);
@@ -862,7 +865,7 @@ export const createGroupsAndAddUserInGroup = (groupName, email) => {
commonSelectors.toastMessage,
groupsText.userAddedToast
);
-};
+}
export const inviteUserBasedOnRole = (firstName, email, role = "end-user") => {
fillUserInviteForm(firstName, email);
diff --git a/docker/ce-entrypoint.sh b/docker/ce-entrypoint.sh
index 4b63af2e45..b18ab59ffd 100755
--- a/docker/ce-entrypoint.sh
+++ b/docker/ce-entrypoint.sh
@@ -1,6 +1,10 @@
#!/bin/bash
set -e
+if [ -f "./.env" ]; then
+ export $(grep -v '^#' ./.env | xargs -d '\n') || true
+fi
+
if [ -d "./server/dist" ]; then
SETUP_CMD='npm run db:setup:prod'
else
diff --git a/docker/ce-preview.Dockerfile b/docker/ce-preview.Dockerfile
index 4e9f8dd796..d71e6c1dbc 100644
--- a/docker/ce-preview.Dockerfile
+++ b/docker/ce-preview.Dockerfile
@@ -75,20 +75,39 @@ COPY --from=builder /app/server/templates ./app/server/templates
COPY --from=builder /app/server/scripts ./app/server/scripts
COPY --from=builder /app/server/dist ./app/server/dist
-COPY ./docker/ce-entrypoint.sh ./app/server/entrypoint.sh
-
WORKDIR /app
+USER root
+RUN wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add -
+RUN echo "deb http://apt.postgresql.org/pub/repos/apt/ bullseye-pgdg main" | tee /etc/apt/sources.list.d/pgdg.list
+RUN echo "deb http://deb.debian.org/debian"
+RUN apt update && apt -y install postgresql-13 postgresql-client-13 supervisor
+USER postgres
+RUN service postgresql start && \
+ psql -c "create role tooljet with login superuser password 'postgres';"
+USER root
+
# ENV defaults
-ENV TOOLJET_HOST=http://localhost:80 \
- PGRST_HOST=http://localhost:3000 \
- PGRST_JWT_SECRET=r9iMKoe5CRMgvJBBtp4HrqN7QiPpUToj \
- TOOLJET_DB=tooljet_db \
- ENABLE_TOOLJET_DB=true \
- PORT=80 \
+ENV TOOLJET_HOST=http://localhost \
+ NODE_ENV=production \
LOCKBOX_MASTER_KEY=replace_with_lockbox_master_key \
SECRET_KEY_BASE=replace_with_secret_key_base \
- ORM_LOGGING=all \
+ PG_DB=tooljet_production \
+ PG_USER=tooljet \
+ PG_PASS=postgres \
+ PG_HOST=localhost \
+ ENABLE_TOOLJET_DB=true \
+ TOOLJET_DB_HOST=localhost \
+ TOOLJET_DB_USER=tooljet \
+ TOOLJET_DB_PASS=postgres \
+ TOOLJET_DB=tooljet_db \
+ PGRST_HOST=http://localhost:3000 \
+ PGRST_DB_URI=postgres://tooljet:postgres@localhost/tooljet_db \
+ PGRST_JWT_SECRET=r9iMKoe5CRMgvJBBtp4HrqN7QiPpUToj \
+ PGRST_DB_PRE_CONFIG=postgrest.pre_config \
+ ORM_LOGGING=true \
+ DEPLOYMENT_PLATFORM=docker:local \
+ HOME=/home/appuser \
TERM=xterm
CMD ["/usr/bin/supervisord"]
diff --git a/docker/ee/ee-preview.Dockerfile b/docker/ee/ee-preview.Dockerfile
index d88efbfecf..91e0864bd0 100644
--- a/docker/ee/ee-preview.Dockerfile
+++ b/docker/ee/ee-preview.Dockerfile
@@ -104,20 +104,40 @@ COPY --from=builder /app/server/templates ./app/server/templates
COPY --from=builder /app/server/scripts ./app/server/scripts
COPY --from=builder /app/server/dist ./app/server/dist
-COPY ./docker/ee/ee-entrypoint.sh ./app/server/ee-entrypoint.sh
-
WORKDIR /app
# ENV defaults
-ENV TOOLJET_HOST=http://localhost:80 \
- PGRST_HOST=http://localhost:3000 \
- PGRST_JWT_SECRET=r9iMKoe5CRMgvJBBtp4HrqN7QiPpUToj \
- TOOLJET_DB=tooljet_db \
- ENABLE_TOOLJET_DB=true \
- PORT=80 \
+USER root
+RUN wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add -
+RUN echo "deb http://apt.postgresql.org/pub/repos/apt/ bullseye-pgdg main" | tee /etc/apt/sources.list.d/pgdg.list
+RUN echo "deb http://deb.debian.org/debian"
+RUN apt update && apt -y install postgresql-13 postgresql-client-13 supervisor
+USER postgres
+RUN service postgresql start && \
+ psql -c "create role tooljet with login superuser password 'postgres';"
+USER root
+
+# ENV defaults
+ENV TOOLJET_HOST=http://localhost \
+ NODE_ENV=production \
LOCKBOX_MASTER_KEY=replace_with_lockbox_master_key \
SECRET_KEY_BASE=replace_with_secret_key_base \
- ORM_LOGGING=all \
+ PG_DB=tooljet_production \
+ PG_USER=tooljet \
+ PG_PASS=postgres \
+ PG_HOST=localhost \
+ ENABLE_TOOLJET_DB=true \
+ TOOLJET_DB_HOST=localhost \
+ TOOLJET_DB_USER=tooljet \
+ TOOLJET_DB_PASS=postgres \
+ TOOLJET_DB=tooljet_db \
+ PGRST_HOST=http://localhost:3000 \
+ PGRST_DB_URI=postgres://tooljet:postgres@localhost/tooljet_db \
+ PGRST_JWT_SECRET=r9iMKoe5CRMgvJBBtp4HrqN7QiPpUToj \
+ PGRST_DB_PRE_CONFIG=postgrest.pre_config \
+ ORM_LOGGING=true \
+ DEPLOYMENT_PLATFORM=docker:local \
+ REDIS_PASS= \
TERM=xterm
CMD ["/usr/bin/supervisord"]
diff --git a/server/scripts/boot.sh b/server/scripts/boot.sh
index e12aa43a25..3c2bbad93e 100755
--- a/server/scripts/boot.sh
+++ b/server/scripts/boot.sh
@@ -1,6 +1,8 @@
#!/bin/bash
set -e
+service postgresql start
+
echo "
_____ _ ___ _
|_ _| | | |_ | | |