Merge branch 'develop'
22
.github/ISSUE_TEMPLATE/05_refactor_code_base.md
vendored
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
---
|
||||
name: 🛠 Refactor Codebase
|
||||
about: Refactoring code
|
||||
labels: 'refactor'
|
||||
title: "[refactor]: "
|
||||
---
|
||||
|
||||
### What area of the codebase is to be refactored?
|
||||
|
||||
<!--
|
||||
Provide a description of the codebase area to be refactored.
|
||||
-->
|
||||
|
||||
(Write your answer here.)
|
||||
|
||||
### What are the potential advantages of this proposed refactoring?
|
||||
|
||||
<!--
|
||||
Provide a description of the potential advantages of the proposed refactoring.
|
||||
-->
|
||||
|
||||
(Describe the advantages here.)
|
||||
|
|
@ -82,6 +82,7 @@ Want to give ToolJet a quick spin on your local machine? You can run the followi
|
|||
```bash
|
||||
docker run \
|
||||
--name tooljet \
|
||||
--user root \
|
||||
--restart unless-stopped \
|
||||
-p 3000:3000 \
|
||||
-v tooljet_data:/var/lib/postgresql/13/main \
|
||||
|
|
|
|||
|
|
@ -15,15 +15,15 @@ ENV NODE_OPTIONS="--max-old-space-size=4096"
|
|||
COPY ./plugins/package.json ./plugins/package-lock.json ./plugins/
|
||||
RUN npm --prefix plugins install
|
||||
COPY ./plugins/ ./plugins/
|
||||
ENV NODE_ENV=production
|
||||
RUN npm --prefix plugins run build
|
||||
RUN NODE_ENV=production npm --prefix plugins run build
|
||||
RUN npm --prefix plugins prune --production
|
||||
|
||||
# Build frontend
|
||||
COPY ./frontend/package.json ./frontend/package-lock.json ./frontend/
|
||||
RUN npm --prefix frontend install --only=production
|
||||
RUN npm --prefix frontend install
|
||||
COPY ./frontend ./frontend
|
||||
RUN npm --prefix frontend run build
|
||||
RUN npm --prefix frontend run build --production
|
||||
RUN npm --prefix frontend prune --production
|
||||
|
||||
FROM openresty/openresty:1.19.9.1rc1-buster-fat
|
||||
|
||||
|
|
|
|||
|
|
@ -15,15 +15,17 @@ COPY ./package.json ./package.json
|
|||
COPY ./plugins/package.json ./plugins/package-lock.json ./plugins/
|
||||
RUN npm --prefix plugins install
|
||||
COPY ./plugins/ ./plugins/
|
||||
ENV NODE_ENV=production
|
||||
RUN npm --prefix plugins run build
|
||||
RUN NODE_ENV=production npm --prefix plugins run build
|
||||
RUN npm --prefix plugins prune --production
|
||||
|
||||
# Build frontend
|
||||
COPY ./frontend/package.json ./frontend/package-lock.json ./frontend/
|
||||
RUN npm --prefix frontend install
|
||||
COPY ./frontend/ ./frontend/
|
||||
RUN npm --prefix frontend run build
|
||||
RUN npm --prefix frontend run build --production
|
||||
RUN npm --prefix frontend prune --production
|
||||
|
||||
ENV NODE_ENV=production
|
||||
|
||||
# Build server
|
||||
COPY ./server/package.json ./server/package-lock.json ./server/
|
||||
|
|
|
|||
29
docs/docs/Enterprise/white-label.md
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
---
|
||||
id: white-label
|
||||
title: White Label
|
||||
---
|
||||
|
||||
# White Label
|
||||
|
||||
White Label feature will allow you to remove the ToolJet branding from the ToolJet platform and add your own custom logo and text.
|
||||
|
||||
This feature allows you to rebrand the following:
|
||||
- **App logo** (Logo on login screen, dashboard, and app-editor)
|
||||
|
||||
<img className="screenshot-full" src="/img/enterprise/white-label/applogo.png" alt="ToolJet - Enterprise - White label" height="420"/>
|
||||
|
||||
<img className="screenshot-full" src="/img/enterprise/white-label/appeditor.png" alt="ToolJet - Enterprise - White label" height="420"/>
|
||||
|
||||
- **Favicon**
|
||||
|
||||
- **Page Title** (next to Favicon)
|
||||
|
||||
<img className="screenshot-full" src="/img/enterprise/white-label/favicon.png" alt="ToolJet - Enterprise - White label" height="420"/>
|
||||
|
||||
## Configuration
|
||||
|
||||
To enable white labelling, you'll need to set the below mentioned **environment variables** in the .env file:
|
||||
|
||||
- `WHITE_LABEL_LOGO`: URL of the logo. Preferred dimensions of the logo are: width 130px and height 26px
|
||||
- `WHITE_LABEL_TEXT`: The text that you want to display as Page Title
|
||||
- `WHITE_LABEL_FAVICON`: URL of the favicon. Preferred dimensions of the logo are: 16x16px or 32x32px
|
||||
17
docs/docs/actions/close-modal.md
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
---
|
||||
id: close-modal
|
||||
title: Close modal
|
||||
---
|
||||
|
||||
Use this action to close the modal that is already shown.
|
||||
|
||||
:::info
|
||||
You can also trigger actions from the **JavaScript code**. Check it out [here](/docs/how-to/run-actions-from-runjs).
|
||||
:::
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
97
docs/docs/actions/control-component.md
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
---
|
||||
id: control-component
|
||||
title: Control component
|
||||
---
|
||||
|
||||
Control component action invokes the component specific actions. Component specific actions are the actions that are exclusive actions for a particular widget. Component specific actions can be triggered either through the event handlers or from the Run JavaScript code query.
|
||||
|
||||
:::info
|
||||
Check out the **[live demo](https://youtu.be/JIhSH3YeM3E)** of Component specific actions demonstrated in one of our community call.
|
||||
:::
|
||||
|
||||
## Available Component Specific Actions
|
||||
|
||||
| Widget | Component Specific Actions |
|
||||
|--------|---------------------------|
|
||||
| Button | Click, Set label |
|
||||
| Text | Set text |
|
||||
| Text Input | Set text, Clear |
|
||||
| Text Area | Set text, Clear |
|
||||
| Modal | Show, Close |
|
||||
| Table | Set page |
|
||||
| Dropdown | Select option |
|
||||
| Multiselect | Select option, Deselect option, Clear selection |
|
||||
| Map | Set location |
|
||||
| Checkbox | Set checked |
|
||||
| Radio button | Select option |
|
||||
| Tabs | Set tab |
|
||||
| Color picker | Set color |
|
||||
| File picker | Clear files |
|
||||
|
||||
:::info
|
||||
Currently, Component specific actions are supported only by the above listed widgets. We are working on bringing component specific actions for the remaining widgets.
|
||||
:::
|
||||
|
||||
## Using Component Specific Actions
|
||||
|
||||
### Set a value for text input widget using button's event handler
|
||||
|
||||
- Drag a **Text Input** and a **Button** widget onto the canvas.
|
||||
|
||||
- Go to the **Inspector** on the left sidebar to check the exposed variables available for the `textinput1` widget under the `components`. You'll see that the variable `value` is an empty string because the field value of the text input widget is empty right now.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
- Now enter some value in the text input widget and you'll see that the `value` in inspector has been updated.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
- Now, click on the button's widget handler to open up its properties in the right sidebar and then add a event handler for **On Click** event to trigger **Control Component** action. Select `textinput1` in component dropdown, `Set text` as Action, and in `Text` field enter the text that you want to update in the field value.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
- Now when you'll click on the button you'll see that the field value of the text input widget has been updated with value that you set.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
|
||||
### Clear value of text input widget using JavaScript query
|
||||
|
||||
- Let's clear the value that we set in the previous section, using Run JavaScript code. Create a new Run JavaScript Code query and call the component and the CSA that component provides.
|
||||
|
||||
**Syntax:**
|
||||
```js
|
||||
await components.textinput1.clear()
|
||||
```
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
- Finally, hit the **save and run** query button to fire up the query, and you'll see that the field value of the text input widget has been cleared.
|
||||
|
||||
16
docs/docs/actions/copy-to-clipboard.md
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
---
|
||||
id: copy-to-clipboard
|
||||
title: Copy to clipboard
|
||||
---
|
||||
|
||||
Use this action to copy the text to the clipboard.
|
||||
|
||||
:::info
|
||||
You can also trigger actions from the **JavaScript code**. Check it out [here](/docs/how-to/run-actions-from-runjs).
|
||||
:::
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
18
docs/docs/actions/go-to-app.md
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
---
|
||||
id: go-to-app
|
||||
title: Go to app
|
||||
---
|
||||
|
||||
This action allows you to open any ToolJet application when an event occurs.
|
||||
|
||||
:::info
|
||||
You can also trigger actions from the **JavaScript code**. Check it out [here](/docs/how-to/run-actions-from-runjs).
|
||||
:::
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
|
||||
16
docs/docs/actions/logout.md
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
---
|
||||
id: logout
|
||||
title: Logout
|
||||
---
|
||||
|
||||
This action allows you to log out of the application (ToolJet).
|
||||
|
||||
:::info
|
||||
You can also trigger actions from the **JavaScript code**. Check it out [here](/docs/how-to/run-actions-from-runjs).
|
||||
:::
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
16
docs/docs/actions/open-webpage.md
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
---
|
||||
id: open-webpage
|
||||
title: Open webpage
|
||||
---
|
||||
|
||||
You can use this action to open a webpage(on a new tab) for any event.
|
||||
|
||||
:::info
|
||||
You can also trigger actions from the **JavaScript code**. Check it out [here](/docs/how-to/run-actions-from-runjs).
|
||||
:::
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
16
docs/docs/actions/run-query.md
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
---
|
||||
id: run-query
|
||||
title: Run Query
|
||||
---
|
||||
|
||||
This action allows you to fire queries when an event occurs.
|
||||
|
||||
:::info
|
||||
You can also trigger actions from the **JavaScript code**. Check it out [here](/docs/how-to/run-actions-from-runjs).
|
||||
:::
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
|
@ -10,19 +10,46 @@ This action allows you to specify a `key` and its corresponding `value` to be st
|
|||
## Example: App that stores a name in localStorage and displays it on reload
|
||||
|
||||
1. Add an input field, button and a text as shown
|
||||
<img src="/img/actions/localstorage/sample-app-1.png" alt="Set local storage sample app" height="350" />
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
2. Select the button and add a `Set localStorage` action with `key` set to `name` and value pointing at the value of the text field
|
||||
<img src="/img/actions/localstorage/sample-app-2.png" alt="Set local storage sample app" height="350" />
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
3. Select the text label we've added and set its value to the name item from localStorage
|
||||
<img src="/img/actions/localstorage/sample-app-3.png" alt="Set local storage sample app" height="150" />
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
|
||||
4. Now save the application, this is important as we're about to reload the page.
|
||||
|
||||
5. Type in anything you wish on the input box and click on the button
|
||||
<img src="/img/actions/localstorage/sample-app-4.png" alt="Set local storage sample app" height="150" />
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
|
||||
6. Reload the page, you'll see that the value stored in local storage is persisted and it is displayed on screen!
|
||||
<img src="/img/actions/localstorage/sample-app-5.png" alt="Set local storage sample app" height="350" />
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
|
|
|
|||
16
docs/docs/actions/set-table-page.md
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
---
|
||||
id: set-table-page
|
||||
title: Set Table Page
|
||||
---
|
||||
|
||||
Use this action to change the page index in the table widget.
|
||||
|
||||
:::info
|
||||
You can also trigger actions from the **JavaScript code**. Check it out [here](/docs/how-to/run-actions-from-runjs).
|
||||
:::
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
16
docs/docs/actions/set-variable.md
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
---
|
||||
id: set-variable
|
||||
title: Set variable
|
||||
---
|
||||
|
||||
This action allows you to create a variable and assign a `value` to it.
|
||||
|
||||
:::info
|
||||
You can also trigger actions from the **JavaScript code**. Check it out [here](/docs/how-to/run-actions-from-runjs).
|
||||
:::
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
21
docs/docs/actions/show-alert.md
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
---
|
||||
id: show-alert
|
||||
title: Show alert
|
||||
---
|
||||
|
||||
This action allows you to display an alert message.
|
||||
|
||||
You can set a custom **message** for the alert and choose a particular alert type.
|
||||
|
||||
There are 4 types of alert messages - **Info**, **Success**, **Warning**, and **Danger**.
|
||||
|
||||
:::info
|
||||
You can also trigger actions from the **JavaScript code**. Check it out [here](/docs/how-to/run-actions-from-runjs).
|
||||
:::
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
16
docs/docs/actions/show-modal.md
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
---
|
||||
id: show-modal
|
||||
title: Show modal
|
||||
---
|
||||
|
||||
Use this action to show the modal for an event.
|
||||
|
||||
:::info
|
||||
You can also trigger actions from the **JavaScript code**. Check it out [here](/docs/how-to/run-actions-from-runjs).
|
||||
:::
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
16
docs/docs/actions/unset-variable.md
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
---
|
||||
id: unset-variable
|
||||
title: Unset variable
|
||||
---
|
||||
|
||||
This action allows you to removev the variable variable that was created using the set variable action.
|
||||
|
||||
:::info
|
||||
You can also trigger actions from the **JavaScript code**. Check it out [here](/docs/how-to/run-actions-from-runjs).
|
||||
:::
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
56
docs/docs/data-sources/slack.md
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
---
|
||||
id: slack
|
||||
title: Slack
|
||||
---
|
||||
|
||||
# Slack
|
||||
|
||||
ToolJet can connect to your Slack workspace to send messages.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
## Connection
|
||||
- To add the Slack datasource, click the **Datasource manager** icon on the left-sidebar of the app builder and click on the `Add datasource` button, then select Slack from the modal that pops up.
|
||||
|
||||
- In the next dialog, you'll be asked to choose the **permission scope**. Choose the permission scope and then click on **Connect to Slack** button.
|
||||
|
||||
- A new tab will open up asking for aurization confirmation. Once done, you can close the tab.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
- Click on the '**Save data source** button to save the data source.
|
||||
|
||||
## Supported operations
|
||||
|
||||
1. **List members**
|
||||
2. **Send message**
|
||||
### List members
|
||||
|
||||
This operation will return the data of all the members in your slack workspace.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
### Send message
|
||||
|
||||
This operation will send the message to specified channel in your slack workspace.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
192
docs/docs/data-sources/stripe.md
Normal file
|
|
@ -0,0 +1,192 @@
|
|||
---
|
||||
id: stripe
|
||||
title: Stripe
|
||||
---
|
||||
|
||||
# Stripe
|
||||
|
||||
ToolJet can connect to your Stripe account to read or write customers' and payments' data.
|
||||
|
||||
:::info
|
||||
Check out the **[Stripe Refund App tutorial](https://blog.tooljet.com/build-a-stripe-refund-tool-using-low-code/)**
|
||||
:::
|
||||
|
||||
## Connection
|
||||
|
||||
To add a new Stripe data source, click on the `+` button on data sources panel at the left-bottom corner of the app editor. Select Stripe from the modal that pops up.
|
||||
|
||||
ToolJet requires the **Stripe API key** to connect to your database.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
You can get the Stripe API key from the dashboard of your Stripe account. Go to the Stripe account dashboard, click on the **Developers** on the top right, then on the left-sidebar go to the **API Keys**, you can simple reveal the **Secret Key** and copy-paste on ToolJet.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
## Querying Stripe
|
||||
|
||||
Click on **+** button of the query manager at the bottom panel of the editor and select the Stripe datasource added in the previous step. Enter the query in the editor. Click on the `Save and Run` button to save and then 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
|
||||
|
||||
|
||||
You can check out the some of the operations mentioned below. All the operations for Stripe are available and can be performed from ToolJet. Check out the **[Stripe API documentation](https://stripe.com/docs/api/)** for the detailed information about each operation.
|
||||
|
||||
- **delete,/v1/account**
|
||||
- **get,/v1/account**
|
||||
- **post,/v1/account**
|
||||
- **post,/v1/account/bank_accounts**
|
||||
- **delete,/v1/account/bank_accounts/{id}**
|
||||
- **get,/v1/account/bank_accounts/{id}**
|
||||
- **post,/v1/account/bank_accounts/{id}**
|
||||
- **get,/v1/account/capabilities**
|
||||
- **get,/v1/account/capabilities/{capability}**
|
||||
- **post,/v1/account/capabilities/{capability}**
|
||||
- **get,/v1/account/external_accounts**
|
||||
- **post,/v1/account/external_accounts**
|
||||
- **delete,/v1/account/external_accounts/{id}**
|
||||
- **get,/v1/account/external_accounts/{id}**
|
||||
- **post,/v1/account/external_accounts/{id}**
|
||||
- **post,/v1/account/login_links**
|
||||
- **get,/v1/account/people**
|
||||
- **post,/v1/account/people**
|
||||
- **delete,/v1/account/people/{person}**
|
||||
- **get,/v1/account/people/{person}**
|
||||
- **post,/v1/account/persons**
|
||||
- **delete,/v1/account/persons/{person}**
|
||||
- **get,/v1/account/persons/{person}**
|
||||
- **post,/v1/account/persons/{person}**
|
||||
- **post,/v1/account_links**
|
||||
- **get,/v1/accounts**
|
||||
- **post,/v1/accounts**
|
||||
- **delete,/v1/accounts/{account}**
|
||||
- **get,/v1/accounts/{account}**
|
||||
- **post,/v1/accounts/{account}**
|
||||
- **post,/v1/accounts/{account}/bank_accounts**
|
||||
- **delete,/v1/accounts/{account}/bank_accounts/{id}**
|
||||
- **get,/v1/accounts/{account}/bank_accounts/{id}**
|
||||
- **get,/v1/accounts/{account}/bank_accounts/{id}**
|
||||
- **get,/v1/accounts/{account}/capabilities**
|
||||
- **get,/v1/accounts/{account}/capabilities/{capability}**
|
||||
- **post,/v1/accounts/{account}/capabilities/{capability}**
|
||||
- **get,/v1/accounts/{account}/external_accounts**
|
||||
- **post,/v1/accounts/{account}/external_accounts**
|
||||
- **delete,/v1/accounts/{account}/external_accounts/{id}**
|
||||
- **get,/v1/accounts/{account}/external_accounts/{id}**
|
||||
- **get,/v1/accounts/{account}/external_accounts/{id}**
|
||||
- **post,/v1/accounts/{account}/login_links**
|
||||
- **get,/v1/accounts/{account}/people**
|
||||
- **post,/v1/accounts/{account}/people**
|
||||
- **delete,/v1/accounts/{account}/people/{person}**
|
||||
- **get,/v1/accounts/{account}/people/{person}**
|
||||
- **post,/v1/accounts/{account}/people/{person}**
|
||||
- **get,/v1/accounts/{account}/persons**
|
||||
- **post,/v1/accounts/{account}/persons**
|
||||
- **delete,/v1/accounts/{account}/persons/{person}**
|
||||
- **get,/v1/accounts/{account}/persons/{person}**
|
||||
- **post,/v1/accounts/{account}/persons/{person}**
|
||||
- **post,/v1/accounts/{account}/reject**
|
||||
- **get,/v1/apple_pay/domains**
|
||||
- **post,/v1/apple_pay/domains**
|
||||
- **delete,/v1/apple_pay/domains/{domain}**
|
||||
- **get,/v1/apple_pay/domains/{domain}**
|
||||
- **get,/v1/application_fees**
|
||||
- **get,/v1/application_fees/{fee}/refunds/{id}**
|
||||
- **post,/v1/application_fees/{fee}/refunds/{id}**
|
||||
- **get,/v1/application_fees/{id}**
|
||||
- **post,/v1/application_fees/{id}/refund**
|
||||
- **get,/v1/application_fees/{id}/refunds**
|
||||
- **post,/v1/application_fees/{id}/refunds**
|
||||
- **get,/v1/apps/secrets**
|
||||
|
||||
|
||||
<!--
|
||||
### delete,/v1/account
|
||||
|
||||
This operation can be used to delete the accounts that you manage in Stripe.
|
||||
|
||||
#### Required parameters:
|
||||
|
||||
- **account**: Enter the account id of account that you want to delete. example: `acct_1032D82eZvKYlo2C`
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
### get,/v1/account
|
||||
|
||||
This operation returns the basic account information such as account id, capabilities, currency, country etc.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
### post,/v1/account
|
||||
|
||||
This operation updates the connected account by setting the values of the parameters passed. Any parameters not provided are left unchanged.
|
||||
|
||||
### post,/v1/account/bank_accounts
|
||||
|
||||
This operation will create a bank account in your stripe account.
|
||||
|
||||
### delete,/v1/account/bank_accounts/{id}
|
||||
|
||||
This operation can be used to delete a specified external account for a given account.. You'll need to provide the **id** of the bank account in stripe.
|
||||
|
||||
### get,/v1/account/bank_accounts/{id}
|
||||
|
||||
This operation can be used to retrieve a specified external account whose **id** is provided in parameters.
|
||||
|
||||
### post,/v1/account/bank_accounts/{id}
|
||||
|
||||
This operation can be used to update the metadata, account holder name, account holder type of a bank account belonging to a Custom Account, and optionally sets it as the default for its currency. Other bank account details are not editable by design. You can re-enable a disabled bank account by performing an update call without providing any arguments or changes.
|
||||
|
||||
### get,/v1/account/capabilities
|
||||
|
||||
This operation returns a list of capabilities associated with the account. The capabilities are returned sorted by creation date, with the most recent capability appearing first.
|
||||
|
||||
### get,/v1/account/capabilities/{capability}
|
||||
|
||||
This operation retrieves information about the specified Account Capability.
|
||||
|
||||
### post,/v1/account/capabilities/{capability}
|
||||
|
||||
This operation updates an existing Account Capability.
|
||||
|
||||
### get,/v1/account/external_accounts
|
||||
|
||||
List external accounts for an account.
|
||||
|
||||
### post,/v1/account/external_accounts
|
||||
|
||||
This operation creates an external account for a given account.
|
||||
|
||||
### delete,/v1/account/external_accounts/{id}
|
||||
|
||||
This operation deletes a specified external account for a given account.
|
||||
|
||||
-->
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
54
docs/docs/data-sources/twilio.md
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
---
|
||||
id: twilio
|
||||
title: Twilio
|
||||
---
|
||||
|
||||
# Twilio
|
||||
|
||||
ToolJet can connect to your Twilio account to send sms.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
## Connection
|
||||
- To add the Twilio datasource, click the **Datasource manager** icon on the left-sidebar of the app builder and click on the `Add datasource` button, then select **Twilio** from the modal that pops up.
|
||||
|
||||
- In the next dialog, you'll be asked to enter the Auth Token, Account SID, and Messaging Service SID.
|
||||
|
||||
- You can get the **Auth Token and Account SID** on the dashboard of your Twilio account.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
- For **Messaging Service SID**, you'll need to create a messaging service first from the Services under Messaging in the left-sidebar.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
- After entering the three credentials, you can **Save** the datasource.
|
||||
|
||||
## Supported operations
|
||||
|
||||
1. **Send message**
|
||||
|
||||
### Send message
|
||||
|
||||
This operation will send the specified message to specified mobile number.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,17 +1,17 @@
|
|||
---
|
||||
id: introduction
|
||||
title: Introduction
|
||||
description: ToolJet is an **open-source low-code framework** to build and deploy custom internal tools. ToolJet can connect to your data sources such as databases ( PostgreSQL, MongoDB, MySQL, Elasticsearch, Firestore, DynamoDB, Redis and more ), API endpoints ( ToolJet supports OAuth2 authorization ) and external services ( Stripe, Slack, Google Sheets, Airtable and more ). Once the data sources are connected, ToolJet can run queries on these data sources to fetch and update data. The data fetched from data sources can be visualised and modified using the UI widgets such as tables, charts, forms, etc.
|
||||
description: ToolJet is an **open-source low-code framework** to build and deploy custom internal tools. ToolJet can connect to your data sources such as databases ( PostgreSQL, MongoDB, MS SQL Server, Snowflake, , BigQuery, etc ), API/GraphQL endpoints, SaaS tools ( Airtable, Stripe, Google Sheets, etc ) and cloud object storage services ( AWS S3, Google Cloud Storage and Minio ). Once the data sources are connected, ToolJet can run queries on these data sources to fetch and update data. The data fetched from data sources can be visualised and modified using the UI widgets such as tables, charts, forms, etc.
|
||||
slug: /
|
||||
---
|
||||
|
||||
# Introduction
|
||||
|
||||
ToolJet is an **open-source low-code framework** to build and deploy custom internal tools. ToolJet can connect to your data sources such as databases ( PostgreSQL, MongoDB, MySQL, Elasticsearch, Firestore, DynamoDB, Redis and more ), API endpoints ( ToolJet supports OAuth2 authorization ) and external services ( Stripe, Slack, Google Sheets, Airtable and more ). Once the data sources are connected, ToolJet can run queries on these data sources to fetch and update data. The data fetched from data sources can be visualised and modified using the UI widgets such as tables, charts, forms, etc.
|
||||
ToolJet is an **open-source low-code framework** to build and deploy custom internal tools. ToolJet can connect to your data sources such as databases ( PostgreSQL, MongoDB, MS SQL Server, Snowflake, , BigQuery, etc ), API/GraphQL endpoints, SaaS tools ( Airtable, Stripe, Google Sheets, etc ) and cloud object storage services ( AWS S3, Google Cloud Storage and Minio ). Once the data sources are connected, ToolJet can run queries on these data sources to fetch and update data. The data fetched from data sources can be visualised and modified using the UI widgets such as tables, charts, forms, etc.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||

|
||||
<img className="screenshot-full" src="/img/introduction/githubstar.png" />
|
||||
|
||||
</div>
|
||||
|
||||
|
|
|
|||
43
docs/docs/setup/digitalocean.md
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
---
|
||||
id: digitalocean
|
||||
title: DigitalOcean
|
||||
---
|
||||
|
||||
# Deploying ToolJet on DigitalOcean
|
||||
|
||||
Now you can quickly deploy ToolJet using the Deploy to DigitalOcean button.
|
||||
|
||||
## Deploying
|
||||
|
||||
#### Follow the steps below to deploy ToolJet on DigitalOcean:
|
||||
|
||||
|
||||
1. Click on the button below to start one click deployment
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
[](https://cloud.digitalocean.com/apps/new?repo=https://github.com/ToolJet/ToolJet/tree/main)
|
||||
|
||||
</div>
|
||||
|
||||
2. A new tab will open up, sign-in to your DigitalOCean account. Once signed-in, the **Create App** page will open up and **Resources** will be already selected. Click on **Next** button.
|
||||
|
||||
<img className="screenshot-full" src="/img/setup/digitalocean/resources.png" alt="ToolJet - Deploy on DigitalOcean - Resources" />
|
||||
|
||||
3. Now, on **Environment Variables** page you can add new variables or edit the existing ones. Check the [environment variables here](/docs/setup/env-vars).
|
||||
|
||||
<img className="screenshot-full" src="/img/setup/digitalocean/env.png" alt="ToolJet - Deploy on DigitalOcean - Environment Variables" />
|
||||
|
||||
4. On the next page, you can change the **App name**, **Project**, and the **Region**.
|
||||
|
||||
<img className="screenshot-full" src="/img/setup/digitalocean/region.png" alt="ToolJet - Deploy on DigitalOcean - App name" />
|
||||
|
||||
5. On the last page, you'll be asked to **Review** all the app details such that we entered before such as **Resources**, **Environment Variables**, **Region**, and there will also be **Billing** section at the end. Review all the details and click the **Create Resource** button.
|
||||
|
||||
<img className="screenshot-full" src="/img/setup/digitalocean/review.png" alt="ToolJet - Deploy on DigitalOcean - App name" />
|
||||
|
||||
6. Once you click the **Create Resource** button, the build will begin. Once the build is complete, you'll see the resource and a **URL** next to it. Click on the URL to open the deployed **ToolJet**.
|
||||
|
||||
:::tip
|
||||
ToolJet server and client can be deployed as standalone applications. If you do not want to deploy the client on DigitalOcean, modify `package.json` accordingly. We have a [guide](/docs/setup/client) on deploying ToolJet client using services such as Firebase.
|
||||
:::
|
||||
|
|
@ -95,7 +95,7 @@ If you rather want to try out ToolJet locally with docker, you can follow the st
|
|||
8. Seed the database:
|
||||
|
||||
```bash
|
||||
docker-compose run server npm run db:seed
|
||||
docker-compose exec server npm run db:seed:prod
|
||||
```
|
||||
|
||||
This seeds the database with a default user with the following credentials:
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ Both the ToolJet server and client requires some environment variables to start
|
|||
|
||||
| variable | description |
|
||||
| ------------ | --------------------------------------------------------------- |
|
||||
| TOOLJET_HOST | the public URL of ToolJet client ( eg: https://app.tooljet.com ) |
|
||||
| TOOLJET_HOST | the public URL of ToolJet client ( eg: https://app.tooljet.com ) |
|
||||
|
||||
#### Lockbox configuration ( required )
|
||||
|
||||
|
|
@ -91,8 +91,13 @@ You will still be able to see the signup page but won't be able to successfully
|
|||
|
||||
#### 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 (`/`).
|
||||
By default, the `SERVE_CLIENT` variable will be unset and the server will serve the client at its `/` end-point.
|
||||
You can set `SERVE_CLIENT` to `false` to disable this behaviour.
|
||||
|
||||
#### Serve client at subpath
|
||||
|
||||
If ToolJet is hosted on a domain subpath, you can set the environment variable `SUB_PATH` to support it.
|
||||
Please note the subpath is to be set with trailing `/` and is applicable only when the server is serving the frontend client.
|
||||
|
||||
#### SMTP configuration ( optional )
|
||||
|
||||
|
|
|
|||
|
|
@ -130,7 +130,7 @@ Signing up requires [SMTP configuration](https://docs.tooljet.com/docs/setup/env
|
|||
```bash
|
||||
gcloud run deploy <replace-service-name> \
|
||||
--image gcr.io/<replace-your-project-id>/tooljet/tooljet-server-ce:latest \
|
||||
--args "npm,run,db:seed"
|
||||
--args "npm,run,db:seed:prod"
|
||||
```
|
||||
|
||||
The deployment will fail as it runs a seed script. Check logs to see that default user was created. Now run the following command to have the app deployed.
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ You will be able to access your ToolJet installation once the pods and services
|
|||
|
||||
If you want to seed the database with a sample user, please SSH into a pod and run:
|
||||
|
||||
`npm run db:seed --prefix server`
|
||||
`npm run db:seed:prod --prefix server`
|
||||
|
||||
This seeds the database with a default user with the following credentials:
|
||||
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ You will be able to access your ToolJet installation once the pods, service and
|
|||
|
||||
If you want to seed the database with a sample user, please SSH into a pod and run:
|
||||
|
||||
`npm run db:seed --prefix server`
|
||||
`npm run db:seed:prod --prefix server`
|
||||
|
||||
This seeds the database with a default user with the following credentials:
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
---
|
||||
id: organization-environment-variables
|
||||
id: workspace-environment-variables
|
||||
title: Workspace Environment Variables
|
||||
---
|
||||
|
||||
|
|
@ -6,11 +6,9 @@ title: Date-range picker
|
|||
|
||||
The date-range picker widget allows users to select a range of dates.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
## How To Use Date Range Picker Widget
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
<iframe height="500" src="https://www.youtube.com/embed/iBJQeh1kerE" title="Date range picker Widget" frameborder="0" allowfullscreen width="100%"></iframe>
|
||||
|
||||
## Properties
|
||||
|
||||
|
|
|
|||
|
|
@ -6,11 +6,9 @@ title: Dropdown
|
|||
|
||||
The Dropdown widget can be used to collect user input from a list of options.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
## How To Use Dropdown Widget
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
<iframe height="500" src="https://www.youtube.com/embed/PKlkD2rtlP8" title="Dropdown widget" frameborder="0" allowfullscreen width="100%"></iframe>
|
||||
|
||||
:::tip
|
||||
Dropdown options can be referred to your query data with dynamic variables.
|
||||
|
|
|
|||
|
|
@ -6,11 +6,9 @@ title: Radio Button
|
|||
|
||||
Radio button widget can be used to select one option from a group of options.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
## How To Use Radio button Widget
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
<iframe height="500" src="https://www.youtube.com/embed/lfy7nq6NqAw" title="Radio button Widget" frameborder="0" allowfullscreen width="100%"></iframe>
|
||||
|
||||
:::tip
|
||||
Radio buttons are preferred when the list of options is less than six, and all the options can be displayed at once.
|
||||
|
|
|
|||
|
|
@ -51,17 +51,21 @@ Toggle on or off to display the widget in mobile view. You can programmatically
|
|||
|
||||
## Styles
|
||||
|
||||
### Text color
|
||||
| Style | Description |
|
||||
| ----------- | ----------- |
|
||||
| Font Weight | You can change the font weight of the text in following ways: **normal (default), bold, lighter, bolder** |
|
||||
| Text Decoration | You can change the text decoration in following ways : **none(default), overline, line-through, underline, overline underline** |
|
||||
| Text Transformation | You can transform the text in following ways: **none (default), uppercase, lowercase, capitalize** |
|
||||
| Font Style | You can change the font style in following ways: **normal(default), italic, oblique** |
|
||||
| Line Height | You can change the line height by providing number as input (example - 1.5) |
|
||||
| Text Indent | You can change the text indent by providing the number as input (example - 10) |
|
||||
| Letter Spacing | You can change the letter spacing by proviving the number as input (example - 2) |
|
||||
| Word Spacing | You can change the letter spacing by proviving the number as input (example - 2) |
|
||||
| Font Variant | You can change the font variant of the text in the following ways: **normal (default), small-caps, initial, inherit** |
|
||||
| Text Size | By default, the text size is set to 14. You can enter any value from 1-100 to set custom text size. |
|
||||
| Text Color | You can change the background color of the text by entering the Hex color code or choosing a color of your choice from the color picker. |
|
||||
| Align Text | You can align the text inside the widget in following ways: left, right, center, justified |
|
||||
|
||||
Change the color of the text by providing the `Hex color code` or choosing a color from the picker.
|
||||
|
||||
### Align text
|
||||
|
||||
You can align the text inside the widget in following ways:
|
||||
- Left
|
||||
- Right
|
||||
- Center
|
||||
- Justified
|
||||
|
||||
### Visibility
|
||||
|
||||
|
|
|
|||
|
|
@ -10,11 +10,9 @@ Textarea widgets let users enter and edit just text like [Text Input](/docs/widg
|
|||
Textarea should be preferred over [Text Input](/docs/widgets/text-input) when user input is more than one sentence.
|
||||
:::
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
## How To Use Textarea Widget
|
||||
|
||||

|
||||
|
||||
</div>
|
||||
<iframe height="500" src="https://www.youtube.com/embed/ja66x6DeZxk" title="Textarea Widget" frameborder="0" allowfullscreen width="100%"></iframe>
|
||||
|
||||
## Properties
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
const devServerPlugin = require('./src/plugins/devServer/index.js');
|
||||
|
||||
const isProd = process.env.NODE_ENV === 'production';
|
||||
|
||||
/** @type {import('@docusaurus/types').DocusaurusConfig} */
|
||||
|
|
@ -22,16 +24,7 @@ module.exports = {
|
|||
isCloseable: true,
|
||||
},
|
||||
colorMode: {
|
||||
switchConfig: {
|
||||
darkIcon: '\00a0 ',
|
||||
lightIcon: '\00a0',
|
||||
darkIconStyle: {
|
||||
display: 'none',
|
||||
},
|
||||
lightIconStyle: {
|
||||
display: 'none',
|
||||
},
|
||||
},
|
||||
|
||||
},
|
||||
navbar: {
|
||||
logo: {
|
||||
|
|
@ -47,18 +40,21 @@ module.exports = {
|
|||
},
|
||||
{
|
||||
href: 'https://github.com/ToolJet/ToolJet',
|
||||
label: 'GitHub',
|
||||
position: 'right',
|
||||
className: 'navbar-social-link navbar-github-logo',
|
||||
'aria-label': 'GitHub repository',
|
||||
},
|
||||
{
|
||||
href: 'https://join.slack.com/t/tooljet/shared_invite/zt-r2neyfcw-KD1COL6t2kgVTlTtAV5rtg',
|
||||
label: 'Slack',
|
||||
position: 'right',
|
||||
className: 'navbar-social-link navbar-slack-logo',
|
||||
'aria-label': 'Slack workspace',
|
||||
},
|
||||
{
|
||||
href: 'https://twitter.com/ToolJet',
|
||||
label: 'Twitter',
|
||||
position: 'right',
|
||||
className: 'navbar-social-link navbar-twitter-logo',
|
||||
'aria-label': 'Twitter account',
|
||||
},
|
||||
],
|
||||
},
|
||||
|
|
@ -78,8 +74,8 @@ module.exports = {
|
|||
title: 'Community',
|
||||
items: [
|
||||
{
|
||||
label: 'Stack Overflow',
|
||||
href: 'https://stackoverflow.com/questions/tagged/tooljet',
|
||||
label: 'Slack',
|
||||
href: 'https://join.slack.com/t/tooljet/shared_invite/zt-r2neyfcw-KD1COL6t2kgVTlTtAV5rtg',
|
||||
},
|
||||
],
|
||||
},
|
||||
|
|
@ -91,8 +87,8 @@ module.exports = {
|
|||
href: 'https://github.com/ToolJet/ToolJet',
|
||||
},
|
||||
{
|
||||
label: 'Slack',
|
||||
href: 'https://join.slack.com/t/tooljet/shared_invite/zt-r2neyfcw-KD1COL6t2kgVTlTtAV5rtg',
|
||||
label: 'YouTube',
|
||||
href: 'https://www.youtube.com/channel/UCf1p2G5Z7fPpvlBPf4l2I1w',
|
||||
},
|
||||
{
|
||||
label: 'Twitter',
|
||||
|
|
@ -135,4 +131,7 @@ module.exports = {
|
|||
},
|
||||
],
|
||||
],
|
||||
plugins: [
|
||||
devServerPlugin,
|
||||
],
|
||||
};
|
||||
|
|
|
|||
20822
docs/package-lock.json
generated
Normal file
|
|
@ -14,10 +14,10 @@
|
|||
"write-heading-ids": "docusaurus write-heading-ids"
|
||||
},
|
||||
"dependencies": {
|
||||
"@docusaurus/core": "^2.0.0-beta.15",
|
||||
"@docusaurus/plugin-google-gtag": "^2.0.0-alpha.73",
|
||||
"@docusaurus/plugin-sitemap": "^2.0.0-beta.20",
|
||||
"@docusaurus/preset-classic": "^2.0.0-beta.15",
|
||||
"@docusaurus/core": "^2.0.1",
|
||||
"@docusaurus/plugin-google-gtag": "^2.0.1",
|
||||
"@docusaurus/plugin-sitemap": "^2.0.1",
|
||||
"@docusaurus/preset-classic": "^2.0.1",
|
||||
"@mdx-js/react": "^1.6.21",
|
||||
"clsx": "^1.1.1",
|
||||
"react": "^17.0.1",
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ const sidebars = {
|
|||
link: {type: 'doc', id: 'setup/index'},
|
||||
items: [
|
||||
'setup/try-tooljet',
|
||||
'setup/digitalocean',
|
||||
'setup/docker',
|
||||
'setup/heroku',
|
||||
'setup/ec2',
|
||||
|
|
@ -55,7 +56,7 @@ const sidebars = {
|
|||
'tutorial/manage-users-groups',
|
||||
'tutorial/keyboard-shortcuts',
|
||||
'tutorial/multiworkspace',
|
||||
'tutorial/organization-environment-variables'
|
||||
'tutorial/workspace-environment-variables'
|
||||
],
|
||||
},
|
||||
{
|
||||
|
|
@ -92,8 +93,11 @@ const sidebars = {
|
|||
'data-sources/rethinkdb',
|
||||
'data-sources/saphana',
|
||||
'data-sources/sendgrid',
|
||||
'data-sources/slack',
|
||||
'data-sources/smtp',
|
||||
'data-sources/snowflake',
|
||||
'data-sources/stripe',
|
||||
'data-sources/twilio',
|
||||
'data-sources/typesense',
|
||||
'data-sources/woocommerce',
|
||||
],
|
||||
|
|
@ -160,8 +164,20 @@ const sidebars = {
|
|||
keywords: ['actions','events'],
|
||||
},
|
||||
items: [
|
||||
'actions/generate-file',
|
||||
'actions/show-alert',
|
||||
'actions/logout',
|
||||
'actions/run-query',
|
||||
'actions/open-webpage',
|
||||
'actions/go-to-app',
|
||||
'actions/show-modal',
|
||||
'actions/close-modal',
|
||||
'actions/copy-to-clipboard',
|
||||
'actions/set-localstorage',
|
||||
'actions/generate-file',
|
||||
'actions/set-table-page',
|
||||
'actions/set-variable',
|
||||
'actions/unset-variable',
|
||||
'actions/control-component',
|
||||
],
|
||||
},
|
||||
{
|
||||
|
|
@ -188,6 +204,7 @@ const sidebars = {
|
|||
label: 'Enterprise',
|
||||
items: [
|
||||
'Enterprise/audit_logs',
|
||||
'Enterprise/white-label',
|
||||
]
|
||||
},
|
||||
{
|
||||
|
|
|
|||
|
|
@ -36,8 +36,8 @@
|
|||
--tblr-danger: #d63939;
|
||||
--tblr-light: #f4f6fa;
|
||||
--tblr-dark: #232e3c;
|
||||
--tblr-font-sans-serif: "Inter",-apple-system,BlinkMacSystemFont,San Francisco,Segoe UI,Roboto,Helvetica Neue,sans-serif;
|
||||
--tblr-font-monospace: null,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;
|
||||
--tblr-font-sans-serif: "Inter", -apple-system, BlinkMacSystemFont, San Francisco, Segoe UI, Roboto, Helvetica Neue, sans-serif;
|
||||
--tblr-font-monospace: null, Menlo, Monaco, Consolas, Liberation Mono, Courier New, monospace;
|
||||
--tblr-gradient: linear-gradient(180deg, rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0));
|
||||
}
|
||||
|
||||
|
|
@ -62,13 +62,13 @@
|
|||
margin-bottom: 1rem;
|
||||
border-radius: 4px;
|
||||
background: #fff;
|
||||
border: 1px solid rgba(101,109,119,.16);
|
||||
box-shadow: rgba(35,46,60,.04) 0 2px 4px 0;
|
||||
border: 1px solid rgba(101, 109, 119, .16);
|
||||
box-shadow: rgba(35, 46, 60, .04) 0 2px 4px 0;
|
||||
border-left: .25rem solid var(--tblr-alert-color);
|
||||
}
|
||||
|
||||
.admonition-heading {
|
||||
display: none;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.admonition-tip {
|
||||
|
|
@ -79,7 +79,7 @@
|
|||
--tblr-alert-color: #4299e1;
|
||||
}
|
||||
|
||||
.screenshot-full {
|
||||
.screenshot-full {
|
||||
border: 1px solid #dadde1;
|
||||
}
|
||||
|
||||
|
|
@ -90,7 +90,7 @@
|
|||
padding: 0 var(--ifm-pre-padding);
|
||||
}
|
||||
|
||||
.navbar__link {
|
||||
.navbar__link {
|
||||
color: var(--ifm-color-primary);
|
||||
}
|
||||
|
||||
|
|
@ -113,6 +113,7 @@ body {
|
|||
:root {
|
||||
--ifm-font-size-base: 18px;
|
||||
}
|
||||
|
||||
article header h1 {
|
||||
font-size: 1.5rem !important;
|
||||
}
|
||||
|
|
@ -120,6 +121,7 @@ body {
|
|||
article h2 {
|
||||
font-size: 1.2rem !important;
|
||||
}
|
||||
|
||||
.hero .hero__title {
|
||||
font-size: 2.5rem;
|
||||
}
|
||||
|
|
@ -129,11 +131,12 @@ body {
|
|||
:root {
|
||||
--ifm-font-size-base: 17px;
|
||||
}
|
||||
article h1 {
|
||||
|
||||
article h1 {
|
||||
font-size: 2rem !important;
|
||||
}
|
||||
|
||||
article h2 {
|
||||
article h2 {
|
||||
font-size: 1.5rem !important;
|
||||
}
|
||||
}
|
||||
|
|
@ -156,7 +159,7 @@ body {
|
|||
height: 25px;
|
||||
}
|
||||
|
||||
strong {
|
||||
strong {
|
||||
color: #4d72fa;
|
||||
}
|
||||
|
||||
|
|
@ -172,6 +175,42 @@ strong {
|
|||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.navbar-social-link:hover {
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
.navbar-social-link::before {
|
||||
content: '';
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
display: flex;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
.navbar-github-logo::before {
|
||||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' aria-hidden='true' viewBox='0 0 16 16' version='1.1' data-view-component='true' %3E%3Cpath fill-rule='evenodd' d='M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z' %3E%3C/path%3E%3C/svg%3E");
|
||||
}
|
||||
|
||||
[data-theme='dark'] .navbar-github-logo::before {
|
||||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='white' aria-hidden='true' viewBox='0 0 16 16' version='1.1' data-view-component='true' %3E%3Cpath fill-rule='evenodd' d='M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z' %3E%3C/path%3E%3C/svg%3E");
|
||||
}
|
||||
|
||||
.navbar-slack-logo::before {
|
||||
background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M5.042 15.165a2.528 2.528 0 0 1-2.52 2.523A2.528 2.528 0 0 1 0 15.165a2.527 2.527 0 0 1 2.522-2.52h2.52v2.52zM6.313 15.165a2.527 2.527 0 0 1 2.521-2.52 2.527 2.527 0 0 1 2.521 2.52v6.313A2.528 2.528 0 0 1 8.834 24a2.528 2.528 0 0 1-2.521-2.522v-6.313zM8.834 5.042a2.528 2.528 0 0 1-2.521-2.52A2.528 2.528 0 0 1 8.834 0a2.528 2.528 0 0 1 2.521 2.522v2.52H8.834zM8.834 6.313a2.528 2.528 0 0 1 2.521 2.521 2.528 2.528 0 0 1-2.521 2.521H2.522A2.528 2.528 0 0 1 0 8.834a2.528 2.528 0 0 1 2.522-2.521h6.312zM18.956 8.834a2.528 2.528 0 0 1 2.522-2.521A2.528 2.528 0 0 1 24 8.834a2.528 2.528 0 0 1-2.522 2.521h-2.522V8.834zM17.688 8.834a2.528 2.528 0 0 1-2.523 2.521 2.527 2.527 0 0 1-2.52-2.521V2.522A2.527 2.527 0 0 1 15.165 0a2.528 2.528 0 0 1 2.523 2.522v6.312zM15.165 18.956a2.528 2.528 0 0 1 2.523 2.522A2.528 2.528 0 0 1 15.165 24a2.527 2.527 0 0 1-2.52-2.522v-2.522h2.52zM15.165 17.688a2.527 2.527 0 0 1-2.52-2.523 2.526 2.526 0 0 1 2.52-2.52h6.313A2.527 2.527 0 0 1 24 15.165a2.528 2.528 0 0 1-2.522 2.523h-6.313z' /%3E%3C/svg%3E");
|
||||
}
|
||||
|
||||
[data-theme='dark'] .navbar-slack-logo::before {
|
||||
background-image: url("data:image/svg+xml,%3Csvg fill='white' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M5.042 15.165a2.528 2.528 0 0 1-2.52 2.523A2.528 2.528 0 0 1 0 15.165a2.527 2.527 0 0 1 2.522-2.52h2.52v2.52zM6.313 15.165a2.527 2.527 0 0 1 2.521-2.52 2.527 2.527 0 0 1 2.521 2.52v6.313A2.528 2.528 0 0 1 8.834 24a2.528 2.528 0 0 1-2.521-2.522v-6.313zM8.834 5.042a2.528 2.528 0 0 1-2.521-2.52A2.528 2.528 0 0 1 8.834 0a2.528 2.528 0 0 1 2.521 2.522v2.52H8.834zM8.834 6.313a2.528 2.528 0 0 1 2.521 2.521 2.528 2.528 0 0 1-2.521 2.521H2.522A2.528 2.528 0 0 1 0 8.834a2.528 2.528 0 0 1 2.522-2.521h6.312zM18.956 8.834a2.528 2.528 0 0 1 2.522-2.521A2.528 2.528 0 0 1 24 8.834a2.528 2.528 0 0 1-2.522 2.521h-2.522V8.834zM17.688 8.834a2.528 2.528 0 0 1-2.523 2.521 2.527 2.527 0 0 1-2.52-2.521V2.522A2.527 2.527 0 0 1 15.165 0a2.528 2.528 0 0 1 2.523 2.522v6.312zM15.165 18.956a2.528 2.528 0 0 1 2.523 2.522A2.528 2.528 0 0 1 15.165 24a2.527 2.527 0 0 1-2.52-2.522v-2.522h2.52zM15.165 17.688a2.527 2.527 0 0 1-2.52-2.523 2.526 2.526 0 0 1 2.52-2.52h6.313A2.527 2.527 0 0 1 24 15.165a2.528 2.528 0 0 1-2.522 2.523h-6.313z' /%3E%3C/svg%3E");
|
||||
}
|
||||
|
||||
.navbar-twitter-logo::before {
|
||||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' aria-hidden='true'%3E%3Cpath d='M23.643 4.937c-.835.37-1.732.62-2.675.733.962-.576 1.7-1.49 2.048-2.578-.9.534-1.897.922-2.958 1.13-.85-.904-2.06-1.47-3.4-1.47-2.572 0-4.658 2.086-4.658 4.66 0 .364.042.718.12 1.06-3.873-.195-7.304-2.05-9.602-4.868-.4.69-.63 1.49-.63 2.342 0 1.616.823 3.043 2.072 3.878-.764-.025-1.482-.234-2.11-.583v.06c0 2.257 1.605 4.14 3.737 4.568-.392.106-.803.162-1.227.162-.3 0-.593-.028-.877-.082.593 1.85 2.313 3.198 4.352 3.234-1.595 1.25-3.604 1.995-5.786 1.995-.376 0-.747-.022-1.112-.065 2.062 1.323 4.51 2.093 7.14 2.093 8.57 0 13.255-7.098 13.255-13.254 0-.2-.005-.402-.014-.602.91-.658 1.7-1.477 2.323-2.41z' %3E%3C/path%3E%3C/svg%3E");
|
||||
}
|
||||
|
||||
[data-theme='dark'] .navbar-twitter-logo::before {
|
||||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='white' viewBox='0 0 24 24' aria-hidden='true'%3E%3Cpath d='M23.643 4.937c-.835.37-1.732.62-2.675.733.962-.576 1.7-1.49 2.048-2.578-.9.534-1.897.922-2.958 1.13-.85-.904-2.06-1.47-3.4-1.47-2.572 0-4.658 2.086-4.658 4.66 0 .364.042.718.12 1.06-3.873-.195-7.304-2.05-9.602-4.868-.4.69-.63 1.49-.63 2.342 0 1.616.823 3.043 2.072 3.878-.764-.025-1.482-.234-2.11-.583v.06c0 2.257 1.605 4.14 3.737 4.568-.392.106-.803.162-1.227.162-.3 0-.593-.028-.877-.082.593 1.85 2.313 3.198 4.352 3.234-1.595 1.25-3.604 1.995-5.786 1.995-.376 0-.747-.022-1.112-.065 2.062 1.323 4.51 2.093 7.14 2.093 8.57 0 13.255-7.098 13.255-13.254 0-.2-.005-.402-.014-.602.91-.658 1.7-1.477 2.323-2.41z' %3E%3C/path%3E%3C/svg%3E");
|
||||
}
|
||||
|
||||
[data-theme='light'] .DocSearch {
|
||||
/* --docsearch-primary-color: var(--ifm-color-primary); */
|
||||
/* --docsearch-text-color: var(--ifm-font-color-base); */
|
||||
|
|
@ -205,9 +244,14 @@ strong {
|
|||
--docsearch-hit-background: var(--ifm-color-emphasis-100);
|
||||
/* Footer */
|
||||
--docsearch-footer-background: var(--ifm-background-surface-color);
|
||||
--docsearch-key-gradient: linear-gradient(
|
||||
-26.5deg,
|
||||
var(--ifm-color-emphasis-200) 0%,
|
||||
var(--ifm-color-emphasis-100) 100%
|
||||
);
|
||||
}
|
||||
--docsearch-key-gradient: linear-gradient(-26.5deg,
|
||||
var(--ifm-color-emphasis-200) 0%,
|
||||
var(--ifm-color-emphasis-100) 100%);
|
||||
}
|
||||
|
||||
@media screen and (min-width: 768px) {
|
||||
.DocSearch-Button-Container {
|
||||
min-width: 200px;
|
||||
/* Fixes #3856 */
|
||||
}
|
||||
}
|
||||
|
|
|
|||
12
docs/src/plugins/devServer/index.js
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
module.exports = function (context, options) {
|
||||
return {
|
||||
name: 'dev-server-plugin',
|
||||
configureWebpack(config, isServer, utils) {
|
||||
return {
|
||||
devServer: {
|
||||
open: '/docs',
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
};
|
||||
BIN
docs/static/img/actions/closemodal/closemodal.png
vendored
Normal file
|
After Width: | Height: | Size: 73 KiB |
BIN
docs/static/img/actions/controlcomponent/button.png
vendored
Normal file
|
After Width: | Height: | Size: 389 KiB |
BIN
docs/static/img/actions/controlcomponent/clear.png
vendored
Normal file
|
After Width: | Height: | Size: 301 KiB |
BIN
docs/static/img/actions/controlcomponent/inspector.png
vendored
Normal file
|
After Width: | Height: | Size: 692 KiB |
BIN
docs/static/img/actions/controlcomponent/jsoption.png
vendored
Normal file
|
After Width: | Height: | Size: 332 KiB |
BIN
docs/static/img/actions/controlcomponent/set.png
vendored
Normal file
|
After Width: | Height: | Size: 701 KiB |
BIN
docs/static/img/actions/controlcomponent/updated.png
vendored
Normal file
|
After Width: | Height: | Size: 212 KiB |
BIN
docs/static/img/actions/copytoclipboard/copytoclipboard.png
vendored
Normal file
|
After Width: | Height: | Size: 111 KiB |
BIN
docs/static/img/actions/gotoapp/gotoapp.png
vendored
Normal file
|
After Width: | Height: | Size: 106 KiB |
BIN
docs/static/img/actions/localstorage/1.png
vendored
Normal file
|
After Width: | Height: | Size: 195 KiB |
BIN
docs/static/img/actions/localstorage/2.png
vendored
Normal file
|
After Width: | Height: | Size: 86 KiB |
BIN
docs/static/img/actions/localstorage/3.png
vendored
Normal file
|
After Width: | Height: | Size: 38 KiB |
BIN
docs/static/img/actions/localstorage/5.png
vendored
Normal file
|
After Width: | Height: | Size: 113 KiB |
BIN
docs/static/img/actions/localstorage/6.png
vendored
Normal file
|
After Width: | Height: | Size: 121 KiB |
|
Before Width: | Height: | Size: 44 KiB |
|
Before Width: | Height: | Size: 40 KiB |
|
Before Width: | Height: | Size: 9.1 KiB |
|
Before Width: | Height: | Size: 6.7 KiB |
|
Before Width: | Height: | Size: 9.1 KiB |
BIN
docs/static/img/actions/logout/logout.png
vendored
Normal file
|
After Width: | Height: | Size: 47 KiB |
BIN
docs/static/img/actions/open-webpage/open.png
vendored
Normal file
|
After Width: | Height: | Size: 286 KiB |
BIN
docs/static/img/actions/run-query/run-query.png
vendored
Normal file
|
After Width: | Height: | Size: 78 KiB |
BIN
docs/static/img/actions/settablepage/settablepage.png
vendored
Normal file
|
After Width: | Height: | Size: 81 KiB |
BIN
docs/static/img/actions/setvar/setvar.png
vendored
Normal file
|
After Width: | Height: | Size: 90 KiB |
BIN
docs/static/img/actions/show-alert/show-alert.png
vendored
Normal file
|
After Width: | Height: | Size: 89 KiB |
BIN
docs/static/img/actions/showmodal/showmodal.png
vendored
Normal file
|
After Width: | Height: | Size: 73 KiB |
BIN
docs/static/img/actions/unsetvar/unsetvar.png
vendored
Normal file
|
After Width: | Height: | Size: 61 KiB |
|
Before Width: | Height: | Size: 38 KiB After Width: | Height: | Size: 34 KiB |
BIN
docs/static/img/datasource-reference/slack/authorize.png
vendored
Normal file
|
After Width: | Height: | Size: 1.2 MiB |
BIN
docs/static/img/datasource-reference/slack/connect.png
vendored
Normal file
|
After Width: | Height: | Size: 71 KiB |
BIN
docs/static/img/datasource-reference/slack/listmembers.png
vendored
Normal file
|
After Width: | Height: | Size: 58 KiB |
BIN
docs/static/img/datasource-reference/slack/sendmessage.png
vendored
Normal file
|
After Width: | Height: | Size: 410 KiB |
BIN
docs/static/img/datasource-reference/stripe/apikey.png
vendored
Normal file
|
After Width: | Height: | Size: 1.2 MiB |
BIN
docs/static/img/datasource-reference/stripe/connect.png
vendored
Normal file
|
After Width: | Height: | Size: 36 KiB |
BIN
docs/static/img/datasource-reference/stripe/delete-account.png
vendored
Normal file
|
After Width: | Height: | Size: 471 KiB |
BIN
docs/static/img/datasource-reference/stripe/get-account.png
vendored
Normal file
|
After Width: | Height: | Size: 201 KiB |
BIN
docs/static/img/datasource-reference/twilio/auth.png
vendored
Normal file
|
After Width: | Height: | Size: 1.5 MiB |
BIN
docs/static/img/datasource-reference/twilio/connect.png
vendored
Normal file
|
After Width: | Height: | Size: 117 KiB |
BIN
docs/static/img/datasource-reference/twilio/sid.png
vendored
Normal file
|
After Width: | Height: | Size: 1.2 MiB |
BIN
docs/static/img/datasource-reference/twilio/sms.png
vendored
Normal file
|
After Width: | Height: | Size: 75 KiB |
BIN
docs/static/img/enterprise/white-label/appeditor.png
vendored
Normal file
|
After Width: | Height: | Size: 87 KiB |
BIN
docs/static/img/enterprise/white-label/applogo.png
vendored
Normal file
|
After Width: | Height: | Size: 402 KiB |
BIN
docs/static/img/enterprise/white-label/favicon.png
vendored
Normal file
|
After Width: | Height: | Size: 285 KiB |
BIN
docs/static/img/setup/digitalocean/env.png
vendored
Normal file
|
After Width: | Height: | Size: 523 KiB |
BIN
docs/static/img/setup/digitalocean/region.png
vendored
Normal file
|
After Width: | Height: | Size: 429 KiB |
BIN
docs/static/img/setup/digitalocean/resources.png
vendored
Normal file
|
After Width: | Height: | Size: 397 KiB |
BIN
docs/static/img/setup/digitalocean/review.png
vendored
Normal file
|
After Width: | Height: | Size: 401 KiB |
72
frontend/.eslintrc.js
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
module.exports = {
|
||||
env: {
|
||||
browser: true,
|
||||
amd: true,
|
||||
es2021: true,
|
||||
node: true,
|
||||
'jest/globals': true,
|
||||
},
|
||||
extends: [
|
||||
'eslint:recommended',
|
||||
'plugin:react/recommended',
|
||||
'plugin:react-hooks/recommended',
|
||||
'plugin:import/errors',
|
||||
'plugin:import/warnings',
|
||||
'plugin:prettier/recommended',
|
||||
],
|
||||
parser: '@babel/eslint-parser',
|
||||
parserOptions: {
|
||||
requireConfigFile: false,
|
||||
babelOptions: {
|
||||
configFile: __dirname + '/babel.config.js',
|
||||
},
|
||||
ecmaFeatures: {
|
||||
jsx: true,
|
||||
},
|
||||
ecmaVersion: 12,
|
||||
sourceType: 'module',
|
||||
},
|
||||
plugins: ['react', 'prettier', 'jest'],
|
||||
rules: {
|
||||
'prettier/prettier': [
|
||||
'error',
|
||||
{
|
||||
semi: true,
|
||||
trailingComma: 'es5',
|
||||
printWidth: 120,
|
||||
singleQuote: true,
|
||||
arrowParens: 'always',
|
||||
proseWrap: 'preserve',
|
||||
},
|
||||
],
|
||||
'react/prop-types': 0,
|
||||
'react/display-name': 'off',
|
||||
'no-unused-vars': [
|
||||
'warn',
|
||||
{
|
||||
argsIgnorePattern: '^_',
|
||||
varsIgnorePattern: '^_',
|
||||
},
|
||||
],
|
||||
'react/no-deprecated': 0,
|
||||
'no-prototype-builtins': 0,
|
||||
'jest/no-disabled-tests': 'warn',
|
||||
'jest/no-focused-tests': 'error',
|
||||
'jest/no-identical-title': 'error',
|
||||
'jest/prefer-to-have-length': 'warn',
|
||||
'jest/valid-expect': 'error',
|
||||
},
|
||||
settings: {
|
||||
react: {
|
||||
version: 'detect',
|
||||
},
|
||||
'import/resolver': 'webpack',
|
||||
},
|
||||
globals: {
|
||||
path: true,
|
||||
fetch: true,
|
||||
process: true,
|
||||
module: true,
|
||||
__dirname: true,
|
||||
},
|
||||
};
|
||||
|
|
@ -1,63 +0,0 @@
|
|||
{
|
||||
"env": {
|
||||
"browser": true,
|
||||
"amd": true,
|
||||
"es2021": true,
|
||||
"jest/globals": true
|
||||
},
|
||||
"extends": [
|
||||
"eslint:recommended",
|
||||
"plugin:react/recommended",
|
||||
"plugin:react-hooks/recommended",
|
||||
"plugin:import/errors",
|
||||
"plugin:import/warnings",
|
||||
"plugin:prettier/recommended"
|
||||
],
|
||||
"parser": "babel-eslint",
|
||||
"parserOptions": {
|
||||
"ecmaFeatures": {
|
||||
"jsx": true
|
||||
},
|
||||
"ecmaVersion": 12,
|
||||
"sourceType": "module"
|
||||
},
|
||||
"plugins": ["react", "prettier", "jest"],
|
||||
"rules": {
|
||||
"prettier/prettier": [
|
||||
"error",
|
||||
{
|
||||
"semi": true,
|
||||
"trailingComma": "es5",
|
||||
"printWidth": 120,
|
||||
"singleQuote": true,
|
||||
"arrowParens": "always",
|
||||
"proseWrap": "preserve"
|
||||
}
|
||||
],
|
||||
"react/prop-types": 0,
|
||||
"react/display-name": "off",
|
||||
"no-unused-vars": ["warn", {
|
||||
"argsIgnorePattern": "^_",
|
||||
"varsIgnorePattern": "^_"
|
||||
}],
|
||||
"react/no-deprecated": 0,
|
||||
"no-prototype-builtins": 0,
|
||||
"jest/no-disabled-tests": "warn",
|
||||
"jest/no-focused-tests": "error",
|
||||
"jest/no-identical-title": "error",
|
||||
"jest/prefer-to-have-length": "warn",
|
||||
"jest/valid-expect": "error"
|
||||
},
|
||||
"settings": {
|
||||
"react": {
|
||||
"version": "detect"
|
||||
},
|
||||
"import/resolver": "webpack"
|
||||
},
|
||||
"globals": {
|
||||
"fetch": true,
|
||||
"process": true,
|
||||
"module": true,
|
||||
"__dirname": true
|
||||
}
|
||||
}
|
||||
2456
frontend/package-lock.json
generated
|
|
@ -3,48 +3,29 @@
|
|||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@babel/core": "^7.4.3",
|
||||
"@babel/plugin-proposal-class-properties": "^7.10.4",
|
||||
"@babel/plugin-transform-runtime": "^7.16.10",
|
||||
"@babel/preset-env": "^7.4.3",
|
||||
"@babel/preset-react": "^7.0.0",
|
||||
"@react-google-maps/api": "^2.1.1",
|
||||
"@sentry/react": "^6.17.6",
|
||||
"@sentry/tracing": "^6.17.6",
|
||||
"@svgr/webpack": "^5.5.0",
|
||||
"@testing-library/jest-dom": "^4.2.4",
|
||||
"@testing-library/react": "^9.5.0",
|
||||
"@testing-library/user-event": "^7.2.1",
|
||||
"@tooljet/plugins": "../plugins",
|
||||
"@uiw/react-codemirror": "^3.0.6",
|
||||
"@y-presence/react": "^2.0.0",
|
||||
"array-move": "^3.0.1",
|
||||
"axios": "^0.24.0",
|
||||
"babel-eslint": "^10.1.0",
|
||||
"babel-loader": "^8.0.5",
|
||||
"babel-plugin-console-source": "^2.0.5",
|
||||
"babel-plugin-import": "^1.13.3",
|
||||
"bootstrap": "^4.6.0",
|
||||
"classnames": "^2.3.1",
|
||||
"compression-webpack-plugin": "^10.0.0",
|
||||
"css-loader": "^6.5.1",
|
||||
"date-fns": "^2.28.0",
|
||||
"dompurify": "^2.2.7",
|
||||
"draft-js": "^0.11.7",
|
||||
"draft-js-export-html": "^1.4.1",
|
||||
"driver.js": "^0.9.8",
|
||||
"emoji-mart": "^3.0.1",
|
||||
"esbuild": "^0.15.3",
|
||||
"fuse.js": "^6.4.6",
|
||||
"history": "^4.9.0",
|
||||
"html-loader": "^3.1.0",
|
||||
"html-webpack-plugin": "^5.3.2",
|
||||
"immer": "^9.0.6",
|
||||
"immutability-helper": "^3.1.1",
|
||||
"lodash": "^4.17.21",
|
||||
"moment": "^2.29.1",
|
||||
"moment-timezone": "^0.5.34",
|
||||
"node-sass": "^4.14.1",
|
||||
"papaparse": "^5.3.0",
|
||||
"plotly.js-basic-dist-min": "^1.58.4",
|
||||
"psl": "^1.8.0",
|
||||
|
|
@ -90,21 +71,29 @@
|
|||
"react-tooltip": "^4.2.18",
|
||||
"react-zoom-pan-pinch": "^2.1.3",
|
||||
"rxjs": "^6.3.3",
|
||||
"sass-loader": "^12.4.0",
|
||||
"semver": "^5.7.1",
|
||||
"style-loader": "^3.3.1",
|
||||
"superstruct": "^0.15.4",
|
||||
"terser-webpack-plugin": "^5.3.4",
|
||||
"tinycolor2": "^1.4.2",
|
||||
"url-join": "^5.0.0",
|
||||
"uuid": "8.3.2",
|
||||
"webpack": "^5.55.1",
|
||||
"webpack-cli": "^4.8.0",
|
||||
"xlsx": "^0.18.5",
|
||||
"y-websocket": "^1.4.0",
|
||||
"yjs": "^13.5.28",
|
||||
"yup": "^0.27.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.4.3",
|
||||
"@babel/eslint-parser": "^7.18.9",
|
||||
"@babel/plugin-proposal-class-properties": "^7.10.4",
|
||||
"@babel/plugin-transform-runtime": "^7.16.10",
|
||||
"@babel/preset-env": "^7.4.3",
|
||||
"@babel/preset-react": "^7.18.6",
|
||||
"babel-loader": "^8.0.5",
|
||||
"babel-plugin-console-source": "^2.0.5",
|
||||
"babel-plugin-import": "^1.13.3",
|
||||
"compression-webpack-plugin": "^10.0.0",
|
||||
"css-loader": "^6.5.1",
|
||||
"esbuild": "^0.15.3",
|
||||
"eslint": "^7.32.0",
|
||||
"eslint-config-prettier": "^8.3.0",
|
||||
"eslint-import-resolver-webpack": "^0.13.1",
|
||||
|
|
@ -113,10 +102,22 @@
|
|||
"eslint-plugin-prettier": "^3.4.1",
|
||||
"eslint-plugin-react": "^7.25.2",
|
||||
"eslint-plugin-react-hooks": "^4.2.0",
|
||||
"html-loader": "^3.1.0",
|
||||
"html-webpack-plugin": "^5.3.2",
|
||||
"jest": "^27.5.1",
|
||||
"node-sass": "^4.14.1",
|
||||
"path": "^0.12.7",
|
||||
"prettier": "^2.3.2",
|
||||
"webpack-dev-server": "^4.7.4"
|
||||
"sass-loader": "^12.4.0",
|
||||
"style-loader": "^3.3.1",
|
||||
"terser-webpack-plugin": "^5.3.4",
|
||||
"webpack": "^5.55.1",
|
||||
"webpack-cli": "^4.8.0",
|
||||
"webpack-dev-server": "^4.7.4",
|
||||
"@svgr/webpack": "^5.5.0",
|
||||
"@testing-library/jest-dom": "^4.2.4",
|
||||
"@testing-library/react": "^9.5.0",
|
||||
"@testing-library/user-event": "^7.2.1"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "webpack serve --port 8082 --host 0.0.0.0",
|
||||
|
|
@ -155,4 +156,4 @@
|
|||
"jsx"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -21,7 +21,7 @@ import { ResetPassword } from '@/ResetPassword';
|
|||
import { ManageSSO } from '@/ManageSSO';
|
||||
import { ManageOrgVars } from '@/ManageOrgVars';
|
||||
import { lt } from 'semver';
|
||||
import { Toaster } from 'react-hot-toast';
|
||||
import Toast from '@/_ui/Toast';
|
||||
import { RealtimeEditor } from '@/Editor/RealtimeEditor';
|
||||
import { Editor } from '@/Editor/Editor';
|
||||
import { RedirectSso } from '@/RedirectSso/RedirectSso';
|
||||
|
|
@ -76,6 +76,7 @@ class App extends React.Component {
|
|||
|
||||
if (darkMode) {
|
||||
toastOptions = {
|
||||
className: 'toast-dark-mode',
|
||||
style: {
|
||||
borderRadius: '10px',
|
||||
background: '#333',
|
||||
|
|
@ -259,7 +260,7 @@ class App extends React.Component {
|
|||
/>
|
||||
</div>
|
||||
</BrowserRouter>
|
||||
<Toaster toastOptions={toastOptions} />
|
||||
<Toast toastOptions={toastOptions} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -164,9 +164,6 @@ export const Box = function Box({
|
|||
? validateProperties(resolvedProperties, componentMeta.properties)
|
||||
: [resolvedProperties, []];
|
||||
|
||||
if (componentMeta.component === 'Button') {
|
||||
// console.log('validated properties', validatedProperties, 'resolvedProperties', resolvedProperties);
|
||||
}
|
||||
const resolvedStyles = resolveStyles(component, currentState, null, customResolvables);
|
||||
const [validatedStyles, styleErrors] =
|
||||
mode === 'edit' && component.validate
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ export const Number = ({ value, onChange, forceCodeBox }) => {
|
|||
backgroundColor: 'transparent',
|
||||
border: 'none',
|
||||
color: darkMode && '#fff',
|
||||
width: '100%',
|
||||
};
|
||||
return (
|
||||
<>
|
||||
|
|
@ -17,7 +18,7 @@ export const Number = ({ value, onChange, forceCodeBox }) => {
|
|||
<div className="field form-control" style={{ padding: '0.225rem 0.35rem' }} data-cy="border-radius-input">
|
||||
<input
|
||||
style={numberTheme}
|
||||
type="text"
|
||||
type="number"
|
||||
onChange={(e) => {
|
||||
setNumber(e.target.value);
|
||||
onChange(`{{${e.target.value}}}`);
|
||||
|
|
|
|||
|
|
@ -5,7 +5,14 @@ import 'react-dates/lib/css/_datepicker.css';
|
|||
import 'react-dates/initialize';
|
||||
import moment from 'moment';
|
||||
|
||||
export const DaterangePicker = function DaterangePicker({ height, properties, styles, setExposedVariable, width }) {
|
||||
export const DaterangePicker = function DaterangePicker({
|
||||
height,
|
||||
properties,
|
||||
styles,
|
||||
setExposedVariable,
|
||||
width,
|
||||
darkMode,
|
||||
}) {
|
||||
const { borderRadius, visibility, disabledState } = styles;
|
||||
const { defaultStartDate, defaultEndDate } = properties;
|
||||
const formatProp = typeof properties.format === 'string' ? properties.format : '';
|
||||
|
|
@ -54,7 +61,10 @@ export const DaterangePicker = function DaterangePicker({ height, properties, st
|
|||
}
|
||||
|
||||
return (
|
||||
<div className="daterange-picker-widget p-0" style={{ height, display: visibility ? '' : 'none' }}>
|
||||
<div
|
||||
className={`daterange-picker-widget ${darkMode && 'theme-dark'} p-0`}
|
||||
style={{ height, display: visibility ? '' : 'none' }}
|
||||
>
|
||||
<DateRangePicker
|
||||
disabled={disabledState}
|
||||
startDate={startDate}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import React, { useEffect, useMemo } from 'react';
|
|||
import { useDropzone } from 'react-dropzone';
|
||||
import { resolveWidgetFieldValue } from '@/_helpers/utils';
|
||||
import { toast } from 'react-hot-toast';
|
||||
import * as XLSX from 'xlsx/xlsx.mjs';
|
||||
|
||||
export const FilePicker = ({
|
||||
width,
|
||||
|
|
@ -24,9 +25,11 @@ export const FilePicker = ({
|
|||
const fileType = component.definition.properties.fileType?.value ?? 'image/*';
|
||||
const maxSize = component.definition.properties.maxSize?.value ?? 1048576;
|
||||
const minSize = component.definition.properties.minSize?.value ?? 0;
|
||||
const parseContent = component.definition.properties.parseContent?.value ?? false;
|
||||
const parseContent = resolveWidgetFieldValue(
|
||||
component.definition.properties.parseContent?.value ?? false,
|
||||
currentState
|
||||
);
|
||||
const fileTypeFromExtension = component.definition.properties.parseFileType?.value ?? 'auto-detect';
|
||||
|
||||
const parsedEnableDropzone =
|
||||
typeof enableDropzone !== 'boolean' ? resolveWidgetFieldValue(enableDropzone, currentState) : true;
|
||||
const parsedEnablePicker =
|
||||
|
|
@ -182,7 +185,9 @@ export const FilePicker = ({
|
|||
content: readFileAsText,
|
||||
dataURL: readFileAsDataURL, // TODO: Fix dataURL to have correct format
|
||||
base64Data: readFileAsDataURL,
|
||||
parsedData: shouldProcessFileParsing ? await processFileContent(file.type, readFileAsText) : null,
|
||||
parsedData: shouldProcessFileParsing
|
||||
? await processFileContent(file.type, { readFileAsDataURL, readFileAsText })
|
||||
: null,
|
||||
filePath: file.path,
|
||||
};
|
||||
};
|
||||
|
|
@ -395,11 +400,27 @@ const processCSV = (str, delimiter = ',') => {
|
|||
handleErrors(error);
|
||||
}
|
||||
};
|
||||
const processXls = (str) => {
|
||||
try {
|
||||
const wb = XLSX.read(str, { type: 'base64' });
|
||||
const wsname = wb.SheetNames[0];
|
||||
const ws = wb.Sheets[wsname];
|
||||
/* Convert array of arrays */
|
||||
const data = XLSX.utils.sheet_to_json(ws);
|
||||
return data;
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
handleErrors(error);
|
||||
}
|
||||
};
|
||||
|
||||
const processFileContent = (fileType, fileContent) => {
|
||||
switch (fileType) {
|
||||
case 'text/csv':
|
||||
return processCSV(fileContent);
|
||||
return processCSV(fileContent.readFileAsText);
|
||||
case 'application/vnd.ms-excel':
|
||||
case 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet':
|
||||
return processXls(fileContent.readFileAsDataURL);
|
||||
|
||||
default:
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -58,6 +58,7 @@ export const Modal = function Modal({
|
|||
enforceFocus={false}
|
||||
animation={false}
|
||||
onEscapeKeyDown={() => hideOnEsc && hideModal()}
|
||||
id="modal-container"
|
||||
>
|
||||
{containerProps.mode === 'edit' && <ConfigHandle id={id} component={component} />}
|
||||
{!hideTitleBar && (
|
||||
|
|
|
|||
|
|
@ -122,7 +122,7 @@ export const Multiselect = function Multiselect({
|
|||
<div className="col-auto my-auto d-flex align-items-center">
|
||||
<label
|
||||
style={{ marginRight: label ? '1rem' : '', marginBottom: 0 }}
|
||||
className="form-label py-1"
|
||||
className="form-label py-1 text-secondary"
|
||||
data-cy={`multiselect-label-${component.name.toLowerCase()}`}
|
||||
>
|
||||
{label}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
import React, { useState, useCallback, useRef, useEffect } from 'react';
|
||||
// eslint-disable-next-line import/no-unresolved
|
||||
import { Document, Page } from 'react-pdf/dist/esm/entry.webpack';
|
||||
import 'react-pdf/dist/esm/Page/AnnotationLayer.css';
|
||||
import { debounce } from 'lodash';
|
||||
|
||||
export const PDF = React.memo(({ styles, properties, width, height, component }) => {
|
||||
const pdfName = component.name;
|
||||
|
|
@ -9,30 +11,39 @@ export const PDF = React.memo(({ styles, properties, width, height, component })
|
|||
const [numPages, setNumPages] = useState(null);
|
||||
const [pageNumber, setPageNumber] = useState(null);
|
||||
const pageRef = useRef([]);
|
||||
const documentRef = useRef(null);
|
||||
const hasScrollRef = useRef(false);
|
||||
const [error, setError] = useState(true);
|
||||
const [pageLoading, setPageLoading] = useState(true);
|
||||
const onDocumentLoadSuccess = (document) => {
|
||||
const [hasButtonClicked, setButtonClick] = useState(false);
|
||||
|
||||
const onDocumentLoadSuccess = async (document) => {
|
||||
const { numPages: nextNumPages } = document;
|
||||
setNumPages(nextNumPages);
|
||||
setPageNumber(1);
|
||||
setError(false);
|
||||
setPageLoading(false);
|
||||
};
|
||||
|
||||
const onDocumentLoadError = () => {
|
||||
setError(true);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
setPageLoading(true);
|
||||
}, [url]);
|
||||
|
||||
const options = {
|
||||
root: document.querySelector('#pdf-wrapper'),
|
||||
rootMargin: '0px',
|
||||
threshold: 0.5,
|
||||
threshold: 0.7,
|
||||
};
|
||||
|
||||
const trackIntersection = (entries) => {
|
||||
let isCaptured = false;
|
||||
entries.forEach((entry) => {
|
||||
if (entry.isIntersecting) {
|
||||
if (entry.isIntersecting && !isCaptured && hasScrollRef.current) {
|
||||
isCaptured = true;
|
||||
const currentPage = parseInt(entry.target.getAttribute('data-page-number'));
|
||||
if (pageNumber !== currentPage) setPageNumber(currentPage);
|
||||
}
|
||||
|
|
@ -50,7 +61,9 @@ export const PDF = React.memo(({ styles, properties, width, height, component })
|
|||
|
||||
const updatePage = useCallback(
|
||||
(offset) => {
|
||||
pageRef.current[pageNumber + offset - 1].scrollIntoView({ block: 'nearest' });
|
||||
const { offsetTop } = pageRef.current[pageNumber + offset - 1];
|
||||
documentRef.current.scrollTop = offsetTop;
|
||||
setButtonClick(true);
|
||||
setPageNumber((prevPageNumber) => (prevPageNumber || 1) + offset);
|
||||
},
|
||||
[pageNumber]
|
||||
|
|
@ -99,10 +112,24 @@ export const PDF = React.memo(({ styles, properties, width, height, component })
|
|||
document.body.removeChild(anchor);
|
||||
URL.revokeObjectURL(pdfURL);
|
||||
}
|
||||
|
||||
const handleScroll = () => {
|
||||
if (hasButtonClicked) return setButtonClick(false);
|
||||
if (!hasScrollRef.current) hasScrollRef.current = true;
|
||||
debounce(() => {
|
||||
if (hasScrollRef.current) hasScrollRef.current = false;
|
||||
}, 150);
|
||||
};
|
||||
|
||||
return (
|
||||
<div style={{ display: visibility ? 'flex' : 'none', width: width - 3, height }}>
|
||||
<div className="d-flex position-relative h-100 flex-column" style={{ margin: '0 auto', overflow: 'hidden' }}>
|
||||
<div className="scrollable h-100 col position-relative" id="pdf-wrapper">
|
||||
<div
|
||||
className="scrollable h-100 col position-relative"
|
||||
id="pdf-wrapper"
|
||||
ref={documentRef}
|
||||
onScroll={handleScroll}
|
||||
>
|
||||
{url === '' ? 'No PDF file specified' : renderPDF()}
|
||||
</div>
|
||||
{!error && !pageLoading && (showDownloadOption || pageControls) && (
|
||||
|
|
|
|||
|
|
@ -2,8 +2,22 @@ import React, { useState, useEffect } from 'react';
|
|||
import DOMPurify from 'dompurify';
|
||||
|
||||
export const Text = function Text({ height, properties, styles, darkMode, registerAction }) {
|
||||
const { textSize, textColor, textAlign, visibility, disabledState } = styles;
|
||||
|
||||
let {
|
||||
textSize,
|
||||
textColor,
|
||||
textAlign,
|
||||
visibility,
|
||||
disabledState,
|
||||
fontWeight,
|
||||
decoration,
|
||||
transformation,
|
||||
fontStyle,
|
||||
lineHeight,
|
||||
textIndent,
|
||||
letterSpacing,
|
||||
wordSpacing,
|
||||
fontVariant,
|
||||
} = styles;
|
||||
const [loadingState, setLoadingState] = useState(false);
|
||||
const [text, setText] = useState(() => computeText());
|
||||
|
||||
|
|
@ -31,6 +45,15 @@ export const Text = function Text({ height, properties, styles, darkMode, regist
|
|||
display: visibility ? 'flex' : 'none',
|
||||
alignItems: 'center',
|
||||
textAlign,
|
||||
fontWeight: fontWeight ? fontWeight : fontWeight === '0' ? 0 : 'normal',
|
||||
lineHeight: lineHeight ?? 1.5,
|
||||
textDecoration: decoration ?? 'none',
|
||||
textTransform: transformation ?? 'none',
|
||||
fontStyle: fontStyle ?? 'none',
|
||||
fontVariant: fontVariant ?? 'normal',
|
||||
textIndent: `${textIndent}px` ?? '0px',
|
||||
letterSpacing: `${letterSpacing}px` ?? '0px',
|
||||
wordSpacing: `${wordSpacing}px` ?? '0px',
|
||||
};
|
||||
|
||||
return (
|
||||
|
|
|
|||