Merge branch 'main' into appdefinition-architecture-revamp

This commit is contained in:
arpitnath 2023-10-14 16:30:16 +05:30
commit 0adbcbd3f7
51 changed files with 356769 additions and 528 deletions

View file

@ -1,4 +1,4 @@
name: Cypress E2E Test
name: Cypress App-Builder
on:
pull_request_target:
@ -117,94 +117,80 @@ jobs:
name: screenshots
path: cypress-tests/cypress/screenshots
Cypress-Platform:
Cypress-App-builder-Subpath:
runs-on: ubuntu-22.04
if: ${{ github.event.action == 'labeled' && github.event.label.name == 'run-cypress-workspace' }}
if: ${{ github.event.action == 'labeled' && github.event.label.name == 'run-cypress-app-builder-subpath' }}
steps:
- name: Setup Node.js
uses: actions/setup-node@v2
with:
node-version: 18.3.0
- name: Set up Docker
uses: docker-practice/actions-setup-docker@master
- name: Run PosgtreSQL Database Docker Container
run: |
sudo docker network create tooljet
sudo docker run -d --name postgres -p 5432:5432 -e POSTGRES_PASSWORD=postgres -e POSTGRES_USER=postgres -e POSTGRES_PORT=5432 -d postgres:13
- name: Checkout
uses: actions/checkout@v3
with:
ref: ${{ github.event.pull_request.head.ref }}
- name: Install and build dependencies
# Create Docker Buildx builder with platform configuration
- name: Set up Docker Buildx
run: |
npm cache clean --force
npm install
npm install --prefix server
npm install --prefix frontend
npm run build:plugins
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:cypress
- name: Set up environment variables
run: |
echo "TOOLJET_HOST=http://localhost:8082" >> .env
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=localhost" >> .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" >> .env
echo "TOOLJET_DB=tooljet_db" >> .env
echo "TOOLJET_DB_USER=postgres" >> .env
echo "TOOLJET_DB_HOST=localhost" >> .env
echo "TOOLJET_DB_HOST=postgres" >> .env
echo "TOOLJET_DB_PASS=postgres" >> .env
echo "PGRST_JWT_SECRET=r9iMKoe5CRMgvJBBtp4HrqN7QiPpUToj" >> .env
echo "PGRST_HOST=localhost:3001" >> .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
- name: Set up database
run: |
npm run --prefix server db:create
npm run --prefix server db:reset
npm run --prefix server db:seed
- 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: sleep 5
run: sleep 5
- name: Run docker-compose file
run: docker-compose up -d
- name: Run PostgREST Docker Container
run: |
sudo docker run -d --name postgrest --network tooljet -p 3001:3000 \
-e PGRST_DB_URI="postgres://postgres:postgres@postgres:5432/tooljet" -e PGRST_DB_ANON_ROLE="postgres" -e PGRST_JWT_SECRET="r9iMKoe5CRMgvJBBtp4HrqN7QiPpUToj" \
postgrest/postgrest:v10.1.1.20221215
- name: Checking containers
run: docker ps -a
- name: Run plugins compilation in watch mode
run: cd plugins && npm start &
- name: Run the server
run: cd server && npm run start:dev &
- name: Run the client
run: cd frontend && npm start &
- 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:8082; do
until curl --silent --fail http://localhost:80/apps/tooljet/; do
sleep 5
done'
- name: docker logs
run: sudo docker logs postgrest
- name: Create Cypress environment file
id: create-json
uses: jsdaniell/create-json@1.1.2
@ -213,57 +199,12 @@ jobs:
json: ${{ secrets.CYPRESS_SECRETS }}
dir: "./cypress-tests"
- name: Platform
- name: App Builder subpath
uses: cypress-io/github-action@v5
with:
working-directory: ./cypress-tests
config: "baseUrl=http://localhost:8082"
config-file: cypress-workspace.config.js
- name: Capture Screenshots
uses: actions/upload-artifact@v3
if: always()
with:
name: screenshots
path: cypress-tests/cypress/screenshots
Cypress-Marketplace:
runs-on: ubuntu-22.04
if: ${{ github.event.action == 'labeled' && github.event.label.name == 'run-cypress-marketplace' }}
steps:
- name: Checkout
uses: actions/checkout@v3
with:
ref: ${{ github.event.pull_request.head.ref }}
- name: Setup Node.js
uses: actions/setup-node@v2
with:
node-version: 18.3.0
- name: Checking the PR URL
run: |
timeout 1500 bash -c '
until curl --silent --fail https://tooljet-pr-cypress-${{ env.PR_NUMBER }}.onrender.com; do
sleep 100
done'
- name: Create Cypress environment file
id: create-json
uses: jsdaniell/create-json@1.1.2
with:
name: "cypress.env.json"
json: ${{ secrets.CYPRESS_SECRETS }}
dir: "./cypress-tests"
- name: Marketplace
uses: cypress-io/github-action@v5
with:
working-directory: ./cypress-tests
config: "baseUrl=https://tooljet-pr-cypress-${{ env.PR_NUMBER }}.onrender.com"
config-file: cypress-marketplace.config.js
config: "baseUrl=http://localhost:80/apps/tooljet/"
config-file: cypress-app-builder.config.js
- name: Capture Screenshots
uses: actions/upload-artifact@v3

View file

@ -0,0 +1,201 @@
name: Cypress Marketplace
on:
pull_request_target:
types: [labeled, unlabeled, closed]
workflow_dispatch:
env:
PR_NUMBER: ${{ github.event.number }}
BRANCH_NAME: ${{ github.head_ref || github.ref_name }}
jobs:
Cypress-Marketplace:
runs-on: ubuntu-22.04
if: ${{ github.event.action == 'labeled' && github.event.label.name == 'run-cypress-marketplace' }}
steps:
- name: Checkout
uses: actions/checkout@v3
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:cypress
- 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
- 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; do
sleep 5
done'
- name: Create Cypress environment file
id: create-json
uses: jsdaniell/create-json@1.1.2
with:
name: "cypress.env.json"
json: ${{ secrets.CYPRESS_SECRETS }}
dir: "./cypress-tests"
- name: Marketplace
uses: cypress-io/github-action@v5
with:
working-directory: ./cypress-tests
config: "baseUrl=http://localhost:80"
config-file: cypress-marketplace.config.js
- name: Capture Screenshots
uses: actions/upload-artifact@v3
if: always()
with:
name: screenshots
path: cypress-tests/cypress/screenshots
Cypress-Marketplace-Subpath:
runs-on: ubuntu-22.04
if: ${{ github.event.action == 'labeled' && github.event.label.name == 'run-cypress-marketplace-subpath' }}
steps:
- name: Checkout
uses: actions/checkout@v3
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:cypress
- 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
- 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: Create Cypress environment file
id: create-json
uses: jsdaniell/create-json@1.1.2
with:
name: "cypress.env.json"
json: ${{ secrets.CYPRESS_SECRETS }}
dir: "./cypress-tests"
- name: Marketplace subpath
uses: cypress-io/github-action@v5
with:
working-directory: ./cypress-tests
config: "baseUrl=http://localhost:80/apps/tooljet/"
config-file: cypress-marketplace.config.js
- name: Capture Screenshots
uses: actions/upload-artifact@v3
if: always()
with:
name: screenshots
path: cypress-tests/cypress/screenshots

218
.github/workflows/cypress-platform.yml vendored Normal file
View file

@ -0,0 +1,218 @@
name: Cypress Platform
on:
pull_request_target:
types: [labeled, unlabeled, closed]
workflow_dispatch:
env:
PR_NUMBER: ${{ github.event.number }}
BRANCH_NAME: ${{ github.head_ref || github.ref_name }}
jobs:
Cypress-Platform:
runs-on: ubuntu-22.04
if: ${{ github.event.action == 'labeled' && github.event.label.name == 'run-cypress-workspace' }}
steps:
- name: Setup Node.js
uses: actions/setup-node@v2
with:
node-version: 18.3.0
- name: Set up Docker
uses: docker-practice/actions-setup-docker@master
- name: Run PosgtreSQL Database Docker Container
run: |
sudo docker network create tooljet
sudo docker run -d --name postgres -p 5432:5432 -e POSTGRES_PASSWORD=postgres -e POSTGRES_USER=postgres -e POSTGRES_PORT=5432 -d postgres:13
- name: Checkout
uses: actions/checkout@v3
with:
ref: ${{ github.event.pull_request.head.ref }}
- name: Install and build dependencies
run: |
npm cache clean --force
npm install
npm install --prefix server
npm install --prefix frontend
npm run build:plugins
- name: Set up environment variables
run: |
echo "TOOLJET_HOST=http://localhost:8082" >> .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=localhost" >> .env
echo "PG_PASS=postgres" >> .env
echo "PG_PORT=5432" >> .env
echo "ENABLE_TOOLJET_DB=true" >> .env
echo "TOOLJET_DB=tooljet" >> .env
echo "TOOLJET_DB_USER=postgres" >> .env
echo "TOOLJET_DB_HOST=localhost" >> .env
echo "TOOLJET_DB_PASS=postgres" >> .env
echo "PGRST_JWT_SECRET=r9iMKoe5CRMgvJBBtp4HrqN7QiPpUToj" >> .env
echo "PGRST_HOST=localhost:3001" >> .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
- name: Set up database
run: |
npm run --prefix server db:create
npm run --prefix server db:reset
npm run --prefix server db:seed
- name: sleep 5
run: sleep 5
- name: Run PostgREST Docker Container
run: |
sudo docker run -d --name postgrest --network tooljet -p 3001:3000 \
-e PGRST_DB_URI="postgres://postgres:postgres@postgres:5432/tooljet" -e PGRST_DB_ANON_ROLE="postgres" -e PGRST_JWT_SECRET="r9iMKoe5CRMgvJBBtp4HrqN7QiPpUToj" \
postgrest/postgrest:v10.1.1.20221215
- name: Run plugins compilation in watch mode
run: cd plugins && npm start &
- name: Run the server
run: cd server && npm run start:dev &
- name: Run the client
run: cd frontend && npm start &
- name: Wait for the server to be ready
run: |
timeout 1500 bash -c '
until curl --silent --fail http://localhost:8082; do
sleep 5
done'
- name: docker logs
run: sudo docker logs postgrest
- name: Create Cypress environment file
id: create-json
uses: jsdaniell/create-json@1.1.2
with:
name: "cypress.env.json"
json: ${{ secrets.CYPRESS_SECRETS }}
dir: "./cypress-tests"
- name: Platform
uses: cypress-io/github-action@v5
with:
working-directory: ./cypress-tests
config: "baseUrl=http://localhost:8082"
config-file: cypress-workspace.config.js
- name: Capture Screenshots
uses: actions/upload-artifact@v3
if: always()
with:
name: screenshots
path: cypress-tests/cypress/screenshots
Cypress-Platform-subpath:
runs-on: ubuntu-22.04
if: ${{ github.event.action == 'labeled' && github.event.label.name == 'run-cypress-workspace-subpath' }}
steps:
- name: Checkout
uses: actions/checkout@v3
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:cypress
- 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
- 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: Create Cypress environment file
id: create-json
uses: jsdaniell/create-json@1.1.2
with:
name: "cypress.env.json"
json: ${{ secrets.CYPRESS_SECRETS }}
dir: "./cypress-tests"
- name: Platform-subpath
uses: cypress-io/github-action@v5
with:
working-directory: ./cypress-tests
config: "baseUrl=http://localhost:80/apps/tooljet/"
config-file: cypress-workspace.config.js
- name: Capture Screenshots
uses: actions/upload-artifact@v3
if: always()
with:
name: screenshots
path: cypress-tests/cypress/screenshots

View file

@ -1,351 +0,0 @@
name: Render cypress app deploy
on:
pull_request_target:
types: [labeled, unlabeled, closed]
env:
PR_NUMBER: ${{ github.event.number }}
BRANCH_NAME: ${{ github.head_ref || github.ref_name }}
permissions:
pull-requests: write
issues: write
jobs:
create-review-cypress-app:
if: ${{ github.event.action == 'labeled' && github.event.label.name == 'create-review-cypress-app' }}
runs-on: ubuntu-latest
steps:
- name: Create deployment
id: create-deployment
run: |
export RESPONSE=$(curl --request POST \
--url https://api.render.com/v1/services \
--header 'accept: application/json' \
--header 'content-type: application/json' \
--header 'Authorization: Bearer ${{ secrets.RENDER_API_KEY }}' \
--data '
{
"autoDeploy": "yes",
"branch": "${{ env.BRANCH_NAME }}",
"name": "ToolJet PR CYPRESS #${{ env.PR_NUMBER }}",
"notifyOnFail": "default",
"ownerId": "tea-caeo4bj19n072h3dddc0",
"repo": "${{ github.event.pull_request.head.repo.git_url }}",
"slug": "tooljet-pr-cypress-${{ env.PR_NUMBER }}",
"suspended": "not_suspended",
"suspenders": [],
"type": "web_service",
"envVars": [
{
"key": "PG_HOST",
"value": "${{ secrets.RENDER_PG_HOST }}"
},
{
"key": "PG_PORT",
"value": "5432"
},
{
"key": "PG_USER",
"value": "${{ secrets.RENDER_PG_USER }}"
},
{
"key": "PG_PASS",
"value": "${{ secrets.RENDER_PG_PASS }}"
},
{
"key": "PG_DB",
"value": "${{ env.PR_NUMBER }}_cypress"
},
{
"key": "ENABLE_TOOLJET_DB",
"value": "true"
},
{
"key": "TOOLJET_DB",
"value": "${{ env.PR_NUMBER }}_cypress"
},
{
"key": "TOOLJET_DB_HOST",
"value": "${{ secrets.RENDER_PG_HOST }}"
},
{
"key": "TOOLJET_DB_USER",
"value": "${{ secrets.RENDER_PG_USER }}"
},
{
"key": "TOOLJET_DB_PASS",
"value": "${{ secrets.RENDER_PG_PASS }}"
},
{
"key": "TOOLJET_DB_PORT",
"value": "5432"
},
{
"key": "PGRST_DB_URI",
"value": "postgres://${{ secrets.RENDER_PG_USER }}:${{ secrets.RENDER_PG_PASS }}@${{ secrets.RENDER_PG_HOST }}/${{ env.PR_NUMBER }}_cypress"
},
{
"key": "PGRST_HOST",
"value": "127.0.0.1:3000"
},
{
"key": "PGRST_JWT_SECRET",
"value": "r9iMKoe5CRMgvJBBtp4HrqN7QiPpUToj"
},
{
"key": "PGRST_LOG_LEVEL",
"value": "info"
},
{
"key": "PORT",
"value": "80"
},
{
"key": "TOOLJET_HOST",
"value": "https://tooljet-pr-cypress-${{ env.PR_NUMBER }}.onrender.com"
},
{
"key": "DISABLE_TOOLJET_TELEMETRY",
"value": "true"
},
{
"key": "SMTP_ADDRESS",
"value": "smtp.mailtrap.io"
},
{
"key": "SMTP_DOMAIN",
"value": "smtp.mailtrap.io"
},
{
"key": "SMTP_PORT",
"value": "2525"
},
{
"key": "SMTP_USERNAME",
"value": "${{ secrets.RENDER_SMTP_USERNAME }}"
},
{
"key": "SMTP_PASSWORD",
"value": "${{ secrets.RENDER_SMTP_PASSWORD }}"
},
{
"key": "ENABLE_MARKETPLACE_FEATURE",
"value": "true"
},
{
"key": "SSO_GIT_OAUTH2_CLIENT_ID",
"value": "dummy"
},
{
"key": "SSO_GIT_OAUTH2_CLIENT_SECRET",
"value": "dummy"
},
{
"key": "SSO_GIT_OAUTH2_HOST",
"value": "dummy"
},
{
"key": "SSO_GOOGLE_OAUTH2_CLIENT_ID",
"value": "dummy"
}
],
"serviceDetails": {
"disk": null,
"env": "docker",
"envSpecificDetails": {
"dockerCommand": "",
"dockerContext": "./",
"dockerfilePath": "./docker/preview.Dockerfile"
},
"healthCheckPath": "/api/health",
"numInstances": 1,
"openPorts": [{
"port": 80,
"protocol": "TCP"
}],
"plan": "pro",
"pullRequestPreviewsEnabled": "no",
"region": "oregon",
"url": "https://tooljet-pr-cypress-${{ env.PR_NUMBER }}.onrender.com"
}
}')
echo "response: $RESPONSE"
export SERVICE_ID=$(echo $RESPONSE | jq -r '.service.id')
echo "SERVICE_ID=$SERVICE_ID" >> $GITHUB_ENV
- name: Comment deployment URL
uses: actions/github-script@v5
with:
github-token: ${{secrets.GITHUB_TOKEN}}
script: |
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: 'Deployment: https://tooljet-pr-cypress-${{ env.PR_NUMBER }}.onrender.com \n Dashboard: https://dashboard.render.com/web/${{ env.SERVICE_ID }}'
})
- uses: actions/github-script@v6
with:
script: |
try {
await github.rest.issues.removeLabel({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
name: 'create-review-cypress-app'
})
} catch (e) {
console.log(e)
}
await github.rest.issues.addLabels({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
labels: ['active-review-cypress-app']
})
destroy-review-cypress-app:
if: ${{ (github.event.action == 'labeled' && github.event.label.name == 'destroy-review-cypress-app') || github.event.action == 'closed' }}
runs-on: ubuntu-latest
steps:
- name: Delete service
run: |
export SERVICE_ID=$(curl --request GET \
--url 'https://api.render.com/v1/services?name=ToolJet%20PR%20CYPRESS%20%23${{ env.PR_NUMBER }}&limit=1' \
--header 'accept: application/json' \
--header 'authorization: Bearer ${{ secrets.RENDER_API_KEY }}' | \
jq -r '.[0].service.id')
curl --request DELETE \
--url https://api.render.com/v1/services/$SERVICE_ID \
--header 'accept: application/json' \
--header 'authorization: Bearer ${{ secrets.RENDER_API_KEY }}'
- uses: actions/github-script@v6
with:
script: |
try {
await github.rest.issues.removeLabel({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
name: 'destroy-review-cypress-app'
})
} catch (e) {
console.log(e)
}
try {
await github.rest.issues.removeLabel({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
name: 'suspend-review-cypress-app'
})
} catch (e) {
console.log(e)
}
try {
await github.rest.issues.removeLabel({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
name: 'active-review-cypress-app'
})
} catch (e) {
console.log(e)
}
- name: Install PostgreSQL client
run: |
sudo apt update
sudo apt install postgresql-client -y
- name: Wait after installing PostgreSQL
run: sleep 25
- name: Drop PostgreSQL PR database
env:
PGHOST: ${{ secrets.RENDER_DS_PG_HOST }}
PGPORT: 5432
PGUSER: ${{ secrets.RENDER_DS_PG_USER }}
PGDATABASE: ${{ env.PR_NUMBER }}_cypress
run: |
PGPASSWORD=${{ secrets.RENDER_DS_PG_PASS }} psql -h $PGHOST -p $PGPORT -U $PGUSER -d postgres -c "drop database \"$PGDATABASE\" ;"
suspend-review-cypress-app:
if: ${{ github.event.action == 'labeled' && github.event.label.name == 'suspend-review-cypress-app' }}
runs-on: ubuntu-latest
steps:
- name: Suspend service
run: |
export SERVICE_ID=$(curl --request GET \
--url 'https://api.render.com/v1/services?name=ToolJet%20PR%20CYPRESS%20%23${{ env.PR_NUMBER }}&limit=1' \
--header 'accept: application/json' \
--header 'authorization: Bearer ${{ secrets.RENDER_API_KEY }}' | \
jq -r '.[0].service.id')
curl --request POST \
--url https://api.render.com/v1/services/$SERVICE_ID/suspend \
--header 'accept: application/json' \
--header 'authorization: Bearer ${{ secrets.RENDER_API_KEY }}'
- uses: actions/github-script@v6
with:
script: |
try {
await github.rest.issues.removeLabel({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
name: 'active-review-cypress-app'
})
} catch (e) {
console.log(e)
}
resume-review-cypress-app:
if: ${{ github.event.action == 'unlabeled' && github.event.label.name == 'suspend-review-cypress-app' }}
runs-on: ubuntu-latest
steps:
- name: Resume service
run: |
export SERVICE_ID=$(curl --request GET \
--url 'https://api.render.com/v1/services?name=ToolJet%20PR%20CYPRESS%20%23${{ env.PR_NUMBER }}&limit=1' \
--header 'accept: application/json' \
--header 'authorization: Bearer ${{ secrets.RENDER_API_KEY }}' | \
jq -r '.[0].service.id')
curl --request POST \
--url https://api.render.com/v1/services/$SERVICE_ID/resume \
--header 'accept: application/json' \
--header 'authorization: Bearer ${{ secrets.RENDER_API_KEY }}'
- uses: actions/github-script@v6
with:
script: |
await github.rest.issues.addLabels({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
labels: ['active-review-cypress-app']
})
try {
await github.rest.issues.removeLabel({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
name: 'suspend-review-cypress-app'
})
} catch (e) {
console.log(e)
}

View file

@ -1,45 +0,0 @@
name: Label for stale render cypress app deploy
on:
workflow_dispatch:
schedule:
- cron: '0 0 * * *'
permissions:
issues: write
jobs:
label-stale-deploys:
runs-on: ubuntu-latest
permissions:
pull-requests: write
steps:
- uses: akshaysasidrn/stale-label-fetch@v1.1
id: stale-label
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
stale-label: 'active-review-cypress-app'
stale-time: '86400'
type: 'pull_request'
- name: Get stale numbers
run: echo "Matched PR numbers - ${{ steps.stale-label.outputs.stale-numbers }}"
- name: Add suspend label
uses: actions/github-script@v6
env:
STALE_NUMBERS: ${{ steps.stale-label.outputs.stale-numbers }}
with:
github-token: ${{ secrets.TJ_BOT_PAT }}
script: |
if (!process.env.STALE_NUMBERS) return
const prNumbers = process.env.STALE_NUMBERS.split(",")
console.log(`Adding suspend labels for: ${prNumbers}`)
for (const prNumber of prNumbers) {
github.rest.issues.addLabels({
issue_number: prNumber,
owner: context.repo.owner,
repo: context.repo.repo,
labels: ['suspend-review-cypress-app']
})
}

View file

@ -1 +1 @@
2.19.2
2.20.1

View file

@ -0,0 +1,79 @@
---
id: saml
title: SAML
---
ToolJet supports SAML authentication for your workspace. The supported SAML providers are: Okta, Active Directory Federation Services, Azure AD, Auth0 and other SAML SSO providers.
### Configuring SAML
To enable SAML authentication, you need to configure the following workspace settings:
1. Go to **Workspace Settings** > **SSO** > **SAML**.
<div style={{textAlign: 'center'}}>
<img className="screenshot-full" src="/img/sso/saml/workspaceset.png" alt="SSO :SAMP" />
</div>
2. By default, SAML is disabled. Toggle it on to enable SAML authentication.
<div style={{textAlign: 'center'}}>
<img className="screenshot-full" src="/img/sso/saml/enable.png" alt="SSO :SAMP" />
</div>
3. Enter the following configuration details:
- **SAML Provider Name**: Enter the name of your SAML provider. This name will be displayed on the login page.
- **Identity provider metadata**: Upload the data from the metadata file provided by your SAML provider. This file contains the SAML configuration details.
- **Group Attribute**: Enter the name of the attribute that contains the group information of the user. This attribute is used to map the user to the appropriate group.
- **Redirect URL**: Copy the redirect URL provided and paste it in the SAML provider's configuration page.
:::tip Downloading the metadata from your identity provider
Generally, the metadata is available in the form of an XML file which can be downloaded from your identity provider's dashboard.
Copy the metadata from the XML file and paste it into the ToolJet's SAML SSO configuration settings. Please ensure that the metadata is pasted in the correct format, as it contains essential configuration details from the identity provider necessary for authentication.
Additionally, you can often find this data by navigating to https://&ltyour-identity-provider&gt/federationmetadata/2007-06/federationmetadata.xml
:::
<div style={{textAlign: 'center'}}>
<img className="screenshot-full" src="/img/sso/saml/config.png" alt="SSO :SAMP" />
</div>
4. Once configured, click **Save Changes**.
### Logging in with SAML
1. Go to the **[General Settings](/docs/user-authentication/general-settings)** and copy the **Login URL** provided. Furthermore, you have the flexibility to choose whether to turn on 'Enable Signups,' allowing users to signup without an invite. Through SSO authentication, we check if the user already exists; if so, they can sign in seamlessly. Otherwise, an error will be displayed. Conversely, with this option disabled, only invited users can log in, provided SSO authentication is successful.
<div style={{textAlign: 'center'}}>
<img className="screenshot-full" src="/img/sso/saml/url.png" alt="SSO :SAML"/>
</div>
2. The **Login URL** obtained can be used to access the workspace. Please note that ToolJet supports SAML login at the workspace level, ensuring users are logged in specifically to the selected workspace.
As a result, users can now log in to your workspace using the provided Login URL. The login page will prominently feature the name of the SAML provider configured in your workspace settings.
<div style={{textAlign: 'center'}}>
<img className="screenshot-full" src="/img/sso/saml/login.png" alt="SSO :SAMP" />
</div>
3. Click on **Sign in with `SAML Name`** button and you will be redirected to the SAML provider's login page.
<div style={{textAlign: 'center'}}>
<img className="screenshot-full" src="/img/sso/saml/auth.png" alt="SSO :SAMP" />
</div>
4. Enter your credentials and click **Login**. If the user is signing in for the first time, they will be redirected to the ToolJet's onboarding page.

View file

@ -271,6 +271,7 @@ const sidebars = {
],
},
'user-authentication/sso/ldap',
'user-authentication/sso/saml',
],
},
],

BIN
docs/static/img/sso/saml/auth.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 192 KiB

BIN
docs/static/img/sso/saml/config.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 431 KiB

BIN
docs/static/img/sso/saml/enable.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

BIN
docs/static/img/sso/saml/login.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 174 KiB

BIN
docs/static/img/sso/saml/url.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 367 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 102 KiB

View file

@ -0,0 +1,79 @@
---
id: saml
title: SAML
---
ToolJet supports SAML authentication for your workspace. The supported SAML providers are: Okta, Active Directory Federation Services, Azure AD, Auth0 and other SAML SSO providers.
### Configuring SAML
To enable SAML authentication, you need to configure the following workspace settings:
1. Go to **Workspace Settings** > **SSO** > **SAML**.
<div style={{textAlign: 'center'}}>
<img className="screenshot-full" src="/img/sso/saml/workspaceset.png" alt="SSO :SAMP" />
</div>
2. By default, SAML is disabled. Toggle it on to enable SAML authentication.
<div style={{textAlign: 'center'}}>
<img className="screenshot-full" src="/img/sso/saml/enable.png" alt="SSO :SAMP" />
</div>
3. Enter the following configuration details:
- **SAML Provider Name**: Enter the name of your SAML provider. This name will be displayed on the login page.
- **Identity provider metadata**: Upload the data from the metadata file provided by your SAML provider. This file contains the SAML configuration details.
- **Group Attribute**: Enter the name of the attribute that contains the group information of the user. This attribute is used to map the user to the appropriate group.
- **Redirect URL**: Copy the redirect URL provided and paste it in the SAML provider's configuration page.
:::tip Downloading the metadata from your identity provider
Generally, the metadata is available in the form of an XML file which can be downloaded from your identity provider's dashboard.
Copy the metadata from the XML file and paste it into the ToolJet's SAML SSO configuration settings. Please ensure that the metadata is pasted in the correct format, as it contains essential configuration details from the identity provider necessary for authentication.
Additionally, you can often find this data by navigating to https://&ltyour-identity-provider&gt/federationmetadata/2007-06/federationmetadata.xml
:::
<div style={{textAlign: 'center'}}>
<img className="screenshot-full" src="/img/sso/saml/config.png" alt="SSO :SAMP" />
</div>
4. Once configured, click **Save Changes**.
### Logging in with SAML
1. Go to the **[General Settings](/docs/user-authentication/general-settings)** and copy the **Login URL** provided. Furthermore, you have the flexibility to choose whether to turn on 'Enable Signups,' allowing users to signup without an invite. Through SSO authentication, we check if the user already exists; if so, they can sign in seamlessly. Otherwise, an error will be displayed. Conversely, with this option disabled, only invited users can log in, provided SSO authentication is successful.
<div style={{textAlign: 'center'}}>
<img className="screenshot-full" src="/img/sso/saml/url.png" alt="SSO :SAML"/>
</div>
2. The **Login URL** obtained can be used to access the workspace. Please note that ToolJet supports SAML login at the workspace level, ensuring users are logged in specifically to the selected workspace.
As a result, users can now log in to your workspace using the provided Login URL. The login page will prominently feature the name of the SAML provider configured in your workspace settings.
<div style={{textAlign: 'center'}}>
<img className="screenshot-full" src="/img/sso/saml/login.png" alt="SSO :SAMP" />
</div>
3. Click on **Sign in with `SAML Name`** button and you will be redirected to the SAML provider's login page.
<div style={{textAlign: 'center'}}>
<img className="screenshot-full" src="/img/sso/saml/auth.png" alt="SSO :SAMP" />
</div>
4. Enter your credentials and click **Login**. If the user is signing in for the first time, they will be redirected to the ToolJet's onboarding page.

View file

@ -260,7 +260,8 @@
"user-authentication/sso/openid/google-openid"
]
},
"user-authentication/sso/ldap"
"user-authentication/sso/ldap",
"user-authentication/sso/saml"
]
}
]
@ -421,4 +422,4 @@
]
}
]
}
}

View file

@ -1 +1 @@
2.19.2
2.20.1

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 85 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 81 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 85 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 239 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 238 KiB

View file

@ -1,5 +1,6 @@
import React, { useState, useEffect } from 'react';
import { ButtonSolid } from '@/_ui/AppButton/AppButton';
import Skeleton, { SkeletonTheme } from 'react-loading-skeleton';
export const Pagination = function Pagination({
onPageIndexChanged,
@ -16,6 +17,7 @@ export const Pagination = function Pagination({
// eslint-disable-next-line no-unused-vars
darkMode,
tableWidth,
loadingState,
}) {
const [pageCount, setPageCount] = useState(autoPageCount);
@ -50,6 +52,16 @@ export const Pagination = function Pagination({
gotoPage(pageIndex - 1);
}
if (loadingState) {
return (
<div className="w-100">
<SkeletonTheme baseColor="var(--slate3)" width="100%">
<Skeleton count={1} width={'100%'} height={28} className="mb-1" />
</SkeletonTheme>
</div>
);
}
return (
<div className="pagination-container d-flex h-100 align-items-center custom-gap-4" data-cy="pagination-section">
<div className="d-flex">

View file

@ -1547,15 +1547,7 @@ export function Table({
))}
</div>
<div className={`col d-flex justify-content-center h-100 ${loadingState && 'w-100'}`}>
{loadingState && (
<div className="w-100">
<SkeletonTheme baseColor="var(--slate3)" width="100%">
<Skeleton count={1} width={'100%'} height={28} className="mb-1" />
</SkeletonTheme>
</div>
)}
{enablePagination && !loadingState && (
{enablePagination && (
<Pagination
lastActivePageIndex={pageIndex}
serverSide={serverSidePagination}
@ -1570,6 +1562,7 @@ export function Table({
enablePrevButton={enablePrevButton}
darkMode={darkMode}
tableWidth={width}
loadingState={loadingState}
/>
)}
</div>

View file

@ -689,7 +689,7 @@ export const Container = ({
our&nbsp;
<a
className="color-indigo9 "
href="https://docs.tooljet.com/docs#the-very-quick-quickstart"
href="https://docs.tooljet.com/docs/#quickstart-guide"
target="_blank"
rel="noreferrer"
>

View file

@ -63,7 +63,7 @@ export default function TemplateLibraryModal(props) {
toast.success('App created.', {
position: 'top-center',
});
navigate(`/${getWorkspaceId()}/apps/${data.id}`);
navigate(`/${getWorkspaceId()}/apps/${data.app[0].id}`);
})
.catch((e) => {
toast.error(e.error, {

View file

@ -1 +1 @@
2.19.2
2.20.1

View file

@ -21,9 +21,8 @@ export class LibraryAppsController {
if (!ability.can('createApp', App)) {
throw new ForbiddenException('You do not have permissions to perform this action');
}
const newApp = await this.libraryAppCreationService.perform(user, identifier);
return newApp;
const result = await this.libraryAppCreationService.perform(user, identifier);
return result;
}
@Get()

View file

@ -48,5 +48,6 @@ if (process.env.ENABLE_TOOLJET_DB === 'true') {
CredentialsService,
PostgrestProxyService,
],
exports: [ImportExportResourcesService],
})
export class ImportExportResourcesModule {}

View file

@ -16,9 +16,14 @@ import { PluginsService } from '@services/plugins.service';
import { Plugin } from 'src/entities/plugin.entity';
import { PluginsHelper } from 'src/helpers/plugins.helper';
import { AppEnvironmentService } from '@services/app_environments.service';
import { ImportExportResourcesModule } from '../import_export_resources/import_export_resources.module';
@Module({
imports: [TypeOrmModule.forFeature([App, Credential, File, Plugin, DataSource]), CaslModule],
imports: [
TypeOrmModule.forFeature([App, Credential, File, Plugin, DataSource]),
CaslModule,
ImportExportResourcesModule,
],
providers: [
EncryptionService,
CredentialsService,

View file

@ -1,30 +1,63 @@
import { BadRequestException, Injectable } from '@nestjs/common';
import { App } from '../entities/app.entity';
import { User } from '../entities/user.entity';
import { AppImportExportService } from './app_import_export.service';
import { readFileSync } from 'fs';
import { Logger } from 'nestjs-pino';
import { ImportExportResourcesService } from './import_export_resources.service';
import { ImportResourcesDto } from '@dto/import-resources.dto';
import { AppImportExportService } from './app_import_export.service';
@Injectable()
export class LibraryAppCreationService {
constructor(private readonly appImportExportService: AppImportExportService, private readonly logger: Logger) {}
constructor(
private readonly importExportResourcesService: ImportExportResourcesService,
private readonly appImportExportService: AppImportExportService,
private readonly logger: Logger
) {}
async perform(currentUser: User, identifier: string): Promise<App> {
const newApp = await this.appImportExportService.import(currentUser, this.findAppDefinition(identifier));
async perform(currentUser: User, identifier: string) {
const templateDefinition = this.findTemplateDefinition(identifier);
const importDto = new ImportResourcesDto();
importDto.organization_id = currentUser.organizationId;
importDto.app = templateDefinition.app || templateDefinition.appV2;
importDto.tooljet_database = templateDefinition.tooljet_database;
return newApp;
if (this.isVersionGreaterThanOrEqual(templateDefinition.tooljet_version, '2.16.0')) {
return await this.importExportResourcesService.import(currentUser, importDto);
} else {
const importedApp = await this.appImportExportService.import(currentUser, templateDefinition);
return {
app: [importedApp],
tooljet_database: [],
};
}
}
findAppDefinition(identifier: string) {
let appDefinition: object;
findTemplateDefinition(identifier: string) {
try {
appDefinition = JSON.parse(readFileSync(`templates/${identifier}/definition.json`, 'utf-8'));
return JSON.parse(readFileSync(`templates/${identifier}/definition.json`, 'utf-8'));
} catch (err) {
this.logger.error(err);
throw new BadRequestException('App definition not found');
}
}
return appDefinition;
isVersionGreaterThanOrEqual(version1: string, version2: string) {
if (!version1) return false;
const v1Parts = version1.split('-')[0].split('.').map(Number);
const v2Parts = version2.split('-')[0].split('.').map(Number);
for (let i = 0; i < Math.max(v1Parts.length, v2Parts.length); i++) {
const v1Part = +v1Parts[i] || 0;
const v2Part = +v2Parts[i] || 0;
if (v1Part < v2Part) {
return false;
} else if (v1Part > v2Part) {
return true;
}
}
return true;
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,13 @@
{
"name": "Customer support admin",
"description": "The Customer Support Admin template streamlines support with a Main Dashboard for ticket management and All Contacts for maintaining customer data.",
"widgets": ["Table", "Chart"],
"sources": [
{
"name": "Tooljet Database",
"id": "tooljetdb"
}
],
"id": "customer-support-admin",
"category": "operations"
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,13 @@
{
"name": "Customer ticketing form",
"description": "The Customer Ticketing Form optimizes support ticket management, seamlessly gathering customer info and tracking ticket progress with deep integration into Customer Support Admin.",
"widgets": ["Table", "Chart"],
"sources": [
{
"name": "Tooljet Database",
"id": "tooljetdb"
}
],
"id": "customer-ticketing-form",
"category": "operations"
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,13 @@
{
"name": "Inventory management",
"description": "Easily manage, control, and optimise your inventory with our single-page Inventory Management Template.",
"widgets": ["Table", "Chart"],
"sources": [
{
"name": "Tooljet Database",
"id": "tooljetdb"
}
],
"id": "inventory-management",
"category": "operations"
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,13 @@
{
"name": "Lead management system",
"description": "The Lead Management System template streamlines lead lifecycle with four status templates: Leads (capturing potential leads) and Opportunities (converting leads), along with Customers (effective relationship management) and Lost (learning from lost opportunities).",
"widgets": ["Table", "Chart"],
"sources": [
{
"name": "Tooljet Database",
"id": "tooljetdb"
}
],
"id": "lead-management-system",
"category": "sales"
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,13 @@
{
"name": "Sales analytics dashboard",
"description": "The Sales Analytics Dashboard template offers comprehensive sales monitoring and insights with four key sections: Main Dashboard (critical metrics), Orders (order details), Customers (demographics & history), and Products (product performance).",
"widgets": ["Table", "Chart"],
"sources": [
{
"name": "Tooljet Database",
"id": "tooljetdb"
}
],
"id": "sales-analytics-dashboard",
"category": "sales"
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,13 @@
{
"name": "Supply chain management",
"description": "The Supply Chain Management template optimizes operations with a Main Dashboard for KPIs, Product Inventory for stock management, and All Orders for tracking and updates.",
"widgets": ["Table", "Chart"],
"sources": [
{
"name": "Tooljet Database",
"id": "tooljetdb"
}
],
"id": "supply-chain-management",
"category": "operations"
}

View file

@ -42,12 +42,12 @@ describe('library apps controller', () => {
response = await request(app.getHttpServer())
.post('/api/library_apps')
.send({ identifier: 'github-contributors' })
.send({ identifier: 'supply-chain-management' })
.set('tj-workspace-id', adminUserData.user.defaultOrganizationId)
.set('Cookie', adminUserData['tokenCookie']);
expect(response.statusCode).toBe(201);
expect(response.body.name).toContain('GitHub Contributor Leaderboard');
expect(response.body.app[0].name).toContain('Supply Chain Management');
});
it('should return error if template identifier is not found', async () => {