Merge branch 'release/v1.0'

This commit is contained in:
Navaneeth Pk 2022-02-08 12:43:59 +05:30
commit f78b9c1e95
759 changed files with 102405 additions and 35503 deletions

View file

@ -34,4 +34,11 @@ SENTRY_DNS=
SENTRY_DEBUG=
# FEATURE TOGGLE
COMMENT_FEATURE_ENABLE=
COMMENT_FEATURE_ENABLE=
#SSO
SSO_DISABLE_SIGNUP=
SSO_RESTRICTED_DOMAIN=
SSO_GOOGLE_OAUTH2_CLIENT_ID=
SSO_GIT_OAUTH2_CLIENT_ID=
SSO_GIT_OAUTH2_CLIENT_SECRET=

View file

@ -1,10 +1,11 @@
name: CI
# Controls when the workflow will run
on:
# Triggers the workflow on push or pull request events but only for the develop branch
push:
branches: [develop, main]
pull_request:
types: [labeled, opened, synchronize, reopened]
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
@ -28,6 +29,10 @@ env:
jobs:
build:
runs-on: ubuntu-latest
if: |
contains(github.event.pull_request.labels.*.name, 'run-ci') ||
github.ref == 'refs/heads/main' ||
github.ref == 'refs/heads/develop'
steps:
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
@ -56,7 +61,10 @@ jobs:
lint:
runs-on: ubuntu-latest
if: |
contains(github.event.pull_request.labels.*.name, 'run-ci') ||
github.ref == 'refs/heads/main' ||
github.ref == 'refs/heads/develop'
steps:
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
- uses: actions/checkout@v2
@ -80,6 +88,7 @@ jobs:
${{ runner.os }}-
- run: npm i -g npm@7.20.0
- run: npm run build:plugins
- run: npm --prefix frontend ci && npm --prefix server ci
- run: npm --prefix server run lint && npm --prefix frontend run lint
@ -114,6 +123,9 @@ jobs:
${{ runner.os }}-
- run: apt update && apt install -y postgresql
- run: npm i -g npm@7.20.0
- run: npm --prefix plugins ci
- run: npm --prefix plugins run create:client && npm --prefix plugins run create:server
- run: npm --prefix plugins run build:packages && npm --prefix plugins run build:server
- run: npm --prefix server ci
- run: npm --prefix server run db:create
- run: npm --prefix server run db:migrate
@ -150,6 +162,9 @@ jobs:
${{ runner.os }}-
- run: apt update && apt install -y postgresql
- run: npm i -g npm@7.20.0
- run: npm --prefix plugins ci
- run: npm --prefix plugins run create:client && npm --prefix plugins run create:server
- run: npm --prefix plugins run build:packages && npm --prefix plugins run build:server
- run: npm --prefix server ci
- run: npm --prefix server run db:create
- run: npm --prefix server run db:migrate

View file

@ -1 +1 @@
0.13.6
1.0.0

15
.vscode/settings.json vendored
View file

@ -10,5 +10,18 @@
],
"eslint.format.enable": true,
"editor.formatOnSave": true,
"json.schemas": [
{
"fileMatch": [
"/*.operations.json"
],
"url": "https://raw.githubusercontent.com/ToolJet/ToolJet/develop/plugins/schemas/operations.schema.json"
},
{
"fileMatch": [
"/*.manifest.json"
],
"url": "https://raw.githubusercontent.com/ToolJet/ToolJet/develop/plugins/schemas/manifest.schema.json"
}
]
}

View file

@ -1,2 +1,2 @@
web: npm run start:prod --prefix server
release: npm run db:migrate --prefix server && npm run db:seed --prefix server
release: (export NODE_OPTIONS="--max_old_space_size=1024"; cd server && npm run db:migrate && node dist/scripts/seeds.js)

View file

@ -19,26 +19,49 @@ ToolJet is an **open-source low-code framework** to build and deploy internal to
<p align="center">
<kbd>
<img src="https://user-images.githubusercontent.com/7828962/144586771-c6d6cba5-8f79-4e0c-80b4-aa1a38657229.png"/>
<img src="https://user-images.githubusercontent.com/7828962/149466475-1d1f0b3e-8e25-49e8-a5c9-73e068f78de9.png"/>
</kbd>
</p>
## Features
---
- Visual app builder with widgets, such as tables, charts, modals, buttons, dropdowns, and more.
- All widgets are responsive
- Mobile 📱 & desktop layouts 🖥
- Dark mode
- Connect to databases, cloud storages and APIs.
- Deploy on-premise (supports Docker, Kubernetes, Heroku, AWS EC2, Google Cloud Run, and more).
- Granular access control on organization-level and app-level.
- Write JS code almost anywhere in the builder.
- Query editors for all supported data sources.
- Transform query results using JS code.
- All the credentials are securely encrypted using `aes-256-gcm`.
- ToolJet acts only as a proxy and doesn't store any data.
- Support for OAuth.
### Visual application builder
<p align="center">
<kbd>
<img src="https://user-images.githubusercontent.com/7828962/152667206-aaa0ae52-1260-48ce-9d0d-0f2e478f9fd1.png"/>
</kbd>
</p>
![2_alt](https://user-images.githubusercontent.com/7828962/152912302-625f7f3e-3659-46cc-9be6-b52c4a3c370c.png)
![3](https://user-images.githubusercontent.com/7828962/152912291-f5019ed6-e319-4b00-910f-ee7bdb1c05d7.png)
![Final_comment_final](https://user-images.githubusercontent.com/7828962/152912265-a9d4a25f-0853-43af-b92a-322af6b0a4eb.gif)
![5](https://user-images.githubusercontent.com/7828962/152912276-e85c16a4-438f-4b88-9072-18e60017f74b.png)
![6](https://user-images.githubusercontent.com/7828962/152912278-422458b9-eec0-477c-9554-672091734901.png)
## All features
- *Visual app builder:* 35+ built-in responsive widgets such as Tables, Charts, Lists, Forms, Progressbars, and more.
- *20+ data sources:* connect to databases, cloud storages and APIs.
- *Desktop & mobile*: ;layout widths can be customised to support different screens.
- *Self-host:* (supports Docker, Kubernetes, Heroku, AWS EC2, Google Cloud Run, and more).
- *Collaborate:* add comments anywhere on the canvas and tag your team members.
- *Extend with plugins:*: use our [commandline tool](https://www.npmjs.com/package/tooljet) to easily boostrap new connectors.
- *Version control:* every application have different versions with proper release cycle.
- *Run JS code:* ability custom JavaScript snippets
- *Granular access control* on organization-level and app-level.
- *low-code:* write JS code almost anywhere in the builder. For example, the color property of text can be set to `status === 'success' ? 'green' : 'red'`
- *no-code query editors* for all supported data sources.
- *Join and transform data:* transform query results using just JavaScript code.
- *Secure:* All the credentials are securely encrypted using `aes-256-gcm`.
- *Doesn't store data:* ToolJet acts only as a proxy and doesn't store any data.
- *SSO:* Supports multiple SSO providers
<hr>
@ -99,4 +122,4 @@ Kindly read our [Contributing Guide](CONTRIBUTING.md) to learn and understand ab
</a>
## Licence
ToolJet © 2021, ToolJet Solutions Inc - Released under the GNU Affero General Public License v3.0.
ToolJet © 2022, ToolJet Solutions Inc - Released under the GNU Affero General Public License v3.0.

View file

@ -3,7 +3,7 @@
"description": "ToolJet is an open-source low-code framework to build and deploy internal tools.",
"website": "https://tooljet.io/",
"repository": "https://github.com/tooljet/tooljet",
"logo": "https://app.tooljet.io/assets/images/logo.svg",
"logo": "https://tooljet.com/blue-logo.png",
"success_url": "/",
"scripts": {
"predeploy": "npm install --prefix server && npm run build --prefix server"

55
cli/.eslintrc.js Normal file
View file

@ -0,0 +1,55 @@
module.exports = {
env: {
node: true,
},
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/recommended',
'plugin:prettier/recommended',
],
ignorePatterns: ['.eslintrc.js'],
parser: '@typescript-eslint/parser',
parserOptions: {
ecmaVersion: 12,
sourceType: 'module',
project: ['./tsconfig.json'],
},
overrides: [
{
files: ['*.ts'],
parserOptions: {
project: ['./tsconfig.json'],
tsconfigRootDir: __dirname,
},
},
],
plugins: ['@typescript-eslint', 'prettier'],
rules: {
'prettier/prettier': [
'error',
{
semi: true,
trailingComma: 'es5',
printWidth: 120,
singleQuote: true,
},
],
'@typescript-eslint/no-floating-promises': ['error'],
'@typescript-eslint/interface-name-prefix': 'off',
'@typescript-eslint/explicit-function-return-type': 'off',
'@typescript-eslint/explicit-module-boundary-types': 'off',
'@typescript-eslint/no-explicit-any': 'off',
'@typescript-eslint/no-unused-vars': ['error', { vars: 'all', args: 'none' }],
'@typescript-eslint/no-var-requires': 'off',
'@typescript-eslint/no-empty-function': 0,
'@typescript-eslint/ban-types': [
'error',
{
types: {
object: false,
},
extendDefaults: true,
},
],
},
};

17
cli/.gitignore vendored Normal file
View file

@ -0,0 +1,17 @@
node_modules
lerna-debug.log
npm-debug.log
packages/*/dist
packages/*/coverage
.vscode/
pip-wheel-metadata/
tsconfig.tsbuildinfo
.DS_Store
.idea
.vs
dist
.vscode
*.tsbuildinfo
*.tabl.json
*.swp
*.snk

93
cli/README.md Normal file
View file

@ -0,0 +1,93 @@
tooljet cli
=================
<!-- toc -->
* [Usage](#usage)
* [Commands](#commands)
<!-- tocstop -->
# Usage
<!-- usage -->
```sh-session
$ npm install -g @tooljet/cli
$ tooljet COMMAND
running command...
$ tooljet (--version)
@tooljet/cli/0.0.6 darwin-arm64 node-v16.13.1
$ tooljet --help [COMMAND]
USAGE
$ tooljet COMMAND
...
```
<!-- usagestop -->
Command should be executed inside `Tooljet` directory
# Commands
<!-- commands -->
* [`tooljet plugin create PLUGIN_NAME`](#tooljet-plugin-create-plugin_name)
* [`tooljet plugin delete PLUGIN_NAME`](#tooljet-plugin-delete-plugin_name)
* [`tooljet plugin install NPM_MODULE`](#tooljet-plugin-install-npm_module)
## `tooljet plugin create PLUGIN_NAME`
Create a new tooljet plugin
```
USAGE
$ tooljet plugin create [PLUGIN_NAME] [--type database|api|cloud-storage] [-b]
ARGUMENTS
PLUGIN_NAME Name of the plugin
FLAGS
-b, --build
--type=<option> <options: database|api|cloud-storage>
DESCRIPTION
Create a new tooljet plugin
EXAMPLES
$ tooljet plugin create <name> --type=<database | api | cloud-storage> [--build]
```
## `tooljet plugin delete PLUGIN_NAME`
Delete a tooljet plugin
```
USAGE
$ tooljet plugin delete [PLUGIN_NAME] [-b]
ARGUMENTS
PLUGIN_NAME Name of the plugin
FLAGS
-b, --build
DESCRIPTION
Delete a tooljet plugin
EXAMPLES
$ tooljet plugin delete <name> [--build]
```
## `tooljet plugin install NPM_MODULE`
Installs a new npm module inside a tooljet plugin
```
USAGE
$ tooljet plugin install [NPM_MODULE] --plugin <value>
ARGUMENTS
NPM_MODULE Name of the npm module
FLAGS
--plugin=<value> (required)
DESCRIPTION
Installs a new npm module inside a tooljet plugin
EXAMPLES
$ tooljet plugin install <npm_module> --plugin <plugin_name>
```
<!-- commandsstop -->

17
cli/bin/dev Executable file
View file

@ -0,0 +1,17 @@
#!/usr/bin/env node
const oclif = require('@oclif/core')
const path = require('path')
const project = path.join(__dirname, '..', 'tsconfig.json')
// In dev mode -> use ts-node and dev plugins
process.env.NODE_ENV = 'development'
require('ts-node').register({project})
// In dev mode, always show stack traces
oclif.settings.debug = true;
// Start the CLI
oclif.run().then(oclif.flush).catch(oclif.Errors.handle)

3
cli/bin/dev.cmd Normal file
View file

@ -0,0 +1,3 @@
@echo off
node "%~dp0\dev" %*

5
cli/bin/run Executable file
View file

@ -0,0 +1,5 @@
#!/usr/bin/env node
const oclif = require('@oclif/core')
oclif.run().then(require('@oclif/core/flush')).catch(require('@oclif/core/handle'))

3
cli/bin/run.cmd Normal file
View file

@ -0,0 +1,3 @@
@echo off
node "%~dp0\run" %*

20159
cli/package-lock.json generated Normal file

File diff suppressed because it is too large Load diff

82
cli/package.json Normal file
View file

@ -0,0 +1,82 @@
{
"name": "@tooljet/cli",
"description": "tooljet cli tool",
"version": "0.0.6",
"bin": {
"tooljet": "./bin/run"
},
"bugs": "https://github.com/tooljet/tooljet/issues",
"dependencies": {
"@oclif/core": "^1",
"@oclif/plugin-help": "^5",
"@oclif/plugin-plugins": "^2.1.0",
"@types/inquirer": "^8.1.3",
"hygen": "^6.1.0",
"inquirer": "^7.3.3",
"rimraf": "^3.0.2"
},
"devDependencies": {
"@oclif/test": "^2",
"@types/chai": "^4",
"@types/mocha": "^9.0.0",
"@types/node": "^16.9.4",
"@types/node-notifier": "^8.0.2",
"@typescript-eslint/eslint-plugin": "^4.31.1",
"@typescript-eslint/parser": "^4.31.1",
"chai": "^4",
"eslint": "^7.32.0",
"eslint-config-oclif": "^4",
"eslint-config-oclif-typescript": "^1.0.2",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-prettier": "^3.4.1",
"globby": "^11",
"mocha": "^9",
"oclif": "^2.0.0-main.10",
"shx": "^0.3.3",
"ts-node": "^10.2.1",
"tslib": "^2.3.1",
"typescript": "^4.4.3"
},
"dirname": "oex",
"engines": {
"node": ">=12.0.0"
},
"files": [
"/bin",
"/dist",
"/npm-shrinkwrap.json",
"/oclif.manifest.json"
],
"homepage": "https://github.com/tooljet/tooljet",
"keywords": [
"tooljet",
"tooljet-cli"
],
"license": "MIT",
"main": "dist/index.js",
"oclif": {
"bin": "tooljet",
"commands": "./dist/commands",
"plugins": [],
"topicSeparator": " ",
"topics": {
"plugin": {
"description": "manage plugins options: create, delete and install"
}
}
},
"repository": {
"type": "git",
"url": "git+https://github.com/tooljet/tooljet.git"
},
"scripts": {
"build": "shx rm -rf dist && tsc -b",
"lint": "eslint . '**/*.ts'",
"postpack": "shx rm -f oclif.manifest.json",
"posttest": "npm run lint",
"prepack": "npm run build && oclif manifest && oclif readme",
"test": "mocha --forbid-only \"test/**/*.test.ts\"",
"version": "oclif readme && git add README.md"
},
"types": "dist/index.d.ts"
}

View file

@ -0,0 +1,111 @@
import { Command, Flags, CliUx } from '@oclif/core';
import * as inquirer from 'inquirer';
const execa = require('execa');
const path = require('path');
const fs = require('fs');
const { runner } = require('hygen');
const Logger = require('hygen/lib/logger');
export default class Create extends Command {
static flags = {
type: Flags.string({ options: ['database', 'api', 'cloud-storage'] }),
build: Flags.boolean({ char: 'b' }),
};
static description = 'Create a new tooljet plugin';
static examples = [`$ tooljet plugin create <name> --type=<database | api | cloud-storage> [--build]`];
static args = [{ name: 'plugin_name', description: 'Name of the plugin', required: true }];
async run(): Promise<void> {
const { args, flags } = await this.parse(Create);
if (Number(args.plugin_name)) {
this.log('\x1b[41m%s\x1b[0m', 'Error : Plugin name can not be a number');
process.exit(1);
}
let { type } = flags;
const name = await CliUx.ux.prompt('Enter plugin display name');
if (Number(name)) {
this.log('\x1b[41m%s\x1b[0m', 'Error : Plugin Display name can not be a number');
process.exit(1);
}
if (!type) {
const responses: any = await inquirer.prompt([
{
name: 'type',
message: 'select a type',
type: 'list',
choices: [{ name: 'database' }, { name: 'api' }, { name: 'cloud-storage' }],
},
]);
type = responses.type;
}
const pluginsPath = 'plugins';
const docsPath = 'docs';
const defaultTemplates = path.join('plugins', '_templates');
if (!(fs.existsSync(pluginsPath) && fs.existsSync(docsPath) && fs.existsSync(defaultTemplates))) {
this.log(
'\x1b[41m%s\x1b[0m',
'Error : plugins, docs or plugins/_templates directory missing, make sure that you are runing this command in Tooljet directory'
);
process.exit(1);
}
const hygenArgs = [
'plugin',
'new',
'--name',
`${args.plugin_name}`,
'--type',
`${type}`,
'--display_name',
`${name}`,
'--plugins_path',
`${pluginsPath}`,
'--docs_path',
`${docsPath}`,
];
CliUx.ux.action.start('creating plugin');
runner(hygenArgs, {
templates: defaultTemplates,
cwd: process.cwd(),
logger: new Logger(console.log.bind(console)),
createPrompter: () => require('enquirer'),
exec: (action: any, body: string | any[]) => {
const opts = body && body.length > 0 ? { input: body } : {};
return require('execa').shell(action, opts);
},
debug: !!process.env.DEBUG,
});
await execa('npx', ['lerna', 'link', 'convert'], { cwd: pluginsPath });
CliUx.ux.action.stop();
if (flags.build) {
CliUx.ux.action.start('building plugins');
await execa.command('npm run build:plugins', { cwd: process.cwd() });
CliUx.ux.action.stop();
}
this.log('\x1b[42m', '\x1b[30m', `Plugin: ${args.plugin_name} created successfully`, '\x1b[0m');
const tree = CliUx.ux.tree();
tree.insert('plugins');
const subtree = CliUx.ux.tree();
subtree.insert(`${args.plugin_name}`);
tree.nodes.plugins.insert('packages', subtree);
tree.display();
}
}

View file

@ -0,0 +1,62 @@
import { Command, CliUx, Flags } from '@oclif/core';
import * as inquirer from 'inquirer';
const execa = require('execa');
const path = require('path');
const fs = require('fs');
const rimraf = require('rimraf');
export default class Delete extends Command {
static description = 'Delete a tooljet plugin';
static flags = {
build: Flags.boolean({ char: 'b' }),
};
static examples = [`$ tooljet plugin delete <name> [--build]`];
static args = [{ name: 'plugin_name', description: 'Name of the plugin', required: true }];
async run(): Promise<void> {
const { args, flags } = await this.parse(Delete);
const pluginsPath = 'plugins';
const pluginPath = path.join('plugins', 'packages', `${args.plugin_name}`);
const pluginDocPath = path.join('docs', 'docs', 'data-sources', `${args.plugin_name}.md`);
if (!(fs.existsSync(pluginsPath) && fs.existsSync(pluginPath) && fs.existsSync(pluginDocPath))) {
this.log(
'\x1b[41m%s\x1b[0m',
'Error : Plugin not found, make sure that you are runing this command in Tooljet directory'
);
process.exit(1);
}
void inquirer
.prompt({
name: 'confirm',
type: 'confirm',
message: 'Are you sure?',
default: 'yes',
})
.then(async (answers: any) => {
if (answers.confirm) {
CliUx.ux.action.start('deleting plugin');
rimraf.sync(pluginPath);
rimraf.sync(pluginDocPath);
await execa('npx', ['lerna', 'link', 'convert'], { cwd: pluginsPath });
CliUx.ux.action.stop();
if (flags.build) {
CliUx.ux.action.start('building plugins');
await execa.command('npm run build:plugins', { cwd: process.cwd() });
CliUx.ux.action.stop();
}
this.log('\x1b[42m', '\x1b[30m', `Plugin: ${args.plugin_name} deleted successfully`, '\x1b[0m');
} else {
CliUx.ux.action.stop();
this.log(`Aborted by user`);
}
});
}
}

View file

@ -0,0 +1,35 @@
import { Command, Flags, CliUx } from '@oclif/core';
const execa = require('execa');
const path = require('path');
const fs = require('fs');
export default class Install extends Command {
static flags = {
plugin: Flags.string({ required: true }),
};
static description = 'Installs a new npm module inside a tooljet plugin';
static examples = [`$ tooljet plugin install <npm_module> --plugin <plugin_name>`];
static args = [{ name: 'npm_module', description: 'Name of the npm module', required: true }];
async run(): Promise<void> {
const { args, flags } = await this.parse(Install);
const plugin = flags.plugin;
const pluginPath = path.join('plugins', 'packages', `${plugin}`);
if (!fs.existsSync(pluginPath)) {
this.log(
'\x1b[41m%s\x1b[0m',
'Error : Plugin not found, make sure that you are runing this command in Tooljet directory'
);
process.exit(1);
}
CliUx.ux.action.start('adding npm module');
await execa('npm', ['i', `${args.npm_module}`], { cwd: pluginPath });
CliUx.ux.action.stop();
this.log('\x1b[42m', '\x1b[30m', `Package: ${args.npm_module} added to ${plugin}`, '\x1b[0m');
}
}

14
cli/tsconfig.json Normal file
View file

@ -0,0 +1,14 @@
{
"compilerOptions": {
"declaration": true,
"importHelpers": true,
"module": "commonjs",
"outDir": "dist",
"rootDir": "src",
"strict": true,
"target": "es2019"
},
"include": [
"src/**/*"
]
}

View file

@ -51,6 +51,8 @@ mv /tmp/.env ~/app/.env
mv /tmp/setup_app ~/app/setup_app
sudo chmod +x ~/app/setup_app
sudo npm install -g npm@7.20.0
# Building ToolJet app
sudo npm install -g @nestjs/cli
sudo npm run build

View file

@ -1,37 +1,53 @@
version: '3'
version: "3"
services:
plugins:
build:
context: ./
dockerfile: ./docker/plugins.Dockerfile.dev
image: tooljet-plugins:development
platform: linux/x86_64
volumes:
- plugins_vol:/app/plugins
command: npm run --prefix plugins start
client:
build:
context: ./frontend
dockerfile: ../docker/client.Dockerfile.dev
context: ./
dockerfile: ./docker/client.Dockerfile.dev
image: tooljet-client:development
platform: linux/x86_64
volumes:
- ./frontend:/app:delegated
- /app/node_modules/
- ./frontend:/app/frontend:delegated
- plugins_vol:/app/plugins
- /app/frontend/node_modules/
ports:
- 8082:8082
environment:
- WEBPACKER_DEV_SERVER_HOST=0.0.0.0
- NODE_ENV=development
command: ['npm', 'start']
command: npm run --prefix frontend start
server:
build:
context: .
context: ./
dockerfile: ./docker/server.Dockerfile.dev
image: tooljet-server:development
platform: linux/x86_64
depends_on:
- postgres
volumes:
- ./server:/app:delegated
- /app/node_modules/
- ./server:/app/server:delegated
- plugins_vol:/app/plugins
- /app/server/node_modules/
- ./.env:/app/.env
- ./.env.test:/app/.env.test
ports:
- 3000:3000
environment:
- SERVE_CLIENT=false
- FORCE_COLOR=1
command: npm run start:dev
command: npm run --prefix server start:dev
postgres:
image: postgres:13
@ -45,5 +61,8 @@ services:
volumes:
postgres:
node_modules:
cache:
plugins_vol:
driver_opts:
type: none
device: ${PWD}/plugins
o: bind

View file

@ -1,22 +1,28 @@
# pull official base image
FROM node:14.17.3-alpine AS builder
ENV NODE_ENV=production
RUN npm i -g npm@7.20.0
# set working directory
WORKDIR /app
# add `/app/node_modules/.bin` to $PATH
ENV PATH /app/node_modules/.bin:$PATH
COPY ./package.json ./package.json
# Fix for heap limit allocation issue
ENV NODE_OPTIONS="--max-old-space-size=4096"
# install app dependencies
COPY ./frontend/package.json ./frontend/package-lock.json ./
RUN npm install --only=production
COPY ./frontend .
RUN NODE_ENV=production npm run-script build
# Build plugins
COPY ./plugins/package.json ./plugins/package-lock.json ./plugins/
RUN npm --prefix plugins install
COPY ./plugins/ ./plugins/
RUN npm run build:plugins
# Build frontend
ENV NODE_ENV=production
COPY ./frontend/package.json ./frontend/package-lock.json ./frontend/
RUN npm --prefix frontend install --only=production
COPY ./frontend ./frontend
RUN npm --prefix frontend run build
FROM openresty/openresty:1.19.9.1rc1-buster-fat
@ -28,7 +34,7 @@ RUN luarocks install lua-resty-auto-ssl
RUN mkdir /etc/resty-auto-ssl /var/log/openresty /var/www /etc/fallback-certs
COPY --from=builder /app/build /var/www
COPY --from=builder /app/frontend/build /var/www
COPY ./frontend/config/nginx.conf.template /etc/openresty/nginx.conf.template
COPY ./frontend/config/entrypoint.sh /entrypoint.sh

View file

@ -3,25 +3,25 @@ FROM node:14.17.3-alpine
ENV NODE_ENV=development
RUN npm i -g npm@7.20.0
# set working directory
WORKDIR /app
COPY ./package.json ./package.json
# add `/app/node_modules/.bin` to $PATH
ENV PATH /app/node_modules/.bin:$PATH
# Fix for heap limit allocation issue
ENV NODE_OPTIONS="--max-old-space-size=4096"
# install app dependencies
COPY package.json package-lock.json ./
RUN npm install
RUN npm install react-scripts@3.4.1 -g --silent
# add app
COPY . ./
COPY ./frontend/package.json ./frontend/package-lock.json ./frontend/
RUN npm --prefix frontend install
COPY ./frontend/ ./frontend/
# start app
CMD ["npm", "start"]
CMD ["npm", "--prefix", "frontend", "start"]
EXPOSE 8082

View file

@ -0,0 +1,17 @@
# pull official base image
FROM node:14.17.3-alpine AS builder
RUN npm i -g npm@7.20.0
# set working directory
WORKDIR /app
COPY ./package.json ./package.json
# Fix for heap limit allocation issue
ENV NODE_OPTIONS="--max-old-space-size=4096"
# Build plugins
COPY ./plugins/package.json ./plugins/package-lock.json ./plugins/
RUN npm --prefix plugins install
COPY ./plugins/ ./plugins/

View file

@ -1,29 +1,59 @@
FROM node:14.17.3-buster
FROM node:14.17.3-alpine AS builder
# Fix for JS heap limit allocation issue
ENV NODE_OPTIONS="--max-old-space-size=4096"
RUN apt update && apt install -y \
build-essential \
postgresql \
freetds-dev
RUN npm i -g npm@7.20.0
RUN mkdir -p /app
WORKDIR /app
ENV NODE_ENV=production
COPY ./package.json ./package-lock.json ./
# Building ToolJet client
WORKDIR /app
# Scripts for building
COPY ./package.json ./package.json
# Build plugins
COPY ./plugins/package.json ./plugins/package-lock.json ./plugins/
RUN npm --prefix plugins install
COPY ./plugins/ ./plugins/
RUN npm run build:plugins
ENV NODE_ENV=production
# Build frontend
COPY ./frontend/package.json ./frontend/package-lock.json ./frontend/
RUN npm --prefix frontend install
COPY ./frontend/ ./frontend/
RUN NODE_ENV=production npm --prefix frontend run build
RUN npm --prefix frontend run build
# Building ToolJet server
# Build server
COPY ./server/package.json ./server/package-lock.json ./server/
RUN npm --prefix server install
COPY ./server/ ./server/
RUN npm install -g @nestjs/cli
RUN npm --prefix server run build
FROM node:14.17.3-alpine
ENV NODE_ENV=production
ENV NODE_OPTIONS="--max-old-space-size=4096"
RUN apk add postgresql-client freetds
RUN mkdir -p /app
# copy npm scripts
COPY --from=builder /app/package.json ./app/package.json
# copy plugins dependencies
COPY --from=builder /app/plugins/dist ./app/plugins/dist
COPY --from=builder /app/plugins/client.js ./app/plugins/client.js
COPY --from=builder /app/plugins/node_modules ./app/plugins/node_modules
COPY --from=builder /app/plugins/packages/common ./app/plugins/packages/common
COPY --from=builder /app/plugins/package.json ./app/plugins/package.json
# copy frontend build
COPY --from=builder /app/frontend/build ./app/frontend/build
# copy server build
# NOTE: typescript dependency on /server/scripts and typeorm for db creation and migration.
# Need to check if we can optimize such that only executable dist from prev stage can be copied
COPY --from=builder /app/server ./app/server
WORKDIR /app
ENTRYPOINT ["./server/entrypoint.sh"]

View file

@ -1,24 +1,51 @@
FROM node:14.17.3-buster
ENV NODE_ENV=production
FROM node:14.17.3-alpine as builder
# Fix for JS heap limit allocation issue
ENV NODE_OPTIONS="--max-old-space-size=4096"
RUN apt update && apt install -y \
build-essential \
postgresql \
freetds-dev
RUN npm i -g npm@7.20.0
RUN npm install -g @nestjs/cli
RUN mkdir -p /app
WORKDIR /app
# Building ToolJet server
COPY ./server/package.json ./server/package-lock.json ./
RUN npm install --only=production
COPY ./server/ ./
RUN npm run build
COPY ./package.json ./package.json
ENTRYPOINT ["./entrypoint.sh"]
# Building ToolJet plugins
COPY ./plugins/package.json ./plugins/package-lock.json ./plugins/
RUN npm --prefix plugins install
COPY ./plugins/ ./plugins/
RUN npm run build:plugins
ENV NODE_ENV=production
# Building ToolJet server
COPY ./server/package.json ./server/package-lock.json ./server/
RUN npm --prefix server install --only=production
COPY ./server/ ./server/
RUN npm --prefix server run build
FROM node:14.17.3-alpine
ENV NODE_ENV=production
ENV NODE_OPTIONS="--max-old-space-size=4096"
RUN apk add postgresql-client freetds
RUN mkdir -p /app
# copy npm scripts
COPY --from=builder /app/package.json ./app/package.json
# copy plugins dependencies
COPY --from=builder /app/plugins/dist ./app/plugins/dist
COPY --from=builder /app/plugins/client.js ./app/plugins/client.js
COPY --from=builder /app/plugins/node_modules ./app/plugins/node_modules
COPY --from=builder /app/plugins/packages/common ./app/plugins/packages/common
COPY --from=builder /app/plugins/package.json ./app/plugins/package.json
# copy server build
# NOTE: typescript dependency on /server/scripts and typeorm for db creation and migration.
# Need to check if we can optimize such that only executable dist from prev stage can be copied
COPY --from=builder /app/server ./app/server
WORKDIR /app
ENTRYPOINT ["./server/entrypoint.sh"]

View file

@ -1,21 +1,19 @@
# pull official base image
FROM node:14.17.3-buster
FROM node:14.17.3-alpine
RUN apk add postgresql-client freetds
ENV NODE_ENV=development
ENV NODE_OPTIONS="--max-old-space-size=4096"
RUN apt update && apt install -y \
build-essential \
postgresql \
freetds-dev
RUN npm i -g npm@7.20.0
RUN mkdir -p /app
WORKDIR /app
COPY ./server/package.json ./server/package-lock.json ./
RUN npm install
COPY ./server/ ./
COPY ./package.json ./package.json
COPY ./.env ../.env
COPY ./.env.test ../.env.test
# install app dependencies
COPY ./server/package.json ./server/package-lock.json ./server/
RUN npm --prefix server install
COPY ./server/ ./server/
ENTRYPOINT ["./entrypoint.sh"]
ENTRYPOINT ["./server/entrypoint.sh"]

View file

@ -2,7 +2,7 @@
The audit log is the report of all the activities done in your ToolJet account. It will capture and display events automatically by recording who performed an activity, what when, and where the activity was performed, along with other information such as IP address.
<img class="screenshot-full" src="/img/Enterprise/audit_logs/audit_logs.gif" alt="ToolJet - Enterprise - Audit logs" height="420"/>
<img class="screenshot-full" src="/img/enterprise/audit_logs/audit_logs.gif" alt="ToolJet - Enterprise - Audit logs" height="420"/>
### Filter audit logs
@ -66,4 +66,4 @@ It is mandatory to set a Data Range in `From` and `To` to filter audit logs.
| resource_id | There are several [resources](#select-resources) and each resource that is created, an id get associated with it.|
| resource_name | Displays the name of the [resources](#select-resources) that was logged in the event. For example, if an app was created or deleted then it will display the name of the app. |
| resource_type | isplays the type of the [resources](#select-resources) that was logged in the event. |
| user_id | Every user account in ToolJet has an id associated with it and is recorded when an event occurs. |
| user_id | Every user account in ToolJet has an id associated with it and is recorded when an event occurs. |

View file

@ -0,0 +1,227 @@
---
sidebar_position: 3
sidebar_label: Creating a plugin
---
# Creating plugins for ToolJet
## What are plugins
ToolJet is built with extensibility in mind. Plugins allows developers to extend the functionalities of ToolJet using JavaScript. Plugins can only be connectors at this moment. For example, the data source connectors such as PostgreSQL, MySQL, Twilio, Stripe, etc are built as plugins.
In this guide, we will walk you through building plugins for ToolJet with the help of `tooljet` cli.
`tooljet` cli is a commandline tool built for building plugins easily. We will build a simple plugin for BigQuery in this guide.
### What does a plugin look like?
All the plugins live under the `/plugins` directory. The structure of a plugin looks like this:
```
my-awesome-plugin/
package.json
lib/
icon.svg
index.ts
operations.json
manifest.json
```
- manifest.json should include information such as the name of plugin, description, etc.
- operations.json should include the metadata of all the operations supported by the plugin.
- index.ts is the main file. It defines a `QueryService` for the plugin. The `QueryService` handles running of queries, testing connections, caching connectios, etc.
- icon.svg is the icon for the plugin.
- package.json is auto generated by the cli.
## Getting Started
1. Install [tooljet-cli](https://www.npmjs.com/package/@tooljet/cli):
```bash
$ npm i -g @tooljet/cli
```
2. Bootstrap a new plugin using cli
```bash
$ tooljet plugin create bigquery
```
```bash
creating plugin... done
Plugin: bigquery created successfully
└─ plugins
└─ packages
└─ bigquery
```
3. Add the npm package of BigQuery to the plugin dependencies
```bash
$ tooljet plugin install @google-cloud/bigquery --plugin bigquery
```
4. Now the directory for our new plugin should looks something like below:
```bash
plugins/
package.json
packages/
bigquery/
__tests__
bigquery.test.js
package.json
lib/
icon.svg
index.ts
operations.json
manifest.json
```
5. Add data source config paramets to manifest.json
Our BigQuery plugin needs private key of a GCP service account to connect to BigQuery. Let's add `private_key` as a property for the data source.
```json
{
"$schema": "https://json-schema.org/",
"$id": "https://tooljet.io/BigQuery.schema.json",
"title": "BigQuery datasource",
"description": "A schema defining BigQuery datasource",
"type": "api",
"source": {
"name": "BigQuery",
"kind": "bigquery",
"exposedVariables": {
"isLoading": false,
"data": {},
"rawData": {}
},
"options": {
"private_key": { "encrypted": true }
}
},
"defaults": {
"private_key": { "value": "" }
},
"properties": {
"private_key": {
"label": "Private key",
"key": "private_key",
"type": "textarea",
"description": "Enter JSON private key for service account"
}
},
"required": ["private_key"]
}
```
6. Import npm package BigQuery to index.ts
```javascript
const { BigQuery } = require('@google-cloud/bigquery');
```
6. Edit index.ts to include the logic for creating a connection.
```javascript
async getConnection(sourceOptions: any, _options?: object): Promise<any> {
const privateKey = JSON.parse(sourceOptions['private_key']);
const client = new BigQuery({
projectId: privateKey['project_id'],
credentials: {
client_email: privateKey['client_email'],
private_key: privateKey['private_key'],
},
});
return client;
}
```
7. Edit index.ts to include the logic for testing connection.
When a new data source is being added to a ToolJet application, the connection can be tested.
:::info
NOTE: Every data source might not have a way to test connection. If not applicable for your data source, you can disable the test connection feature by adding `"customTesting": true,` to the `manifest.json` of your plugin.
:::
8. Add manifest entry for operations
In this example, let's add two operations for our BigQuery plugin.
- *List databases* - Lists all the databases.
- *Query database* - Query a specific database.
We need to make the entries to `operations.json`. The `operations.json` should look like this now:
```json
{
"$schema": "https://json-schema.org/",
"$id": "https://tooljet.io/dataqueries/Bigquery.schema.json",
"title": "Dynamodb datasource",
"description": "Operations for BigQuery plugin",
"type": "object",
"defaults": {},
"properties": {
"operation": {
"label": "Operation",
"key": "operation",
"type": "dropdown-component-flip",
"description": "Single select dropdown for operation",
"list": [
{
"value": "list_datasets",
"name": "List Datasets"
},
{
"value": "query",
"name": "Query"
}
]
},
"query": {
"query": {
"label": "Query",
"key": "query",
"type": "codehinter",
"description": "",
"height": "150px"
}
}
}
}
```
8. Handle the logic for running queries in `index.ts`
`QueryService` receives the metadata of the data source including the credentials and configs for connecting and parameters for the query that was run. In our example, `sourceOptions` will have the `private_key` of BigQuery datasource associated with the query. `queryOptions` will have the configs and parameters for the specific query. For example, `queryOption.operation` will give the id of current operation.
```javascript
export default class BigQueryQueryService implements QueryService {
async run(sourceOptions: any, queryOptions: any, _dataSourceId: string): Promise<QueryResult> {
const operation = queryOptions.operation;
const client = await this.getConnection(sourceOptions);
let result = {};
try {
switch (operation) {
case 'list_datasets':
result = await client.getDatasets();
break;
}
} catch (error) {
throw new QueryError('Query could not be completed', error.message, {});
}
return {
status: 'ok',
data: result,
};
}
}
```
9. Since it is a smiliar step for adding the logic for handling `query` operationg, skipping it.
10. Tests
Test files are generated by the cli when a plugin is created. You can use `jest` for writing the tests.
Tests for a specific plugin can be run using the command `tooljet plugin test --bigquery`
13. The plugin is now ready!

View file

@ -61,10 +61,12 @@ Follow these steps to setup and run ToolJet on macOS for development purposes. O
ORM_LOGGING=all
```
4. Install dependencies
4. Install and build dependencies
```bash
npm install
npm install --prefix server
npm install --prefix frontend
npm run build:plugins
```
5. Set up database
@ -72,11 +74,9 @@ Follow these steps to setup and run ToolJet on macOS for development purposes. O
npm run --prefix server db:reset
```
6. Install webpack & nest-cli
6. Run plugins compilation in watch mode
```bash
npm install -g webpack
npm install -g webpack-cli
npm install -g @nestjs/cli
cd ./plugins && npm start
```
7. Run the server

View file

@ -80,6 +80,7 @@ docker-compose version 1.26.2, build eefe0d31
```bash
docker-compose build
docker-compose run --rm plugins npm run build:plugins
```
5. Run ToolJet
@ -91,7 +92,7 @@ docker-compose version 1.26.2, build eefe0d31
6. ToolJet server is built using NestJS and the data such as application definitions are persisted on a postgres database. You can run the below command to seed the database.
```bash
docker-compose run --rm server npm run db:seed
docker-compose exec server npm run db:seed
```
7. ToolJet should now be served locally at `http://localhost:8082`. You can login using the default user created.

View file

@ -43,10 +43,12 @@ Follow these steps to setup and run ToolJet on Ubuntu. Open terminal and run the
SECRET_KEY_BASE=4229d5774cfe7f60e75d6b3bf3a1dbb054a696b6d21b6d5de7b73291899797a222265e12c0a8e8d844f83ebacdf9a67ec42584edf1c2b23e1e7813f8a3339041
```
4. Install dependencies
4. Install and build dependencies
```bash
npm install
npm install --prefix server
npm install --prefix frontend
npm run build:plugins
```
5. Set up database
@ -54,19 +56,25 @@ Follow these steps to setup and run ToolJet on Ubuntu. Open terminal and run the
npm run --prefix server db:reset
```
6. Run the server
6. Run plugins compilation in watch mode
```bash
cd ./plugins && npm start
```
7. Run the server
```bash
cd ./server && npm run start:dev
```
7. Run the client
8. Run the client
```bash
cd ./frontend && npm start
```
The client will start running on the port 8082, you can access the client by visiting: [https://localhost:8082](https://localhost:8082)
8. Create login credentials
9. Create login credentials
Visiting https://localhost:8082 should redirect you to the login page, click on the signup link and enter your email. The emails sent by the server in development environment are captured and are opened in your default browser. Click the invitation link in the email preview to setup the account.

View file

@ -22,6 +22,7 @@ Supported queries:
- Listing records
- Retrieving a record
- Creating a record
- Updating a record
- Deleting a record
@ -98,6 +99,67 @@ Example response from Airtable:
}
```
## Creating a record
Required parameters:
- Base ID
- Table name
- Records
<img class="screenshot-full" src="/img/datasource-reference/airtable/airtable-create.png" alt="ToolJet - Datasource Airtable Create Operarion" height="420"/>
#### Example Records:
```json
[
{
"fields": {
"Notes": "sdfdsf",
"Name": "dsfdsf"
}
},
{
"fields": {
"Notes": "note1",
"Name": "dsfdsf"
}
}
]
```
Click on the `run` button to run the query.
:::info
NOTE: Query must be saved before running.
:::
Example response from Airtable:
```json
{
"records": [
{
"id": "rec5RuZ1COoZGtGDY",
"fields": {
"Notes": "sdfdsf",
"Name": "dsfdsf"
},
"createdTime": "2022-02-07T20:25:27.000Z"
},
{
"id": "recaYbFPonNNu6Cwj",
"fields": {
"Notes": "note1",
"Name": "dsfdsf"
},
"createdTime": "2022-02-07T20:25:27.000Z"
}
]
}
```
## Updating a record
Required parameters:

View file

@ -1,35 +0,0 @@
---
sidebar_position: 12
---
# Amazon S3
ToolJet can connect to Amazon S3 buckets and perform various operation on them.
## Connection
To add a new S3 source, click on the Add or edit datasource icon on the left sidebar of the app editor and click on `Add datasource` button. Select AWS S3 from the modal that pops up.
ToolJet requires the following to connect to your DynamoDB.
- Region
- Access key
- Secret key
It is recommended to create a new IAM user for the database so that you can control the access levels of ToolJet.
<img src="/img/datasource-reference/aws-s3-connect.png" alt="ToolJet - AWS S3 connection" height="250"/>
Click on 'Test connection' button to verify if the credentials are correct and that the database is accessible to ToolJet server. Click on 'Save' button to save the datasource.
## Querying AWS S3
Click on + button of the query manager at the bottom panel of the editor and select the datasource added in the previous step as the datasource. Select the operation that you want to perform and click 'Save' to save the query.
<img src="/img/datasource-reference/aws-s3-query.png" alt="ToolJet - AWS S3 query" height="250"/>
Click on the 'run' button to run the query. NOTE: Query should be saved before running.
:::tip
Query results can be transformed using transformations. Read our transformations documentation to see how: link
:::

View file

@ -0,0 +1,99 @@
---
sidebar_position: 18
---
# BigQuery
ToolJet can connect to bigquery databases to run BigQuery quries.
## Connection
Please refer [this](https://cloud.google.com/bigquery/docs/bigquery-web-ui) link to enable BigQuery API in Google cloud console.
Create Service Account and key, then get your configs downloaded as json
To add a new BigQuery, click on the `+` button on data sources panel at the left-bottom corner of the app editor. Select BigQuery from the modal that pops up.
ToolJet requires the configs json downloaded from your account to connect to BigQuery. Paste the json into the `Private key` field
The json looks like :
```json
{
"type": "service_account",
"project_id": "tooljet-279812",
"private_key_id": "ea6e234sdfsdf3242b91525626edeef74a14e58761",
"private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvQIBADAAhdh67sidfnIUWWWBAQC8V+z0vaM/rFiA\nrq8fzVjSpEu7Cietjn82SVtguAlAUP9YpRepzi4rDmRgVQiXe4KES7VGQhmg3hUj\nbBASbdI5WRCvAC2ujzrxv3rbfjYRWfm+OqzpUBWaEKbwSGc6rNkhmirvhjiFdl5k\nn7aK7w3bmQfBlnNM6+WiQdT09g2qx3lmRDoUUpuCngkhbWOs3gN/U6wlm0cHKtbF\nWUOwKdyeZrm3UORUDkFvq6rVSF8vob+FQxf24FuvpBmXi2o2dqqglle8rlm8Lz83\ns4kAVbqVjtGrVXm6QUcnLISqJCJUnFkSuFpo60GCcgAVrwyAq/6aQH3IM78QKzFL\n8q5b65rXAgMBAAECggEAClIF8tRk0VuG3NZH5lg3q8fDOyaLBFdVKcHKtzCec3Ez\no6C4RcxP6Hk5IbPrtgggjVIi/Z7exKRv2mAwFvuSuJJSQSSjXC7Fm87AQPdYFWYt\noFYIeLGPlFMO++H3Nh+Xt3I5NBLR58UmH48iBdgR3pygXi1C5eBvQ2rdNVTL/uxw\n3iULu8WcVBw8glzkdLNLDq94uqbW7/qyji7QWNkU+804sA0LEj4PWmO7B9k1LCLK\nFV0Ppv+SJYMS2MhWmXPHnYVfeNaKJKPQpHsS2ep/hyjEO/3Fvm3o3cp6SrEkNGIH\nGKeozlfV7MQj7tMHLqWddDBXtFwYVEmN0UJVafvGsQKBgQDsEVzb7DG/xlMpuDQv\nqpLGWXR5DdAhzxVJzeh11Ongb+XxBOVSyTDKJLvOX4rI7tDqqN7b2pabUA3ZjvXv\nhMPXr7AjL6yoJEzVCyo1+pi26OL99OcO+7gUDa0axHFt6LZuPw00r+2Nl0FqrXNR\n+qUiPuZpp2MuKjMwLCwhr5YuqwKBgQDMPv6TPMl+oocoQ4uc84uY58Ywb7XZjmhY\n8jXdA38I454EbQGeLja+2knDpDkF6g14cTzVJe/Ec4A6QmeIieTFSJKBV4VCZ3QN\npLR4PrET7o9GL3mtwnNqcHPw2dLNHtn1OgsOUfJMWPIrFK2abVNAmYIBtOGA4eyH\nrOl+NcAUhQKBgC4EKGy6OuxeFYHxZULRZjEB6QFb3vFoM4cieyjU6w4T4ee8g5NC\nop8U0AMnfp8yZkkHyAFlN6xoy3pYMrqQz7gwiA4j0e0ovk1dEspY4gHtnanRXmT+\nTmCiVdb86ft5vG37HnDhxlWuYVMRIoSdbikhx7papauvEDFYuvWKC6VnAoGBAJQr\nvxOhrauozNRw6//YzxUGT8kjwZEqtpiQXnMP7kDMn/4l9l6CuESMp6a+pH+d5FfU\nDoWzF9Y01HlvYxyyrLxSgbZDf/FEi/S54BK7qEsFbftExclAn+o/2lyIKV2VXBmD\nGjIxUM4CWOzX+3lkhlj/BEmop0+Qlr92uY1OASLhAoGAfTb/Le0Nf5bGLjK3hI9D\no/oDI5Ryj5rTMxmG/wRjE+1Jm6BjFzEyH2CvnFonccyHQ+wGn61AgbRFLn+Tg5fz\nZXpzD2Xq3Y/AXtrdaayK0wnpMvVE1bZt+ikeVAWX+gR79igTqSXRgCuyp+edsgcE\nZ+2Eser4Z5BpqfFjqFW8MhY=\n-----END PRIVATE KEY-----\n",
"client_email": "tooljettest@tooljet-279812.iam.gserviceaccount.com",
"client_id": "106795637455432158803",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://oauth2.googleapis.com/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/tooljettest%40tooljet-279812.iam.gserviceaccount.com"
}
```
<img src="/img/datasource-reference/bigquery/bq-create.png" alt="ToolJet - BigQuery connection" height="250"/>
Click on 'Test connection' button to verify if the credentials are correct and that the API is accessible to ToolJet server. Click on 'Save' button to save the datasource.
## Querying BigQuery
Click on `+` button of the query manager at the bottom panel of the editor and select the database added in the previous step as the datasource. Select the operation that you want to perform and click 'Save' to save the query.
<img src="/img/datasource-reference/bigquery/bq-query.png" alt="ToolJet - BigQuery query" height="250"/>
Click on the 'run' button to run the query. NOTE: Query should be saved before running.
:::tip
Query results can be transformed using transformations. Read our transformations documentation to see how: [link](/docs/tutorial/transformations)
:::
### Supported operations
- [List Datasets](#list-datatsets)
- [List Tables](#list-tables)
- [Query](#query)
#### List Datasets
Retruns list of datasets
#### List Tables
Return list of tables within a dataset
#### Query
Return data based on the `Query`.
`Query options` [Reference](https://cloud.google.com/bigquery/docs/reference/rest/v2/Job).
`Query result options` [Reference](https://cloud.google.com/nodejs/docs/reference/bigquery/latest/overview#_google_cloud_bigquery_QueryResultsOptions_type)

View file

@ -0,0 +1,56 @@
---
sidebar_position: 4
---
# Custom JavaScript
You can write custom JavaScript code to interact with components and queries. To do that, you just need to create a new query and select **Run JavaScript Code** from the datasources dropdown.
<div style={{textAlign: 'center'}}>
![ToolJet - Datasource Custom JavaScript](/img/datasource-reference/custom-javascript/custom-javascript.png)
</div>
#### Example: Displaying random number
- Let's drag a **button** and a **text** widget inside a container widget.
- Create a new query and select **Run JavaScript code** from dropdown.
- Write the code in **JavaScript editor** and save the query:
```jsx
const a = Math.floor(Math.random() * (10 - 1)) + 1;
return a;
```
:::tip
The return value is used as the `data` of the query.
:::
- Let's edit the properties of widgets:
- Add an event handler to the button - Select **On Click** event, **Run Query** action, and select the `runjs1` query that we created. This will run the JavaScript code every time the button is clicked.
- Edit the property of text widget - In the text field enter **Random number: `{{queries.runjs1.data}}`**. It will display the output as Random number: *result from JS code*
<div style={{textAlign: 'center'}}>
![Display random number using JS](/img/datasource-reference/custom-javascript/jsrandom.gif)
</div>
You can also write custom JavaScript code to get the data from **External APIs** and manipulate the response for graphical representation. Here's the [tutorial](https://blog.tooljet.com/build-github-stars-history-app-in-5-minutes-using-low-code/) on how we used custom JavaScript code to build an app using GitHub API.
### Libraries
ToolJet allows you to internally utilize these libraries:
| Name | Documentation |
| ----------- | ----------- |
| Moment | [https://momentjs.com/docs/](https://momentjs.com/docs/) |
| Lodash | [https://lodash.com/docs/](https://lodash.com/docs/) |
| Axios | [https://axios-http.com/docs/intro](https://axios-http.com/docs/intro) |
:::danger
Issues with writing custom JavaScript code? Ask in our [Slack community](https://join.slack.com/t/tooljet/shared_invite/zt-r2neyfcw-KD1COL6t2kgVTlTtAV5rtg).
:::

View file

@ -1,5 +1,5 @@
---
sidebar_position: 11
sidebar_position: 5
---
# DynamoDB

View file

@ -1,5 +1,5 @@
---
sidebar_position: 2
sidebar_position: 6
---
# Elasticsearch

View file

@ -1,5 +1,5 @@
---
sidebar_position: 13
sidebar_position: 7
---
# Google Cloud Storage
@ -8,23 +8,24 @@ ToolJet can connect to GCS buckets and perform various operation on them.
## Connection
To add a new GCS source, click on the Add or edit datasource icon on the left sidebar of the app editor and click on `Add datasource` button. Select GCS from the modal that pops up.
To add a new GCS source, click on the **Add or edit datasource** icon on the left sidebar of the app editor and click on `Add datasource` button. Select GCS from the modal that pops up.
ToolJet requires the json private key of a service account to be able to connect to GCS.
ToolJet requires the **json private key** of a service account to be able to connect to GCS.
You can follow the [google documentation](https://cloud.google.com/docs/authentication/getting-started) to get started.
<img src="/img/datasource-reference/gcs-connect.png" alt="ToolJet - GCS connection" height="250"/>
![ToolJet - GCS connection](/img/datasource-reference/gcs-connect.png)
Click on 'Test connection' button to verify if the credentials are correct and that the database is accessible to ToolJet server. Click on 'Save' button to save the datasource.
Click on **Test connection** button to verify if the credentials are correct and that the database is accessible to ToolJet server. Click on **Save** button to save the datasource.
## Querying GCS
Click on + button of the query manager at the bottom panel of the editor and select the datasource added in the previous step as the datasource. Select the operation that you want to perform and click 'Save' to save the query.
Click on `+` button of the **query manager** at the bottom panel of the editor and select the datasource added in the previous step as the datasource. Select the operation that you want to perform and click **Save** to save the query.
<img src="/img/datasource-reference/gcs-query.png" alt="ToolJet - GCS query" height="250"/>
![ToolJet - GCS query](/img/datasource-reference/gcs-query.png)
Click on the 'run' button to run the query. NOTE: Query should be saved before running.
Click on the **run** button to run the query.
**NOTE**: Query should be saved before running.
:::tip
Query results can be transformed using transformations. Read our transformations documentation to see how: link
Query results can be transformed using transformations. Read our transformations documentation to see how: [link](/docs/tutorial/transformations)
:::

View file

@ -1,5 +1,5 @@
---
sidebar_position: 4
sidebar_position: 8
---
# Google Sheets

View file

@ -1,5 +1,5 @@
---
sidebar_position: 5
sidebar_position: 9
---
# GraphQL

View file

@ -0,0 +1,35 @@
# MinIO
ToolJet can connect to minio and perform various operation on them.
## Connection
To add a new minio source, click on the **Add or edit datasource** icon on the left sidebar of the app editor and click on `Add datasource` button. Select Minio from the modal that pops up.
ToolJet requires the following to connect to your DynamoDB:
- **Host**
- **Port**
- **Access key**
- **Secret key**
<div style={{textAlign: 'center'}}>
![ToolJet - Minio connection](/img/datasource-reference/minio-connect.png)
</div>
Click on **Test connection** button to verify if the credentials are correct and that the database is accessible to ToolJet server. Click on **Save** button to save the datasource.
## Querying Minio
Click on `+` button of the **query manager** at the bottom panel of the editor and select the datasource added in the previous step as the datasource. Select the operation that you want to perform and click **Save** to save the query.
![ToolJet - Mino query](/img/datasource-reference/minio-query.png)
Click on the **run** button to run the query.
**NOTE**: Query should be saved before running.
:::tip
Query results can be transformed using transformations. Read our transformations documentation to see how: [link](/docs/tutorial/transformations)
:::

View file

@ -1,5 +1,5 @@
---
sidebar_position: 11
sidebar_position: 10
---
# MongoDB
@ -36,3 +36,71 @@ Click on the 'run' button to run the query. NOTE: Query should be saved before r
:::tip
Query results can be transformed using transformations. Read our transformations documentation to see how: [link](/docs/tutorial/transformations)
:::
### Supported operations
- [List Collections](#list-collections)
- [Find One](#find-one)
- [Find Many](#find-many)
- [Total Count](#total-count)
- [Count](#count)
- [Distinct](#distinct)
- [Insert One](#insert-one)
- [Insert Many](#insert-many)
- [Update One](#update-one)
- [Update Many](#update-many)
- [Replace One](#replace-one)
- [Find One and Update](#find-one-and-update)
- [Find One and Replace](#find-one-and-replace)
- [Find One and Delete](#find-one-and-delete)
- [Aggregate](#aggregate)
- [Delete One](#delete-one)
- [Delete Many](#delete-many)
- [Bulk Operations](#bulk-operations)
#### List Collections
Retruns list of collections
#### Fine One
Return a document which satisfy the given filter and options. [Reference](https://docs.mongodb.com/drivers/node/v4.0/usage-examples/findOne)
#### Fine Many
Return list of documents which satisfy the given filter and options. [Reference](https://docs.mongodb.com/drivers/node/v4.0/usage-examples/find/)
#### Total Count
Returns an estimation of the number of documents in the collection based on collection metadata. [Reference](https://mongodb.github.io/node-mongodb-native/4.0/classes/collection.html#estimateddocumentcount)
#### Count
Returns the number of documents based on the filter. [Reference](https://mongodb.github.io/node-mongodb-native/4.0/classes/collection.html#countdocuments)
#### Distinct
Retrieve a list of distinct values for a field based on the filter. [Reference](https://docs.mongodb.com/drivers/node/v4.0/usage-examples/distinct/)
#### Insert One
Insert a document. [Reference](https://docs.mongodb.com/drivers/node/v4.0/usage-examples/insertOne/)
#### Insert Many
Insert list of documents. [Reference](https://docs.mongodb.com/drivers/node/v4.0/usage-examples/insertMany/)
#### Update One
Update a document based on the filter. [Reference](https://docs.mongodb.com/drivers/node/v4.0/usage-examples/updateOne/)
#### Update Many
Update many documents based on the filter. [Reference](https://docs.mongodb.com/drivers/node/v4.0/usage-examples/updateMany/)
#### Replace One
Replace a document based on filter. [Reference](https://docs.mongodb.com/drivers/node/v4.0/usage-examples/replaceOne/)
#### Find One and Update
If your application requires the document after updating, use this instead of `Update One`. [Reference](https://mongodb.github.io/node-mongodb-native/4.0/classes/collection.html#findoneandupdate)
#### Find One and Replace
If your application requires the document after updating, use this instead of `Replace One`. [Reference](https://mongodb.github.io/node-mongodb-native/4.0/classes/collection.html#findoneandreplace)
#### Find One and Delete
If your application requires the document after deleting, use this instead of `Delete One`. [Reference](https://mongodb.github.io/node-mongodb-native/4.0/classes/collection.html#findoneanddelete)
#### Aggregate
Aggregation operations are expressions you can use to produce reduced and summarized results. [Reference](https://docs.mongodb.com/drivers/node/v4.0/fundamentals/aggregation/)
#### Delete One
Delete a record based on the filter. [Reference](https://docs.mongodb.com/drivers/node/v4.0/usage-examples/deleteOne/)
#### Delete Many
Delete many records based on the filter. [Reference](https://docs.mongodb.com/drivers/node/v4.0/usage-examples/deleteMany/)
#### Bulk Operations
Perform bulk operations. [Reference](https://docs.mongodb.com/drivers/node/v4.0/usage-examples/bulkWrite/)
### Dynamic Quries
```javascript
{ amount: { $lt: '{{ components.textinput1.value }}' }}
// Dates
// supported: Extended JSON syntax
{ createdAt: { $date: '{{ new Date('01/10/2020') }}'} }
// not supported: MongoDB classic syntax
{ createdAt: new Date('01/10/2020') }
```
Reference on [mongodb extended JSON](https://docs.mongodb.com/manual/reference/mongodb-extended-json/) supported data types

View file

@ -1,5 +1,5 @@
---
sidebar_position: 6
sidebar_position: 11
---
# MS SQL Server / Azure SQL databases

View file

@ -1,5 +1,5 @@
---
sidebar_position: 7
sidebar_position: 12
---
# MySQL

View file

@ -1,5 +1,5 @@
---
sidebar_position: 8
sidebar_position: 13
---
# PostgreSQL

View file

@ -1,5 +1,5 @@
---
sidebar_position: 9
sidebar_position: 14
---
# Redis

View file

@ -1,5 +1,5 @@
---
sidebar_position: 10
sidebar_position: 15
---
# REST API

View file

@ -0,0 +1,41 @@
---
sidebar_position: 2
---
# Amazon S3
ToolJet can connect to Amazon S3 buckets and perform various operation on them.
## Connection
To add a new S3 source, click on the Add or edit datasource icon on the left sidebar of the app editor and click on `Add datasource` button. Select AWS S3 from the modal that pops up.
ToolJet requires the following to connect to your DynamoDB:
- **Region**
- **Access key**
- **Secret key**
It is recommended to create a new IAM user for the database so that you can control the access levels of ToolJet.
![ToolJet - AWS S3 connection](/img/datasource-reference/aws-s3-connect.png)
Click on **Test connection** button to verify if the credentials are correct and that the database is accessible to ToolJet server. Click on **Save** button to save the datasource.
## Querying AWS S3
Click on `+` button of the **query manager** at the bottom panel of the editor and select the datasource added in the previous step as the datasource. Select the operation that you want to perform and click **Save** to save the query.
![ToolJet - AWS S3 query](/img/datasource-reference/aws-s3-query.png)
Click on the **run** button to run the query.
**NOTE**: Query should be saved before running.
:::tip
Query results can be transformed using transformations. Read our transformations documentation to see how: [link](/docs/tutorial/transformations)
:::
:::info
We built an app to view and upload files to AWS S3 buckets. Check out the complete tutorial [here](https://blog.tooljet.com/building-an-app-to-view-and-upload-files-in-aws-s3-bucket/).
:::

View file

@ -1,5 +1,5 @@
---
sidebar_position: 11
sidebar_position: 16
---
# SendGrid
@ -41,9 +41,12 @@ Optional parameters:
<img class="screenshot-full" src="/img/datasource-reference/sendgrid/sendgrid-query.jpg" alt="ToolJet - Query SendGrid" height="420"/>
:::info
**Send mail to** - accepts a array/list of emails separated by comma.
**Send mail to** - accepts an array/list of emails separated by comma.
For example:
`{{["dev@tooljet.io", "admin@tooljet.io"]}}`.
**Send mail from** - accepts a string.
For example: `admin@tooljet.io`
:::
:::tip

View file

@ -1,3 +1,7 @@
---
sidebar_position: 17
---
# TypeSense
ToolJet can connect to your TypeSense deployment to read and write data.

View file

@ -6,7 +6,7 @@ sidebar_label: Docker
# Deploying ToolJet using docker-compose
:::info
You should setup a PostgreSQL database manually to be used by the ToolJet server.
You should setup a PostgreSQL database manually to be used by the ToolJet server.
:::
Follow the steps below to deploy ToolJet on a server using docker-compose. This setup will deploy both ToolJet server and ToolJet client.
@ -14,13 +14,13 @@ Follow the steps below to deploy ToolJet on a server using docker-compose. This
1. Setup a PostgreSQL database and make sure that the database is accessible.
2. Make sure that the server can receive traffic on port 80, 443 and 22.
For example, if the server is an AWS EC2 instance and the installation should receive traffic from the internet, the inbound rules of the security group should look like this:
For example, if the server is an AWS EC2 instance and the installation should receive traffic from the internet, the inbound rules of the security group should look like this:
protocol| port | allowed_cidr|
----| ----------- | ----------- |
tcp | 22 | your IP |
tcp | 80 | 0.0.0.0/0 |
tcp | 443 | 0.0.0.0/0 |
--------| ------- | ----------- |
tcp | 22 | your IP |
tcp | 80 | 0.0.0.0/0 |
tcp | 443 | 0.0.0.0/0 |
3. Install docker and docker-compose on the server.
[Docker Installation](https://docs.docker.com/engine/install/)
@ -28,14 +28,13 @@ For example, if the server is an AWS EC2 instance and the installation should re
4. Download our production docker-compose file into the server by running:
```bash
curl -LO https://raw.githubusercontent.com/ToolJet/ToolJet/main/deploy/docker/docker-compose.yaml
curl -LO https://raw.githubusercontent.com/ToolJet/ToolJet/main/deploy/docker/docker-compose.yaml
```
5. Create `.env` file in the current directory (where the docker-compose.yaml file is downloaded):
```bash
curl -LO https://raw.githubusercontent.com/ToolJet/ToolJet/main/.env.example
mv .env.example .env
curl -LO https://raw.githubusercontent.com/ToolJet/ToolJet/main/.env.example mv .env.example .env
```
Set up environment variables in `.env` file as explained in [environment variables reference](/docs/deployment/env-vars)
@ -43,27 +42,27 @@ For example, if the server is an AWS EC2 instance and the installation should re
`TOOLJET_HOST` environment variable can either be the public ipv4 address of your server or a custom domain that you want to use.
:::info
We use a [lets encrypt](https://letsencrypt.org/) plugin on top of nginx to create TLS certificates on the fly.
:::
:::info
We use a [lets encrypt](https://letsencrypt.org/) plugin on top of nginx to create TLS certificates on the fly.
:::
Examples:
`TOOLJET_HOST=http://12.34.56.78` or
`TOOLJET_HOST=https://yourdomain.com` or
`TOOLJET_HOST=https://tooljet.yourdomain.com`
:::info
Please make sure that `TOOLJET_HOST` starts with either `http://` or `https://`
:::
:::info
Please make sure that `TOOLJET_HOST` starts with either `http://` or `https://`
:::
:::info
If there are self signed HTTPS endpoints that Tooljet needs to connect to, please make sure that `NODE_EXTRA_CA_CERTS` environment variable is set to the absolute path containing the certificates.
:::
:::info
If there are self signed HTTPS endpoints that Tooljet needs to connect to, please make sure that `NODE_EXTRA_CA_CERTS` environment variable is set to the absolute path containing the certificates.
:::
6. Once you've populated the `.env` file, run
```bash
docker-compose up -d
docker-compose up -d
```
to start all the required services.

View file

@ -13,7 +13,7 @@ Google Cloud Platform provides access to more than 350 APIs and Services that ca
3. Enter the Application details and select the appropriate scopes for your application. We will select the profile and the email scopes.
4. Once you have created the OAuth consent screen, Create new credentials for the **OAuth client ID** from the **Credentials** section in the left sidebar.
5. Select the application type, enter the application name, and then add the following URIs under Authorised Redirect URIs:
1. `https://app.tooljet.io/oauth2/authorize` (if youre using ToolJet cloud)
1. `https://app.tooljet.com/oauth2/authorize` (if youre using ToolJet cloud)
2. `http://localhost:8082/oauth2/authorize` (if youre using ToolJet locally)
6. Now save and then youll get the **Client ID and Client secret** for your application.
@ -42,7 +42,7 @@ You can rename the datasource by clicking on its default name `REST API`
| ----------- | ----------- |
| response_type | code ( `code` refers to the Authorization Code) |
| client_id | **Client ID** |
| redirect_uri | `http://localhost:8082/oauth2/authorize` if using ToolJet locally or enter this `https://app.tooljet.io/oauth2/authorize` if using ToolJet Cloud. |
| redirect_uri | `http://localhost:8082/oauth2/authorize` if using ToolJet locally or enter this `https://app.tooljet.com/oauth2/authorize` if using ToolJet Cloud. |
- Keep the default selection for **Client Authentication** and **Save** the datasource.

View file

@ -10,6 +10,8 @@ ToolJet is an **open-source low-code framework** to build and deploy custom inte
## How ToolJet works
<img class="screenshot-full" src="/img/how-it-works.png" alt="ToolJet - adding datasources" />
ToolJet has just 3 fundamental principles to build apps:
- **Connect to data sources:** Connect to your existing data sources such as PostgreSQL, MySQL, Firestore, Stripe, Google Sheets, API endpoints, etc.

32
docs/docs/sso/github.md Normal file
View file

@ -0,0 +1,32 @@
---
sidebar_position: 6
sidebar_label: Github
---
# Github Single Sign-on
Goto [Github Developer settings](https://github.com/settings/developers) and navigate to `OAuth Apps` and create a project. `Authorization callback URL` should be `<Your Domain>/sso/git`
<img class="screenshot-full" src="/img/sso/git/create-project.png" alt="ToolJet - Github create project" height="420"/>
<br /><br /><br />
Open the application details, and you can see the `Client ID`
<img class="screenshot-full" src="/img/sso/git/client-id.png" alt="ToolJet - Git view client id" height="420"/>
<br /><br /><br />
Then create `Client secrets` by clicking `Generate new client secret`
<img class="screenshot-full" src="/img/sso/git/client-secret.png" alt="ToolJet - Git create client secret" height="420"/>
<br /><br /><br />
Lastly, supply the environment variables `SSO_GIT_OAUTH2_CLIENT_ID` which is client id and `SSO_GIT_OAUTH2_CLIENT_SECRET` is client secret to your deployment.
:::info
### Restrict signup via SSO
Set the environment variable `SSO_DISABLE_SIGNUP` to `true` to ensure that users can only log in and not sign up via SSO. If this variable is set to `true`, only those users who have already signed up, or the ones that are invited, can access ToolJet via SSO.
:::
<br />
The Git sign-in button will now be available in your ToolJet login screen.

View file

@ -37,10 +37,10 @@ Lastly, supply the environment variable `SSO_GOOGLE_OAUTH2_CLIENT_ID` to your de
:::info
### Restrict to your domain
Set the environment variable `RESTRICTED_DOMAIN` to ensure that ToolJet verifies the domain of the user who signs in via SSO, on the server side.
### Restrict to your domains
Set the environment variable `SSO_RESTRICTED_DOMAIN` to ensure that ToolJet verifies the domain of the user who signs in via SSO, on the server side.
If you're setting this environment variable, please make sure that the value does not contain any protocols, subdomains or slashes. It should
simply be `yourdomain.com`.
simply be `yourdomain.com`. Add multiple domians separated by coma example : `yourdomain.com,yourotherdomain.com`
:::
:::info

View file

@ -5,19 +5,33 @@ sidebar_position: 2
# Adding a datasource
:::tip
The datsources are created on app level and not on organization level.
The datasources are created on app level and not on organization level.
:::
Datasource manager is on the left-sidebar of the app builder. To add a new datasource, click on the `Add datasource` button.
<img class="screenshot-full" src="/img/tutorial/adding-datasource/adding-datasources.gif" alt="ToolJet - adding datasources" height="420"/>
<div style={{textAlign: 'center'}}>
![ToolJet - Tutorial - Adding a datasource](/img/tutorial/adding-datasource/add-datasource.png)
</div>
You will be prompted to select the datasource that you wish to add. Let's select PostgreSQL for this tutorial. You will then need to provide the credentials of your PostgreSQL database. The fields that are marked as `encrypted` will be encrypted before saving to ToolJet's database.
<img class="screenshot-full" src="/img/tutorial/adding-datasource/adding-pg.gif" alt="ToolJet - adding Postgres datasource" height="420"/>
<div style={{textAlign: 'center'}}>
![ToolJet - Tutorial - Adding a datasource](/img/tutorial/adding-datasource/datasources.png)
</div>
The name of the datasource must be unique (within the app) and can be changed by clicking on the datasource name at the top of the prompt. Click on `Test Connection` button to verify the connection, this might take a couple of minutes. Once verified, save the datasource.
:::tip
If you are using ToolJet cloud and if your datasource is not publicly accessible, please white-list our IP address ( shown while creating a new datasource ).
:::
:::
<div style={{textAlign: 'center'}}>
![ToolJet - Tutorial - Adding a datasource](/img/tutorial/adding-datasource/postgres.png)
</div>

View file

@ -5,7 +5,12 @@ sidebar_position: 5
# Adding a widget
To add a widget, navigate to the `Widget manager` on the right sidebar. It will display the list of built-in widgets that can be added to the app. Use the search functionality to quickly find the widget that you want.
<img class="screenshot-full" src="/img/tutorial/adding-widget/adding-widget.gif" alt="ToolJet - widgets list" height="420"/>
<div style={{textAlign: 'center'}}>
![ToolJet - Tutorial - Adding a widget](/img/tutorial/adding-widget/widget.png)
</div>
## Drag and drop a widget
Let's add a `table` widget to the app to show the customer data from the query that we created in the previous steps.
@ -13,7 +18,12 @@ To add a widget, drag and drop the widget to the canvas.
## Resize a widget
The widgets can be resized and repositioned within the canvas.
<img class="screenshot-full" src="/img/tutorial/adding-widget/resize-table.gif" alt="ToolJet - Table component" height="420"/>
<div style={{textAlign: 'center'}}>
![ToolJet - Tutorial - Adding a widget](/img/tutorial/adding-widget/resize.gif)
</div>
## Adding widgets to Modal
To add a widget to Modal, we need to trigger [Show modal action](/docs/tutorial/actions#available-actions)
@ -27,17 +37,29 @@ Before triggering `Show modal action` we need to add a modal widget to the canva
- Click on the canvas area for the `Widget manager` sidebar
- Navigate to the Widget manager on the right sidebar and Drag and drop a widget into the Modal
<img class="screenshot-full" src="/img/tutorial/adding-widget/adding-widget-to-modal.gif" alt="ToolJet - Adding widget to Modal" height="420"/>
<div style={{textAlign: 'center'}}>
![ToolJet - Tutorial - Adding a widget](/img/tutorial/adding-widget/adding-widget-to-modal.gif)
</div>
## Resize table columns
We can resize the column width using the resize handle of the column.
<img class="screenshot-full" src="/img/tutorial/adding-widget/column-width-table.gif" alt="ToolJet - Table component" height="420"/>
<div style={{textAlign: 'center'}}>
![ToolJet - Tutorial - Adding a widget](/img/tutorial/adding-widget/resize-table-column.gif)
</div>
## Change widget properties
Click on the widget to open the inspect panel on right sidebar. Here you can change the properties of the widgets. Let's configure the table columns to display the customer data. The display order of columns can be changed by dragging icon near the column name.
<img class="screenshot-full" src="/img/tutorial/adding-widget/widget-inspect-panel.gif" alt="ToolJet - Table component" height="420"/>
<div style={{textAlign: 'center'}}>
![ToolJet - Tutorial - Adding a widget](/img/tutorial/adding-widget/inspect-panel.gif)
</div>
## Connecting data with widget
Now we will connect the `data` object of the `fetch customers` query with the table. Click on the table widget to open the inspector on right sidebar. We can see that the data property of the table have an empty array as the value. The data field, like almost every other field on the editor supports single-line javascript code within double brackets. Variable suggestions will be shows as a dropdown while you type the code in the field.
@ -46,7 +68,11 @@ Let's select `data` object of the 'postgresql' query.
Since we have already run the query in previous step, the data will be immediately displayed in the table.
<img class="screenshot-full" src="/img/tutorial/adding-widget/table-data.gif" alt="ToolJet - Table with data" height="420"/>
<div style={{textAlign: 'center'}}>
![ToolJet - Tutorial - Adding a widget](/img/tutorial/adding-widget/table-data.gif)
</div>
So far in this tutorial, we have connected to a PostgreSQL database and displayed the data on a table.

View file

@ -15,19 +15,32 @@ You can click on the 'enlarge' icon to enlarge query editor pane.
- Copy the query given below and paste on the query area.
- Select SQL mode
```SQL
```sql
SELECT * FROM customers;
```
<img class="screenshot-full" src="/img/tutorial/building-queries/query.gif" alt="ToolJet - postgresql connection" height="420"/>
<div style={{textAlign: 'center'}}>
![ToolJet - Tutorial - Building a query](/img/tutorial/building-queries/query.png)
</div>
Query results can be previewed by clicking the `preview` button. Previewing queries will not alter the state of the app.
<img class="screenshot-full" src="/img/tutorial/building-queries/preview.gif" alt="ToolJet - postgresql query preview" height="420"/>
<div style={{textAlign: 'center'}}>
![ToolJet - Tutorial - Building a query](/img/tutorial/building-queries/preview.gif)
</div>
## Advanced options
<img class="screenshot-full" src="/img/tutorial/building-queries/advanced-query.gif" alt="ToolJet - advanced query options" height="420"/>
<div style={{textAlign: 'center'}}>
![ToolJet - Tutorial - Building a query](/img/tutorial/building-queries/advanced-options.gif)
</div>
#### Run query on page load
If this option is enabled, the query will be run when the app is loaded for the first time. The queries can have more than one trigger, ie the same query can later be triggered again using a button's click event or table's row selected event or any other events.
@ -35,7 +48,11 @@ If this option is enabled, the query will be run when the app is loaded for the
#### Request confirmation before running query
Enable this option to show a prompt to confirm the action before a query is run. The confirmation prompt will look like this:
<img src="/img/tutorial/building-queries/confirm.png" alt="ToolJet - Redis connection" height="120"/>
<div style={{textAlign: 'center'}}>
![ToolJet - Tutorial - Building a query](/img/tutorial/building-queries/confirm.png)
</div>
#### Show notification on success
Enable this option to show a custom message on query completion. Duration of the notification can also be set.

View file

@ -8,13 +8,22 @@ sidebar_position: 1
Apps in ToolJet binds the widgets, datasources and queries together.
:::
<img class="screenshot-full" src="/img/tutorial/create-app.gif" alt="ToolJet - tutorial for creating a new app" height="420"/>
This tutorial will walk you through building a simple app to fetch customer information from a PostgreSQL database and display the data using the table widget.
To create a new ToolJet app, click on the **'Create App'** button on the ToolJet dashboard.
To create a new ToolJet app, click on the **'Create new application'** button on the ToolJet dashboard.
<div style={{textAlign: 'center'}}>
You will be redirected to the visual app editor once the app has been created. The name of the app can be changed by clicking on the app name at top-left of the app builder.
![ToolJet - Creating an app](/img/tutorial/creating-new-app/dashboard.png)
</div>
You will be redirected to the visual app editor once the app has been created. Create the first version of your app to start building. The name of the app can be changed by clicking on the app name at top-left of the app builder.
<div style={{textAlign: 'center'}}>
![ToolJet - Creating an app](/img/tutorial/creating-new-app/visual-app-editor.png)
</div>
The main components of an app:

View file

@ -1,14 +1,23 @@
---
sidebar_position: 11
sidebar_position: 7
---
# Debugger
The debugger captures errors that happens while running the queries. For example, when a database query fails due to the unavailability of a database or when a REST API query fails due to an incorrect URL, the errors will be displayed on the debugger. The debugger also displays relevant data related to the error along with the error message. Debugger is located on the left-sidebar.
<img class="screenshot-full" src="/img/tutorial/debugger/debugger.gif" alt="ToolJet - Debugger" height="420"/>
<div style={{textAlign: 'center'}}>
![ToolJet - Debugger](/img/tutorial/debugger/debugger.gif)
</div>
## Pin Debugger
You can click on the `pin` icon at the top-right corner of the debugger if you do not want the debugger to close. The debugger will remain open until it is unpinned.
<img class="screenshot-full" src="/img/tutorial/debugger/pinned-debugger.gif" alt="ToolJet - Debugger" height="420"/>
<div style={{textAlign: 'center'}}>
![ToolJet - Debugger](/img/tutorial/debugger/pinned-debugger.gif)
</div>

View file

@ -0,0 +1,43 @@
---
sidebar_position: 12
---
# Keyboard Shortcuts
You can perform operations like undo, redo, clone, or removing the widget directly using the keyboard shortcuts.
## Undo
You can undo any operation performed on the visual app editor using the following shortcut keys:
**On Mac:** `cmd + z`
**On Linux/Windows:** `ctrl + z`
## Redo
If you have `undo` an operation and want to redo that again than you can use the following shortcut keys:
**On Mac:** `cmd + shift + z`
**On Linux/Windows:** `ctrl + shift + z`
## Clone
Now you can create multiple clones of any widget without having to drag and drop the widget again from the sidebar. Just select any widget that you want to create a clone and use the following shortcut keys:
**On Mac:** `cmd + d`
**On Linux/Windows:** `ctrl + d`
## Remove widget
Now you can delete a selected widget by using the following shortcut keys:
**On Mac:** `backspace`
**On Linux/Windows:** `delete`
## Unselect the selected widget
You can quickly deselect a widget using the `esc` key.

View file

@ -0,0 +1,181 @@
---
sidebar_position: 11
---
# Managing Users and Groups
## Managing Users
Admin of an organization can add users to the organization. To manage the users in your organization, just go to the **Account menu** on top right corner and click on the **Manage Users**.
<div style={{textAlign: 'center'}}>
![ToolJet - Managing Users and Groups](/img/tutorial/manage-users-groups/menu1.png)
</div>
### Inviting users
Admins can invite anyone to a ToolJet organization using the email address. To invite a user:
- On the **Manage Users** page click on the `Invite new user` button.
<div style={{textAlign: 'center'}}>
![ToolJet - Managing Users and Groups](/img/tutorial/manage-users-groups/userspage.png)
</div>
- Now enter the details of new user such as first name, last name, email, and then click on the **Create User**.
<div style={{textAlign: 'center'}}>
![ToolJet - Managing Users and Groups](/img/tutorial/manage-users-groups/addnewuser.png)
</div>
- An email including the **Invite Link** to join your organization will be send to the created user. The status will turn from **invited** to **active** after the user successfully joins your organization using the invite link.
:::tip
You can also copy the invitation url by clicking on the copy icon next to `invited` status of the created user.
:::
<div style={{textAlign: 'center'}}>
![ToolJet - Managing Users and Groups](/img/tutorial/manage-users-groups/status.png)
</div>
### Disabling a user's access
You can disable any active user's access to your organization by clicking on the **Archive** and then the status of the user will change from **active** to **archived**.
<div style={{textAlign: 'center'}}>
![ToolJet - Managing Users and Groups](/img/tutorial/manage-users-groups/archived.png)
</div>
### Enabling a user's access
Similar to archiving a user's access, you can enable it again by clicking on **Unarchive**. The status of user will change from **archived** to **invited** and the user will have to join again using the invite link recieved via the e-mail.
<div style={{textAlign: 'center'}}>
![ToolJet - Managing Users and Groups](/img/tutorial/manage-users-groups/status.png)
</div>
## Managing Groups
On ToolJet, Admins can create groups for users added in an organization and grant them access to particular app(s) with specific permissions. To manage groups, just go to the **Account menu** on top right corner and click on the **Manage Groups**.
<div style={{textAlign: 'center'}}>
![ToolJet - Managing Users and Groups](/img/tutorial/manage-users-groups/menu2.png)
</div>
### Group properties
Every group on ToolJet has three components:
#### Apps:
Admins can add or remove any number of apps for a group of users. To add an app to a group, select an app from the dropdown and click on `Add` button next to it. You can also set app permissions such as `View` or `Edit` for the group. You can set different permissions for different apps in a group.
<div style={{textAlign: 'center'}}>
![ToolJet - Managing Users and Groups](/img/tutorial/manage-users-groups/apps.png)
</div>
#### Users:
Admins can add or remove any numbers of users in a group. Just select a user from the dropdown and click on `Add` button to add it to a group. To delete a user from a group, click on `Delete` button next to it.
<div style={{textAlign: 'center'}}>
![ToolJet - Managing Users and Groups](/img/tutorial/manage-users-groups/users.png)
</div>
#### Permissions:
Admins can set granular permission like creating/deleting apps or creating folder for a group of users.
<div style={{textAlign: 'center'}}>
![ToolJet - Managing Users and Groups](/img/tutorial/manage-users-groups/permissions.png)
</div>
:::tip
All the activities performed by any Admin or any user in a ToolJet organization is logged in `Audit logs` - including any activity related with managing users and groups.
:::
### Predefined Groups
By default, every organization will have two User Groups:
**1. All Users**
This group contains all the users and admins.
| Apps | Users | Permissions |
| ----------- | ----------- | ----------- |
| You can add or remove apps. | Modification is disabled. This group will have all the users and admins added in an organization. | You can edit permissions for all the users globally. |
<div style={{textAlign: 'center'}}>
![ToolJet - Managing Users and Groups](/img/tutorial/manage-users-groups/allusers.png)
</div>
**2. Admin**
This group contains admins by default. Admins can add more admins or remove the users in this group.
| Apps | Users | Permissions |
| ----------- | ----------- | ----------- |
| Modification is disabled. By default, this group has `Edit` permission for all the apps in an organization | Admins can add or remove users in this group. | Modification is disabled. By default, all the admins can create and delete apps or create folders. |
<div style={{textAlign: 'center'}}>
![ToolJet - Managing Users and Groups](/img/tutorial/manage-users-groups/admin.png)
</div>
### Creating new group
- Click on `Create new group` button in the **User Groups** page.
<div style={{textAlign: 'center'}}>
![ToolJet - Managing Users and Groups](/img/tutorial/manage-users-groups/newgroup1.png)
</div>
- Enter a name for the group and click `Create Group` button.
<div style={{textAlign: 'center'}}>
![ToolJet - Managing Users and Groups](/img/tutorial/manage-users-groups/newgroup2.png)
</div>
- Once the group is created, you can add **Apps**, **Users** and set their **Properties** for that group.
### Deleting a group
To delete a group, click on `Delete` next to it. It will confirm whether you want to delete it or not, Click on `Yes` to delete the group.
<div style={{textAlign: 'center'}}>
![ToolJet - Managing Users and Groups](/img/tutorial/manage-users-groups/deletegroup.png)
</div>

View file

@ -10,7 +10,12 @@ Mobile layout is activated when the width of the window is less than 600px.
Widgets can be shown on desktop, mobile, or both.
:::
<img class="screenshot-full" src="/img/tutorial/mobile-layout/mobile-layout.gif" alt="ToolJet - widgets list" height="420"/>
<div style={{textAlign: 'center'}}>
![ToolJet - widgets list](/img/tutorial/mobile-layout/mobile-layout.gif)
</div>
## Adding existing widget to mobile layout
Click on the widget to open inspector. Scroll down to the `layout` section and enable mobile layout. The width of the widget will be adjusted to fit the mobile layout.

View file

@ -2,5 +2,50 @@
sidebar_position: 10
---
# Sharing and deploying apps
# Preview and Sharing Apps
## Preview
Clicking on `Preview` will open up the released version of the app in the new tab. This is useful if you want to immediately check the app in production.
<div style={{textAlign: 'center'}}>
![ToolJet - Managing Users and Groups](/img/tutorial/sharing/preview.gif)
</div>
## Sharing an app
Once you have released a version of your app, you can share the app with others using a customised url. To share an app:
- Click on the **Share** button on the top-right corner
<div style={{textAlign: 'center'}}>
![ToolJet - Managing Users and Groups](/img/tutorial/sharing/share.png)
</div>
- In the dialog box, turn on the toggle switch to `Make the application public` and shareable
<div style={{textAlign: 'center'}}>
![ToolJet - Managing Users and Groups](/img/tutorial/sharing/toggle.png)
</div>
- Create your own `customised URL` for the app and click on `copy` to copy the URL
<div style={{textAlign: 'center'}}>
![ToolJet - Managing Users and Groups](/img/tutorial/sharing/url.png)
</div>
- You can also `Embedd` your application using the embeddable link
<div style={{textAlign: 'center'}}>
![ToolJet - Managing Users and Groups](/img/tutorial/sharing/embedd.png)
</div>

View file

@ -1,5 +1,5 @@
---
tracking: 12
sidebar_position: 13
---
# Tracking

View file

@ -20,14 +20,26 @@ return data.map((row) => {
The query will now look like this:
<img class="screenshot-full" src="/img/tutorial/transformations/transform.gif" alt="ToolJet - Query result transformations" height="420"/>
<div style={{textAlign: 'center'}}>
![ToolJet - Tutorial - Query result transformations](/img/tutorial/transformations/transform.gif)
</div>
Click the `create` button to create the query. Saved queries can be run using the `run` icon near the query name. Queries run using the run button wil behave just as if it was triggered by an app event like button click and thus will alter the state of the app. You can view the query results using the state inspector on the left side-bar of the app builder.
<img class="screenshot-full" src="/img/tutorial/transformations/result.gif" alt="ToolJet - Query result transformations" height="420"/>
<div style={{textAlign: 'center'}}>
![ToolJet - Tutorial - Query result transformations](/img/tutorial/transformations/result.gif)
</div>
We can see that `first_name` and `last_name` is added to all the rows in the `data` object of the query. If you need the original data of the query, it will be available in the `rawData` object of the query.
<img class="screenshot-full" src="/img/tutorial/transformations/rawdata.png" alt="ToolJet - Query result transformations" height="420"/>
<div style={{textAlign: 'center'}}>
![ToolJet - Tutorial - Query result transformations](/img/tutorial/transformations/rawdata.png)
</div>
In the next section, we will see how we can this data using ToolJet's built-in widgets.

View file

@ -0,0 +1,73 @@
---
sidebar_position: 9
---
# Versioning and Release
Versioning and Release lets you version control your apps and release app changes to the users.
## Versioning
Versioning is really useful if multiple developers are working on an app, it allows them to save their own version of the app. This also prevents developers from overwriting the other developer's work.
### Creating a Version
You can create new versions from **App Version Manager** on the top-right corner. It displays the version of the app that you're currently working and can be used to switch between the different version of the app. To create a new version:
- Go to the **App Version Manager** and click on the dropdown. It will display all the versions of the app that have been created.
<div style={{textAlign: 'center'}}>
![ToolJet - Managing Users and Groups](/img/tutorial/versioning-and-release/appversion.png)
</div>
- Click on **Create Version** and a modal will pop-up. Enter a **Version Name** and click on **Create version from** dropdown that will include all the versions of the app, choose a version that you want to use for your new version and then click on `Create Version`.
<div style={{textAlign: 'center'}}>
![ToolJet - Managing Users and Groups](/img/tutorial/versioning-and-release/modal.png)
</div>
## Release
Making a release let's you publish the app and push the changes to production.
### Releasing a version
To release a version:
- Go to the **App Version Manager** and select the `version` from the dropdown that you want to release.
<div style={{textAlign: 'center'}}>
![ToolJet - Managing Users and Groups](/img/tutorial/versioning-and-release/versiondropdown.png)
</div>
- Click on the `Release` button on the top-right corner.
<div style={{textAlign: 'center'}}>
![ToolJet - Managing Users and Groups](/img/tutorial/versioning-and-release/release.png)
</div>
:::tip
ToolJet will block editing of the `Released version` of an app and will display a prompt to create a new version to make the changes. This is to prevent accidentally pushing an unfinished app to the live version.
<div style={{textAlign: 'center'}}>
![ToolJet - Managing Users and Groups](/img/tutorial/versioning-and-release/prompt.png)
</div>
:::

View file

@ -64,3 +64,16 @@ Example:
The chart will look like this:
<img class="screenshot-full" src="/img/widgets/chart/pie.png" alt="ToolJet - line charts" height="420"/>
## Visually using JSON
In the chart widget, you can also plot a chart with JSON data. So the JSON will contain the information about the chart type, chart data, etc. You can learn more about the JSON properties from [here](https://plotly.com/javascript/reference/).
Anyway, to work with the JSON you need to enable the ``Use Plotly JSON schema`` toggle from the properties section.
<img class="screenshot-full" src="/img/widgets/chart/plot_from_json.png" alt="ToolJet - line charts" height="420"/>
It will show the ``Json description`` field to put the JSON data.
The end result will be like this:
<img class="screenshot-full" src="/img/widgets/chart/from_json.png" alt="ToolJet - line charts" height="420"/>

View file

@ -0,0 +1,25 @@
# Circular Progress Bar
Circular progress bar widget can be used to show progress in a progress circle.
<img class="screenshot-full" src="/img/widgets/circular-progressbar/circular-progress.gif" alt="ToolJet - Widget Reference - Tags" height="420"/>
#### Properties
| properties | description |
| ----------- | ----------- |
| Text | We can set a text inside the progress circle.|
| Progress | It can be used to set the progress of the widget. Progress should be an integer between 0 and 100.|
#### Styles
| properties | description |
| ----------- | ----------- |
| Color | To define stroke color.|
| Stroke width | To define the width of stroke, value must between 0-100. ``Default: 8``.|
| Counter Clockwise | Whether to rotate progress bar in counterclockwise direction. ``Default: false``.|
| circleRatio | To define ratio of the full circle diameter the progressbar should use. ``Default: 1``.|
#### More info
Circular progress bar widget uses [react-circular-progress](https://github.com/kevinsqi/react-circular-progressbar) package. Check the repo for futher more details about properties and styles.

View file

@ -21,7 +21,7 @@ Filepicker widget allows the user to drag and drop files or upload files by brow
On file selected event can be triggered when one or more files are selected.
#### Properties
## Properties
| properties | description |
| ----------- | ----------- |
@ -33,8 +33,20 @@ On file selected event can be triggered when one or more files are selected.
| Max size limit| Maximum file size (in bytes).|
| Min size limit| Minimum file size (in bytes).|
:::tip::
:::tip
Files can be accepted or rejected based on the file types, maximum file count, maximum file size (in bytes) and minimum file size (in bytes).
If `Pick mulitple files` is set to false and additional files are dropped, all files besides the first will be rejected.
Any file that does not have a size in the range of `Max size limit` and `Min size limit` will be rejected.
:::
:::
## Options
| options | description |
| ----------- | ----------- |
| Parse content | parse the selected files, supports **CSV** files. |
| File type | If **Parse content** is enabled, options to auto-detect files and parse content or parse selected file types. |
:::info
If the **Parse content** option is toggled on, it only parses the next file that is selected, not the already selected one.
:::

View file

@ -0,0 +1,79 @@
# List view
List view widget allows to create a list of repeatable rows of data. Just like container widget, you can nest other widgets inside of it and control how many times they repeat.
<div style={{textAlign: 'center'}}>
![ToolJet - List view widget](/img/widgets/list-view/listviewapp.png)
</div>
### Properties
#### Layout
| Layout | description |
| ----------- | ----------- |
| List data | Enter the data that you want to diplay into the widget. Data in the form of array of objects or data from a query that returns an array of objects.|
| Row height | The default value of row height is set to `100`, you can enter a number to set the row height accordingly. |
| Show bottom border | This property displays a border after every row and is set `{{true}}` by default. Set it `{{false}}` to remove the border. |
<div style={{textAlign: 'center'}}>
![ToolJet - List view widget](/img/widgets/list-view/layout.png)
</div>
#### Styles
| Style | Description |
| ----------- | ----------- |
| backgroundColor | You can change the background color of the widget by entering the Hex color code or choosing a color of your choice from the color picker. |
| Visibility | This is to control the visibility of the widget. If `{{false}}` the widget will not visible after the app is deployed. It can only have boolean values i.e. either `{{true}}` or `{{false}}`. By default, it's set to `{{true}}`. |
| Disable | This property only accepts boolean values. If set to `{{true}}`, the widget will be locked and becomes non-functional. By default, its value is set to `{{false}}`. |
<div style={{textAlign: 'center'}}>
![ToolJet - List view widget](/img/widgets/list-view/style.png)
</div>
### Example: Displaying data in the list view
- Let's start by creating a new app and then dragging the List view widget onto the canvas.
<div style={{textAlign: 'center'}}>
![ToolJet - List view widget](/img/widgets/list-view/emptylist.png)
</div>
- Now lets create a query and select REST API from the datasource dropdown. Chose the `GET` method and enter the API endpoint - `https://reqres.in/api/users?page=1`. Save this query and fire it. Inspect the query results from the left sidebar, you'll see that it resulted the `data` object having array of objects.
<div style={{textAlign: 'center'}}>
![ToolJet - List view widget](/img/widgets/list-view/data.gif)
</div>
- Now lets edit the `List data` property of list view widget for displaying the query data. We will use JS to get the data from the query - `{{queries.restapi1.data.data}}`. Here the last `data` is data object that includes array of objects, the first `data` is the data resulted from the `restapi1` query. This will automatically create the rows in the widget using the data.
<div style={{textAlign: 'center'}}>
![ToolJet - List view widget](/img/widgets/list-view/datadisplay.png)
</div>
- Finally, we will need to nest widgets into the first row of list view widget and the widget will automatically create the subsequent instances. The subsequent rows will appear the same way you'll display the data in the first row.
<div style={{textAlign: 'center'}}>
![ToolJet - List view widget](/img/widgets/list-view/addingwidgets.gif)
</div>
:::tip
Use `{{listItem.key}}` to display data on the nested widgets. Example: For displaying the images we used `{{listItem.avatar}}` where **avatar** is one of the key in the objects from the query result.
:::

View file

@ -10,6 +10,8 @@ Numbers can be changed by using the arrow keys.
#### Properties
| properties | description |
| ----------- | ----------- |
| Placeholder | It specifies a hint that describes the expected value.|
| properties | description |
| ------------- | ---------------------------------------------------------- |
| Placeholder | It specifies a hint that describes the expected value. |
| Maximum value | It specifies the maximum value the number input can go to. |
| Minimum value | It specifies the minimum value the number input can go to. |

View file

@ -0,0 +1,32 @@
# Statistics
Statistics can be used to display different statistical information.
<img class="screenshot-full" src="/img/widgets/statistics/statistics.gif" alt="ToolJet - Star rating Widget" height="420"/>
#### Properties
| properties | description |
| ---------------------- | ------------------------------------------------------------------------------------------------------------------------ |
| Primary value label | This property lets you add and remove primary value label. |
| Primary value | This property lets you add and remove primary value,the actual amount can be represented here. |
| Secondary value label | This property lets you add and remove secondary value label. |
| Secondary value | This property lets you add and remove secondary value,the chnage in value can be represented here. |
| Secondaory sign display | This property lets you add and secondary sign either positive or negative,can be used to represent positive(increase) or negative(decrease) movement.Default value is positive.|
#### Layout
| Layout | description |
| --------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
| Show on desktop | This property have toggle switch. If enabled, the Tabs widget will display in the desktop view else it will not appear. This is enabled by default. |
| Show on mobile | This property have toggle switch. If enabled, the Tabs wisget will display in the mobile view else it will not appear. |
#### Styles
| Style | Description |
| --------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Primary Label Colour | You can change the primary label color by entering the Hex color code or choosing a color of your choice from the color picker.|
| Primary Text Colour | You can change the primary text color of the primary la bbey entering the Hex color code or choosing a color of your choice from the color picker.|
| Secondary Label Colour| You can change the secondary label color of the primary la bbey entering the Hex color code or choosing a color of your choice from the color picker.|
| Secondary Text Colour | You can change the secondary text color of the primary la bbey entering the Hex color code or choosing a color of your choice from the color picker.|

View file

@ -138,4 +138,5 @@ If the data of a cell is changed, "save changes" button will be shown at the bot
| Style | Description |
| ----------- | ----------- |
| Cell size | This decides the size of table cells. You can choose between a `Compact` size for table cells or a `Spacious` size |
| Cell size | This decides the size of table cells. You can choose between a `Compact` size for table cells or a `Spacious` size |
| Action button radius | This field can be used to give a radius to all action buttons. The default value is `0` |

11
docs/docs/widgets/tags.md Normal file
View file

@ -0,0 +1,11 @@
# Tags
Tags widget can be used to show array of data as tags.
<img class="screenshot-full" src="/img/widgets/tags/tags.gif" alt="ToolJet - Widget Reference - Tags" height="420"/>
#### Properties
| properties | description |
| ----------- | ----------- |
| Data | It can be used to set array of tags. It must be an array of objects like this ```[ { title: 'tag1', color: '#000000', textColor: '#fff' }, { title: 'tag2', color: '#fefefe', textColor: 'green' } ]```. Each object should contain a title and color code of a particular tag, also a text color.|

View file

@ -10,6 +10,7 @@ module.exports = {
organizationName: 'ToolJet', // Usually your GitHub org/user name.
projectName: 'ToolJet', // Usually your repo name.
themeConfig: {
image: 'img/tooljet-og-image.png',
announcementBar: {
id: 'support_us',
content:
@ -36,11 +37,11 @@ module.exports = {
},
},
navbar: {
title: 'ToolJet',
logo: {
href: '/docs/intro',
alt: 'ToolJet Logo',
src: 'img/logo.svg',
width: 90
},
items: [
{

View file

@ -7,7 +7,7 @@
/* You can override the default Infima variables here. */
:root {
--ifm-color-primary: #3c92dc;
--ifm-color-primary: #4d72fa;
--ifm-color-primary-dark: rgb(33, 175, 144);
--ifm-color-primary-darker: rgb(31, 165, 136);
--ifm-color-primary-darkest: rgb(26, 136, 112);
@ -15,6 +15,7 @@
--ifm-color-primary-lighter: rgb(102, 212, 189);
--ifm-color-primary-lightest: rgb(146, 224, 208);
--ifm-code-font-size: 95%;
--ifm-menu-color-active: #4d72fa;
--tblr-blue: #206bc4;
--tblr-azure: #4299e1;
--tblr-indigo: #4263eb;
@ -148,7 +149,7 @@ body {
}
strong {
color: #3c92dc;
color: #4d72fa;
}
.alert a {

Binary file not shown.

After

Width:  |  Height:  |  Size: 428 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 102 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 439 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

BIN
docs/static/img/how-it-works.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 101 KiB

View file

@ -1,10 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="215px" height="190px" viewBox="0 0 215 190" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<svg width="637px" height="128px" viewBox="0 0 637 128" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>logo</title>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="logo" fill="#4D72DA" fill-rule="nonzero">
<path d="M214.605,188.381 C214.605,189.21 213.926,189.889 213.097,189.889 C213.082,189.889 213.082,189.889 213.068,189.889 C212.735,189.889 212.388,189.785 212.116,189.558 C195.325,175.876 160.494,166.296 121.197,164.532 C120.411,164.502 119.778,163.868 119.749,163.098 C116.369,87.596 110.274,65.933 107.515,65.043 C104.844,65.933 98.749,87.596 95.37,163.098 C95.34,163.868 94.706,164.501 93.922,164.532 C54.625,166.297 19.792,175.877 3.002,189.558 C2.443,190.01 1.629,189.996 1.086,189.528 C0.528,189.06 0.378,188.275 0.739,187.642 L106.247,0.824 C106.775,-0.127 108.344,-0.127 108.872,0.824 L214.243,187.4 C214.47,187.672 214.605,188.003 214.605,188.381 Z" id="Path"></path>
<path d="M115.715,166.383 C112.789,187.097 109.954,189.889 107.573,189.889 C105.191,189.889 102.358,187.097 99.433,166.383 C99.38,166.013 99.486,165.642 99.737,165.351 C99.975,165.06 100.333,164.888 100.703,164.888 C102.848,164.823 105.097,164.796 107.585,164.796 C110.06,164.796 112.31,164.822 114.44,164.888 C114.812,164.888 115.168,165.06 115.407,165.351 C115.662,165.642 115.768,166.013 115.715,166.383 Z" id="Path"></path>
<g id="logo" fill="#4D72FA" fill-rule="nonzero">
<path d="M98.855,2.691 L98.855,22.238 C98.855,22.921 98.296,23.479 97.614,23.479 L62.044,23.479 L62.044,126.315 C62.044,126.999 61.485,127.556 60.803,127.556 L38.165,127.556 C37.482,127.556 36.924,126.998 36.924,126.315 L36.924,23.479 L1.442,23.479 C0.759,23.479 0.201,22.921 0.201,22.238 L0.201,2.691 C0.201,2.009 0.76,1.45 1.442,1.45 L97.614,1.45 C98.296,1.45 98.855,2.009 98.855,2.691 Z" id="Path"></path>
<path d="M193.215,56.977 C190.584,50.821 186.885,45.385 182.219,40.805 C177.552,36.225 171.905,32.565 165.464,29.909 C158.998,27.253 151.862,25.9 144.216,25.9 C136.633,25.9 129.534,27.253 123.105,29.909 C116.688,32.565 111.067,36.226 106.4,40.805 C101.721,45.385 98.035,50.821 95.442,56.977 C92.847,63.133 91.532,69.797 91.532,76.771 C91.532,83.76 92.86,90.423 95.491,96.579 C98.11,102.735 101.796,108.173 106.438,112.751 C111.08,117.33 116.677,120.98 123.068,123.599 C129.46,126.229 136.546,127.558 144.13,127.558 C151.824,127.558 158.998,126.229 165.452,123.599 C171.906,120.98 177.565,117.33 182.256,112.751 C186.96,108.173 190.671,102.749 193.265,96.629 C195.859,90.499 197.187,83.822 197.187,76.772 C197.187,69.797 195.846,63.132 193.215,56.977 Z M144.403,105.986 C140.469,105.986 136.745,105.254 133.345,103.814 C129.932,102.376 126.916,100.339 124.372,97.769 C121.84,95.202 119.805,92.086 118.328,88.524 C116.851,84.974 116.094,80.991 116.094,76.684 C116.094,72.452 116.852,68.493 118.328,64.931 C119.805,61.369 121.84,58.266 124.372,55.697 C126.916,53.128 129.932,51.117 133.333,49.702 C136.746,48.288 140.469,47.568 144.403,47.568 C148.276,47.568 151.974,48.3 155.411,49.74 C158.861,51.192 161.89,53.203 164.434,55.747 C166.966,58.291 169.001,61.381 170.478,64.931 C171.955,68.493 172.7,72.452 172.7,76.684 C172.7,80.991 171.955,84.987 170.478,88.574 C169,92.161 166.965,95.288 164.421,97.857 C161.889,100.426 158.874,102.437 155.473,103.851 C152.06,105.267 148.337,105.986 144.403,105.986 Z" id="Shape"></path>
<path d="M312.174,56.977 C309.555,50.821 305.857,45.385 301.177,40.805 C296.511,36.225 290.876,32.565 284.422,29.909 C277.969,27.253 270.82,25.9 263.175,25.9 C255.605,25.9 248.492,27.253 242.065,29.909 C235.648,32.565 230.026,36.226 225.36,40.805 C220.694,45.384 217.006,50.821 214.401,56.977 C211.807,63.133 210.491,69.797 210.491,76.771 C210.491,83.76 211.819,90.423 214.451,96.579 C217.082,102.735 220.767,108.173 225.397,112.751 C230.04,117.33 235.636,120.98 242.027,123.599 C248.42,126.229 255.506,127.558 263.09,127.558 C270.783,127.558 277.957,126.229 284.411,123.599 C290.877,120.98 296.524,117.33 301.227,112.751 C305.931,108.173 309.63,102.749 312.224,96.629 C314.829,90.499 316.146,83.822 316.146,76.772 C316.146,69.797 314.805,63.132 312.174,56.977 Z M263.361,105.986 C259.426,105.986 255.704,105.254 252.302,103.814 C248.889,102.376 245.874,100.339 243.33,97.769 C240.798,95.202 238.762,92.098 237.285,88.524 C235.807,84.962 235.063,80.978 235.063,76.684 C235.063,72.452 235.807,68.493 237.285,64.931 C238.762,61.369 240.798,58.266 243.33,55.697 C245.874,53.128 248.889,51.117 252.29,49.702 C255.703,48.288 259.426,47.568 263.36,47.568 C267.232,47.568 270.944,48.3 274.381,49.74 C277.819,51.192 280.847,53.203 283.392,55.747 C285.923,58.291 287.959,61.381 289.436,64.931 C290.914,68.493 291.658,72.452 291.658,76.684 C291.658,80.991 290.914,84.987 289.436,88.574 C287.959,92.173 285.923,95.288 283.379,97.857 C280.847,100.426 277.832,102.437 274.431,103.851 C271.019,105.267 267.296,105.986 263.361,105.986 Z" id="Shape"></path>
<path d="M359.385,2.691 L359.385,126.316 C359.385,127 358.826,127.557 358.144,127.557 L336.053,127.557 C335.369,127.557 334.812,126.999 334.812,126.316 L334.812,2.691 C334.812,2.009 335.37,1.45 336.053,1.45 L358.144,1.45 C358.826,1.45 359.385,2.009 359.385,2.691 Z" id="Path"></path>
<path d="M433.527,2.691 L433.527,85.782 C433.527,92.583 432.509,98.638 430.486,103.778 C428.45,108.964 425.484,113.382 421.673,116.92 C417.864,120.444 413.149,123.139 407.675,124.9 C402.263,126.663 396.046,127.556 389.195,127.556 L374.836,127.556 C374.153,127.556 373.596,126.998 373.596,126.315 L373.596,106.767 C373.596,106.085 374.154,105.526 374.836,105.526 L389.195,105.526 C396.133,105.526 401.122,103.814 404.026,100.426 C407.005,96.976 408.506,92.023 408.506,85.682 L408.58,2.69 C408.58,2.008 409.139,1.449 409.821,1.449 L432.285,1.449 C432.969,1.449 433.527,2.009 433.527,2.691 Z" id="Path"></path>
<path d="M551.803,56.977 C549.172,50.821 545.473,45.385 540.795,40.805 C536.129,36.225 530.494,32.565 524.04,29.909 C517.586,27.253 510.437,25.9 502.792,25.9 C495.223,25.9 488.122,27.253 481.693,29.909 C475.265,32.565 469.642,36.226 464.976,40.805 C460.31,45.384 456.622,50.821 454.03,56.977 C451.424,63.133 450.107,69.797 450.107,76.771 C450.107,83.76 451.423,90.412 454.03,96.53 C456.623,102.661 460.31,108.085 464.976,112.664 C469.642,117.23 475.265,120.905 481.693,123.561 C488.122,126.216 495.222,127.557 502.792,127.557 C509.085,127.557 514.955,126.663 520.23,124.901 C525.517,123.151 530.295,120.743 534.466,117.791 C538.635,114.824 542.259,111.349 545.238,107.489 C548.203,103.618 550.5,99.521 552.051,95.289 C552.187,94.917 552.137,94.495 551.902,94.16 C551.666,93.825 551.294,93.626 550.884,93.626 L526.981,93.626 C526.522,93.626 526.112,93.874 525.889,94.272 C523.828,97.984 520.776,101.037 516.804,103.333 C512.844,105.642 508.19,106.808 502.978,106.808 C499.689,106.808 496.437,106.237 493.31,105.108 C490.182,103.978 487.29,102.365 484.708,100.304 C482.14,98.257 479.905,95.725 478.081,92.759 C476.506,90.214 475.338,87.372 474.606,84.295 L553.974,84.295 C554.594,84.295 555.116,83.835 555.203,83.227 C555.327,82.372 555.438,81.491 555.563,80.583 C555.699,79.603 555.760006,78.361 555.760006,76.772 C555.762,69.797 554.435,63.132 551.803,56.977 Z M502.979,46.117 C506.455,46.117 509.693,46.651 512.598,47.718 C515.514,48.785 518.158,50.287 520.466,52.186 C522.774,54.097 524.76,56.394 526.373,59.024 C527.726,61.221 528.806,63.616 529.6,66.172 L475.352,66.172 C476.159,63.629 477.263,61.233 478.665,59.036 C480.341,56.406 482.401,54.109 484.797,52.21 C487.192,50.298 489.947,48.797 492.987,47.717 C496.016,46.65 499.379,46.117 502.979,46.117 Z" id="Shape"></path>
<path d="M636.458,108.146 L636.271,126.327 C636.258,127.011 635.712,127.556 635.03,127.556 L617.122,127.556 C612.033,127.556 607.168,127.022 602.662,125.968 C598.058,124.9 593.988,122.902 590.587,120.035 C587.187,117.155 584.456,113.183 582.471,108.231 C580.51,103.317 579.517,96.951 579.517,89.317 L579.517,52.11 L565.133,52.11 C564.449,52.11 563.892,51.551 563.892,50.869 L563.892,33.779 C563.892,33.22 564.264,32.736 564.797,32.587 L579.108,28.616 L583.426,1.486 C583.526,0.89 584.046,0.443 584.655,0.443 L602.85,0.443 C603.532,0.443 604.09,1.002 604.09,1.684 L604.09,30.539 L632.673,30.539 C633.356,30.539 633.914,31.098 633.914,31.78 L633.914,50.868 C633.914,51.55 633.355,52.109 632.673,52.109 L604.003,52.109 L604.003,89.13 C604.003,92.742 604.425,95.734 605.244,98.03 C606.063,100.3 607.143,102.099 608.483,103.379 C609.812,104.657 611.399,105.563 613.199,106.071 C615.061,106.618 617.084,106.89 619.219,106.89 L635.217,106.89 C635.552,106.89 635.862,107.027 636.098,107.262 C636.333,107.5 636.458,107.811 636.458,108.146 Z" id="Path"></path>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 7.5 KiB

BIN
docs/static/img/sso/git/client-id.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 181 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 242 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 67 KiB

BIN
docs/static/img/tooljet-og-image.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 115 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 145 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.7 MiB

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