From 94e08c6645ea6be3b2a1d230ba6ba342a6c18aef Mon Sep 17 00:00:00 2001 From: AxelTLarsson Date: Mon, 28 Jan 2019 12:13:42 +0100 Subject: [PATCH] Upgrade to v6.0.0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Squashed commit of the following: commit 4780bd9c5ef212dd4c38bafb525abc991812d59b Merge: 3ee7537a ef66da7d Author: Arik Fraimovich Date: Sun Dec 16 20:27:43 2018 +0200 Merge pull request #3196 from getredash/master Sync release/6.0.x branch with master commit ef66da7d94c1c9ff7d4adb924f09047a49899a62 Author: Arik Fraimovich Date: Sun Dec 16 16:01:20 2018 +0200 V6 release (#3195) * V6 release * Remove "-beta" * Update package.json * Update package-lock.json * Update CHANGELOG.md commit 57c8fbe14e91c7091a5b89186a5cd17e4971e991 Author: Arik Fraimovich Date: Sun Dec 16 09:55:34 2018 +0200 README updates 1. Remove link to Slack channel. 2. Update number of data sources. commit 938a20e7c05a2c3d55fa6805dc5830b318e30e27 Author: Arik Fraimovich Date: Sun Dec 16 09:42:32 2018 +0200 Use multiple issue templates instead of a single one (#3194) * Switch to issue templates * Apply a label to non bugs commit f5dbdf245a705d7813e6ff56575660616a1f05c9 Author: Arik Fraimovich Date: Thu Dec 13 15:10:31 2018 +0200 Safely create_app in Celery code (try to fetch current_app first). (#3187) Closes #3181. commit 8481dacff43b767ccc129ea068a09d888c130db2 Author: Gabriel Dutra Date: Wed Dec 12 19:32:12 2018 -0200 Fix eslint issues on user.js (#3186) commit e23a07af03939e943e95c75b904963dcfd711557 Author: Omer Lachish Date: Wed Dec 12 08:30:46 2018 +0200 Remove missing coverage from pytest terminal output (#3180) * Remove missing coverage from pytest terminal output * move coverage reporting to CI commit 52434a837f668fefa3673cd17f59cd8aae3d603a Author: Arik Fraimovich Date: Tue Dec 11 15:03:29 2018 +0200 Make refresh_queries less noisey in logs (#3183) commit 230ad33f02a331175aefffd8f13f4c4f1371a0bc Author: Arik Fraimovich Date: Tue Dec 11 14:57:42 2018 +0200 [Redshift] Fix: support for schema names with dots. (#3182) commit cfe12c5a5d37b8ec01c8a26fd9c8c8ad97e12d07 Author: Gabriel Dutra Date: Mon Dec 10 18:29:36 2018 -0200 Add DB Seed to Cypress and setup Percy (#3155) * Update Cypress element selectors * Add seed data function to Cypress * Change Cypress setup to be part of db-seed * Add DatabaseSource selector to Create Data Source spec * Add getElement command to Cypress * Fix eslint issues * Change Cypress getElement to getByTestId * Add Percy and test it with the CI * Change Percy dependency for CI to Cypress' Dockerfile * Change Percy's execution to the docker container - add --no-save to avoid errors on Dockerfile.cypress - pass PERCY_TOKEN from the CI to docker container * Fix missed char on CircleCI config file * Move Percy execution back to host on the CI * Test adding PERCY_TOKEN to frontend-e2e-tests on CI config * Undo add PERCY_TOKEN to config.yml * Add Percy token and .git folder to Cypress * Remove Percy install from config.yml * Ignore .git folder again and use Percy env vars instead * Update PERCY_PULL_REQUEST to be CIRCLE_PR_NUMBER * Update cypress-server.js to handle other cypress commands - cypress-server.js -> cypress.js - new commands added to cypress.js - CircleCI config updated accordingly - added a Homepage screenshot * Remove trailing spaces * Add Create Query spec * Disable Cypress videos * Update run browser to Chrome * Add missing --browser chrome commit 38ed046c9fae428e17d9af9e8a7c51f3d6df3983 Author: Omer Lachish Date: Mon Dec 10 14:02:50 2018 +0200 Fix disable error message (#3175) * display correct error message when attempting to disable yourself * 403 (Forbidden) feels like a better status code than 400 (Bad Request) * fix broken test * remove redundant error title commit 1acf063755ca5caabf01a28cd482f28562b28f3b Author: Takuya Arita Date: Mon Dec 10 19:35:25 2018 +0900 FIX: Reject empty query name (#3171) commit 76321937d766e650a1f6bdf61b0a6575c9f063fc Author: Omer Lachish Date: Wed Dec 5 12:21:18 2018 +0200 Remove API permissions for users who have been disabled (#3162) commit c9ca2b99f6e266a8af92a4addeb532737e2b17e9 Author: Arik Fraimovich Date: Wed Dec 5 11:28:05 2018 +0200 Fix: Alert.evaluate failing when the column is missing. (#3167) commit d42f0b2d40a2b7686b20d8a8c59a8eb21e87c821 Author: Arik Fraimovich Date: Wed Dec 5 10:11:08 2018 +0200 Directly using record_event task requires timestamp (#3166) Using the helper instead. commit e530c23d4cfee361483db590b52a1f0afdf3cf50 Author: Vladislav Denisov Date: Wed Dec 5 10:29:47 2018 +0300 clickhouse: fixed int() conversion error (#3161) commit 0973ee8abbeea3cf74ca082fdc3c9acfeb4beb85 Author: Omer Lachish Date: Tue Dec 4 22:14:32 2018 +0200 Include correct version in production builds (#3163) * take the first 8 characters for frontend version, not backend version * run `npm run build` after version has been updated in CI * `pack` should run last commit 3ee7537a6c049a98e7284c67b98130556031e263 Author: Arik Fraimovich Date: Mon Dec 3 22:07:20 2018 +0200 WIP: Update CHANGELOG (#3159) commit 9c12b045787f2f87106ffab046291a015cdb1d31 Author: Arik Fraimovich Date: Mon Dec 3 10:57:36 2018 +0200 json_dumps: add support for serializing buffer objects. (#3156) commit 9579f12a83becf778a692acf185fc34ebb3efe1c Author: Omer Lachish Date: Sun Dec 2 21:51:06 2018 +0200 Protect against SQL injections by using tree comparisons (#3109) * add SQLQuery class with tests for safe queries and non-safe tautology attacks * add test for union query injections * split .apply calls to newline * add tests for comment attacks * remove double underscore * extract complex children check to variable * inherit from object because I'm not a lamer Co-Authored-By: rauchy * simplify cognitive complexity * check that additional columns are not injected * detect appended queries * inline .apply calls * move SQLQuery to it's own module * move SQLQuery tests to their own module * serialize SQLQuery instances * raise an exception when attempting to serialize an unsafe query * queries without parameters are safe * remove redundant parentheses * use cached properties * rename SQLInjectionException to SQLInjectionError * support multiple word params and param negations * refactor out methods that don't involve any state * don't cache text() * reduce cognitive complexity commit 463d4ce518292de0bec436b9bfb2d1e68ab077fd Author: Zsolt Kocsmárszky Date: Sun Dec 2 09:42:30 2018 +0100 Fix label positioning on no found screen (#3148) * Fix label positioning on no found screen * Use TagsControl component on not found screen commit 2e4d1964521ede72b224ce06ac0c0edbc006524a Author: Zsolt Kocsmárszky Date: Sun Dec 2 09:27:01 2018 +0100 Add and improve recent db logos that didn't fit in size properly (#3147) * Add and improve recent db logos that didn't fit in size properly * Update mongodb logo * Remove Athena Direct as requested commit 4078af299637b7cffa04d2dda6ef565f48a5059c Author: Zsolt Kocsmárszky Date: Thu Nov 29 20:04:35 2018 +0100 Update, replace and fix new alert destination logos so it fits better (#3146) commit 73825ea266945fcf52516f2c0f4d43b534bc2e8c Author: Zsolt Kocsmárszky Date: Thu Nov 29 20:02:54 2018 +0100 Improve tag link colors and fix group tags on Users page (#3149) commit b2a0d618441519ae0d88c69d2a4a7759d7b4c424 Author: Zsolt Kocsmárszky Date: Thu Nov 29 14:40:44 2018 +0100 Better manage permissions modal (#3139) * Improved design for manage permissions * Show Owner on Permission modal, remove owner from dropdown options * Pass owner to Permissions modal commit 1774edabc0a8f6234f4239636f31ecf674392ea5 Author: Omer Lachish Date: Thu Nov 29 15:20:30 2018 +0200 take the first 8 characters for frontend version, not backend version (#3145) commit 54b8e7c13622f2a9b8d3b9214f7aa117b37526e3 Merge: 757333c2 54f09f73 Author: Omer Lachish Date: Thu Nov 29 15:17:14 2018 +0200 Merge pull request #3144 from getredash/display-frontend-version Display only the first 8 characters of frontend version commit 54f09f73dbf403df5614691b32fb76ffc62d42ff Author: Omer Lachish Date: Thu Nov 29 15:03:37 2018 +0200 take the first 8 characters for frontend version commit 35aca1d4cf4d03bdd8de3f6b8209d64f5876bf3b Merge: 407f14ff 757333c2 Author: Omer Lachish Date: Thu Nov 29 15:03:11 2018 +0200 Merge branch 'master' into display-frontend-version commit 757333c2d610dc7867dc7f5849558026063cd659 Author: Levko Kravets Date: Thu Nov 29 14:48:21 2018 +0200 When editing a dashboard title results in the visualizations being replaced by the loading markers (#3142) * getredash/redash#3015 When editing a dashboard title results in the visualizations being replaced by the loading markers * CR1 Co-Authored-By: kravets-levko commit 92728de04caad09c2c35ec54cd297a8abe619743 Author: Omer Lachish Date: Thu Nov 29 14:24:23 2018 +0200 Display frontend version (#3105) * add git-revision-webpack-plugin * configure git-revision-webpack-plugin * add commit to footer * rename version and commit to backendVersion and frontendVersion * rename version and commit to backendVersion and frontendVersion * disable lint error due to use of globals * fix snapshot test * read frontend version from VERSION file instead latest git revision * directly require from version.json file instead of going through WebPack's DefinePlugin * run snapshots commit 407f14ffcac85575917ceeeaae5c006045d2d800 Author: Omer Lachish Date: Thu Nov 29 13:07:04 2018 +0200 run snapshots commit ecb8a5c244db1df100eb1e0dbc8c5bcfcf0f2644 Author: Arik Fraimovich Date: Thu Nov 29 13:01:23 2018 +0200 Hive/Databricks related improvements (#3143) * Hive: fix issues in building options. * Hive: add missing import. * Split Hive into two query runners: one for http and a regular one. * Upgrade pyhive to support http. * Specific implementation for databricks: * Different schema loader, because column names are different (or Hive's schema loader is broken). * Simpler configuration. * Simplify Databricks setup even more by removing username. commit 0e8fab48724d6666db4b4f5499256ad22414ca9e Author: Omer Lachish Date: Thu Nov 29 13:00:13 2018 +0200 directly require from version.json file instead of going through WebPack's DefinePlugin commit c15fa0c592d665812cee176b057f882aedee9bf7 Author: Omer Lachish Date: Thu Nov 29 11:57:53 2018 +0200 read frontend version from VERSION file instead latest git revision commit 09ab00e360b811ff277f8d7732761cb5b83344a4 Author: Levko Kravets Date: Thu Nov 29 11:35:17 2018 +0200 Migrate all tags components to React (#3138) commit 1728f924cfb1c49d3ae63073d781003337111167 Author: Truong Hoang Phuoc, Robert Date: Thu Nov 29 15:19:36 2018 +0800 Fix schema refresh to work on MySQL 8 (#3141) commit 8dc10fbd9a051647e0a9547478414d7c67a35fb8 Merge: 8028397f a16170e7 Author: Omer Lachish Date: Thu Nov 29 09:13:41 2018 +0200 Merge branch 'master' into display-frontend-version commit a16170e7014ecb773b748963497f7ddcc7dec43d Author: Jannis Leidel Date: Wed Nov 28 13:06:15 2018 +0100 Fix tag counts for dashboards and queries. (#3120) * Fix tag counts for dashboards to be distinct. This also makes use of the Dashboard.all base query. Fix #3108. * Use Query.all_queries as the base query for Query.all_tags. * Add test case for Dashboard.all_tags. commit 07c0bba56849dfa902a9785cf1b1c16b59dc2ec4 Author: Arik Fraimovich Date: Wed Nov 28 10:36:33 2018 +0200 Delete now.json (#3134) commit d36d18f85b5556071f7812574dd19f4c0b8546a0 Author: Arik Fraimovich Date: Tue Nov 27 09:06:44 2018 +0200 Support unicode in Postgres/Redshift schema (#3124) commit bd20ce12ac94d21b425fff55cc6c906395ca8c48 Author: Arik Fraimovich Date: Mon Nov 26 21:22:14 2018 +0200 Don't allow updating user's email to blacklisted domain. (#3127) commit 1cdfcfaa3cfcc1427d803e7c72e550ec8fbd00dd Author: Arik Fraimovich Date: Mon Nov 26 21:21:49 2018 +0200 Vertica: update driver & add support for connection timeout (#3125) * Update Vertica driver version * Vertica: add support for connection timeout commit 2fdace518a7ceacbfd2f6f1c29318f222e51d3b4 Author: Arik Fraimovich Date: Mon Nov 26 21:21:07 2018 +0200 Use lower timeout for the first 5 seconds when polling for results. (#3128) commit 3516e4ef45c74bb44c24d27a452aa45deb504796 Author: Igor Canadi Date: Mon Nov 26 11:20:37 2018 -0800 Add Rockset query runner (#3068) * Add Rockset query runner Per REST API documented here: https://docs.rockset.com/rest/ * Update rockset.py * Add Rockset logo * Refactor Rockset qury runner: * More idomatic names for configuration. * Move API code to separate class to make it easier removing it when we switch to official library. * Make Test Connection work. * apply autopep8 to rockset.py commit d84296814200a8f5d444801aa2cc70f5535d59cd Author: Arik Fraimovich Date: Mon Nov 26 16:08:04 2018 +0200 MongoDB: add support for sorting columns. (#3126) commit 600741620a6889915327357847e2350be2037776 Author: Arik Fraimovich Date: Mon Nov 26 15:31:39 2018 +0200 Remove (Beta) from Query Results query runner name (#3123) commit 45f4277eb4f0a3db01f5f286c876a3917f5bb2f9 Author: YOSHIDA Katsuhiko Date: Mon Nov 26 21:23:55 2018 +0900 Fix forked query is opened in the same tab (#3121) commit bcf3041c91da6f15397aaccd80654986ffe5b1b4 Author: Jannis Leidel Date: Mon Nov 26 13:02:52 2018 +0100 Show menu divider only if query is archived. (#3122) Fix #3117. commit da423340ecba15532f82aec7d929c7f921ccf553 Author: Zsolt Kocsmárszky Date: Mon Nov 26 12:41:07 2018 +0100 Fix mobile padding issues on Query results (#3111) commit 4003d4f1aa9a8ffd19ccdd0fb937eaa0238a81f3 Author: Arik Fraimovich Date: Mon Nov 26 09:58:39 2018 +0200 Add event tracking to autocomplete toggle & trackEvent helper function (#3114) * Add non Angular version of Events. * Add event tracking for autocomplete toggle * Fix lint error in QueryEditor commit a6b782e0ce1422db51ea023e6f6d5cd64b774a66 Author: YOSHIDA Katsuhiko Date: Sun Nov 25 21:11:27 2018 +0900 Add get_current_user() into Python Data Source (#3088) commit 5648de9ba8abb9b7c8596697d1a2dc17f8d59fe9 Author: YOSHIDA Katsuhiko Date: Sun Nov 25 21:09:52 2018 +0900 Open new tab when forking a query (#3089) * Open new tab when forking a query * Delete old fork menu item and add icon commit 13eb365f7b72776cb0a954ac0436c1b9bf7fa54e Author: Jannis Leidel Date: Sun Nov 25 13:08:25 2018 +0100 Update changelog for v6.0.0-beta. (#3112) * Add v6.0.0-beta changelog entry. * Update CHANGELOG.md commit 8257d9d0371ae579eec7577946f6234ae0eda227 Author: Udomomo Date: Sun Nov 25 20:47:25 2018 +0900 Add permissions to the result of "manage.py groups list" command (#3007) * Add permissions to the result of "groups list" command * added permissions to test case * removed setting for debug commit babbeb79f0c9d7f8fe5a9f4e6b51c740b23e1e38 Author: Allen Short Date: Fri Nov 23 13:28:30 2018 +0000 keep query text in local state for now (#3107) (#3110) * keep query text in local state for now (#3107) This will be unnecessary once the queryText prop isn't managed by Angular. * Fix: make formatQuery work commit 8028397f274b25bd8ada025d4a6a67b91997407f Merge: fae2b708 e05c8e60 Author: Omer Lachish Date: Thu Nov 22 12:52:43 2018 +0200 Merge branch 'master' into display-frontend-version commit e05c8e6060c2a185e951b2ecd5ff53ca8aec2673 Author: Subhi Al Hasan Date: Wed Nov 21 17:13:12 2018 +0200 Fix collection fields retreival bug when Views are present in MONGO DB (#3097) * Fix collection fields retreival bug when Views are present in MongoDB * fixing _is_collection_a_view function * Update redash/query_runner/mongodb.py Co-Authored-By: jodevsa commit fae2b708662389eb2b0a8fe928269ad16220c887 Merge: 1119fce4 1b66fff3 Author: Omer Lachish Date: Wed Nov 21 10:49:29 2018 +0200 Merge branch 'display-frontend-version' of github.com:getredash/redash into display-frontend-version commit 1119fce44c67534f50d43be9ae9c2edc180ecf35 Merge: bfb7edc0 0fe1b5f9 Author: Omer Lachish Date: Wed Nov 21 10:48:03 2018 +0200 Merge branch 'master' into display-frontend-version commit bfb7edc0eb2b4b4f628c3e8390800804559d5192 Author: Omer Lachish Date: Wed Nov 21 10:47:54 2018 +0200 fix snapshot test commit a39a7394736551193825ad34a813464d1581a3b2 Author: Omer Lachish Date: Wed Nov 21 10:44:34 2018 +0200 disable lint error due to use of globals commit c9dfac5b1d979319ee7c8f968ac010fb4d8a8664 Author: Omer Lachish Date: Tue Nov 20 23:34:39 2018 +0200 rename version and commit to backendVersion and frontendVersion commit 1b66fff3be618da345f905c1f2a7bc4c40146bed Author: Omer Lachish Date: Tue Nov 20 23:34:39 2018 +0200 rename version and commit to backendVersion and frontendVersion commit 0fe1b5f9d439c4d9b76c592ad4c17f4e4c51d86e Author: Arik Fraimovich Date: Tue Nov 20 23:34:37 2018 +0200 Fix: registerAll fails after minification (#3106) commit 143db90a509bbe0c80b8e55ce76fbb572679ab81 Author: Levko Kravets Date: Tue Nov 20 18:48:41 2018 +0200 Fix query page header (#3046) * getredash/redash#3017 Improve query page header * getredash/redash#3017 Resolve conflicts * getredash/redash#3017 CR1 (fix margins/paddings) commit bac90db3ee7a099fd3a3a3350f193dbfed364b01 Author: Arik Fraimovich Date: Tue Nov 20 18:45:33 2018 +0200 Autocomplete toggle improvements (#3091) * Autocomplete toggle improvements: * Refactor to its own component. * Show state in tooltip (enabled/disabled). * Disable the toggle if autocomplete is not possible (no schema/too many tokens). * Remove unsued code. * Custom icons font (currently has only two icons). Generated with Icomoon. If we extend its use, we should probably automate this and move to its own package. * Don't disable live autocomplete for data sources without schema. It can still be useful to autocomplete from local keywords. * Differentiate between autocomplete toggle states with an icon. Also added explicit message for the disabled state. * Remember thes state of autocomplete. * Only auto register init functions. commit 649d46de89c15252b65a50a91f5e3c4315a52ab1 Author: Omer Lachish Date: Tue Nov 20 15:25:07 2018 +0200 add commit to footer commit 0163e85eda0d66ec13ccaf5b917167a7e713a469 Author: Omer Lachish Date: Tue Nov 20 15:24:55 2018 +0200 configure git-revision-webpack-plugin commit f25beb3fb776c9cf2f458be1a08ab65c5f6e2670 Author: Omer Lachish Date: Tue Nov 20 15:24:41 2018 +0200 add git-revision-webpack-plugin commit c66f63d7a5e152202e9c0faa98dcec0c4b8ea6df Author: Omer Lachish Date: Tue Nov 20 12:22:15 2018 +0200 Prevent Query's updated_at from changing when it is linked to new query results (#3082) * avoid Query's updated_at from changing when it is linked to new query results * move comment to previous line * move QueryResult tests to their own module * add test which verifies that updated_at is not changed on query data updates * tests were false positives - they compared HH:MM:SS, but that never changed because the original time was 1 week behind. * remove redundant constructor * remove hack and use a proper event to prevent updated_at from changing * use self.assertEqual instead of assert commit 16ae0aa3d8a30a75e1cb72daaa0ed8691e46c4dd Author: Levko Kravets Date: Tue Nov 20 11:06:09 2018 +0200 getredash/redash#2901 Fix docs links (#3102) commit 68ada7b590ce359f6fccc8a548ebca33b62d936b Author: Arik Fraimovich Date: Tue Nov 20 10:04:42 2018 +0200 UI for the feature flag of the share edit permissions feature (#3077) * Remove unused settings. * Add: UI feature flag for sharing permissions * Revise feature flag message commit 9e745ef6489f396da2f8d7aaf85abfe6567e769b Author: San Date: Tue Nov 20 15:48:24 2018 +0800 Delete redundant regex segment (#3100) commit ee0d7f5ec9efd03dcd3415980ca2eade81fbab38 Author: Allen Short Date: Tue Nov 20 06:06:32 2018 +0000 force angular to update query editor properly (re #3098) (#3099) commit e36853ca84e6d8431a06899c8aab455ad6c15bcc Author: Levko Kravets Date: Mon Nov 19 12:33:05 2018 +0200 Tags autocomplete: some tags not shown on search (#3094) * getredash/redash#3052 Tags autocomplete: some tags not shown on search * getredash/redash#3052 CR1 commit d43b35ba6f9e3b8ee013062cc25ce6c9c165ea25 Author: YOSHIDA Katsuhiko Date: Sun Nov 18 18:21:00 2018 +0900 Change Standard SQL as the default (#3085) commit 6e4f0ccee8513cdba70a7a97cf5f51ff0c80d5cf Author: Topher Cyll Date: Sun Nov 18 04:05:18 2018 -0500 Bubble chart marker size override was clobbering seriesColor. (#3063) Colors can now be set for bubble charts in UI. commit 0ce7772aa356daebc9fc80f72e95dbb53f03fa9c Author: Vladislav Denisov Date: Thu Nov 15 23:11:43 2018 +0300 clickhouse: added WITH TOTALS option support (#3083) commit f6ef38479c915d5cfd967c4e7f200044f76a5a3c Author: San Date: Fri Nov 16 04:08:02 2018 +0800 support tel, sms, mailto links in the query result (#3084) commit bf85ddaaffa125a7474d87690f5a2cd97be1613b Author: Arik Fraimovich Date: Thu Nov 15 08:58:30 2018 +0200 Always use basic autocomplete. (#3079) commit 8bb96c8c9170b016473745f41466cf706405588e Author: Arik Fraimovich Date: Wed Nov 14 15:43:34 2018 +0200 Fix: URL data source shouldn't require URL. (#3078) Closes #2919. commit 42b05cee00dab3b73e6275bf50df91796a8968eb Author: Filipe Veloso Date: Wed Nov 14 10:27:19 2018 -0200 Update docker-compose.yml (#2905) * Update docker-compose.yml jut updating docker-compose dev to version 3, any special reason to keep redis on 3? and pg on 9.5? I could also add a volume to pg, any reason not to do so? * rollback to redis 3 and pg 9.5 due to consistency in project defaults * Configure volume directly in worker service. commit d0fd02123a3ca1a8112f666b4206e40cfadf5598 Author: Anton Burnashev Date: Wed Nov 14 09:44:38 2018 +0100 Add white-space padding to separators in the footer (#3076) (#3076) Closes #3075 commit e34203dac3f1977cbf219bc0b29119d0db01ce9d Author: Takuya Arita Date: Tue Nov 13 23:45:40 2018 +0900 Remove only Redash containers (#3073) commit c2bd8518a68c87679a0834d678f08c4a13be1bbd Author: koooge Date: Mon Nov 12 17:06:25 2018 +0900 Makefile: Add make targets for test (#3032) commit 46363ccc70152efae0ac8a650eca19450476d0c5 Author: Levko Kravets Date: Mon Nov 12 08:50:44 2018 +0200 Table visualization horizontal scrollbar should not be always visible (#3061) commit 5e1512e777ec2fe056f227920b0748808f6a632b Author: Levko Kravets Date: Thu Nov 8 22:54:08 2018 +0200 Mustache: don't html-escape query parameters values (#3058) commit 188c045fdb6366eb203d7520bb55ab914fa2d7d7 Author: Arik Fraimovich Date: Thu Nov 8 11:20:05 2018 +0100 Add Kylin logo (#3054) commit 57d921dc2b44fb4dcb68235b4668ef1fde2ce503 Author: Omer Lachish Date: Thu Nov 8 11:48:45 2018 +0200 Druid query runner (#3047) * add Druid query runner skeleton * enable Druid only if package is available * add Druid * remove redundant override * correct configuration schema * implements run_query * implement get_schema * remove username and password * fix small lint issues * proper indentation * add correct type mapping commit df0804c8fd97c7ec5ba609587a6a7a3fa1361c50 Author: Xin Bai <1145490031@qq.com> Date: Thu Nov 8 17:24:05 2018 +0800 Add Kylin plugin for SQL query (#2936) commit c289dde8067c17b2f259128256e6a7f98abb5906 Author: Alexander Leibzon Date: Thu Nov 8 11:18:33 2018 +0200 Google analytics fix fixes #2965 (#3008) * add PagerDuty as an Alert Destination * remove comments * add unknown state handling * fixes * revert setup.sh * Remove test method. * resolves #2965 * more elegant, as per Arik's suggestion * Add missing whitespace. commit b7cadca3b72d9028d5c6d0b61644f662f048e805 Author: Levko Kravets Date: Thu Nov 8 11:17:18 2018 +0200 Edit-in-place component ignored isEditable flag and didn't work on Groups page (#3049) commit 43f82007070e3ad5a5ff16960f49faf6872915bb Author: Sami Jaktholm Date: Thu Nov 8 10:53:04 2018 +0200 feat(redshift): hide tables the configured user cannot access (#2866) The SVV_COLUMNS table used to determine the tables of a Redshift database includes all tables, even those the current user cannot access, by default. These tables clutter the schema browser and make it harder for users to determine which tables they should have access to. These changes modify the Redshift query runner so that tables the configured user cannot access are filtered out from the database schema. The checks are two-fold: * First, the query uses HAS_SCHEMA_PRIVILEGE to check if the current user has USAGE rights on a schema the given table belongs to. This privilege is required to access any of the tables in a schema. * Second, the query tries to determine if the current user has SELECT access to the given table. Two cases need to be considered here: * First, we need to check if the table is part of an external schema. Access to tables in external schema is controlled at schema level - you cannot grant or revoke access to specific external tables. Additionally, the HAS_TABLE_PRIVILEGE returns an error if it is asked to give a verdict for an external table. Hence, the query checks if the schema a specific table belongs to is an external schema and if it is, the table is included in the list (if we got here the user already had USAGE on the given schema). This check short-circuits the table-level access check for external tables which means they are never passed to HAS_TABLE_PRIVILEGE(). * Then, if the table was not part of an external schema, the HAS_TABLE_PRIVILEGE() function is used to determine if the user has SELECT access to the given table. The table is included in the schema if this check passes. Together this condition ensures that tables the user definitely cannot access are not included in the schema browser. These changes have been tested to work in an environment that includes normal and external schemas, normal and late-binding views, and normal and external tables. commit a1b580bba6a52a2e9491e811c6ab194ca4fe1edc Author: Arik Fraimovich Date: Wed Nov 7 17:21:31 2018 +0100 Fix Docker Compose version number in Cypress config (#3051) * Update Docker compose version * Experiment with Docker-Composeless CI build * Switch back to Docker compose based tests commit 19d0313ea231c66f002252f1394baa5f2b0ca23b Author: Zsolt Kocsmárszky Date: Wed Nov 7 16:58:15 2018 +0100 Fixing tag issues (#3006) * Add title="" for tags * Fix lines * Fix long tag and overlaying tag issues on queries commit 667fe43e23d2a09a7330e4679278a992da5310df Author: Arik Fraimovich Date: Wed Nov 7 16:57:37 2018 +0100 Revert "address tag display on query list page" (#3050) * Revert "remove pytest_watch (#3048)" This reverts commit 096eba387644b2cbe3e4c314c223417f53ad0f0e. * Revert "address tag display on query list page (#2803)" This reverts commit 99115a12e60611639365cac5f378e05fe1b951bb. commit 096eba387644b2cbe3e4c314c223417f53ad0f0e Author: Omer Lachish Date: Wed Nov 7 17:49:41 2018 +0200 remove pytest_watch (#3048) commit 99115a12e60611639365cac5f378e05fe1b951bb Author: Alison Date: Wed Nov 7 09:12:31 2018 -0600 address tag display on query list page (#2803) * address tag display on query list page * character limit tags in css * updates to tags on levko's feedback commit 7d601cbbc963cb3ae2ee40e759ffad65bb39010f Author: Gabriel Dutra Date: Wed Nov 7 11:37:08 2018 -0200 Cypress based E2E tests (#3019) commit bf6a09c5aa6f52ce362f106f1c6336115cc40967 Author: GitSumito Date: Wed Nov 7 00:45:39 2018 +0900 CLI sort (#3041) commit 99967e720fd00ef2349af02598f8970346091611 Author: Yossi-a Date: Mon Nov 5 04:47:42 2018 +0200 Sort columns with undefined values (#2745) * sort should treat undefine value as the minimal value * explicit undefined check commit 27f489de206521e1e912c47845ae2d43adaba60e Author: Arik Fraimovich Date: Sun Nov 4 12:12:13 2018 +0200 Build docker image on master branch. (#3039) commit 46941d3aa159131c216b6e2199e4fe12394224dd Author: yoavbls Date: Thu Nov 1 15:58:50 2018 +0200 Update Flask-Admin to 1.5.2 (#3036) I don't know if someone uses flask-admin but I upgraded it because of this bug: https://github.com/flask-admin/flask-admin/issues/1588 In 1.4.2 you cant add and edit records/ commit 60c230add7277b7af741b2ec769e9cd177a34de2 Author: Levko Kravets Date: Thu Nov 1 15:57:39 2018 +0200 getredash/redash#3034 Postgres query runner: handle NaN/Infinity values (#3035) commit 0784a0c6f5bfd49baa965ccf0ca0d95737f0926d Author: Takuya Arita Date: Wed Oct 31 18:05:17 2018 +0900 Add some tests for Query Results (#3031) commit 9288d89248c2b39a922a2bf1fcbac8d10bbc49a9 Author: Zsolt Kocsmárszky Date: Mon Oct 29 21:09:49 2018 +0100 Fix query result section (#2980) commit 391fbe130bdf96e1c36aeb2144ceadcacc10309e Author: Levko Kravets Date: Mon Oct 29 22:08:35 2018 +0200 getredash/redash#2998 Charts lose responsive features after refreshing the dashboard (#3024) commit e25c8c41450a8d802c5e8e1f10d6d14f7cc8d0cd Author: Levko Kravets Date: Mon Oct 29 11:38:29 2018 +0200 getredash/redash#3022 Toolbox covers part of the chart (#3023) commit 57353d1b405a1068dada4c1de9d7329ea92112ec Author: Arik Fraimovich Date: Sun Oct 28 15:58:20 2018 +0200 Add -beta to version commit 7f4e08154fd3ac688219d056e9ec2297d9cebbcc Author: Arik Fraimovich Date: Sun Oct 28 15:56:32 2018 +0200 Bump version commit 500c82815b60e6dbbff7bd1c57647dfebe70ef57 Author: Arik Fraimovich Date: Sun Oct 28 15:31:27 2018 +0200 Add netlify config (#2999) commit 4a846f04e9aa04fbe2ab1591ce5a947cc2848dd6 Author: Arik Fraimovich Date: Sun Oct 28 11:11:11 2018 +0200 Add settings to import commit b1e9d87e2a67b502e39c039db98f8c84f6b2b851 Author: Takuya Arita Date: Sun Oct 28 17:40:07 2018 +0900 Apply query format options from settings (#2342) * Apply query format options from settings * Apply sqlparse format options via env-vars commit ab6ed7da34dd2797914382c435981450b7bf9d7a Author: Arik Fraimovich Date: Tue Oct 23 09:49:24 2018 +0300 Fix: setup.sh fails when run as root. (#2996) Closes #2979 commit 2e6883c5276b4e5774083439c80cf1b55a54780f Author: GitSumito Date: Sun Oct 21 17:40:07 2018 +0900 Add "Users" users are belong to into groups list (#2991) commit 4c44999b2c52b09beae5a419b24a7cc574fa3412 Author: YOSHIDA Katsuhiko Date: Sun Oct 21 17:39:37 2018 +0900 Fix an invalid prop type warning (#2992) commit 34c118cf83e1c2e40de40cb1f6aa255ba16bedb5 Author: deecay Date: Sun Oct 21 17:39:06 2018 +0900 Add: Heatmap chart visualization by Plotly (#2080) commit 38a89b9783439cca5253f0184e4e676e4927be5c Author: Arik Fraimovich Date: Sun Oct 21 11:38:47 2018 +0300 Table visualization: change default size to 25 and add more size options. (#2982) commit 6e836795b28e9fecd05bfc9b2e642f3a429bf248 Author: YOSHIDA Katsuhiko Date: Sun Oct 21 17:38:11 2018 +0900 Fix url scheme (#2994) commit 719fc41dd1cf0d3d81907cdde61f41fb6debe66c Author: YOSHIDA Katsuhiko Date: Sat Oct 20 21:33:31 2018 +0900 Add page size settings (#2993) Add page size settings. | name | default | description | | :---- | :------ | :---------- | | `REDASH_PAGE_SIZE` | 20 | How many items are displayed in one page as default. | | `REDASH_PAGE_SIZE_OPTIONS` | 5,10,20,50,100 | How many steps as page_size. | This feature has requested at the meetup in Japan. https://redash-meetup.connpass.com/event/101420/ commit 467ec201dac375fda655ef8263460f427e6647b2 Author: Arik Fraimovich Date: Fri Oct 19 19:04:02 2018 +0300 Add Jest based tests to our stack (#2985) * Add Jest packages * Add first test * Install eslint rules for jest & move deps to dev * Configure cirlce to run jest * package.json: Remove dev command * package.json: clean command * Don't autoload test files. * Fix: webpack-dev-server was recompiling all the files on every change * Update CircleCI step names commit 5ab143de41b2a169848b63541bc19222c94cb80f Author: koooge Date: Fri Oct 19 18:25:24 2018 +0900 Rearrange make target (#2989) commit 284e497483af6005a07e04e2bba85a0cef2b163e Author: Arik Fraimovich Date: Fri Oct 19 11:00:33 2018 +0300 Databricks updates: logo, name and enable by default (#2983) * Add Databricsk logo. * Enable it by default. * Rename to Databricks. commit c5613dddf1d78cb001e2bb590c21e83f16184bc1 Author: dmonego Date: Thu Oct 18 14:21:47 2018 -0400 Chnage: switch to Webpack 4 (#2933) commit 34fb3ac79f11cf2055f86cb359a2ce068c3c6c96 Author: Arik Fraimovich Date: Thu Oct 18 17:33:58 2018 +0300 Change: add timeout to destination requests. (#2960) commit 5f58c328f16593756a6af8ca46be8807776cc787 Author: Arik Fraimovich Date: Thu Oct 18 17:33:24 2018 +0300 MongoDB: skip system collections when loading schema. (#2961) commit 7d1dbb87dbe83d13f1ad1d271d4dab96fea8cbcb Author: Arik Fraimovich Date: Thu Oct 18 17:32:43 2018 +0300 Change: update MongoDB requirements to support srv. (#2962) commit 45f4d462451f1cadea06fd80cde531c649ba2380 Author: GitSumito Date: Thu Oct 18 23:32:21 2018 +0900 Add "Groups" users are belong to into users list (#2967) commit 44d05c35ac58f7a786ba2932e5d5269b8936ea20 Author: Arik Fraimovich Date: Thu Oct 18 17:31:48 2018 +0300 Presto query runner improvements (#2968) * Presto: support for setting protocol (http/https). * Presto: safe loading error message. commit edd2cb85f7820510ab93526234839a18362c7624 Author: Arik Fraimovich Date: Thu Oct 18 14:59:00 2018 +0300 Update CHANGELOG.md commit 6c364369bb0eb98e2191c2e502fed72abe5a74c7 Author: Hiroka Zaitsu Date: Thu Oct 18 15:43:28 2018 +0900 Fix: TreasureData data source - deduplicate column names (#2867) * Fix: TreasureData data source - deduplicate column names * Maping types commit 869841b2ac387bea3e1c04e3053b5eb343a80c2a Author: YOSHIDA Katsuhiko Date: Thu Oct 18 03:55:58 2018 +0900 Preventing open redirection (#2906) * Prevent open redirection attack * Add redirection url after logging in test * Sanitize url just before redirecting it * Consider when next parameter is None commit c71f722552144cf73c38438ad45982b509fa3d6b Author: Arik Fraimovich Date: Tue Oct 16 15:23:00 2018 +0300 Query Results query runner improvements: (#2969) - Show meaningful error when failing to create table. - Quote column names to allow more characters types. commit af3a1e00c6ccf583da73b37d182a9405ecb5f0ab Author: Jannis Leidel Date: Tue Oct 16 10:38:37 2018 +0200 Fix #2757 - Use full text search ranking when searching in list views. (#2798) This applies to the queries, dashboard and users views. commit 5b2ec81e65e270595fca37366fb03c380da87b5d Author: Gabriel Dutra Date: Mon Oct 15 17:08:18 2018 -0300 Fix no tags shown when having empty set (#2964) commit 0008e5803b487f07ed555aaed2074b55164db115 Author: Vladislav Denisov Date: Mon Oct 15 20:06:16 2018 +0300 clickhouse: move timeout to params (#2956) * clickhouse: timeout moved to params * clickhouse: use get() method for timeout commit e1c1f67abb3745bf0122fc7949aea988f2da660a Author: Arik Fraimovich Date: Mon Oct 15 20:05:40 2018 +0300 Add: option to auto reload widget data in shared dashboards. (#2959) commit 30283235a4f471e5d5cd0fe55349b314dd83f622 Author: Marina Samuel Date: Mon Oct 15 13:05:07 2018 -0400 Fix tarball build failure. (#2963) commit 845e33b3968d68d074e280002f76a4b09ef53053 Author: Levko Kravets Date: Mon Oct 15 19:59:05 2018 +0300 Query page layout improvements for small screens (#2922) * getredash/redash#2796 Make entire page scrollable on small screens; improve metadata block * getredash/redash#2796 Improve query page header layout; fix small bugs (margins, etc.) commit 17baa6618821ceca3306ca6fce00d5f5f3fe2e26 Author: Arik Fraimovich Date: Mon Oct 15 17:45:22 2018 +0300 Show "Add description" only after saving the query. (#2958) Closes #2897 commit 5df7bd12c9e0977fea408126f69d5cec12820d61 Author: Arik Fraimovich Date: Mon Oct 15 17:38:22 2018 +0300 Fix: apply missing CSS classes to EditInPlace component. (#2957) commit e14c8b61a0141615704db04dffbd5c5f7ee98450 Author: Nicolas Ferrandini Date: Mon Oct 15 16:13:39 2018 +0200 Add DB2 as a data source using ibm-db python package (#2848) * Add DB2 as a data source using ibm-db python package * fix some codeclimate issue * fix long line and missing white space * Manage case of bad import * Add DB2 query_runner as default query runner * Fixed minor PEP8 rules commit a8a3ec66fd730ca260e903e95db39490b26d550c Author: Arik Fraimovich Date: Mon Oct 15 16:01:38 2018 +0300 Bring back fix to Box plot hover. (#2941) commit a4b9c2da122b806504931c3e7e00a75315086c67 Author: GitSumito Date: Mon Oct 15 21:57:51 2018 +0900 fixed https://github.com/getredash/redash/issues/2950 (#2951) * fixed https://github.com/getredash/redash/issues/2950 * fixed test code * Effective -> Active. thank you @kravets-levko commit e6146dae0fb6e4b60ee42cf270dfb09c7a818f9a Author: Vladislav Denisov Date: Mon Oct 15 15:03:02 2018 +0300 Clickhouse fixes (#2953) * clickhouse: avoid last line with comment in query * clickhouse: add request timeout commit bd3fe880a4831c6ddf798822973a7b8d7d9267c3 Author: Levko Kravets Date: Mon Oct 15 14:51:13 2018 +0300 Add missing default "extensions" directory (webpack fails to build without it) (#2952) commit 02e919c39bd495cb9dd2ec1021b3225dcf42b213 Author: Marina Samuel Date: Sun Oct 14 08:53:39 2018 -0400 Closes #2565: Add frontend extension capability. (#2799) commit 99c73aef2d925cac269dbfd2b763b6961f68992f Author: Arik Fraimovich Date: Sun Oct 14 14:39:52 2018 +0300 Update snowflake_connector_python version (#2946) commit be377b5f594ba1715c429f0182e3ea2e00e22a9b Author: Ralphilius <4253551+ralphilius@users.noreply.github.com> Date: Sun Oct 14 15:23:20 2018 +0700 Add Counter label (#2900) * Add Counter label * Update index.js * Added visualization name as placeholder * Backward-compatible for visualization name as label commit 6b11ae43125d352ffd2fa8f193ef24bf6c745a72 Author: Zsolt Kocsmárszky Date: Sun Oct 14 10:00:27 2018 +0200 Design refinements (#2927) * Fix search size on smaller tablet size * Less prominent tag counter * Fix hiding logo * Add missing space between icon and button text * Different embed icon * Revert embed icon to its original * Better edit source icon + markup cleanup commit 9021977a54b591f2a3f60ec355cc2207f905fd2e Author: YOSHIDA Katsuhiko Date: Sun Oct 14 16:49:11 2018 +0900 Fix admin api recording (#2937) commit 9c8d06578ae7e2a807179d22829443aebc9c97d6 Author: Sami Jaktholm Date: Sun Oct 14 10:42:31 2018 +0300 feat: add support for expanding dashboard visualizations (#2824) * feat: add support for expanding dashboard visualizations These changes implement support for expanding a dashboard visualization into a larger modal dialog. This is useful if you have a dashboard with lots of small widgets and want to inspect one of the widgets more closely. In the past, this would've required you to navigate to the query page to see a larger version of the visualization. With these changes, visualizations can be expanded right from the dashboard. The implementation is simple as it just renders the visualization into a modal dialog. Other parts of the widget (e.g. parameters) are not included in this dialog. * chore(widget-dialog): use query-link widget to render title This reduces code duplication a bit. The link is made read-only as navigation doesn't close the modal dialog. * fix: make ui-select dropdown z-index > modal dialog z-index in dashboard page Otherwise the dropdown renders behind the modal dialog if filter value is changed from the modal view of a widget. commit 114beb24806572741a80cb455bf3e98a40f8448b Author: YOSHIDA Katsuhiko Date: Sun Oct 14 16:39:08 2018 +0900 Auto focus tag input (#2938) commit e97a5cbb29e3fe5ffea05d5fc4a9ca70f8801cee Author: Alexander Leibzon Date: Sun Oct 14 10:35:39 2018 +0300 add PagerDuty as an Alert Destination (#2903) commit e87efc8bc30cefa0176fea7f12169cf202452727 Author: Alexander Leibzon Date: Thu Oct 11 21:07:20 2018 +0300 fixes #2924 (#2931) Google Spreadsheets: support for open by url commit be7f601d21cf2b8748ec918b72323caab8da30ab Author: Arik Fraimovich Date: Thu Oct 11 14:12:28 2018 +0300 Speed up builds by skipping installing requirements_all_ds.txt in CI unit tests (#2928) * Speed up builds by skipping requirements_all_ds.txt * Update docker compose file version * Start services before running commands * Add boto and Athena dependencies to requirements_dev.txt commit 9b59d10677717796c0ee91bd2420e9fe5b083270 Author: Levko Kravets Date: Thu Oct 11 12:27:28 2018 +0300 Use Plotly's function to clean y-values (x may be category or date/time) (#2872) commit a40669e07f0fa3829b5313f2834c390a8b79a89e Author: Levko Kravets Date: Thu Oct 11 11:23:40 2018 +0300 getredash/redash#2875 Update plotly.js; some cleanup; fix chart legend issue in horizontal mode (#2902) commit 0bcf5d4be761ceb8d94b47bb636ef2a6afc4db45 Merge: 6ea03e58 8bc96764 Author: Levko Kravets Date: Thu Oct 11 09:08:31 2018 +0300 Merge pull request #2929 from combineads/fix-date-filter Fix: date value in a filter is duplicated. commit 8bc96764a6c3aca5939ab3477c19f7be86845273 Author: combineads Date: Thu Oct 11 14:56:57 2018 +0900 Fix: date value in a filter is duplicated. commit 6ea03e58b41cb543c550348bf9d4923b7f4ce047 Author: Niko Eckerskorn Date: Thu Oct 11 03:13:48 2018 +1100 Address edgecase when retrieving Glue schemas for Athena query runner. (#2868) Fixes getredash/redash#2858 commit 94801665abce630a4441339753ee0880935c3330 Author: Gabriel Dutra Date: Wed Oct 10 09:07:11 2018 -0300 Fix output file name not changing after rename query (#2917) commit aa12151e191176c4899bc3fd990c76d17843bc4f Author: Gabriel Dutra Date: Wed Oct 10 08:56:31 2018 -0300 Fix export query results output file name (#2916) - regexp `/ /g` will seek for all space ocurrences, not only the first commit c2429e92d2a5dd58cbe378b9cc06f3be969f747e Author: Jannis Leidel Date: Tue Oct 9 15:38:06 2018 +0200 Consistently use simplejson to loading and dumping JSON. (#2817) * Consistently use simplejson to loading and dumping JSON. This introduces the new functions redash.utils.json_dumps and redash.utils.json_loads and simplifies the custom encoder setup. UUIDs are now handled by the default encoder, too. Fixes #2807. Use string comparison in parse_boolean instead of the (simple)json module. commit 5ffc85c066e5f1f156e736b5d7262ca210f5495f Author: Jannis Leidel Date: Mon Oct 8 12:06:58 2018 +0200 Extend menu item text a bit for visual consistency. commit fad757c878aad6d2d0e7ad5cb814b2f0b771cbe5 Author: Jannis Leidel Date: Mon Oct 8 12:05:25 2018 +0200 Don’t show “Add to dashboard” in dropdown to unsaved queries. commit 3351a281eea748f2cf2c8f16295ac6de875f40e4 Author: Jannis Leidel Date: Mon Oct 8 12:03:54 2018 +0200 Fix webpack build error about BigMessage. (#2910) commit 1f0053f531a7455a5aa866bbeda34f5991e29877 Author: Arik Fraimovich Date: Mon Oct 8 10:05:16 2018 +0300 MySQL: hide sys tables (#2909) commit 935dc3836087ecc83e735d4c036ff49507aaed49 Author: Arik Fraimovich Date: Mon Oct 8 09:41:15 2018 +0300 Update setup files: (#2908) * Remove use of newgrp * Updated packer configuration commit bfef7fae93ebb1fbfb464021afd295620d81de82 Author: Arik Fraimovich Date: Mon Oct 8 09:39:57 2018 +0300 Remove unused dependencies. (#2907) Closes #2782 commit da6d456f6feb4c7c385e44e7efc9abb8a13a5deb Author: cclauss Date: Fri Oct 5 12:48:01 2018 +0200 CircleCI: Flake8 tests passing on Legacy Python and Python 3 (#2881) commit c19199c2fbb29c6c9d4c4df47382af0b3e7b2976 Author: Arik Fraimovich Date: Thu Oct 4 12:34:03 2018 +0300 Add margin between format and autocomplete buttons (#2899) commit 1e78861f85bb92e6aa16746b8bcce52574498e6b Author: Arik Fraimovich Date: Thu Oct 4 12:27:36 2018 +0300 Move Ant styles into a central location. (#2898) This is to ensure that we include our override after loading Ant's styles. commit 10bc5a0bf66500f1036166027b02609f04b6d82d Author: Arik Fraimovich Date: Thu Oct 4 12:01:38 2018 +0300 Remove misplaced bracket. (#2894) commit 313af904df75f2c665ad0e0f488431204ddf8f22 Author: Marina Samuel Date: Thu Oct 4 02:07:58 2018 -0400 Add ability for extensions to add periodic tasks. (#2740) commit 8c478087a91f770f51517f04f37d90068571a9e3 Author: Allen Short Date: Wed Oct 3 19:25:19 2018 +0000 Rewrite query editor to React (#2636) commit ccac41c6d4d877f88e3c2291679390c11103d4fd Author: Arik Fraimovich Date: Tue Oct 2 16:22:47 2018 +0300 Fix: JS build breaks because registerAll tries to run EditInPlace component (#2886) commit 69635f2c401406e629bb0a68e7d117d920a2dc0d Author: Jannis Leidel Date: Tue Oct 2 15:11:01 2018 +0200 Rename Yandex Metrika to Metrica. (#2884) Fix #2874. commit 1867ea50bbf702270f77209bbf217ffd44b8c300 Author: yoavbls Date: Tue Oct 2 16:05:41 2018 +0300 Add option to query cached results (#2855) commit c64d5ef6c05dd3e393ac3c56a6a959819562b395 Author: Jannis Leidel Date: Mon Oct 1 21:29:20 2018 +0200 Fix #2876 - Remove accidental query-result-link component from 'Add to dashboard link.' (#2883) commit e3a63899d35a981ff1b1aad0ff192ba19b816aed Author: Alison Date: Mon Oct 1 04:11:32 2018 -0500 Add ability to search table column names in schema browser (#2681) commit 4685887fe549a4ba7248aa4bb11a146d41e4791b Author: Jannis Leidel Date: Fri Sep 28 21:55:47 2018 +0200 Fix name of edit-in-place React component. commit f103357e600755b08f933daf210479a80f2e5193 Author: Arik Fraimovich Date: Fri Sep 28 22:45:13 2018 +0300 Fix: wrong reference (EditInPlaceText -> EditInPlace) commit 11738f73ac937204ec7d256eb082bcb3e8a12701 Author: Jannis Leidel Date: Thu Sep 27 17:31:31 2018 +0200 Removed redundant exception handling since execute_query task handles that. commit d07c4f969be0097ad66c201bdf85f67896a31f85 Author: Allen Short Date: Wed Feb 7 20:01:51 2018 +0000 Support authentication for the URL query runner. Adds a new BaseHTTPQueryRunner class and tests. commit 505aafbce364eb2bf95ae38cce41cad8671be5c1 Author: Allen Short Date: Fri Sep 28 19:30:10 2018 +0000 Convert edit-in-place component to React (#2637) commit b7656938797dacda97545d69f8e628e75dd62202 Author: Marina Samuel Date: Fri Sep 28 15:28:30 2018 -0400 Upgrade Celery to 4.2.1. (#2773) commit 4620fed0cf20306407abcf0a1a318f0af33700f6 Author: Jannis Leidel Date: Fri Sep 28 16:24:13 2018 +0200 Use server side sort order for tag list and show count of tagged items. (#2833) * Use tag list ordering from backend. This basically stops resorting the tag list on the client side and use the already existing (and correct) descending sort order bu tag usage count from the backend. * Show count of tagged items in tag list. commit 48ad1d2dce8ebeb6a3893cba9331eccc175bff4c Author: Arik Fraimovich Date: Fri Sep 28 17:18:41 2018 +0300 Add v5.0.1 to the CHANGELOG. commit f2c323a0897adec943427d533d6f1a871aca26c8 Author: Arik Fraimovich Date: Fri Sep 28 11:52:14 2018 +0300 Disable integration tests The integration tests are currently not failing and providing false positives when running them. I'm disabling this until the test suite is more stable. @jrbenny35 @jezdez commit ec17cc7eabdadf057a98bbf0684cc4c5ef077c5f Author: Levko Kravets Date: Fri Sep 28 11:26:37 2018 +0300 getredash/redash#2854 Widget titles wrong rendering on public dashboards (#2870) commit 6c7bbe9041304c546cfac2590590f1b344d894f0 Merge: 551b0222 2b0e6e9e Author: Arik Fraimovich Date: Thu Sep 27 21:47:56 2018 +0300 Merge branch 'master' of github.com:getredash/redash commit 551b0222c4eff0ac21e7f71567b59902dbe4c422 Author: Arik Fraimovich Date: Thu Sep 27 21:47:45 2018 +0300 Cleanup packer configuration commit 2b0e6e9e790c1f1c9b782887e1ca871726437bf5 Author: Jannis Leidel Date: Thu Sep 27 17:06:26 2018 +0200 Refactor list based controllers. (#2790) This reduces the code duplication between the dashboard, user and queries list pages and normalizes many of the APIs between them. This also: - allows sorting query favorites - adds a pagination size select to the dashboard list - fixes a bunch of UI inconsistencies between the queries and dashboards list (e.g. margins) The new ListCtrl class is subclassed in the various specific page controllers and extended as needed. New list pages can make use of the same pattern in the future. This also adds some missing event recordings from 34e39eda4a02916380b47c1e20849a372926e083. commit 4727c192539c0f7b29092a786ca270e3e0540e8f Author: Levko Kravets Date: Thu Sep 27 13:27:10 2018 +0300 getredash/redash#2796 Improve counter text scaling (#2840) commit 2ff4d07e83e5618d42f7b12962bee47214ad73fb Merge: 1997f53f 28fbc2ae Author: Arik Fraimovich Date: Thu Sep 27 12:34:28 2018 +0300 Change placement (right/bottom) of chart legend depending on chart width (#2852) Closes getredash/redash#2796. commit 1997f53f40a44e37c0c6736d315ebe2943306585 Author: Arik Fraimovich Date: Thu Sep 27 10:36:48 2018 +0300 Fix CircleCI setup for release branches. (#2859) commit c03b5d51b7870ac3948797da936b1d12b8167ade Author: Jannis Leidel Date: Thu Sep 27 09:20:07 2018 +0200 Simplified data source resource. Refs #2856. commit 197665bb6af92de8300e75c4af60432ecf0b4437 Author: yoavbls Date: Thu Sep 27 10:15:36 2018 +0300 Fix bug in DataSourceResource load (#2857) commit 28fbc2ae624483cffa04630591801c58c0ba1378 Author: Levko Kravets Date: Wed Sep 26 18:46:49 2018 +0300 getredash/redash#2796 Change placement (right/bottom) of chart legend depending on chart width commit ea1c4ca85c601427d5077295d367c8ab23d34835 Author: Alexey Korobkov Date: Wed Sep 26 23:17:48 2018 +0500 Add auth via JWT providers (#2768) * authentication via JWT providers * add support for IAP JWT auth * remove jwt_auth Blueprint and /headers endpoint * fix pep8: imports commit 588e0cce43d27faa8b8196ac0d4cc5c8ed7c36e4 Author: Alison Date: Wed Sep 26 10:32:38 2018 -0500 Add autocomplete toggle (#2780) commit 8a50351520067fc3af6593263d8e1cc376292443 Author: Alison Date: Wed Sep 26 10:29:38 2018 -0500 Add ability to add viz to dashboard from query edit page (#2767) commit 34e39eda4a02916380b47c1e20849a372926e083 Author: Alison Date: Wed Sep 26 10:17:46 2018 -0500 Port moving events serverside (#2766) commit 28a8525ce3fb24d303132c52109b5d62c67fae4f Author: Alison Date: Wed Sep 26 10:07:03 2018 -0500 Add databricks query runner (#2747) Fixes #2685. commit 5e70f9c04a864feb8165058c3201c793cb66604e Author: Arik Fraimovich Date: Tue Sep 25 21:08:46 2018 +0300 Update README.md commit a05b5ba68deca88bfbed3eebf462d84de5e96d96 Author: Arik Fraimovich Date: Tue Sep 25 21:08:24 2018 +0300 Docker based setup scripts (#2850) commit 40ba66c58eae3a1181f8f2e9e4e9555bcdc632ef Author: Dan VerWeire Date: Tue Sep 25 12:12:04 2018 -0400 Fix invalid reference to alert.to_dict() in webhook (#2849) --- .circleci/config.yml | 116 +- .circleci/docker-compose.circle.yml | 2 +- .circleci/docker-compose.cypress.yml | 47 + .circleci/docker_tag | 9 +- .circleci/update_version | 3 +- .dockerignore | 2 + .github/ISSUE_TEMPLATE.md | 34 - .github/ISSUE_TEMPLATE/---bug_report.md | 34 + .github/ISSUE_TEMPLATE/--anything_else.md | 17 + .gitignore | 2 + CHANGELOG.md | 226 + CONTRIBUTING.md | 6 +- Dockerfile | 8 +- Dockerfile.cypress | 11 + Makefile | 51 + README.md | 5 +- bin/bundle-extensions | 39 + bin/flake8_tests.sh | 7 + bin/get_changes.py | 3 +- bin/release_manager.py | 4 +- client/.eslintrc.js | 5 +- .../app/assets/images/db-logos/databricks.png | Bin 0 -> 17187 bytes client/app/assets/images/db-logos/db2.png | Bin 0 -> 13397 bytes client/app/assets/images/db-logos/druid.png | Bin 0 -> 11452 bytes .../app/assets/images/db-logos/hive_http.png | Bin 0 -> 25212 bytes client/app/assets/images/db-logos/kylin.png | Bin 0 -> 24361 bytes client/app/assets/images/db-logos/mongodb.png | Bin 15967 -> 9299 bytes client/app/assets/images/db-logos/rockset.png | Bin 0 -> 6768 bytes .../assets/images/destinations/chatwork.png | Bin 19201 -> 11523 bytes .../assets/images/destinations/mattermost.png | Bin 27133 -> 12261 bytes .../assets/images/destinations/pagerduty.png | Bin 0 -> 8408 bytes .../assets/less/inc/bootstrap-overrides.less | 7 + client/app/assets/less/inc/edit-in-place.less | 9 - client/app/assets/less/inc/list-group.less | 138 +- .../inc/visualizations/counter-render.less | 73 +- client/app/assets/less/main.less | 6 +- client/app/assets/less/redash/ant.less | 29 + client/app/assets/less/redash/query.less | 147 +- .../assets/less/redash/redash-newstyle.less | 45 +- .../app/assets/less/redash/tags-control.less | 13 + client/app/components/AutocompleteToggle.jsx | 43 + client/app/components/BigMessage.jsx | 2 + client/app/components/DateInput.jsx | 1 + client/app/components/DateRangeInput.jsx | 4 +- client/app/components/DateTimeInput.jsx | 1 + client/app/components/DateTimeRangeInput.jsx | 5 +- client/app/components/EditInPlace.jsx | 92 + .../app/components/{footer.js => Footer.jsx} | 17 +- client/app/components/Footer.test.js | 16 + .../app/components/NoTaggedObjectsFound.jsx | 12 +- client/app/components/QueryEditor.jsx | 283 + .../__snapshots__/Footer.test.js.snap | 37 + .../alerts/alert-subscriptions/index.js | 3 + .../app/components/app-header/app-header.html | 4 +- client/app/components/app-header/index.js | 4 +- client/app/components/app-view/index.js | 12 +- .../components/cancel-query-button/index.js | 8 +- .../dashboards/add-widget-dialog.js | 2 + .../dashboards/edit-dashboard-dialog.js | 2 + .../components/dashboards/gridstack/index.js | 2 + .../components/dashboards/widget-dialog.html | 12 + .../components/dashboards/widget-dialog.less | 8 + client/app/components/dashboards/widget.html | 11 +- client/app/components/dashboards/widget.js | 30 +- client/app/components/dynamic-form.html | 11 +- client/app/components/dynamic-form.js | 3 + .../dynamic-table/default-cell/index.js | 3 + .../dynamic-table/dynamic-table-row.js | 7 +- .../dynamic-table/dynamic-table.html | 2 +- .../dynamic-table/dynamic-table.less | 2 +- client/app/components/dynamic-table/index.js | 27 +- .../dynamic-table/json-cell/index.js | 4 +- client/app/components/edit-in-place.js | 97 - .../email-settings-warning/index.js | 5 +- .../app/components/empty-state/empty-state.js | 2 + client/app/components/error-messages.js | 5 +- .../app/components/favorites-control/index.js | 1 + client/app/components/filters.js | 3 +- .../components/groups/edit-group-dialog.js | 2 + client/app/components/groups/group-name.js | 8 +- client/app/components/overlay.js | 2 + client/app/components/page-header/index.js | 6 +- client/app/components/paginator.js | 2 + client/app/components/parameters.js | 26 +- .../components/permissions-editor/index.js | 10 +- .../permissions-editor.html | 27 +- client/app/components/proptypes.js | 16 + .../queries/alert-unsaved-changes.js | 3 + .../app/components/queries/api-key-dialog.js | 2 + .../components/queries/embed-code-dialog.js | 6 +- client/app/components/queries/query-editor.js | 160 - .../components/queries/query-results-link.js | 7 +- .../app/components/queries/schedule-dialog.js | 6 +- .../components/queries/schema-browser.html | 6 +- .../app/components/queries/schema-browser.js | 15 + .../components/queries/visualization-embed.js | 3 + client/app/components/query-link.js | 7 +- client/app/components/rd-tab/index.js | 2 + client/app/components/rd-time-ago.js | 3 + client/app/components/rd-timer.js | 3 + client/app/components/settings-screen.js | 3 + client/app/components/sort-icon.js | 3 + client/app/components/tab-nav/index.js | 3 + .../tags-control/DashboardTagsControl.jsx | 12 + .../tags-control/ModelTagsControl.jsx | 44 + .../tags-control/QueryTagsControl.jsx | 12 + .../components/tags-control/TagsControl.jsx | 82 + .../tags-control/TagsEditorModal.jsx | 103 + .../tags-control/control-template.html | 5 - client/app/components/tags-control/index.js | 68 - .../tags-control/modal-template.html | 18 - .../app/components/tags-list/tags-list.html | 6 +- client/app/components/tags-list/tags-list.js | 7 +- client/app/components/transclude-replace.js | 26 + client/app/components/type-picker.html | 2 +- client/app/components/type-picker.js | 3 + client/app/components/visualization-name.js | 18 - client/app/config/dashboard-grid-options.js | 3 + client/app/config/index.js | 19 +- client/app/directives/autofocus.js | 3 + client/app/directives/compare-to.js | 3 + client/app/directives/index.js | 3 + client/app/directives/resizable-toggle.js | 3 + client/app/directives/resize-event.js | 3 + client/app/directives/title.js | 3 + client/app/extensions/.gitkeep | 0 client/app/filters/datetime.js | 3 + client/app/filters/markdown.js | 3 + client/app/index.js | 2 +- client/app/lib/list-ctrl.js | 119 + client/app/lib/localOptions.js | 19 + client/app/lib/pagination/live-paginator.js | 14 +- client/app/lib/recordEvent.js | 25 + .../app/pages/admin/outdated-queries/index.js | 5 +- client/app/pages/admin/status/index.js | 3 + client/app/pages/admin/tasks/index.js | 3 + client/app/pages/alert/index.js | 5 +- client/app/pages/alerts-list/index.js | 7 +- .../app/pages/dashboards/dashboard-list.html | 37 +- client/app/pages/dashboards/dashboard-list.js | 103 +- client/app/pages/dashboards/dashboard.html | 9 +- client/app/pages/dashboards/dashboard.js | 48 +- client/app/pages/dashboards/dashboard.less | 4 +- .../dashboards/public-dashboard-page.html | 2 +- .../pages/dashboards/public-dashboard-page.js | 28 +- client/app/pages/data-sources/list.js | 7 +- client/app/pages/data-sources/show.js | 33 +- client/app/pages/destinations/list.js | 7 +- client/app/pages/destinations/show.js | 22 +- client/app/pages/groups/data-sources.js | 6 +- client/app/pages/groups/list.js | 6 +- client/app/pages/groups/show.js | 7 +- client/app/pages/home/index.js | 3 + client/app/pages/queries-list/index.js | 160 +- .../app/pages/queries-list/queries-list.html | 20 +- .../app/pages/queries/add-to-dashboard.html | 19 + client/app/pages/queries/add-to-dashboard.js | 62 + client/app/pages/queries/query.html | 229 +- client/app/pages/queries/source-view.js | 20 +- client/app/pages/queries/view.js | 76 +- client/app/pages/query-snippets/edit.js | 6 +- client/app/pages/query-snippets/list.js | 7 +- client/app/pages/settings/organization.html | 11 +- client/app/pages/settings/organization.js | 2 + client/app/pages/users/list.html | 16 +- client/app/pages/users/list.js | 146 +- client/app/pages/users/new.js | 3 + client/app/pages/users/show.js | 6 +- client/app/redash-font/fonts/redash-icons.eot | Bin 0 -> 1740 bytes client/app/redash-font/fonts/redash-icons.svg | 12 + client/app/redash-font/fonts/redash-icons.ttf | Bin 0 -> 1556 bytes .../app/redash-font/fonts/redash-icons.woff | Bin 0 -> 1632 bytes client/app/redash-font/style.less | 39 + client/app/redash-font/variables.less | 6 + client/app/services/alert-dialog.js | 3 + client/app/services/alert-subscription.js | 3 + client/app/services/alert.js | 3 + client/app/services/auth.js | 29 +- client/app/services/dashboard.js | 3 + client/app/services/data-source.js | 3 + client/app/services/destination.js | 3 + client/app/services/events.js | 29 +- client/app/services/getTags.js | 9 + client/app/services/group.js | 3 + client/app/services/http.js | 5 +- client/app/services/keyboard-shortcuts.js | 3 + client/app/services/notifications.js | 3 + client/app/services/offline-listener.js | 2 + client/app/services/organization-status.js | 3 + client/app/services/policy.js | 3 + client/app/services/query-result.js | 137 +- client/app/services/query-snippet.js | 3 + client/app/services/query.js | 7 +- client/app/services/tags.js | 14 - client/app/services/user.js | 14 +- client/app/services/widget.js | 3 + client/app/version.json | 1 + client/app/visualizations/box-plot/index.js | 3 + .../visualizations/chart/chart-editor.html | 96 +- client/app/visualizations/chart/index.js | 29 +- .../app/visualizations/chart/plotly/index.js | 25 +- .../app/visualizations/chart/plotly/utils.js | 290 +- .../choropleth/choropleth-editor.html | 2 +- client/app/visualizations/choropleth/index.js | 3 + client/app/visualizations/cohort/index.js | 3 + .../counter/counter-editor.html | 16 +- .../app/visualizations/counter/counter.html | 27 +- client/app/visualizations/counter/index.js | 42 +- .../edit-visualization-dialog.js | 54 +- client/app/visualizations/funnel/index.js | 82 +- client/app/visualizations/index.js | 2 + client/app/visualizations/map/index.js | 5 +- client/app/visualizations/pivot/index.js | 10 +- client/app/visualizations/sankey/index.js | 98 +- client/app/visualizations/sunburst/index.js | 2 + client/app/visualizations/table/index.js | 6 +- .../visualizations/table/table-editor.html | 4 +- client/app/visualizations/word-cloud/index.js | 9 +- cypress.json | 4 + cypress/cypress.js | 72 + .../data-source/create_data_source_spec.js | 18 + .../integration/query/create_query_spec.js | 21 + cypress/integration/user/login_spec.js | 30 + cypress/integration/user/logout_spec.js | 13 + cypress/plugins/index.js | 1 + cypress/seed-data.js | 35 + cypress/support/commands.js | 19 + cypress/support/index.js | 1 + docker-compose.yml | 12 +- migrations/versions/969126bd800f_.py | 23 +- netlify.toml | 39 + now.json | 9 - .../0003_update_data_source_config.py | 20 +- .../0011_migrate_bigquery_to_json.py | 12 +- old_migrations/0013_update_counter_options.py | 6 +- package-lock.json | 9649 ++++++++++++----- package.json | 50 +- pytest.ini | 1 - redash/__init__.py | 12 +- redash/admin.py | 4 +- redash/authentication/__init__.py | 17 +- redash/authentication/saml_auth.py | 2 +- redash/cli/__init__.py | 6 +- redash/cli/data_sources.py | 11 +- redash/cli/groups.py | 10 +- redash/cli/organization.py | 2 +- redash/cli/users.py | 13 +- redash/destinations/__init__.py | 3 +- redash/destinations/chatwork.py | 3 +- redash/destinations/hipchat.py | 4 +- redash/destinations/mattermost.py | 4 +- redash/destinations/pagerduty.py | 78 + redash/destinations/slack.py | 4 +- redash/destinations/webhook.py | 5 +- redash/extensions.py | 22 +- redash/handlers/admin.py | 22 +- redash/handlers/alerts.py | 13 +- redash/handlers/authentication.py | 6 +- redash/handlers/base.py | 14 +- redash/handlers/dashboards.py | 58 +- redash/handlers/data_sources.py | 29 +- redash/handlers/destinations.py | 20 +- redash/handlers/embed.py | 5 +- redash/handlers/favorites.py | 15 +- redash/handlers/groups.py | 25 +- redash/handlers/queries.py | 70 +- redash/handlers/query_results.py | 25 +- redash/handlers/query_snippets.py | 11 + redash/handlers/users.py | 48 +- redash/handlers/visualizations.py | 12 +- redash/handlers/webpack.py | 4 +- redash/handlers/widgets.py | 13 +- redash/metrics/celery.py | 8 +- redash/models.py | 136 +- redash/query_runner/__init__.py | 96 +- redash/query_runner/athena.py | 10 +- redash/query_runner/axibase_tsd.py | 9 +- redash/query_runner/big_query.py | 21 +- redash/query_runner/cass.py | 12 +- redash/query_runner/clickhouse.py | 69 +- redash/query_runner/databricks.py | 84 + redash/query_runner/db2.py | 152 + redash/query_runner/druid.py | 97 + redash/query_runner/dynamodb_sql.py | 7 +- redash/query_runner/elasticsearch.py | 17 +- redash/query_runner/google_analytics.py | 11 +- redash/query_runner/google_spreadsheets.py | 19 +- redash/query_runner/graphite.py | 9 +- redash/query_runner/hive_ds.py | 131 +- redash/query_runner/impala_ds.py | 6 +- redash/query_runner/influx_db.py | 7 +- redash/query_runner/jql.py | 50 +- redash/query_runner/kylin.py | 146 + redash/query_runner/mapd.py | 2 - redash/query_runner/memsql_ds.py | 8 +- redash/query_runner/mongodb.py | 47 +- redash/query_runner/mssql.py | 16 +- redash/query_runner/mssql_odbc.py | 11 +- redash/query_runner/mysql.py | 15 +- redash/query_runner/oracle.py | 12 +- redash/query_runner/pg.py | 28 +- redash/query_runner/presto.py | 21 +- redash/query_runner/python.py | 22 +- redash/query_runner/query_results.py | 74 +- redash/query_runner/rockset.py | 103 + redash/query_runner/script.py | 2 - redash/query_runner/snowflake.py | 5 +- redash/query_runner/sqlite.py | 15 +- redash/query_runner/treasuredata.py | 14 +- redash/query_runner/url.py | 38 +- redash/query_runner/vertica.py | 18 +- .../{yandex_metrika.py => yandex_metrica.py} | 38 +- redash/serializers.py | 20 +- redash/settings/__init__.py | 49 +- redash/settings/helpers.py | 12 +- redash/settings/organization.py | 10 +- redash/tasks/queries.py | 41 +- redash/templates/footer.html | 4 +- redash/templates/login.html | 6 +- redash/utils/__init__.py | 74 +- redash/utils/configuration.py | 8 +- redash/utils/human_time.py | 2 - redash/utils/sql_query.py | 71 + redash/worker.py | 25 +- requirements.txt | 9 +- requirements_all_ds.txt | 10 +- requirements_dev.txt | 8 +- setup/README.md | 23 + setup/amazon_linux/README.md | 4 - setup/amazon_linux/bootstrap.sh | 220 - setup/amazon_linux/files/env | 4 - setup/amazon_linux/files/nginx_redash_site | 23 - setup/amazon_linux/files/postgres_apt.sh | 162 - .../files/redash_supervisord_init | 125 - setup/amazon_linux/files/redis.conf | 785 -- setup/amazon_linux/files/redis_init | 66 - setup/amazon_linux/files/supervisord.conf | 31 - setup/docker-compose.yml | 52 + setup/generate_key.sh | 19 + setup/packer.json | 20 +- setup/setup.sh | 71 + setup/ubuntu/README.md | 1 - setup/ubuntu/bootstrap.sh | 110 - setup/ubuntu/files/env | 3 - setup/ubuntu/files/nginx_redash_site | 24 - setup/ubuntu/files/supervisord.conf | 33 - tests/__init__.py | 8 +- tests/handlers/test_dashboards.py | 9 +- tests/handlers/test_query_results.py | 15 +- tests/handlers/test_users.py | 15 +- tests/models/test_alerts.py | 26 + tests/models/test_dashboards.py | 30 + tests/models/test_queries.py | 15 + tests/models/test_query_results.py | 69 + tests/query_runner/test_athena.py | 190 + tests/query_runner/test_http.py | 136 + tests/query_runner/test_mongodb.py | 22 +- tests/query_runner/test_prometheus.py | 2 +- tests/query_runner/test_query_results.py | 46 +- tests/test_authentication.py | 20 +- tests/test_cli.py | 72 + tests/test_models.py | 57 - tests/test_utils.py | 9 +- tests/utils/__init__.py | 0 tests/utils/test_sql_query.py | 94 + webpack.config.js | 76 +- 366 files changed, 13406 insertions(+), 6963 deletions(-) create mode 100644 .circleci/docker-compose.cypress.yml delete mode 100644 .github/ISSUE_TEMPLATE.md create mode 100644 .github/ISSUE_TEMPLATE/---bug_report.md create mode 100644 .github/ISSUE_TEMPLATE/--anything_else.md create mode 100644 Dockerfile.cypress create mode 100644 Makefile create mode 100755 bin/bundle-extensions create mode 100755 bin/flake8_tests.sh create mode 100644 client/app/assets/images/db-logos/databricks.png create mode 100644 client/app/assets/images/db-logos/db2.png create mode 100644 client/app/assets/images/db-logos/druid.png create mode 100644 client/app/assets/images/db-logos/hive_http.png create mode 100644 client/app/assets/images/db-logos/kylin.png create mode 100644 client/app/assets/images/db-logos/rockset.png create mode 100644 client/app/assets/images/destinations/pagerduty.png create mode 100644 client/app/assets/less/redash/tags-control.less create mode 100644 client/app/components/AutocompleteToggle.jsx create mode 100644 client/app/components/EditInPlace.jsx rename client/app/components/{footer.js => Footer.jsx} (69%) create mode 100644 client/app/components/Footer.test.js create mode 100644 client/app/components/QueryEditor.jsx create mode 100644 client/app/components/__snapshots__/Footer.test.js.snap create mode 100644 client/app/components/dashboards/widget-dialog.html create mode 100644 client/app/components/dashboards/widget-dialog.less delete mode 100644 client/app/components/edit-in-place.js create mode 100644 client/app/components/proptypes.js delete mode 100644 client/app/components/queries/query-editor.js create mode 100644 client/app/components/tags-control/DashboardTagsControl.jsx create mode 100644 client/app/components/tags-control/ModelTagsControl.jsx create mode 100644 client/app/components/tags-control/QueryTagsControl.jsx create mode 100644 client/app/components/tags-control/TagsControl.jsx create mode 100644 client/app/components/tags-control/TagsEditorModal.jsx delete mode 100644 client/app/components/tags-control/control-template.html delete mode 100644 client/app/components/tags-control/index.js delete mode 100644 client/app/components/tags-control/modal-template.html create mode 100644 client/app/components/transclude-replace.js delete mode 100644 client/app/components/visualization-name.js create mode 100644 client/app/extensions/.gitkeep create mode 100644 client/app/lib/list-ctrl.js create mode 100644 client/app/lib/localOptions.js create mode 100644 client/app/lib/recordEvent.js create mode 100644 client/app/pages/queries/add-to-dashboard.html create mode 100644 client/app/pages/queries/add-to-dashboard.js create mode 100755 client/app/redash-font/fonts/redash-icons.eot create mode 100755 client/app/redash-font/fonts/redash-icons.svg create mode 100755 client/app/redash-font/fonts/redash-icons.ttf create mode 100755 client/app/redash-font/fonts/redash-icons.woff create mode 100755 client/app/redash-font/style.less create mode 100755 client/app/redash-font/variables.less create mode 100644 client/app/services/getTags.js delete mode 100644 client/app/services/tags.js create mode 100644 client/app/version.json create mode 100644 cypress.json create mode 100644 cypress/cypress.js create mode 100644 cypress/integration/data-source/create_data_source_spec.js create mode 100644 cypress/integration/query/create_query_spec.js create mode 100644 cypress/integration/user/login_spec.js create mode 100644 cypress/integration/user/logout_spec.js create mode 100644 cypress/plugins/index.js create mode 100644 cypress/seed-data.js create mode 100644 cypress/support/commands.js create mode 100644 cypress/support/index.js create mode 100644 netlify.toml delete mode 100644 now.json create mode 100644 redash/destinations/pagerduty.py create mode 100644 redash/query_runner/databricks.py create mode 100644 redash/query_runner/db2.py create mode 100644 redash/query_runner/druid.py create mode 100644 redash/query_runner/kylin.py create mode 100644 redash/query_runner/rockset.py rename redash/query_runner/{yandex_metrika.py => yandex_metrica.py} (85%) create mode 100644 redash/utils/sql_query.py create mode 100644 setup/README.md delete mode 100644 setup/amazon_linux/README.md delete mode 100755 setup/amazon_linux/bootstrap.sh delete mode 100644 setup/amazon_linux/files/env delete mode 100644 setup/amazon_linux/files/nginx_redash_site delete mode 100644 setup/amazon_linux/files/postgres_apt.sh delete mode 100644 setup/amazon_linux/files/redash_supervisord_init delete mode 100644 setup/amazon_linux/files/redis.conf delete mode 100644 setup/amazon_linux/files/redis_init delete mode 100644 setup/amazon_linux/files/supervisord.conf create mode 100644 setup/docker-compose.yml create mode 100644 setup/generate_key.sh create mode 100644 setup/setup.sh delete mode 100644 setup/ubuntu/README.md delete mode 100644 setup/ubuntu/bootstrap.sh delete mode 100644 setup/ubuntu/files/env delete mode 100644 setup/ubuntu/files/nginx_redash_site delete mode 100644 setup/ubuntu/files/supervisord.conf create mode 100644 tests/models/test_dashboards.py create mode 100644 tests/models/test_query_results.py create mode 100644 tests/query_runner/test_athena.py create mode 100644 tests/query_runner/test_http.py create mode 100644 tests/utils/__init__.py create mode 100644 tests/utils/test_sql_query.py diff --git a/.circleci/config.yml b/.circleci/config.yml index 48fc6be062..2c8b15a75f 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,6 +1,19 @@ version: 2.0 + +flake8-steps: &steps + - checkout + - run: sudo pip install flake8 + - run: ./bin/flake8_tests.sh jobs: - unit-tests: + python-flake8-tests: + docker: + - image: circleci/python:3.7.0 + steps: *steps + legacy-python-flake8-tests: + docker: + - image: circleci/python:2.7.15 + steps: *steps + backend-unit-tests: environment: COMPOSE_FILE: .circleci/docker-compose.circle.yml COMPOSE_PROJECT_NAME: redash @@ -13,6 +26,7 @@ jobs: name: Build Docker Images command: | set -x + docker-compose build --build-arg skip_ds_deps=true docker-compose up -d sleep 10 - run: @@ -20,25 +34,58 @@ jobs: command: docker-compose run --rm postgres psql -h postgres -U postgres -c "create database tests;" - run: name: Run Tests - command: docker-compose run --name tests redash tests --junitxml=junit.xml tests/ + command: docker-compose run --name tests redash tests --junitxml=junit.xml --cov-report xml --cov=redash --cov-config .coveragerc tests/ - run: name: Copy Test Results command: | mkdir -p /tmp/test-results/unit-tests - docker cp tests:/app/coverage.xml ./coverage.xml + docker cp tests:/app/coverage.xml ./coverage.xml docker cp tests:/app/junit.xml /tmp/test-results/unit-tests/results.xml - store_test_results: path: /tmp/test-results - store_artifacts: path: coverage.xml + frontend-unit-tests: + docker: + - image: circleci/node:8 + steps: + - checkout + - run: sudo apt install python-pip + - run: npm install + - run: npm run bundle + - run: npm test + frontend-e2e-tests: + environment: + COMPOSE_FILE: .circleci/docker-compose.cypress.yml + COMPOSE_PROJECT_NAME: cypress + PERCY_TOKEN_ENCODED: MWM3OGUzNzk4ZWQ2NTE4YTBhMDAwZDNiNWE1Nzc4ZjEzZjYyMzY1MjE0NjY0NDRiOGE5ODc5ZGYzYTU4ZmE4NQ== + docker: + - image: circleci/node:8 + steps: + - setup_remote_docker + - checkout + - run: + name: Install npm dependencies + command: | + npm install + - run: + name: Setup Redash server + command: | + npm run cypress start + docker-compose run cypress node ./cypress/cypress.js db-seed + - run: + name: Execute Cypress tests + command: npm run cypress run-ci build-tarball: docker: - image: circleci/node:8 steps: - checkout + - run: sudo apt install python-pip - run: npm install - - run: npm run build - run: .circleci/update_version + - run: npm run bundle + - run: npm run build - run: .circleci/pack - store_artifacts: path: /tmp/artifacts/ @@ -52,63 +99,18 @@ jobs: - run: docker login -u $DOCKER_USER -p $DOCKER_PASS - run: docker build -t redash/redash:$(.circleci/docker_tag) . - run: docker push redash/redash:$(.circleci/docker_tag) - integration-tests: - working_directory: ~/redash - machine: true - environment: - REDASH_SERVER_URL : "http://127.0.0.1:5000/" - DOCKER_IMAGE: mozilla/redash-ui-tests - steps: - - checkout - - run: - name: Install Docker Compose - command: | - set -x - pip install --upgrade pip - pip install docker-compose>=1.18 - docker-compose --version - - run: - name: Pull redash images - command: | - set -x - docker-compose -f docker-compose.yml up --no-start - sleep 10 - - run: - name: Pull redash-ui-tests - command: docker pull "${DOCKER_IMAGE}":latest - - run: - name: Setup redash instance - command: | - set -x - docker-compose run --rm --user root server create_db - docker-compose run --rm postgres psql -h postgres -U postgres -c "create database tests" - docker-compose run --rm --user root server /app/manage.py users create_root root@example.com "rootuser" --password "IAMROOT" --org default - docker-compose run --rm --user root server /app/manage.py ds new "ui-tests" --type "url" --options '{"title": "uitests"}' - docker-compose run -d -p 5000:5000 --user root server - docker-compose start postgres - docker-compose run --rm --user root server npm install - docker-compose run --rm --user root server npm run build - - run: - name: Run tests - command: | - set -x - docker run --net="host" --env REDASH_SERVER_URL="${REDASH_SERVER_URL}" "${DOCKER_IMAGE}" - - store_artifacts: - path: report.html workflows: version: 2 - integration_tests: - jobs: - - integration-tests: - filters: - branches: - only: master build: jobs: - - unit-tests + - python-flake8-tests + - legacy-python-flake8-tests + - backend-unit-tests + - frontend-unit-tests + - frontend-e2e-tests - build-tarball: requires: - - unit-tests + - backend-unit-tests filters: tags: only: /v[0-9]+(\.[0-9\-a-z]+)*/ @@ -118,8 +120,10 @@ workflows: - /release\/.*/ - build-docker-image: requires: - - unit-tests + - backend-unit-tests filters: branches: only: + - master + - preview-build - /release\/.*/ diff --git a/.circleci/docker-compose.circle.yml b/.circleci/docker-compose.circle.yml index 166b22a98b..e756a92ff3 100644 --- a/.circleci/docker-compose.circle.yml +++ b/.circleci/docker-compose.circle.yml @@ -1,4 +1,4 @@ -version: '2' +version: '3' services: redash: build: ../ diff --git a/.circleci/docker-compose.cypress.yml b/.circleci/docker-compose.cypress.yml new file mode 100644 index 0000000000..2581d5d1a9 --- /dev/null +++ b/.circleci/docker-compose.cypress.yml @@ -0,0 +1,47 @@ +version: '3' +services: + server: + build: ../ + command: dev_server + depends_on: + - postgres + - redis + ports: + - "5000:5000" + environment: + PYTHONUNBUFFERED: 0 + REDASH_LOG_LEVEL: "INFO" + REDASH_REDIS_URL: "redis://redis:6379/0" + REDASH_DATABASE_URL: "postgresql://postgres@postgres/postgres" + worker: + build: ../ + command: scheduler + depends_on: + - server + environment: + PYTHONUNBUFFERED: 0 + REDASH_LOG_LEVEL: "INFO" + REDASH_REDIS_URL: "redis://redis:6379/0" + REDASH_DATABASE_URL: "postgresql://postgres@postgres/postgres" + QUEUES: "queries,scheduled_queries,celery" + WORKERS_COUNT: 2 + cypress: + build: + context: ../ + dockerfile: Dockerfile.cypress + depends_on: + - server + - worker + environment: + CYPRESS_baseUrl: "http://server:5000" + PERCY_TOKEN: ${PERCY_TOKEN} + PERCY_BRANCH: ${CIRCLE_BRANCH} + PERCY_COMMIT: ${CIRCLE_SHA1} + PERCY_PULL_REQUEST: ${CIRCLE_PR_NUMBER} + redis: + image: redis:3.0-alpine + restart: unless-stopped + postgres: + image: postgres:9.5.6-alpine + command: "postgres -c fsync=off -c full_page_writes=off -c synchronous_commit=OFF" + restart: unless-stopped diff --git a/.circleci/docker_tag b/.circleci/docker_tag index 540f5d45ff..5f20a48bd0 100755 --- a/.circleci/docker_tag +++ b/.circleci/docker_tag @@ -1,5 +1,10 @@ #!/bin/bash -VERSION=$(jq -r .version package.json) -FULL_VERSION=$VERSION.b$CIRCLE_BUILD_NUM +if [ $CIRCLE_BRANCH = master ] || [ $CIRCLE_BRANCH = preview-build ] +then + FULL_VERSION='preview' +else + VERSION=$(jq -r .version package.json) + FULL_VERSION=$VERSION.b$CIRCLE_BUILD_NUM +fi echo $FULL_VERSION diff --git a/.circleci/update_version b/.circleci/update_version index 997ca5f290..d397fb23df 100755 --- a/.circleci/update_version +++ b/.circleci/update_version @@ -2,4 +2,5 @@ VERSION=$(jq -r .version package.json) FULL_VERSION=$VERSION+b$CIRCLE_BUILD_NUM -sed -ri "s/^__version__ = '([A-Za-z0-9.-]*)'/__version__ = '$FULL_VERSION'/" redash/__init__.py \ No newline at end of file +sed -ri "s/^__version__ = '([A-Za-z0-9.-]*)'/__version__ = '$FULL_VERSION'/" redash/__init__.py +sed -i "s/dev/$CIRCLE_SHA1/" client/app/version.json diff --git a/.dockerignore b/.dockerignore index 1ff2e91ddd..69c145ad11 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,4 +1,6 @@ client/.tmp/ +client/dist/ node_modules/ .tmp/ +.venv/ .git/ diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md deleted file mode 100644 index 1f52a61269..0000000000 --- a/.github/ISSUE_TEMPLATE.md +++ /dev/null @@ -1,34 +0,0 @@ - - -### Issue Summary - -A summary of the issue and the browser/OS environment in which it occurs. - -### Steps to Reproduce - -1. This is the first step -2. This is the second step, etc. - -Any other info e.g. Why do you consider this to be a bug? What did you expect to happen instead? - -### Technical details: - -* Redash Version: -* Browser/OS: -* How did you install Redash: diff --git a/.github/ISSUE_TEMPLATE/---bug_report.md b/.github/ISSUE_TEMPLATE/---bug_report.md new file mode 100644 index 0000000000..f376d6f1ce --- /dev/null +++ b/.github/ISSUE_TEMPLATE/---bug_report.md @@ -0,0 +1,34 @@ +--- +name: "\U0001F41B Bug report" +about: Report reproducible software issues so we can improve +--- + + + +### Issue Summary + +A summary of the issue and the browser/OS environment in which it occurs. + +### Steps to Reproduce + +1. This is the first step +2. This is the second step, etc. + +Any other info e.g. Why do you consider this to be a bug? What did you expect to happen instead? + +### Technical details: + +* Redash Version: +* Browser/OS: +* How did you install Redash: diff --git a/.github/ISSUE_TEMPLATE/--anything_else.md b/.github/ISSUE_TEMPLATE/--anything_else.md new file mode 100644 index 0000000000..9db411b781 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/--anything_else.md @@ -0,0 +1,17 @@ +--- +name: "\U0001F4A1Anything else" +about: "For help, support, features & ideas - please use https://discuss.redash.io \U0001F46B " +labels: "Support Question" +--- + +We use GitHub only for bug reports 🐛 + +Anything else should be posted to https://discuss.redash.io 👫 + +🚨For support, help & questions use https://discuss.redash.io/c/support +💡For feature requests & ideas use https://discuss.redash.io/c/feature-requests + +Alternatively, check out these resources below. Thanks! 😁. + +- [Forum](https://disucss.redash.io) +- [Knowledge Base](https://redash.io/help) diff --git a/.gitignore b/.gitignore index e405ce2850..7307021b73 100644 --- a/.gitignore +++ b/.gitignore @@ -24,3 +24,5 @@ node_modules .sass-cache npm-debug.log +cypress/screenshots +cypress/videos diff --git a/CHANGELOG.md b/CHANGELOG.md index d80f2726a5..9341e1c32d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,231 @@ # Change Log +## v6.0.0 - 2018-12-16 + +v6.0.0 release version. Mainly includes fixes for regressions from the beta version. + +This release had contributions from 5 people: @rauchy, @denisov-vlad, @arikfr, @ariarijp, and @gabrieldutra. Thank you, everyone 🙏 + +### Changed + +* #3183 Make refresh_queries less noisey in logs. @arikfr + +### Fixed + +* #3163 Include correct version in production builds. @rauchy +* #3161 Clickhouse: fix int() conversion error. @denisov-vlad +* #3166 Directly using record_event task requires timestamp. @arikfr +* #3167 Alert.evaluate failing when the column is missing. @arikfr +* ##3162 Remove API permissions for users who have been disabled. @rauchy +* #3171 Reject empty query name. @ariarijp +* #3175, #3186 Fix disable error message. @rauchy, @gabrieldutra +* #3182 [Redshift] support for schema names with dots. @arikfr +* #3187 Safely create_app in Celery code (try to fetch current_app first). @arikfr + +### Other + +* #3155 Add DB Seed to Cypress and setup Percy. @gabrieldutra +* #3180 Remove coverage from pytest terminal output. @rauchy + + +## v6.0.0-beta - 2018-12-03 + +This release was 2 months in the making and it is full with good stuff! + +* We have 5 new data sources: Databricks, IBM DB2, Kylin, Druid and Rockset. ⌗ +* There are fixes and improvements to 11 existing data sources (MySQL, Redshift, Postgres, MongoDB, Google BigQuery, Vertica, TreasureData, Presto, ClickHouse, Google Sheets and Google Analytics). +* The Query Results data source can now load cached results, just use the `cached_query_` prefix instead of `query_`. +* On the visualizations front we added a Heatmap visualization and did updated the table and counter visualizations. +* Alerts got some fixes and a new destination: PagerDuty. +* If the live autocomplete in the code editor annoys you, you can disable it now (although we're working to make it better, see #3092). +* Fast queries will now load faster. 🏃‍♂️ +* We improved the layout of visualizations and content on smaller screen sizes. 📱 +* For those of you who like sharing, you can now enable the ability to share ownership of queries and dashboards and let others to edit them. Check the Settings page to enable this feature. + +There were also important changes to the code and infrastructure: + +* More components moved to React. +* We switched to Webpack 4 with the help of @dmonego. +* We upgraded to Celery 4 with the help of @emtwo, @jezdez, @mashrikt and @atharvai. +* We started moving towards Python 3 for our backend. The first step was to make sure our code pass basic sanity tests with Flake 8, which was implemented by @cclauss. +* We improved our testing on the frontend by adding setup for Jest tests and E2E testing using Cypress (@gabrieldutra). +* Each pull request now gets a deploy preview using Netlify to easily test frontend changes. + +This is just a summary, you're welcome to review the full list below. ⬇ + +This release had contributions from 38 people: @arikfr, @kravets-levko, @jezdez, @kyoshidajp, @kocsmy, @alison985, @gabrieldutra, @washort, @GitSumito, @emtwo, @rauchy, @alexanderlz, @denisov-vlad, @ariarijp, @yoavbls, @zhujunsan, @sjakthol, @koooge, @SakuradaJun, @dmonego, @Udomomo, @cclauss, @combineads, @zaimy, @Trigl, @ralphilius, @jodevsa, @deecay, @igorcanadi, @pashaxp, @hoangphuoc25, @toph, @burnash, @wankdanker, @Yossi-a, @Rovel, @kadrach, and @nicof38. Thank you, everyone 🙏 + +### Added + +* #2747, #3143 Add a new Databricks query runner. @alison985, @jezdez, @arikfr +* #2767 Add ability to add viz to dashboard from query edit page. @alison985, @jezdez +* #2780 Add a query autocomplete toggle. @alison985, @jezdez, @arikfr +* #2768 Add authentication via JWT providers. @SakuradaJun +* #2790 Add the ability to sort favorited queries, paginate the dashboard list and improve UI inconsistencies. @jezdez +* #2681 Add ability to search table column names in schema browser. @alison985 +* #2855 Add option to query cached results. @yoavbls +* #2740 Add ability for extensions to add periodic tasks. @emtwo +* #2924 Google Spreadsheets: Add support for opening by URL. @alexanderlz +* #2903 Add PagerDuty as an Alert Destination. @alexanderlz +* #2824 Add support for expanding dashboard visualizations. @sjakthol +* #2900 Add ability to specify a counter label. @ralphilius +* #2565 Add frontend extension capabilities. @emtwo +* #2848 Add IBM Db2 as a data source using the ibm-db Python package. @nicof38 +* #2959 Add option to auto reload widget data in shared dashboards. @arikfr +* #2993 Add page size settings. @kyoshidajp +* #2080 New Heatmap chart visualization with Plotly. @deecay +* #2991 Show users in CLI group list. @GitSumito +* #2342 New SQLPARSE_FORMAT_OPTIONS setting to configure query formatter. @ariarijp +* #3031 Add some tests for Query Results. @ariarijp +* #2936 Add Kylin data source. @Trigl +* #3047 Add Druid data source. @rauchy +* #3077 New user interface for the feature flag of the share edit permissions feature. @arikfr +* #3007 Add permissions to the result of "manage.py groups list" command. @Udomomo +* #3088 Add get_current_user() fuction for the Python query runner. @kyoshidajp +* #3114 Add event tracking to autocomplete toggle. @arikfr +* #3068 Add Rockset query runner. @igorcanadi, @arikfr +* #3105 Display frontend version. @rauchy + +### Changed + +* #2636 Rewrite query editor with React. @washort, @arikfr +* #2637 Convert edit-in-place component to React. @washort, @arikfr +* #2766 Suitable events are now being recorded server side instead of in the frontend. @alison985, @jezdez +* #2796 Change placement (right/bottom) of chart legend depending on chart width. @kravets-levko +* #2833 Uses server side sort order for tag list and show count of tagged items. @jezdez +* #2318 Support authentication for the URL data source. @jezdez +* #2884 Rename Yandex Metrika to Metrica. @jezdez +* #2909 MySQL: hide sys tables. @arikfr +* #2817 Consistently use simplejson for loading and dumping JSON. @jezdez +* #2872 Use Plotly's function to clean y-values (x may be category or date/time). @kravets-levko +* #2938 Auto focus tag input. @kyoshidajp +* #2927 Design refinements for queries pages. @kocsmy +* #2950 Show activity status in CLI user list. @GitSumito +* #2968 Presto data source: setting protocol (http/https), safe loading of error messages. @arikfr +* #2967 Show groups in CLI user list. @GitSumito +* #2603 MongoDB: Update requirements to support srv. @arikfr +* #2961 MongoDB: Skip system collections when loading schema. @arikfr +* #2960 Add timeout to various HTTP requests. @arikfr +* #2983 Databricks: New logo, updated name and enabled by default. @arikfr +* #2982 Table visualization: change default size to 25 and add more size options. @arikfr +* #2866 Redshift: Hide tables the configured user cannot access. @sjakthol +* #3058 Mustache: don't html-escape query parameters values. @kravets-levko +* #3079 Always use basic autocomplete, as well as the live autocomplete. @arikfr +* #3084 Support tel://, sms://, mailto:// links in query results. @zhujunsan +* #3083 Clickhouse: Add WITH TOTALS option support. @denisov-vlad +* #3063 Allow setting colors for bubble charts. @toph +* #3085 BigQuery: Switch to Standard SQL as the default. @kyoshidajp +* #3094 Tags autocomplete: Show note when creating a new label. @kravets-levko +* #2984 Autocomplete toggle improvements. @arikfr +* #3089 Open new tab when forking a query. @kyoshidajp +* #3126 MongoDB: add support for sorting columns. @arikfr +* #3128 Improve backoff algorithm of query results polling to speed it up. @arikfr +* #3125 Vertica: update driver & add support for connection timeout. @arikfr +* #3124 Support unicode in Postgres/Redshift schema. @arikfr +* #3138 Migrate all tags components to React. @kravets-levko +* #3139 Better manage permissions modal. @kocsmy +* #3149 Improve tag link colors and fix group tags on Users page. @kocsmy +* #3146 Update, replace and fix new alert destination logos so it fits better. @kocsmy +* #3147 Add and improve recent db logos that didn't fit in size properly. @kocsmy +* #3148 Fix label positioning on no found screen. @kocsmy +* #3156 json_dumps: add support for serializing buffer objects. @arikfr + +### Fixed + +* #2849 Fix invalid reference to alert.to_dict() in webhook. @wankdanker +* #2840 Improve counter visualization text scaling. @kravets-levko +* #2854 Widget titles are no longer rendered wrong on public dashboards. @kravets-levko +* #2318 Removed redundant exception handling in data sources since that's handled in the query backend. @jezdez +* #2886 Fix Javascript build that broke because registerAll tried to run EditInPlace component. @arikfr +* #2911 Don’t show “Add to dashboard” in dropdown to unsaved queries. @jezdez +* #2916 Fix export query results output file name. @gabrieldutra +* #2917 Fix output file name not changing after rename query. @gabrieldutra +* #2868 Address edge case when retrieving Glue schemas for Athena data source. @kadrach +* #2929 Fix: date value in a filter is duplicated. @combineads +* #2875 Unbreak charts with long legend break in horizontal mode. Update plotly.js. @kravets-levko +* #2937 Fix event recording in admin API backend. @kyoshidajp +* #2953 Minor fixes for the Clickhouse data source. @denisov-vlad +* #2941 Bring back fix to Box plot hover. @arikfr +* #2957 Apply missing CSS classes to EditInPlace component. @arikfr +* #2897 Show "Add description" only after saving the query. @arikfr +* #2922 Query page layout improvements for small screens. @kravets-levko +* #2956 Clickhouse: move timeout to params. @denisov-vlad +* #2964 Fix no tags shown when having empty set. @gabrieldutra +* #2757 Use full text search ranking when searching in list views. @jezdez +* #2969 Query Results data source: improved errors, quoted column names. @arikfr +* #2906 Preventing open redirection in loging process. @kyoshidajp +* #2867 TreasureData: Deduplicate column names. @zaimy +* #2994 Fix scheme of various URLs from http to https. @kyoshidajp +* #2992 Fix an invalid prop type warning in new version notifier. @kyoshidajp +* #3022 Fix Toolbox covering part of a chart. @kravets-levko +* #2998 Fix charts losing responsive features after refreshing the dashboard. @kravets-levko +* #3034 Postgres: handle NaN/Infinity values. @kravets-levko +* #2745 Sort columns with undefined values. @Yossi-a +* #3041 Sort CLI output of lists. @GitSumito +* #2803, #3006 Address various tag display issues on query list page. @kocsmy, @alison985 +* #3049 Fix edit-in-place component which ignored isEditable flag and didn't work on Groups page. @kravets-levko +* #2965 Google Analytics: Fix crash when no results are returned. @alexanderlz +* #3061 Fix table visualization so that the horizontal scrollbar is not be always visible. @kravets-levko +* #3076 Add white-space padding to separators in the footer. @burnash +* #2919 Fix URL data source to not require a URL. @arikfr +* #3098 Force AngularJS to update query editor properly. @washort +* #3100 Delete redundant regex segment in query result frontend. @zhujunsan +* #2978 Prevent the query update timestamp from changing when it is linked to new query results. @rauchy +* #3046 Fix query page header. @kravets-levko +* #3097 Mongo: Fix collection fields retreival bug when Views are present. @jodevsa +* #3107 Keep query text in local state for now. @washort +* #3111 Fix mobile padding issues on Query results. @kocsmy +* #3122 Show menu divider only if query is archived. @jezdez +* #3120 Fix tag counts for dashboards and queries. @jezdez +* #3141 Fix schema refresh to work on MySQL 8. @hoangphuoc25 +* #3142 Fix: editing dashboard title results in the visualizations being replaced by the loading markers. @kravets-levko + +### Other + +* #2850 The setup scripts are now based on Ubuntu 18.04 LTS and Docker. @pashaxp, @arikfr +* #2985 Add Jest based tests to our stack. @arikfr +* #2999 Add netlify configuration. @arikfr +* #3000 Initial Cypress based E2E test infrastructure. @gabrieldutra +* #2898 Move Ant styles into a central location. @arikfr +* #2910 Fix webpack build error about BigMessage. @jezdez +* #2928 Speed up builds by skipping installing requirements_all_ds.txt in CI unit tests. @arikfr +* #2963 Fix tarball build failure. @emtwo +* #2996 Fix setup.sh failures when run as root. @arikfr +* #2989 Rearrange make targets. @koooge +* #3036 Update Flask-Admin to 1.5.2. @yoavbls +* #2901 Fix documentation links. @kravets-levko +* #3073 Remove only Redash containers in clean Make task. @ariarijp +* #3048 Remove pytest-watch dependency to workaround an issue with watchdog. @rauchy +* #2905 Update development docker-compose.yml file to use latest Redis and Postgres servers and specify working volume explictly. @Rovel +* #3032 Makefile: Add make targets for test. @koooge +* #2933 Switch to Webpack 4. @dmonego +* #2908 Update setup files. @arikfr +* #2946 Update snowflake_connector_python version. @arikfr +* #2773 Upgrade to Celery 4.2.1. @emtwo, @jezdez +* #2881 CircleCI: Make flake8 tests pass on Legacy Python and Python 3. @cclauss +* #2907 Remove unused dependencies (honcho, wsgiref). @arikfr +* #3039 Build docker image on master branch. @arikfr +* #3106 Fix registerAll failures after minification. @arikfr + + +## v5.0.2 - 2018-10-18 + +### Security + +* Fix: prevent Open Redirect vulnerability. + + +## v5.0.1 - 2018-09-27 + +### Added + +* Added support for JWT authentication (for services like Cloudflare Access or Google IAP). + +### Changed + +* Upgraded Celery version to 3.1.26 to make upgrade to Celery 4 easier. + + ## v5.0.0 - 2018-09-21 Final release for V5. Most of the changes were already in the beta release of V5, but this includes several fixes along diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e92c1b4e90..1288782f5f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -9,7 +9,7 @@ The following is a set of guidelines for contributing to Redash. These are guide - [Feature Roadmap](https://trello.com/b/b2LUHU7A/redash-roadmap) - [Feature Requests](https://discuss.redash.io/c/feature-requests) - [Documentation](https://redash.io/help/) -- [Blog](http://blog.redash.io/) +- [Blog](https://blog.redash.io/) - [Twitter](https://twitter.com/getredash) --- @@ -67,7 +67,7 @@ The project's documentation can be found at [https://redash.io/help/](https://re ### Release Method -We publish a stable release every ~2 months, although the goal is to get to a stable release every month. You can see the change log on [GitHub releases page](http://github.com/getredash/redash/releases). +We publish a stable release every ~2 months, although the goal is to get to a stable release every month. You can see the change log on [GitHub releases page](https://github.com/getredash/redash/releases). Every build of the master branch updates the latest *RC release*. These releases are usually stable, but might contain regressions and therefore recommended for "advanced users" only. @@ -75,4 +75,4 @@ When we release a new stable release, we also update the *latest* Docker image t ## Code of Conduct -This project adheres to the Contributor Covenant [code of conduct](http://redash.io/community/code_of_conduct). By participating, you are expected to uphold this code. Please report unacceptable behavior to team@redash.io. +This project adheres to the Contributor Covenant [code of conduct](https://redash.io/community/code_of_conduct). By participating, you are expected to uphold this code. Please report unacceptable behavior to team@redash.io. diff --git a/Dockerfile b/Dockerfile index a82661e527..5176e7df46 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,12 +1,16 @@ FROM redash/base:latest +# Controls whether to install extra dependencies needed for all data sources. +ARG skip_ds_deps + # We first copy only the requirements file, to avoid rebuilding on every file # change. COPY requirements.txt requirements_dev.txt requirements_all_ds.txt ./ -RUN pip install -r requirements.txt -r requirements_dev.txt -r requirements_all_ds.txt +RUN pip install -r requirements.txt -r requirements_dev.txt +RUN if [ "x$skip_ds_deps" = "x" ] ; then pip install -r requirements_all_ds.txt ; else echo "Skipping pip install -r requirements_all_ds.txt" ; fi COPY . ./ -RUN npm install && npm run build && rm -rf node_modules +RUN npm install && npm run bundle && npm run build && rm -rf node_modules RUN chown -R redash /app USER redash diff --git a/Dockerfile.cypress b/Dockerfile.cypress new file mode 100644 index 0000000000..3efef14f49 --- /dev/null +++ b/Dockerfile.cypress @@ -0,0 +1,11 @@ +FROM cypress/browsers:chrome67 + +ENV APP /usr/src/app +WORKDIR $APP + +RUN npm install --no-save cypress @percy/cypress > /dev/null + +COPY cypress $APP/cypress +COPY cypress.json $APP/cypress.json + +RUN ./node_modules/.bin/cypress verify diff --git a/Makefile b/Makefile new file mode 100644 index 0000000000..d13ecacf31 --- /dev/null +++ b/Makefile @@ -0,0 +1,51 @@ +.PHONY: compose_build up test_db create_database clean down bundle tests lint backend-unit-tests frontend-unit-tests test build watch start + +compose_build: + docker-compose build + +up: + docker-compose up -d --build + +test_db: + @for i in `seq 1 5`; do \ + if (docker-compose exec postgres sh -c 'psql -U postgres -c "select 1;"' 2>&1 > /dev/null) then break; \ + else echo "postgres initializing..."; sleep 5; fi \ + done + docker-compose exec postgres sh -c 'psql -U postgres -c "drop database if exists tests;" && psql -U postgres -c "create database tests;"' + +create_database: + docker-compose run server create_db + +clean: + docker-compose down && docker-compose rm + +down: + docker-compose down + +bundle: + docker-compose run server bin/bundle-extensions + +tests: + docker-compose run server tests + +lint: + ./bin/flake8_tests.sh + +backend-unit-tests: up test_db + docker-compose run --rm --name tests server tests + +frontend-unit-tests: bundle + npm install + npm run bundle + npm test + +test: lint backend-unit-tests frontend-unit-tests + +build: bundle + npm run build + +watch: bundle + npm run watch + +start: bundle + npm run start diff --git a/README.md b/README.md index 6f68a344bc..cd2e5ae0de 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ Today **_Redash_** has support for querying multiple databases, including: Redsh **_Redash_** consists of two parts: -1. **Query Editor**: think of [JS Fiddle](http://jsfiddle.net) for SQL queries. It's your way to share data in the organization in an open way, by sharing both the dataset and the query that generated it. This way everyone can peer review not only the resulting dataset but also the process that generated it. Also it's possible to fork it and generate new datasets and reach new insights. +1. **Query Editor**: think of [JS Fiddle](https://jsfiddle.net) for SQL queries. It's your way to share data in the organization in an open way, by sharing both the dataset and the query that generated it. This way everyone can peer review not only the resulting dataset but also the process that generated it. Also it's possible to fork it and generate new datasets and reach new insights. 2. **Visualizations and Dashboards**: once you have a dataset, you can create different visualizations out of it, and then combine several visualizations into a single dashboard. Currently Redash supports charts, pivot table, cohorts and [more](https://redash.io/help/user-guide/visualizations/visualization-types). @@ -31,13 +31,12 @@ Today **_Redash_** has support for querying multiple databases, including: Redsh ## Supported Data Sources -Redash supports more than 25 [data sources](https://redash.io/help/data-sources/supported-data-sources). +Redash supports more than 35 [data sources](https://redash.io/help/data-sources/supported-data-sources). ## Getting Help * Issues: https://github.com/getredash/redash/issues * Discussion Forum: https://discuss.redash.io/ -* Slack: http://slack.redash.io/ ## Reporting Bugs and Contributing Code diff --git a/bin/bundle-extensions b/bin/bundle-extensions new file mode 100755 index 0000000000..8416aab776 --- /dev/null +++ b/bin/bundle-extensions @@ -0,0 +1,39 @@ +#!/usr/bin/env python + +import os +from subprocess import call +from distutils.dir_util import copy_tree + +from pkg_resources import iter_entry_points, resource_filename, resource_isdir + + + +# Make a directory for extensions and set it as an environment variable +# to be picked up by webpack. +EXTENSIONS_RELATIVE_PATH = os.path.join('client', 'app', 'extensions') +EXTENSIONS_DIRECTORY = os.path.join( + os.path.dirname(os.path.dirname(__file__)), + EXTENSIONS_RELATIVE_PATH) + +if not os.path.exists(EXTENSIONS_DIRECTORY): + os.makedirs(EXTENSIONS_DIRECTORY) +os.environ["EXTENSIONS_DIRECTORY"] = EXTENSIONS_RELATIVE_PATH + +for entry_point in iter_entry_points('redash.extensions'): + # This is where the frontend code for an extension lives + # inside of its package. + content_folder_relative = os.path.join( + entry_point.name, 'bundle') + (root_module, _) = os.path.splitext(entry_point.module_name) + + if not resource_isdir(root_module, content_folder_relative): + continue + + content_folder = resource_filename(root_module, content_folder_relative) + + # This is where we place our extensions folder. + destination = os.path.join( + EXTENSIONS_DIRECTORY, + entry_point.name) + + copy_tree(content_folder, destination) diff --git a/bin/flake8_tests.sh b/bin/flake8_tests.sh new file mode 100755 index 0000000000..3d6be0d2a9 --- /dev/null +++ b/bin/flake8_tests.sh @@ -0,0 +1,7 @@ +#!/bin/sh + +flake8 --version ; pip --version +# stop the build if there are Python syntax errors or undefined names +flake8 . --count --select=E901,E999,F821,F822,F823 --show-source --statistics +# exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide +flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics diff --git a/bin/get_changes.py b/bin/get_changes.py index 1de784fb78..6d98d8672b 100644 --- a/bin/get_changes.py +++ b/bin/get_changes.py @@ -1,4 +1,5 @@ #!/bin/env python +from __future__ import print_function import sys import re import subprocess @@ -32,4 +33,4 @@ def get_change_log(previous_sha): changes = get_change_log(previous_sha) for change in changes: - print change \ No newline at end of file + print(change) \ No newline at end of file diff --git a/bin/release_manager.py b/bin/release_manager.py index 521a9b8b52..df00169da7 100644 --- a/bin/release_manager.py +++ b/bin/release_manager.py @@ -1,10 +1,10 @@ from __future__ import print_function import os import sys -import json import re import subprocess import requests +import simplejson github_token = os.environ['GITHUB_TOKEN'] auth = (github_token, 'x-oauth-basic') @@ -17,7 +17,7 @@ def _github_request(method, path, params=None, headers={}): url = path if params is not None: - params = json.dumps(params) + params = simplejson.dumps(params) response = requests.request(method, url, data=params, auth=auth) return response diff --git a/client/.eslintrc.js b/client/.eslintrc.js index ed429e2aee..10fae2b4c6 100644 --- a/client/.eslintrc.js +++ b/client/.eslintrc.js @@ -1,11 +1,14 @@ module.exports = { root: true, - extends: "airbnb", + extends: ["airbnb", "plugin:jest/recommended"], + plugins: ["jest", "cypress"], settings: { "import/resolver": "webpack" }, parser: "babel-eslint", env: { + "jest/globals": true, + "cypress/globals": true, "browser": true, "node": true }, diff --git a/client/app/assets/images/db-logos/databricks.png b/client/app/assets/images/db-logos/databricks.png new file mode 100644 index 0000000000000000000000000000000000000000..f2031b5fd116f20e71cc0f1f5964837dda7f46f0 GIT binary patch literal 17187 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 EKh2MjNdN!< literal 0 HcmV?d00001 diff --git a/client/app/assets/images/db-logos/db2.png b/client/app/assets/images/db-logos/db2.png new file mode 100644 index 0000000000000000000000000000000000000000..b5995ce6a4d5eec1fce2f0fe77b7bce6aaa4d7bb GIT binary patch literal 13397 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 z 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 Ml1dUaV#dM$14EM4JOBUy literal 0 HcmV?d00001 diff --git a/client/app/assets/images/db-logos/druid.png b/client/app/assets/images/db-logos/druid.png new file mode 100644 index 0000000000000000000000000000000000000000..d5ded0fad004d5d9b883a92b05175e5f3d41886d GIT binary patch literal 11452 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 literal 0 HcmV?d00001 diff --git a/client/app/assets/images/db-logos/hive_http.png b/client/app/assets/images/db-logos/hive_http.png new file mode 100644 index 0000000000000000000000000000000000000000..c9a127db3f9dfdc009825f70208332c65913b0fa GIT binary patch literal 25212 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 F{{i__G~xgN literal 0 HcmV?d00001 diff --git a/client/app/assets/images/db-logos/kylin.png b/client/app/assets/images/db-logos/kylin.png new file mode 100644 index 0000000000000000000000000000000000000000..914787a67946e27aafcc132afda1a520ee09b60e GIT binary patch literal 24361 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ⅇ$a@o~?bz*V*ZGKH+K5^;33JLE$(m^Og*n z_cw}omm!GG23%G@M@l!~R%^&vrUc(iOHS+FIEsq-oamD1uE`J8OQoCVUe!!{Yky8z z$Y%NJ%;Ds+nY2`dlG055bV&wHg z%`GaHlM=rZ)y!1k4v}Ba$VE93a2JhVjJmK-?sWCP`(s9CyZ}&w+$Molrn(lB`$)K2 zl^QI&7C&IT^wZ!cxmdM}|A>vdWo}^y;7$A1g{#4>=xhr8<5Q_H^X#-;%a=7x>S?T9 zdltZ%w^OQR!Bx=uP zcw>{M*FML;Z(3wL=i-&UEj+MQ-ie2!Y~)U#n;g{}z8Du?uBE(YZ=RoR7TOQG6%>-N zex;Nemb1H!EK{MaA!AIa4$S}SNp(^BZ?-i;Tc}5lAjG{Wwt3M=utS)uKZxb*(HP;} z09U@o_;6YZZvq6D8we_{9~1*NTybw)DrR)ScR@_Q(apX@=*`W4>tDD)D9^fwbScQ2 zo5^h^ew1aejgNLkxEykCzUYZdK`M9!Tm4@w!#kG7f~)}EANG>hN_D42Sj8^(@Vq8D;&UGR?TOv3skYUKx#uf6`wgfZM>Tg{+=4FW zNfrq#v3-FDnxOH1sd~lo)NdPkVt^+tFkqs3YRK9;CVc{)c{Tke_uiWZuDSzG0L`Uj zxf7z%xQ1p;z9r%E64Jo>Fb_RsO`B>mT?rd%i*+TM1pUpmAUGYrwYMS;qEDrWS$#h! zGyB4hdHAJ0KdR^~sy-XG658wDBAsIa*6=Wv?Z zo9*=ncOEE6zetKf|qr!B_uo{g7Tn{V0a+EL~t@aD8dM!&L? zs%K|R*>4Uc<0?h|5BT-ngUXN|(uo(D)nF0ckrFR6D@(&Cok zqL{D;&mj3r)}BE28}y#It4Fv@Gz!(+`0tdlLuKl|T$En!DboXga3NRWibQ?lBj?v! zxA~u|hX?2n>z+)x#y(uLW501dp9iYVrQ_-SiOdE3S&w=hGCjOJ$ioI>T1^eYhzz{+Mvz8;|bhhfC;~N{x sRIq8-zsUcuNd4c!^M#(1hQ8v`5J6wQY4Z5Jx$of==H-}}eTA5+skefsq2^PF>@o(X^VRvr_L6b%3XOhpBm_W%HbJ%RufB-owBE%gl6 zLiix5DhU8pG3bwGhyXx`rYIw+=>a;2y?{ebM zDOa;C>&9a{o`s|Od(-SFqxdt@^nc=~X|4p3Qy~PhDZ|;@+f(q%(U30&(V_+|BXEM? z1UHnYMy{$V`f6>WJgx7G+xF@t8k4qNY!t}{-G51FMLrQsAh=>0?7uG2GEJp{r( z)TvG*WYcO5msksr_E*8V2pDFv3H9T?J~MAVMPvN93mJ)F$+5O7%P)46f#l6Ai#h_J zx-WAiYS)a2x6uRxDftCU$!hj2oF!$?CQyQ$O+FUeIijX)uhDwAAjf}D^gq_*FdS16`k#(jbCjAJmilV3N=wFH?(fP83C3TQ)6#!If5FG@;n*nU{ zKC6xJXh`^(kGGAcS-mR`PHxjv(bmu4*I~c=O*8=~ehyQ5zC8CbT56K9PT@)UU_I5i zJxdNc&vHrilm3||i05ZS@Zx*ZnbrSpx3YXV@X?h-Q zoCat(Q7zdVw7)j%33TUcH*3uU2=t7#S)mcg<@b^?`S-e$Mlf*ag()I9EA-vnSK<6~Zx5{;%-p%lgGGmSQ zIR{0RU4PCX%zm|>KxXE6ZmGWLH(5p$ML~Y}MB)NW zMm_ftLEG&ME_m^lizl0%6mkLH%3YHv!~Mo;JoDoaT_E1u<N8Q{g5Aukmddy&rMk+Dx8rwo zOPr4TEYKj#`L;_)%}ONOE^zX~><0@L7?&3dDGZ&BM;~mI-uMv}KeL-^bI!%|j<7*q z*^XX42z9wMkD}=^M!Ibl*_*JM=ERb2TGy$OS)zT9myf0Jp~8^KMQ-Uy7`>#tk`?%8 zfa^rR(!(4B*3?sE%ZF6KUE`B=j@$wX*>lHhUw|k! zjn7-Cx2H{8t_{=_vRgY3YGT*|UM3)30sL&DyVDFNm39d$G0Fjz@(RFM)M=?dAwR7M zE*aSNKh&OGwe?L>E&L3S8vJUr(nb(|Khx0Z5l}%ku1EEN1hhPDYNKoXUV6UW(7qgt z`hyNx6f)Y9qjzS57;Bhu_970m3-%Gm%vNy#9n*h^J~Bw{+lxr7DmW&$&X*|?RsrFNpXVs1IUs)Y3Td@r@gE&f0fnJH3ufG7gk!~w zafVYjM==3>+rEYE%bPd76I_Upmn^@wU>CUH#F<~V*{kCout~+0h$P( z4qSml#<7G!q5udA!f}O041GWYtosEV5SWUSXyCA^R4P|e;c%vk@@gsxSu%@l0{f?k zlua*%H2^zS@54L-JvQ)c;`kzKLfO6w=$$HW-XJ0$^F`%CU17x-j?U3i(P9l8D?!>2x)D9UF;;urpr@e%+ihHwK9*xUh!; zg)&|oYItgaJ|Hlkw&t$H2(N%0VZnLRD|d3+SL;Wd>p<=Jl518hF*BB}r$XBO-C7q* zDTd;vsA-|x*d=qi^JwjZ&;n8~zDs(~#$lG&rI$Dg{I3IpNJaYF>qe{+9KU59XgivD;9-#b$q3e(v1NvdYpzEW&S^_ctlv;OCa zke>-M?`ltZjc%U4H;;^|Uw~P`^R?A#_sn8g#b-^F{wJ&KD_h!7FdKyV`$Ne_J=lF3 z8LOkb%eWt#98ype<6*=&g8lyphks@Nf5*muH8_(*RE~^?$l<77;W2urj!KrPoSa!W z2Y`q5z#ch)wCMZ2k5eOagY$|lR~m%k(~BwbgUVD)gE|!_rs9h5mjR0e@0^h)7KD#u z&U_9(%Dr7o@`1?6#Z@fVH!NRiAXz*LQlvzJcx&e*7#$6>^ma*7+_%1F|KKUQFH^4n z#QTlxcjW?EM{kMUIAaOx1H89$`tOr{?%zTtD0yb3}4BW6o6*uq3^oLNosDTF=Z$w-`5i$M{%7SSsvHnI{F?p*LW z=YpWUN6k75evXC5^lWzahlN%o{#sRWpM_3&-Qq`k`YsOX@`v#-+Xp~%AU6jQ-Xg7U2eM4p->_#z?>Zw;^4m3gN#&ssqufP>Q+I6ww| zo#rSiSz~O{TW~hJy?b)dQs6DMkVZ!N^HPDVqjc{6v~$GU|Dr%b>`Y^VybzB)NPY>} zIDcYbA3D){&qedpQ8VH_##oK?&P8oBOiE)CIvD4fTb#t_@|1XxR60Nk{>eCd|GZ-Y z5w393A!;CBQjX&T;?Cwn!i%ZTe}yVil{CrB0j6_DsM_dyyxByUTb(W8uh{gfP$u~x z=JYjAV*5;g9SRS>&J2(OS7T*onIRb%t!J-4?TDz5>A}CV-2G$N@lB05jivg&;arrt zKaLObuqS?}luF$lTSN741=Wa}gTG5(C0dE*s!*>g3k&NGnI?VtftmBu>1nj32l@Fi z>p*#Zpg2JH57|ff97pc7=c-RSi%j()%DGCAq-TZst?~@CUewDv*q(W9Cx6jk`f3{G zDPKu(kF!M3YO<_zqF}9nC%XnP_CM^|+xlng^|J-a&Yf|UG2bIiEvE>PBscC0MB&7B z=n?}~t8=xRDW(Y1F3GQ%^f6sUb8NqG;{H&dx(EtQaew+*2#J*sv$>S@EynlbbDCMm z$GVSYSNZJ5<4dZ|sycU^a!R%~y--u3yTWJ~lLgwJ_^>YWBt~4NarKQ-a(l4c$7j*a z{;C#wb5^G$eZW= z(-gmryBrE`jYmIu7}PrxGvklQD~x*?`emwjX~_B!KDFlV-VYB`9Nm8|=e>cc%MK z-Z;^5o|YdV_g5LZ4{1(m^jI?2xxC?33!7bOcW3_I$Mz9^g1}+2GnA@&kiAy0m!mNp z_j<_A#*R@XG zL^v0T%iJTd*|PH~EFOw#V^i|v3ayNwNs_4CAulCSuPNq#HQccu;$UThhxD$lshC?` z`#CzE{UY;M+)#Q_omVO3n{sA6CnS)C<(7%*a_G-NwOQcrf6g-|ROAHfH49{5jfYz7 zO`mmROy`|}!=!}zWo3fVg(`js>^N0ohIOVMT#Ph_$K5*O@(3kjYv1=OAhIB^F}^1z zaJ)B47+29&is_zmLR3x&sfV=rF7jd-5ea6!&8l`AoRi3q3zIap7Xw4XWG06=wEc?n z;$^D;rkS7Td5a|@P0Z-OG_QQ|`IRJdnO0lPUymtM#RIudE z`62F0?AN{_AUg zLwj4E#@HSMj1#0S-%&R2$M0oBP3m$|QPL+8PuL|>#R*yBtCN?iFrLD0t2HaCHuRps z*7F?*3kG4};~&q6J=95}Z{oWB&JtVV_{zH5(*@uuZt^C_I$sua5A5_*-mIK4X3MYr z!y8o-E?uvyOL3TJj0U*<+ApGE_^%#+*(GAlCzsV$m@O_&>#Jm>gbfY~anK zpWRSw&z7M9*gvV@n%=i0sbFqi-ak@!=tXg3DIPE=@b+h3& zGB$}?O9><{BT7M~SuHoxl4zm#Eq!HIHB&8#gjfMs$_U?sS~oe1J`5HT#S48c`#^G^ zsr~~KtiE%4H)0nim>L^lZ`8mS{~4&|gt_`=5xXAgi3f1OY3J@?eocS_tAUxjkr&pn zErf5MZhhW(G@i5!?DLvSXGiEy~G<4!5cr`1U2Su`LfUM*GYX;>m!kR3fa0TL- z_zQ9oeB80&Q702EOo5=Yew(LbRq1yj3cW;!z}VS?Ir?B8YY$IN!;7@$P4lw-2F=C+fgV}qG~-B0U?e0}A(1=`mQii|JE@;TOj$H`9# zNp>4+2pwXNJRe)ZI<9&r{9^K?m{%EWZfaMN%R$RNnd>i&F7C)-KCcYma~9_L#2p1&2vaLik>|hK2nvQ_uq-4iH+zi>9$x9TT%@I$ zmtsO*>1y}VF{DcTrVo?pJEQFYMlvp;2&H5V3~nBm(9y3^0~of6UFM&G81X> z_ya7BvfLg^d|lpM&gScj**-UY?Zmp-ZIF8Tl?rMf)5l#?enviU6+Xl5L%Q}B zVby~d^m~5v)wN|u*N0eb;S+X$x{mS;Lr5wGO$aOeoL;0^%|kh9KTlWiT{)ObR)VqE zKQCNpu{Y-_huTf_p`@W4kyN>a>+>nhv-dGKDUzS;RA;Bunnr0450sbS>6nL~wT4c< zlYUkt16&E2)Y}7B4^5_!V&5hh3p*FKw2ZLz4-{~~Scu3ivR6{1cOXW0=xc+(Lc#y_ z(dhpN#rRKX$$ujA7j?uo&GRs_PNTio7*7d>1teY?k!$=HwNUg67ROop-B3iuh#3ba zeNY@gB=_?j!wo_~MV7NWH;wy11i$^ub7ZD^lA-~Tn|O~gw-O3I$Quqt!{P3Svc=KN zckM*w_IXVQ-5VkZZ5|_9M#*Vm_D%vC;~P4JGgN9i!cP4trr`q3#F!o59@IxZ(S9e# z%MY@)mCL^+R5d-3IwSH%PK{^265081zBuB5k#V9uO$&Nw>WC=Q2|}N=mBJDdBc%rX zAADn5d>(jYpbIo-uhkMGTgqR`o|V1Qy>=vV&*|I|CO|#qO4tN8ePVpuKV-IyxoEO; ze{A+~R9@c<(c%N~YKvS6z6m0_w}kD^B!n(sM_N?W9Hpd7^) z45w%A-z;ZA`_KzKHSVITbR)kdzL%nP(WJ?4Cn_U#OqoL54! zPf2fH`+ZTZlIO!to*K|6T7wxJ^g~O}c%`nvuI`+aQa%(AhV0L1X-|jLhnQt1FJYBE z{95#x7hoyYK+gG-bj+Wa#K2?jJSA;n)UJ%(@576-q0nJ7qoF-aa#Y|Q{)hYXw}6eo z(No#UgA(LO7U4P-<#q!%d94JZujZ7`xE&0@i*9rLOy#FT!uM$&1~*3Qy|jMicryUE zBmQZq4)EKc-hrC7Vx7Ky{c2`+fqx_U7uCTe=uUF+XQW=)v^JVmSAaRZXJ**>6zCoF z%#Fr>vqwZxU*z{?#Mpe+e$dB9S_oE$#9Tc+n;yU9z0FJm=6k6^E&H2e1H!#J_#EfW zB;a}aeKo7vf$>V~Y%x3WxF6gC(uRbKG9E+6XuH=;g9GblU*!nFupga*=Bo5o=2C~{ z#(Gis(SoM?I(VHNl8pVr{`AAi3WWK0qwl4fAhR6p<(NKjIY!~N6djkC)dciKhxIcAGF2*~r-e=V zKPkw**ncTuDY#7r+Tc8fr`ys0z9Kt^jMooC}U!N z3COPqEXkr!;c4N;>*~NqbDZpAdO;^Z2!_%;28Uyt^q>4q*q%W|0xa3W!Zrk=`pO@_ zOoXd+2@JNS%8 zzp2R~e&nWsA?%v+eCZW<9xy@K@#HaeoDh9sz&|7ch6NBf8Qc#oA$>7o(C|R~QGIKk z`&$F2H&7`2A^0}UB3c`^^h&94$;?&S{y8*JKW}$ADkP{p{jhxnWMJN;wz`0sS-4+O z%@qL6?Dd2)LZvDM!VMsebFzTD!BD-)Dqz}EN9WP6=T zJe&5>a*paA;T^C1>jMp7g!XK=cz4z>r{S7M(D2GV!NYm*mHz!eP` zvMCvG=C;JcjT4PL0vlr*?NJEWxJpoA`0fYeVL?6gFN?*zZZZwKh`l+4g@NyJ(|iwt zNg_oAa!-r0=xVa$t{CPPIYy4`Tlw&gpmD|bG>a5+36!XOa_ks@_V^lR|DGJc>M$ z%~wSQxV36IZd~boYIMOwN3;3KE0hJe`8;9dI$oB?sqrk{U_?3O4IU5UZM8vnA1JE; z+7_?Y&+l|pSnIOn~m`Bb6 zoe?Y(*N_Ks3kj$+Wso=EE%Q-q4t&{~ouj!p5&F&2zp@(2W*w$$pSu&d_LK`tUovDFOzQlMdzibcXznYs?_QN97 z1EW^gJ+H$70T~iy_$Eg%J3xJ%n&cvT&U!I-%oM1l*v8^PEhJA z3ghR-l;(^%o?6rDQlZi9^;qUP8Xu1!e7pPgb?FA50e6=`oTF{L2Ctzn3H*weD5FidgWYFtudRtzUF= zyR*!$fhY0FB0d=1a@->Xd^eY7`W704yP@2{(3Il(CFp%8F-!0qk?HPD!R!$? z6O_tqANSppF6lxLpAX!7O?ukli>Nm#Twz=wS0EBZG~_$oqWZaOBIR?a*@hkXRw4@{ z5pvn+vP`(_iB{ERXAkq6Y4@yixr1tk{!U~yd0XJ`%s1?~2cs1Ohjw&jYd9&~vSsA^ zfYdvS)7HudyMx3PibVVYcZK^^CdK9_P1Q|4ZYtzwgbzXcK!Ak=b=nQu--KyQXMNvr z{LL{&|EPK|#t84(WLX1BCjYIF`Y_m3@A)WFT>s))LREB`?yM;9d!APIF=TzmIzc?N z_(ECG)05uS-w%3k6ZsM$?aBO_;vvK+rCH5TY2(SUV9N9P{RR&Se&*n@_d7bY)Wpz`n@t;-oB|XG{fWqiatI?)cbTIiB!s^X`^Z+J`On;$#nKHhnoRl#Jp`gqZCQvdKfo8qpl z*Z9e7anTglC$?28=~h4EV%uJHY^-)#t`zAM>8g#sX1C;e1LMHl8d^=DrzP~~v*yc4 zHj8Jr%P+A4tOyvL${FB^H)zef&%vb~I#HtgF&IqlkA}732&HyzayG0#KczUPol5#z zU#Pt(?xVMsHgq+545B_|bZ7#SRt%aptfFUk-|0Slh#qf4ns8~F?0=Ey?hjk*a9~`?$7}p!%cH~> zvWiWoM-*MVizt&uQy{AHS>uuXyfo7+Ci(51IwOVlPn-*x4<(5|@7ImAOL8aw{ zv|~wToY#SB#pf9s8|DL#bG}_dF^t>uHxMl9wd;)Et|{#HzG!RD-?_vQQCxe?vmbFu zu@=X%;&pghHW*+5=R1WJ$9lIK+UqgHepg@$F0prkbop@NK#;2#U~}APWwt|Fiba3M zP!v?a6={;b+Mih){|;Bt69sc`!)#&HMWOlPaB&`%EplZXd43-R)=jLLH~retu$U@& zcL|mfUDJsQzP*9znk*Hls9l2(1lGsO$Ivl>LCb&+hNn=^B%wWgUl?icGLawQB^Pfo z+!hp9HF%*{q!U#e^(PY*grvES2x1`ga5DM}BS`18J&RmDJaK3o{9bX^S{#TA^;Vo{ z*qq=1%OiVFiQzKXvM6lLGaluMZg{13bU BAVL5D literal 15967 zcmch;V{mUz5H|RWZQHhO+sTcS8{2knY#TQ=Zfx7OZJV3_yZd2xt9EPOt*!lX>P(%P zQ!`!NJx}-39j+)Z0SAo@4FCY(q$EX^0RW(%S0Df+_|KEZCGF;C1ZpNECjjbd2>l{({_VQKts*0Vz=ytB)M63~5fOt|#y2AY zmQ2AbCq#c^z>-n{E0eb3Z77IBcKm9Xn+`l^W>S9_izabroop8$5EQZ3pRJGF8YS>N z?NFZlM$RYu4X&3}SJ%9!xB|8%tFKDNvZPrH$@F9%*LkziX)`B=L}FmLW%Lim>NnBN zjvUFm0B`%uIZx1WHAyJ^&a399Tl)1wP_EXwmt{$V z^!?}V>b^#%>v_E*+9uA?rtV|;cH$di{N;6Gm1=v`o+s8Aq6AQ1~pP*^*am8}cZ z@`s{9!_i$Kb{1Kv}wWmLlLf7`#9j^y3%-$OwDNX9Du9{ z3qs&_L`7_k>fc?T{mw7Ah8l1>;xXn|pRMD8O6Et)dY18+kB}divXke1y0Cr4jm=s( zyj!%HVfV2dwc79RKTUPsghK7)cXzq=L$JWV*Ul7Hz<~cZ(GemdLb4Jv9u5{n7e4`t zq_)ZRWI>;3$)x6%bvu_hYLFT5DRWvt7(W+Bb==OsSm!FA14Ja+mypd)&#N_?mlY6= zWFo6}&4>A_+We6oQ_XOJ)&h-#GVDpqHm< z?gRH6U_ggz4Q^#*5T4e2(@F`@Xz3j^%nkM7V*r$u7ZFGdyV}}@@WQ+8KL)@6n^r;n ziMc5_lVhQ|#Z@USfEjgiqf-HT0A);zC<>Ci!>;vcp$4&~-QS%LzI@f-T`GD2q5x(_ zCQ4MzQC$2#M%(@<7Y@*S6uIW3y;xJ+uUhizv=zF+@uzn@gFM3l5s8>4(9_H);`*lu zHiun0TVz2fZ7z#Lpp2zjd6Vpd&nW)aNlpE%vH_Y~R0|!&rxN-eW}iVZ?~VBRRrX7g zrvv%s&B$oMPzgnR)gu00?rxrM3dx41{)wMj?%BMTb z?G|kyVQQ4P^!a#CV=1#9pBf|1xDs)m2iq-A>ig_`QE8?;G$RC6t`{Q z_qYmFi}AQm+qk?50;$LMZKQb(PtS9iM0K}y?FM#QtmZOH&)xhU&cZz+SQ;D0zX6-g z*dDc=GSN%R<~I~o|3+|R_Hv!VoBMVoz(ZD0U=A~T3R7XZ8?lvdOUR!1&&z+KEtc<6V+i8Co@WwH8q??|YK<(yoQWh~Euchm@ zE`n1rX_v>}4@|fqD3ZrxcQe|_-I}GJ4~x41$L^%Z^)ht!=w(TFiXPgz>)?1TGLS7-~%3HRLP2cOthP=iYZ`K`!> zn>4%3a4x`jNwp5P#hnr;y7(D~svi>sp{jV`Y*oAKrof+8iFrDDz%L95iNsg)AT$iX zM&n!XB$LcJ+#f6`i1Ok70SffOfi|_J494>SS@mbhSci+xi05LsY zlgp<+_|Hu8)pamQM6haG0gb7{W~pgxx0kklyR8D#7U$`YmpNfg%!(g-pS{|`HgKGx z-{w|c ); } @@ -41,3 +44,5 @@ Footer.propTypes = { export default function init(ngModule) { ngModule.component('footer', react2angular(Footer, [], ['clientConfig', 'currentUser'])); } + +init.init = true; diff --git a/client/app/components/Footer.test.js b/client/app/components/Footer.test.js new file mode 100644 index 0000000000..81a157ebfc --- /dev/null +++ b/client/app/components/Footer.test.js @@ -0,0 +1,16 @@ +import React from 'react'; +import renderer from 'react-test-renderer'; +import { Footer } from './Footer'; + +test('Footer renders', () => { + const clientConfig = { + version: '5.0.1', + newVersionAvailable: true, + }; + const currentUser = { + isAdmin: true, + }; + const component = renderer.create(
); + const tree = component.toJSON(); + expect(tree).toMatchSnapshot(); +}); diff --git a/client/app/components/NoTaggedObjectsFound.jsx b/client/app/components/NoTaggedObjectsFound.jsx index a64b2c68e6..f552e6e8a8 100644 --- a/client/app/components/NoTaggedObjectsFound.jsx +++ b/client/app/components/NoTaggedObjectsFound.jsx @@ -1,17 +1,13 @@ import React from 'react'; import PropTypes from 'prop-types'; import { react2angular } from 'react2angular'; -import { BigMessage } from './BigMessage.jsx'; +import { BigMessage } from '@/components/BigMessage'; +import TagsControl from '@/components/tags-control/TagsControl'; function NoTaggedObjectsFound({ objectType, tags }) { return ( - No {objectType} found tagged with - {Array.from(tags).map(tag => ( - - {tag} - - ))}. + No {objectType} found tagged with . ); } @@ -24,3 +20,5 @@ NoTaggedObjectsFound.propTypes = { export default function init(ngModule) { ngModule.component('noTaggedObjectsFound', react2angular(NoTaggedObjectsFound)); } + +init.init = true; diff --git a/client/app/components/QueryEditor.jsx b/client/app/components/QueryEditor.jsx new file mode 100644 index 0000000000..9da2abb81f --- /dev/null +++ b/client/app/components/QueryEditor.jsx @@ -0,0 +1,283 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { map } from 'lodash'; +import Tooltip from 'antd/lib/tooltip'; +import { react2angular } from 'react2angular'; + +import AceEditor from 'react-ace'; +import ace from 'brace'; +import toastr from 'angular-toastr'; + +import 'brace/ext/language_tools'; +import 'brace/mode/json'; +import 'brace/mode/python'; +import 'brace/mode/sql'; +import 'brace/theme/textmate'; +import 'brace/ext/searchbox'; + +import localOptions from '@/lib/localOptions'; +import AutocompleteToggle from '@/components/AutocompleteToggle'; +import { DataSource, Schema } from './proptypes'; + +const langTools = ace.acequire('ace/ext/language_tools'); +const snippetsModule = ace.acequire('ace/snippets'); + +// By default Ace will try to load snippet files for the different modes and fail. +// We don't need them, so we use these placeholders until we define our own. +function defineDummySnippets(mode) { + ace.define(`ace/snippets/${mode}`, ['require', 'exports', 'module'], (require, exports) => { + exports.snippetText = ''; + exports.scope = mode; + }); +} + +defineDummySnippets('python'); +defineDummySnippets('sql'); +defineDummySnippets('json'); + +function buildKeywordsFromSchema(schema) { + const keywords = {}; + schema.forEach((table) => { + keywords[table.name] = 'Table'; + table.columns.forEach((c) => { + keywords[c] = 'Column'; + keywords[`${table.name}.${c}`] = 'Column'; + }); + }); + + return map(keywords, (v, k) => ({ + name: k, + value: k, + score: 0, + meta: v, + })); +} + +class QueryEditor extends React.Component { + static propTypes = { + queryText: PropTypes.string.isRequired, + schema: Schema, // eslint-disable-line react/no-unused-prop-types + addNewParameter: PropTypes.func.isRequired, + dataSources: PropTypes.arrayOf(DataSource), + dataSource: DataSource, + canEdit: PropTypes.bool.isRequired, + isDirty: PropTypes.bool.isRequired, + isQueryOwner: PropTypes.bool.isRequired, + updateDataSource: PropTypes.func.isRequired, + canExecuteQuery: PropTypes.func.isRequired, + executeQuery: PropTypes.func.isRequired, + queryExecuting: PropTypes.bool.isRequired, + saveQuery: PropTypes.func.isRequired, + updateQuery: PropTypes.func.isRequired, + listenForResize: PropTypes.func.isRequired, + listenForEditorCommand: PropTypes.func.isRequired, + }; + + static defaultProps = { + schema: null, + dataSource: {}, + dataSources: [], + }; + + constructor(props) { + super(props); + this.state = { + schema: null, // eslint-disable-line react/no-unused-state + keywords: [], // eslint-disable-line react/no-unused-state + autocompleteQuery: localOptions.get('liveAutocomplete', true), + liveAutocompleteDisabled: false, + // XXX temporary while interfacing with angular + queryText: props.queryText, + }; + langTools.addCompleter({ + getCompletions: (state, session, pos, prefix, callback) => { + if (prefix.length === 0) { + callback(null, []); + return; + } + callback(null, this.state.keywords); + }, + }); + + this.onLoad = (editor) => { + // Release Cmd/Ctrl+L to the browser + editor.commands.bindKey('Cmd+L', null); + editor.commands.bindKey('Ctrl+P', null); + editor.commands.bindKey('Ctrl+L', null); + + // eslint-disable-next-line react/prop-types + this.props.QuerySnippet.query((snippets) => { + const snippetManager = snippetsModule.snippetManager; + const m = { + snippetText: '', + }; + m.snippets = snippetManager.parseSnippetFile(m.snippetText); + snippets.forEach((snippet) => { + m.snippets.push(snippet.getSnippet()); + }); + snippetManager.register(m.snippets || [], m.scope); + }); + editor.focus(); + this.props.listenForResize(() => editor.resize()); + this.props.listenForEditorCommand((e, command, ...args) => { + switch (command) { + case 'focus': { + editor.focus(); + break; + } + case 'paste': { + const [text] = args; + editor.session.doc.replace(editor.selection.getRange(), text); + const range = editor.selection.getRange(); + this.props.updateQuery(editor.session.getValue()); + editor.selection.setRange(range); + break; + } + default: + break; + } + }); + }; + + this.formatQuery = () => { + // eslint-disable-next-line react/prop-types + const format = this.props.Query.format; + format(this.props.dataSource.syntax || 'sql', this.props.queryText) + .then(this.updateQuery) + .catch(error => toastr.error(error)); + }; + } + + static getDerivedStateFromProps(nextProps, prevState) { + if (!nextProps.schema) { + return { keywords: [], liveAutocompleteDisabled: false }; + } else if (nextProps.schema !== prevState.schema) { + const tokensCount = nextProps.schema.reduce((totalLength, table) => totalLength + table.columns.length, 0); + return { + schema: nextProps.schema, + keywords: buildKeywordsFromSchema(nextProps.schema), + liveAutocompleteDisabled: tokensCount > 5000, + }; + } + return null; + } + + updateQuery = (queryText) => { + this.props.updateQuery(queryText); + this.setState({ queryText }); + }; + + toggleAutocomplete = (state) => { + this.setState({ autocompleteQuery: state }); + localOptions.set('liveAutocomplete', state); + } + + render() { + // eslint-disable-next-line react/prop-types + const modKey = this.props.KeyboardShortcuts.modKey; + + const isExecuteDisabled = this.props.queryExecuting || !this.props.canExecuteQuery(); + + return ( +
+
+
+ +
+ +
+
+ + Add New Parameter ({modKey} + P) + + } + > + + + + + + + + {this.props.canEdit ? ( + + + + ) : null} + + {/* + Tooltip wraps disabled buttons with `` and moves all styles + and classes to that ``. There is a piece of CSS that fixes + button appearance, but also wwe need to add `disabled` class to + disabled buttons so it will be assigned to wrapper and make it + looking properly + */} + + +
+
+
+
+ ); + } +} + +export default function init(ngModule) { + ngModule.component('queryEditor', react2angular(QueryEditor, null, ['QuerySnippet', 'Query', 'KeyboardShortcuts'])); +} + +init.init = true; diff --git a/client/app/components/__snapshots__/Footer.test.js.snap b/client/app/components/__snapshots__/Footer.test.js.snap new file mode 100644 index 0000000000..853e38f1ce --- /dev/null +++ b/client/app/components/__snapshots__/Footer.test.js.snap @@ -0,0 +1,37 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Footer renders 1`] = ` + +`; diff --git a/client/app/components/alerts/alert-subscriptions/index.js b/client/app/components/alerts/alert-subscriptions/index.js index 24c2a86d32..e0dc5793e4 100644 --- a/client/app/components/alerts/alert-subscriptions/index.js +++ b/client/app/components/alerts/alert-subscriptions/index.js @@ -111,3 +111,6 @@ export default function init(ngModule) { controller, })); } + +init.init = true; + diff --git a/client/app/components/app-header/app-header.html b/client/app/components/app-header/app-header.html index 7fe846c67e..cb31912cf7 100644 --- a/client/app/components/app-header/app-header.html +++ b/client/app/components/app-header/app-header.html @@ -86,7 +86,7 @@

WyO8zQaaO)9cnWU?3WEiFI1 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 diff --git a/client/app/assets/images/destinations/pagerduty.png b/client/app/assets/images/destinations/pagerduty.png new file mode 100644 index 0000000000000000000000000000000000000000..5ea3c03e362ffa9bd163621326fcdce4c879f645 GIT binary patch literal 8408 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 small { - font-size: 11px; - color: #C5C5C5; - margin-left: 10px; - } -} - -.list-group-item-heading, -.list-group-item-text { - .text-overflow(); -} - -.list-group-item-text { - display: block; - - &:not(:last-child) { - margin-bottom: 4px; - } -} - -.list-group-img { - width: 38px; - height: 38px; - border-radius: 2px; -} +.list-group { + margin-bottom: 0; + + &.lg-alt .list-group-item { + border: 0; + } + + &:not(.lg-alt) { + &.lg-listview .list-group-item { + border-left: 0; + border-right: 0; + + &:last-child { + border-bottom: 0; + } + } + } +} + +tags-list { + a { + line-height: 1.1; + } +} + +.tags-list__name { + display: inline-block; + overflow: hidden; + text-overflow: ellipsis; + width: 88%; + line-height: 1.3; +} + +.max-character { + .text-overflow(); +} + +.list-group-item { + &.active { + button { + color: white; + } + } + .cr-alt { + line-height: 100%; + margin-top: 2px; + } +} + +.list-group-item-heading { + margin-bottom: 2px; + color: #333; + + & > small { + font-size: 11px; + color: #C5C5C5; + margin-left: 10px; + } +} + +.list-group-item-heading, +.list-group-item-text { + .text-overflow(); +} + +.list-group-item-text { + display: block; + + &:not(:last-child) { + margin-bottom: 4px; + } +} + +.list-group-img { + width: 38px; + height: 38px; + border-radius: 2px; +} diff --git a/client/app/assets/less/inc/visualizations/counter-render.less b/client/app/assets/less/inc/visualizations/counter-render.less index f123093e90..c57c297a98 100755 --- a/client/app/assets/less/inc/visualizations/counter-render.less +++ b/client/app/assets/less/inc/visualizations/counter-render.less @@ -3,52 +3,43 @@ counter-renderer { text-align: center; padding: 15px 10px; overflow: hidden; -} -counter-renderer counter { - margin: 0; - padding: 0; - display: block; - font-size: 80px; - overflow: hidden; - height: 200px; -} + counter { + margin: 0; + padding: 0; + font-size: 80px; + line-height: normal; + overflow: hidden; + display: flex; + align-items: center; + justify-content: center; -counter-renderer value, -counter-renderer counter-name, -counter-renderer counter-target { - font-size: 1em; - line-height: 1em; - display: block; -} + value, + counter-target { + font-size: 1em; + display: block; + } -counter-renderer value .ruler, -counter-renderer counter-name .ruler, -counter-renderer counter-target .ruler { - display: block; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - font: inherit; - line-height: inherit; - margin: 0; - padding: 0; -} + counter-name { + font-size: 0.5em; + display: block; + } -counter-renderer counter-target { - color: #ccc; -} + &.positive value { + color: #5cb85c; + } -counter-renderer counter.positive value { - color: #5cb85c; -} + &.negative value { + color: #d9534f; + } + } -counter-renderer counter.negative value { - color: #d9534f; - margin-right: 15px; -} + counter-target { + color: #ccc; + } -counter-renderer counter-name { - font-size: 0.5em; - display: block; + counter-name { + font-size: 0.5em; + display: block; + } } diff --git a/client/app/assets/less/main.less b/client/app/assets/less/main.less index 11f67bcf16..db3d55c294 100644 --- a/client/app/assets/less/main.less +++ b/client/app/assets/less/main.less @@ -1,6 +1,3 @@ -@import '~antd/lib/style/core/iconfont.less'; -@import '~antd/lib/input/style/index.less'; -@import '~antd/lib/date-picker/style/index.less'; @import 'redash/ant'; /** LESS Plugins **/ @@ -14,8 +11,8 @@ @import '~ui-select/dist/select.css'; @import '~angular-toastr/src/toastr'; @import '~angular-resizable/src/angular-resizable.css'; -@import '~pace-progress/themes/blue/pace-theme-minimal.css'; @import '~material-design-iconic-font/dist/css/material-design-iconic-font.css'; +@import '~pace-progress/themes/blue/pace-theme-minimal.css'; @import 'inc/angular'; @import 'inc/variables'; @@ -81,6 +78,7 @@ @import 'redash/redash-newstyle'; @import 'redash/redash-table'; @import 'redash/query'; +@import 'redash/tags-control'; diff --git a/client/app/assets/less/redash/ant.less b/client/app/assets/less/redash/ant.less index 9d961c032f..deb8d75555 100644 --- a/client/app/assets/less/redash/ant.less +++ b/client/app/assets/less/redash/ant.less @@ -1,3 +1,10 @@ +@import '~antd/lib/style/core/iconfont.less'; +@import '~antd/lib/style/core/motion.less'; +@import '~antd/lib/input/style/index.less'; +@import '~antd/lib/date-picker/style/index.less'; +@import '~antd/lib/tooltip/style/index.less'; +@import '~antd/lib/select/style/index.less'; + // Overwritting Ant Design defaults to fit into Redash current style @font-family-no-number : @redash-font; @font-family : @redash-font; @@ -7,3 +14,25 @@ @border-color-base : #e8e8e8; @primary-color : @blue; + +// Fix for disabled button styles inside Tooltip component. +// Tooltip wraps disabled buttons with `` and moves all styles +// and classes to that ``. This resets all button styles and +// turns it into simple inline element (because now it's wrapper is a button) +.btn { + button[disabled] { + -moz-appearance: none !important; + -webkit-appearance: none !important; + appearance: none !important; + border: 0 !important; + outline: none !important; + background: transparent !important; + margin: 0 !important; + padding: 0 !important; + } +} + +// Fix for Ant dropdowns when they are used in Boootstrap modals +.ant-dropdown-in-bootstrap-modal { + z-index: 1050; +} diff --git a/client/app/assets/less/redash/query.less b/client/app/assets/less/redash/query.less index 30231788a3..20791a8c47 100644 --- a/client/app/assets/less/redash/query.less +++ b/client/app/assets/less/redash/query.less @@ -95,10 +95,6 @@ edit-in-place p.editable:hover { margin-bottom: 10px; } -.source-control { - -} - .ace_editor.ace_autocomplete .ace_completion-highlight { text-shadow: none !important; background: #ffff005e; @@ -225,26 +221,29 @@ edit-in-place p.editable:hover { } .page-header--new { - .label-default { - margin-right: 3px; + .query-tags, + .query-tags__mobile { + .label-default, + .label-warning { + margin-right: 3px; + } } } .page-header--query { - display: flex; - align-items: center; - - h3 { - display: inline-block; + .page-title { + display: block; + margin-left: 15px; + margin-right: 15px; } } a.label-tag { background: fade(@redash-gray, 15%); - color: #333; + color: darken(@redash-gray, 15%); &:hover { - color: #333; + color: darken(@redash-gray, 15%); background: fade(@redash-gray, 25%); } } @@ -527,58 +526,89 @@ nav .rg-bottom { } } -// Smaller screens - -@media (max-width: 880px) { - .query-fullscreen { - flex-direction: column; - overflow: hidden; +.query-tags { + display: inline-block; + vertical-align: middle; + margin-top: -3px; // padding-top of tags +} - nav { - display: none; - } +.query-tags__mobile { + display: none; + margin: -5px 0 0 0; + padding: 0 0 0 23px; +} - .schema-container { - display: none; - } +.table--permission { + .profile__image { + margin-right: 0; } +} - .query-page-wrapper { - .container { +.mp__permission-type { + text-transform: capitalize; +} + +// Smaller screens + +@media (max-width: 880px) { + .page-header--query { + .page-title { margin-left: 0; margin-right: 0; } } - .query-fullscreen .query-metadata__mobile { - display: block; - border-bottom: 1px solid #efefef; - padding: 10px 0; - min-height: 0 !important; - flex-shrink: 0; - } - - a.navbar-brand { + .query-tags:not(.query-tags__empty) { display: none; } - .page-header--query { - padding-left: 0px !important; + .query-tags__mobile:not(.query-tags__empty) { + display: block; + } - h3 { - line-height: 1.25; - } + .btn--showhide, + .query-actions-menu .dropdown-toggle { + margin-bottom: 5px; } - .query-fullscreen .content { - height: 100%; + .btn-publish { + display: none; } - .datasource-small { - visibility: visible; + .tab-nav .tab-new-vis { + display: none; } .query-fullscreen { + flex-direction: column; + overflow: hidden; + + nav { + display: none; + } + + .schema-container { + display: none; + } + + .query-metadata__mobile { + border-bottom: 1px solid #efefef; + min-height: 0 !important; + flex-shrink: 0; + padding: 10px 15px; + display: flex; + flex-wrap: nowrap; + justify-content: space-between; + align-items: center; + + .profile__image_thumb { + margin: 0 5px 0 0; + } + + .query-metadata__property { + white-space: nowrap; + } + } main { flex-direction: column-reverse; @@ -600,18 +630,31 @@ nav .rg-bottom { .content { width: 100%; + height: 100%; + + .static-position__mobile { + position: static !important; + } + } + + .bottom-controller-container { + z-index: 9; } } -} + .query-page-wrapper { + .container { + margin-left: 0; + margin-right: 0; + } + } -@media (max-width: 438px) { - .btn--showhide { - margin-bottom: 5px; + a.navbar-brand { + display: none; } - .btn-publish { - margin-bottom: 5px; + .datasource-small { + visibility: visible; } } @@ -629,6 +672,6 @@ nav .rg-bottom { } .btn-edit-visualisation { - display: none; + } } diff --git a/client/app/assets/less/redash/redash-newstyle.less b/client/app/assets/less/redash/redash-newstyle.less index 38a8ce650b..2f18c05ad4 100644 --- a/client/app/assets/less/redash/redash-newstyle.less +++ b/client/app/assets/less/redash/redash-newstyle.less @@ -1,3 +1,5 @@ +@import (reference, less) '~bootstrap/less/labels.less'; + // Variables @redash-gray: rgba(102, 136, 153, 1); @redash-orange: rgba(255, 120, 100, 1); @@ -366,8 +368,8 @@ body { page-header, .page-header--new { h3 { - margin: 0; - line-height: 1.75; + margin: 0.2em 0; + line-height: 1.3; font-weight: 500; } } @@ -449,10 +451,27 @@ page-header, .page-header--new { background: fade(@redash-gray, 85%); } +.label-tag-unpublished { + background: fade(@redash-gray, 85%); +} + +.label-tag-archived { + .label-warning(); +} + .label-tag { background: fade(@redash-gray, 10%); color: fade(@redash-gray, 75%); +} + +.label-tag-unpublished, +.label-tag-archived, +.label-tag { margin-right: 3px; + display: inline-block; + margin-top: 2px; + max-width: 24ch; + .text-overflow(); } .tab-nav > li > a { @@ -732,6 +751,14 @@ page-header, .page-header--new { margin-top: 2px; } +.tags-list { + + .badge-light { + background: fade(@redash-gray, 10%); + color: fade(@redash-gray, 75%); + } +} + .dropdown-menu--profile { li { width: 200px; @@ -805,10 +832,6 @@ text.slicetext { } .query-page-wrapper { - .page-header--query { - padding-bottom: 5px !important; - } - h3 { font-size: 18px; } @@ -860,6 +883,16 @@ text.slicetext { } } +@media (min-width: 768px) and (max-width: 850px) { + .menu-search { + width: 175px; + } + + a.navbar-brand { + display: none !important; + } +} + @media (max-width: 1084px) { .dropdown--profile__username { display: none; diff --git a/client/app/assets/less/redash/tags-control.less b/client/app/assets/less/redash/tags-control.less new file mode 100644 index 0000000000..3aaf402620 --- /dev/null +++ b/client/app/assets/less/redash/tags-control.less @@ -0,0 +1,13 @@ +.tags-control { + display: flex; + flex-direction: row; + flex-wrap: wrap; + align-items: stretch; + justify-content: flex-start; + line-height: 1em; + + &.inline-tags-control { + display: inline-block; + vertical-align: middle; + } +} diff --git a/client/app/components/AutocompleteToggle.jsx b/client/app/components/AutocompleteToggle.jsx new file mode 100644 index 0000000000..e74e0a9047 --- /dev/null +++ b/client/app/components/AutocompleteToggle.jsx @@ -0,0 +1,43 @@ +import React from 'react'; +import Tooltip from 'antd/lib/tooltip'; +import PropTypes from 'prop-types'; +import '@/redash-font/style.less'; +import recordEvent from '@/lib/recordEvent'; + +export default function AutocompleteToggle({ state, disabled, onToggle }) { + let tooltipMessage = 'Live Autocomplete Enabled'; + let icon = 'icon-flash'; + if (!state) { + tooltipMessage = 'Live Autocomplete Disabled'; + icon = 'icon-flash-off'; + } + + if (disabled) { + tooltipMessage = 'Live Autocomplete Not Available (Use Ctrl+Space to Trigger)'; + icon = 'icon-flash-off'; + } + + const toggle = (newState) => { + recordEvent('toggle_autocomplete', 'screen', 'query_editor', { state: newState }); + onToggle(newState); + }; + + return ( + + + + ); +} + +AutocompleteToggle.propTypes = { + state: PropTypes.bool.isRequired, + disabled: PropTypes.bool.isRequired, + onToggle: PropTypes.func.isRequired, +}; diff --git a/client/app/components/BigMessage.jsx b/client/app/components/BigMessage.jsx index 37d88e7ee5..e667113e6b 100644 --- a/client/app/components/BigMessage.jsx +++ b/client/app/components/BigMessage.jsx @@ -29,3 +29,5 @@ BigMessage.defaultProps = { export default function init(ngModule) { ngModule.component('bigMessage', react2angular(BigMessage)); } + +init.init = true; diff --git a/client/app/components/DateInput.jsx b/client/app/components/DateInput.jsx index 603990a0a4..e72dc4112e 100644 --- a/client/app/components/DateInput.jsx +++ b/client/app/components/DateInput.jsx @@ -45,3 +45,4 @@ export default function init(ngModule) { ngModule.component('dateInput', react2angular(DateInput, null, ['clientConfig'])); } +init.init = true; diff --git a/client/app/components/DateRangeInput.jsx b/client/app/components/DateRangeInput.jsx index 30e7151c41..0d864216ad 100644 --- a/client/app/components/DateRangeInput.jsx +++ b/client/app/components/DateRangeInput.jsx @@ -4,9 +4,6 @@ import React from 'react'; import PropTypes from 'prop-types'; import { react2angular } from 'react2angular'; import { RangePicker } from 'antd/lib/date-picker'; -import 'antd/lib/style/core/iconfont.less'; -import 'antd/lib/input/style/index.less'; -import 'antd/lib/date-picker/style/index.less'; function DateRangeInput({ value, @@ -53,3 +50,4 @@ export default function init(ngModule) { ngModule.component('dateRangeInput', react2angular(DateRangeInput, null, ['clientConfig'])); } +init.init = true; diff --git a/client/app/components/DateTimeInput.jsx b/client/app/components/DateTimeInput.jsx index 56c26ce6f9..739ec17f8d 100644 --- a/client/app/components/DateTimeInput.jsx +++ b/client/app/components/DateTimeInput.jsx @@ -50,3 +50,4 @@ export default function init(ngModule) { ngModule.component('dateTimeInput', react2angular(DateTimeInput, null, ['clientConfig'])); } +init.init = true; diff --git a/client/app/components/DateTimeRangeInput.jsx b/client/app/components/DateTimeRangeInput.jsx index 0bfba09811..5cab36c0f6 100644 --- a/client/app/components/DateTimeRangeInput.jsx +++ b/client/app/components/DateTimeRangeInput.jsx @@ -4,9 +4,6 @@ import React from 'react'; import PropTypes from 'prop-types'; import { react2angular } from 'react2angular'; import { RangePicker } from 'antd/lib/date-picker'; -import 'antd/lib/style/core/iconfont.less'; -import 'antd/lib/input/style/index.less'; -import 'antd/lib/date-picker/style/index.less'; function DateTimeRangeInput({ value, @@ -58,3 +55,5 @@ export default function init(ngModule) { ngModule.component('dateTimeRangeInput', react2angular(DateTimeRangeInput, null, ['clientConfig'])); } +init.init = true; + diff --git a/client/app/components/EditInPlace.jsx b/client/app/components/EditInPlace.jsx new file mode 100644 index 0000000000..369f5d470b --- /dev/null +++ b/client/app/components/EditInPlace.jsx @@ -0,0 +1,92 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { react2angular } from 'react2angular'; + +export class EditInPlace extends React.Component { + static propTypes = { + ignoreBlanks: PropTypes.bool, + isEditable: PropTypes.bool, + editor: PropTypes.string.isRequired, + placeholder: PropTypes.string, + value: PropTypes.string, + onDone: PropTypes.func.isRequired, + }; + + static defaultProps = { + ignoreBlanks: false, + isEditable: true, + placeholder: '', + value: '', + }; + constructor(props) { + super(props); + this.state = { + editing: false, + }; + this.inputRef = React.createRef(); + const self = this; + this.componentDidUpdate = (prevProps, prevState) => { + if (self.state.editing && !prevState.editing) { + self.inputRef.current.focus(); + } + }; + } + + startEditing = () => { + if (this.props.isEditable) { + this.setState({ editing: true }); + } + }; + + stopEditing = () => { + const newValue = this.inputRef.current.value; + const ignorableBlank = this.props.ignoreBlanks && newValue === ''; + if (!ignorableBlank && newValue !== this.props.value) { + this.props.onDone(newValue); + } + this.setState({ editing: false }); + }; + + keyDown = (event) => { + if (event.keyCode === 13 && !event.shiftKey) { + event.preventDefault(); + this.stopEditing(); + } else if (event.keyCode === 27) { + this.setState({ editing: false }); + } + }; + + renderNormal = () => ( + + {this.props.value || this.props.placeholder} + + ); + + renderEdit = () => + React.createElement(this.props.editor, { + ref: this.inputRef, + className: 'rd-form-control', + defaultValue: this.props.value, + onBlur: this.stopEditing, + onKeyDown: this.keyDown, + }); + + render() { + return ( + + {this.state.editing ? this.renderEdit() : this.renderNormal()} + + ); + } +} + +export default function init(ngModule) { + ngModule.component('editInPlace', react2angular(EditInPlace)); +} + +init.init = true; diff --git a/client/app/components/footer.js b/client/app/components/Footer.jsx similarity index 69% rename from client/app/components/footer.js rename to client/app/components/Footer.jsx index 622c03eee8..bd1f06efda 100644 --- a/client/app/components/footer.js +++ b/client/app/components/Footer.jsx @@ -3,9 +3,12 @@ import PropTypes from 'prop-types'; import { react2angular } from 'react2angular'; -function Footer({ clientConfig, currentUser }) { - const version = clientConfig.version; +import frontendVersion from '../version.json'; + +export function Footer({ clientConfig, currentUser }) { + const backendVersion = clientConfig.version; const newVersionAvailable = clientConfig.newVersionAvailable && currentUser.isAdmin; + const separator = ' \u2022 '; let newVersionString = ''; if (newVersionAvailable) { @@ -18,12 +21,12 @@ function Footer({ clientConfig, currentUser }) { return (