From dbc179ceadbc0a63969b8c62627e2b38cb18daec Mon Sep 17 00:00:00 2001 From: Abhinav Jha Date: Thu, 13 Aug 2020 10:16:06 +0530 Subject: [PATCH 01/14] Add sentry release and environment configurations (#277) * Add sentry release and environment configurations * Fixing nginx config issue Co-authored-by: Satbir Singh --- .../templates/nginx-linux.conf.template | 4 ++ .../docker/templates/nginx-mac.conf.template | 4 ++ app/client/public/index.html | 6 ++- app/client/src/configs/index.ts | 39 +++++++++++++++++-- app/client/src/configs/types.ts | 4 +- app/client/src/utils/AppsmithUtils.tsx | 2 +- 6 files changed, 52 insertions(+), 7 deletions(-) diff --git a/app/client/docker/templates/nginx-linux.conf.template b/app/client/docker/templates/nginx-linux.conf.template index ad70d138c3..7142c4355e 100644 --- a/app/client/docker/templates/nginx-linux.conf.template +++ b/app/client/docker/templates/nginx-linux.conf.template @@ -31,6 +31,8 @@ server { sub_filter __APPSMITH_CLIENT_LOG_LEVEL__ '${APPSMITH_CLIENT_LOG_LEVEL}'; sub_filter __APPSMITH_GOOGLE_MAPS_API_KEY__ '${APPSMITH_GOOGLE_MAPS_API_KEY}'; sub_filter __APPSMITH_TNC_PP__ '${APPSMITH_TNC_PP}'; + sub_filter __APPSMITH_SENTRY_RELEASE__ '${APPSMITH_SENTRY_RELEASE}'; + sub_filter __APPSMITH_SENTRY_ENVIRONMENT__ '${APPSMITH_SENTRY_ENVIRONMENT}'; } location /f { @@ -93,6 +95,8 @@ server { sub_filter __APPSMITH_CLIENT_LOG_LEVEL__ '${APPSMITH_CLIENT_LOG_LEVEL}'; sub_filter __APPSMITH_GOOGLE_MAPS_API_KEY__ '${APPSMITH_GOOGLE_MAPS_API_KEY}'; sub_filter __APPSMITH_TNC_PP__ '${APPSMITH_TNC_PP}'; + sub_filter __APPSMITH_SENTRY_RELEASE__ '${APPSMITH_SENTRY_RELEASE}'; + sub_filter __APPSMITH_SENTRY_ENVIRONMENT__ '${APPSMITH_SENTRY_ENVIRONMENT}'; } location /f { diff --git a/app/client/docker/templates/nginx-mac.conf.template b/app/client/docker/templates/nginx-mac.conf.template index bbef205cd5..39ec75fd7b 100644 --- a/app/client/docker/templates/nginx-mac.conf.template +++ b/app/client/docker/templates/nginx-mac.conf.template @@ -31,6 +31,8 @@ server { sub_filter __APPSMITH_CLIENT_LOG_LEVEL__ '${APPSMITH_CLIENT_LOG_LEVEL}'; sub_filter __APPSMITH_GOOGLE_MAPS_API_KEY__ '${APPSMITH_GOOGLE_MAPS_API_KEY}'; sub_filter __APPSMITH_TNC_PP__ '${APPSMITH_TNC_PP}'; + sub_filter __APPSMITH_SENTRY_RELEASE__ '${APPSMITH_SENTRY_RELEASE}'; + sub_filter __APPSMITH_SENTRY_ENVIRONMENT__ '${APPSMITH_SENTRY_ENVIRONMENT}'; } location /f { @@ -94,6 +96,8 @@ server { sub_filter __APPSMITH_CLIENT_LOG_LEVEL__ '${APPSMITH_CLIENT_LOG_LEVEL}'; sub_filter __APPSMITH_GOOGLE_MAPS_API_KEY__ '${APPSMITH_GOOGLE_MAPS_API_KEY}'; sub_filter __APPSMITH_TNC_PP__ '${APPSMITH_TNC_PP}'; + sub_filter __APPSMITH_SENTRY_RELEASE__ '${APPSMITH_SENTRY_RELEASE}'; + sub_filter __APPSMITH_SENTRY_ENVIRONMENT__ '${APPSMITH_SENTRY_ENVIRONMENT}'; } diff --git a/app/client/public/index.html b/app/client/public/index.html index c24a1fd079..1df3d5fcc9 100755 --- a/app/client/public/index.html +++ b/app/client/public/index.html @@ -53,7 +53,11 @@ const CONFIG_LOG_LEVEL_INDEX = LOG_LEVELS.indexOf(parseConfig("__APPSMITH_CLIENT_LOG_LEVEL__")); window.SENTRY_CONFIG = parseConfig("__APPSMITH_SENTRY_DSN__"); window.APPSMITH_FEATURE_CONFIGS = { - sentry: parseConfig("__APPSMITH_SENTRY_DSN__"), + sentry: { + dsn: parseConfig("__APPSMITH_SENTRY_DSN__"), + release: parseConfig("__APPSMITH_SENTRY_RELEASE__"), + environment: parseConfig("__APPSMITH_SENTRY_ENVIRONMENT__"), + }, hotjar: { id: parseConfig("__APPSMITH_HOTJAR_HJID__"), sv: parseConfig("__APPSMITH_HOTJAR_HJSV__"), diff --git a/app/client/src/configs/index.ts b/app/client/src/configs/index.ts index 1ad9d0ba7a..24ba7f7a3a 100644 --- a/app/client/src/configs/index.ts +++ b/app/client/src/configs/index.ts @@ -1,6 +1,10 @@ import { AppsmithUIConfigs, FeatureFlagConfig } from "./types"; type INJECTED_CONFIGS = { - sentry: string; + sentry: { + dsn: string; + release: string; + environment: string; + }; hotjar: { id: string; sv: string; @@ -27,9 +31,19 @@ declare global { } } +const capitalizeText = (text: string) => { + const rest = text.slice(1); + const first = text[0].toUpperCase(); + return `${first}${rest}`; +}; + const getConfigsFromEnvVars = (): INJECTED_CONFIGS => { return { - sentry: process.env.REACT_APP_SENTRY_DSN || "", + sentry: { + dsn: process.env.REACT_APP_SENTRY_DSN || "", + release: process.env.REACT_APP_SENTRY_RELEASE || "", + environment: capitalizeText(process.env.NODE_ENV), + }, hotjar: { id: process.env.REACT_APP_HOTJAR_HJID || "", sv: process.env.REACT_APP_HOTJAR_HJSV || "", @@ -92,7 +106,19 @@ export const getAppsmithConfigs = (): AppsmithUIConfigs => { return; }; - const sentry = getConfig(ENV_CONFIG.sentry, APPSMITH_FEATURE_CONFIGS.sentry); + // const sentry = getConfig(ENV_CONFIG.sentry, APPSMITH_FEATURE_CONFIGS.sentry); + const sentryDSN = getConfig( + ENV_CONFIG.sentry.dsn, + APPSMITH_FEATURE_CONFIGS.sentry.dsn, + ); + const sentryRelease = getConfig( + ENV_CONFIG.sentry.release, + APPSMITH_FEATURE_CONFIGS.sentry.release, + ); + const sentryENV = getConfig( + APPSMITH_FEATURE_CONFIGS.sentry.environment, + ENV_CONFIG.sentry.environment, + ); const segment = getConfig( ENV_CONFIG.segment, APPSMITH_FEATURE_CONFIGS.segment, @@ -124,7 +150,12 @@ export const getAppsmithConfigs = (): AppsmithUIConfigs => { ); return { - sentry: { enabled: sentry.enabled, apiKey: sentry.value }, + sentry: { + enabled: sentryDSN.enabled && sentryRelease.enabled && sentryENV.enabled, + dsn: sentryDSN.value, + release: sentryRelease.value, + environment: sentryENV.value, + }, hotjar: { enabled: hotjarId.enabled && hotjarSV.enabled, id: hotjarId.value, diff --git a/app/client/src/configs/types.ts b/app/client/src/configs/types.ts index 03e62bef6a..7fbd8178c3 100644 --- a/app/client/src/configs/types.ts +++ b/app/client/src/configs/types.ts @@ -26,7 +26,9 @@ export type FeatureFlagConfig = { export type AppsmithUIConfigs = { sentry: { enabled: boolean; - apiKey: string; + dsn: string; + release: string; + environment: string; }; hotjar: { enabled: boolean; diff --git a/app/client/src/utils/AppsmithUtils.tsx b/app/client/src/utils/AppsmithUtils.tsx index 0e1199435c..643a4611b4 100644 --- a/app/client/src/utils/AppsmithUtils.tsx +++ b/app/client/src/utils/AppsmithUtils.tsx @@ -31,7 +31,7 @@ export const appInitializer = () => { FeatureFlag.initialize(appsmithConfigs.featureFlag); if (appsmithConfigs.sentry.enabled) { - Sentry.init({ dsn: appsmithConfigs.sentry.apiKey }); + Sentry.init(appsmithConfigs.sentry); } if (appsmithConfigs.hotjar.enabled) { const { id, sv } = appsmithConfigs.hotjar; From 3b1c43dbdcc16e80442f57b982a6c7fecdd204c5 Mon Sep 17 00:00:00 2001 From: satbir121 <39981226+satbir121@users.noreply.github.com> Date: Thu, 13 Aug 2020 22:07:15 +0530 Subject: [PATCH 02/14] Adding base64 library to realm executor (#304) * Adding base64 library to realm executor * Changing base64 interface to btoa and atob * Making base64 a dependancy --- app/client/package.json | 1 + .../jsExecution/JSExecutionManagerSingleton.ts | 9 +++++++++ app/client/yarn.lock | 15 +++++++++++++++ 3 files changed, 25 insertions(+) diff --git a/app/client/package.json b/app/client/package.json index b239f4ef7c..1c0cae4845 100644 --- a/app/client/package.json +++ b/app/client/package.json @@ -60,6 +60,7 @@ "instantsearch.js": "^4.4.1", "interweave": "^12.1.1", "interweave-autolink": "^4.0.1", + "js-base64": "^3.4.5", "json-fn": "^1.1.1", "lint-staged": "^9.2.5", "localforage": "^1.7.3", diff --git a/app/client/src/jsExecution/JSExecutionManagerSingleton.ts b/app/client/src/jsExecution/JSExecutionManagerSingleton.ts index df0240c910..f10d0d2f8c 100644 --- a/app/client/src/jsExecution/JSExecutionManagerSingleton.ts +++ b/app/client/src/jsExecution/JSExecutionManagerSingleton.ts @@ -1,6 +1,7 @@ import RealmExecutor from "./RealmExecutor"; import moment from "moment-timezone"; import { ActionDescription } from "entities/DataTree/dataTreeFactory"; +import { btoa, atob } from "js-base64"; export type JSExecutorGlobal = Record; export type JSExecutorResult = { @@ -30,6 +31,14 @@ export const extraLibraries = [ accessor: "moment", lib: moment, }, + { + accessor: "btoa", + lib: btoa, + }, + { + accessor: "atob", + lib: atob, + }, ]; class JSExecutionManager { diff --git a/app/client/yarn.lock b/app/client/yarn.lock index 10b4a26d63..a131cdba8e 100644 --- a/app/client/yarn.lock +++ b/app/client/yarn.lock @@ -7322,6 +7322,21 @@ js-base64@^2.1.8: version "2.5.1" resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.5.1.tgz#1efa39ef2c5f7980bb1784ade4a8af2de3291121" +js-base64@^3.4.5: + version "3.4.5" + resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-3.4.5.tgz#6d1921e65a172cfd924604e1416dfaff45752c3e" + integrity sha512-Ub/AANierdcT8nm4ndBn3KzpZQ3MdHX4a+bwoVdjgeHCZ0ZEcP+UB4nmR4Z5lR6SH3Y+qAPmgVR0RxKJNHNHEg== + +js-string-escape@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/js-string-escape/-/js-string-escape-1.0.1.tgz#e2625badbc0d67c7533e9edc1068c587ae4137ef" + integrity sha1-4mJbrbwNZ8dTPp7cEGjFh65BN+8= + +js-stringify@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/js-stringify/-/js-stringify-1.0.2.tgz#1736fddfd9724f28a3682adc6230ae7e4e9679db" + integrity sha1-Fzb939lyTyijaCrcYjCufk6Weds= + "js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" From 78c4b5a38287b4b97dac0fc08854282fd3e9217b Mon Sep 17 00:00:00 2001 From: Hetu Nandu Date: Mon, 17 Aug 2020 10:33:15 +0530 Subject: [PATCH 03/14] Fixes date widget crashing when no date format is mentioned (#322) Fixed by using a proper default format string for ISO dates --- app/client/src/constants/WidgetValidation.ts | 2 ++ app/client/src/utils/Validators.ts | 5 +++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/app/client/src/constants/WidgetValidation.ts b/app/client/src/constants/WidgetValidation.ts index 9741656714..556c0e6fe3 100644 --- a/app/client/src/constants/WidgetValidation.ts +++ b/app/client/src/constants/WidgetValidation.ts @@ -33,3 +33,5 @@ export type Validator = ( props: WidgetProps, dataTree?: DataTree, ) => ValidationResponse; + +export const ISO_DATE_FORMAT = "YYYY-MM-DDTHH:mm:ss.SSSZ"; diff --git a/app/client/src/utils/Validators.ts b/app/client/src/utils/Validators.ts index 449f23e8f1..7be2897b03 100644 --- a/app/client/src/utils/Validators.ts +++ b/app/client/src/utils/Validators.ts @@ -1,5 +1,6 @@ import _ from "lodash"; import { + ISO_DATE_FORMAT, VALIDATION_TYPES, ValidationResponse, ValidationType, @@ -392,8 +393,8 @@ export const VALIDATORS: Record = { .minute(0) .second(0) .millisecond(0); - const dateFormat = props.dateFormat ? props.dateFormat : moment.ISO_8601; - // const dateStr = moment().toISOString(); + const dateFormat = props.dateFormat ? props.dateFormat : ISO_DATE_FORMAT; + const todayDateString = today.format(dateFormat); if (dateString === undefined) { return { From 9ecb402f5b672fc8b0a95ec0f9e2ed8a044f6a4c Mon Sep 17 00:00:00 2001 From: areyabhishek Date: Tue, 18 Aug 2020 23:57:50 +0530 Subject: [PATCH 04/14] Update README.md --- README.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index b47e3f5e29..a5e6130258 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,8 @@

-

Open source alternative to Power Apps, Salesforce Lightning platform, and Retool

+

The quickest way to build dashboards, workflows, forms, or any kind of internal business tool.

+

Open source alternative to Power Apps, Salesforce Lightning platform, Unqork, Forest admin, and Retool.

@@ -23,9 +24,9 @@ ----------------- Appsmith is a fast, easy, and secure way to build any custom internal tools. Using Appsmith is easy. -1. Create a page using pre-built UI components like table, charts, and forms. +1. Create a page using pre-built UI components like table, charts, map viewers and forms. 2. Connect the UI components to any REST API or databases like MySQL, Postgres, and MongoDB. Write any logic in JS. -3. Then deploy the interal tool to a custom URL and invite users to sign in with their Google acounts. +3. Deploy the interal tool to a custom URL and invite users to sign in with their Google acounts. Do all this **without HTML/CSS**, and writing any custom integrations. From 62d0ec6b17618413f80b680bf78dff5bf719b7ad Mon Sep 17 00:00:00 2001 From: areyabhishek Date: Tue, 18 Aug 2020 23:58:30 +0530 Subject: [PATCH 05/14] Update README.md --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index a5e6130258..0208af071a 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,6 @@

The quickest way to build dashboards, workflows, forms, or any kind of internal business tool.

-

Open source alternative to Power Apps, Salesforce Lightning platform, Unqork, Forest admin, and Retool.

From 3762ea6210dcdb0b435c460192a86ac74655a9bd Mon Sep 17 00:00:00 2001 From: areyabhishek Date: Wed, 19 Aug 2020 00:06:40 +0530 Subject: [PATCH 06/14] Update README.md --- README.md | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 0208af071a..417f240f4c 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ Appsmith is a fast, easy, and secure way to build any custom internal tools. Usi 2. Connect the UI components to any REST API or databases like MySQL, Postgres, and MongoDB. Write any logic in JS. 3. Deploy the interal tool to a custom URL and invite users to sign in with their Google acounts. -Do all this **without HTML/CSS**, and writing any custom integrations. +Do all this without depending on multiple UI libraries, coding authentication logic or writing any DB or API integrations. See the looped gif below to see how something gets built on Appsmith. ![UI Builder Demo](https://github.com/appsmithOrg/appsmith/blob/readme/static/demo.gif) @@ -38,21 +38,22 @@ Do all this **without HTML/CSS**, and writing any custom integrations. * [Customer Support Dashboard](https://app.appsmith.com/applications/5f2aeb2580ca1f6faaed4e4a/pages/5f2aeb2580ca1f6faaed4e4c#utm_source=github&utm_medium=homepage) ## Getting Started - -* [Cloud Hosted](https://app.appsmith.com/user/signup) +You can try our online sandbox or deploy a Docker image on a server. +* [Online sandbox](https://app.appsmith.com/user/signup) * [Deploy with Docker](https://docs.appsmith.com/quick-start#docker) ## Why Appsmith? -If we're building an internal tool, our obvious choices are to use an admin panel or if we happen to be blessed with HTML/CSS skills, we might **"bootstrap"** a new project. While this may seem like a great idea at first, internal tools almost always require a ton of iterations and eventually we reach a point where we're either spending a lot of time customising the admin panel or the UI terrifies users so much, they prefer [holding our hand](https://giphy.com/gifs/agentm-agent-m-1gg6pvaqHBv56/fullscreen) every time they try to use it. +When we need an internal tool, we turn to admin panels frameworks or use a bootstrap theme. Admin panels have an opinionated design +These choices don't always work out because internal tools require iterations, maintenance, enhancements and eventually we reach a point where we're either spending a lot of time customising the admin panel or the UI terrifies users so much, they prefer [holding our hand](https://giphy.com/gifs/agentm-agent-m-1gg6pvaqHBv56/fullscreen) every time they try to use it. Appsmith provides a better way of building internal tools by visualising them as modular blocks (**Widgets, APIs, Queries, JS**) and giving developers a simple user interface to configure them. With appsmith updating UI, changing dataflows and modifying business logic becomes a [piece of cake](https://i.kym-cdn.com/photos/images/newsfeed/001/355/125/5ca.png) because you no longer have to trudge through large undocumented code bases or **fight with HTML/CSS**. We understand that while some configurations are static and are better controlled via UI, a lot of it is dynamic and should be configured through code. Appsmith doesn't take the fun out of coding, instead it treats every block as an object and exposes it via javascript so that you can read, transform and manipulate it. Whether it's a widget, API or query, you get to decide where you need to configure and where you need to code. ## Features * **Build custom UI**: Drag & drop, resize and style widgets **without HTML / CSS**. [Read more](https://docs.appsmith.com/core-concepts/building-the-ui) -* **Query data**: Query & update your database directly from the UI. Supports **postgres, mongo, REST & GraphQL APIs**. [Read more](https://docs.appsmith.com/core-concepts/building-the-ui/displaying-api-data) -* **JS Logic**: Write snippets of business logic using JS to transform data, manipuate UI or trigger workflows +* **Query data**: Query & update your database directly from the UI. Connect to **postgres, mongo, MySQL, REST & GraphQL APIs**. [Read more](https://docs.appsmith.com/core-concepts/building-the-ui/displaying-api-data) +* **JS Logic**: Write snippets of business logic using JS to transform data, manipuate UI or trigger workflows. Use Lodash functions * **Data Workflows**: Simple configuration to create flows when users interact with the UI. [Read more](https://docs.appsmith.com/core-concepts/building-the-ui/calling-apis-from-widgets) * **Realtime Editor**: Changes in your application reflect instantly with every edit. No need to compile! * **Works with existing, live databases**: Connect directly to any Postgres & Mongo db From fb279442c2e6d826d4d6eceddffc517d5f9e3c93 Mon Sep 17 00:00:00 2001 From: areyabhishek Date: Wed, 19 Aug 2020 00:17:58 +0530 Subject: [PATCH 07/14] Update README.md --- README.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 417f240f4c..af4c8dbb36 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ Appsmith is a fast, easy, and secure way to build any custom internal tools. Usi 2. Connect the UI components to any REST API or databases like MySQL, Postgres, and MongoDB. Write any logic in JS. 3. Deploy the interal tool to a custom URL and invite users to sign in with their Google acounts. -Do all this without depending on multiple UI libraries, coding authentication logic or writing any DB or API integrations. See the looped gif below to see how something gets built on Appsmith. +Do all this without depending on multiple UI libraries, coding authentication logic or writing any DB or API integrations. See the looped gif below to see how something gets built on Appsmith. It might remind you of Visual Basic. ![UI Builder Demo](https://github.com/appsmithOrg/appsmith/blob/readme/static/demo.gif) @@ -44,10 +44,9 @@ You can try our online sandbox or deploy a Docker image on a server. ## Why Appsmith? -When we need an internal tool, we turn to admin panels frameworks or use a bootstrap theme. Admin panels have an opinionated design -These choices don't always work out because internal tools require iterations, maintenance, enhancements and eventually we reach a point where we're either spending a lot of time customising the admin panel or the UI terrifies users so much, they prefer [holding our hand](https://giphy.com/gifs/agentm-agent-m-1gg6pvaqHBv56/fullscreen) every time they try to use it. +When we build internal tools today, we turn to admin panels frameworks or use a bootstrap theme. We took inspirations from the best admin panels, bootstrap themes, and brought back the easy UI builder of Visual Basic. -Appsmith provides a better way of building internal tools by visualising them as modular blocks (**Widgets, APIs, Queries, JS**) and giving developers a simple user interface to configure them. With appsmith updating UI, changing dataflows and modifying business logic becomes a [piece of cake](https://i.kym-cdn.com/photos/images/newsfeed/001/355/125/5ca.png) because you no longer have to trudge through large undocumented code bases or **fight with HTML/CSS**. We understand that while some configurations are static and are better controlled via UI, a lot of it is dynamic and should be configured through code. Appsmith doesn't take the fun out of coding, instead it treats every block as an object and exposes it via javascript so that you can read, transform and manipulate it. Whether it's a widget, API or query, you get to decide where you need to configure and where you need to code. +Appsmith is a quicker way of building internal tools by visualising them as modular blocks (**Widgets, APIs, Queries, JS**) and giving developers a simple user interface to configure them. New features, UI modification, changing dataflows, and modifying business logic becomes a [piece of cake](https://i.kym-cdn.com/photos/images/newsfeed/001/355/125/5ca.png) because you no longer have to trudge through large undocumented code bases or wrestle with HTML/CSS. We understand that while some configurations are static and are better controlled via UI, a lot of it is dynamic and should be configured through code. Appsmith doesn't take the fun out of coding, instead it treats every block as an object and exposes it via javascript so that you can read, transform and manipulate it. Whether it's a widget, API or query, you get to decide where you need to configure and where you need to code. ## Features From 0543392638bcca0cff3ee9d2e1c6aff5f10200a4 Mon Sep 17 00:00:00 2001 From: areyabhishek Date: Wed, 19 Aug 2020 00:19:07 +0530 Subject: [PATCH 08/14] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index af4c8dbb36..00515191ea 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ ----------------- -Appsmith is a fast, easy, and secure way to build any custom internal tools. Using Appsmith is easy. +Appsmith is a fast, easy, and secure way to build any custom internal tools. Here's how you build something: 1. Create a page using pre-built UI components like table, charts, map viewers and forms. 2. Connect the UI components to any REST API or databases like MySQL, Postgres, and MongoDB. Write any logic in JS. 3. Deploy the interal tool to a custom URL and invite users to sign in with their Google acounts. @@ -55,7 +55,7 @@ Appsmith is a quicker way of building internal tools by visualising them as modu * **JS Logic**: Write snippets of business logic using JS to transform data, manipuate UI or trigger workflows. Use Lodash functions * **Data Workflows**: Simple configuration to create flows when users interact with the UI. [Read more](https://docs.appsmith.com/core-concepts/building-the-ui/calling-apis-from-widgets) * **Realtime Editor**: Changes in your application reflect instantly with every edit. No need to compile! -* **Works with existing, live databases**: Connect directly to any Postgres & Mongo db +* **Works with existing, live databases**: Connect directly to any Postgres, MySQL, & Mongo db * **Fine-grained access control**: Control who can edit / view your applications from a single control panel * **App management**: Build and organise multiple applications on a single platform From 5126c4679cd2ebcdb8629e93d95a79172baf082d Mon Sep 17 00:00:00 2001 From: Nikhil Nandagopal Date: Thu, 20 Aug 2020 12:03:08 +0530 Subject: [PATCH 09/14] Updated Links --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 00515191ea..34fe65160a 100644 --- a/README.md +++ b/README.md @@ -35,12 +35,12 @@ Do all this without depending on multiple UI libraries, coding authentication lo ## Example Applications -* [Customer Support Dashboard](https://app.appsmith.com/applications/5f2aeb2580ca1f6faaed4e4a/pages/5f2aeb2580ca1f6faaed4e4c#utm_source=github&utm_medium=homepage) +* [Customer Support Dashboard](https://bit.ly/cs-dashboard-appsmith) ## Getting Started You can try our online sandbox or deploy a Docker image on a server. -* [Online sandbox](https://app.appsmith.com/user/signup) -* [Deploy with Docker](https://docs.appsmith.com/quick-start#docker) +* [Online sandbox](https://bit.ly/appsmith-signup-github) +* [Deploy with Docker](https://bit.ly/appsmith-docker-github) ## Why Appsmith? From 17af152148d1a045ef8af4ad396ef5fc9258c4f4 Mon Sep 17 00:00:00 2001 From: vicky-primathon <67091118+vicky-primathon@users.noreply.github.com> Date: Thu, 20 Aug 2020 15:00:19 +0530 Subject: [PATCH 10/14] Table Widget: Filter updates (#355) - Show symbol signifying selected filters in table widget - Show callout to prompt users to change column data types for accurate filter operations --- .../appsmith/ReactTableComponent.tsx | 5 +- .../designSystems/appsmith/Table.tsx | 6 +- .../designSystems/appsmith/TableFilters.tsx | 141 ++++++++++++------ .../designSystems/appsmith/TableHeader.tsx | 5 +- .../appsmith/TableStyledWrappers.tsx | 1 + .../designSystems/appsmith/TableUtilities.tsx | 4 +- app/client/src/constants/messages.ts | 3 + app/client/src/widgets/TableWidget.tsx | 2 +- 8 files changed, 113 insertions(+), 54 deletions(-) diff --git a/app/client/src/components/designSystems/appsmith/ReactTableComponent.tsx b/app/client/src/components/designSystems/appsmith/ReactTableComponent.tsx index dcbad406ed..5252b3c80e 100644 --- a/app/client/src/components/designSystems/appsmith/ReactTableComponent.tsx +++ b/app/client/src/components/designSystems/appsmith/ReactTableComponent.tsx @@ -1,7 +1,6 @@ import React, { useEffect } from "react"; import { ColumnAction } from "components/propertyControls/ColumnActionSelectorControl"; import Table from "components/designSystems/appsmith/Table"; -import { RenderMode, RenderModes } from "constants/WidgetConstants"; import { debounce } from "lodash"; import { getMenuOptions } from "components/designSystems/appsmith/TableUtilities"; import { @@ -37,7 +36,7 @@ interface ReactTableComponentProps { isDisabled?: boolean; isVisible?: boolean; isLoading: boolean; - renderMode: RenderMode; + editMode: boolean; width: number; height: number; pageSize: number; @@ -282,7 +281,7 @@ const ReactTableComponent = (props: ReactTableComponentProps) => { hiddenColumns={props.hiddenColumns} updateHiddenColumns={props.updateHiddenColumns} data={props.tableData} - displayColumnActions={props.renderMode === RenderModes.CANVAS} + editMode={props.editMode} columnNameMap={props.columnNameMap} getColumnMenu={getColumnMenu} handleColumnNameUpdate={handleColumnNameUpdate} diff --git a/app/client/src/components/designSystems/appsmith/Table.tsx b/app/client/src/components/designSystems/appsmith/Table.tsx index 0daaaba156..3aae6e6df9 100644 --- a/app/client/src/components/designSystems/appsmith/Table.tsx +++ b/app/client/src/components/designSystems/appsmith/Table.tsx @@ -33,7 +33,7 @@ interface TableProps { hiddenColumns?: string[]; updateHiddenColumns: (hiddenColumns?: string[]) => void; data: object[]; - displayColumnActions: boolean; + editMode: boolean; columnNameMap?: { [key: string]: string }; getColumnMenu: (columnIndex: number) => ColumnMenuOptionProps[]; handleColumnNameUpdate: (columnIndex: number, columnName: string) => void; @@ -142,7 +142,7 @@ export const Table = (props: TableProps) => { updateHiddenColumns={props.updateHiddenColumns} filters={props.filters} applyFilter={props.applyFilter} - displayColumnActions={props.displayColumnActions} + editMode={props.editMode} compactMode={props.compactMode} updateCompactMode={props.updateCompactMode} tableSizes={tableSizes} @@ -168,7 +168,7 @@ export const Table = (props: TableProps) => { } columnIndex={columnIndex} isHidden={column.isHidden} - displayColumnActions={props.displayColumnActions} + editMode={props.editMode} handleColumnNameUpdate={props.handleColumnNameUpdate} getColumnMenu={props.getColumnMenu} handleResizeColumn={props.handleResizeColumn} diff --git a/app/client/src/components/designSystems/appsmith/TableFilters.tsx b/app/client/src/components/designSystems/appsmith/TableFilters.tsx index 93a61a04b0..03d6aa8d6a 100644 --- a/app/client/src/components/designSystems/appsmith/TableFilters.tsx +++ b/app/client/src/components/designSystems/appsmith/TableFilters.tsx @@ -18,6 +18,13 @@ import { Operator, OperatorTypes, } from "widgets/TableWidget"; +import { TABLE_FILTER_COLUMN_TYPE_CALLOUT } from "constants/messages"; + +const TableFilterOuterWrapper = styled.div` + display: flex; + flex-direction: column; + width: 100%; +`; const TableFilerWrapper = styled.div` display: flex; @@ -37,6 +44,41 @@ const ButtonWrapper = styled.div` background: transparent; } `; + +const SelectedFilterWrapper = styled.div` + position: absolute; + top: 12px; + right: 12px; + background: ${Colors.GREEN}; + border: 0.5px solid ${Colors.WHITE}; + box-sizing: border-box; + border-radius: 50%; + width: 10px; + height: 10px; + display: flex; + justify-content: center; + align-items: center; + font-weight: bold; + font-size: 6px; + color: ${Colors.WHITE}; +`; + +const ColumnTypeBindingMessage = styled.div` + width: 100%; + height: 41px; + line-height: 41px; + background: ${Colors.ATHENS_GRAY_DARKER}; + border: 1px dashed ${Colors.GEYSER_LIGHT}; + box-sizing: border-box; + font-size: 12px; + color: ${Colors.SLATE_GRAY}; + letter-spacing: 0.04em; + font-weight: 500; + padding: 0 16px; + min-width: 350px; + border-bottom-left-radius: 4px; + border-bottom-right-radius: 4px; +`; export interface ReactTableFilter { column: string; operator: Operator; @@ -53,6 +95,7 @@ interface TableFilterProps { columns: ReactTableColumnProps[]; filters?: ReactTableFilter[]; applyFilter: (filters: ReactTableFilter[]) => void; + editMode: boolean; } const TableFilters = (props: TableFilterProps) => { @@ -135,51 +178,63 @@ const TableFilters = (props: TableFilterProps) => { > - - e.stopPropagation()}> - {filters.map((filter: ReactTableFilter, index: number) => { - return ( - = 2 ? filters[1].operator : filter.operator - } - column={filter.column} - condition={filter.condition} - value={filter.value} - columns={columns} - applyFilter={(filter: ReactTableFilter, index: number) => { - const updatedFilters = props.filters ? [...props.filters] : []; - updatedFilters[index] = filter; - props.applyFilter(updatedFilters); - }} - removeFilter={(index: number) => { - const filters: ReactTableFilter[] = props.filters || []; - if (index === 1 && filters.length > 2) { - filters[2].operator = filters[1].operator; - } - const newFilters = [ - ...filters.slice(0, index), - ...filters.slice(index + 1), - ]; - props.applyFilter(newFilters); - }} - /> - ); - })} {showAddFilter ? ( - -