mirror of
https://github.com/ToolJet/ToolJet
synced 2026-05-23 00:48:25 +00:00
Merge branch 'main' into fix/external-epi
This commit is contained in:
commit
3d697f08b1
27 changed files with 550 additions and 415 deletions
68
.github/workflows/cypress-appbuilder.yml
vendored
68
.github/workflows/cypress-appbuilder.yml
vendored
|
|
@ -13,16 +13,18 @@ jobs:
|
|||
Cypress-App-Builder:
|
||||
runs-on: ubuntu-22.04
|
||||
if: |
|
||||
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')
|
||||
contains(github.event.pull_request.labels.*.name, 'run-cypress-app-builder-ce') ||
|
||||
contains(github.event.pull_request.labels.*.name, 'run-cypress-app-builder-ee') ||
|
||||
contains(github.event.pull_request.labels.*.name, 'run-cypress') ||
|
||||
contains(github.event.pull_request.labels.*.name, 'run-cypress-ce')
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
edition: >-
|
||||
${{
|
||||
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-app-builder-ce') && fromJson('["ce"]') ||
|
||||
contains(github.event.pull_request.labels.*.name, 'run-cypress-ce') && fromJson('["ce"]') ||
|
||||
contains(github.event.pull_request.labels.*.name, 'run-cypress-app-builder-ee') && fromJson('["ee"]') ||
|
||||
contains(github.event.pull_request.labels.*.name, 'run-cypress') && fromJson('["ce", "ee"]') ||
|
||||
fromJson('[]')
|
||||
}}
|
||||
|
|
@ -158,35 +160,35 @@ jobs:
|
|||
name: screenshots-appbuilder-${{ matrix.edition }}
|
||||
path: cypress-tests/cypress/screenshots
|
||||
|
||||
Cypress-App-builder-Subpath:
|
||||
runs-on: ubuntu-22.04
|
||||
if: contains(github.event.pull_request.labels.*.name, 'run-cypress') ||
|
||||
contains(github.event.pull_request.labels.*.name, 'run-cypress-app-builder-subpath')
|
||||
# Cypress-App-builder-Subpath:
|
||||
# runs-on: ubuntu-22.04
|
||||
# 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
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.ref }}
|
||||
# steps:
|
||||
# - name: Checkout
|
||||
# uses: actions/checkout@v3
|
||||
# with:
|
||||
# ref: ${{ github.event.pull_request.head.ref }}
|
||||
|
||||
- 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: 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: App Builder subpath
|
||||
uses: cypress-io/github-action@v5
|
||||
with:
|
||||
working-directory: ./cypress-tests
|
||||
config: "baseUrl=http://localhost:80/apps/tooljet/"
|
||||
config-file: cypress-app-builder.config.js
|
||||
# - name: App Builder subpath
|
||||
# uses: cypress-io/github-action@v5
|
||||
# with:
|
||||
# working-directory: ./cypress-tests
|
||||
# config: "baseUrl=http://localhost:80/apps/tooljet/"
|
||||
# config-file: cypress-app-builder.config.js
|
||||
|
||||
- name: Capture Screenshots
|
||||
uses: actions/upload-artifact@v4
|
||||
if: always()
|
||||
with:
|
||||
name: screenshots
|
||||
path: cypress-tests/cypress/screenshots
|
||||
# - name: Capture Screenshots
|
||||
# uses: actions/upload-artifact@v4
|
||||
# if: always()
|
||||
# with:
|
||||
# name: screenshots
|
||||
# path: cypress-tests/cypress/screenshots
|
||||
|
|
|
|||
10
.github/workflows/cypress-marketplace.yml
vendored
10
.github/workflows/cypress-marketplace.yml
vendored
|
|
@ -15,16 +15,18 @@ jobs:
|
|||
runs-on: ubuntu-22.04
|
||||
|
||||
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')
|
||||
contains(github.event.pull_request.labels.*.name, 'run-cypress-marketplace-ce') ||
|
||||
contains(github.event.pull_request.labels.*.name, 'run-cypress-marketplace-ee') ||
|
||||
contains(github.event.pull_request.labels.*.name, 'run-cypress-ce')
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
edition: >-
|
||||
${{
|
||||
contains(github.event.pull_request.labels.*.name, 'run-cypress') && fromJson('["ce", "ee"]') ||
|
||||
contains(github.event.pull_request.labels.*.name, 'run-ce-cypress-marketplace') && fromJson('["ce"]') ||
|
||||
contains(github.event.pull_request.labels.*.name, 'run-ee-cypress-marketplace') && fromJson('["ee"]') ||
|
||||
contains(github.event.pull_request.labels.*.name, 'run-cypress-ce') && fromJson('["ce"]') ||
|
||||
contains(github.event.pull_request.labels.*.name, 'run-cypress-marketplace-ce') && fromJson('["ce"]') ||
|
||||
contains(github.event.pull_request.labels.*.name, 'run-cypress-marketplace-ee') && fromJson('["ee"]') ||
|
||||
fromJson('[]')
|
||||
}}
|
||||
|
||||
|
|
|
|||
11
.github/workflows/cypress-platform.yml
vendored
11
.github/workflows/cypress-platform.yml
vendored
|
|
@ -13,15 +13,18 @@ jobs:
|
|||
Cypress-Platform:
|
||||
runs-on: ubuntu-22.04
|
||||
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')
|
||||
contains(github.event.pull_request.labels.*.name, 'run-cypress-platform-ce') ||
|
||||
contains(github.event.pull_request.labels.*.name, 'run-cypress-platform-ee') ||
|
||||
contains(github.event.pull_request.labels.*.name, 'run-cypress-ce')
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
edition: >-
|
||||
${{
|
||||
contains(github.event.pull_request.labels.*.name, 'run-cypress') && fromJson('["ce", "ee"]') ||
|
||||
contains(github.event.pull_request.labels.*.name, 'run-ce-cypress-platform') && fromJson('["ce"]') ||
|
||||
contains(github.event.pull_request.labels.*.name, 'run-ee-cypress-platform') && fromJson('["ee"]') ||
|
||||
contains(github.event.pull_request.labels.*.name, 'run-cypress-ce') && fromJson('["ce"]') ||
|
||||
contains(github.event.pull_request.labels.*.name, 'run-cypress-platform-ce') && fromJson('["ce"]') ||
|
||||
contains(github.event.pull_request.labels.*.name, 'run-cypress-platform-ee') && fromJson('["ee"]') ||
|
||||
fromJson('[]')
|
||||
}}
|
||||
|
||||
|
|
|
|||
138
.github/workflows/render-preview-deploy.yml
vendored
138
.github/workflows/render-preview-deploy.yml
vendored
|
|
@ -80,7 +80,7 @@ jobs:
|
|||
},
|
||||
{
|
||||
"key": "PG_USER",
|
||||
"value": "tooljet"
|
||||
"value": "postgres"
|
||||
},
|
||||
{
|
||||
"key": "PG_PASS",
|
||||
|
|
@ -100,7 +100,7 @@ jobs:
|
|||
},
|
||||
{
|
||||
"key": "TOOLJET_DB_USER",
|
||||
"value": "tooljet"
|
||||
"value": "postgres"
|
||||
},
|
||||
{
|
||||
"key": "TOOLJET_DB_PASS",
|
||||
|
|
@ -116,7 +116,7 @@ jobs:
|
|||
},
|
||||
{
|
||||
"key": "PGRST_DB_URI",
|
||||
"value": "postgres://tooljet:postgres@localhost/${{ env.PR_NUMBER }}-ce-tjdb"
|
||||
"value": "postgres://postgres:postgres@localhost/${{ env.PR_NUMBER }}-ce-tjdb"
|
||||
},
|
||||
{
|
||||
"key": "PGRST_HOST",
|
||||
|
|
@ -168,7 +168,11 @@ jobs:
|
|||
}
|
||||
],
|
||||
"serviceDetails": {
|
||||
"disk": null,
|
||||
"disk": {
|
||||
"name": "tooljet-ce-pr-${{ env.PR_NUMBER }}-postgresql",
|
||||
"mountPath": "/data",
|
||||
"sizeGB": 10
|
||||
},
|
||||
"env": "docker",
|
||||
"envSpecificDetails": {
|
||||
"dockerCommand": "",
|
||||
|
|
@ -279,35 +283,35 @@ jobs:
|
|||
console.log(e)
|
||||
}
|
||||
|
||||
- name: Install PostgreSQL client
|
||||
run: |
|
||||
sudo apt update
|
||||
sudo apt install postgresql-client -y
|
||||
# - name: Install PostgreSQL client
|
||||
# run: |
|
||||
# sudo apt update
|
||||
# sudo apt install postgresql-client -y
|
||||
|
||||
- name: Wait after installing PostgreSQL
|
||||
run: sleep 25
|
||||
# - name: Wait after installing PostgreSQL
|
||||
# run: sleep 25
|
||||
|
||||
- name: Drop PostgreSQL PR databases
|
||||
env:
|
||||
PGHOST: ${{ secrets.RENDER_DS_PG_HOST }}
|
||||
PGPORT: 5432
|
||||
PGUSER: ${{ secrets.RENDER_DS_PG_USER }}
|
||||
PGDATABASE: ${{ env.PR_NUMBER }}-ce
|
||||
PGTJBDATABASE: ${{ env.PR_NUMBER }}-ce-tjdb
|
||||
run: |
|
||||
if PGPASSWORD=${{ secrets.RENDER_DS_PG_PASS }} psql -h $PGHOST -p $PGPORT -U $PGUSER -lqt | cut -d \| -f 1 | grep -qw $PGDATABASE; then
|
||||
echo "Database $PGDATABASE exists, deleting..."
|
||||
PGPASSWORD=${{ secrets.RENDER_DS_PG_PASS }} psql -h $PGHOST -p $PGPORT -U $PGUSER -d postgres -c "drop database \"$PGDATABASE\" ;"
|
||||
else
|
||||
echo "Database $PGDATABASE does not exist."
|
||||
fi
|
||||
# - name: Drop PostgreSQL PR databases
|
||||
# env:
|
||||
# PGHOST: ${{ secrets.RENDER_DS_PG_HOST }}
|
||||
# PGPORT: 5432
|
||||
# PGUSER: ${{ secrets.RENDER_DS_PG_USER }}
|
||||
# PGDATABASE: ${{ env.PR_NUMBER }}-ce
|
||||
# PGTJBDATABASE: ${{ env.PR_NUMBER }}-ce-tjdb
|
||||
# run: |
|
||||
# if PGPASSWORD=${{ secrets.RENDER_DS_PG_PASS }} psql -h $PGHOST -p $PGPORT -U $PGUSER -lqt | cut -d \| -f 1 | grep -qw $PGDATABASE; then
|
||||
# echo "Database $PGDATABASE exists, deleting..."
|
||||
# PGPASSWORD=${{ secrets.RENDER_DS_PG_PASS }} psql -h $PGHOST -p $PGPORT -U $PGUSER -d postgres -c "drop database \"$PGDATABASE\" ;"
|
||||
# else
|
||||
# echo "Database $PGDATABASE does not exist."
|
||||
# fi
|
||||
|
||||
if PGPASSWORD=${{ secrets.RENDER_DS_PG_PASS }} psql -h $PGHOST -p $PGPORT -U $PGUSER -lqt | cut -d \| -f 1 | grep -qw $PGTJBDATABASE; then
|
||||
echo "Database $PGTJBDATABASE exists, deleting..."
|
||||
PGPASSWORD=${{ secrets.RENDER_DS_PG_PASS }} psql -h $PGHOST -p $PGPORT -U $PGUSER -d postgres -c "drop database \"$PGTJBDATABASE\" ;"
|
||||
else
|
||||
echo "Database $PGTJBDATABASE does not exist."
|
||||
fi
|
||||
# if PGPASSWORD=${{ secrets.RENDER_DS_PG_PASS }} psql -h $PGHOST -p $PGPORT -U $PGUSER -lqt | cut -d \| -f 1 | grep -qw $PGTJBDATABASE; then
|
||||
# echo "Database $PGTJBDATABASE exists, deleting..."
|
||||
# PGPASSWORD=${{ secrets.RENDER_DS_PG_PASS }} psql -h $PGHOST -p $PGPORT -U $PGUSER -d postgres -c "drop database \"$PGTJBDATABASE\" ;"
|
||||
# else
|
||||
# echo "Database $PGTJBDATABASE does not exist."
|
||||
# fi
|
||||
|
||||
suspend-ce-review-app:
|
||||
if: ${{ github.event.action == 'labeled' && github.event.label.name == 'suspend-ce-review-app' }}
|
||||
|
|
@ -317,7 +321,7 @@ jobs:
|
|||
- name: Suspend service
|
||||
run: |
|
||||
export SERVICE_ID=$(curl --request GET \
|
||||
--url 'https://api.render.com/v1/services?name=ToolJet%20PR%20%23${{ env.PR_NUMBER }}&limit=1' \
|
||||
--url 'https://api.render.com/v1/services?name=ToolJet%20CE%20PR%20%23${{ env.PR_NUMBER }}&limit=1' \
|
||||
--header 'accept: application/json' \
|
||||
--header 'authorization: Bearer ${{ secrets.RENDER_API_KEY }}' | \
|
||||
jq -r '.[0].service.id')
|
||||
|
|
@ -349,7 +353,7 @@ jobs:
|
|||
- name: Resume service
|
||||
run: |
|
||||
export SERVICE_ID=$(curl --request GET \
|
||||
--url 'https://api.render.com/v1/services?name=ToolJet%20PR%20%23${{ env.PR_NUMBER }}&limit=1' \
|
||||
--url 'https://api.render.com/v1/services?name=ToolJet%20CE%20PR%20%23${{ env.PR_NUMBER }}&limit=1' \
|
||||
--header 'accept: application/json' \
|
||||
--header 'authorization: Bearer ${{ secrets.RENDER_API_KEY }}' | \
|
||||
jq -r '.[0].service.id')
|
||||
|
|
@ -420,7 +424,7 @@ jobs:
|
|||
},
|
||||
{
|
||||
"key": "PG_USER",
|
||||
"value": "tooljet"
|
||||
"value": "postgres"
|
||||
},
|
||||
{
|
||||
"key": "PG_PASS",
|
||||
|
|
@ -440,7 +444,7 @@ jobs:
|
|||
},
|
||||
{
|
||||
"key": "TOOLJET_DB_USER",
|
||||
"value": "tooljet"
|
||||
"value": "postgres"
|
||||
},
|
||||
{
|
||||
"key": "TOOLJET_DB_PASS",
|
||||
|
|
@ -456,7 +460,7 @@ jobs:
|
|||
},
|
||||
{
|
||||
"key": "PGRST_DB_URI",
|
||||
"value": "postgres://tooljet:postgres@localhost/${{ env.PR_NUMBER }}-ee-tjdb"
|
||||
"value": "postgres://postgres:postgres@localhost/${{ env.PR_NUMBER }}-ee-tjdb"
|
||||
},
|
||||
{
|
||||
"key": "PGRST_HOST",
|
||||
|
|
@ -536,7 +540,11 @@ jobs:
|
|||
}
|
||||
],
|
||||
"serviceDetails": {
|
||||
"disk": null,
|
||||
"disk": {
|
||||
"name": "tooljet-ee-pr-${{ env.PR_NUMBER }}-postgresql",
|
||||
"mountPath": "/var/lib/postgresql/13/main",
|
||||
"sizeGB": 10
|
||||
},
|
||||
"env": "docker",
|
||||
"envSpecificDetails": {
|
||||
"dockerCommand": "",
|
||||
|
|
@ -549,7 +557,7 @@ jobs:
|
|||
"port": 80,
|
||||
"protocol": "TCP"
|
||||
}],
|
||||
"plan": "starter",
|
||||
"plan": "standard",
|
||||
"pullRequestPreviewsEnabled": "no",
|
||||
"region": "oregon",
|
||||
"url": "https://tooljet-ee-pr-${{ env.PR_NUMBER }}.onrender.com"
|
||||
|
|
@ -647,35 +655,35 @@ jobs:
|
|||
console.log(e)
|
||||
}
|
||||
|
||||
- name: Install PostgreSQL client
|
||||
run: |
|
||||
sudo apt update
|
||||
sudo apt install postgresql-client -y
|
||||
# - name: Install PostgreSQL client
|
||||
# run: |
|
||||
# sudo apt update
|
||||
# sudo apt install postgresql-client -y
|
||||
|
||||
- name: Wait after installing PostgreSQL
|
||||
run: sleep 25
|
||||
# - name: Wait after installing PostgreSQL
|
||||
# run: sleep 25
|
||||
|
||||
- name: Drop PostgreSQL PR databases
|
||||
env:
|
||||
PGHOST: ${{ secrets.RENDER_DS_PG_HOST }}
|
||||
PGPORT: 5432
|
||||
PGUSER: ${{ secrets.RENDER_DS_PG_USER }}
|
||||
PGDATABASE: ${{ env.PR_NUMBER }}-ee
|
||||
PGTJBDATABASE: ${{ env.PR_NUMBER }}-ee-tjdb
|
||||
run: |
|
||||
if PGPASSWORD=${{ secrets.RENDER_DS_PG_PASS }} psql -h $PGHOST -p $PGPORT -U $PGUSER -lqt | cut -d \| -f 1 | grep -qw $PGDATABASE; then
|
||||
echo "Database $PGDATABASE exists, deleting..."
|
||||
PGPASSWORD=${{ secrets.RENDER_DS_PG_PASS }} psql -h $PGHOST -p $PGPORT -U $PGUSER -d postgres -c "drop database \"$PGDATABASE\" ;"
|
||||
else
|
||||
echo "Database $PGDATABASE does not exist."
|
||||
fi
|
||||
# - name: Drop PostgreSQL PR databases
|
||||
# env:
|
||||
# PGHOST: ${{ secrets.RENDER_DS_PG_HOST }}
|
||||
# PGPORT: 5432
|
||||
# PGUSER: ${{ secrets.RENDER_DS_PG_USER }}
|
||||
# PGDATABASE: ${{ env.PR_NUMBER }}-ee
|
||||
# PGTJBDATABASE: ${{ env.PR_NUMBER }}-ee-tjdb
|
||||
# run: |
|
||||
# if PGPASSWORD=${{ secrets.RENDER_DS_PG_PASS }} psql -h $PGHOST -p $PGPORT -U $PGUSER -lqt | cut -d \| -f 1 | grep -qw $PGDATABASE; then
|
||||
# echo "Database $PGDATABASE exists, deleting..."
|
||||
# PGPASSWORD=${{ secrets.RENDER_DS_PG_PASS }} psql -h $PGHOST -p $PGPORT -U $PGUSER -d postgres -c "drop database \"$PGDATABASE\" ;"
|
||||
# else
|
||||
# echo "Database $PGDATABASE does not exist."
|
||||
# fi
|
||||
|
||||
if PGPASSWORD=${{ secrets.RENDER_DS_PG_PASS }} psql -h $PGHOST -p $PGPORT -U $PGUSER -lqt | cut -d \| -f 1 | grep -qw $PGTJBDATABASE; then
|
||||
echo "Database $PGTJBDATABASE exists, deleting..."
|
||||
PGPASSWORD=${{ secrets.RENDER_DS_PG_PASS }} psql -h $PGHOST -p $PGPORT -U $PGUSER -d postgres -c "drop database \"$PGTJBDATABASE\" ;"
|
||||
else
|
||||
echo "Database $PGTJBDATABASE does not exist."
|
||||
fi
|
||||
# if PGPASSWORD=${{ secrets.RENDER_DS_PG_PASS }} psql -h $PGHOST -p $PGPORT -U $PGUSER -lqt | cut -d \| -f 1 | grep -qw $PGTJBDATABASE; then
|
||||
# echo "Database $PGTJBDATABASE exists, deleting..."
|
||||
# PGPASSWORD=${{ secrets.RENDER_DS_PG_PASS }} psql -h $PGHOST -p $PGPORT -U $PGUSER -d postgres -c "drop database \"$PGTJBDATABASE\" ;"
|
||||
# else
|
||||
# echo "Database $PGTJBDATABASE does not exist."
|
||||
# fi
|
||||
|
||||
suspend-ee-review-app:
|
||||
if: ${{ github.event.action == 'labeled' && github.event.label.name == 'suspend-ee-review-app' }}
|
||||
|
|
@ -685,7 +693,7 @@ jobs:
|
|||
- name: Suspend service
|
||||
run: |
|
||||
export SERVICE_ID=$(curl --request GET \
|
||||
--url 'https://api.render.com/v1/services?name=ToolJet%20PR%20%23${{ env.PR_NUMBER }}&limit=1' \
|
||||
--url 'https://api.render.com/v1/services?name=ToolJet%20EE%20PR%20%23${{ env.PR_NUMBER }}&limit=1' \
|
||||
--header 'accept: application/json' \
|
||||
--header 'authorization: Bearer ${{ secrets.RENDER_API_KEY }}' | \
|
||||
jq -r '.[0].service.id')
|
||||
|
|
@ -717,7 +725,7 @@ jobs:
|
|||
- name: Resume service
|
||||
run: |
|
||||
export SERVICE_ID=$(curl --request GET \
|
||||
--url 'https://api.render.com/v1/services?name=ToolJet%20PR%20%23${{ env.PR_NUMBER }}&limit=1' \
|
||||
--url 'https://api.render.com/v1/services?name=ToolJet%20EE%20PR%20%23${{ env.PR_NUMBER }}&limit=1' \
|
||||
--header 'accept: application/json' \
|
||||
--header 'authorization: Bearer ${{ secrets.RENDER_API_KEY }}' | \
|
||||
jq -r '.[0].service.id')
|
||||
|
|
|
|||
|
|
@ -689,7 +689,7 @@ Cypress.Commands.add(
|
|||
name: dataSourceName,
|
||||
options: [
|
||||
{ key: "connection_type", value: "manual", encrypted: false },
|
||||
{ key: "host", value: "35.238.9.114" },
|
||||
{ key: "host", value: "9.234.17.31" },
|
||||
{ key: "port", value: 5432 },
|
||||
{ key: "database", value: "student" },
|
||||
{ key: "username", value: "postgres" },
|
||||
|
|
|
|||
|
|
@ -6,7 +6,8 @@ export const commonSelectors = {
|
|||
toastMessage: ".go3958317564",
|
||||
oldToastMessage: ".go318386747",
|
||||
appSlugAccept: '[data-cy="app-slug-accepted-label"]',
|
||||
newToastMessage: '.drawer-container > [style="position: fixed; z-index: 9999; inset: 16px; pointer-events: none;"] > .go4109123758 > .go2072408551 > .go3958317564',
|
||||
newToastMessage:
|
||||
'.drawer-container > [style="position: fixed; z-index: 9999; inset: 16px; pointer-events: none;"] > .go4109123758 > .go2072408551 > .go3958317564',
|
||||
toastCloseButton: '[data-cy="toast-close-button"]',
|
||||
editButton: "[data-cy=edit-button]",
|
||||
workspaceConstantNameInput: '[data-cy="name-input-field"]',
|
||||
|
|
@ -18,7 +19,7 @@ export const commonSelectors = {
|
|||
appCardOptionsButton: "[data-cy=app-card-menu-icon]",
|
||||
autoSave: "[data-cy=autosave-indicator]",
|
||||
nameInputFieldd: "[data-cy=name-input-field]",
|
||||
valueInputFieldd: '[data-cy=value-input-field]',
|
||||
valueInputFieldd: "[data-cy=value-input-field]",
|
||||
skipButton: ".driver-close-btn",
|
||||
skipInstallationModal: "[data-cy=skip-button]",
|
||||
homePageLogo: "[data-cy=home-page-logo]",
|
||||
|
|
@ -395,7 +396,7 @@ export const commonWidgetSelector = {
|
|||
modalCloseButton: '[data-cy="modal-close-button"]',
|
||||
iframeLinkLabel: '[data-cy="iframe-link-label"]',
|
||||
ifameLinkCopyButton: '[data-cy="iframe-link-copy-button"]',
|
||||
appSlugLabel: '[data-cy="input-field-label"]',
|
||||
appSlugLabel: '[data-cy="unique-app-slug-field-label"]',
|
||||
appSlugInput: '[data-cy="app-slug-input-field"]',
|
||||
appSlugInfoLabel: '[data-cy="helper-text"]',
|
||||
appLinkLabel: '[data-cy="app-link-label"]',
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ export const restAPISelector = {
|
|||
return `[data-cy="${cyParamName(header)}-delete-button-${cyParamName(index)}"]`;
|
||||
},
|
||||
addMoreButton: (header) => {
|
||||
return `[data-cy="${cyParamName(header)}-add-more-button"]`;
|
||||
return `[data-cy="${cyParamName(header)}-add-button"]`;
|
||||
},
|
||||
dropdownLabel: (label) => {
|
||||
return `[data-cy="${cyParamName(label)}-dropdown-label"]`;
|
||||
|
|
|
|||
|
|
@ -80,8 +80,8 @@ describe("Workspace constants", () => {
|
|||
addNewconstants("restapiHeaderKey", "customHeader");
|
||||
addNewconstants("restapiHeaderValue", "key=value");
|
||||
addNewconstants("deleteConst", "deleteconst");
|
||||
addNewconstants("gconst", "236");
|
||||
addNewconstants("gconstUrl", "http://34.66.166.236:4000/");
|
||||
addNewconstants("gconst", "108");
|
||||
addNewconstants("gconstUrl", "http://20.29.40.108:4000/");
|
||||
addNewconstants("gconstEndpoint", "production");
|
||||
|
||||
// create secret constants
|
||||
|
|
@ -118,6 +118,7 @@ describe("Workspace constants", () => {
|
|||
|
||||
//Verify all static and datasource queries output in components
|
||||
for (let i = 3; i <= 16; i++) {
|
||||
cy.log("Verifying textinput" + i);
|
||||
cy.get(commonWidgetSelector.draggableWidget(`textinput${i}`))
|
||||
.verifyVisibleElement("have.value", "Production environment testing");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -78,14 +78,16 @@ describe("Manage Groups", () => {
|
|||
cy.createApp(data.appName);
|
||||
cy.verifyToastMessage(
|
||||
commonSelectors.toastMessage,
|
||||
commonText.appCreatedToast
|
||||
commonText.appCreatedToast,
|
||||
false
|
||||
);
|
||||
cy.backToApps();
|
||||
|
||||
cy.deleteApp(data.appName);
|
||||
cy.verifyToastMessage(
|
||||
commonSelectors.toastMessage,
|
||||
commonText.appDeletedToast
|
||||
commonText.appDeletedToast,
|
||||
false
|
||||
);
|
||||
|
||||
// Folder operations
|
||||
|
|
@ -115,7 +117,8 @@ describe("Manage Groups", () => {
|
|||
cy.get(commonSelectors.cloneAppButton).click();
|
||||
cy.verifyToastMessage(
|
||||
commonSelectors.toastMessage,
|
||||
dashboardText.appClonedToast
|
||||
dashboardText.appClonedToast,
|
||||
false
|
||||
);
|
||||
// cy.get(commonSelectors.cancelButton).click();
|
||||
cy.apiLogout();
|
||||
|
|
@ -177,14 +180,16 @@ describe("Manage Groups", () => {
|
|||
cy.createApp(data.appName);
|
||||
cy.verifyToastMessage(
|
||||
commonSelectors.toastMessage,
|
||||
commonText.appCreatedToast
|
||||
commonText.appCreatedToast,
|
||||
false
|
||||
);
|
||||
cy.backToApps();
|
||||
|
||||
cy.deleteApp(data.appName);
|
||||
cy.verifyToastMessage(
|
||||
commonSelectors.toastMessage,
|
||||
commonText.appDeletedToast
|
||||
commonText.appDeletedToast,
|
||||
false
|
||||
);
|
||||
|
||||
// Folder operations
|
||||
|
|
@ -2127,7 +2127,7 @@
|
|||
"encrypted": false
|
||||
},
|
||||
"host": {
|
||||
"value": "35.238.9.114",
|
||||
"value": "9.234.17.31",
|
||||
"encrypted": false
|
||||
},
|
||||
"port": {
|
||||
|
|
|
|||
|
|
@ -585,7 +585,7 @@
|
|||
"encrypted": false
|
||||
},
|
||||
"host": {
|
||||
"value": "35.238.9.114",
|
||||
"value": "9.234.17.31",
|
||||
"encrypted": false
|
||||
},
|
||||
"port": {
|
||||
|
|
|
|||
|
|
@ -1862,7 +1862,7 @@
|
|||
"encrypted": false
|
||||
},
|
||||
"host": {
|
||||
"value": "35.238.9.114",
|
||||
"value": "9.234.17.31",
|
||||
"encrypted": false
|
||||
},
|
||||
"port": {
|
||||
|
|
|
|||
|
|
@ -2766,7 +2766,7 @@
|
|||
"name": "restapiStaticUrlG",
|
||||
"options": {
|
||||
"method": "get",
|
||||
"url": "http://34.66.166.236:4000/{{constants.gconstEndpoint}}",
|
||||
"url": "http://20.29.40.108:4000/{{constants.gconstEndpoint}}",
|
||||
"url_params": [
|
||||
[
|
||||
"",
|
||||
|
|
@ -2814,7 +2814,7 @@
|
|||
"name": "restapiUrlS",
|
||||
"options": {
|
||||
"method": "get",
|
||||
"url": "http://34.66.166.236:4000/{{secrets.sconstEndpoint}}",
|
||||
"url": "http://20.29.40.108:4000/{{secrets.sconstEndpoint}}",
|
||||
"url_params": [
|
||||
[
|
||||
"",
|
||||
|
|
@ -2908,7 +2908,7 @@
|
|||
"name": "restapiUrlGS",
|
||||
"options": {
|
||||
"method": "get",
|
||||
"url": "http://34.66.166.{{constants.gconst}}{{secrets.sconst}}/production",
|
||||
"url": "http://20.29.40.{{constants.gconst}}{{secrets.sconst}}/production",
|
||||
"url_params": [
|
||||
[
|
||||
"",
|
||||
|
|
@ -3419,7 +3419,7 @@
|
|||
"environmentId": "dab04b8d-7d1a-468a-b219-b2e1d0169d8c",
|
||||
"options": {
|
||||
"url": {
|
||||
"value": "http://34.66.166.236:4000/{{constants.gconstEndpoint}}",
|
||||
"value": "http://20.29.40.108:4000/{{constants.gconstEndpoint}}",
|
||||
"encrypted": false
|
||||
},
|
||||
"auth_type": {
|
||||
|
|
@ -3540,7 +3540,7 @@
|
|||
"environmentId": "dab04b8d-7d1a-468a-b219-b2e1d0169d8c",
|
||||
"options": {
|
||||
"url": {
|
||||
"value": "http://34.66.166.236:4000/{{secrets.sconstEndpoint}}",
|
||||
"value": "http://20.29.40.108:4000/{{secrets.sconstEndpoint}}",
|
||||
"encrypted": false
|
||||
},
|
||||
"auth_type": {
|
||||
|
|
@ -3782,7 +3782,7 @@
|
|||
"environmentId": "dab04b8d-7d1a-468a-b219-b2e1d0169d8c",
|
||||
"options": {
|
||||
"url": {
|
||||
"value": "http://34.66.166.{{constants.gconst}}{{secrets.sconst}}/production",
|
||||
"value": "http://20.29.40.{{constants.gconst}}{{secrets.sconst}}/production",
|
||||
"encrypted": false
|
||||
},
|
||||
"auth_type": {
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ COPY --from=postgrest/postgrest:v12.2.0 /bin/postgrest /bin
|
|||
|
||||
ENV NODE_ENV=production
|
||||
ENV NODE_OPTIONS="--max-old-space-size=4096"
|
||||
RUN apt-get update && apt-get install -y postgresql-client freetds-dev libaio1 wget supervisor
|
||||
RUN apt-get update && apt-get install -y freetds-dev libaio1 wget supervisor
|
||||
|
||||
# Install Instantclient Basic Light Oracle and Dependencies
|
||||
WORKDIR /opt/oracle
|
||||
|
|
@ -54,9 +54,6 @@ ENV LD_LIBRARY_PATH="/opt/oracle/instantclient_11_2:/opt/oracle/instantclient_21
|
|||
|
||||
WORKDIR /
|
||||
|
||||
RUN mkdir -p /app /var/log/supervisor
|
||||
COPY /deploy/docker/supervisord.conf /etc/supervisor/conf.d/supervisord.conf
|
||||
|
||||
# copy npm scripts
|
||||
COPY --from=builder /app/package.json ./app/package.json
|
||||
# copy plugins dependencies
|
||||
|
|
@ -77,32 +74,56 @@ COPY --from=builder /app/server/dist ./app/server/dist
|
|||
|
||||
WORKDIR /app
|
||||
|
||||
# Install PostgreSQL
|
||||
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
|
||||
|
||||
RUN mkdir -p /var/log/supervisor /var/run/postgresql && \
|
||||
chown -R postgres:postgres /var/run/postgresql /var/log/supervisor
|
||||
|
||||
# Explicitly create PG main directory with correct ownerships
|
||||
RUN mkdir -p /var/lib/postgresql/13/main && \
|
||||
chown -R postgres:postgres /var/lib/postgresql
|
||||
|
||||
# Configure Supervisor to manage PostgREST, ToolJet, and Redis
|
||||
RUN echo "[supervisord] \n" \
|
||||
"nodaemon=true \n" \
|
||||
"user=root \n" \
|
||||
"\n" \
|
||||
"[program:postgrest] \n" \
|
||||
"command=/bin/postgrest \n" \
|
||||
"autostart=true \n" \
|
||||
"autorestart=true \n" \
|
||||
"\n" \
|
||||
"[program:tooljet] \n" \
|
||||
"user=root \n" \
|
||||
"command=/bin/bash -c '/app/server/scripts/boot.sh' \n" \
|
||||
"autostart=true \n" \
|
||||
"autorestart=true \n" \
|
||||
"stderr_logfile=/dev/stdout \n" \
|
||||
"stderr_logfile_maxbytes=0 \n" \
|
||||
"stdout_logfile=/dev/stdout \n" \
|
||||
"stdout_logfile_maxbytes=0 \n" | sed 's/ //' > /etc/supervisor/conf.d/supervisord.conf
|
||||
|
||||
# ENV defaults
|
||||
ENV TOOLJET_HOST=http://localhost \
|
||||
PORT=80 \
|
||||
NODE_ENV=production \
|
||||
LOCKBOX_MASTER_KEY=replace_with_lockbox_master_key \
|
||||
SECRET_KEY_BASE=replace_with_secret_key_base \
|
||||
PG_DB=tooljet_production \
|
||||
PG_USER=tooljet \
|
||||
PG_USER=postgres \
|
||||
PG_PASS=postgres \
|
||||
PG_HOST=localhost \
|
||||
ENABLE_TOOLJET_DB=true \
|
||||
TOOLJET_DB_HOST=localhost \
|
||||
TOOLJET_DB_USER=tooljet \
|
||||
TOOLJET_DB_USER=postgres \
|
||||
TOOLJET_DB_PASS=postgres \
|
||||
TOOLJET_DB=tooljet_db \
|
||||
PGRST_HOST=http://localhost:3000 \
|
||||
PGRST_DB_URI=postgres://tooljet:postgres@localhost/tooljet_db \
|
||||
PGRST_DB_URI=postgres://postgres:postgres@localhost/tooljet_db \
|
||||
PGRST_JWT_SECRET=r9iMKoe5CRMgvJBBtp4HrqN7QiPpUToj \
|
||||
PGRST_DB_PRE_CONFIG=postgrest.pre_config \
|
||||
ORM_LOGGING=true \
|
||||
|
|
@ -110,4 +131,7 @@ ENV TOOLJET_HOST=http://localhost \
|
|||
HOME=/home/appuser \
|
||||
TERM=xterm
|
||||
|
||||
CMD ["/usr/bin/supervisord"]
|
||||
|
||||
RUN chmod +x ./server/scripts/preview.sh
|
||||
# Set the entrypoint
|
||||
ENTRYPOINT ["./server/scripts/preview.sh"]
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ WORKDIR /app
|
|||
ARG CUSTOM_GITHUB_TOKEN
|
||||
ARG BRANCH_NAME
|
||||
|
||||
# Clone and checkout the frontend repository
|
||||
# Clone and checkout the frontend repositorys
|
||||
RUN git config --global url."https://x-access-token:${CUSTOM_GITHUB_TOKEN}@github.com/".insteadOf "https://github.com/"
|
||||
|
||||
RUN git config --global http.version HTTP/1.1
|
||||
|
|
@ -66,7 +66,7 @@ COPY --from=postgrest/postgrest:v12.2.0 /bin/postgrest /bin
|
|||
ENV NODE_ENV=production
|
||||
ENV TOOLJET_EDITION=ee
|
||||
ENV NODE_OPTIONS="--max-old-space-size=4096"
|
||||
RUN apt-get update && apt-get install -y postgresql-client freetds-dev libaio1 wget supervisor
|
||||
RUN apt-get update && apt-get install -y freetds-dev libaio1 wget supervisor
|
||||
|
||||
# Install Instantclient Basic Light Oracle and Dependencies
|
||||
WORKDIR /opt/oracle
|
||||
|
|
@ -82,9 +82,6 @@ ENV LD_LIBRARY_PATH="/opt/oracle/instantclient_11_2:/opt/oracle/instantclient_21
|
|||
|
||||
WORKDIR /
|
||||
|
||||
RUN mkdir -p /app /var/log/supervisor
|
||||
COPY /deploy/docker/supervisord.conf /etc/supervisor/conf.d/supervisord.conf
|
||||
|
||||
# copy npm scripts
|
||||
COPY --from=builder /app/package.json ./app/package.json
|
||||
# copy plugins dependencies
|
||||
|
|
@ -106,38 +103,73 @@ COPY --from=builder /app/server/dist ./app/server/dist
|
|||
|
||||
WORKDIR /app
|
||||
|
||||
# ENV defaults
|
||||
# Install PostgreSQL
|
||||
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
|
||||
RUN apt update && apt -y install postgresql-13 postgresql-client-13 supervisor --fix-missing
|
||||
|
||||
|
||||
# Explicitly create PG main directory with correct ownership
|
||||
RUN mkdir -p /var/lib/postgresql/13/main && \
|
||||
chown -R postgres:postgres /var/lib/postgresql
|
||||
|
||||
RUN mkdir -p /var/log/supervisor /var/run/postgresql && \
|
||||
chown -R postgres:postgres /var/run/postgresql /var/log/supervisor
|
||||
|
||||
# Remove existing data and create directory with proper ownership
|
||||
RUN rm -rf /var/lib/postgresql/13/main && \
|
||||
mkdir -p /var/lib/postgresql/13/main && \
|
||||
chown -R postgres:postgres /var/lib/postgresql
|
||||
|
||||
# Initialize PostgreSQL
|
||||
RUN su - postgres -c "/usr/lib/postgresql/13/bin/initdb -D /var/lib/postgresql/13/main"
|
||||
|
||||
# Configure Supervisor to manage PostgREST, ToolJet, and Redis
|
||||
RUN echo "[supervisord] \n" \
|
||||
"nodaemon=true \n" \
|
||||
"user=root \n" \
|
||||
"\n" \
|
||||
"[program:postgrest] \n" \
|
||||
"command=/bin/postgrest \n" \
|
||||
"autostart=true \n" \
|
||||
"autorestart=true \n" \
|
||||
"\n" \
|
||||
"[program:tooljet] \n" \
|
||||
"user=root \n" \
|
||||
"command=/bin/bash -c '/app/server/scripts/boot.sh' \n" \
|
||||
"autostart=true \n" \
|
||||
"autorestart=true \n" \
|
||||
"stderr_logfile=/dev/stdout \n" \
|
||||
"stderr_logfile_maxbytes=0 \n" \
|
||||
"stdout_logfile=/dev/stdout \n" \
|
||||
"stdout_logfile_maxbytes=0 \n" | sed 's/ //' > /etc/supervisor/conf.d/supervisord.conf
|
||||
|
||||
# ENV defaults
|
||||
ENV TOOLJET_HOST=http://localhost \
|
||||
PORT=80 \
|
||||
NODE_ENV=production \
|
||||
LOCKBOX_MASTER_KEY=replace_with_lockbox_master_key \
|
||||
SECRET_KEY_BASE=replace_with_secret_key_base \
|
||||
PG_DB=tooljet_production \
|
||||
PG_USER=tooljet \
|
||||
PG_USER=postgres \
|
||||
PG_PASS=postgres \
|
||||
PG_HOST=localhost \
|
||||
ENABLE_TOOLJET_DB=true \
|
||||
TOOLJET_DB_HOST=localhost \
|
||||
TOOLJET_DB_USER=tooljet \
|
||||
TOOLJET_DB_USER=postgres \
|
||||
TOOLJET_DB_PASS=postgres \
|
||||
TOOLJET_DB=tooljet_db \
|
||||
PGRST_HOST=http://localhost:3000 \
|
||||
PGRST_DB_URI=postgres://tooljet:postgres@localhost/tooljet_db \
|
||||
PGRST_DB_URI=postgres://postgres:postgres@localhost/tooljet_db \
|
||||
PGRST_JWT_SECRET=r9iMKoe5CRMgvJBBtp4HrqN7QiPpUToj \
|
||||
PGRST_DB_PRE_CONFIG=postgrest.pre_config \
|
||||
ORM_LOGGING=true \
|
||||
DEPLOYMENT_PLATFORM=docker:local \
|
||||
REDIS_PASS= \
|
||||
HOME=/home/appuser \
|
||||
TERM=xterm
|
||||
|
||||
CMD ["/usr/bin/supervisord"]
|
||||
|
||||
RUN chmod +x ./server/scripts/preview.sh
|
||||
# Set the entrypoint
|
||||
ENTRYPOINT ["./server/scripts/preview.sh"]
|
||||
|
|
|
|||
|
|
@ -254,7 +254,7 @@ const RunButton = ({ buttonLoadingState }) => {
|
|||
<ButtonComponent
|
||||
size="medium"
|
||||
variant="secondary"
|
||||
onClick={() => runQuery(selectedQuery?.id, selectedQuery?.name, undefined, 'edit', {}, true)}
|
||||
onClick={() => runQuery(selectedQuery?.id, selectedQuery?.name, undefined, 'edit', {}, true, undefined, true)}
|
||||
leadingIcon="play01"
|
||||
disabled={isInDraft}
|
||||
isLoading={isLoading}
|
||||
|
|
|
|||
|
|
@ -216,248 +216,237 @@ const useAppData = (appId, moduleId, darkMode, mode = 'edit', { environmentId, v
|
|||
}
|
||||
|
||||
// const appDataPromise = appService.fetchApp(appId);
|
||||
appDataPromise
|
||||
.then(async (result) => {
|
||||
let appData = { ...result };
|
||||
let editorEnvironment = result.editorEnvironment;
|
||||
if (isPreviewForVersion) {
|
||||
const rawDataQueries = appData?.data_queries;
|
||||
const rawEditingVersionDataQueries = appData?.editing_version?.data_queries;
|
||||
appData = convertAllKeysToSnakeCase(appData);
|
||||
appDataPromise.then(async (result) => {
|
||||
let appData = { ...result };
|
||||
let editorEnvironment = result.editorEnvironment;
|
||||
if (isPreviewForVersion) {
|
||||
const rawDataQueries = appData?.data_queries;
|
||||
const rawEditingVersionDataQueries = appData?.editing_version?.data_queries;
|
||||
appData = convertAllKeysToSnakeCase(appData);
|
||||
|
||||
appData.data_queries = rawDataQueries;
|
||||
if (appData.editing_version && rawEditingVersionDataQueries) {
|
||||
appData.editing_version.data_queries = rawEditingVersionDataQueries;
|
||||
}
|
||||
appData.data_queries = rawDataQueries;
|
||||
if (appData.editing_version && rawEditingVersionDataQueries) {
|
||||
appData.editing_version.data_queries = rawEditingVersionDataQueries;
|
||||
}
|
||||
|
||||
editorEnvironment = {
|
||||
id: environmentId,
|
||||
name: queryParams.env,
|
||||
};
|
||||
}
|
||||
|
||||
let constantsResp;
|
||||
if (mode !== 'edit') {
|
||||
try {
|
||||
const queryParams = { slug: slug };
|
||||
const viewerEnvironment = await appEnvironmentService.getEnvironment(environmentId, queryParams);
|
||||
editorEnvironment = {
|
||||
id: environmentId,
|
||||
name: queryParams.env,
|
||||
id: viewerEnvironment?.environment?.id,
|
||||
name: viewerEnvironment?.environment?.name,
|
||||
};
|
||||
constantsResp =
|
||||
isPublicAccess && appData.is_public
|
||||
? await orgEnvironmentConstantService.getConstantsFromPublicApp(slug, viewerEnvironment?.environment?.id)
|
||||
: await orgEnvironmentConstantService.getConstantsFromApp(slug, viewerEnvironment?.environment?.id);
|
||||
} catch (error) {
|
||||
console.error('Error fetching viewer environment:', error);
|
||||
}
|
||||
}
|
||||
|
||||
let constantsResp;
|
||||
if (mode !== 'edit') {
|
||||
try {
|
||||
const queryParams = { slug: slug };
|
||||
const viewerEnvironment = await appEnvironmentService.getEnvironment(environmentId, queryParams);
|
||||
editorEnvironment = {
|
||||
id: viewerEnvironment?.environment?.id,
|
||||
name: viewerEnvironment?.environment?.name,
|
||||
};
|
||||
constantsResp =
|
||||
isPublicAccess && appData.is_public
|
||||
? await orgEnvironmentConstantService.getConstantsFromPublicApp(
|
||||
slug,
|
||||
viewerEnvironment?.environment?.id
|
||||
)
|
||||
: await orgEnvironmentConstantService.getConstantsFromApp(slug, viewerEnvironment?.environment?.id);
|
||||
} catch (error) {
|
||||
console.error('Error fetching viewer environment:', error);
|
||||
}
|
||||
}
|
||||
if (mode === 'edit') {
|
||||
constantsResp = await orgEnvironmentConstantService.getConstantsFromEnvironment(editorEnvironment?.id);
|
||||
}
|
||||
// get the constants for specific environment
|
||||
constantsResp.constants = extractEnvironmentConstantsFromConstantsList(
|
||||
constantsResp?.constants,
|
||||
editorEnvironment?.name
|
||||
);
|
||||
|
||||
if (mode === 'edit') {
|
||||
constantsResp = await orgEnvironmentConstantService.getConstantsFromEnvironment(editorEnvironment?.id);
|
||||
}
|
||||
// get the constants for specific environment
|
||||
constantsResp.constants = extractEnvironmentConstantsFromConstantsList(
|
||||
constantsResp?.constants,
|
||||
editorEnvironment?.name
|
||||
);
|
||||
setIsPublicAccess(isPublicAccess && mode !== 'edit' && appData.is_public);
|
||||
|
||||
setIsPublicAccess(isPublicAccess && mode !== 'edit' && appData.is_public);
|
||||
fetchAndInjectCustomStyles(isPublicAccess && mode !== 'edit' && appData.is_public);
|
||||
|
||||
fetchAndInjectCustomStyles(isPublicAccess && mode !== 'edit' && appData.is_public);
|
||||
|
||||
const pages = appData.pages.map((page) => {
|
||||
return page;
|
||||
});
|
||||
const conversation = appData.ai_conversation;
|
||||
const docsConversation = appData.ai_conversation_learn;
|
||||
if (setConversation && setDocsConversation) {
|
||||
setConversation(conversation);
|
||||
setDocsConversation(docsConversation);
|
||||
// important to control ai inputs
|
||||
getCreditBalance();
|
||||
}
|
||||
|
||||
let showWalkthrough = true;
|
||||
// if app was created from propmt, and no earlier messages are present in the conversation, send the prompt message
|
||||
|
||||
// handles the getappdataby slug api call. Gets the homePageId from the appData.
|
||||
const homePageId =
|
||||
appData.editing_version?.homePageId || appData.editing_version?.home_page_id || appData.home_page_id;
|
||||
|
||||
setApp({
|
||||
appName: appData.name,
|
||||
appId: appData.id,
|
||||
slug: appData.slug,
|
||||
currentAppEnvironmentId: editorEnvironment.id,
|
||||
isMaintenanceOn:
|
||||
'is_maintenance_on' in result
|
||||
? result.is_maintenance_on
|
||||
: 'isMaintenanceOn' in result
|
||||
? result.isMaintenanceOn
|
||||
: false,
|
||||
organizationId: appData.organizationId || appData.organization_id,
|
||||
homePageId: homePageId,
|
||||
isPublic: appData.is_public,
|
||||
creationMode: appData.creation_mode,
|
||||
});
|
||||
setIsEditorFreezed(appData.should_freeze_editor);
|
||||
const global_settings = mapKeys(
|
||||
appData.editing_version?.global_settings || appData.global_settings,
|
||||
(value, key) => camelCase(key)
|
||||
);
|
||||
if (!global_settings?.theme) {
|
||||
global_settings.theme = baseTheme;
|
||||
}
|
||||
setGlobalSettings(global_settings);
|
||||
setPages(pages, moduleId);
|
||||
setPageSettings(
|
||||
computePageSettings(deepCamelCase(appData?.editing_version?.page_settings ?? appData?.page_settings))
|
||||
);
|
||||
|
||||
// set starting page as homepage initially
|
||||
let startingPage = appData.pages.find((page) => page.id === homePageId);
|
||||
|
||||
//no access to homepage, set to the next available page
|
||||
if (startingPage?.restricted) {
|
||||
startingPage = appData.pages.find((page) => !page?.restricted);
|
||||
}
|
||||
|
||||
if (initialLoadRef.current) {
|
||||
// if initial load, check if the path has a page handle and set that as the starting page
|
||||
const initialLoadPath = location.pathname.split('/').pop();
|
||||
|
||||
const page = appData.pages.find((page) => page.handle === initialLoadPath && !page.isPageGroup);
|
||||
if (page) {
|
||||
// if page is disabled, and not editing redirect to home page
|
||||
const shouldRedirect = page?.restricted || (mode !== 'edit' && page?.disabled);
|
||||
|
||||
if (shouldRedirect) {
|
||||
const newUrl = window.location.href.replace(initialLoadPath, startingPage.handle);
|
||||
window.history.replaceState(null, null, newUrl);
|
||||
|
||||
if (page?.restricted) {
|
||||
toast.error('Access to this page is restricted. Contact admin to know more.', {
|
||||
className: 'text-nowrap w-auto mw-100',
|
||||
});
|
||||
}
|
||||
} else {
|
||||
startingPage = page;
|
||||
}
|
||||
}
|
||||
|
||||
// navigate(`/${getWorkspaceId()}/apps/${slug ?? appId}/${startingPage.handle}`);
|
||||
}
|
||||
|
||||
// Add page id and handle to the state on initial load
|
||||
const currentState = window.history.state || {};
|
||||
const pageInfo = {
|
||||
id: startingPage.id,
|
||||
handle: startingPage.handle,
|
||||
};
|
||||
const newState = { ...currentState, ...pageInfo };
|
||||
window.history.replaceState(newState, '', window.location.href);
|
||||
|
||||
setCurrentPageHandle(startingPage.handle);
|
||||
updateFeatureAccess();
|
||||
setCurrentPageId(startingPage.id, moduleId);
|
||||
setResolvedPageConstants({
|
||||
id: startingPage?.id,
|
||||
handle: startingPage?.handle,
|
||||
name: startingPage?.name,
|
||||
});
|
||||
setComponentNameIdMapping(moduleId);
|
||||
updateEventsField('events', appData.events);
|
||||
setCurrentVersionId(appData.editing_version?.id || appData.current_version_id);
|
||||
setAppHomePageId(homePageId);
|
||||
|
||||
const queryData =
|
||||
isPublicAccess || (mode !== 'edit' && appData.is_public)
|
||||
? appData
|
||||
: await dataqueryService.getAll(appData.editing_version?.id || appData.current_version_id);
|
||||
const dataQueries = queryData.data_queries || queryData?.editing_version?.data_queries;
|
||||
dataQueries.forEach((query) => normalizeQueryTransformationOptions(query));
|
||||
setQueries(dataQueries);
|
||||
if (dataQueries?.length > 0) {
|
||||
setSelectedQuery(dataQueries[0]?.id);
|
||||
initialiseResolvedQuery(dataQueries.map((query) => query.id));
|
||||
}
|
||||
const constants = constantsResp?.constants;
|
||||
|
||||
if (constants) {
|
||||
const orgConstants = {};
|
||||
const orgSecrets = {};
|
||||
constants.map((constant) => {
|
||||
if (constant.type !== 'Secret') {
|
||||
orgConstants[constant.name] = constant.value;
|
||||
} else {
|
||||
orgSecrets[constant.name] = constant.value;
|
||||
}
|
||||
});
|
||||
setResolvedConstants(orgConstants);
|
||||
setSecrets(orgSecrets);
|
||||
}
|
||||
setQueryMapping(moduleId);
|
||||
|
||||
setResolvedGlobals('environment', editorEnvironment);
|
||||
setResolvedGlobals('mode', { value: mode });
|
||||
setResolvedGlobals('currentUser', {
|
||||
...user,
|
||||
groups: currentSession?.groups,
|
||||
role: currentSession?.role?.name,
|
||||
ssoUserInfo: currentSession?.ssoUserInfo,
|
||||
...(currentSession?.currentUser?.metadata && !isEmpty(currentSession?.currentUser?.metadata)
|
||||
? { metadata: currentSession?.currentUser?.metadata }
|
||||
: {}),
|
||||
});
|
||||
setResolvedGlobals('urlparams', JSON.parse(JSON.stringify(queryString.parse(location?.search))));
|
||||
initDependencyGraph(moduleId);
|
||||
setCurrentMode(mode); // TODO: set mode based on the slug/appDef
|
||||
if (
|
||||
state.ai &&
|
||||
state?.prompt &&
|
||||
initialLoadRef.current &&
|
||||
(conversation?.aiConversationMessages || []).length === 0
|
||||
) {
|
||||
setSelectedSidebarItem('tooljetai');
|
||||
toggleLeftSidebar('true');
|
||||
sendMessage(state.prompt);
|
||||
setConversationZeroState(true);
|
||||
showWalkthrough = false;
|
||||
}
|
||||
// fetchDataSources(appData.editing_version.id, editorEnvironment.id);
|
||||
if (!isPublicAccess) {
|
||||
const envFromQueryParams = mode === 'view' && new URLSearchParams(location?.search)?.get('env');
|
||||
useStore.getState().init(appData.editing_version?.id || appData.current_version_id, envFromQueryParams);
|
||||
fetchGlobalDataSources(
|
||||
appData.organization_id,
|
||||
appData.editing_version?.id || appData.current_version_id,
|
||||
editorEnvironment.id
|
||||
);
|
||||
}
|
||||
useStore.getState().updateEditingVersion(appData.editing_version?.id || appData.current_version_id); //check if this is needed
|
||||
updateReleasedVersionId(appData.current_version_id);
|
||||
|
||||
setEditorLoading(false);
|
||||
initialLoadRef.current = false;
|
||||
// only show if app is not created from prompt
|
||||
if (showWalkthrough) initEditorWalkThrough();
|
||||
checkAndSetTrueBuildSuggestionsFlag();
|
||||
return () => {
|
||||
document.title = retrieveWhiteLabelText();
|
||||
};
|
||||
})
|
||||
.catch((error) => {
|
||||
if (isPublicAccess) {
|
||||
if (mode !== 'edit') {
|
||||
handleError('view', error);
|
||||
}
|
||||
}
|
||||
const pages = appData.pages.map((page) => {
|
||||
return page;
|
||||
});
|
||||
const conversation = appData.ai_conversation;
|
||||
const docsConversation = appData.ai_conversation_learn;
|
||||
if (setConversation && setDocsConversation) {
|
||||
setConversation(conversation);
|
||||
setDocsConversation(docsConversation);
|
||||
// important to control ai inputs
|
||||
getCreditBalance();
|
||||
}
|
||||
|
||||
let showWalkthrough = true;
|
||||
// if app was created from propmt, and no earlier messages are present in the conversation, send the prompt message
|
||||
|
||||
// handles the getappdataby slug api call. Gets the homePageId from the appData.
|
||||
const homePageId =
|
||||
appData.editing_version?.homePageId || appData.editing_version?.home_page_id || appData.home_page_id;
|
||||
|
||||
setApp({
|
||||
appName: appData.name,
|
||||
appId: appData.id,
|
||||
slug: appData.slug,
|
||||
currentAppEnvironmentId: editorEnvironment.id,
|
||||
isMaintenanceOn:
|
||||
'is_maintenance_on' in result
|
||||
? result.is_maintenance_on
|
||||
: 'isMaintenanceOn' in result
|
||||
? result.isMaintenanceOn
|
||||
: false,
|
||||
organizationId: appData.organizationId || appData.organization_id,
|
||||
homePageId: homePageId,
|
||||
isPublic: appData.is_public,
|
||||
creationMode: appData.creation_mode,
|
||||
});
|
||||
setIsEditorFreezed(appData.should_freeze_editor);
|
||||
const global_settings = mapKeys(
|
||||
appData.editing_version?.global_settings || appData.global_settings,
|
||||
(value, key) => camelCase(key)
|
||||
);
|
||||
if (!global_settings?.theme) {
|
||||
global_settings.theme = baseTheme;
|
||||
}
|
||||
setGlobalSettings(global_settings);
|
||||
setPages(pages, moduleId);
|
||||
setPageSettings(
|
||||
computePageSettings(deepCamelCase(appData?.editing_version?.page_settings ?? appData?.page_settings))
|
||||
);
|
||||
|
||||
// set starting page as homepage initially
|
||||
let startingPage = appData.pages.find((page) => page.id === homePageId);
|
||||
|
||||
//no access to homepage, set to the next available page
|
||||
if (startingPage?.restricted) {
|
||||
startingPage = appData.pages.find((page) => !page?.restricted);
|
||||
}
|
||||
|
||||
if (initialLoadRef.current) {
|
||||
// if initial load, check if the path has a page handle and set that as the starting page
|
||||
const initialLoadPath = location.pathname.split('/').pop();
|
||||
|
||||
const page = appData.pages.find((page) => page.handle === initialLoadPath && !page.isPageGroup);
|
||||
if (page) {
|
||||
// if page is disabled, and not editing redirect to home page
|
||||
const shouldRedirect = page?.restricted || (mode !== 'edit' && page?.disabled);
|
||||
|
||||
if (shouldRedirect) {
|
||||
const newUrl = window.location.href.replace(initialLoadPath, startingPage.handle);
|
||||
window.history.replaceState(null, null, newUrl);
|
||||
|
||||
if (page?.restricted) {
|
||||
toast.error('Access to this page is restricted. Contact admin to know more.', {
|
||||
className: 'text-nowrap w-auto mw-100',
|
||||
});
|
||||
}
|
||||
} else {
|
||||
startingPage = page;
|
||||
}
|
||||
}
|
||||
|
||||
// navigate(`/${getWorkspaceId()}/apps/${slug ?? appId}/${startingPage.handle}`);
|
||||
}
|
||||
|
||||
// Add page id and handle to the state on initial load
|
||||
const currentState = window.history.state || {};
|
||||
const pageInfo = {
|
||||
id: startingPage.id,
|
||||
handle: startingPage.handle,
|
||||
};
|
||||
const newState = { ...currentState, ...pageInfo };
|
||||
window.history.replaceState(newState, '', window.location.href);
|
||||
|
||||
setCurrentPageHandle(startingPage.handle);
|
||||
updateFeatureAccess();
|
||||
setCurrentPageId(startingPage.id, moduleId);
|
||||
setResolvedPageConstants({
|
||||
id: startingPage?.id,
|
||||
handle: startingPage?.handle,
|
||||
name: startingPage?.name,
|
||||
});
|
||||
setComponentNameIdMapping(moduleId);
|
||||
updateEventsField('events', appData.events);
|
||||
setCurrentVersionId(appData.editing_version?.id || appData.current_version_id);
|
||||
setAppHomePageId(homePageId);
|
||||
|
||||
const queryData =
|
||||
isPublicAccess || (mode !== 'edit' && appData.is_public)
|
||||
? appData
|
||||
: await dataqueryService.getAll(appData.editing_version?.id || appData.current_version_id);
|
||||
const dataQueries = queryData.data_queries || queryData?.editing_version?.data_queries;
|
||||
dataQueries.forEach((query) => normalizeQueryTransformationOptions(query));
|
||||
setQueries(dataQueries);
|
||||
if (dataQueries?.length > 0) {
|
||||
setSelectedQuery(dataQueries[0]?.id);
|
||||
initialiseResolvedQuery(dataQueries.map((query) => query.id));
|
||||
}
|
||||
const constants = constantsResp?.constants;
|
||||
|
||||
if (constants) {
|
||||
const orgConstants = {};
|
||||
const orgSecrets = {};
|
||||
constants.map((constant) => {
|
||||
if (constant.type !== 'Secret') {
|
||||
orgConstants[constant.name] = constant.value;
|
||||
} else {
|
||||
orgSecrets[constant.name] = constant.value;
|
||||
}
|
||||
});
|
||||
setResolvedConstants(orgConstants);
|
||||
setSecrets(orgSecrets);
|
||||
}
|
||||
setQueryMapping(moduleId);
|
||||
|
||||
setResolvedGlobals('environment', editorEnvironment);
|
||||
setResolvedGlobals('mode', { value: mode });
|
||||
setResolvedGlobals('currentUser', {
|
||||
...user,
|
||||
groups: currentSession?.groups,
|
||||
role: currentSession?.role?.name,
|
||||
ssoUserInfo: currentSession?.ssoUserInfo,
|
||||
...(currentSession?.currentUser?.metadata && !isEmpty(currentSession?.currentUser?.metadata)
|
||||
? { metadata: currentSession?.currentUser?.metadata }
|
||||
: {}),
|
||||
});
|
||||
setResolvedGlobals('urlparams', JSON.parse(JSON.stringify(queryString.parse(location?.search))));
|
||||
initDependencyGraph(moduleId);
|
||||
setCurrentMode(mode); // TODO: set mode based on the slug/appDef
|
||||
if (
|
||||
state.ai &&
|
||||
state?.prompt &&
|
||||
initialLoadRef.current &&
|
||||
(conversation?.aiConversationMessages || []).length === 0
|
||||
) {
|
||||
setSelectedSidebarItem('tooljetai');
|
||||
toggleLeftSidebar('true');
|
||||
sendMessage(state.prompt);
|
||||
setConversationZeroState(true);
|
||||
showWalkthrough = false;
|
||||
}
|
||||
// fetchDataSources(appData.editing_version.id, editorEnvironment.id);
|
||||
if (!isPublicAccess) {
|
||||
const envFromQueryParams = mode === 'view' && new URLSearchParams(location?.search)?.get('env');
|
||||
useStore.getState().init(appData.editing_version?.id || appData.current_version_id, envFromQueryParams);
|
||||
fetchGlobalDataSources(
|
||||
appData.organization_id,
|
||||
appData.editing_version?.id || appData.current_version_id,
|
||||
editorEnvironment.id
|
||||
);
|
||||
}
|
||||
useStore.getState().updateEditingVersion(appData.editing_version?.id || appData.current_version_id); //check if this is needed
|
||||
updateReleasedVersionId(appData.current_version_id);
|
||||
|
||||
setEditorLoading(false);
|
||||
initialLoadRef.current = false;
|
||||
// only show if app is not created from prompt
|
||||
if (showWalkthrough) initEditorWalkThrough();
|
||||
checkAndSetTrueBuildSuggestionsFlag();
|
||||
return () => {
|
||||
document.title = retrieveWhiteLabelText();
|
||||
};
|
||||
});
|
||||
}, [setApp, setEditorLoading, currentSession]);
|
||||
|
||||
useEffect(() => {
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ import { Constants } from '@/_helpers/utils';
|
|||
import { OverlayTrigger, Tooltip } from 'react-bootstrap';
|
||||
import Sharepoint from '@/_components/Sharepoint';
|
||||
import AccordionForm from './AccordionForm';
|
||||
import { generateCypressDataCy } from '../modules/common/helpers/cypressHelpers';
|
||||
|
||||
const DynamicForm = ({
|
||||
schema,
|
||||
|
|
@ -534,7 +535,7 @@ const DynamicForm = ({
|
|||
const labelElement = (
|
||||
<label
|
||||
className="form-label"
|
||||
data-cy={`label-${String(label).toLowerCase().replace(/\s+/g, '-')}`}
|
||||
data-cy={`label-${generateCypressDataCy(label)}`}
|
||||
style={{ textDecoration: tooltip ? 'underline 2px dashed' : 'none', textDecorationColor: 'var(--slate8)' }}
|
||||
>
|
||||
{label}
|
||||
|
|
@ -572,7 +573,7 @@ const DynamicForm = ({
|
|||
'd-flex': isHorizontalLayout,
|
||||
'dynamic-form-row': isHorizontalLayout,
|
||||
})}
|
||||
data-cy={`${key.replace(/_/g, '-')}-section`}
|
||||
data-cy={`${generateCypressDataCy(key)}-section`}
|
||||
key={key}
|
||||
>
|
||||
{!isSpecificComponent && (
|
||||
|
|
@ -628,7 +629,7 @@ const DynamicForm = ({
|
|||
<Element
|
||||
{...getElementProps(obj[key])}
|
||||
{...computedProps[propertyKey]}
|
||||
data-cy={`${String(label).toLocaleLowerCase().replace(/\s+/g, '-')}-text-field`}
|
||||
data-cy={`${generateCypressDataCy(label)}-text-field`}
|
||||
dataCy={obj[key].key.replace(/_/g, '-')}
|
||||
//to be removed after whole ui is same
|
||||
isHorizontalLayout={isHorizontalLayout}
|
||||
|
|
@ -663,15 +664,16 @@ const DynamicForm = ({
|
|||
{(flipComponentDropdown.label || isHorizontalLayout) && (
|
||||
<label
|
||||
className={cx('form-label')}
|
||||
data-cy={`${String(flipComponentDropdown.label)
|
||||
.toLocaleLowerCase()
|
||||
.replace(/\s+/g, '-')}-dropdown-label`}
|
||||
data-cy={`${generateCypressDataCy(flipComponentDropdown.label)}-dropdown-label`}
|
||||
>
|
||||
{flipComponentDropdown.label}
|
||||
</label>
|
||||
)}
|
||||
|
||||
<div data-cy={`${String(flipComponentDropdown.label).toLocaleLowerCase().replace(/\s+/g, '-')}-select-dropdown`} className={cx({ 'flex-grow-1': isHorizontalLayout })}>
|
||||
<div
|
||||
data-cy={`${generateCypressDataCy(flipComponentDropdown.label)}-select-dropdown`}
|
||||
className={cx({ 'flex-grow-1': isHorizontalLayout })}
|
||||
>
|
||||
<Select
|
||||
{...getElementProps(flipComponentDropdown)}
|
||||
styles={computeSelectStyles ? computeSelectStyles('100%') : {}}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ import { canDeleteDataSource, canUpdateDataSource } from '@/_helpers';
|
|||
import { OverlayTrigger, Tooltip } from 'react-bootstrap';
|
||||
import { orgEnvironmentVariableService, orgEnvironmentConstantService } from '../_services';
|
||||
import { Constants } from '@/_helpers/utils';
|
||||
import { generateCypressDataCy } from '../modules/common/helpers/cypressHelpers.js';
|
||||
|
||||
const DynamicFormV2 = ({
|
||||
schema,
|
||||
|
|
@ -437,7 +438,7 @@ const DynamicFormV2 = ({
|
|||
const labelElement = (
|
||||
<label
|
||||
className="form-label"
|
||||
data-cy={`label-${String(label).toLowerCase().replace(/\s+/g, '-')}`}
|
||||
data-cy={`label-${generateCypressDataCy(label)}`}
|
||||
style={{ textDecoration: tooltip ? 'underline 2px dashed' : 'none', textDecorationColor: 'var(--slate8)' }}
|
||||
>
|
||||
{label}
|
||||
|
|
@ -475,6 +476,7 @@ const DynamicFormV2 = ({
|
|||
'd-flex': isHorizontalLayout,
|
||||
'dynamic-form-row': isHorizontalLayout,
|
||||
})}
|
||||
data-cy={`${generateCypressDataCy(key)}-section`}
|
||||
key={key}
|
||||
>
|
||||
{!isSpecificComponent && (
|
||||
|
|
@ -505,7 +507,8 @@ const DynamicFormV2 = ({
|
|||
<Element
|
||||
{...getElementProps(uiProperties[key])}
|
||||
{...computedProps[propertyKey]}
|
||||
data-cy={`${String(label).toLocaleLowerCase().replace(/\s+/g, '-')}-text-field`}
|
||||
data-cy={`${generateCypressDataCy(label)}-text-field`}
|
||||
dataCy={uiProperties[key].key.replace(/_/g, '-')}
|
||||
//to be removed after whole ui is same
|
||||
isHorizontalLayout={isHorizontalLayout}
|
||||
/>
|
||||
|
|
@ -539,15 +542,16 @@ const DynamicFormV2 = ({
|
|||
{(flipComponentDropdown.label || isHorizontalLayout) && (
|
||||
<label
|
||||
className={cx('form-label')}
|
||||
data-cy={`${String(flipComponentDropdown.label)
|
||||
.toLocaleLowerCase()
|
||||
.replace(/\s+/g, '-')}-dropdown-label`}
|
||||
data-cy={`${generateCypressDataCy(flipComponentDropdown.label)}-dropdown-label`}
|
||||
>
|
||||
{flipComponentDropdown.label}
|
||||
</label>
|
||||
)}
|
||||
|
||||
<div data-cy={'query-select-dropdown'} className={cx({ 'flex-grow-1': isHorizontalLayout })}>
|
||||
<div
|
||||
data-cy={`${generateCypressDataCy(flipComponentDropdown.label)}-select-dropdown`}
|
||||
className={cx({ 'flex-grow-1': isHorizontalLayout })}
|
||||
>
|
||||
<Select {...getElementProps(flipComponentDropdown)} styles={{}} useCustomStyles={false} />
|
||||
</div>
|
||||
{flipComponentDropdown.helpText && (
|
||||
|
|
|
|||
|
|
@ -21,8 +21,7 @@ export default ({
|
|||
return (
|
||||
<div className="table-content-wrapper">
|
||||
{options.length === 0 && (
|
||||
<div className="empty-key-value"
|
||||
data-cy="label-empty-key-value">
|
||||
<div className="empty-key-value" data-cy="label-empty-key-value">
|
||||
<InfoIcon style={{ width: '16px', marginRight: '5px' }} />
|
||||
<span>There are no key value pairs added</span>
|
||||
</div>
|
||||
|
|
@ -86,7 +85,7 @@ export default ({
|
|||
|
||||
<div className="d-flex mb-2" style={{ height: '16px' }}>
|
||||
<ButtonSolid
|
||||
data-cy={`${dataCy}-add-more-button`}
|
||||
data-cy={`${dataCy}-add-button`}
|
||||
variant="ghostBlue"
|
||||
size="sm"
|
||||
onClick={() => addNewKeyValuePair(options)}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import NumberInput from './NumberInput';
|
|||
import TextInput from './TextInput';
|
||||
import { HelperMessage, InputLabel, ValidationMessage } from '../InputUtils/InputUtils';
|
||||
import { ButtonSolid } from '../../../../_components/AppButton';
|
||||
import { generateCypressDataCy } from '../../../../modules/common/helpers/cypressHelpers.js';
|
||||
|
||||
const CommonInput = ({ label, helperText, disabled, required, onChange: change, ...restProps }) => {
|
||||
const { type, encrypted, validation, isValidatedMessages, isDisabled } = restProps;
|
||||
|
|
@ -65,13 +66,14 @@ const CommonInput = ({ label, helperText, disabled, required, onChange: change,
|
|||
rel="noreferrer"
|
||||
disabled={isDisabled}
|
||||
onClick={toggleEditing}
|
||||
data-cy={`button-${generateCypressDataCy(isEditing ? 'Cancel' : 'Edit')}`}
|
||||
>
|
||||
{isEditing ? 'Cancel' : 'Edit'}
|
||||
</ButtonSolid>
|
||||
</div>
|
||||
|
||||
<div className="col-auto mb-2">
|
||||
<small className="text-green">
|
||||
<small className="text-green" data-cy="encrypted-text">
|
||||
<img className="mx-2 encrypted-icon" src="assets/images/icons/padlock.svg" width="12" height="12" />
|
||||
Encrypted
|
||||
</small>
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import { Label } from '../../Label/Label';
|
|||
import ValidationIcon from './ValidationIcon';
|
||||
import { cn } from '@/lib/utils';
|
||||
import HelperIcon from './HelperIcon';
|
||||
import { generateCypressDataCy } from '../../../../modules/common/helpers/cypressHelpers.js';
|
||||
|
||||
export const ValidationMessage = ({ response, validationMessage, className }) => (
|
||||
<div className={cn('tw-flex tw-pl-[2px] tw-items-start tw-my-[2px]', className)}>
|
||||
|
|
@ -14,7 +15,7 @@ export const ValidationMessage = ({ response, validationMessage, className }) =>
|
|||
type="helper"
|
||||
size="default"
|
||||
className={`tw-font-normal ${response === true ? 'tw-text-text-success' : '!tw-text-text-warning'}`}
|
||||
data-cy="validation-label"
|
||||
data-cy={`${generateCypressDataCy(validationMessage)}-validation-label`}
|
||||
>
|
||||
{validationMessage}
|
||||
</Label>
|
||||
|
|
@ -53,7 +54,7 @@ export const InputLabel = ({ disabled, label, required }) => (
|
|||
type="label"
|
||||
size="default"
|
||||
className={`tw-font-medium tw-mb-[2px] ${disabled ? 'tw-text-text-disabled' : ''}`}
|
||||
data-cy="input-field-label"
|
||||
data-cy={`${generateCypressDataCy(label)}-field-label`}
|
||||
>
|
||||
{label}
|
||||
{required && <RequiredIndicator disabled={disabled} />}
|
||||
|
|
|
|||
6
frontend/src/modules/common/helpers/cypressHelpers.js
Normal file
6
frontend/src/modules/common/helpers/cypressHelpers.js
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
export function generateCypressDataCy(text) {
|
||||
return String(text)
|
||||
.toLowerCase()
|
||||
.replace(/[^a-z0-9]+/g, "-")
|
||||
.replace(/^-+|-+$/g, "");
|
||||
}
|
||||
|
|
@ -36,6 +36,7 @@ import './dataSourceManager.theme.scss';
|
|||
import { canUpdateDataSource } from '@/_helpers';
|
||||
import DataSourceSchemaManager from '@/_helpers/dataSourceSchemaManager';
|
||||
import MultiEnvTabs from './MultiEnvTabs';
|
||||
import { generateCypressDataCy } from '../../../common/helpers/cypressHelpers';
|
||||
|
||||
class DataSourceManagerComponent extends React.Component {
|
||||
constructor(props) {
|
||||
|
|
@ -1127,7 +1128,11 @@ class DataSourceManagerComponent extends React.Component {
|
|||
<div className="row w-100">
|
||||
<div className="alert alert-danger" role="alert">
|
||||
{validationError.map((error, index) => (
|
||||
<div key={index} className="text-muted" data-cy="connection-alert-text">
|
||||
<div
|
||||
key={index}
|
||||
className="text-muted"
|
||||
data-cy={`${generateCypressDataCy(error)}-field-alert-text`}
|
||||
>
|
||||
{error}
|
||||
</div>
|
||||
))}
|
||||
|
|
|
|||
|
|
@ -16,7 +16,9 @@ export class EnforceNewBasicPlanLimits1742369617678 implements MigrationInterfac
|
|||
}
|
||||
const manager = queryRunner.manager;
|
||||
const nestApp = await NestFactory.createApplicationContext(await AppModule.register({ IS_GET_CONTEXT: true }));
|
||||
const { LicenseCountsService } = await import(`${await getImportPath(true, edition)}/licensing/services/count.service`);
|
||||
const { LicenseCountsService } = await import(
|
||||
`${await getImportPath(true, edition)}/licensing/services/count.service`
|
||||
);
|
||||
const licenseInitService = nestApp.get(LicenseInitService);
|
||||
|
||||
const { isValid } = await licenseInitService.initForMigration(manager);
|
||||
|
|
@ -170,6 +172,32 @@ export class EnforceNewBasicPlanLimits1742369617678 implements MigrationInterfac
|
|||
await manager.query(archiveViewersInstanceQuery);
|
||||
}
|
||||
}
|
||||
|
||||
const superAdminCountQuery = `
|
||||
SELECT COUNT(*) FROM users
|
||||
WHERE status = '${USER_STATUS.ACTIVE}' AND user_type = '${USER_TYPE.INSTANCE}'
|
||||
`;
|
||||
const superAdminCount = await manager.query(superAdminCountQuery);
|
||||
|
||||
if (superAdminCount === 0) {
|
||||
const superAdminsQuery = `
|
||||
SELECT * FROM users
|
||||
WHERE user_type = '${USER_TYPE.INSTANCE}'
|
||||
ORDER BY id ASC
|
||||
`;
|
||||
const superAdmins = await manager.query(superAdminsQuery);
|
||||
|
||||
if (superAdmins.length > 0) {
|
||||
const oneInstanceUser = superAdmins[0];
|
||||
console.log('Activating one instance user:', oneInstanceUser.id, oneInstanceUser.email);
|
||||
const activateUserQuery = `
|
||||
UPDATE users
|
||||
SET status = '${USER_STATUS.ACTIVE}'
|
||||
WHERE id = '${oneInstanceUser.id}'
|
||||
`;
|
||||
await manager.query(activateUserQuery);
|
||||
}
|
||||
}
|
||||
}
|
||||
await nestApp.close();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
service postgresql start
|
||||
|
||||
echo "
|
||||
_____ _ ___ _
|
||||
|_ _| | | |_ | | |
|
||||
|
|
@ -15,6 +13,7 @@ Everything you need to build internal tools!
|
|||
GitHub: https://github.com/ToolJet/ToolJet
|
||||
"
|
||||
|
||||
# Run setup
|
||||
npm run db:setup:prod
|
||||
npm run db:seed:prod
|
||||
npm run start:prod
|
||||
# Start ToolJet
|
||||
exec npm run start:prod
|
||||
|
|
|
|||
22
server/scripts/preview.sh
Normal file
22
server/scripts/preview.sh
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
# Fix ownership and permissions
|
||||
chown -R postgres:postgres /var/lib/postgresql /var/run/postgresql
|
||||
chmod 0700 /var/lib/postgresql/13/main
|
||||
|
||||
# Initialize DB cluster if needed
|
||||
if [ ! -s "/var/lib/postgresql/13/main/PG_VERSION" ]; then
|
||||
echo "Initializing PostgreSQL..."
|
||||
su - postgres -c "/usr/lib/postgresql/13/bin/initdb -D /var/lib/postgresql/13/main"
|
||||
fi
|
||||
|
||||
# Start PostgreSQL
|
||||
echo "Starting PostgreSQL..."
|
||||
su - postgres -c "/usr/lib/postgresql/13/bin/pg_ctl -D /var/lib/postgresql/13/main -w start"
|
||||
|
||||
# Export the PORT variable to be used by the application
|
||||
export PORT=${PORT:-80}
|
||||
|
||||
# Start Supervisor
|
||||
exec supervisord -c /etc/supervisor/conf.d/supervisord.conf
|
||||
Loading…
Reference in a new issue