diff --git a/Gemfile b/Gemfile index e29e04cee7..342d65e5e6 100644 --- a/Gemfile +++ b/Gemfile @@ -39,6 +39,7 @@ gem "mongo", "~> 2" gem 'aws-sdk', '~> 3' gem 'kaminari' gem 'lockbox' +gem 'tiny_tds' group :development, :test do # Call 'byebug' anywhere in the code to stop execution and get a debugger console diff --git a/Gemfile.lock b/Gemfile.lock index 63a944e78f..d6a2454679 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1354,6 +1354,7 @@ GEM activesupport (>= 4.0) sprockets (>= 3.0.0) thor (1.1.0) + tiny_tds (2.1.5) typhoeus (1.4.0) ethon (>= 0.9.0) tzinfo (2.0.4) @@ -1394,6 +1395,7 @@ DEPENDENCIES rubocop-rails simple_command spring + tiny_tds typhoeus tzinfo-data diff --git a/app/services/mssql_query_service.rb b/app/services/mssql_query_service.rb new file mode 100644 index 0000000000..e19d48c0fb --- /dev/null +++ b/app/services/mssql_query_service.rb @@ -0,0 +1,59 @@ +class MssqlQueryService + include DatasourceUtils + attr_accessor :data_query, :data_source, :options, :source_options, :current_user + + def initialize(data_query, data_source, options, source_options, current_user) + @data_query = data_query + @data_source = data_source + @options = options + @source_options = source_options + @current_user = current_user + end + + def self.connection(options) + TinyTds::Client.new( + database: options.dig('database', 'value'), + username: options.dig('username', 'value'), + password: options.dig('password', 'value'), + host: options.dig('host', 'value'), + port: options.dig('port', 'value'), + azure: ActiveModel::Type::Boolean.new.cast( + options.dig('azure', 'value') + ) || false + ) + end + + def process + connection = get_cached_connection(data_source) + connection ||= create_connection + query_text = options['query'] + results = connection.execute(query_text) + + { status: 'success', data: results.to_a } + rescue StandardError => e + if connection&.active? + connection&.close + reset_connection(data_source) + end + + error = { message: e.message, code: 400 } + end + + private + + def create_connection + connection = TinyTds::Client.new( + database: source_options['database'], + username: source_options['username'], + password: source_options['password'], + host: source_options['host'], + port: source_options['port'], + azure: ActiveModel::Type::Boolean.new.cast( + source_options['azure'] + ) || false + ) + + cache_connection(data_source, connection) + connection + end +end diff --git a/config/database.yml b/config/database.yml index 9757b2b962..83ffd969b5 100644 --- a/config/database.yml +++ b/config/database.yml @@ -3,6 +3,7 @@ default: &default encoding: unicode pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> + development: <<: *default database: tooljet_development @@ -13,6 +14,9 @@ development: test: <<: *default database: tooljet_test + username: postgres + password: <%= ENV.fetch("DB_PASSWORD", '') %> + host: <%= ENV.fetch("DB_HOST", 'localhost') %> production: <<: *default @@ -20,4 +24,4 @@ production: database: <%= ENV['PG_DB'] %> username: <%= ENV['PG_USER'] %> password: <%= ENV['PG_PASS'] %> - \ No newline at end of file + diff --git a/db/seeds.rb b/db/seeds.rb index 2c9d60a218..141ca27390 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -1,4 +1,4 @@ org = Organization.create(name: 'My organization') user = User.create(first_name: 'The', last_name: 'Developer', email: 'dev@tooljet.io', password: 'password', organization: org) -OrganizationUser.create(user: user, organization: org, role: 'admin') \ No newline at end of file +OrganizationUser.create(user: user, organization: org, role: 'admin', status: 'active') diff --git a/docker-compose.yaml b/docker-compose.yaml index 0b60fd0b04..ea6922e826 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -4,7 +4,7 @@ services: base: &base build: context: . - dockerfile: ./docker/server.Dockerfile + dockerfile: ./docker/server.Dockerfile.dev args: RAILS_ENV: 'development' tty: true @@ -32,7 +32,7 @@ services: <<: *base build: context: . - dockerfile: ./docker/server.Dockerfile + dockerfile: ./docker/server.Dockerfile.dev image: tooljet-server:development volumes: - ./:/app:delegated @@ -46,14 +46,12 @@ services: - RAILS_ENV=development - DB_PASSWORD=postgres - DB_HOST=postgres - entrypoint: ["bash", "/app/docker/entrypoints/server.sh"] + entrypoint: ["bash", "/app/docker/entrypoints/server.sh"] command: ["bundle", "exec", "rails", "s", "-p", "3000", "-b", "0.0.0.0"] postgres: image: postgres:12 restart: always - ports: - - '5432:5432' volumes: - postgres:/data/postgres environment: @@ -61,6 +59,7 @@ services: - POSTGRES_USER=postgres - POSTGRES_PASSWORD=postgres + volumes: postgres: node_modules: diff --git a/docker/entrypoints/server.sh b/docker/entrypoints/server.sh index eaeea2bf52..ae3d784dac 100644 --- a/docker/entrypoints/server.sh +++ b/docker/entrypoints/server.sh @@ -1,7 +1,11 @@ #!/bin/bash set -e - +bundle check || bundle install rake db:create rake db:migrate -exec "$@" \ No newline at end of file +if [ -e tmp/pids/server.pid ]; then + rm tmp/pids/server.pid +fi + +exec "$@" diff --git a/docker/server.Dockerfile b/docker/server.Dockerfile index eed9178700..91f6210de0 100644 --- a/docker/server.Dockerfile +++ b/docker/server.Dockerfile @@ -2,7 +2,8 @@ FROM ruby:2.7.3-buster RUN apt update && apt install -y \ build-essential \ - postgresql + postgresql \ + freetds-dev RUN mkdir -p /app WORKDIR /app diff --git a/docker/server.Dockerfile.dev b/docker/server.Dockerfile.dev new file mode 100644 index 0000000000..1724b182f7 --- /dev/null +++ b/docker/server.Dockerfile.dev @@ -0,0 +1,18 @@ +FROM ruby:2.7.3-buster + +RUN apt update && apt install -y \ + build-essential \ + postgresql \ + freetds-dev + +RUN mkdir -p /app +WORKDIR /app + +COPY Gemfile Gemfile.lock ./ +RUN gem install bundler && bundle install --jobs 20 --retry 5 + +ENV RAILS_ENV=development + +COPY . ./ + +RUN ["chmod", "755", "docker/entrypoints/server.sh"] diff --git a/docs/docs/contributing-guide/setup/Mac OS.md b/docs/docs/contributing-guide/setup/Mac OS.md index 4282e5bb62..28283440b6 100644 --- a/docs/docs/contributing-guide/setup/Mac OS.md +++ b/docs/docs/contributing-guide/setup/Mac OS.md @@ -22,11 +22,15 @@ Follow these steps to setup and run ToolJet on Mac OS. Open terminal and run the $ curl -L https://get.rvm.io | bash -s stable ``` - ### Install Ruby using RVM + ### Install Ruby using RVM ```bash $ rvm install ruby-2.7.3 $ rvm use 2.7.3 ``` + ### Install [Bundler](https://bundler.io/) + ```bash + gem install bundler:2.1.4 + ``` ### Install Node.js ```bash @@ -42,41 +46,52 @@ Follow these steps to setup and run ToolJet on Mac OS. Open terminal and run the ### Install MySQL ( optional ) Skip this step if you do not want to connect to MySQL datasources. ```bash - $ brew install mysql + $ brew install mysql ``` 2. ## Setup environment variables Create a `.env` file by copying `.env.example`. More information on the variables that can be set is given here: env variable reference ```bash $ cp .env.example .env - ``` + ``` -3. ## Install Ruby on Rails dependencies +3. ## Populate the keys in the env file. + Run `openssl rand -hex 64` to create secure secrets and use them as the values for `LOCKBOX_MASTER_KEY` and `SECRET_KEY_BASE`. + + Example: + ```bash + $ cat .env + TOOLJET_HOST=http://localhost:8082 + LOCKBOX_MASTER_KEY=c92bcc7f112ffbdd131d1fb6c5005e372b8802f85f6c4586e5a88f57a541382841c8c99e5701b84862e448dd5db846f705321a41bd48a0fed1b58b9596a3877f + SECRET_KEY_BASE=4229d5774cfe7f60e75d6b3bf3a1dbb054a696b6d21b6d5de7b73291899797a222265e12c0a8e8d844f83ebacdf9a67ec42584edf1c2b23e1e7813f8a3339041 + ``` + +4. ## Install Ruby on Rails dependencies ```bash $ bundle ``` -4. ## install React dependencies - ```bash +5. ## install React dependencies + ```bash $ npm install ``` -5. ## Setup Rails server - ```bash +6. ## Setup Rails server + ```bash $ bundle exec rake db:create $ bundle exec rake db:reset $ bundle exec rails server ``` -6. ## Create login credentials +7. ## Create login credentials - 1. Open rails console using: + 1. Open rails console using: - ```bash + ```bash $ bundle exec rails console ``` - 2. Create a new organization + 2. Create a new organization ```ruby Organization.create(name: 'Dev') ``` @@ -88,12 +103,12 @@ Follow these steps to setup and run ToolJet on Mac OS. Open terminal and run the 4. Add user to the organization as admin ```ruby - OrganizationUser.create(user: User.first, organization: Organization.first, role: 'admin') + OrganizationUser.create(user: User.first, organization: Organization.first, role: 'admin', status: 'active') ``` -7. ## Running the React frontend ( Client ) - ```bash +8. ## Running the React frontend ( Client ) + ```bash $ cd ./frontend && npm start ``` -The client will start running on the port 8082, you can access the client by visiting: [https://localhost:8082](https://localhost:8082 ) \ No newline at end of file +The client will start running on the port 8082, you can access the client by visiting: [https://localhost:8082](https://localhost:8082) diff --git a/docs/docs/contributing-guide/setup/docker.md b/docs/docs/contributing-guide/setup/docker.md index 600dbce43a..1651f97ef9 100644 --- a/docs/docs/contributing-guide/setup/docker.md +++ b/docs/docs/contributing-guide/setup/docker.md @@ -7,12 +7,12 @@ Docker compose is the easiest way to setup ToolJet server and client locally. ## Prerequisites -Make sure you have the latest version of `docker` and `docker-compose` installed. +Make sure you have the latest version of `docker` and `docker-compose` installed. -[Official docker installation guide](https://docs.docker.com/desktop/) +[Official docker installation guide](https://docs.docker.com/desktop/) [Official docker-compose installation guide](https://docs.docker.com/compose/install/) -We recommend: +We recommend: ```bash $ docker --version Docker version 19.03.12, build 48a66213fe @@ -20,11 +20,11 @@ $ docker-compose --version docker-compose version 1.26.2, build eefe0d31 ``` -## Setting up +## Setting up 1. Close the repository ```bash -$ git clone https://github.com/tooljet/tooljet.git +$ git clone https://github.com/tooljet/tooljet.git ``` 2. Create a `.env` file by copying `.env.example`. More information on the variables that can be set is given here: env variable reference @@ -32,9 +32,19 @@ $ git clone https://github.com/tooljet/tooljet.git $ cp .env.example .env ``` -3. Build docker images +3. Populate the keys in the `.env` file. Run `openssl rand -hex 64` to create secure secrets and use them as the values for `LOCKBOX_MASTER_KEY` and `SECRET_KEY_BASE`. + +Example: ```bash -$ docker-compose build +$ cat .env +TOOLJET_HOST=http://localhost:8082 +LOCKBOX_MASTER_KEY=c92bcc7f112ffbdd131d1fb6c5005e372b8802f85f6c4586e5a88f57a541382841c8c99e5701b84862e448dd5db846f705321a41bd48a0fed1b58b9596a3877f +SECRET_KEY_BASE=4229d5774cfe7f60e75d6b3bf3a1dbb054a696b6d21b6d5de7b73291899797a222265e12c0a8e8d844f83ebacdf9a67ec42584edf1c2b23e1e7813f8a3339041 +``` + +4. Build docker images +```bash +$ docker-compose build ``` 4. ToolJet server is built using Ruby on Rails. You have to reset the database if building for the first time. @@ -47,51 +57,29 @@ $ docker-compose run server rails db:reset $ docker-compose up ``` -6. Creating login credentials - - 1. Open rails console using: - - ```bash - $ docker-compose run server rails console - ``` - - 2. Create a new organization - ```ruby - Organization.create(name: 'Dev') - ``` - - 3. Create a new user - ```ruby - User.create(first_name: 'dev', email: 'dev@tooljet.io', password: 'password', organization: Organization.first) - ``` - - 4. Add user to the organization as admin - ```ruby - OrganizationUser.create(user: User.first, organization: Organization.first, role: 'admin') - ``` +6. The app should now be served locally at http://localhost:8082/. You can login using the default user created. + [ email: dev@tooljet.io + password: password + ] 7. To shut down the containers, ```bash -$ docker-compose down +$ docker-compose stop ``` -## Running Rails tests +## Running Rails tests -To run all the tests +To run all the tests -```bash -$ docker-compose run server rails test +```bash +$ docker-compose run server rails test ``` -To run a specific test -```bash +To run a specific test +```bash $ docker-compose run server rails test : ``` ## Troubleshooting -If there is any change to dockerfiles, Gemfile or package.json, rebuild the images using: - -```bash -$ docker-compose up --build -``` \ No newline at end of file +Please open a new issue at https://github.com/ToolJet/ToolJet/issues or join our slack channel (https://join.slack.com/t/tooljet/shared_invite/zt-r2neyfcw-KD1COL6t2kgVTlTtAV5rtg) if you encounter any issues when trying to run ToolJet locally. diff --git a/docs/docs/contributing-guide/setup/ubuntu.md b/docs/docs/contributing-guide/setup/ubuntu.md index 4a7991675c..d22fd38ea2 100644 --- a/docs/docs/contributing-guide/setup/ubuntu.md +++ b/docs/docs/contributing-guide/setup/ubuntu.md @@ -16,7 +16,7 @@ Follow these steps to setup and run ToolJet on Ubuntu. Open terminal and run the $ sudo apt-get install rvm ``` - ### Install Ruby using RVM + ### Install Ruby using RVM ```bash $ rvm install ruby-2.7.3 $ rvm use 2.7.3 @@ -38,34 +38,46 @@ Follow these steps to setup and run ToolJet on Ubuntu. Open terminal and run the Create a `.env` file by copying `.env.example`. More information on the variables that can be set is given here: env variable reference ```bash $ cp .env.example .env - ``` + ``` -3. ## Install Ruby on Rails dependencies + +3. ## Populate the keys in the env file. + Run `openssl rand -hex 64` to create secure secrets and use them as the values for `LOCKBOX_MASTER_KEY` and `SECRET_KEY_BASE`. + + Example: + ```bash + $ cat .env + TOOLJET_HOST=http://localhost:8082 + LOCKBOX_MASTER_KEY=c92bcc7f112ffbdd131d1fb6c5005e372b8802f85f6c4586e5a88f57a541382841c8c99e5701b84862e448dd5db846f705321a41bd48a0fed1b58b9596a3877f + SECRET_KEY_BASE=4229d5774cfe7f60e75d6b3bf3a1dbb054a696b6d21b6d5de7b73291899797a222265e12c0a8e8d844f83ebacdf9a67ec42584edf1c2b23e1e7813f8a3339041 + ``` + +4. ## Install Ruby on Rails dependencies ```bash $ bundle ``` -4. ## install React dependencies - ```bash +5. ## install React dependencies + ```bash $ npm install ``` -5. ## Setup Rails server - ```bash +6. ## Setup Rails server + ```bash $ bundle exec rake db:create $ bundle exec rake db:reset $ bundle exec rails server ``` -6. ## Create login credentials +7. ## Create login credentials - 1. Open rails console using: + 1. Open rails console using: - ```bash + ```bash $ bundle exec rails console ``` - 2. Create a new organization + 2. Create a new organization ```ruby Organization.create(name: 'Dev') ``` @@ -77,12 +89,12 @@ Follow these steps to setup and run ToolJet on Ubuntu. Open terminal and run the 4. Add user to the organization as admin ```ruby - OrganizationUser.create(user: User.first, organization: Organization.first, role: 'admin') + OrganizationUser.create(user: User.first, organization: Organization.first, role: 'admin', status: 'active') ``` -7. ## Running the React frontend ( Client ) - ```bash +8. ## Running the React frontend ( Client ) + ```bash $ cd ./frontend && npm start ``` -The client will start running on the port 8082, you can access the client by visiting: [https://localhost:8082](https://localhost:8082 ) \ No newline at end of file +The client will start running on the port 8082, you can access the client by visiting: [https://localhost:8082](https://localhost:8082) diff --git a/frontend/assets/images/icons/editor/datasources/mssql.svg b/frontend/assets/images/icons/editor/datasources/mssql.svg new file mode 100644 index 0000000000..30758ba323 --- /dev/null +++ b/frontend/assets/images/icons/editor/datasources/mssql.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/frontend/src/Editor/Components/Table/Table.jsx b/frontend/src/Editor/Components/Table/Table.jsx index ecc1c80b09..b649e632a0 100644 --- a/frontend/src/Editor/Components/Table/Table.jsx +++ b/frontend/src/Editor/Components/Table/Table.jsx @@ -278,7 +278,7 @@ export function Table({ onBlur={(e) => { handleCellValueChange(cell.row.index, column.key || column.name, e.target.value, cell.row.original); }} - value={cellValue} + defaultValue={cellValue} > ; } if (columnType === 'dropdown') { diff --git a/frontend/src/Editor/DataSourceManager/DataSourceManager.jsx b/frontend/src/Editor/DataSourceManager/DataSourceManager.jsx index 69f3f2585f..ee9e0719bd 100644 --- a/frontend/src/Editor/DataSourceManager/DataSourceManager.jsx +++ b/frontend/src/Editor/DataSourceManager/DataSourceManager.jsx @@ -148,7 +148,7 @@ class DataSourceManager extends React.Component { {selectedDataSource && (
+
diff --git a/frontend/src/Editor/DataSourceManager/DataSourceTypes.js b/frontend/src/Editor/DataSourceManager/DataSourceTypes.js index 8b1cc2e5db..986358f348 100644 --- a/frontend/src/Editor/DataSourceManager/DataSourceTypes.js +++ b/frontend/src/Editor/DataSourceManager/DataSourceTypes.js @@ -31,6 +31,22 @@ export const dataBaseSources = [ password: { type: 'string', encrypted: true } } }, + { + name: 'SQL Server', + kind: 'mssql', + exposedVariables: { + isLoading: {}, + data: {}, + rawData: {} + }, + options: { + host: { type: 'string' }, + port: { type: 'string' }, + database: { type: 'string' }, + username: { type: 'string' }, + password: { type: 'string', encrypted: true } + } + }, { name: 'MongoDB', kind: 'mongodb', diff --git a/frontend/src/Editor/DataSourceManager/DefaultOptions.js b/frontend/src/Editor/DataSourceManager/DefaultOptions.js index 9f71ff9481..b3c4f82e7a 100644 --- a/frontend/src/Editor/DataSourceManager/DefaultOptions.js +++ b/frontend/src/Editor/DataSourceManager/DefaultOptions.js @@ -13,6 +13,13 @@ export const defaultOptions = { username: { value: '' }, password: { value: '' } }, + mssql: { + host: { value: 'localhost' }, + port: { value: 1433 }, + database: { value: '' }, + username: { value: '' }, + password: { value: '' } + }, redis: { host: { value: 'localhost' }, port: { value: 6379 }, @@ -28,7 +35,7 @@ export const defaultOptions = { connection_type: { value: 'manual' }, connection_string: { value: ''} }, - + elasticsearch: { scheme: { value: 'https' }, host: { value: 'localhost' }, diff --git a/frontend/src/Editor/DataSourceManager/SourceComponents/Mssql.jsx b/frontend/src/Editor/DataSourceManager/SourceComponents/Mssql.jsx new file mode 100644 index 0000000000..3fd4ccead0 --- /dev/null +++ b/frontend/src/Editor/DataSourceManager/SourceComponents/Mssql.jsx @@ -0,0 +1,80 @@ +import React from 'react'; + +export const Mssql = ({ + optionchanged, options +}) => { + return ( +
+
+
+ + optionchanged('host', e.target.value)} + value={options.host.value} + /> +
+
+ + optionchanged('port', e.target.value)} + value={options.port.value} + /> +
+
+
+
+ + optionchanged('database', e.target.value)} + value={options.database.value} + /> +
+
+ + optionchanged('username', e.target.value)} + value={options.username.value} + /> +
+
+ + optionchanged('password', e.target.value)} + value={options.password.value} + /> +
+
+
+
+
+ +
+
+
+
+ ); +}; diff --git a/frontend/src/Editor/DataSourceManager/SourceComponents/index.js b/frontend/src/Editor/DataSourceManager/SourceComponents/index.js index 007afd4ee0..f2504dcf41 100644 --- a/frontend/src/Editor/DataSourceManager/SourceComponents/index.js +++ b/frontend/src/Editor/DataSourceManager/SourceComponents/index.js @@ -10,6 +10,7 @@ import { Slack } from './Slack'; import { Mongodb } from './Mongodb'; import { Dynamodb } from './Dynamodb'; import { Airtable } from './Airtable'; +import { Mssql } from './Mssql'; export const SourceComponents = { Elasticsearch, @@ -23,5 +24,6 @@ export const SourceComponents = { Slack, Mongodb, Dynamodb, - Airtable + Airtable, + Mssql }; diff --git a/frontend/src/Editor/Editor.jsx b/frontend/src/Editor/Editor.jsx index 091592d581..53137eeeb4 100644 --- a/frontend/src/Editor/Editor.jsx +++ b/frontend/src/Editor/Editor.jsx @@ -230,6 +230,16 @@ class Editor extends React.Component { this.computeComponentState(newDefinition.components); }; + handleInspectorView = (component) => { + if (this.state.selectedComponent.hasOwnProperty('component')) { + const { id: selectedComponentId } = this.state.selectedComponent; + if (selectedComponentId === component.id) { + this.setState({selectedComponent: null}) + this.switchSidebarTab(2); + } + } + } + removeComponent = (component) => { let newDefinition = this.state.appDefinition; @@ -241,7 +251,7 @@ class Editor extends React.Component { delete newDefinition.components[component.id]; this.appDefinitionChanged(newDefinition); - this.switchSidebarTab(2); + this.handleInspectorView(component); }; componentDefinitionChanged = (newDefinition) => { diff --git a/frontend/src/Editor/Inspector/EventSelector.jsx b/frontend/src/Editor/Inspector/EventSelector.jsx index 7807ac973a..bcad706e40 100644 --- a/frontend/src/Editor/Inspector/EventSelector.jsx +++ b/frontend/src/Editor/Inspector/EventSelector.jsx @@ -93,13 +93,11 @@ export const EventSelector = ({ {definition.actionId === 'show-alert' && (
- eventOptionUpdated(param, 'message', e.target.value, extraData)} - value={message} - type="text" - className="form-control form-control-sm" - placeholder="Text goes here" + eventOptionUpdated(param, 'message', value, extraData)} /> +
)} diff --git a/frontend/src/Editor/Inspector/Inspector.jsx b/frontend/src/Editor/Inspector/Inspector.jsx index b8e807cc72..f949dac530 100644 --- a/frontend/src/Editor/Inspector/Inspector.jsx +++ b/frontend/src/Editor/Inspector/Inspector.jsx @@ -7,7 +7,7 @@ import OverlayTrigger from 'react-bootstrap/OverlayTrigger'; import Popover from 'react-bootstrap/Popover'; import ReactTooltip from 'react-tooltip'; import { toast } from 'react-toastify'; -import { validateQueryName } from '@/_helpers/utils'; +import { validateQueryName, convertToKebabCase } from '@/_helpers/utils'; export const Inspector = ({ selectedComponentId, @@ -244,7 +244,7 @@ export const Inspector = ({
- + {componentMeta.name} documentation diff --git a/frontend/src/Editor/QueryManager/QueryEditors/Mssql.jsx b/frontend/src/Editor/QueryManager/QueryEditors/Mssql.jsx new file mode 100644 index 0000000000..e95e6c29b4 --- /dev/null +++ b/frontend/src/Editor/QueryManager/QueryEditors/Mssql.jsx @@ -0,0 +1,41 @@ +import React from 'react'; +import { CodeHinter } from '../../CodeBuilder/CodeHinter'; +import { changeOption } from './utils'; + +class Mssql extends React.Component { + constructor(props) { + super(props); + + this.state = {}; + } + + componentDidMount() { + this.setState({ + options: this.props.options + }); + } + + render() { + const { options } = this.state; + + return ( +
+ {options && ( +
+ changeOption(this, 'query', value)} + /> +
+ )} +
+ ); + } +} + +export { Mssql }; diff --git a/frontend/src/Editor/QueryManager/QueryEditors/index.js b/frontend/src/Editor/QueryManager/QueryEditors/index.js index 798b11b673..739e6c7e7e 100644 --- a/frontend/src/Editor/QueryManager/QueryEditors/index.js +++ b/frontend/src/Editor/QueryManager/QueryEditors/index.js @@ -10,6 +10,7 @@ import { Slack } from './Slack'; import { Mongodb } from './Mongodb'; import { Dynamodb } from './Dynamodb'; import { Airtable } from './Airtable'; +import { Mssql } from './Mssql'; export const allSources = { Restapi, @@ -23,5 +24,6 @@ export const allSources = { Slack, Mongodb, Dynamodb, - Airtable + Airtable, + Mssql }; diff --git a/frontend/src/Editor/QueryManager/constants.js b/frontend/src/Editor/QueryManager/constants.js index 3e8d696433..8528fbf1ca 100644 --- a/frontend/src/Editor/QueryManager/constants.js +++ b/frontend/src/Editor/QueryManager/constants.js @@ -32,5 +32,8 @@ export const defaultOptions = { }, airtable: { + }, + mssql: { + } }; diff --git a/frontend/src/_helpers/appUtils.js b/frontend/src/_helpers/appUtils.js index f536ab404f..4bcd7e3cde 100644 --- a/frontend/src/_helpers/appUtils.js +++ b/frontend/src/_helpers/appUtils.js @@ -88,7 +88,8 @@ async function copyToClipboard(text) { function executeAction(_ref, event) { if (event) { if (event.actionId === 'show-alert') { - toast(event.options.message, { hideProgressBar: true }); + const message = resolveReferences(event.options.message, _ref.state.currentState); + toast(message, { hideProgressBar: true }); } if (event.actionId === 'open-webpage') { diff --git a/frontend/src/_helpers/utils.js b/frontend/src/_helpers/utils.js index 874250d118..c4c4be7a5f 100644 --- a/frontend/src/_helpers/utils.js +++ b/frontend/src/_helpers/utils.js @@ -129,3 +129,6 @@ export function validateQueryName(name){ const nameRegex = new RegExp('^[A-Za-z0-9_-]*$'); return nameRegex.test(name); }; + + +export const convertToKebabCase = string => string.replace(/([a-z])([A-Z])/g, '$1-$2').replace(/\s+/g, '-').toLowerCase()