+
:::tip
Airtable API has a rate limit and at the time of writing this documentation, the limit is 5 requests per second per base. You can read more about rate limits here ( https://airtable.com/api ).
:::
@@ -20,6 +22,8 @@ Supported queries:
- Listing records
- Retrieving a record
+- Updating a record
+- Deleting a record
## Listing records
@@ -88,4 +92,61 @@ Example response from Airtable:
},
"createdTime": "2021-05-12T14:30:33.000Z"
}
+```
+
+## Updating a record
+
+Required parameters:
+- Base ID
+- Table name
+- Record ID
+
+
+
+#### Example body:
+
+
+
+
+Click on the `run` button to run the query.
+
+:::info
+NOTE: Query must be saved before running.
+:::
+
+Example response from Airtable:
+```json
+{
+ "id": "recu9xMnUdr2n2cw8",
+ "fields": {
+ "Notes": "Example Notes",
+ "Name": "change"
+ },
+ "createdTime": "2021-08-08T17:27:17.000Z"
+}
+```
+
+## Deleting a record
+
+Required parameters:
+- Base ID
+- Table name
+- Record ID
+
+
+
+
+Click on the `run` button to run the query.
+
+:::info
+NOTE: Query must be saved before running.
+:::
+
+Example response from Airtable:
+
+```json
+{
+ deleted: true
+ id: "recIKsyZgqI4zoqS7"
+}
```
\ No newline at end of file
diff --git a/docs/docs/deployment/env-vars.md b/docs/docs/deployment/env-vars.md
index b6c04fb80f..05c94af43b 100644
--- a/docs/docs/deployment/env-vars.md
+++ b/docs/docs/deployment/env-vars.md
@@ -51,6 +51,10 @@ If want to restrict the signups and allow new users only by invitations, set the
You will still be able to see the signup page but won't be able to successfully submit the form.
:::
+#### Serve client as a server end-point ( optional )
+
+By default, the `SERVE_CLIENT` variable will be set to `false` and the server won't serve the client at its `/` end-point.
+You can set `SERVE_CLIENT` to `true` and the server will attempt to serve the client at its root end-point (`/`).
#### SMTP configuration ( optional )
diff --git a/docs/docs/deployment/kubernetes.md b/docs/docs/deployment/kubernetes.md
index 42edf933aa..8007f8c586 100644
--- a/docs/docs/deployment/kubernetes.md
+++ b/docs/docs/deployment/kubernetes.md
@@ -21,12 +21,12 @@ Follow the steps below to deploy ToolJet on a Kubernetes cluster.
3. Create a Kubernetes deployment
```bash
- kubectl apply -f https://raw.githubusercontent.com/ToolJet/ToolJet/main/deploy/kubernetes/server-deployment.yaml
+ kubectl apply -f https://raw.githubusercontent.com/ToolJet/ToolJet/main/deploy/kubernetes/deployment.yaml
```
- :::info
- The file given above is just a template and might not suit production environments. You should download the file and configure parameters such as the replica count and environment variables according to your needs.
- :::
+:::info
+The file given above is just a template and might not suit production environments. You should download the file and configure parameters such as the replica count and environment variables according to your needs.
+:::
4. Verify if ToolJet is running
diff --git a/docs/docs/widgets/qr-scanner.md b/docs/docs/widgets/qr-scanner.md
new file mode 100644
index 0000000000..aa604b48c3
--- /dev/null
+++ b/docs/docs/widgets/qr-scanner.md
@@ -0,0 +1,24 @@
+---
+sidebar_position: 1
+---
+
+# QR Scanner
+Scan QR codes using device camera and hold the data they carry.
+
+
+#### Known issue:
+In IOS, you might have to stick to the Safari browser as camera access had been restricted for third party browsers.
+
+## Exposed variables
+#### lastDetectedValue
+This variable holds the data contained in the last QR code scanned by the widget.
+
+## Events
+#### onDetect
+This event is fired whenever the widget successfully scans a QR code.
+
+## Debugging tip
+Browser camera APIs restrict this widget to only work in either `localhost` or `https`.
+
+So if you're testing it out, be sure to either use `localhost` or `https`.
+
diff --git a/docs/docs/widgets/radio-button.md b/docs/docs/widgets/radio-button.md
new file mode 100644
index 0000000000..895d8aafb2
--- /dev/null
+++ b/docs/docs/widgets/radio-button.md
@@ -0,0 +1,35 @@
+---
+sidebar_position: 2
+---
+
+# Radio Button
+
+Radio Buttons can be used to select one option from a group of options.
+
+
+
+:::tip
+Radio buttons are preferred when the list of options is less than six and all the options can be displayed at once.
+:::
+
+:::info
+For more than six options, consider using [Dropdown](/docs/widgets/dropdown) widget.
+:::
+
+
+## Event: onSelectionChange
+
+This event is triggered when an option is clicked.
+
+
+## Property : Values (Array)
+
+This property can be used for setting the value of the input it was called on.
+
+## Property : Display Values (Array of strings)
+
+This property specifies the values to be displayed as options
+
+
+## Example
+
\ No newline at end of file
diff --git a/docs/docs/widgets/table.md b/docs/docs/widgets/table.md
index 568647f7b7..b1c277f78c 100644
--- a/docs/docs/widgets/table.md
+++ b/docs/docs/widgets/table.md
@@ -39,6 +39,7 @@ To display email column, the key for the column should be `user.email`.
- Tags - similar to badges but the values are not predefined.
- Dropdown
- Multiselect dropdown
+- Toggle switch
## Client-side pagination
@@ -51,6 +52,8 @@ Server-side pagination can be used to run a query whenever the page is changed.
## Search
Client-side search is enabled by default and server-side search can be enabled from the events section of the inspector. Whenever the search text is changed, the `searchText` property of the table component is updated. If server-side search is enabled, `on search` event is fired after the content of `searchText` property is changed. `searchText` can be used to run a specific query to search for the records in your datasource.
+If you don't wish to use the search feature altogether, you can disable it from the inspector.
+
## Event: On row clicked
This event is triggered when a table row is clicked. `selectedRow` property of the table object will have the table data of the selected row.
diff --git a/docs/docs/widgets/toggle-switch.md b/docs/docs/widgets/toggle-switch.md
new file mode 100644
index 0000000000..6e197be4e8
--- /dev/null
+++ b/docs/docs/widgets/toggle-switch.md
@@ -0,0 +1,20 @@
+---
+sidebar_position: 2
+---
+
+# Toggle Switch
+
+Toggle switch widget allows the user to change a setting between two states.
+
+The Toggle switch widget should be used if we want to make a binary choice,
+such as turning something **on or off** or **enable or disable**.
+
+
+
+
+## Event: onChange
+This event is triggered whenever toggle switch is clicked.
+
+## Property : Label
+This property can be used to set a label for the switch.
+Default Label: **Toggle label**
\ No newline at end of file
diff --git a/docs/static/img/datasource-reference/airtable-delete.png b/docs/static/img/datasource-reference/airtable-delete.png
new file mode 100644
index 0000000000..0cfc7e7d52
Binary files /dev/null and b/docs/static/img/datasource-reference/airtable-delete.png differ
diff --git a/docs/static/img/datasource-reference/airtable-intro.gif b/docs/static/img/datasource-reference/airtable-intro.gif
new file mode 100644
index 0000000000..e97c799525
Binary files /dev/null and b/docs/static/img/datasource-reference/airtable-intro.gif differ
diff --git a/docs/static/img/datasource-reference/airtable-update-example-body.png b/docs/static/img/datasource-reference/airtable-update-example-body.png
new file mode 100644
index 0000000000..b166effcac
Binary files /dev/null and b/docs/static/img/datasource-reference/airtable-update-example-body.png differ
diff --git a/docs/static/img/datasource-reference/airtable-update.png b/docs/static/img/datasource-reference/airtable-update.png
new file mode 100644
index 0000000000..f3b2a9a721
Binary files /dev/null and b/docs/static/img/datasource-reference/airtable-update.png differ
diff --git a/docs/static/img/widgets/qr-scanner/qr-scanner.jpeg b/docs/static/img/widgets/qr-scanner/qr-scanner.jpeg
new file mode 100644
index 0000000000..0dc368a4ba
Binary files /dev/null and b/docs/static/img/widgets/qr-scanner/qr-scanner.jpeg differ
diff --git a/docs/static/img/widgets/radio-button/property.gif b/docs/static/img/widgets/radio-button/property.gif
new file mode 100644
index 0000000000..d51dd91c0b
Binary files /dev/null and b/docs/static/img/widgets/radio-button/property.gif differ
diff --git a/docs/static/img/widgets/radio-button/widget.gif b/docs/static/img/widgets/radio-button/widget.gif
new file mode 100644
index 0000000000..8f23d457b3
Binary files /dev/null and b/docs/static/img/widgets/radio-button/widget.gif differ
diff --git a/docs/static/img/widgets/toggle-switch/toggle-switch.gif b/docs/static/img/widgets/toggle-switch/toggle-switch.gif
new file mode 100644
index 0000000000..9f092844a6
Binary files /dev/null and b/docs/static/img/widgets/toggle-switch/toggle-switch.gif differ
diff --git a/frontend/assets/images/icons/editor/left-sidebar/back.svg b/frontend/assets/images/icons/editor/left-sidebar/back.svg
new file mode 100644
index 0000000000..0cf2d04965
--- /dev/null
+++ b/frontend/assets/images/icons/editor/left-sidebar/back.svg
@@ -0,0 +1,40 @@
+
+
+
+
diff --git a/frontend/assets/images/icons/editor/left-sidebar/database.svg b/frontend/assets/images/icons/editor/left-sidebar/database.svg
new file mode 100644
index 0000000000..e08aede99c
--- /dev/null
+++ b/frontend/assets/images/icons/editor/left-sidebar/database.svg
@@ -0,0 +1,92 @@
+
+
+
diff --git a/frontend/assets/images/icons/editor/left-sidebar/debugger.svg b/frontend/assets/images/icons/editor/left-sidebar/debugger.svg
new file mode 100644
index 0000000000..10c0a14e49
--- /dev/null
+++ b/frontend/assets/images/icons/editor/left-sidebar/debugger.svg
@@ -0,0 +1,69 @@
+
+
+
diff --git a/frontend/assets/images/icons/editor/left-sidebar/inspector.svg b/frontend/assets/images/icons/editor/left-sidebar/inspector.svg
new file mode 100644
index 0000000000..f80b5e3431
--- /dev/null
+++ b/frontend/assets/images/icons/editor/left-sidebar/inspector.svg
@@ -0,0 +1,78 @@
+
+
+
+
diff --git a/frontend/assets/images/icons/editor/left-sidebar/support.svg b/frontend/assets/images/icons/editor/left-sidebar/support.svg
new file mode 100644
index 0000000000..1295c1f2e6
--- /dev/null
+++ b/frontend/assets/images/icons/editor/left-sidebar/support.svg
@@ -0,0 +1,5 @@
+
+
+
diff --git a/frontend/assets/images/icons/widgets/qrscanner.svg b/frontend/assets/images/icons/widgets/qrscanner.svg
new file mode 100644
index 0000000000..076e9d6889
--- /dev/null
+++ b/frontend/assets/images/icons/widgets/qrscanner.svg
@@ -0,0 +1 @@
+
diff --git a/frontend/assets/images/icons/widgets/radio-button.svg b/frontend/assets/images/icons/widgets/radio-button.svg
new file mode 100644
index 0000000000..e7ac452bb5
--- /dev/null
+++ b/frontend/assets/images/icons/widgets/radio-button.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/frontend/assets/images/icons/widgets/textarea.svg b/frontend/assets/images/icons/widgets/textarea.svg
index 85a1ac1549..a950ea3e8d 100644
--- a/frontend/assets/images/icons/widgets/textarea.svg
+++ b/frontend/assets/images/icons/widgets/textarea.svg
@@ -11,4 +11,4 @@
-
\ No newline at end of file
+
diff --git a/frontend/assets/images/icons/widgets/toggle.svg b/frontend/assets/images/icons/widgets/toggle.svg
new file mode 100644
index 0000000000..7e39fbc4ab
--- /dev/null
+++ b/frontend/assets/images/icons/widgets/toggle.svg
@@ -0,0 +1,5 @@
+
\ No newline at end of file
diff --git a/frontend/assets/images/icons/widgets/toggleswitch.svg b/frontend/assets/images/icons/widgets/toggleswitch.svg
new file mode 100644
index 0000000000..7e39fbc4ab
--- /dev/null
+++ b/frontend/assets/images/icons/widgets/toggleswitch.svg
@@ -0,0 +1,5 @@
+
\ No newline at end of file
diff --git a/frontend/package-lock.json b/frontend/package-lock.json
index 6720a0dc9d..7d2a26a6ba 100644
--- a/frontend/package-lock.json
+++ b/frontend/package-lock.json
@@ -5,6 +5,7 @@
"requires": true,
"packages": {
"": {
+ "name": "frontend",
"version": "0.1.0",
"dependencies": {
"@babel/core": "^7.4.3",
@@ -47,11 +48,13 @@
"react-lazyload": "^3.2.0",
"react-loading-skeleton": "^2.2.0",
"react-plotly.js": "^2.5.1",
+ "react-qr-reader": "^2.2.1",
"react-resizable": "^1.11.1",
"react-rnd": "^10.3.0",
"react-router-dom": "^5.0.0",
"react-scripts": "3.4.3",
"react-select-search": "^3.0.5",
+ "react-spring": "^9.2.4",
"react-table": "^7.6.3",
"react-table-plugins": "^1.3.1",
"react-toastify": "^7.0.3",
@@ -2227,6 +2230,133 @@
"resolved": "https://registry.npmjs.org/@react-google-maps/marker-clusterer/-/marker-clusterer-2.1.1.tgz",
"integrity": "sha512-LIqf1T2dVXRaf/gqk/7kEDpRvr1aQGlqOv/p5zwZus3qI6/3qK4jxNpc89gQ2WkCMrGwcI/fTQrnI55BZCxsLA=="
},
+ "node_modules/@react-spring/animated": {
+ "version": "9.2.4",
+ "resolved": "https://registry.npmjs.org/@react-spring/animated/-/animated-9.2.4.tgz",
+ "integrity": "sha512-AfV6ZM8pCCAT29GY5C8/1bOPjZrv/7kD0vedjiE/tEYvNDwg9GlscrvsTViWR2XykJoYrDfdkYArrldWpsCJ5g==",
+ "dependencies": {
+ "@react-spring/shared": "~9.2.0",
+ "@react-spring/types": "~9.2.0"
+ },
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0"
+ }
+ },
+ "node_modules/@react-spring/core": {
+ "version": "9.2.4",
+ "resolved": "https://registry.npmjs.org/@react-spring/core/-/core-9.2.4.tgz",
+ "integrity": "sha512-R+PwyfsjiuYCWqaTTfCpYpRmsP0h87RNm7uxC1Uxy7QAHUfHEm2sAHn+AdHPwq/MbVwDssVT8C5yf2WGcqiXGg==",
+ "hasInstallScript": true,
+ "dependencies": {
+ "@react-spring/animated": "~9.2.0",
+ "@react-spring/shared": "~9.2.0",
+ "@react-spring/types": "~9.2.0"
+ },
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0"
+ }
+ },
+ "node_modules/@react-spring/konva": {
+ "version": "9.2.4",
+ "resolved": "https://registry.npmjs.org/@react-spring/konva/-/konva-9.2.4.tgz",
+ "integrity": "sha512-19anDOIkfjcydDTfGgVIuZ3lruZxKubYGs9oHCswaP8SRLj7c1kkopJHUr/S4LXGxiIdqdF0XucWm0iTEPEq4w==",
+ "dependencies": {
+ "@react-spring/animated": "~9.2.0",
+ "@react-spring/core": "~9.2.0",
+ "@react-spring/shared": "~9.2.0",
+ "@react-spring/types": "~9.2.0"
+ },
+ "peerDependencies": {
+ "konva": ">=2.6",
+ "react": "^16.8.0 || ^17.0.0",
+ "react-konva": "^16.8.0 || ^17.0.0"
+ }
+ },
+ "node_modules/@react-spring/native": {
+ "version": "9.2.4",
+ "resolved": "https://registry.npmjs.org/@react-spring/native/-/native-9.2.4.tgz",
+ "integrity": "sha512-xKJWKh5qOhSclpL3iuGwJRLoZzTNvlBEnIrMs8yh8xvX6z9Lmnu4uGu5DpfrnM1GzBvRoktoCoLEx/VcEYFSng==",
+ "dependencies": {
+ "@react-spring/animated": "~9.2.0",
+ "@react-spring/core": "~9.2.0",
+ "@react-spring/shared": "~9.2.0",
+ "@react-spring/types": "~9.2.0"
+ },
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0",
+ "react-native": ">=0.58"
+ }
+ },
+ "node_modules/@react-spring/rafz": {
+ "version": "9.2.4",
+ "resolved": "https://registry.npmjs.org/@react-spring/rafz/-/rafz-9.2.4.tgz",
+ "integrity": "sha512-SOKf9eue+vAX+DGo7kWYNl9i9J3gPUlQjifIcV9Bzw9h3i30wPOOP0TjS7iMG/kLp2cdHQYDNFte6nt23VAZkQ=="
+ },
+ "node_modules/@react-spring/shared": {
+ "version": "9.2.4",
+ "resolved": "https://registry.npmjs.org/@react-spring/shared/-/shared-9.2.4.tgz",
+ "integrity": "sha512-ZEr4l2BxmyFRUvRA2VCkPfCJii4E7cGkwbjmTBx1EmcGrOnde/V2eF5dxqCTY3k35QuCegkrWe0coRJVkh8q2Q==",
+ "dependencies": {
+ "@react-spring/rafz": "~9.2.0",
+ "@react-spring/types": "~9.2.0"
+ },
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0"
+ }
+ },
+ "node_modules/@react-spring/three": {
+ "version": "9.2.4",
+ "resolved": "https://registry.npmjs.org/@react-spring/three/-/three-9.2.4.tgz",
+ "integrity": "sha512-ljFig7XW099VWwRPKPUf+4yYLivp/sSWXN3oO5SJOF/9BSoV1quS/9chZ5Myl5J14od3CsHf89Tv4FdlX5kHlA==",
+ "dependencies": {
+ "@react-spring/animated": "~9.2.0",
+ "@react-spring/core": "~9.2.0",
+ "@react-spring/shared": "~9.2.0",
+ "@react-spring/types": "~9.2.0"
+ },
+ "peerDependencies": {
+ "@react-three/fiber": ">=6.0",
+ "react": ">=16.11",
+ "three": ">=0.126"
+ }
+ },
+ "node_modules/@react-spring/types": {
+ "version": "9.2.4",
+ "resolved": "https://registry.npmjs.org/@react-spring/types/-/types-9.2.4.tgz",
+ "integrity": "sha512-zHUXrWO8nweUN/ISjrjqU7GgXXvoEbFca1CgiE0TY0H/dqJb3l+Rhx8ecPVNYimzFg3ZZ1/T0egpLop8SOv4aA=="
+ },
+ "node_modules/@react-spring/web": {
+ "version": "9.2.4",
+ "resolved": "https://registry.npmjs.org/@react-spring/web/-/web-9.2.4.tgz",
+ "integrity": "sha512-vtPvOalLFvuju/MDBtoSnCyt0xXSL6Amyv82fljOuWPl1yGd4M1WteijnYL9Zlriljl0a3oXcPunAVYTD9dbDQ==",
+ "dependencies": {
+ "@react-spring/animated": "~9.2.0",
+ "@react-spring/core": "~9.2.0",
+ "@react-spring/shared": "~9.2.0",
+ "@react-spring/types": "~9.2.0"
+ },
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0",
+ "react-dom": "^16.8.0 || ^17.0.0"
+ }
+ },
+ "node_modules/@react-spring/zdog": {
+ "version": "9.2.4",
+ "resolved": "https://registry.npmjs.org/@react-spring/zdog/-/zdog-9.2.4.tgz",
+ "integrity": "sha512-rv7ptedS37SHr6yuCbRkUErAzAhebdgt8f4KUtZWzseC+7qLNkaZWf+uujgsb881qAuX9b9yz8rre9UKeYepgw==",
+ "dependencies": {
+ "@react-spring/animated": "~9.2.0",
+ "@react-spring/core": "~9.2.0",
+ "@react-spring/shared": "~9.2.0",
+ "@react-spring/types": "~9.2.0"
+ },
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0",
+ "react-dom": "^16.8.0 || ^17.0.0",
+ "react-zdog": ">=1.0",
+ "zdog": ">=1.0"
+ }
+ },
"node_modules/@restart/context": {
"version": "2.1.4",
"resolved": "https://registry.npmjs.org/@restart/context/-/context-2.1.4.tgz",
@@ -8690,7 +8820,8 @@
"node_modules/flatten": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/flatten/-/flatten-1.0.3.tgz",
- "integrity": "sha512-dVsPA/UwQ8+2uoFe5GHtiBMu48dWLTdsuEd7CKGlZlD78r1TTWBvDuFaFGKCo/ZfEr95Uk56vZoX86OsHkUeIg=="
+ "integrity": "sha512-dVsPA/UwQ8+2uoFe5GHtiBMu48dWLTdsuEd7CKGlZlD78r1TTWBvDuFaFGKCo/ZfEr95Uk56vZoX86OsHkUeIg==",
+ "deprecated": "flatten is deprecated in favor of utility frameworks such as lodash."
},
"node_modules/flush-write-stream": {
"version": "1.1.1",
@@ -11633,6 +11764,11 @@
"verror": "1.10.0"
}
},
+ "node_modules/jsqr": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/jsqr/-/jsqr-1.4.0.tgz",
+ "integrity": "sha512-dxLob7q65Xg2DvstYkRpkYtmKm2sPJ9oFhrhmudT1dZvNFFTlroai3AWSpLey/w5vMcLBXRgOJsbXpdN9HzU/A=="
+ },
"node_modules/killable": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/killable/-/killable-1.0.1.tgz",
@@ -16191,6 +16327,20 @@
"react": "^15.0.0-0 || ^16.0.0-0 || ^17.0.0-0"
}
},
+ "node_modules/react-qr-reader": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/react-qr-reader/-/react-qr-reader-2.2.1.tgz",
+ "integrity": "sha512-EL5JEj53u2yAOgtpAKAVBzD/SiKWn0Bl7AZy6ZrSf1lub7xHwtaXe6XSx36Wbhl1VMGmvmrwYMRwO1aSCT2fwA==",
+ "dependencies": {
+ "jsqr": "^1.2.0",
+ "prop-types": "^15.7.2",
+ "webrtc-adapter": "^7.2.1"
+ },
+ "peerDependencies": {
+ "react": "~16",
+ "react-dom": "~16"
+ }
+ },
"node_modules/react-resizable": {
"version": "1.11.1",
"resolved": "https://registry.npmjs.org/react-resizable/-/react-resizable-1.11.1.tgz",
@@ -17207,6 +17357,19 @@
"node": ">=6"
}
},
+ "node_modules/react-spring": {
+ "version": "9.2.4",
+ "resolved": "https://registry.npmjs.org/react-spring/-/react-spring-9.2.4.tgz",
+ "integrity": "sha512-bMjbyTW0ZGd+/h9cjtohLqCwOGqX2OuaTvalOVfLCGmhzEg/u3GgopI3LAm4UD2Br3MNdVdGgNVoESg4MGqKFQ==",
+ "dependencies": {
+ "@react-spring/core": "~9.2.0",
+ "@react-spring/konva": "~9.2.0",
+ "@react-spring/native": "~9.2.0",
+ "@react-spring/three": "~9.2.0",
+ "@react-spring/web": "~9.2.0",
+ "@react-spring/zdog": "~9.2.0"
+ }
+ },
"node_modules/react-table": {
"version": "7.6.3",
"resolved": "https://registry.npmjs.org/react-table/-/react-table-7.6.3.tgz",
@@ -17954,6 +18117,18 @@
"node": "6.* || >= 7.*"
}
},
+ "node_modules/rtcpeerconnection-shim": {
+ "version": "1.2.15",
+ "resolved": "https://registry.npmjs.org/rtcpeerconnection-shim/-/rtcpeerconnection-shim-1.2.15.tgz",
+ "integrity": "sha512-C6DxhXt7bssQ1nHb154lqeL0SXz5Dx4RczXZu2Aa/L1NJFnEVDxFwCBo3fqtuljhHIGceg5JKBV4XJ0gW5JKyw==",
+ "dependencies": {
+ "sdp": "^2.6.0"
+ },
+ "engines": {
+ "node": ">=6.0.0",
+ "npm": ">=3.10.0"
+ }
+ },
"node_modules/run-async": {
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz",
@@ -18179,6 +18354,11 @@
"node": ">=0.8.0"
}
},
+ "node_modules/sdp": {
+ "version": "2.12.0",
+ "resolved": "https://registry.npmjs.org/sdp/-/sdp-2.12.0.tgz",
+ "integrity": "sha512-jhXqQAQVM+8Xj5EjJGVweuEzgtGWb3tmEEpl3CLP3cStInSbVHSg0QWOGQzNq8pSID4JkpeV2mPqlMDLrm0/Vw=="
+ },
"node_modules/select-hose": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz",
@@ -19279,6 +19459,7 @@
"version": "2.2.2",
"resolved": "https://registry.npmjs.org/tar/-/tar-2.2.2.tgz",
"integrity": "sha512-FCEhQ/4rE1zYv9rYXJw/msRqsnmlje5jHP6huWeBZ704jUTy02c5AZyWujpMR1ax6mVw9NyJMfuK2CMDWVIfgA==",
+ "deprecated": "This version of tar is no longer supported, and will not receive security updates. Please upgrade asap.",
"dependencies": {
"block-stream": "*",
"fstream": "^1.0.12",
@@ -20993,6 +21174,19 @@
"resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
"integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="
},
+ "node_modules/webrtc-adapter": {
+ "version": "7.7.1",
+ "resolved": "https://registry.npmjs.org/webrtc-adapter/-/webrtc-adapter-7.7.1.tgz",
+ "integrity": "sha512-TbrbBmiQBL9n0/5bvDdORc6ZfRY/Z7JnEj+EYOD1ghseZdpJ+nF2yx14k3LgQKc7JZnG7HAcL+zHnY25So9d7A==",
+ "dependencies": {
+ "rtcpeerconnection-shim": "^1.2.15",
+ "sdp": "^2.12.0"
+ },
+ "engines": {
+ "node": ">=6.0.0",
+ "npm": ">=3.10.0"
+ }
+ },
"node_modules/websocket-driver": {
"version": "0.7.4",
"resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz",
@@ -23233,6 +23427,99 @@
"resolved": "https://registry.npmjs.org/@react-google-maps/marker-clusterer/-/marker-clusterer-2.1.1.tgz",
"integrity": "sha512-LIqf1T2dVXRaf/gqk/7kEDpRvr1aQGlqOv/p5zwZus3qI6/3qK4jxNpc89gQ2WkCMrGwcI/fTQrnI55BZCxsLA=="
},
+ "@react-spring/animated": {
+ "version": "9.2.4",
+ "resolved": "https://registry.npmjs.org/@react-spring/animated/-/animated-9.2.4.tgz",
+ "integrity": "sha512-AfV6ZM8pCCAT29GY5C8/1bOPjZrv/7kD0vedjiE/tEYvNDwg9GlscrvsTViWR2XykJoYrDfdkYArrldWpsCJ5g==",
+ "requires": {
+ "@react-spring/shared": "~9.2.0",
+ "@react-spring/types": "~9.2.0"
+ }
+ },
+ "@react-spring/core": {
+ "version": "9.2.4",
+ "resolved": "https://registry.npmjs.org/@react-spring/core/-/core-9.2.4.tgz",
+ "integrity": "sha512-R+PwyfsjiuYCWqaTTfCpYpRmsP0h87RNm7uxC1Uxy7QAHUfHEm2sAHn+AdHPwq/MbVwDssVT8C5yf2WGcqiXGg==",
+ "requires": {
+ "@react-spring/animated": "~9.2.0",
+ "@react-spring/shared": "~9.2.0",
+ "@react-spring/types": "~9.2.0"
+ }
+ },
+ "@react-spring/konva": {
+ "version": "9.2.4",
+ "resolved": "https://registry.npmjs.org/@react-spring/konva/-/konva-9.2.4.tgz",
+ "integrity": "sha512-19anDOIkfjcydDTfGgVIuZ3lruZxKubYGs9oHCswaP8SRLj7c1kkopJHUr/S4LXGxiIdqdF0XucWm0iTEPEq4w==",
+ "requires": {
+ "@react-spring/animated": "~9.2.0",
+ "@react-spring/core": "~9.2.0",
+ "@react-spring/shared": "~9.2.0",
+ "@react-spring/types": "~9.2.0"
+ }
+ },
+ "@react-spring/native": {
+ "version": "9.2.4",
+ "resolved": "https://registry.npmjs.org/@react-spring/native/-/native-9.2.4.tgz",
+ "integrity": "sha512-xKJWKh5qOhSclpL3iuGwJRLoZzTNvlBEnIrMs8yh8xvX6z9Lmnu4uGu5DpfrnM1GzBvRoktoCoLEx/VcEYFSng==",
+ "requires": {
+ "@react-spring/animated": "~9.2.0",
+ "@react-spring/core": "~9.2.0",
+ "@react-spring/shared": "~9.2.0",
+ "@react-spring/types": "~9.2.0"
+ }
+ },
+ "@react-spring/rafz": {
+ "version": "9.2.4",
+ "resolved": "https://registry.npmjs.org/@react-spring/rafz/-/rafz-9.2.4.tgz",
+ "integrity": "sha512-SOKf9eue+vAX+DGo7kWYNl9i9J3gPUlQjifIcV9Bzw9h3i30wPOOP0TjS7iMG/kLp2cdHQYDNFte6nt23VAZkQ=="
+ },
+ "@react-spring/shared": {
+ "version": "9.2.4",
+ "resolved": "https://registry.npmjs.org/@react-spring/shared/-/shared-9.2.4.tgz",
+ "integrity": "sha512-ZEr4l2BxmyFRUvRA2VCkPfCJii4E7cGkwbjmTBx1EmcGrOnde/V2eF5dxqCTY3k35QuCegkrWe0coRJVkh8q2Q==",
+ "requires": {
+ "@react-spring/rafz": "~9.2.0",
+ "@react-spring/types": "~9.2.0"
+ }
+ },
+ "@react-spring/three": {
+ "version": "9.2.4",
+ "resolved": "https://registry.npmjs.org/@react-spring/three/-/three-9.2.4.tgz",
+ "integrity": "sha512-ljFig7XW099VWwRPKPUf+4yYLivp/sSWXN3oO5SJOF/9BSoV1quS/9chZ5Myl5J14od3CsHf89Tv4FdlX5kHlA==",
+ "requires": {
+ "@react-spring/animated": "~9.2.0",
+ "@react-spring/core": "~9.2.0",
+ "@react-spring/shared": "~9.2.0",
+ "@react-spring/types": "~9.2.0"
+ }
+ },
+ "@react-spring/types": {
+ "version": "9.2.4",
+ "resolved": "https://registry.npmjs.org/@react-spring/types/-/types-9.2.4.tgz",
+ "integrity": "sha512-zHUXrWO8nweUN/ISjrjqU7GgXXvoEbFca1CgiE0TY0H/dqJb3l+Rhx8ecPVNYimzFg3ZZ1/T0egpLop8SOv4aA=="
+ },
+ "@react-spring/web": {
+ "version": "9.2.4",
+ "resolved": "https://registry.npmjs.org/@react-spring/web/-/web-9.2.4.tgz",
+ "integrity": "sha512-vtPvOalLFvuju/MDBtoSnCyt0xXSL6Amyv82fljOuWPl1yGd4M1WteijnYL9Zlriljl0a3oXcPunAVYTD9dbDQ==",
+ "requires": {
+ "@react-spring/animated": "~9.2.0",
+ "@react-spring/core": "~9.2.0",
+ "@react-spring/shared": "~9.2.0",
+ "@react-spring/types": "~9.2.0"
+ }
+ },
+ "@react-spring/zdog": {
+ "version": "9.2.4",
+ "resolved": "https://registry.npmjs.org/@react-spring/zdog/-/zdog-9.2.4.tgz",
+ "integrity": "sha512-rv7ptedS37SHr6yuCbRkUErAzAhebdgt8f4KUtZWzseC+7qLNkaZWf+uujgsb881qAuX9b9yz8rre9UKeYepgw==",
+ "requires": {
+ "@react-spring/animated": "~9.2.0",
+ "@react-spring/core": "~9.2.0",
+ "@react-spring/shared": "~9.2.0",
+ "@react-spring/types": "~9.2.0"
+ }
+ },
"@restart/context": {
"version": "2.1.4",
"resolved": "https://registry.npmjs.org/@restart/context/-/context-2.1.4.tgz",
@@ -30684,6 +30971,11 @@
"verror": "1.10.0"
}
},
+ "jsqr": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/jsqr/-/jsqr-1.4.0.tgz",
+ "integrity": "sha512-dxLob7q65Xg2DvstYkRpkYtmKm2sPJ9oFhrhmudT1dZvNFFTlroai3AWSpLey/w5vMcLBXRgOJsbXpdN9HzU/A=="
+ },
"killable": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/killable/-/killable-1.0.1.tgz",
@@ -34357,6 +34649,16 @@
"prop-types": "^15.5.8"
}
},
+ "react-qr-reader": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/react-qr-reader/-/react-qr-reader-2.2.1.tgz",
+ "integrity": "sha512-EL5JEj53u2yAOgtpAKAVBzD/SiKWn0Bl7AZy6ZrSf1lub7xHwtaXe6XSx36Wbhl1VMGmvmrwYMRwO1aSCT2fwA==",
+ "requires": {
+ "jsqr": "^1.2.0",
+ "prop-types": "^15.7.2",
+ "webrtc-adapter": "^7.2.1"
+ }
+ },
"react-resizable": {
"version": "1.11.1",
"resolved": "https://registry.npmjs.org/react-resizable/-/react-resizable-1.11.1.tgz",
@@ -35148,6 +35450,19 @@
}
}
},
+ "react-spring": {
+ "version": "9.2.4",
+ "resolved": "https://registry.npmjs.org/react-spring/-/react-spring-9.2.4.tgz",
+ "integrity": "sha512-bMjbyTW0ZGd+/h9cjtohLqCwOGqX2OuaTvalOVfLCGmhzEg/u3GgopI3LAm4UD2Br3MNdVdGgNVoESg4MGqKFQ==",
+ "requires": {
+ "@react-spring/core": "~9.2.0",
+ "@react-spring/konva": "~9.2.0",
+ "@react-spring/native": "~9.2.0",
+ "@react-spring/three": "~9.2.0",
+ "@react-spring/web": "~9.2.0",
+ "@react-spring/zdog": "~9.2.0"
+ }
+ },
"react-table": {
"version": "7.6.3",
"resolved": "https://registry.npmjs.org/react-table/-/react-table-7.6.3.tgz",
@@ -35727,6 +36042,14 @@
"resolved": "https://registry.npmjs.org/rsvp/-/rsvp-4.8.5.tgz",
"integrity": "sha512-nfMOlASu9OnRJo1mbEk2cz0D56a1MBNrJ7orjRZQG10XDyuvwksKbuXNp6qa+kbn839HwjwhBzhFmdsaEAfauA=="
},
+ "rtcpeerconnection-shim": {
+ "version": "1.2.15",
+ "resolved": "https://registry.npmjs.org/rtcpeerconnection-shim/-/rtcpeerconnection-shim-1.2.15.tgz",
+ "integrity": "sha512-C6DxhXt7bssQ1nHb154lqeL0SXz5Dx4RczXZu2Aa/L1NJFnEVDxFwCBo3fqtuljhHIGceg5JKBV4XJ0gW5JKyw==",
+ "requires": {
+ "sdp": "^2.6.0"
+ }
+ },
"run-async": {
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz",
@@ -35891,6 +36214,11 @@
}
}
},
+ "sdp": {
+ "version": "2.12.0",
+ "resolved": "https://registry.npmjs.org/sdp/-/sdp-2.12.0.tgz",
+ "integrity": "sha512-jhXqQAQVM+8Xj5EjJGVweuEzgtGWb3tmEEpl3CLP3cStInSbVHSg0QWOGQzNq8pSID4JkpeV2mPqlMDLrm0/Vw=="
+ },
"select-hose": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz",
@@ -38141,6 +38469,15 @@
"source-map": "~0.6.1"
}
},
+ "webrtc-adapter": {
+ "version": "7.7.1",
+ "resolved": "https://registry.npmjs.org/webrtc-adapter/-/webrtc-adapter-7.7.1.tgz",
+ "integrity": "sha512-TbrbBmiQBL9n0/5bvDdORc6ZfRY/Z7JnEj+EYOD1ghseZdpJ+nF2yx14k3LgQKc7JZnG7HAcL+zHnY25So9d7A==",
+ "requires": {
+ "rtcpeerconnection-shim": "^1.2.15",
+ "sdp": "^2.12.0"
+ }
+ },
"websocket-driver": {
"version": "0.7.4",
"resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz",
diff --git a/frontend/package.json b/frontend/package.json
index c5f235a516..3f2b5b24c1 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -43,11 +43,13 @@
"react-lazyload": "^3.2.0",
"react-loading-skeleton": "^2.2.0",
"react-plotly.js": "^2.5.1",
+ "react-qr-reader": "^2.2.1",
"react-resizable": "^1.11.1",
"react-rnd": "^10.3.0",
"react-router-dom": "^5.0.0",
"react-scripts": "3.4.3",
"react-select-search": "^3.0.5",
+ "react-spring": "^9.2.4",
"react-table": "^7.6.3",
"react-table-plugins": "^1.3.1",
"react-toastify": "^7.0.3",
@@ -55,6 +57,7 @@
"rxjs": "^6.3.3",
"semver": "^5.7.1",
"tinycolor2": "^1.4.2",
+ "uuid": "8.3.2",
"webpack-cli": "^3.3.0",
"yup": "^0.27.0"
},
diff --git a/frontend/src/App/App.jsx b/frontend/src/App/App.jsx
index 4ffb486917..9eb2edd322 100644
--- a/frontend/src/App/App.jsx
+++ b/frontend/src/App/App.jsx
@@ -13,6 +13,7 @@ import '@/_styles/theme.scss';
import { ToastContainer } from 'react-toastify';
import 'react-toastify/dist/ReactToastify.css';
import { ManageOrgUsers } from '@/ManageOrgUsers';
+import { SettingsPage } from '../SettingsPage/SettingsPage';
import { OnboardingModal } from '@/Onboarding/OnboardingModal';
import {ForgotPassword} from '@/ForgotPassword'
import { ResetPassword } from '@/ResetPassword';
@@ -87,6 +88,7 @@ class App extends React.Component {
|
+ |
+
| + 100% + | +
| + 90% + | +
| + 80% + | +
| + 70% + | +
| + 60% + | +
Showing { (currentPage - 1) * 10 + 1} to {currentPage * 10} of {count}
- -Showing {startingAppCount(currentPage)} to {endingAppCount(currentPage, count)} of {count}
+ +Hi ${name || ''},
-+ Please use the link below to set up your account and get started. -
+ +
Welcome aboard,
ToolJet Team
@@ -90,12 +90,12 @@ export class EmailService {
Hi ${name || ''},
-+ ${sender} has invited you to use ToolJet. Use the link below to set up your account and get started. -
+ +
Welcome aboard,
ToolJet Team
diff --git a/server/src/services/folders.service.ts b/server/src/services/folders.service.ts
index d9925cf0fc..27bdab48d9 100644
--- a/server/src/services/folders.service.ts
+++ b/server/src/services/folders.service.ts
@@ -44,6 +44,19 @@ export class FoldersService {
return await this.foldersRepository.findOneOrFail(folderId);
}
+ async userAppCount(user: User, folder: Folder) {
+ const result = await this.foldersRepository
+ .createQueryBuilder('folder')
+ .where("id = :id", { id: folder.id })
+ .loadRelationCountAndMap(
+ 'folder.appCount', 'folder.apps', 'apps',
+ qb => qb.andWhere("apps.user_id = :user_id", { user_id: user.id })
+ )
+ .getMany();
+
+ return result[0].appCount;
+ }
+
async getAppsFor(user: User, folder: Folder, page: number): Promise