diff --git a/deploy/install.sh b/deploy/install.sh new file mode 100755 index 0000000000..8b4dd0083c --- /dev/null +++ b/deploy/install.sh @@ -0,0 +1,179 @@ +#!/bin/bash +set -o errexit + +echo "" > appsmith_deploy.log + +is_command_present() { + type "$1" >/dev/null 2>&1 +} + +install_docker() { + if [[ $package_manager -eq apt-get ]];then + echo "++++++++++++++++++++++++" + echo "Setting up docker repos" + sudo $package_manager update --quiet + + sudo apt-get -y --quiet install gnupg-agent + curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add - + sudo add-apt-repository \ + "deb [arch=amd64] https://download.docker.com/linux/ubuntu \ + $(lsb_release -cs) \ + stable" + else + sudo yum install -y yum-utils + sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo + fi + + sudo ${package_manager} -y update --quiet + echo "Installing docker" + sudo ${package_manager} -y install docker-ce docker-ce-cli containerd.io --quiet + + echo "Installing docker-compose" + sudo curl -L "https://github.com/docker/compose/releases/download/1.26.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose + sudo chmod +x /usr/local/bin/docker-compose +} + +echo -e "\U1F44B Thank you for trying out Appsmith! " +echo "" + +declare -A osInfo; + +osInfo[/etc/debian_version]="apt-get" +osInfo[/etc/centos-release]="yum" +osInfo[/etc/redhat-release]="yum" + +# Checking OS and assiging package manager +desired_os=0 +echo -e "\U1F575 Detecting your OS" +echo "" +for f in ${!osInfo[@]} +do + if [[ -f $f ]];then + package_manager=${osInfo[$f]} + desired_os=1 + fi +done + +if [[ $desired_os -eq 0 ]];then + echo "This script is currently meant to install Appsmith on Ubuntu | RHEL | CentOS machines." + echo "Please contact hello@appsmith.com with your OS details if you wish to extend this support" + echo -e "Exiting for now. Bye! \U1F44B" + exit +fi + +read -p 'Installation Directory [appsmith]: ' install_dir +install_dir=${install_dir:-appsmith} +mkdir -p $PWD/$install_dir +install_dir=$PWD/$install_dir +echo "Appsmith needs a mongodb instance to run" +echo "1) Automatically setup mongo db on this instance (recommended)" +echo "2) Connect to an external mongo db" +read -p 'Enter option number [1]: ' mongo_option +mongo_option=${mongo_option:-1} + +if [[ $mongo_option -eq 2 ]];then + read -p 'Enter your mongo db host: ' mongo_host + read -p 'Enter the mongo root user: ' mongo_root_user + read -sp 'Enter the mongo password: ' mongo_root_password + read -p 'Enter your mongo database name: ' mongo_database +elif [[ $mongo_option -eq 1 ]];then + mongo_host="mongo" + mongo_database="appsmith" + read -p 'Set the mongo root user: ' mongo_root_user + read -sp 'Set the mongo password: ' mongo_root_password +fi +echo "" +read -p 'Would you like to setup a custom domain to access appsmith? [Y/n]: ' setup_domain +setup_domain=${setup_domain:-Y} + +if [ $setup_domain == "Y" -o $setup_domain == "y" -o $setup_domain == "yes" -o $setup_domain == "Yes" ];then + read -p 'Enter your domain name (example.com): ' custom_domain +fi + +NGINX_SSL_CMNT="" +if [[ -z $custom_domain ]]; then + NGINX_SSL_CMNT="#" +fi + +#mkdir template +#cd template +#curl https://raw.githubusercontent.com/Nikhil-Nandagopal/test-rep/master/docker-compose.yml.sh --output docker-compose.yml.sh +#curl https://raw.githubusercontent.com/Nikhil-Nandagopal/test-rep/master/init-letsencrypt.sh.sh --output init-letsencrypt.sh.sh +#curl https://raw.githubusercontent.com/Nikhil-Nandagopal/test-rep/master/mongo-init.js.sh --output mongo-init.js.sh +#curl https://raw.githubusercontent.com/Nikhil-Nandagopal/test-rep/master/nginx_app.conf.sh --output nginx_app.conf.sh +#curl https://raw.githubusercontent.com/Nikhil-Nandagopal/test-rep/master/nginx_app.conf.sh --output nginx_app.conf.sh +#cd .. + +# Role - Docker +if ! is_command_present docker ;then + install_docker +fi + +# Role - Folder +for directory_name in nginx certbot mongo/db opa/config appsmith-server/config +do + if [[ ! -d "$install_dir/data/$directory_name" ]];then + mkdir -p "$install_dir/data/$directory_name" + fi +done + +echo "Generating the configuration files from the templates" +. ./template/nginx_app.conf.sh +. ./template/docker-compose.yml.sh +. ./template/mongo-init.js.sh +. ./template/init-letsencrypt.sh.sh +. ./template/docker.env.sh +chmod 0755 init-letsencrypt.sh + +declare -A fileInfo + +fileInfo[/data/nginx/app.conf]="nginx_app.conf" +fileInfo[/docker-compose.yml]="docker-compose.yml" +fileInfo[/data/mongo/init.js]="mongo-init.js" +fileInfo[/init-letsencrypt.sh]="init-letsencrypt.sh" +fileInfo[/docker.env]="docker.env" + +for f in ${!fileInfo[@]} +do + + if [ -f $install_dir/$f ] + then + echo "File already exist." + read -p "File $f already exist. Would you like to replace it? [Y]: " value + + if [ $value == "Y" -o $value == "y" -o $value == "yes" -o $value == "Yes" ] + then + mv -f ${fileInfo[$f]} $install_dir$f + echo "File $install_dir$f replaced succeffuly!" + else + echo "You choose not to replae existing file: $install_dir$f" + rm -rf ${fileInfo[$f]} + echo "File ${fileInfo[$f]} removed from source directory." + echo "" + fi + else + mv -f ${fileInfo[$f]} $install_dir$f + fi + +done + + +echo "" + +#echo "Running init-letsencrypt.sh...." +cd $install_dir +if [[ ! -z $custom_domain ]]; then + echo "Running init-letsencrypt.sh...." + sudo ./init-letsencrypt.sh +else + echo "No domain found. Skipping generation of LetsEncrypt certificate." +fi + +echo "Updating the container images" +sudo docker-compose pull +echo "Starting the Appsmith containers" +sudo docker-compose -f docker-compose.yml up -d --remove-orphans +echo "" +echo "Your installation is complete. Please run the following command to ensure that all the containers are running without errors" +echo " cd $install_dir && sudo docker-compose ps -a" +echo -e "Peace out \U1F596" diff --git a/deploy/template/docker-compose.yml.sh b/deploy/template/docker-compose.yml.sh new file mode 100644 index 0000000000..632afeda9f --- /dev/null +++ b/deploy/template/docker-compose.yml.sh @@ -0,0 +1,78 @@ +#!/bin/sh + +if [ -f docker-compose.yml ] + then + echo "file docker-compose.yml already exists" + else + touch docker-compose.yml +fi + + + +cat > docker-compose.yml << EOF +version: "3.7" + +services: + nginx: + image: appsmith/appsmith-editor + env_file: ./docker.env + ports: + - "80:80" + - "443:443" + volumes: + - ./data/nginx:/etc/nginx/conf.d + - ./data/certbot/conf:/etc/letsencrypt + - ./data/certbot/www:/var/www/certbot + command: "/bin/sh -c 'while :; do sleep 6h & wait \$\${!}; nginx -s reload; done & nginx -g \"daemon off;\"'" + depends_on: + - appsmith-internal-server + networks: + - appsmith + + certbot: + image: certbot/certbot + volumes: + - ./data/certbot/conf:/etc/letsencrypt + - ./data/certbot/www:/var/www/certbot + entrypoint: "/bin/sh -c 'trap exit TERM; while :; do certbot renew; sleep 12h & wait \$\${!}; done;'" + networks: + - appsmith + + appsmith-internal-server: + image: appsmith/appsmith-server:latest + env_file: ./docker.env + ports: + - "8080:8080" + links: + - mongo + depends_on: + - mongo + networks: + - appsmith + + mongo: + image: mongo + ports: + - "27017:27017" + environment: + - MONGO_INITDB_DATABASE=appsmith + - MONGO_INITDB_ROOT_USERNAME=$mongo_root_user + - MONGO_INITDB_ROOT_PASSWORD=$mongo_root_password + volumes: + - ./data/mongo/db:/data/db + - ./data/mongo/init.js:/docker-entrypoint-initdb.d/init.js:ro + networks: + - appsmith + + redis: + image: redis + ports: + - "6379:6379" + networks: + - appsmith + +networks: + appsmith: + driver: bridge + +EOF diff --git a/deploy/template/docker.env.sh b/deploy/template/docker.env.sh new file mode 100644 index 0000000000..e63cea4133 --- /dev/null +++ b/deploy/template/docker.env.sh @@ -0,0 +1,30 @@ +#!/bin/sh + +if [ -f docker-compose.yml ] + then + echo "file docker-compose.yml already exists" + else + touch docker-compose.yml +fi + +cat > docker.env << EOF +APPSMITH_MAIL_ENABLED=false +# APPSMITH_MAIL_HOST= +# APPSMITH_MAIL_PASSWORD= +# APPSMITH_MAIL_PORT= +# APPSMITH_MAIL_SMTP_AUTH= +# APPSMITH_MAIL_SMTP_TLS_ENABLED= +# APPSMITH_MAIL_USERNAME= +# APPSMITH_MARKETPLACE_URL= +APPSMITH_MONGODB_URI=mongodb://$mongo_root_user:$mongo_root_password@$mongo_host/appsmith?retryWrites=true +# APPSMITH_OAUTH2_GITHUB_CLIENT_ID= +# APPSMITH_OAUTH2_GITHUB_CLIENT_SECRET= +# APPSMITH_OAUTH2_GOOGLE_CLIENT_ID= +# APPSMITH_OAUTH2_GOOGLE_CLIENT_SECRET= +# APPSMITH_RAPID_API_KEY_VALUE= +APPSMITH_REDIS_URL=redis://redis:6379 +# APPSMITH_ROLLBAR_ACCESS_TOKEN= +# APPSMITH_ROLLBAR_ENV= +# APPSMITH_SEGMENT_KEY= + +EOF diff --git a/deploy/template/init-letsencrypt.sh.sh b/deploy/template/init-letsencrypt.sh.sh new file mode 100755 index 0000000000..3f41c3ad5d --- /dev/null +++ b/deploy/template/init-letsencrypt.sh.sh @@ -0,0 +1,96 @@ +#!/bin/sh + +if [ -f init-letsencrypt.sh ] + then + echo "file init-letsencrypt.sh already exists" + else + touch init-letsencrypt.sh +fi + + + +cat > init-letsencrypt.sh << EOF +#!/bin/bash + +if ! [ -x "\$(command -v docker-compose)" ]; then + echo 'Error: docker-compose is not installed.' >&2 + exit 1 +fi + +domains=($custom_domain) +rsa_key_size=4096 +data_path="./data/certbot" +email="" # Adding a valid address is strongly recommended +staging=0 # Set to 1 if you're testing your setup to avoid hitting request limits + +echo "\$data_path" +if [ -d "\$data_path" ]; then + read -p "Existing data found for \$domains. Continue and replace existing certificate? [y/N] " decision + if [ "\$decision" != "Y" ] && [ "\$decision" != "y" ]; then + exit + fi +fi + + +if [ ! -e "\$data_path/conf/options-ssl-nginx.conf" ] || [ ! -e "\$data_path/conf/ssl-dhparams.pem" ]; then + echo "### Downloading recommended TLS parameters ..." + mkdir -p "\$data_path/conf" + curl -s https://raw.githubusercontent.com/certbot/certbot/master/certbot-nginx/certbot_nginx/_internal/tls_configs/options-ssl-nginx.conf > "\$data_path/conf/options-ssl-nginx.conf" + curl -s https://raw.githubusercontent.com/certbot/certbot/master/certbot/certbot/ssl-dhparams.pem > "\$data_path/conf/ssl-dhparams.pem" + echo +fi + +echo "### Creating dummy certificate for \$domains ..." +path="/etc/letsencrypt/live/\$domains" +mkdir -p "\$data_path/conf/live/\$domains" +docker-compose run --rm --entrypoint "\\ + openssl req -x509 -nodes -newkey rsa:1024 -days 1\\ + -keyout '\$path/privkey.pem' \\ + -out '\$path/fullchain.pem' \\ + -subj '/CN=localhost'" certbot +echo + + +echo "### Starting nginx ..." +docker-compose up --force-recreate -d nginx +echo + +echo "### Deleting dummy certificate for \$domains ..." +docker-compose run --rm --entrypoint "\\ + rm -Rf /etc/letsencrypt/live/\$domains && \\ + rm -Rf /etc/letsencrypt/archive/\$domains && \\ + rm -Rf /etc/letsencrypt/renewal/\$domains.conf" certbot +echo + + +echo "### Requesting Let's Encrypt certificate for \$domains ..." +#Join \$domains to -d args +domain_args="" +for domain in "\${domains[@]}"; do + domain_args="\$domain_args -d \$domain" +done + +# Select appropriate email arg +case "\$email" in + "") email_arg="--register-unsafely-without-email" ;; + *) email_arg="--email \$email" ;; +esac + +# Enable staging mode if needed +if [ \$staging != "0" ]; then staging_arg="--staging"; fi + +docker-compose run --rm --entrypoint "\\ + certbot certonly --webroot -w /var/www/certbot \\ + \$staging_arg \\ + \$email_arg \\ + \$domain_args \\ + --rsa-key-size \$rsa_key_size \\ + --agree-tos \\ + --force-renewal" certbot +echo + +echo "### Reloading nginx ..." +docker-compose exec nginx nginx -s reload + + +EOF diff --git a/deploy/template/mongo-init.js.sh b/deploy/template/mongo-init.js.sh new file mode 100644 index 0000000000..f765e9db19 --- /dev/null +++ b/deploy/template/mongo-init.js.sh @@ -0,0 +1,1543 @@ +#!/bin/sh + +if [ -f mongo-init.js ] + then + echo "file docker-compose.yml already exists" + else + touch mongo-init.js +fi + + + +cat > mongo-init.js << EOF +let error = false +print("**** Going to start Mongo seed ****") + +let res = [ + db.createUser( + { + user: "$mongo_root_user", + pwd: "$mongo_root_password", + roles: [{ + role: "readAnyDatabase", + db: "admin" + }, "readWrite"] + } + ), + + db.group.insert({ + "_id" : ObjectId("5df8c225078d501fc3f45361"), + "name" : "Admin", + "displayName" : "Admin", + "organizationId" : "default-org", + "permissions" : [ + "read:groups", + "read:organizations", + "create:users", + "update:users", + "create:groups", + "create:organizations", + "read:users", + "read:pages", + "create:pages", + "update:pages", + "read:layouts", + "create:layouts", + "update:layouts", + "read:properties", + "create:properties", + "update:properties", + "read:actions", + "create:actions", + "update:actions", + "read:resources", + "create:resources", + "update:resources", + "read:plugins", + "create:plugins", + "delete:actions", + "create:collections", + "update:collections", + "delete:collections", + "read:collections", + "create:applications", + "update:applications", + "read:applications", + "read:datasources", + "create:datasources", + "update:datasources", + "read:configs", + "update:configs", + "create:configs", + "delete:applications", + "create:import", + "read:import", + "update:import", + "create:providers", + "read:providers", + "update:providers", + "read:marketplace", + "delete:import", + "delete:pages", + "create:templates", + "update:templates", + "read:templates", + "read:items", + "create:items", + "delete:datasources" + ], + "isDefault" : false, + "deleted" : false, + "_class" : "com.appsmith.server.domains.Group" + }), + + + db.group.insert({ + "_id" : ObjectId("5df8c1fa078d501fc3f44d41"), + "name" : "Member", + "displayName" : "Member", + "organizationId" : "default-org", + "permissions" : [ + "read:groups", + "read:organizations", + "create:users", + "update:users", + "create:groups", + "create:organizations", + "read:users", + "read:pages", + "create:pages", + "update:pages", + "read:layouts", + "create:layouts", + "update:layouts", + "read:properties", + "create:properties", + "update:properties", + "read:actions", + "create:actions", + "update:actions", + "read:resources", + "create:resources", + "update:resources", + "read:plugins", + "create:plugins", + "delete:actions", + "create:collections", + "update:collections", + "delete:collections", + "read:collections", + "create:applications", + "update:applications", + "read:applications", + "read:datasources", + "create:datasources", + "update:datasources", + "read:configs", + "update:configs", + "create:configs", + "delete:applications", + "create:import", + "read:import", + "update:import", + "create:providers", + "read:providers", + "update:providers", + "read:marketplace", + "delete:import", + "delete:pages", + "create:templates", + "update:templates", + "read:templates", + "read:items", + "create:items", + "delete:datasources" + ], + "isDefault" : true, + "deleted" : false, + "_class" : "com.appsmith.server.domains.Group" + }), + + db.group.insert({ + "_id" : ObjectId("5df8c1e0078d501fc3f4491b"), + "name" : "Owner", + "displayName" : "Owner", + "organizationId" : "default-org", + "permissions" : [ + "read:groups", + "read:organizations", + "create:users", + "update:users", + "create:groups", + "create:organizations", + "read:users", + "read:pages", + "create:pages", + "update:pages", + "read:layouts", + "create:layouts", + "update:layouts", + "read:properties", + "create:properties", + "update:properties", + "read:actions", + "create:actions", + "update:actions", + "read:resources", + "create:resources", + "update:resources", + "read:plugins", + "create:plugins", + "delete:actions", + "create:collections", + "update:collections", + "delete:collections", + "read:collections", + "create:applications", + "update:applications", + "read:applications", + "read:datasources", + "create:datasources", + "update:datasources", + "read:configs", + "update:configs", + "create:configs", + "delete:applications", + "create:import", + "read:import", + "update:import", + "create:providers", + "read:providers", + "update:providers", + "read:marketplace", + "delete:import", + "delete:pages", + "create:templates", + "update:templates", + "read:templates", + "read:items", + "create:items", + "delete:datasources" + ], + "isDefault" : false, + "deleted" : false, + "_class" : "com.appsmith.server.domains.Group" + }), + + db.config.insert({ + "config" : { + "CONTAINER_WIDGET" : [ + { + "id" : "5.1", + "sectionName" : "General", + "children" : [ + { + "id" : "5.1.1", + "helpText" : "Use a html color name, HEX, RGB or RGBA value", + "placeholderText" : "#FFFFFF / Gray / rgb(255, 99, 71)", + "propertyName" : "backgroundColor", + "label" : "Background Color", + "validationType" : "HTML_COLOR", + "errorMessage" : "Invalid HTML color name, HEX, RGB or RGBA value", + "expected" : { + "message" : "HTML colors/HEX/RGB/RGBA value", + "type" : "string" + }, + "controlType" : "INPUT_TEXT" + }, + { + "id" : "5.1.2", + "helpText" : "Controls the visibility of the widget", + "propertyName" : "isVisible", + "label" : "Visible", + "validationType" : "BOOLEAN", + "errorMessage" : "Must be a valid boolean value", + "expected" : { + "message" : "Value should evaluate to true or false", + "type" : "Boolean" + }, + "controlType" : "SWITCH", + "isJSConvertible" : true + }, + { + "id" : "5.1.3", + "propertyName" : "shouldScrollContents", + "label" : "Scroll Contents", + "validationType" : "BOOLEAN", + "errorMessage" : "Must be a valid boolean value", + "expected" : { + "message" : "Value should evaluate to true or false", + "type" : "Boolean" + }, + "controlType" : "SWITCH" + } + ] + } + ], + "DATE_PICKER_WIDGET" : [ + { + "sectionName" : "General", + "id" : "6.1", + "children" : [ + { + "id" : "6.1.2", + "propertyName" : "defaultDate", + "label" : "Default Date", + "validationType" : "DATE", + "helpText" : "Sets the default date of the widget. The date is updated if the default date changes", + "errorMessage" : "Must be a valid date", + "controlType" : "DATE_PICKER", + "placeholderText" : "Enter Default Date", + "isJSConvertible" : true + }, + { + "id" : "6.1.3", + "propertyName" : "isRequired", + "label" : "Required", + "helpText" : "Disables a form submit button when this widget is empty", + "validationType" : "BOOLEAN", + "errorMessage" : "Must be a valid boolean value", + "controlType" : "SWITCH" + }, + { + "id" : "6.1.4", + "propertyName" : "isVisible", + "label" : "Visible", + "helpText" : "Controls the visibility of the widget", + "validationType" : "BOOLEAN", + "errorMessage" : "Must be a valid boolean value", + "controlType" : "SWITCH" + }, + { + "id" : "6.1.5", + "propertyName" : "isDisabled", + "label" : "Disabled", + "validationType" : "BOOLEAN", + "helpText" : "Disables input to this widget", + "errorMessage" : "Must be a valid boolean value", + "controlType" : "SWITCH" + } + ] + }, + { + "sectionName" : "Actions", + "id" : "6.2", + "children" : [ + { + "id" : "6.2.1", + "propertyName" : "onDateSelected", + "label" : "onDateSelected", + "controlType" : "ACTION_SELECTOR" + } + ] + } + ], + "TABLE_WIDGET" : [ + { + "id" : "7.1", + "sectionName" : "General", + "children" : [ + { + "id" : "7.1.1", + "helpText" : "Takes in an array of objects to display rows in the table. Bind data from an API using {{}}", + "propertyName" : "tableData", + "label" : "Table Data", + "controlType" : "INPUT_TEXT", + "validationType" : "TABLE_ARRAY", + "errorMessage" : "Requires an array of objects", + "expected" : { + "message" : "An array of objects. Keys are column names", + "type" : "Record[]" + }, + "placeholderText" : "Enter [{ \"col1\": \"val1\" }]", + "inputType" : "ARRAY" + }, + { + "id" : "7.1.2", + "helpText" : "Bind the Table.pageNo property in your API and call it onPageChange", + "validationType" : "BOOLEAN", + "errorMessage" : "Must be a valid boolean value", + "propertyName" : "serverSidePaginationEnabled", + "label" : "Server Side Pagination", + "controlType" : "SWITCH" + }, + { + "id" : "7.1.3", + "helpText" : "Controls the visibility of the widget", + "propertyName" : "isVisible", + "validationType" : "BOOLEAN", + "errorMessage" : "Must be a valid boolean value", + "isJSConvertible" : true, + "label" : "Visible", + "controlType" : "SWITCH", + "expected" : { + "message" : "Value should evaluate to true or false", + "type" : "Boolean" + } + }, + { + "id" : "7.1.4", + "helpText" : "Enable PDF Export", + "propertyName" : "exportPDF", + "label" : "PDF Export", + "controlType" : "SWITCH" + }, + { + "id" : "7.1.5", + "helpText" : "Enable Excel Export", + "propertyName" : "exportExcel", + "label" : "Excel Export", + "controlType" : "SWITCH" + }, + { + "id" : "7.1.6", + "helpText" : "Enable CSV Export", + "propertyName" : "exportCsv", + "label" : "CSV Export", + "controlType" : "SWITCH" + } + ] + }, + { + "id" : "7.2", + "sectionName" : "Actions", + "children" : [ + { + "id" : "7.2.1", + "helpText" : "Adds a button action for every row. Reference the Table.selectedRow property in the action", + "propertyName" : "columnActions", + "label" : "Row Button", + "controlType" : "COLUMN_ACTION_SELECTOR" + }, + { + "id" : "7.2.2", + "helpText" : "Triggers an action when a table row is selected", + "propertyName" : "onRowSelected", + "label" : "onRowSelected", + "controlType" : "ACTION_SELECTOR", + "isJSConvertible" : true + }, + { + "id" : "7.2.3", + "helpText" : "Triggers an action when a table page is changed", + "propertyName" : "onPageChange", + "label" : "onPageChange", + "controlType" : "ACTION_SELECTOR", + "isJSConvertible" : true + } + ] + } + ], + "IMAGE_WIDGET" : [ + { + "id" : "3.1", + "sectionName" : "General", + "children" : [ + { + "id" : "3.1.1", + "helpText" : "Renders the url or Base64 in the widget", + "propertyName" : "image", + "label" : "Image", + "controlType" : "INPUT_TEXT", + "validationType" : "URL_BASE64", + "errorMessage" : "Must be a valid url or base64 string", + "placeholderText" : "Enter URL / Base64" + }, + { + "id" : "3.1.2", + "helpText" : "Renders the url or Base64 when no image is provided", + "propertyName" : "defaultImage", + "label" : "Default Image", + "controlType" : "INPUT_TEXT", + "validationType" : "URL_BASE64", + "errorMessage" : "Must be a valid url or base64 string", + "placeholderText" : "Enter URL / Base64" + }, + { + "id" : "3.1.3", + "helpText" : "Controls the visibility of the widget", + "propertyName" : "isVisible", + "validationType" : "BOOLEAN", + "errorMessage" : "Must be a valid boolean value", + "label" : "Visible", + "controlType" : "SWITCH", + "isJSConvertible" : true + } + ] + } + ], + "RADIO_GROUP_WIDGET" : [ + { + "id" : "10.1", + "sectionName" : "General", + "children" : [ + { + "id" : "10.1.2", + "helpText" : "Displays a list of options for a user to select. Values must be unique", + "validationType" : "KEY_VAL", + "errorMessage" : "Requires an array of objects with label and value fields", + "propertyName" : "options", + "label" : "Options", + "controlType" : "OPTION_INPUT", + "isJSConvertible" : true + }, + { + "id" : "10.1.3", + "helpText" : "Selects a value of the options entered by default", + "propertyName" : "defaultOptionValue", + "label" : "Default Selected Value", + "validationType" : "TEXT", + "errorMessage" : "Must be a valid string", + "placeholderText" : "Enter option value", + "controlType" : "INPUT_TEXT" + }, + { + "id" : "10.1.4", + "helpText" : "Disables a form submit button when this widget is empty", + "propertyName" : "isRequired", + "label" : "Required", + "validationType" : "BOOLEAN", + "errorMessage" : "Must be a valid boolean value", + "controlType" : "SWITCH", + "isJSConvertible" : true + }, + { + "id" : "10.1.5", + "helpText" : "Controls the visibility of the widget", + "propertyName" : "isVisible", + "label" : "Visible", + "validationType" : "BOOLEAN", + "errorMessage" : "Must be a valid boolean value", + "controlType" : "SWITCH", + "isJSConvertible" : true + } + ] + }, + { + "id" : "10.2", + "sectionName" : "Actions", + "children" : [ + { + "id" : "10.2.1", + "helpText" : "Triggers an action when a user changes the selected option", + "propertyName" : "onSelectionChange", + "label" : "onSelectionChange", + "controlType" : "ACTION_SELECTOR", + "isJSConvertible" : true + } + ] + } + ], + "TABS_WIDGET" : [ + { + "id" : "16.1", + "sectionName" : "General", + "children" : [ + { + "id" : "16.1.1", + "helpText" : "Takes an array of tab names to render tabs", + "propertyName" : "tabs", + "isJSConvertible" : true, + "label" : "Tabs", + "controlType" : "TABS_INPUT" + }, + { + "id" : "16.1.2", + "propertyName" : "selectedTab", + "helpText" : "Selects a tab name specified by default", + "placeholderText" : "Enter tab name", + "label" : "Default Tab", + "validationType" : "TEXT", + "errorMessage" : "Must be a valid string", + "controlType" : "INPUT_TEXT" + }, + { + "id" : "16.1.5", + "propertyName" : "shouldScrollContents", + "label" : "Scroll Contents", + "validationType" : "BOOLEAN", + "errorMessage" : "Must be a valid boolean value", + "controlType" : "SWITCH" + }, + { + "id" : "16.1.4", + "propertyName" : "isVisible", + "label" : "Visible", + "helpText" : "Controls the visibility of the widget", + "validationType" : "BOOLEAN", + "errorMessage" : "Must be a valid boolean value", + "controlType" : "SWITCH", + "isJSConvertible" : true + } + ] + } + ], + "CHART_WIDGET" : [ + { + "id" : "13.1", + "sectionName" : "General", + "children" : [ + { + "id" : "13.1.1", + "helpText" : "Adds a title to the chart", + "placeholderText" : "Enter title", + "propertyName" : "chartName", + "label" : "Title", + "controlType" : "INPUT_TEXT" + }, + { + "id" : "13.1.2", + "helpText" : "Changes the visualisation of the chart data", + "propertyName" : "chartType", + "label" : "Chart Type", + "controlType" : "DROP_DOWN", + "options" : [ + { + "label" : "Line Chart", + "value" : "LINE_CHART" + }, + { + "label" : "Bar Chart", + "value" : "BAR_CHART" + }, + { + "label" : "Pie Chart", + "value" : "PIE_CHART" + }, + { + "label" : "Column Chart", + "value" : "COLUMN_CHART" + }, + { + "label" : "Area Chart", + "value" : "AREA_CHART" + } + ], + "isJSConvertible" : true + }, + { + "id" : "13.1.6", + "helpText" : "Populates the chart with the data", + "propertyName" : "singleChartData", + "placeholderText" : "Enter [{ \"x\": \"val\", \"y\": \"val\" }]", + "validationType" : "CHART_ARRAY", + "errorMessage" : "Must be an array of x,y", + "label" : "Chart Data", + "controlType" : "INPUT_TEXT" + }, + { + "id" : "13.1.3", + "helpText" : "Specifies the label of the x-axis", + "propertyName" : "xAxisName", + "placeholderText" : "Enter label text", + "label" : "x-axis Label", + "validationType" : "TEXT", + "errorMessage" : "Must be a valid string", + "controlType" : "INPUT_TEXT" + }, + { + "id" : "13.1.5", + "helpText" : "Specifies the label of the y-axis", + "propertyName" : "yAxisName", + "placeholderText" : "Enter label text", + "label" : "y-axis Label", + "controlType" : "INPUT_TEXT" + }, + { + "id" : "13.1.4", + "helpText" : "Enables scrolling inside the chart", + "propertyName" : "allowHorizontalScroll", + "label" : "Allow horizontal scroll", + "controlType" : "SWITCH" + }, + { + "id" : "13.1.7", + "propertyName" : "isVisible", + "label" : "Visible", + "helpText" : "Controls the visibility of the widget", + "validationType" : "BOOLEAN", + "errorMessage" : "Must be a valid boolean value", + "controlType" : "SWITCH", + "isJSConvertible" : true + } + ] + } + ], + "MODAL_WIDGET" : [ + { + "sectionName" : "General", + "id" : "18.1", + "children" : [ + { + "id" : "18.1.1", + "propertyName" : "canOutsideClickClose", + "label" : "Quick Dismiss", + "helpText" : "Allows dismissing the modal when user taps outside", + "validationType" : "BOOLEAN", + "errorMessage" : "Must be a valid boolean value", + "controlType" : "SWITCH" + }, + { + "id" : "18.1.2", + "propertyName" : "size", + "label" : "Modal Type", + "controlType" : "DROP_DOWN", + "options" : [ + { + "label" : "Form Modal", + "value" : "MODAL_LARGE" + }, + { + "label" : "Alert Modal", + "value" : "MODAL_SMALL" + } + ] + }, + { + "id" : "18.1.3", + "propertyName" : "shouldScrollContents", + "label" : "Scroll Contents", + "validationType" : "BOOLEAN", + "errorMessage" : "Must be a valid boolean value", + "controlType" : "SWITCH" + } + ] + } + ], + "INPUT_WIDGET" : [ + { + "id" : "4.1", + "sectionName" : "General", + "children" : [ + { + "id" : "4.1.2", + "helpText" : "Changes the type of data captured in the input", + "propertyName" : "inputType", + "label" : "Data Type", + "controlType" : "DROP_DOWN", + "options" : [ + { + "label" : "Text", + "value" : "TEXT" + }, + { + "label" : "Number", + "value" : "NUMBER" + }, + { + "label" : "Password", + "value" : "PASSWORD" + }, + { + "label" : "Phone Number", + "value" : "PHONE_NUMBER" + }, + { + "label" : "Email", + "value" : "EMAIL" + } + ] + }, + { + "id" : "4.1.3", + "helpText" : "Sets a placeholder text for the input", + "propertyName" : "placeholderText", + "label" : "Placeholder", + "validationType" : "TEXT", + "errorMessage" : "Must be a valid string", + "controlType" : "INPUT_TEXT", + "placeholderText" : "Enter placeholder text" + }, + { + "id" : "4.1.4", + "helpText" : "Sets the default text of the widget. The text is updated if the default text changes", + "propertyName" : "defaultText", + "label" : "Default Input", + "validationType" : "TEXT", + "errorMessage" : "Must be a valid string", + "controlType" : "INPUT_TEXT", + "placeholderText" : "Enter default text" + }, + { + "id" : "4.1.5", + "helpText" : "Adds a validation to the input which displays an error on failure", + "propertyName" : "regex", + "label" : "Regex", + "validationType" : "REGEX", + "errorMessage" : "Must be a valid regex string", + "controlType" : "INPUT_TEXT", + "placeholderText" : "^\\w+@[a-zA-Z_]+?\\.[a-zA-Z]{2,3}$", + "inputType" : "TEXT" + }, + { + "id" : "4.1.6", + "helpText" : "Displays the error message if the regex validation fails", + "propertyName" : "errorMessage", + "label" : "Error Message", + "controlType" : "INPUT_TEXT", + "validationType" : "TEXT", + "errorMessage" : "Must be a valid string", + "placeholderText" : "Enter error message", + "inputType" : "TEXT" + }, + { + "id" : "4.1.7", + "propertyName" : "isRequired", + "label" : "Required", + "validationType" : "BOOLEAN", + "errorMessage" : "Must be a valid boolean value", + "helpText" : "Disables a form submit button when this widget is empty", + "controlType" : "SWITCH", + "isJSConvertible" : true + }, + { + "id" : "4.1.8", + "helpText" : "Controls the visibility of the widget", + "propertyName" : "isVisible", + "label" : "Visible", + "validationType" : "BOOLEAN", + "errorMessage" : "Must be a valid boolean value", + "controlType" : "SWITCH", + "isJSConvertible" : true + }, + { + "id" : "4.1.9", + "helpText" : "Disables input to this widget", + "propertyName" : "isDisabled", + "label" : "Disabled", + "validationType" : "BOOLEAN", + "errorMessage" : "Must be a valid boolean value", + "controlType" : "SWITCH", + "isJSConvertible" : true + } + ] + }, + { + "id" : "4.2.1", + "sectionName" : "Actions", + "children" : [ + { + "id" : "5.11.2", + "helpText" : "Triggers an action when the text is changed", + "propertyName" : "onTextChanged", + "label" : "onTextChanged", + "controlType" : "ACTION_SELECTOR", + "isJSConvertible" : true + } + ] + } + ], + "DROP_DOWN_WIDGET" : [ + { + "id" : "8.1", + "sectionName" : "General", + "children" : [ + { + "id" : "8.1.2", + "helpText" : "Allows users to select either a single option or multiple options", + "propertyName" : "selectionType", + "label" : "Selection Type", + "controlType" : "DROP_DOWN", + "options" : [ + { + "label" : "Single Select", + "value" : "SINGLE_SELECT" + }, + { + "label" : "Multi Select", + "value" : "MULTI_SELECT" + } + ] + }, + { + "id" : "8.1.3", + "helpText" : "Allows users to select either a single option or multiple options. Values must be unique", + "propertyName" : "options", + "label" : "Options", + "validationType" : "KEY_VAL", + "errorMessage" : "Requires an array of objects with label and value fields", + "controlType" : "INPUT_TEXT", + "placeholderText" : "Enter [{label: \"label1\", value: \"value2\"}]" + }, + { + "id" : "8.1.4", + "helpText" : "Selects the option with value by default", + "propertyName" : "defaultOptionValue", + "label" : "Default Option", + "validationType" : "TEXT", + "errorMessage" : "Must be a valid string", + "controlType" : "INPUT_TEXT", + "placeholderText" : "Enter option value" + }, + { + "id" : "8.1.5", + "propertyName" : "isRequired", + "label" : "Required", + "validationType" : "BOOLEAN", + "errorMessage" : "Must be a valid boolean value", + "helpText" : "Disables a form submit button when this widget is empty", + "controlType" : "SWITCH", + "isJSConvertible" : true + }, + { + "id" : "8.1.6", + "helpText" : "Controls the visibility of the widget", + "propertyName" : "isVisible", + "validationType" : "BOOLEAN", + "errorMessage" : "Must be a valid boolean value", + "label" : "Visible", + "controlType" : "SWITCH", + "isJSConvertible" : true + } + ] + }, + { + "id" : "8.2", + "sectionName" : "Actions", + "children" : [ + { + "id" : "8.2.1", + "helpText" : "Triggers an action when a user selects an option", + "propertyName" : "onOptionChange", + "label" : "onOptionChange", + "controlType" : "ACTION_SELECTOR", + "isJSConvertible" : true + } + ] + } + ], + "FORM_BUTTON_WIDGET" : [ + { + "id" : "15.1", + "sectionName" : "General", + "children" : [ + { + "id" : "15.1.1", + "propertyName" : "text", + "label" : "Label", + "validationType" : "TEXT", + "errorMessage" : "Must be a valid string", + "helpText" : "Sets the label of the button", + "controlType" : "INPUT_TEXT", + "placeholderText" : "Enter label text" + }, + { + "id" : "15.1.2", + "propertyName" : "buttonStyle", + "label" : "Button Style", + "helpText" : "Changes the style of the button", + "controlType" : "DROP_DOWN", + "options" : [ + { + "label" : "Primary Button", + "value" : "PRIMARY_BUTTON" + }, + { + "label" : "Secondary Button", + "value" : "SECONDARY_BUTTON" + }, + { + "label" : "Danger Button", + "value" : "DANGER_BUTTON" + } + ] + }, + { + "id" : "15.1.3", + "helpText" : "Disables the button when the parent form has a required widget that is not filled", + "propertyName" : "disabledWhenInvalid", + "label" : "Disabled Invalid Forms", + "validationType" : "BOOLEAN", + "errorMessage" : "Must be a valid boolean value", + "controlType" : "SWITCH" + }, + { + "id" : "15.1.4", + "helpText" : "Resets the fields within the parent form when the click action succeeds", + "propertyName" : "resetFormOnClick", + "label" : "Reset Form on Success", + "validationType" : "BOOLEAN", + "errorMessage" : "Must be a valid boolean value", + "controlType" : "SWITCH", + "isJSConvertible" : true + }, + { + "id" : "15.1.5", + "propertyName" : "isVisible", + "label" : "Visible", + "helpText" : "Controls the visibility of the widget", + "controlType" : "SWITCH", + "validationType" : "BOOLEAN", + "errorMessage" : "Must be a valid boolean value", + "isJSConvertible" : true + } + ] + }, + { + "id" : "15.2", + "sectionName" : "Actions", + "children" : [ + { + "id" : "15.2.1", + "helpText" : "Triggers an action when the button is clicked", + "propertyName" : "onClick", + "label" : "onClick", + "controlType" : "ACTION_SELECTOR", + "isJSConvertible" : true + } + ] + } + ], + "MAP_WIDGET" : [ + { + "sectionName" : "General", + "id" : "25.1", + "children" : [ + { + "id" : "25.1.1", + "propertyName" : "mapCenter", + "label" : "Initial location", + "isJSConvertible" : true, + "controlType" : "LOCATION_SEARCH" + }, + { + "id" : "25.1.4", + "propertyName" : "defaultMarkers", + "label" : "Default markers", + "controlType" : "INPUT_TEXT", + "inputType" : "ARRAY", + "helpText" : "Sets the default markers on the map", + "validationType" : "MARKER_ARRAY", + "errorMessage" : "Must be an array of lat, long", + "placeholderText" : "Enter [{ \"lat\": \"val1\", \"long\": \"val2\" }]" + }, + { + "id" : "25.1.2", + "propertyName" : "enableSearch", + "label" : "Enable search location", + "helpText" : "Enables locaton search", + "validationType" : "BOOLEAN", + "errorMessage" : "Must be a valid boolean value", + "controlType" : "SWITCH" + }, + { + "id" : "25.1.3", + "propertyName" : "enablePickLocation", + "label" : "Enable pick location", + "helpText" : "Allows a user to pick their location", + "validationType" : "BOOLEAN", + "errorMessage" : "Must be a valid boolean value", + "controlType" : "SWITCH" + }, + { + "id" : "25.1.5", + "propertyName" : "enableCreateMarker", + "label" : "Create new marker", + "helpText" : "Allows users to mark locations on the map", + "validationType" : "BOOLEAN", + "errorMessage" : "Must be a valid boolean value", + "controlType" : "SWITCH" + }, + { + "id" : "25.1.6", + "propertyName" : "zoomLevel", + "label" : "Zoom Level", + "controlType" : "STEP", + "helpText" : "Changes the default zoom of the map", + "stepType" : "ZOOM_PERCENTAGE" + }, + { + "id" : "25.1.7", + "propertyName" : "isVisible", + "label" : "Visible", + "helpText" : "Controls the visibility of the widget", + "controlType" : "SWITCH", + "validationType" : "BOOLEAN", + "errorMessage" : "Must be a valid boolean value", + "isJSConvertible" : true + } + ] + }, + { + "id" : "27", + "sectionName" : "Actions", + "children" : [ + { + "id" : "27.1", + "propertyName" : "onMarkerClick", + "label" : "onMarkerClick", + "controlType" : "ACTION_SELECTOR", + "isJSConvertible" : true + }, + { + "id" : "27.2", + "propertyName" : "onCreateMarker", + "label" : "onCreateMarker", + "controlType" : "ACTION_SELECTOR", + "isJSConvertible" : true + } + ] + } + ], + "BUTTON_WIDGET" : [ + { + "id" : "1.1", + "sectionName" : "General", + "children" : [ + { + "id" : "1.1.1", + "propertyName" : "text", + "label" : "Label", + "helpText" : "Sets the label of the button", + "controlType" : "INPUT_TEXT", + "validationType" : "TEXT", + "errorMessage" : "Must be a valid string", + "placeholderText" : "Enter label text" + }, + { + "id" : "1.1.2", + "propertyName" : "buttonStyle", + "label" : "Button Style", + "controlType" : "DROP_DOWN", + "helpText" : "Changes the style of the button", + "options" : [ + { + "label" : "Primary Button", + "value" : "PRIMARY_BUTTON" + }, + { + "label" : "Secondary Button", + "value" : "SECONDARY_BUTTON" + }, + { + "label" : "Danger Button", + "value" : "DANGER_BUTTON" + } + ] + }, + { + "id" : "1.1.3", + "propertyName" : "isDisabled", + "label" : "Disabled", + "controlType" : "SWITCH", + "helpText" : "Disables clicks to this widget", + "validationType" : "BOOLEAN", + "errorMessage" : "Must be a valid boolean value", + "isJSConvertible" : true + }, + { + "id" : "1.1.4", + "propertyName" : "isVisible", + "label" : "Visible", + "helpText" : "Controls the visibility of the widget", + "controlType" : "SWITCH", + "validationType" : "BOOLEAN", + "errorMessage" : "Must be a valid boolean value", + "isJSConvertible" : true + } + ] + }, + { + "id" : "1.2.1", + "sectionName" : "Actions", + "children" : [ + { + "id" : "2.1", + "helpText" : "Triggers an action when the button is clicked", + "propertyName" : "onClick", + "label" : "onClick", + "controlType" : "ACTION_SELECTOR", + "isJSConvertible" : true + } + ] + } + ], + "RICH_TEXT_EDITOR_WIDGET" : [ + { + "id" : "12.1", + "sectionName" : "General", + "children" : [ + { + "id" : "12.1.1", + "propertyName" : "defaultText", + "helpText" : "Sets the default text of the widget. The text is updated if the default text changes", + "label" : "Default text", + "controlType" : "INPUT_TEXT", + "validationType" : "TEXT", + "errorMessage" : "Must be a valid string", + "placeholderText" : "Enter HTML" + }, + { + "id" : "12.1.2", + "propertyName" : "isVisible", + "label" : "Visible", + "helpText" : "Controls the visibility of the widget", + "controlType" : "SWITCH", + "validationType" : "BOOLEAN", + "errorMessage" : "Must be a valid boolean value", + "isJSConvertible" : true + }, + { + "id" : "12.1.3", + "propertyName" : "isDisabled", + "label" : "Disable", + "helpText" : "Disables input to this widget", + "controlType" : "SWITCH", + "validationType" : "BOOLEAN", + "errorMessage" : "Must be a valid boolean value", + "isJSConvertible" : true + } + ] + }, + { + "id" : "12.2", + "sectionName" : "Actions", + "children" : [ + { + "id" : "12.2.1", + "helpText" : "Triggers an action when the text is changed", + "propertyName" : "onTextChange", + "label" : "onTextChange", + "controlType" : "ACTION_SELECTOR", + "isJSConvertible" : true + } + ] + } + ], + "FILE_PICKER_WIDGET" : [ + { + "id" : "11.1", + "sectionName" : "General", + "children" : [ + { + "id" : "11.1.1", + "propertyName" : "label", + "label" : "Label", + "controlType" : "INPUT_TEXT", + "helpText" : "Sets the label of the button", + "placeholderText" : "Enter label text", + "validationType" : "TEXT", + "errorMessage" : "Must be a valid string", + "inputType" : "TEXT" + }, + { + "id" : "11.1.2", + "propertyName" : "maxNumFiles", + "label" : "Max No. files", + "helpText" : "Sets the maximum number of files that can be uploaded at once", + "controlType" : "INPUT_TEXT", + "placeholderText" : "Enter no. of files", + "validationType" : "POS_INT", + "errorMessage" : "Must be a valid number", + "inputType" : "INTEGER" + }, + { + "id" : "11.1.3", + "propertyName" : "maxFileSize", + "helpText" : "Sets the maximum size of each file that can be uploaded", + "label" : "Max file size", + "controlType" : "INPUT_TEXT", + "validationType" : "POS_REAL", + "errorMessage" : "Must be a valid number", + "placeholderText" : "File size in mb", + "inputType" : "INTEGER" + }, + { + "id" : "11.1.4", + "propertyName" : "allowedFileTypes", + "helpText" : "Restricts the type of files which can be uploaded", + "label" : "Allowed File Types", + "controlType" : "MULTI_SELECT", + "placeholderText" : "Select file types", + "options" : [ + { + "label" : "Any File", + "value" : "*" + }, + { + "label" : "Images", + "value" : "image/*" + }, + { + "label" : "Videos", + "value" : "video/*" + }, + { + "label" : "Audio", + "value" : "audio/*" + }, + { + "label" : "Text", + "value" : "text/*" + }, + { + "label" : "MS Word", + "value" : ".doc" + }, + { + "label" : "JPEG", + "value" : "image/jpeg" + }, + { + "label" : "PNG", + "value" : ".png" + } + ], + "isJSConvertible" : true + }, + { + "id" : "11.1.5", + "propertyName" : "isRequired", + "label" : "Required", + "controlType" : "SWITCH", + "helpText" : "Disables a form submit button when this widget is empty", + "validationType" : "BOOLEAN", + "errorMessage" : "Must be a valid boolean value", + "isJSConvertible" : true + }, + { + "id" : "11.1.6", + "propertyName" : "isVisible", + "label" : "Visible", + "helpText" : "Controls the visibility of the widget", + "controlType" : "SWITCH", + "validationType" : "BOOLEAN", + "errorMessage" : "Must be a valid boolean value", + "isJSConvertible" : true + }, + { + "id" : "11.1.7", + "propertyName" : "uploadedFileUrls", + "helpText" : "Stores the url of the uploaded file so that it can be referenced in an action later", + "label" : "Uploaded File URLs", + "controlType" : "INPUT_TEXT", + "placeholderText" : "Enter [ \"url1\", \"url2\" ]", + "validationType" : "STR_ARR", + "errorMessage" : "Must be a valid array of URLs", + "inputType" : "TEXT" + } + ] + }, + { + "id" : "11.2", + "sectionName" : "Actions", + "children" : [ + { + "id" : "11.2.1", + "helpText" : "Triggers an action when the user selects a file. Upload files to a CDN here and store their urls in uploadedFileUrls", + "propertyName" : "onFilesSelected", + "label" : "onFilesSelected", + "controlType" : "ACTION_SELECTOR", + "isJSConvertible" : true + } + ] + } + ], + "CHECKBOX_WIDGET" : [ + { + "id" : "9.1", + "sectionName" : "General", + "children" : [ + { + "id" : "9.1.1", + "propertyName" : "label", + "label" : "Label", + "controlType" : "INPUT_TEXT", + "helpText" : "Displays a label next to the widget", + "validationType" : "TEXT", + "errorMessage" : "Must be a valid string", + "placeholderText" : "Enter label text" + }, + { + "id" : "9.1.2", + "propertyName" : "defaultCheckedState", + "label" : "Default Selected", + "helpText" : "Checks / un-checks the checkbox by default. Changes to the default selection update the widget state", + "controlType" : "SWITCH", + "validationType" : "BOOLEAN", + "errorMessage" : "Must be a valid boolean value", + "isJSConvertible" : true + }, + { + "id" : "9.1.3", + "propertyName" : "isRequired", + "label" : "Required", + "helpText" : "Disables a form submit button when this widget is empty", + "controlType" : "SWITCH", + "validationType" : "BOOLEAN", + "errorMessage" : "Must be a valid boolean value", + "isJSConvertible" : true + }, + { + "id" : "9.1.4", + "propertyName" : "isDisabled", + "label" : "Disabled", + "controlType" : "SWITCH", + "helpText" : "Disables input to this widget", + "validationType" : "BOOLEAN", + "errorMessage" : "Must be a valid boolean value", + "isJSConvertible" : true + }, + { + "id" : "9.1.5", + "propertyName" : "isVisible", + "label" : "Visible", + "helpText" : "Controls the visibility of the widget", + "controlType" : "SWITCH", + "validationType" : "BOOLEAN", + "errorMessage" : "Must be a valid boolean value", + "isJSConvertible" : true + } + ] + }, + { + "id" : "9.2", + "sectionName" : "Actions", + "children" : [ + { + "id" : "9.2.1", + "helpText" : "Triggers an action when the check state is changed", + "propertyName" : "onCheckChange", + "label" : "onCheckChange", + "controlType" : "ACTION_SELECTOR", + "isJSConvertible" : true + } + ] + } + ], + "FORM_WIDGET" : [ + { + "id" : "14.1", + "sectionName" : "General", + "children" : [ + { + "id" : "14.1.1", + "propertyName" : "backgroundColor", + "label" : "Background Color", + "helpText" : "Use a html color name, HEX, RGB or RGBA value", + "placeholderText" : "#FFFFFF / Gray / rgb(255, 99, 71)", + "validationType" : "HTML_COLOR", + "errorMessage" : "Invalid HTML color name, HEX, RGB or RGBA value", + "controlType" : "INPUT_TEXT" + }, + { + "id" : "14.1.2", + "helpText" : "Controls the visibility of the widget", + "propertyName" : "isVisible", + "label" : "Visible", + "controlType" : "SWITCH", + "validationType" : "BOOLEAN", + "errorMessage" : "Must be a valid boolean value", + "isJSConvertible" : true + }, + { + "id" : "14.1.3", + "propertyName" : "shouldScrollContents", + "label" : "Scroll Contents", + "validationType" : "BOOLEAN", + "errorMessage" : "Must be a valid boolean value", + "controlType" : "SWITCH" + } + ] + } + ], + "TEXT_WIDGET" : [ + { + "id" : "2.1", + "sectionName" : "General", + "children" : [ + { + "id" : "2.1.1", + "propertyName" : "text", + "helpText" : "Sets the text of the widget", + "label" : "Text", + "controlType" : "INPUT_TEXT", + "validationType" : "TEXT", + "errorMessage" : "Must be a valid string", + "placeholderText" : "Enter text", + "expected" : { + "message" : "Text to be displayed", + "type" : "string" + } + }, + { + "id" : "2.1.3", + "propertyName" : "textAlign", + "helpText" : "Sets the alignments of the text", + "label" : "Text Align", + "controlType" : "DROP_DOWN", + "options" : [ + { + "label" : "Left", + "value" : "LEFT" + }, + { + "label" : "Center", + "value" : "CENTER" + }, + { + "label" : "Right", + "value" : "RIGHT" + } + ] + }, + { + "id" : "2.1.2", + "propertyName" : "textStyle", + "helpText" : "Sets the font and style of the text", + "label" : "Text Style", + "controlType" : "DROP_DOWN", + "options" : [ + { + "label" : "Heading", + "value" : "HEADING" + }, + { + "label" : "Label", + "value" : "LABEL" + }, + { + "label" : "Body", + "value" : "BODY" + } + ] + }, + { + "id" : "2.1.3", + "propertyName" : "shouldScroll", + "label" : "Enable Scroll", + "helpText" : "Allows scrolling text instead of truncation", + "validationType" : "BOOLEAN", + "errorMessage" : "Must be a valid boolean value", + "controlType" : "SWITCH" + }, + { + "id" : "2.1.4", + "propertyName" : "isVisible", + "helpText" : "Controls the visibility of the widget", + "label" : "Visible", + "controlType" : "SWITCH", + "validationType" : "BOOLEAN", + "errorMessage" : "Must be a valid boolean value", + "isJSConvertible" : true + } + ] + } + ] + }, + "name" : "propertyPane", + "updatedAt" : ISODate("2020-06-02T12:29:11.874Z"), + "deleted" : false, + "_class" : "com.appsmith.server.domains.Config" + }) +] + +printjson(res) + +if (error) { + print('Error occurred while inserting the records') +} + + + +EOF diff --git a/deploy/template/nginx_app.conf.sh b/deploy/template/nginx_app.conf.sh new file mode 100644 index 0000000000..f71af0f66e --- /dev/null +++ b/deploy/template/nginx_app.conf.sh @@ -0,0 +1,84 @@ +#!/bin/sh + +if [ -f nginx_app.conf ] + then + echo "file nginx_app.conf already exists" + else + touch nginx_app.conf +fi + + + +cat > nginx_app.conf << EOF +server { + listen 80; +$NGINX_SSL_CMNT server_name $custom_domain ; + client_max_body_size 10m; + + gzip on; + + root /var/www/appsmith; + index index.html index.htm; + + #location / { + # return 301 https://\$host\$request_uri; + #} + + location /.well-known/acme-challenge/ { + root /var/www/certbot; + } + + proxy_set_header X-Forwarded-Proto \$scheme; + proxy_set_header X-Forwarded-Host \$host; + + location / { + try_files \$uri /index.html =404; + } + + location /f { + proxy_pass https://cdn.optimizely.com/; + } + + location /api { + proxy_pass http://appsmith-internal-server:8080; + } + + location /oauth2 { + proxy_pass http://appsmith-internal-server:8080; + } +} + +$NGINX_SSL_CMNT server { +$NGINX_SSL_CMNT listen 443 ssl; +$NGINX_SSL_CMNT server_name $custom_domain; +$NGINX_SSL_CMNT +$NGINX_SSL_CMNT ssl_certificate /etc/letsencrypt/live/$custom_domain/fullchain.pem; +$NGINX_SSL_CMNT ssl_certificate_key /etc/letsencrypt/live/$custom_domain/privkey.pem; +$NGINX_SSL_CMNT +$NGINX_SSL_CMNT include /etc/letsencrypt/options-ssl-nginx.conf; +$NGINX_SSL_CMNT ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; +$NGINX_SSL_CMNT +$NGINX_SSL_CMNT proxy_set_header X-Forwarded-Proto \$scheme; +$NGINX_SSL_CMNT proxy_set_header X-Forwarded-Host \$host; +$NGINX_SSL_CMNT +$NGINX_SSL_CMNT root /var/www/appsmith; +$NGINX_SSL_CMNT index index.html index.htm; +$NGINX_SSL_CMNT +$NGINX_SSL_CMNT location / { +$NGINX_SSL_CMNT try_files \$uri /index.html =404; +$NGINX_SSL_CMNT } +$NGINX_SSL_CMNT +$NGINX_SSL_CMNT location /f { +$NGINX_SSL_CMNT proxy_pass https://cdn.optimizely.com/; +$NGINX_SSL_CMNT } +$NGINX_SSL_CMNT +$NGINX_SSL_CMNT location /api { +$NGINX_SSL_CMNT proxy_pass http://appsmith-internal-server:8080; +$NGINX_SSL_CMNT } +$NGINX_SSL_CMNT +$NGINX_SSL_CMNT location /oauth2 { +$NGINX_SSL_CMNT proxy_pass http://appsmith-internal-server:8080; +$NGINX_SSL_CMNT } +$NGINX_SSL_CMNT +$NGINX_SSL_CMNT } +EOF