Compare commits

...
Author SHA1 Message Date
BogdanandGitHub c198535292 Change slice ids in the position json during dashboard import. (#1380)
* Change slice ids in the position json during dashboard import.

* Update slice ids in the dashboard json metadata.
2016-10-20 09:17:51 -07:00
ShengyaoQianandMaxime Beauchemin ece69fbb75 Fix migration for make creator owners (#1262) 2016-10-20 08:51:13 -07:00
Ryan YeandMaxime Beauchemin 458651fa3e Add parens for custom where and having (#1337) 2016-10-20 08:22:21 -07:00
Maxime BeaucheminandGitHub b2f7081c6f bumping versions of JS packages to latest (#1352)
* bumping versions of JS packages to latest

* Pining mapbox-gl back to previous version

* bump mapbox-gl to 0.26 ad react-map-gl to 1.7.0
2016-10-19 10:06:11 -07:00
Maxime BeaucheminandGitHub c255e89219 [sqllab] show partition metadata for Presto (#1342) 2016-10-19 09:17:08 -07:00
Nick BarnwellandMaxime Beauchemin 2edce5bf8a Enable "Run Query in New Tab" in SQL Lab (#1343)
* Enable "Clone to New Tab" btn in QueryHistoryTable

Method #1; doesn't feel very clean.

Going to attempt to reimplement using an action and changing state directly
through the reducer rather than creating a new QueryEditor object directly from
the QueryTable

* Move Clone Logic to Action

* Implement PR feedback

* Clean up reducer action; fix bug

Bug => Attempting to clone anything other than the most recent Query for a given
TabbedQueryEditor would throw an exception, because we depended on lastQueryId
to find the title of the QueryEditor to clone. Since you can only activate a
clone from the currently active tab, we can instead fetch the ID of the Editor
to copy the Title of from the tip of tabHistory.

* Tests for Reducer Action

* Fix CodeClimate feedback
2016-10-18 16:02:29 -07:00
Maxime BeaucheminandGitHub 8f299448ea [bugfix] text as subquery fails with 'Series Limit' (#1347) 2016-10-17 18:36:49 -07:00
Maxime BeaucheminandGitHub ecb951bb74 Specify the metric to order by for Series Limit (#1351) 2016-10-17 18:34:26 -07:00
Riccardo MagliocchettiandMaxime Beauchemin 0dff6a9030 Add quarter time grain to postgresql (#1362)
The timestamp returned is the start date of the period.

Reference:
https://www.postgresql.org/docs/9.1/static/functions-datetime.html
2016-10-17 18:32:47 -07:00
vera-liuandGitHub 2095095895 Fixed big number issue (#1355) 2016-10-15 10:40:16 -07:00
Maxime Beauchemin 4fc8a17f2a [hotfix] use instead of prod for Travis build, take 3 2016-10-15 08:40:10 -07:00
Maxime Beauchemin 3cb737f8c8 [hotfix] use instead of prod for Travis build, take2 2016-10-15 08:11:37 -07:00
Maxime Beauchemin 7449aa813b [hotfix] use instead of prod for Travis build 2016-10-15 07:58:41 -07:00
Maxime BeaucheminandGitHub 7a3bcc227c [bugfix] NaN issue in Big Number viz (#1346) 2016-10-14 15:08:52 -07:00
Alanna ScottandGitHub b669a14081 [explore-v2] make chart container work with existing visualization files (#1333)
* make chart container work with nvd3_vis.js

* map vis to module, remove unneeded components

* fix linting

* use existing query and save btns, don't fork more things

* comment out chart and exploreviecontainer specs

* make a change because i think the js test is failing spuriously
2016-10-14 12:54:18 -07:00
Alanna ScottandGitHub 9db4cc8c6d add node/npm versions to contributing.md (#1344)
* add node and npm versions

* use lower case npm

* update wording
2016-10-14 00:00:12 -07:00
ComputeThisandMaxime Beauchemin 65c744f242 Fix utc time calculation if provided datetime has tz info (#1287) 2016-10-13 21:03:20 -07:00
Maxime BeaucheminandGitHub 82bcadf7f8 Moving 'CSS TEmplates' to the Manage menu category (#1336) 2016-10-13 20:55:44 -07:00
BogdanandGitHub f0f8478922 Revert "Override the role with perms for give datasources." (#1345) 2016-10-13 19:21:21 -07:00
BogdanandGitHub 40e7057bce Override the role with perms for give datasources. (#1335)
* Override the role with perms for give datasources.

* Address comments.
2016-10-13 18:18:03 -07:00
BogdanandGitHub 11a8e3591d Some dashboard import/export fixes. (#1340) 2016-10-13 14:36:39 -07:00
Maxime Beauchemin 5bea3986b2 [hotfix] handling json errors in explore view 2016-10-12 19:42:03 -07:00
Maxime Beauchemin 89cb726284 [hotfix] explore errors are not raise properly 2 2016-10-12 17:46:31 -07:00
Maxime Beauchemin 4e9392d21b [hotfix] explore errors are not raise properly 2016-10-12 17:20:42 -07:00
vera-liuandGitHub b785d27241 Taking out object spread operator (#1311)
* Changed eslint channel in codeclimate.yml for object spread

* Revert "Changed eslint channel in codeclimate.yml for object spread"

This reverts commit b9deb8ce84478f9c8f48ca7d41662e7222f40376.

* Took out the object spread operator
2016-10-12 15:54:51 -07:00
Alanna ScottandGitHub 451860afca remove #app styling (#1312) 2016-10-12 14:04:38 -07:00
Ryan YeandMaxime Beauchemin 4cf4e3805c Bugfix when there's only date filter in FilterBox (no groupby) (#1326) 2016-10-12 13:51:40 -07:00
Maxime BeaucheminandGitHub ef2670ca32 Using inheritance scheme to organize db specific code (#1294)
* Using inheritance scheme to organize db specific code

* Addressing comments
2016-10-12 13:50:47 -07:00
BogdanandGitHub 8626c80d3a Stop duplicating datasources (#1321)
* Prevent creating duplicate tables.

* Stop duplicating the tables and druid datasouces.

* Use sqlalchemy func.count
2016-10-12 12:48:24 -07:00
Alanna ScottandGitHub 5cb3cc2ed8 polyfill es2015 in older browsers and for phantomjs (#1323)
* use babel polyfill

* alphabetize entry files, only add babel-polyfill once for each entry
2016-10-12 10:41:26 -07:00
BogdanandGitHub 73cd2ea3b1 Import / export of the dashboards. (#1197)
* Implement import / export dashboard functionality.

* Address comments from discussion.

* Add function descriptions.

* Minor fixes

* Fix tests for python 3.

* Export datasources.

* Implement tables import.

* Json.loads does not support trailing commas.

* Improve alter_dict func

* Resolve comments.

* Refactor tests

* Move params_dict and alter_params to the ImportMixin

* Fix flask menues.
2016-10-11 17:54:40 -07:00
Dennis O'BrienandMaxime Beauchemin cd2ab42abc do not overwrite the stored password with the masked password (#1209)
* do not over-write the stored password with a masked password.
his addresses issue #1199

* added a test to validate that sending a password-masked sqlalchemy_uri does not over-write the stored sqlalchemy_uri

* requery the database object after the update.
use self.assertEqual for more informative error messages.
2016-10-11 16:49:40 -07:00
Maxime BeaucheminandGitHub bf1f5ea3de [sqllab] use encodeURIComponent for copy query URL (#1317)
had to bump babel-preset-airbnb for object-rest-spread to work in my
env.

Change the menu icon, text and tooltip to clarify the usage
2016-10-11 15:50:36 -07:00
Mihail DiordievandMaxime Beauchemin 79460abdd2 [SQLLab] Fix the usage of Redux DevTools Enhancer (#1278)
* Fix the usage of Redux DevTools Enhancer

* Fix ESLint error
2016-10-11 15:27:25 -07:00
Juho LamminmäkiandMaxime Beauchemin 1e6e144d24 Fixed viewing dashboards as anonymous (#1320) 2016-10-11 08:04:00 -07:00
Alanna ScottandGitHub fe66557bbb [explore-v2] hook up ExploreViewContainer to state and add specs (#1300)
* add getParams func to common

* get data from redux state

* specs for chart container and explore view container
2016-10-10 13:46:00 -07:00
vera-liuandGitHub f8e2ce6ff3 Change status color in tab to match with success (#1247) 2016-10-10 13:32:38 -07:00
BogdanandGitHub 19677438c2 Add cascade delete to the 1 to composite relationships. (#1295) 2016-10-09 19:06:22 -07:00
Alanna ScottandGitHub 9012b11101 add ImmutableMultiDict back to views.py (#1298) 2016-10-07 18:27:19 -07:00
Maxime BeaucheminandGitHub f70d301f0d Refactor the explore view (#1252)
* Refactor the explore view

* Fixing the tests

* Addressing comments
2016-10-07 16:24:39 -07:00
vera-liuandGitHub b7d1f78f5e Put formData in store (#1281)
* Put formData in store

* Reform actions and reducers

* Maded modifications based on comments:
2016-10-07 14:53:36 -07:00
Maxime BeaucheminandGitHub 3384e7598e Fixing explore actions & slice controller interactions (#1292)
* Fixing explore actions & slice controller interactions

* Addressing a comment
2016-10-07 14:06:26 -07:00
Alanna ScottandGitHub 382b8e85da [explore v2] add scrollbar to control panel container (#1284)
* add scroll bars to control panel container

* make query and save-btns block elements

* don't use react component, use custom styles

* move style to stylesheet
2016-10-07 11:57:05 -07:00
Maxime Beauchemin 0a3121c243 [doc] installation, load examples before init 2016-10-07 10:57:26 -07:00
vera-liuandMaxime Beauchemin ecfe1a2417 Updated eslinter for object rest spread (#1289) 2016-10-07 10:18:23 -07:00
Stefano OrdineandMaxime Beauchemin 609ae22bda less number of default workers. (#1206) 2016-10-07 10:16:41 -07:00
Francesco RiosaandBogdan 94578cb6a7 reduce chunk size for countries table (#1279)
One user reported the load of the "countries" table exceed
max_allowed_packet which in some configurations can be as low as 1MB.

Changing the chunk size from 500 to 50 has a small cost on the initial
load of the data (one additional second to the 17 taken previously)
while being more universally usable without changing the configuration
of the mysql server.
The new packet size is estimated to be about 500KB.

The committer has not checked other tables
2016-10-07 09:16:26 -07:00
Alanna Scottandvera-liu 8a5f050f6c [explore v2] fix explorev2 chart errors (#1277)
* fix prototypes and arrow function

* only show line chart if viz type is line

* split render lines function

* fix arrow-body linter
2016-10-06 13:07:27 -07:00
vera-liuandGitHub 5c5b393f2f Change userId, dbId to username and dbname (#1274) 2016-10-06 09:53:33 -07:00
Alanna ScottandGitHub f837733d85 [explorev2] chart and controls (#1251)
* create structure for new forked explore view (#1099)

* create structure for new forked explore view

* update component name

* add bootstrap data pattern

* remove console.log

* Created store and reducers (#1108)

* Created store and reducers

* Added spec

* Modifications based on comments

* do use bootstrap data for now

* don't deal with bootstrap data for now

* use victory as a base

* import fake line data, add fake panels, make chart fixed

* add fetch support

* get slice data from json endpoint

* render chart with slicejson

* update chart and label demo

* remove fetch config

* remove dummy control panels

* should be a func

* make TimeSeriesLineChart

* add a comment

* inner height for height

* don't need fetch yet

* trailing comma breaks in package json

* pass in viz data from props

* add style sheet

* set height on explore container

* add legend

* make chart responsive to window resize

* can't use head_css in template bc overrides head_css in basic

* fix linting

* break labelItem into own SFC, make legend SFC

* add propTypes and fix linter
2016-10-05 19:41:16 -07:00
vera-liuandGitHub 66b498de25 Added controls for Table Viz (#1253)
* Added controls for Table Viz

* Change control panel container to stateless

* Changed specs

* Resolved conflicts
2016-10-05 14:53:51 -07:00
vera-liuandMaxime Beauchemin 659bf6d7e8 Moved time column and grains to models.py (#1255) 2016-10-05 13:02:35 -07:00
Riccardo MagliocchettiandMaxime Beauchemin a8a16900e7 docs: add libsasl as system requirement on linux (#1257)
* docs: add libsasl as system requirement on linux

* docs: add openldap as system dependencies on linux too

Fix #1256
2016-10-05 13:00:38 -07:00
Riccardo MagliocchettiandMaxime Beauchemin e50b59e553 docs: document that gunicorn does not work on windows (#1258)
And suggest to use a supported platform instead.

Fix #1236
2016-10-05 12:14:09 -07:00
Riccardo MagliocchettiandMaxime Beauchemin 231804e2b4 CHANGELOG: Add proper credit to tan31989 for #744 (#1259)
As he's the author of the patch
2016-10-05 12:13:38 -07:00
vera-liuandGitHub 421a86ade5 Some polish on query search (#1222)
* Some polish
- Changed query search icon
- CopyToClipboard in action bar

* Added dbId as linked-button, made modifications based on comments

* Fix duplicated import (linting)
2016-10-05 11:43:05 -07:00
Maxime Beauchemin 140a055e4e [docs] add line in installation instructions 2016-10-05 08:56:55 -07:00
Maxime Beauchemin 5bf86d91ec [docs] suggest to upgrade pip and setuptools 2016-10-04 21:59:40 -07:00
Maxime Beauchemin 715cdd98fb Changelog for 0.11.0 2016-10-04 21:39:33 -07:00
Maxime Beauchemin 7a01d9dbcb v0.11.0 2016-10-04 21:27:19 -07:00
BogdanandGitHub 58dfa436ee Do not shadow _ function. (#1254) 2016-10-04 18:30:15 -07:00
vera-liuandGitHub 8ab5e5015a Added access check + Druid in endpoint (#1224)
* Explore control panel - Chart control, TimeFilter, GroupBy, Filters (#1205)

* create structure for new forked explore view (#1099)

* create structure for new forked explore view

* update component name

* add bootstrap data pattern

* remove console.log

* Associate version to entry files (#1060)

* Associate version to entry files

* Modified path joins for configs

* Made changes based on comments

* Created store and reducers (#1108)

* Created store and reducers

* Added spec

* Modifications based on comments

* Explore control panel components: Chart control, Time filter, SQL,
GroupBy and Filters

* Modifications based on comments

* Added access check + Druid in endpoint

* pull grains to constants

* Switch explore.html to old version
2016-10-04 13:44:45 -07:00
vera-liuandMaxime Beauchemin a92190c3ae Fix npm linting error with version string (#1249) 2016-10-04 10:40:46 -07:00
Maxime Beauchemin 055fb6110f bump version to 0.10.0.dev0 2016-10-04 08:46:31 -07:00
Maxime BeaucheminandGitHub 19ab3e2fbd Adding a 'Misc Charts' dashboard as part of the examples (#1208)
This showcases some of the visualization types that were there only as
slices, not as part of any dashboards.
2016-10-04 08:18:17 -07:00
Alanna ScottandGitHub ae54ac9d58 [sql-lab] fix react warnings in dev (#1232)
* rename file to match class

* fix react warnings

* fix proptype typo

* add missing keys
2016-10-03 23:58:47 -07:00
Alanna ScottandGitHub e6e902e8df [explore-v2] setup, basic layout, control panels, v2 url (#1233)
* Explore control panel - Chart control, TimeFilter, GroupBy, Filters (#1205)

* create structure for new forked explore view (#1099)

* create structure for new forked explore view

* update component name

* add bootstrap data pattern

* remove console.log

* Associate version to entry files (#1060)

* Associate version to entry files

* Modified path joins for configs

* Made changes based on comments

* Created store and reducers (#1108)

* Created store and reducers

* Added spec

* Modifications based on comments

* Explore control panel components: Chart control, Time filter, SQL,
GroupBy and Filters

* Modifications based on comments

* accommodate old and new explore urls

* move bootstrap data up in scope

* fix code climate issues

* fix long lines

* fix syntax error
2016-10-03 22:47:39 -07:00
vera-liuandGitHub d8638dbcf3 revert devtool alert (#1238) 2016-10-03 16:21:33 -07:00
BogdanandGitHub 9795e4a532 [SQLLab] Fix updating the database state. (#1225) 2016-10-03 10:40:27 -07:00
BogdanandGitHub e11ef994bb [SQLLab] user server for the query limit check. (#1230) 2016-10-03 09:59:08 -07:00
Maxime BeaucheminandGitHub 472679bb38 [security] allow for requesting access when denied on a dashboard view (#1192)
* Request access on dashboard view

* Fixing the unit tests

* Refactored much in the tests
2016-10-02 18:03:19 -07:00
vera-liuandGitHub d066f8b726 Added alert to install redux devtool (#1228)
* Added alert to install redux devtool

* Change to warning
2016-09-30 15:02:52 -07:00
vera-liuandGitHub aa5bbe6149 Fixed error of inserializable json for druid test (#1213)
* Fixed error of inserializable json for druid test

* Fixed indentation
2016-09-29 09:12:43 -07:00
BogdanandGitHub 9c83b900ae Bring DB in sync with the models.py (#1172)
* Bring DB in sync with the models.py

* Make sure that migrations run on multiple dbs
2016-09-28 13:55:06 -07:00
Maxime Beauchemin f0289cef3a [minor] fixing the icons in the navbar
the top item on the navbar had no icon, and the content of the menu had
two items with the same icon
2016-09-28 10:44:55 -07:00
vera-liuandGitHub 96844c5c12 Share query (#1154)
* In the tab's dropdown menu under SQL editors, copy query link option is
added. A url with copied query will pop up a new editor tab.

* Made changes based on comments

* Move copy query button to right bottom of sql editor box

* Added in Alanna's code for copy url under menu item

* Fixed linting issues
2016-09-27 22:48:01 -07:00
Maxime Beauchemin 1a29163530 A few bugfixes 2016-09-27 10:20:20 -07:00
Maxime Beauchemin b67906cfe1 [hotfix] dashboard doesn't have filter_immune_slices pre-save 2016-09-26 17:11:03 -07:00
Maxime Beauchemin 153667505f [hotfix] slice page is broken 2016-09-26 16:51:11 -07:00
AveplatterandBogdan b6f4062874 Update countries.md (#1194) 2016-09-26 10:23:59 -07:00
prokhandMaxime Beauchemin 44be42c922 Remove duplicate code for property name of SqlaTable (#1190) 2016-09-25 08:41:44 -07:00
vera-liuandGitHub 5f6ef84c4e Vliu query search (#1187)
* Query search page under SQL Lab tab

* Modifications based on comments

* Hash

* Added spec and endpoint test with modifications
based on second round comments

* Changed permission menu in https://github.com/airbnb/caravel/pull/1095/files
2016-09-23 17:41:24 -07:00
vera-liuandGitHub 551c97112c Revert "Query Search Page" (#1186) 2016-09-23 16:28:21 -07:00
vera-liuandGitHub d5c5c0d6ac Query Search Page (#1122)
* Query search page under SQL Lab tab

* Modifications based on comments

* Hash

* Added spec and endpoint test with modifications
based on second round comments

* Changed permission menu in https://github.com/airbnb/caravel/pull/1095/files
2016-09-23 16:13:18 -07:00
Maxime Beauchemin 98902599ff [hotfix] issues around empty params 2016-09-23 15:07:33 -07:00
Maxime Beauchemin 7f3c205c46 [hotfix] reactable bump to 0.14.0 2016-09-23 14:28:13 -07:00
Maxime BeaucheminandGitHub 199342a2d3 Improving the docs around managing roles (#1183) 2016-09-23 13:22:56 -07:00
Maxime Beauchemin d397c0bbf8 [hotfix] FilterBox has issues with react-select version in prod 2016-09-23 13:20:39 -07:00
Maxime Beauchemin 6e5a93a6e1 [hotfix] result set always updates 2016-09-23 12:06:57 -07:00
BogdanandGitHub df89bec712 Infer types. Smart defaults for the visualize window. Basic implementation. (#1134)
* Implement smart suggestions for the visualize flow.

* Address JS comments.

* Implement caravel dataframe wrapper.
2016-09-23 11:14:38 -07:00
Maxime BeaucheminandGitHub fc921d63a1 Simplifying source_registry (#1180) 2016-09-22 21:19:03 -07:00
Maxime BeaucheminandGitHub aed473d0d2 [filtering] define combo of slice/fields unafected by filtering (#1179)
* [FilterBox] dashboard date range filtering

* [filtering] define combo of slice/fields unafected by filtering

* adding an entry to the docs

* Addressed comments
2016-09-22 20:12:48 -07:00
Maxime BeaucheminandGitHub 7115c5458d [FilterBox] dashboard date range filtering (#1165)
* [FilterBox] dashboard date range filtering

* Addressing comments
2016-09-22 14:30:39 -07:00
Maxime BeaucheminandGitHub 8cb0bea57c [sqllab] db migration - setting Database.allow_run_sync=True (#1174) 2016-09-22 14:09:00 -07:00
Dennis O'BrienandMaxime Beauchemin 1fa18922fa when adding a new database use Database.set_sqlalchemy_uri so that the password is stored encrypted. (#1177)
This fixes a regression I introduced with PR #1137
2016-09-22 14:08:42 -07:00
Maxime BeaucheminandBogdan 49cefc8b00 Improve the Test Connection error message (#1175) 2016-09-22 13:09:10 -07:00
BogdanandGitHub cbc70d3738 Implement permission request/approve flow. (#1095)
* Implement permission request/approve flow

* Address the comments.

* Refactor the code to support multiple datasources.

* Reformat the queries.
2016-09-22 09:53:14 -07:00
BogdanandMaxime Beauchemin b855e2f1a6 Add dashboard creator as owner of the dashboard (#1166)
* Add dashboard creator as owner of the dashboard

* Address comments.
2016-09-22 08:17:27 -07:00
Dennis O'BrienandMaxime Beauchemin bc7d0ffad2 Fix TEST CONNECTION on a newly added database. (#1168)
This addresses issue #1167
If the database name passed in the request is not found in the db, test using the sqlalchemy uri passed.
2016-09-22 08:17:05 -07:00
Alanna ScottandGitHub 2f2ed229fb [redux] move some redux utils to shared file (#1164)
* move some redux utils to shared file so they can be used in the new export view too

* enhancer is a func now
2016-09-21 21:54:03 -07:00
Maxime BeaucheminandGitHub b5875764ed [security] allowing to set static headers as configuration (#1126)
* [security] setting X-Frame-Options=SAMEORIGIN to prevent clickjacking

* Changing to a more flexible approach
2016-09-21 14:41:42 -07:00
Maxime BeaucheminandGitHub f1e80a8e1b Adding indexes to table metadata (#1160) 2016-09-21 14:40:33 -07:00
ShengyaoQianandMaxime Beauchemin 5a0e06e7a2 Generalize switch between different datasources (#1078)
* Generalize switch between different datasources.

* Fix previous migration since slice model changed

* Fix warm up cache and other small stuff

* Adding modules and datasources through config

* Replace tabs w/ spaces

* Fix other style issues

* Change add method for SliceModelView to pick the first non-empty ds

* Remove tests on slice add redirect

* Change way of db migration

* Fix styling

* Fix create slice

* Small fixes

* Fix code climate check

* Adding notes on how to create new datasource in CONTRIBUTING.md

* Fix last merge

* A commit just to trigger travis build again

* Add migration to merge two heads

* Fix codeclimate

* Simplify source_registry

* Fix codeclimate

* Remove all getter methods
2016-09-21 09:52:05 -07:00
Maxime BeaucheminandGitHub ed2feaf84b fix build with utf-8 connection string option to mysql (#1159) 2016-09-20 17:30:57 -07:00
Maxime Beauchemin a1338ed52e changing the travis build matrix for faster builds 2016-09-20 14:18:31 -07:00
Maxime Beauchemin d41463ba72 changing the tox build matrix ordering 2016-09-20 14:15:07 -07:00
Alanna ScottandGitHub 0e7af8d8a6 [explore] refactor slice action button group (#1074)
* pull explore actions button group into component

* use button component

* make sure we render all action buttons

* test that embed code is correct

* don't need before each

* generalize modal trigger for use with plain links or icons
2016-09-20 13:45:27 -07:00
Maxime BeaucheminandGitHub 32980a653c [big_number] fix subheader is missing (#1146) 2016-09-20 12:24:29 -07:00
Bob ZiuchkovskiandMaxime Beauchemin d15a212e64 Add support for Werkzeug ProxyFix middleware (#1150)
Add an ENABLE_PROXY_FIX config param.  When set to True, insert the Werkzeug ProxyFix
middleware.  This middleware extracts and applies the X-Forwarded-* headers that are
inserted by common proxies and load balancers.  Fixes #1139.
2016-09-20 12:24:15 -07:00
Maxime Beauchemin 1ce8acc154 Adding license to package.json 2016-09-19 23:48:16 -07:00
Maxime BeaucheminandGitHub e8088d5c9a More improvements to SQL Lab (#1104)
* Handling timeouts

* Fixing timer on non-utc server

* Allowing async with results

* [bugfix] database is not selected

* Making sure the session is up and running

* Cleaning up query results and query objects

* Picking a groupby and metric field on visualize flow

* Showing local time in query history

* Using pull-left pull-right instead of grid layout for table metdata

Long column name were looking weird and icons were wrapping oddly

* Linting

* Eliminating east buttons under the sql editor

* Sort database dropdown by name

* Linting

* Allowing non-SELECT statements to run

* Adding a db config

* Making sqla checkout check cross-db
2016-09-19 15:28:10 -07:00
Riccardo MagliocchettiandMaxime Beauchemin 8081080709 log: be more robust against malformed input (#1127)
Refs #1113
2016-09-19 15:26:57 -07:00
Riccardo MagliocchettiandMaxime Beauchemin 8c619e8383 models: fix slice creation (#1130)
Fix #1128
2016-09-19 15:23:15 -07:00
Maxime BeaucheminandGitHub 1c544c9845 Enable list with checkboxes only on Table->Columns view (#1138) 2016-09-19 15:22:37 -07:00
Dennis O'BrienandMaxime Beauchemin ca66ba4893 Fix initialization of Database sqlalchemy_uri and password (#1137)
* move initialization of Database sqlalchemy_uri and password from DatabaseView.pre_add to utils.get_or_create_main_db.
Unit tests for mysql and postgres include username and password in the SQLALCHEMY_DATABASE_URI.

* modified test_testconn to work with sqlalchemy uri with a username and password.
2016-09-19 15:14:00 -07:00
Riccardo MagliocchettiandMaxime Beauchemin afa1f0916b Make sql test connection work with saved Database instance (#694)
Fix #596
2016-09-17 12:32:41 -07:00
Riccardo MagliocchettiandMaxime Beauchemin 69d37d8b2a Fix double escaping of dttm expressions (#744) (#1103)
If ddtm_expr is an expression with special characters then timestamp_grain escapes
the special characters already escaped.

Solution discussed with sqlalchemy upstream:
https://bitbucket.org/zzzeek/sqlalchemy/issues/3737/literal_column-given-a-specific-sql

Fix #617
2016-09-17 12:30:50 -07:00
Maxime BeaucheminandGitHub b62d7e3e8e [security] prevent XSS on FAB list views (#1125)
* [security] prevent XSS on FAB list views

* addressing comments
2016-09-16 16:25:42 -07:00
Maxime BeaucheminandGitHub e8f1baba43 [explore] giving more room to Slice title (#1118)
* [explore] giving more room to Slice title

* h2->h3 for slice title
2016-09-16 15:41:34 -07:00
vera-liuandGitHub ffe6fb849f Apply stretchMargin only to distribution bar (#1124)
* When the label size is too short, the constant for calculating
margin_size does not apply. Also nvd3 auto-adjust font-size of axis
labels.
Temporary solution here: Setting a fixed font-size on nvd3 axis labels
and a minimum threshold for label size.

* Only stretch margin for dist_bar
2016-09-16 15:39:50 -07:00
Maxime Beauchemin 3602d940eb [hotfix] lint 2016-09-16 09:47:21 -07:00
Maxime BeaucheminandGitHub 9389f89889 [welcome] removing calendar heatmap from welcome page (#1119) 2016-09-16 08:32:59 -07:00
Maxime BeaucheminandGitHub edcc2a11c6 Fixing druid culster perms to mirror sqla databases (#1123) 2016-09-16 08:32:37 -07:00
Maxime Beauchemin 2adc8a0274 [explore] clarifying force-refresh message 2016-09-16 08:20:06 -07:00
vera-liuandGitHub 2432c3155a Associate version to entry files (#1060)
* Associate version to entry files

* Modified path joins for configs

* Made changes based on comments
2016-09-15 17:20:18 -07:00
vera-liuandGitHub 2132f6715e When the label size is too short, the constant for calculating (#1120)
margin_size does not apply. Also nvd3 auto-adjust font-size of axis
labels.
Temporary solution here: Setting a fixed font-size on nvd3 axis labels
and a minimum threshold for label size.
2016-09-15 16:48:35 -07:00
Maxime Beauchemin e895807158 [bugfix] namespacing the mapbox css 2016-09-14 21:24:06 -07:00
Maxime BeaucheminandGitHub c87f34285a Animated GIFs on README (#1109) 2016-09-14 16:39:40 -07:00
Maxime BeaucheminandGitHub 17a317554c [bugfix] filter_immune_slices doesn't work (#1110) 2016-09-14 14:19:37 -07:00
BogdanandGitHub a871ee7858 Clean up the druid sync api. (#1101) 2016-09-13 17:30:36 -07:00
Ryan YeandMaxime Beauchemin 2e6b4b121f Time grain support for unix-timestamp columns (#1093)
* Add time grain support for time columnd in unix timestamp

* Fix datetime parsing for unix epoch

Since we've already converted unix epoch to datetime type,
we shouldn't specify 'unit' parameter in pandas.to_datetime

* Fix SQLite timestamp to datetime conversion
2016-09-13 11:58:47 -07:00
Maxime BeaucheminandGitHub df533d30fc [sql lab] specify schema name when generating vanila query (#1096)
* [sql lab] specify schema name when generating vanila query

* Fixing some react warnings
2016-09-12 23:09:18 -07:00
vera-liuandGitHub 1f761c61dd Single quote filter values with comma (#1084)
* Single quote filter values with comma

* refactor for codeclimate limite

* Added unit tests and tooltip
2016-09-12 13:41:05 -07:00
Maxime Beauchemin 9bf5620887 [sqllab] hide SqlEditor textarea to prevent flicker 2016-09-12 09:23:14 -07:00
Maxime BeaucheminandGitHub 1971bf653c Numerous improvements to SQL Lab (#1088)
* Improving the Visualize flow

* Fixed the timer

* CTAS

* Expiclit engine handling

* make tab full height, stretch for longer content (#1081)

* Better error handling for queries

* Hooked and fixed CSV export

* Linting

* Tying in the dttm in the viz flow

* Indicator showing when going offline

* Addressing comments, fixing the build

* Fixing unit tests
2016-09-11 07:39:07 -07:00
BogdanandGitHub c20ee0c129 Filter Druid Datasources by user permissions. (#1090) 2016-09-09 17:12:09 -07:00
Maxime BeaucheminandGitHub 6aadc6ec13 Simplifying the flow to add a table (#1068)
When specifying a table reference that can not be found, the system used
to still create the object, which would result in confusion and bad
error messages down the line. Now it will fail and not create the
object.

I also removed fields that are not necessary to worry about when
initially creating the table.
2016-09-09 16:39:11 -07:00
Alanna ScottandGitHub 8eb4cbf66e only show the reset state button if location param (#1075) 2016-09-08 13:54:00 -07:00
Alanna ScottandGitHub 0e0eaa0ccd [sql-lab] ui polish (#1079)
* we don't need tooltips on accordion menu, known ui pattern

* use consistent type sizes, bump body type down to 14px

* make editor same height as 3 selects

* table meta data accordion menu

- prevent default on accordion clicks
- always show table actions, they are more discoverable like that
- polish spacing/layout

* remove hover effect on table actions
2016-09-08 12:31:45 -07:00
BogdanandGitHub d454fb402b Add refresh druid datasources endpoint. (#1065) 2016-09-07 17:27:35 -07:00
vera-liuandGitHub 9ae231aeb8 adjust bottom margin according to label sizes on x-axis (#1029)
* adjust bottom margin according to label sizes on x-axis
Note: same as the method in heatmap.js

* add default bottom_margin to dropdown

* Change default to auto
2016-09-07 14:07:02 -07:00
BogdanandGitHub e783219a76 Add cache warmup endpoint (#1063)
* Refactor permissions in the views.py.

* Add get_viz to the slice.

* Add warm up cache endpoint.

* Resolve comments.
2016-09-06 13:58:09 -07:00
BogdanandGitHub 49e4f70f78 Disable complexity check. (#1064) 2016-09-06 12:11:56 -07:00
Maxime BeaucheminandGitHub 62c71110df Adding a ShrinkSql component (#1058) 2016-09-06 11:20:58 -07:00
BogdanandGitHub 544b3f350f Add codeclimate cli instructions. (#1043)
* Add codeclimate cli instructions.

Add the instructions for the users that want to mess around with the codeclimate cli.
It is useful to test locally the config changes.

Reviewers:
* @mistercrunch 
* @ascott 
* @vera-liu

* Update CONTRIBUTING.md

* Update CONTRIBUTING.md
2016-09-02 18:43:28 -07:00
vera-liuandGitHub 9914901099 Change the font on axis (#1028)
A minor css change to make histogram viz look consistent
2016-09-02 10:01:13 -07:00
Maxime Beauchemin badac7379e [touchup] using input-sm on text fields in explore view 2016-09-01 14:59:28 -07:00
Maxime Beauchemin 7dd01cff6f [bugfix] btn timer contianer was left behind 2016-09-01 14:44:20 -07:00
Maxime BeaucheminandGitHub 4b77710016 [SQL Lab] Adding DB options for SQL LAb (#1054)
* [SQL Lab] Adding DB options for SQL LAb

each db can be exposed or not in SQL Lab
CTAS is an option
target_schema placeholder (not hooked yet, but would force the CTAS to
target a specific schema)

* Addressing comments
2016-09-01 14:21:46 -07:00
Maxime Beauchemin 1667d15f31 Reactivating coveralls.io 2016-08-31 23:55:20 -07:00
Chris WilliamsandBogdan bae21194c1 Chris/remove redirect from slice id endpoint (#1044)
* call explore() directly from '/caravel/slice/id/' endpoint instead of redirecting to it.

* pass slice_id instead of slice_params in 'caravel/slice/id/' endpoint to avoid logging errors. add fix for MultiDict bug

* address max's comments

* remove the /slice/id/ endpoint in preference of /datasource_type/datasource_id/slice_id/

* pep8
2016-08-31 16:45:03 -07:00
BogdanandGitHub 4f125eedb5 Add codeclimate labels. (#1050)
@mistercrunch, do you know how to change the text on the labels?
2016-08-31 13:30:36 -07:00
BogdanandGitHub f300ee1010 Small codeclimate fixes. (#1033) 2016-08-31 13:28:42 -07:00
BogdanandGitHub 85d03f5e18 Set up istanbul with codeclimate and travis. (#1046)
* Set up istanbul with codeclimate and travis.

* Put the codeclimate tocken inside .travis.yml
2016-08-31 09:27:07 -07:00
Maxime Beauchemin 3f889492f9 Fixing the build [that I broke] 2016-08-30 23:27:56 -07:00
maxime.beauchemin@airbnb.comandMaxime Beauchemin 508feb2bad [hotfix] getting presto on track 2016-08-31 00:11:00 +00:00
Maxime BeaucheminandGitHub 9f8eef498c [theme] a little bit less blue (#1024)
* [theme] a little bit less blue

* Addressing comments
2016-08-30 15:02:09 -07:00
Maxime BeaucheminandGitHub 561828c2f8 [SQL Lab] moving the db/schema/table select to the left (#1038) 2016-08-30 11:08:41 -07:00
Maxime Beauchemin fc1e63761c Adding celery_tests.py 2016-08-29 22:11:57 -07:00
Maxime BeaucheminandGitHub 38b8db8051 SQL Lab - A multi-tab SQL editor (#514)
* Carapal react mockup

This is really just a mock up written in React to try different
components. It could become scaffolding to build a prototype, or not.

* Merging in Alanna's theme tweaks for SQL lab

* Tweak the display of the alert message in navbar

* Sketching the middleware refresh for Queries

* Adjustments

* Implement timer sync.

* CTAS

* Refactor the queries to be stored as a dict. (#994)

* Download csv endpoint. (#992)

* CSV download engdpoint.

* Use lower case booleans.

* Replcate loop with the object lookup by key.

* First changes for the sync

* Address comments

* Fix query deletions. Update only the queries from the store.

* Sync queries using tmp_id.

* simplify

* Fix the tests in the carapal. (#1023)

* Sync queries using tmp_id.

* Fix the unit tests

* Bux fixes. Pass 2.

* Tweakin' & linting

* Adding alpha label to the SQL LAb navbar entry

* Fixing the python unit tests
2016-08-29 21:55:31 -07:00
Maxime BeaucheminandGitHub f17cfcbfa2 [filter box] making filter order matches the dropdown (#1007)
fixes https://github.com/airbnb/caravel/issues/1005
2016-08-26 15:22:43 -07:00
Maxime BeaucheminandGitHub 7eceb140be [bugfix] slice description makes charts overflow (#993) (#1010) 2016-08-26 15:21:16 -07:00
Maxime BeaucheminandGitHub b93f9ec598 [line chart] adding option for circle markers (#1006) 2016-08-26 11:45:46 -07:00
Alanna ScottandGitHub 36a6714e9e slice/explore header (#996)
* move slice header to partial, show datasource in slice title area if no slice is saved

* change partial name, and use same styling as slice title

* use jinja style guide spacing rule

* use [datasource] - untitled
2016-08-25 11:22:11 -07:00
Shashank ShekharandMaxime Beauchemin 30071eef09 Reduced number of ticks provided as hint to d3.ticks (#1012)
The number of the ticks suggested scales with 3 times as much
as the number of bins. This is unwanted since the number
of ticks is a hint to d3 as per (https://github.com/d3/d3-3.x-api-reference/blob/master/Quantitative-Scales.md#identity_ticks) The high number of suggesting ticks leads to a congested y-axis.
2016-08-25 08:18:22 -07:00
Alanna ScottandGitHub e85978a7ed add if enableAddSlice is truthy (#1015) 2016-08-25 00:03:46 -07:00
Alanna ScottandGitHub d1f43e3e28 [ui] a few unmerged rules (#1014)
* make btn default grey text on lighter bg

* get nav bar links working

* use same bg as airbnb body
2016-08-25 00:02:23 -07:00
Alanna ScottandGitHub de39923d06 [ui] design review changes - default/primary btn colors (#1008)
* change primary colors and inverse nav

* use primary small bans

* only use primary for query btn
2016-08-24 22:28:22 -07:00
Maxime BeaucheminandGitHub f800ff16c1 Making default labels visible (#999) 2016-08-23 14:03:10 -07:00
Alanna ScottandGitHub ef118dee6a move staging alert out of nav (#995) 2016-08-23 10:15:00 -07:00
Maxime BeaucheminandGitHub 2bc1674237 [bugfix] slice description makes charts overflow (#993) 2016-08-22 20:27:03 -07:00
Maxime Beauchemin 9445549aff [tweak] allowing markup widget to overflow 2016-08-22 18:06:57 -07:00
Maxime Beauchemin 95eb928beb [bugfix] markup image is missing in examples 2016-08-22 18:03:08 -07:00
Maxime BeaucheminandGitHub a8fd23dfa4 Linting JSX files (#941)
`.jsx` linting is now in-scope for the `npm run lint` command, and
I linted the base files and some of the viz, there's still quite a bit
of work there, but that's a first pass on it.
2016-08-22 13:21:30 -07:00
Maxime BeaucheminandGitHub 7f2805a3c5 [bugfix] fixing && linting the histogram viz (#987) 2016-08-19 18:03:27 -07:00
Maxime BeaucheminandGitHub a8715294b0 [bugfix] dashboard list doesn't populate in explore->saveas (#979) 2016-08-19 16:50:05 -07:00
Maxime BeaucheminandGitHub c7467f544c Documenting making your own build (#990) 2016-08-19 15:27:35 -07:00
Alanna ScottandGitHub 30ef8eba37 [ui] hack bootswatch/cosmo theme to get better tabs for sql-lab (and other things) (#975)
* start hacking cosmo theme and fixing small ui bugs on pages.

* straighten up welcome page

* fix tab styling

* remove paper theme files

* add tables to docs

* make alerts lighter
2016-08-18 23:49:31 -07:00
Maxime BeaucheminandGitHub 23a5463208 Hack around the "last migration doesn't stamp" Alembic bug (#967)
* Hack around the "last migration doesn't stamp" Alembic bug

This makes MySQL, Sqlite and Postgres work with a special hard coded
rule. I'm hoping Alembic fixes the root cause eventually.

* Running db upgrade twice in tests
2016-08-17 17:10:07 -07:00
Maxime BeaucheminandGitHub 84213ab8cd [line] growth vs factor option for 'Period Ratio' (#970)
* [line] growth vs factor option for 'Period Ratio'

* i18n
2016-08-17 12:26:10 -07:00
Alanna ScottandMaxime Beauchemin 379cf6cbd9 [ui] tweaks and improvements (#965)
* update panel headings, titles

* remove panel heading collapser

* style slice meta controls

* fix favstar on dashboard

* add space between heat map and list
2016-08-17 08:05:47 -07:00
Riccardo MagliocchettiandMaxime Beauchemin a029eaa451 docs: add a faq about mapbox api key (#968)
Also add it to sample config

Fix #952
2016-08-17 08:04:39 -07:00
Maxime Beauchemin ac512ef731 [hotfix] SQL endpoint JQUERY error
Fixes #935
2016-08-16 22:29:11 -07:00
vera-liuandMaxime Beauchemin 80974958bd vera_liu-deleted_dashboard_title_column_in_welcome_page (#951) 2016-08-16 21:52:57 -07:00
Riccardo MagliocchettiandMaxime Beauchemin cc058e5c9e viz: cache datetime.now() in query_obj (#955)
It shouldn't be a big deal, and it's pretty cheap on linux, but
still :)
2016-08-16 21:40:27 -07:00
Riccardo MagliocchettiandMaxime Beauchemin 061d4f1ac7 Refine gamma experience (#883)
* gamma: filter the sqla tables the user has access to

Refs #359

* gamma: filter slices available for dashboards in DashboardModelView

Refs #359

* gamma: limit owners to dashboard to self

As we don't want to leak other users to unpriviliged users

Refs #359
2016-08-16 21:37:55 -07:00
Adam JonesandMaxime Beauchemin 88f4260777 Change default location for db and logs to ~/.caravel Fix #915 (#947) 2016-08-16 21:35:31 -07:00
Adam JonesandMaxime Beauchemin 66c2b84cb4 Add time grains for mssql. (#956) 2016-08-16 21:23:03 -07:00
Shashank ShekharandMaxime Beauchemin 348c09624f add amino to inthewild (#964) 2016-08-16 21:16:59 -07:00
Luca AlbertalliandMaxime Beauchemin 3e551e40a7 Update INTHEWILD.md (#960) 2016-08-16 11:46:00 -07:00
Maxime BeaucheminandGitHub c474581138 Fixing the rendering of the separator widget (#936) 2016-08-16 09:47:47 -07:00
Maxime Beauchemin 5646aa03d2 fixing the build 2016-08-15 23:47:33 -07:00
Maxime Beauchemin 6b5d6b4156 [typo] in setup.py 2016-08-15 23:38:05 -07:00
Maxime Beauchemin 4e1af9a2ca Adding codeclimate-test-reporter to dev-reqs.txt 2016-08-15 23:30:51 -07:00
Maxime Beauchemin 7d1bec11f9 Setting up python to allow 90 2016-08-14 17:24:59 -07:00
Maxime Beauchemin c60476eadd Attempting to setup coverage 2016-08-14 17:20:35 -07:00
Maxime Beauchemin d79220fb71 .codeclimate.yml on the right spot 2016-08-14 17:14:34 -07:00
Maxime Beauchemin a8131dda7a Attempting coverage integration with code climate 2016-08-14 17:08:11 -07:00
Maxime Beauchemin 10011d572a Adding Code Climate conf file 2016-08-14 16:57:46 -07:00
Krish MunotandMaxime Beauchemin d7d10d2847 rectify GitHub's name (#942) 2016-08-14 15:48:46 -07:00
Maxime Beauchemin aa01283774 [hotfix] adding react-select to package.json 2016-08-13 23:28:52 -07:00
Maxime BeaucheminandGitHub 1b9458dcf0 Adding config element for alert message in navbar (#938) 2016-08-12 23:40:24 -07:00
Maxime BeaucheminandGitHub e243a14c64 Refactor around how visualizations/*.js are required (#913)
* Refactor around how visualizations/*.js are required

* Reactifying FilterBox further

* Fixing the auto-refresh on filtering events

* Fixing preselected filters
2016-08-11 21:39:10 -07:00
Gustavo BrianandMaxime Beauchemin 198226a39f Fix date serialization (#873)
* [panoramix] -> [dashed]

* merge from caravel/master

* Updated from airbnb

* Cleaning

* Rebase with upstream/master

* merge from caravel/master

* Updated from airbnb

* Cleaning

* Manual rebase

* Last pending change to rebase

* Convert date to datetime before serialization.
Approach choosen: transform data before serialize and keep just one way to serialize

* Unit test created

* stupid error :(

* remove uneeded code and rename test

* Avoid double type checking
Test updated
note: isinstance(<datetime>, <date>) == True, check order changed

* Increase coverage

* Fix assertRaises
2016-08-10 23:13:59 -07:00
Chris WilliamsandMaxime Beauchemin 2bfb9cc7dd pass the standalone request arg in the /caravel/slices/<slice_id>/ endpoint redirect (#876)
* pass the  request arg in the /caravel/slices/<slice_id>/ endpoint.

remove unused import.

* test that a single slice redirects rather than testing them all. update standalone redirect logic for Javascript 'false' instead of Python False
2016-08-10 23:11:53 -07:00
Riccardo MagliocchettiandMaxime Beauchemin 71bdabe1a1 dashboard: don't enable buttons that would fail (#881)
With gamma users saving the dashboard model would fail if they
are not owner of the dashboard.
So if that's not the case just disable the "Add a new slice to
the dashboard" and "Save the current positioning and CSS".

Refs #359
2016-08-10 23:10:59 -07:00
Maxime BeaucheminandGitHub 9b3b1f69df Fixes explore view when no slice is defined (#924) 2016-08-10 22:59:35 -07:00
Maxime BeaucheminandGitHub 3f21a898c9 Fixing some aspects of the theme (#923) 2016-08-10 22:40:59 -07:00
Maxime BeaucheminandGitHub bcbe08bd5c Fixing some aspects of the theme (#907) 2016-08-10 21:14:24 -07:00
Maxime Beauchemin 4247cabb17 [david-dm] Adding badge for tracking js deps versions 2016-08-10 20:32:23 -07:00
Maxime BeaucheminandGitHub 9a2c7740f0 [bugfix] nvd3's API changed and broke the range filter (#903)
* [bugfix] nvd3's API changed and broke the range filter

* Removing if that is not needed
2016-08-10 17:47:05 -07:00
Maxime BeaucheminandGitHub efdfa81f21 [bugfix] controls info bubble don't show up (#904) 2016-08-10 15:04:50 -07:00
Shashank ShekharandMaxime Beauchemin 15ee6d82e3 Histogram (#888)
* Add Histogram as a visualization

The css and js file use the histogram code from https://bl.ocks.org/mbostock/3048450.
THe viz.py extends from BaseViz to create chart data only for one histogram

* using d3.layout.histogram

* CSS updated

The new css has been used from the d3 chart http://bl.ocks.org/mbostock/1933560

* bars are visible

* added semicolons

* histogram from http://bl.ocks.org/mbostock/1933560

It takes as input no of bins. The histogram cycles through
a set of colors for different lengths of the bar. It places a
y axis coordinate on top or on the upper end of the bar
whichever is suitable.

* update style changes
2016-08-10 15:04:19 -07:00
Maxime BeaucheminandGitHub d15c557cd6 [bugfix] missing spinner in explore view (#914) 2016-08-10 15:02:13 -07:00
Maxime BeaucheminandGitHub 08d682501e [webpack] set up proper dev/prod environment (#916) 2016-08-10 15:02:01 -07:00
Riccardo MagliocchettiandMaxime Beauchemin baf22c3c60 docs: make it clear that some config keys really need to be changed (#912) 2016-08-10 08:15:19 -07:00
Riccardo MagliocchettiandMaxime Beauchemin 5a937f1d0b docs: simplify cryptography installation on Windows (#909)
As suggested here https://github.com/airbnb/caravel/issues/717#issuecomment-232741865
and confirmed there
https://cryptography.io/en/latest/installation/#on-windows
cryptography now ships a statically linked openssl.

Still am not sure we want to make installation on Windows easier :)
2016-08-10 08:14:42 -07:00
BogdanandGitHub d6bb8c6935 Add per database permissions for the SQL Lab. (#885) 2016-08-09 17:53:23 -07:00
Riccardo MagliocchettiandMaxime Beauchemin b48101ca51 docs: recommend python3 and virtualenv (#901)
* docs: make it clear that python3 is the recommended version

* docs: recommend installing inside a virtualenv

And add a virtualenv primer.
2016-08-09 15:56:36 -07:00
BogdanandGitHub 572c6ee85e Update linting instructions. (#896)
flake8 changes tests lints only the test dir.
2016-08-09 09:54:59 -07:00
Alanna ScottandGitHub b0a1f07818 ui update (#879)
* caravel ui update

* make headings bold on /explore

* bump back pagination color
2016-08-08 10:55:03 -07:00
Kang TuandMaxime Beauchemin cb23362a5b handle UUID type field (some database like postgres support UUID type field) (#889) 2016-08-07 22:04:36 -07:00
Riccardo MagliocchettiandMaxime Beauchemin 7c810dbd20 Miscellaneous style fixes spotted by landscape (#874) 2016-08-04 15:30:33 -07:00
Maxime BeaucheminandGitHub 82a8e6316f [bugfix] refresh dashboard widget button doesn't work (#878) 2016-08-03 15:44:10 -07:00
Maxime BeaucheminandGitHub aaef338539 Altering theme for more subtle alerts / labels / buttons (#798)
* Altering theme for more subtle alerts / labels / buttons

* Taking comments into account

* changed button-primary to more sober grey instead of brand-primary
* remove carousel from theme demo page and other useless items

* Forcing links to be gray
2016-08-01 23:09:25 -07:00
Riccardo MagliocchettiandMaxime Beauchemin e7ce38b486 Smarter redirect on slice creation (#691)
After ea8a7ec1ba creating a slice
started redirecting to druid datasource from sqlalchemy tables.
That's quite painful for sqlalchemy tables users.
Instead of hardcoding a choice just query the db, if we don't
have any druid datasource fallback to sqlalchemy tables.
Bonus points we remove hacky javascript and make the message
translatable.

While at it fix druid client test to not hardcode datasource id.
2016-08-01 23:06:19 -07:00
Karl LINandMaxime Beauchemin 862042bb49 add redis cache hint to docs (#861) 2016-08-01 23:04:26 -07:00
George KeandMaxime Beauchemin cbca740f9f use css transforms for dashboard grid cells (#848) 2016-08-01 23:02:54 -07:00
Riccardo MagliocchettiandMaxime Beauchemin e36bc2477a Use flask_babel in CONTRIBUTING (#869)
Instead of deprecated flask.ext.babelpkg
2016-08-01 23:02:41 -07:00
Riccardo MagliocchettiandMaxime Beauchemin 55afda3a7e viz: use sort_values(inplace=True) instead of sort (#870) 2016-08-01 23:02:16 -07:00
Maxime BeaucheminandGitHub ee9141a31a New endpoint that receives SQL and returns data as JSON (#842)
* New endpoint that receives SQL and returns data as JSON

* Addressing comments
2016-07-29 22:39:33 -07:00
Hari Prasath RandMaxime Beauchemin 299e31fdff Added order_by_cols to as_list. Fix to issue #821 (#823) 2016-07-28 11:51:21 -07:00
George KeandMaxime Beauchemin f9427b9bfb Fix mapbox radius calculations being off when changing latitude (#824) 2016-07-28 11:50:39 -07:00
plumbeoandMaxime Beauchemin 88726773f1 Add an option to allow users to choose to what IP address the web server must bind to. Default to 0.0.0.0 (all IP addresses). (#826) 2016-07-28 11:49:43 -07:00
x4baseandMaxime Beauchemin 29e3dd404d Let the user decide the label type of pie charts (#819) 2016-07-28 11:39:29 -07:00
Alanna ScottandGitHub 1101de5ae4 [js linting] use airbnb eslint settings (#796)
* add airbnb eslint settings and lint all the code

* fix linting erros
2016-07-27 16:57:05 -07:00
x4baseandMaxime Beauchemin f43e5f18d5 Support showing the values on top of the bars (#777) 2016-07-25 20:38:26 -07:00
Riccardo MagliocchettiandMaxime Beauchemin 2aea1943d6 Add Maieutical Labs / cloudschooling.it to Caravel users (#816) 2016-07-25 20:33:19 -07:00
Maxime BeaucheminandGitHub 7dd5b6716e Fixing serializing the lazy string (#818) 2016-07-25 20:15:57 -07:00
George KeandMaxime Beauchemin 2425b8f614 [presto] Smaller granularity units; fallback support for H:m:s (#731)
* [presto] Smaller granularity units; fallback support for H:m:s

* break lines >90

* cast to DATETIME instead
2016-07-22 12:10:05 -07:00
Maxime Beauchemin d11dd83c94 [docs] faq entry about server timeouts 2016-07-22 19:05:59 +00:00
George KeandMaxime Beauchemin 6731a287b5 Filter add/remove fix (#779) 2016-07-22 09:47:04 -07:00
aljonesandMaxime Beauchemin cf785b4d03 fix datasources foreign key size (#791) 2016-07-22 09:46:41 -07:00
Riccardo MagliocchettiandMaxime Beauchemin 8b694ddd7a Fix caching in python3 (#806)
* caravel: fix visualization cache for python3

python3 wants bytes and not strings:

2016-07-22 10:36:09,474:INFO:root:Caching for the next 28800 seconds
2016-07-22 10:36:09,475:WARNING:root:Could not cache key 1eeb45f32960f0df0ad99a125bdaf199
2016-07-22 10:36:09,475:ERROR:root:'str' does not support the buffer interface
Traceback (most recent call last):
  File "/home/rm/caraveltest/venv/lib/python3.4/site-packages/caravel/viz.py", line 306, in get_json
    zlib.compress(self.json_dumps(payload)),
TypeError: 'str' does not support the buffer interface

Tested with memcached and pylibmc client library.

* docs: add note about using a proper memcached client library
2016-07-22 09:45:51 -07:00
Riccardo MagliocchettiandMaxime Beauchemin 187149caeb Update documentation url (#805)
Fix #789
2016-07-22 08:31:43 -07:00
yxjamesandMaxime Beauchemin 19f5371787 In subquery use alias to do 'order by' (#795)
* in subqry add orderby metric to select

* add comment
2016-07-21 17:53:25 -07:00
Maxime BeaucheminandGitHub 9cdd289081 Set BoxPlotViz to is_timeseries=False (#802)
Fixes #786
2016-07-21 17:52:29 -07:00
Maxime BeaucheminandGitHub e813726afb Giving hingts that we support SparkSQL (#803) 2016-07-21 17:51:30 -07:00
Alanna ScottandGitHub a704d4ddee remove z-index from slice div and .nvtooltip (#793) 2016-07-21 12:30:40 -07:00
Maxime BeaucheminandGitHub fa0497de5e [eslint] changing to always-multiline on comma-dangle (#794) 2016-07-20 21:32:20 -07:00
Maxime Beauchemin 7bba9f73d0 [bugfix] fix dual alert messages where the second one is empty 2016-07-20 13:46:10 -07:00
Alanna ScottandGitHub 83d5ad216a update contributing.md with js testing details (#781) 2016-07-19 16:14:04 -07:00
smilin-desperadoandMaxime Beauchemin 7306b9caaa Fix small typo in message strings (#778) 2016-07-19 17:30:06 -04:00
Alanna ScottandGitHub 2b237f483f update-webpack-config to match babelrc (#776) 2016-07-15 10:36:22 -07:00
Alanna ScottandGitHub 24e85f52b4 get npm test working (#762) 2016-07-14 19:50:47 -07:00
Alanna ScottandGitHub 1fed498e33 [webpack] revert change to output extension (#760)
* revert change to output extension

* make dashboard use .js
2016-07-14 18:19:52 -07:00
Maxime BeaucheminandGitHub f034f2701e Allowing to define a default format string per-metric (#750) 2016-07-13 23:45:05 -04:00
Maxime BeaucheminandGitHub 8312f1c2aa Adding an option to make separators in dashboard (#699) 2016-07-13 23:40:52 -04:00
Maxime BeaucheminandGitHub 3522bf9b09 Fixes #721 - [mktime out of range] (#756) 2016-07-13 23:39:26 -04:00
vimxiangandMaxime Beauchemin 8a69235220 fix development env req (#761)
when i install for development, get an error:
error: Flask-SQLAlchemy 2.1 is installed but Flask-SQLAlchemy==2.0 is required by set(['flask-appbuilder'])
2016-07-13 23:29:41 -04:00
Maxime Beauchemin b295436bff [bugfix] refresh button on dashboard widget dones't work 2016-07-13 15:07:16 -04:00
x4baseandMaxime Beauchemin 8cfe9e96b8 Preselect filters (#752)
* Preselect filters in filter boxes according to the get parameters

* Use the JSX version in dashboard.html

* Use default parameters in ES6 and fix the indent
2016-07-13 11:23:43 -04:00
alanmcruickshankandMaxime Beauchemin 65efe53bfc Adding in Second and Minute time grains for MySQL (#696)
* Added documentation of the health check endpoint

* Adding Minute and Second time grains for MySQL

* Fixed Migration script so that it doesn't break when new fields added to the models for Dashboards or Slices (using declarative base)

* Revert "Fixed Migration script so that it doesn't break when new fields added to the models for Dashboards or Slices (using declarative base)"

This reverts commit 0b6dd696d6.

* Code Cleanliness
2016-07-13 11:20:40 -04:00
x4baseandMaxime Beauchemin 09c95fb28a Fix the mapbox for Druid (#725) 2016-07-13 10:58:59 -04:00
Riccardo MagliocchettiandMaxime Beauchemin 212284cbd4 viz: make sunburst work again (#728)
By using a different method for renaming the metric columns
Thanks to @simobasso for the help!

Fix #673
2016-07-13 10:42:00 -04:00
Maxime BeaucheminandGitHub 082645d312 [bugfix] html points to dashboard.entry.js instead of jsx (#749) 2016-07-13 00:03:38 -04:00
Alanna ScottandGitHub 18b8e6fa58 make show columns explicit, don't show password column (#748) 2016-07-11 18:15:33 -07:00
Maxime Beauchemin 9d7c05a015 [hotfix] fix py3 compatibility broken by basestring 2016-07-11 17:36:12 -04:00
x4baseandMaxime Beauchemin 3c92ba9bd5 Fix bugs in the world map and deal with edge cases (#722)
* Fix bugs in the world map and deal with edge cases

* Ignore countries labeled XXX
2016-07-10 19:38:12 -07:00
George KeandMaxime Beauchemin 00970d6b99 Fix erroneous options for default slices (#730) 2016-07-10 19:37:02 -07:00
Van TienandMaxime Beauchemin 979782d1cf Fix path for windows platfrom (#742)
* At platform specific path for Windows

* At platform specific path for Windows
2016-07-10 19:20:21 -07:00
George KeandGitHub 04f3e3bc8f "Add Slices" modal on dashboard page (#678)
* Add slice modal

* use datatables, filter by slice creator

* tests & landscaping

* code review + react-bootstrap-table + modularity
2016-07-07 21:40:33 -07:00
Alanna ScottandGitHub afff78868f remove console.log (#729) 2016-07-07 19:04:36 -07:00
Alanna ScottandGitHub 8020464602 [explore] convert query and save btns to react (#690)
* start to convert query and save btns to react

* more explore.jsx to explore/
2016-07-07 18:39:43 -07:00
Maxime BeaucheminandGitHub 8135c240dc Revert "Binding key Q to the running the query in explore view" (#713) 2016-07-01 16:36:06 -07:00
Maxime BeaucheminandGitHub 19983147a3 Binding key Q to the running the query in explore view (#685) 2016-07-01 15:28:40 -07:00
x4baseandMaxime Beauchemin d5b22dd86e Filter empty strings or nulls, and add more operators (#704)
* Filter empty strings or nulls, and add more operators

* Encapsulate strings for translation
2016-07-01 14:45:04 -07:00
Maxime BeaucheminandGitHub 917bc984eb Make DruidDatasource.version_higher support funky version strings (#706) 2016-07-01 14:44:25 -07:00
x4baseandMaxime Beauchemin 1a952a4961 Dashboards can only be deleted by their owners (#701) 2016-07-01 14:33:07 -07:00
lucky2youandMaxime Beauchemin ee00aa6522 some Chinese simplified translation work (#710) 2016-07-01 14:31:22 -07:00
Maxime Beauchemin 2e0e6e3342 [quickfix] support isNaN aggregates in Table viz 2016-06-30 17:34:58 -07:00
Maxime Beauchemin d4641e4457 [docs] FAQ how do I create my own viz? 2016-06-30 17:33:51 -07:00
Maxime Beauchemin 8b95d17b7b [quickfix] embeded view missing some dependencies 2016-06-30 10:34:53 -07:00
Maxime Beauchemin f407bd45fd [quickfix] fix broken CRUD column header links 2016-06-29 22:20:25 -07:00
Maxime Beauchemin fa65888590 Screenshot makeover in README 2016-06-29 11:00:44 -07:00
Maxime Beauchemin dbb9356d7e Changelog updates for 0.10.0 2016-06-28 16:57:44 -07:00
yxjamesandMaxime Beauchemin 1ac2fccd2a fix small issue of dttm PR (#688) 2016-06-28 16:51:26 -07:00
Maxime Beauchemin 57bffe099f v0.10.0 2016-06-28 16:42:33 -07:00
Maxime Beauchemin a016d181d7 [hotfix] mistakes slipped in 2016-06-28 12:58:09 -07:00
Maxime Beauchemin 759c8d5377 [hotfix] fixing minor control issues
* View Query button is disabled
* Missing tooltip on View Query
2016-06-28 12:29:51 -07:00
Maxime BeaucheminandGitHub bd68378d9c Saving slices and adding them to dashboards directly from explore view (#680)
* Saving slices from explore view

* Addressing comments
2016-06-28 10:31:36 -07:00
yxjamesandMaxime Beauchemin 7a7f61a296 datetime format and database expression on column level (#652)
* time format minor features added

* add description for datetime format input

* db version bug walkaround

* removed unecessary comments and fixed minor bug

* fixed code style

* minor fix

* fixed missing time format column in DruidDatasource

* Update models.py

Minor style fix

* Revert "Update models.py"

This reverts commit 6897c388e0.

* removed timestamp_format from druid and removed try catch in migration

* Using spaces, not tabs

* get the most updated migration and add the migration on the head of it

* remove vscode setting file

* use colunm based dttm_format

* modify dttm_converter

* modify datetime viz

* added comments and documents

* fixed some description and removed unnecessary import

* fix migration head

* minor style

* minor style

* deleted empty lines

* delete print statement

* add epoch converter

* error fixed

* fixed epoch parsing issue

* delete unnecessary lines

* fixed typo

* fix minor error

* fix styling issues

* fix styling error

* fixed typo

* support epoch_ms and did some refactoring

* fixed styling error

* fixed styling error

* add one more dataset to test dttm_format and db_expr

* add more slices

* styling

* specified String() lenght
2016-06-27 21:33:44 -07:00
Maxime Beauchemin 3e742c74bb [hotfix] many tooltips were not quoted properly 2016-06-27 20:44:32 -07:00
Maxime BeaucheminandGitHub 6a34b729e9 Adapting Babel to new FAB version, regenerating translations (#684) 2016-06-27 20:10:40 -07:00
Maxime Beauchemin 4191b75966 Adding padding to markup widget 2016-06-26 13:13:16 -07:00
Maxime BeaucheminandGitHub d5b8414fde Showing only dashboards on welcome page (#676) 2016-06-24 18:42:55 -07:00
George KeandGitHub 57ebb2bacf Map visualization (#650)
* simple mapbox viz

use react-map-gl

superclustering of long/lat points

Added hook for map style, huge performance boost from bounding box fix, added count text on clusters

variable gradient size based on metric count

Ability to aggregate over any point property

This needed a change in the supercluster npm module, a PR was placed here:
https://github.com/mapbox/supercluster/pull/12

Aggregator function option in explore, tweaked visual defaults

better radius size management

clustering radius, point metric/unit options

scale cluster labels that don't fit, non-numeric labels for points

Minor fixes, label field affects points, text changes

serve mapbox apikey for slice

global opacity, viewport saves (hacky), bug in point labels

fixing mapbox-gl dependency

mapbox_api_key in config

expose row_limit, fix minor bugs

Add renderWhileDragging flag, groupby. Only show numerical columns for point radius

Implicitly group by lng/lat columns and error when label doesn't match groupby

'Fix' radius in miles problem, still some jankiness

derived fields cannot be typed as of now -> reverting numerical number change

better grouping error checking, expose count(*) for labelling

Custom colour for clusters/points + smart text colouring

Fixed bad positioning and overflow in explore view + small bugs + added thumbnail

* landscaping & eslint & use izip

* landscapin'

* address js code review
2016-06-24 14:16:51 -07:00
Maxime BeaucheminandGitHub 914f23432f Make text in sunburst path more readable (#675) 2016-06-24 12:28:13 -07:00
Maxime BeaucheminandGitHub 967b2ffeb0 Only creating perms for restricted metrics (#655)
* Only creating perms for restricted metrics

* Adding post_update hooks for is_restricted
2016-06-24 08:47:43 -07:00
Maxime BeaucheminandGitHub 131372740e Adding orderby to Table 'not grouped by' and fixing metrics ordering (#669) 2016-06-23 22:43:52 -07:00
Maxime BeaucheminandGitHub 51024b5f8a Reintroducing showControls as an option (#672) 2016-06-23 22:43:40 -07:00
Maxime Beauchemin 141dc12e44 Adding quarter time grain for Presto 2016-06-23 16:59:10 -07:00
Maxime BeaucheminandGitHub e230d9db4a Don't force formatting when using "Period Ratio" (#668)
At the moment, when using the "Period Ratio" option, a percentage
formatting is forced on the Y Axis. This code pre-dates the `Y Axis
Format` option.

People may want to see a growth rate, in which case the current `.3p`
isn't what they want, or they may want only 2 digits of precision or
whatever else. This PR allows that.
2016-06-23 15:28:42 -07:00
Maxime BeaucheminandGitHub 4a8e62b439 Fixing the examples's dashboard positioning (#667) 2016-06-23 15:28:23 -07:00
Maxime BeaucheminandGitHub f949b88ebd A cleaner right side of the navbar with a Github link (#666) 2016-06-23 15:28:07 -07:00
x4baseandMaxime Beauchemin ab71ee4f93 Make the headers of tables and pivot tables fixed (#651) 2016-06-22 16:16:27 -07:00
Maxime BeaucheminandGitHub 8ebe074954 [bugfix] filter widgets to apply on applicable Slices (#658)
Also fixed a white on white issue on hover
2016-06-22 16:14:07 -07:00
Maxime Beauchemin f25e37579d [quickfix] showControls on area chart 2016-06-22 14:21:09 -07:00
Maxime Beauchemin 3ef79bbaf3 [quickfix] removing controls in Area chart to leave more room for the legend 2016-06-22 14:00:35 -07:00
J Phani MaheshandMaxime Beauchemin 73601e4acb docs: correct name of local config module in comments (#653) 2016-06-22 07:55:09 -07:00
Maxime Beauchemin a9fd2271dd [hotfix] caching and list ordering related bugs 2016-06-21 23:44:22 +00:00
Maxime Beauchemin 7c2d485de0 [quickfix] removing year detail in smart_date 2016-06-21 11:20:11 -07:00
kkalyanandMaxime Beauchemin 30da408ace Druid Intervals Issues prevents metadata pull (#526)
* Druid Intervals Issues

* fetching druid version

* fixes

* space

* version fix

* landscape issues
2016-06-21 10:03:56 -07:00
x4baseandMaxime Beauchemin 485234bc78 Add having filters (#553)
Support the dimSelector having filters
2016-06-21 09:43:10 -07:00
x4baseandMaxime Beauchemin 13095eb550 Show right messages as soon as possible (#632)
* Flashed messaged should be flushed in every page

* Show error messages in AJAX style

* Introduce the decorator "api"

* Move toggleCheckbox() to the right place and trigger it in jQuery style
2016-06-21 09:42:54 -07:00
x4baseandMaxime Beauchemin 40e1787948 Improve the error message in the slices (#555)
* Improve the error message in the slices

Let slice.error() accept msg and xhr

* Check error first in nvd3_vis.js
2016-06-21 09:42:44 -07:00
Maxime BeaucheminandGitHub 7e8053abef Adding list of table names to show Dashboard view (#648) 2016-06-21 09:41:48 -07:00
Lech JankovskiandMaxime Beauchemin ff44e46d7b Add impyla to recommended packages for Impala (#649) 2016-06-21 09:41:24 -07:00
Maxime BeaucheminandGitHub d71a67cdad Bumping FAB and cryptography to current version (#647) 2016-06-20 15:31:15 -07:00
George Ke 54e4be1d13 [hotfix] lint error should fail travis build 2016-06-20 15:17:04 -07:00
George Ke fb0750710e [hotfix] missing semicolon breaking build 2016-06-20 14:14:20 -07:00
alanmcruickshankandMaxime Beauchemin 5618df78f8 Added documentation of the health check endpoint (#644) 2016-06-20 09:24:49 -07:00
Chris WilliamsandMaxime Beauchemin 668ede1133 expose /slice/<slice_id>/ endpoint to redirect to a slice's url (#633)
* expose /slice/<slice_id>/ endpoint to redirect to a slice's url

* remove residual print statement

* add unit test for caravel/slices/id endpoint
2016-06-20 09:18:03 -07:00
Maxime BeaucheminandGitHub deb197a1d8 Adding contribution to total option to Bar chart (#641) 2016-06-20 09:16:51 -07:00
Maxime BeaucheminandGitHub 55c549d86f Adding option for reduceXTicks (#640) 2016-06-17 12:31:20 -07:00
Maxime Beauchemin 78eb1e6a54 [hotfix] fixing bug around looking up security access 2016-06-17 11:34:54 -07:00
yxjamesandMaxime Beauchemin 4c8523efc0 Prevent potential db upgrading problem (#628)
* fix general db upgrade problem

* add comments
2016-06-17 08:14:26 -07:00
Riccardo MagliocchettiandMaxime Beauchemin 4400c70514 Make time grains translatable (#622)
* Make time grains translatable

Fix #616

* Refresh translations
2016-06-17 08:12:15 -07:00
Maxime BeaucheminandGitHub 3105c9f9ae Improvments to NVD3 charts (axis labels & min bar width) (#629) 2016-06-17 08:11:53 -07:00
Maxime Beauchemin 04388a7b9b [docs] telling people to use gunicorn server 2016-06-16 09:16:10 -07:00
x4baseandMaxime Beauchemin db30f20341 Only initiate permissions of valid metrics (#630) 2016-06-16 08:55:11 -07:00
x4baseandMaxime Beauchemin 65d9feb0a9 Check ownership before a slice is deleted (#624) 2016-06-15 14:27:36 -07:00
Rocky QiandMaxime Beauchemin 77c5c9400a Update sql.js to fix a invalid error msg (#621)
when using sql.html page to run sql directly, for any SELECT * sql, when click run! button for the second time,
the page will show error msg like: DataTables warning: table id={id} - Cannot reinitialise DataTable.
this can be fix by:https://datatables.net/manual/tech-notes/3#retrieve
2016-06-15 14:27:12 -07:00
Peiji ChenandMaxime Beauchemin 5de8740a38 minor correction on the right npm path (#618)
* minor correction to the right npm path

* minor correction to the right npm path
2016-06-15 14:24:25 -07:00
x4baseandMaxime Beauchemin ea8a7ec1ba Redirect to druid datasource page when the user wants to add slice. Also, provide a link to the table page (#625) 2016-06-15 14:23:25 -07:00
alanmcruickshankandMaxime Beauchemin b38590a0bb Added Hour time grain for MySQL (#615) 2016-06-15 14:22:27 -07:00
x4baseandMaxime Beauchemin ee2d3330aa Prevent the cannot-overwrite error message from being removed before it can be seen (#626) 2016-06-15 14:19:50 -07:00
Maxime Beauchemin aa2b8b42d0 Updating CHANGELOG 2016-06-15 10:13:48 -07:00
Maxime Beauchemin 91e272546a v0.9.1 2016-06-15 09:46:29 -07:00
Maxime BeaucheminandGitHub d90a2c861a Pinning all dependencies to specific versions (#627) 2016-06-15 09:29:37 -07:00
Maxime Beauchemin a117498991 Adding some CRUD field descriptions to clarify things 2016-06-15 08:50:50 -07:00
Maxime Beauchemin e29d71d0ff [hotfix] passing payload to Slice.done everywhere 2016-06-13 22:58:04 -07:00
Maxime Beauchemin bacbd909d1 [hotfix] parallel coordinates grey background on hover 2016-06-13 22:44:57 -07:00
Maxime BeaucheminandGitHub 77d8ccba87 Compress before caching, store more in each memcache key (#614) 2016-06-13 21:59:03 -07:00
Junxian WuandMaxime Beauchemin 347c39b8e9 Better support for Druid cardinality estimation mertics (#613)
* added rocognition of thetasketch and HLL metrics

* make sure the name agreed with SQL convention
2016-06-13 20:49:51 -07:00
Maxime Beauchemin bc58c5d031 [hotfix] delete cache key when set fails 2016-06-13 18:01:55 -07:00
Maxime BeaucheminandGitHub 267c0191a8 Make sure cache.set never fails hard (#611) 2016-06-13 13:26:05 -07:00
Maxime BeaucheminandGitHub 9ed8c32f76 Cranking up FAB to latest (1.7.1) version (#609) 2016-06-13 09:25:22 -07:00
Maxime BeaucheminandGitHub 1a4c7afbef Fixing a potential FK error when doing bulk updates (#606)
I hit this upgrade issue in production where the FK for user wasn't
allowing null. Perhaps it is specific to our environment but I'd rather
fix this.
2016-06-12 21:39:06 -07:00
Maxime Beauchemin c58fd63efc [hotfix] caching indicator was missing on dashboard view 2016-06-12 21:38:32 -07:00
Maxime BeaucheminandGitHub fa13b77cfa Adding postgres to the build matrix (#604) 2016-06-12 11:01:16 -07:00
Maxime BeaucheminandGitHub c490138afe Fixing json issues (#602) 2016-06-11 20:39:25 -07:00
Maxime Beauchemin 327fceefb7 [hotfix] fixes issue around multidict 2016-06-11 08:02:56 -07:00
MarigoldandMaxime Beauchemin 1631137da1 fix missing multiple values for the same parameter name (#565) 2016-06-11 07:55:01 -07:00
Junxian WuandMaxime Beauchemin 4661b0210d Popover to generate iframe html tag when standalone button is clicked (#575)
* fixed

* basic implementation of the iframe embed popover

* remove unecessary comments

* remove public embed iframe

* remove debug print line and public access

* remove uncessary extra line and use better text explain

* maintain the style of airbnb/master

* fixed style

* re-run the test locally. Made sure it passed
2016-06-11 07:48:30 -07:00
Riccardo MagliocchettiandMaxime Beauchemin a8136bb9f5 Update translations files (#595) 2016-06-11 07:47:42 -07:00
x4baseandMaxime Beauchemin 4c6026fdda Add access control over metrics (#584)
* Add the new field "is_restricted" to SqlMetric and DruidMetric

* Add the access control on metrics

* Add the more descriptions on is_restricted

* Update docs/security.rst

* Update docs/security.rst
2016-06-10 15:49:33 -07:00
Maxime BeaucheminandGitHub 55baab413a [hotfix] fixing the build (#594) 2016-06-09 22:58:20 -07:00
Maxime Beauchemin 2f60801059 [hotfix] fixing the build 2016-06-09 21:12:44 -07:00
Maxime Beauchemin 2644dd1984 Adding a test for welcome page 2016-06-09 18:11:24 -07:00
Maxime BeaucheminandGitHub c35e0e831c [hotfix] csv and json link are off (#592)
* Fixing bugs

* [hotfix] csv and json link are off
2016-06-09 18:06:20 -07:00
Maxime BeaucheminandGitHub 60ed3e4050 TOX / Travis build matrix (#593)
* Building on many dbs

* Fixing some translation related error msg
2016-06-09 18:05:58 -07:00
Riccardo MagliocchettiandMaxime Beauchemin dd662eaca3 caravel: mark more strings for translations in viz (#586) 2016-06-09 16:46:27 -07:00
Riccardo MagliocchettiandMaxime Beauchemin e3da785321 caravel: reduce usage of choicify in forms (#591)
So that more string can be translated

Fix #583
2016-06-09 16:45:45 -07:00
Jeremi JoslinandMaxime Beauchemin f4c92da4e6 Make sure the APP_ICON config is used in the template (#590) 2016-06-09 16:45:03 -07:00
Riccardo MagliocchettiandMaxime Beauchemin eb208b921c config: there's no such thing as WEBSERVER_THREADS (#587)
The config option is CARAVEL_WORKERS. Bump example to 16 processes
to keep backward compatibility with the current default.
2016-06-09 16:44:13 -07:00
Riccardo MagliocchettiandMaxime Beauchemin 8a579e2a2a Mark more strings for translations (#581)
* caravel: mark viz strings for translations

* caravel: mark templates string for translation

* caravel: make forms strings translatable

* Update translations
2016-06-08 17:38:43 -07:00
Riccardo MagliocchettiandMaxime Beauchemin cdb573e793 caravel: add missing test requirements in setup.py (#582) 2016-06-08 13:50:43 -07:00
Riccardo MagliocchettiandMaxime Beauchemin ad5507c5f4 views: translate labels and not names (#567)
So that we can install caravel on postgresql:
```
2016-06-03 17:58:05,386:ERROR:flask_appbuilder.base:
Add Permission on Menu Error: (psycopg2.ProgrammingError) can't adapt type '_LazyString'
[SQL: 'SELECT ab_view_menu.id AS ab_view_menu_id, ab_view_menu.name AS
ab_view_menu_name \nFROM ab_view_menu \nWHERE ab_view_menu.name = %(name_1)s \n
LIMIT %(param_1)s'] [parameters: {'param_1': 1, 'name_1': l'Sources'}]
```

Other that translating names should be a recipe for disaster if
you switch language.

Fix #558
2016-06-07 17:43:51 -07:00
George KeandMaxime Beauchemin 24a68f5c48 Two hotfixes (#574)
* fix for dashboards created without slices

* [hotfix] check_ownership param needed for adding slice to dashboard
2016-06-07 11:07:25 -07:00
Maxime Beauchemin 0d800fa302 Fixing bugs where params aren't reflected on nvd3* (#564) 2016-06-07 08:10:49 -07:00
Maxime Beauchemin dc33506bfa Removing deprecated refs to flask.ext.* (#566) 2016-06-05 21:37:03 -07:00
Maxime Beauchemin 89f9efd3a3 Fixing the dashboard's look after resizing the window (#556) 2016-06-03 11:53:37 -07:00
George KeandMaxime Beauchemin 52c2b2348a allow for multiple columns in NOT GROUP BY (#560) 2016-06-03 11:34:29 -07:00
Maxime Beauchemin b5fe9dbe33 Adding a security section to the docs (#561) 2016-06-03 11:33:11 -07:00
Riccardo MagliocchettiandMaxime Beauchemin 5bc50210ad utils: generalize utility to find find_constraint_name (#557)
See https://github.com/airbnb/caravel/pull/531
2016-06-03 09:47:51 -07:00
Riccardo MagliocchettiandMaxime Beauchemin fe402465b1 caravel: catch only ImportError when loading config (#559)
As you may want to see the exception raised on at leasts SyntaxError
2016-06-03 09:46:03 -07:00
Maxime Beauchemin 3ee9a68c09 Only owners can update their objects (#507) 2016-06-02 19:17:34 -07:00
Maxime Beauchemin 29170512ab Adapting default CSS templates to the new grid layout 2016-06-02 16:40:55 -07:00
Maxime Beauchemin b5614a433e Fixing 2 bugs that happen when fields are removed from table (#551) 2016-06-02 12:39:21 -07:00
Giacomo TagliabueandMaxime Beauchemin 5f005d67e3 Add CORS support (#478)
* Add optional CORS

* make CORS an extra dependency

* add documentation
2016-06-02 12:34:36 -07:00
George KeandMaxime Beauchemin c78d3682ac Reactify dashboard grid (#523)
* Use react-grid-layout instead of gridster

* visualizations show and resize

* display slice name and description; links work

* positioning of widgets to match gridster, rowHeight matches

* Change margins, rowHeight, unpositioned viz, and expandedSlices to match gridster

* Saving dashboard, deleting slices, formatting on slices (chart control and resize handle), expanded slices fixed.

* responsiveness + use es6 classes

* Minor ui fixes + linting

* CSS transforms on slices messes up nvd3 tooltip positioning.
Turn off CSS transforms for the time being, with a cost of painting speed.

Issue is currently being looked at on the nvd3 repo
PR: https://github.com/novus/nvd3/pull/1674

* Remove breakpoint listener, fires when it shouldn't (i.e. too often)

* resize is no longer buggy, minor cleanup

* gridster class, const, landscape error

* one source of data for data to front end from python
2016-06-02 12:31:05 -07:00
Luca AlbertalliandMaxime Beauchemin fe6628b0a4 Fix #529 2 - "This Session's transaction has been rolled back" (#531)
* Created migration to fix the bug

* Working also on MySQL

* Added support for Vertica Grains (#515)

* Fix #529 1 "This Session's transaction has been rolled back" (#530)

* Fixing the specific issue

* Added an additional fix for a similar error in #529

Background:
- When an object is modified by SQLAlchemy, it is invalidated so need to be fetched again from the DB
- If there's an exception during a transaction, SQLAlchemy performs a rollback and mark the connection as dirty.

Bug:
- When handling exceptions, the exception handler tries to access the name of the cluster in the main object. Since the name has been invalidated due to a write, SQLAlchemy tries to fetch it on a 'dirty' connection and spits out an error. Solution:
- Fetch the information for handling the exception before starting the process.

* Modified the migration function to to automatically detect the the foreign keys based on the signature.
It supports also sqlite using batch migrations

* i18n: Fix typo in Druid cluster broker port label (#512)

* Update models.py (#541)

removing duplicated `user_id` def
2016-06-02 12:27:59 -07:00
George KeandMaxime Beauchemin cb384d051b Fix for Not Grouped By on Table View (#544)
* fix for default metric in table visualization

* better location for form override; covers all parameters

* remove dead code, use items instead of iteritems for python 3
2016-06-01 22:59:06 -07:00
George KeandMaxime Beauchemin 849063c797 fix world_map appending to old world map when updating (#549) 2016-06-01 22:47:22 -07:00
Luca AlbertalliandMaxime Beauchemin 087c47a37e Fix #529 1 "This Session's transaction has been rolled back" (#530)
* Fixing the specific issue

* Added an additional fix for a similar error in #529

Background:
- When an object is modified by SQLAlchemy, it is invalidated so need to be fetched again from the DB
- If there's an exception during a transaction, SQLAlchemy performs a rollback and mark the connection as dirty.

Bug:
- When handling exceptions, the exception handler tries to access the name of the cluster in the main object. Since the name has been invalidated due to a write, SQLAlchemy tries to fetch it on a 'dirty' connection and spits out an error. Solution:
- Fetch the information for handling the exception before starting the process.
2016-05-31 21:16:32 -07:00
Riccardo MagliocchettiandMaxime Beauchemin b193539fa4 i18n: Fix typo in Druid cluster broker port label (#512) 2016-05-31 21:10:28 -07:00
Luca AlbertalliandMaxime Beauchemin ae7fb012a9 Added support for Vertica Grains (#515) 2016-05-31 21:09:04 -07:00
Jiayu LiuandMaxime Beauchemin 409233d4fc Update models.py (#541)
removing duplicated `user_id` def
2016-05-31 21:07:14 -07:00
Maxime Beauchemin 7d27692828 [hotfix] forcing newer pydruid version 2016-05-24 12:35:55 -07:00
Maxime Beauchemin dee4c34411 [hotfix] adapting to pydruid 0.2.3 2016-05-24 18:35:10 +00:00
Maxime Beauchemin eb3bfb5c56 Cranking FAB to 1.6.2 (#505) 2016-05-23 13:08:50 -07:00
Maxime Beauchemin 57990bfd83 Implementing druid's regex filters (#501)
* Implementing druid's regex filters

* Debugging

* Debuggin'
2016-05-23 13:06:35 -07:00
Xuefeng ZhuandMaxime Beauchemin 29f5ace436 complete Chinese translation (#503) 2016-05-23 11:46:46 -07:00
Maxime Beauchemin 0fcab30652 More translation instrumentation and some french to test (#502) 2016-05-23 11:46:33 -07:00
Maxime Beauchemin c53874c8ab [hotfix] treemap was broken 2016-05-20 14:05:08 -07:00
Maxime Beauchemin e77d50bc61 Adding a doc page for Druid 2016-05-20 12:11:38 -07:00
Maxime Beauchemin f0c6a98027 Gunicorn tweaks, unlimited limit-request-line & limit-request-field_size (#500)
This is mostly to enable long text in the Markdown widget
Related:
https://github.com/benoitc/gunicorn/issues/376
2016-05-20 11:35:41 -07:00
Maxime Beauchemin 58d78beeaa [bugfix] 'Y Axis Zero' would force 1 in Y axis (#497) 2016-05-20 11:10:46 -07:00
Riccardo MagliocchettiandMaxime Beauchemin e1a3854f2a utils: add special serializer for numpy.int64 (#492)
It looks like COUNT(*) returns a numpy.int64 value that the
default JSONEncoder does not handle.

While at if we get a type we are not handling make it easier to
debug the issue by throwing a TypeError exception with useful
data.

Fix #486
2016-05-20 11:10:29 -07:00
Florent BENOITandMaxime Beauchemin 7630d73002 fix typo (#484) 2016-05-20 11:05:28 -07:00
Riccardo MagliocchettiandMaxime Beauchemin 3cfc58e3a2 Add italian translation (#491) 2016-05-20 11:05:08 -07:00
Josh WaltersandMaxime Beauchemin 3ee102b79f Made '__' prefix into suffix. (#496) 2016-05-20 11:03:49 -07:00
Maxime Beauchemin f5180d8724 [hotfix] fix name change on test dashboard triggers error 2016-05-19 08:51:13 -07:00
Maxime Beauchemin 4738b01125 [hotfix] setting default value for druid_time_origin 2016-05-16 23:08:46 -07:00
Maxime Beauchemin d1f0276408 Introducing Horizon charts (#472)
* Introducing Horizon charts

* JS Lintin
2016-05-16 22:49:12 -07:00
Maxime Beauchemin 1766f6edd6 [hotfix] making druid_time_origin stick 2016-05-16 22:48:32 -07:00
Andrii SydorchukandMaxime Beauchemin 8a406b18f5 Add PUBLIC_ROLE_LIKE_GAMMA config flag (#473) 2016-05-16 21:24:43 -07:00
Maxime Beauchemin 2620aeca02 Fixing the heatmap calendar color ranges in the Welcome page (#474) 2016-05-16 21:22:38 -07:00
George KeandMaxime Beauchemin 5c0e30ed70 Added Calendar Heatmap (#475)
* Added sqlite Grains

* Calendar heatmap visualization

* Linting

* Explicit metric setting was breaking tests

* Python linting

* Code cleanup + review

* [fixing the build] a new version of eslint is more picky

* Linting

* Added sqlite Grains

* Calendar heatmap visualization

* Linting

* Linting

* Explicit metric setting was breaking tests

* Python linting

* Code cleanup + review
2016-05-16 17:59:38 -07:00
Maxime Beauchemin 607e1f941b Fixing the build 2 out of 2 2016-05-16 17:41:02 -07:00
Maxime Beauchemin d30567959b [fixing the build] a new version of eslint is more picky 2016-05-16 16:33:08 -07:00
Maxime Beauchemin 83e0e58888 [hotfix] Druid explore/table dropdown doesn't change anything 2016-05-16 16:10:22 -07:00
x4baseandMaxime Beauchemin 5a870fe1c2 Mysql key length (#459)
* Use varchar(255) in MySQL

* Adjust the key lengths in old migration scripts
2016-05-12 10:27:38 -07:00
Maxime Beauchemin d846cb3d73 Updating changelog 2016-05-12 08:51:59 -07:00
Maxime Beauchemin a0099ad6d6 v0.9.0 2016-05-12 08:24:01 -07:00
Maxime Beauchemin f28c2b2557 Cosmetric tweaks in the CRUD list view (#458) 2016-05-11 21:05:32 -07:00
Maxime Beauchemin 52bbb38188 Don't limit parallel coordinates table size (#455)
Before we limited the table size to 10 rows, now there's no limit and it
will overflow properly with a scrollbar.
2016-05-11 17:48:04 -07:00
Maxime Beauchemin aa6e6bdf7a Allowing for templated urls in iFrame (#460)
* Allowing for templated urls in iFrame

This can allow for passing {{ width }} and {{ height }} as dynamic
attributes in the iFrame's URL.

The new method Slice.render_template method could do more eventually
exposing more variables to be used in dynamic strings.

* Passing function references

* js linting
2016-05-11 17:00:46 -07:00
Maxime Beauchemin 6c333d5010 Fixing the missing searchbox bug (#431)
* Fixing the missing searchbox bug

* Linting JS

* Layout tweaks
2016-05-10 11:49:32 -07:00
Maxime Beauchemin 673cce9e56 Attempting to fix #412 (#430)
* Attempting to fix #412

* More flushes
2016-05-10 11:19:30 -07:00
Maxime Beauchemin d79089c587 Improving the parallel coordinate viz (#452)
* Improving the parallel coordinate viz

* Clear container on refresh
* Order of columns is kept
* Option to show/hide the series column in viz
* Color metric not shown by default

* JS linting
2016-05-10 09:39:33 -07:00
Maxime Beauchemin c4e3020369 Conververting datetime based on database dialects (#446) 2016-05-10 09:29:29 -07:00
Maxime Beauchemin 77e9e6a5d7 Fixing issue #444 color function chokes on non-string param (#447) 2016-05-10 09:22:59 -07:00
Siddharth GuptaandMaxime Beauchemin a75d6bc52c add timestamp toggle in chart options (Table Viz) (#439)
* add timestamp toggle in chart options (Table Viz)

* refactor timestamp choices

* fix build error
2016-05-10 09:22:32 -07:00
x4baseandMaxime Beauchemin c5fcbc0709 Support hyperUniqueCardinality type in post aggregation (#451) 2016-05-10 09:21:09 -07:00
Siddharth GuptaandMaxime Beauchemin 2f64c42062 blacklist druid datasources to be refreshed because it takes forever to load all druid datasources metadata which is not even required (given the use cases user should be able to blacklist data sources which are not required to be refreshed). (#441) 2016-05-06 12:03:42 -07:00
Maxime Beauchemin d304ee005a Bugfix in line chart where the series name is an empty string (#434) 2016-05-05 12:19:51 -07:00
JunshuoandMaxime Beauchemin 82fa501dea Update Chinese translation (#438)
Change some Chinese translations to make them sound less robotic
2016-05-05 12:19:21 -07:00
x4baseandMaxime Beauchemin bc7170769b Recursively get the dependency fields of post aggregators (#437) 2016-05-05 08:52:48 -07:00
andrewhnandMaxime Beauchemin 6941f1de64 add unicode data to tests (#432)
* add unicode data to tests

* make tests pass on 2.7

* clean up data loading

- remove duplicate keys in slice_data
- reduce line length

* change manager option flag to -t, --load-test-data

* test --> load_test_data
2016-05-05 08:46:16 -07:00
Maxime Beauchemin a3f549bb9e Some chinese translations as a Proof of Concept (#435) 2016-05-04 21:36:10 -07:00
Andrii SydorchukandMaxime Beauchemin 0bedaed367 Make sure anonymous user with proper permissions can access data (#415)
* Make sure anonymous user with proper permissions can access data

* Review fixes: naming changes

* Review fixes: add more granular tests for public user dashboard access

* Review fixes: test that public user has access only to permitted data sets
2016-05-03 22:31:37 -07:00
x4baseandMaxime Beauchemin 1d0863abfe Rename the dummy variable _ to avoid conflict with lazy_gettext (#427)
Otherwise "local variable '_' referenced before assignment" will be raised
2016-05-03 22:28:30 -07:00
Maxime Beauchemin a3a9ec926f [hotfix] piechart goes black on refresh (#424) 2016-05-03 12:49:52 -07:00
Giacomo TagliabueandMaxime Beauchemin a8d0ae1361 Fix name of test script in contributing guide (#428) 2016-05-03 12:45:38 -07:00
Giacomo TagliabueandMaxime Beauchemin 9a08c45e59 add additional postgres and redshift time grains (#429) 2016-05-03 12:44:42 -07:00
Maxime Beauchemin 88c9516e20 Getting started on translations (#423) 2016-05-02 10:50:23 -07:00
Maxime Beauchemin ec7dbed800 Blank theme (#419)
* A white theme

* Updating TODO

* Fixing tests
2016-05-02 10:04:29 -07:00
Maxime Beauchemin 26d273643b Allowing for druid post aggregations (#418)
* Druid post aggregations

* Fixing tests
2016-05-02 10:00:39 -07:00
Maxime Beauchemin 0ca3f5ec80 Improving SQLA query generation (#421)
* Improving SQLA query generation

* Fixing debug
2016-05-02 10:00:28 -07:00
Siddharth GuptaandMaxime Beauchemin d7ea47387f enable timerotateloghandler (configurable) (#311)
* attempt to enchance logging

* clean up logging

* clean up logging

* reset to logger

* clean up imports

* add comments in config.py

* remove redundant declaration of logging.config. Already exists in caravel/__init__.py

* replace RotatingFileHandler with TimedRotatingFileHandler

* revert back running web server in debug mode

* fix debug in bin/caravel

* resolve build errors - formatting

* need to test

* enable time rotateloghandler

* revert back print statements - add feature for rotatetimelog which is needed and make it configurable

* revert back to default in master

* fix build issues

* remove extra print statement

* change log location to default

* configure console log level and format
2016-05-01 07:59:08 -07:00
x4baseandMaxime Beauchemin 7b5b602e96 Use batch_alter_table to drop column in the migration script (#406) 2016-04-30 08:30:40 -07:00
Chris Williams b78ec54650 Merge pull request #414 from airbnb/chris/fix-sunburst-level-trunc
[bugfix] allow repeated values across levels when building sunburst hierarchy
2016-04-29 10:59:29 -07:00
Maxime Beauchemin 77e4d4b2d4 Fixgin README link 2016-04-28 17:58:09 -07:00
Maxime Beauchemin 2198fd4e3d Adding badge for python versions 2016-04-28 17:55:01 -07:00
Maxime Beauchemin bd47a29076 CHANGELOG update 2016-04-27 19:43:03 -07:00
Maxime Beauchemin 337c9d59ae v0.8.9 2016-04-27 19:38:36 -07:00
Maxime Beauchemin 54860a874c Adding reference to another docker image in READMEM 2016-04-27 18:12:24 -07:00
Maxime Beauchemin 89d1a77281 [hotfix] filter_immune_slices fix 2016-04-27 13:41:06 -07:00
Maxime Beauchemin b634d03ac3 Show only Slices and Dashboards users have access to (#404)
* Introducing more security features

* Many to many owners for slices and dashboards
* Slices are filtered to only slices that the user has access to

* Adding unit tests
2016-04-26 16:44:51 -07:00
Maxime Beauchemin ab64a26b5b fix img loading overlay in explore view (#403) 2016-04-26 16:14:40 -07:00
andrewhnandMaxime Beauchemin a2f2ad84da add navigation, zoom to treemap (#396)
* add navigation, zoom to treemap

* don't use stale form data
2016-04-26 11:51:01 -07:00
Maxime Beauchemin c0fb9eeca4 [bugfix] big_number doesn't fadeout on hover 2016-04-26 09:29:40 -07:00
Maxime Beauchemin 42ac46c1e1 [bugfix] fix context confusion in Slice 2016-04-26 09:29:19 -07:00
Maxime Beauchemin 7b1075990c [hotfix] periodic refresh dashboard feature had broken caching 2016-04-25 15:28:14 -07:00
Maxime Beauchemin 37be01bc12 [hotfix] adding cache_key in payload 2016-04-25 12:41:30 -07:00
Maxime Beauchemin 7d90f26554 Fixing #388 (#391) 2016-04-21 21:10:09 -07:00
Maxime Beauchemin f1e10d8d25 One more Druid test (#387) 2016-04-21 08:17:15 -07:00
x4baseandMaxime Beauchemin b01d378475 Fix the label of the periodic-refresh button (#386) 2016-04-21 08:16:52 -07:00
Maxime Beauchemin a5f33fecd8 Adding login call for Druid test 2016-04-20 20:13:41 -07:00
Maxime Beauchemin f4177bfa94 More examples / tests (#385)
* More examples / tests

* Fixing the dashboards positioning
2016-04-20 17:36:37 -07:00
x4baseandMaxime Beauchemin d8a2b621d8 Periodically update the slices in the dashboard (#374)
* Periodically update the slices in the dashboard

* Make the refresh interval changeable

* Add the button and the modal for the user to change the refresh interval

* Don't use callback for refreshing

* Randomize to prevent all widgets refreshing at the same time

* Show the loading icon as an overlay when the slices refresh
2016-04-20 17:35:07 -07:00
Maxime Beauchemin 9a33557112 Removing forgotten print statement 2016-04-20 15:28:02 -07:00
Kim PhamandMaxime Beauchemin efc6bf4eb8 Redirect application log to stderr, which is picked up by gunicorn. (#335) 2016-04-20 15:09:15 -07:00
Maxime Beauchemin 17e711fda2 Druid unit tests using Mock (#384)
* Initial Druid mock unit tests

* More unit tests

* Test for Druid query

* Adding a groupby test
2016-04-20 15:08:10 -07:00
Maxime Beauchemin 01a8c96820 Specifying python versions supported in setup.py (#382)
* Specifying python versions supported in setup.py

* Fixing py3
2016-04-20 12:27:17 -07:00
Chris WilliamsandMaxime Beauchemin d96b634ded split sunburst breadcrumb names on '_' to apply ' '-dependent wrapping more freqently (#376) 2016-04-19 14:42:36 -07:00
Siddharth GuptaandMaxime Beauchemin afcdcf06a1 Fixing overwrite and save slice permissions for a give role (#298)
* Fixing overwrite and save slice permissions for a give role

* fix function name - build failed

* fix function name and test user permissions

* disable the button in the UI

* fix build error - characters too long in 1 line

* try to disable button on the UI

* disable cursor in caravel css. You wont be able to click anymore if no access

* fix build issues

* fix build errors! god bless me

* disable main features in dashboard and slice

* fix build issues
2016-04-18 13:56:00 -07:00
Maxime Beauchemin 5597eb4cc4 Fix db upgrade script b4456560d4f3 (#370)
* Recreating db upgrade error first

* Wrapping alter table calls in try statements
2016-04-18 12:49:13 -07:00
Siddharth GuptaandMaxime Beauchemin 3f0171b77b Configure Visualizations (#365)
* make viz types configurable

* make visualizations configurable

* deault every viz is true

* add blacklist viz_type

* fix build
2016-04-18 09:00:03 -07:00
Maxime Beauchemin badcd8bfa1 Storing version number in only one place (#362) 2016-04-17 08:20:11 -07:00
Maxime Beauchemin 04f1b176c4 Fixes issue #364 2016-04-17 08:17:08 -07:00
Maxime Beauchemin 899fe19afb [WiP] Attempting to support Druid's granularity origin as a hidden url param (#194)
* Supporting Druid'd time origin feature

* Adding origin to form, making it free form
2016-04-15 17:00:44 -07:00
Maxime Beauchemin f3168518e2 New url default for iframe viz 2016-04-15 16:50:16 -07:00
Maxime Beauchemin 04d769ff24 Some more error handling when rendering the explore view (#361) 2016-04-15 15:00:49 -07:00
Maxime Beauchemin 01c2c7baf8 Fixing unique constraint in SqlaTable model (#360) 2016-04-15 14:53:06 -07:00
Maxime Beauchemin 2d420eee25 v0.8.8 2016-04-14 21:25:47 -07:00
Maxime Beauchemin 1a6757f10a Better type detection for inference of column matrix (#353) 2016-04-14 21:24:04 -07:00
Maxime Beauchemin 63e5e932cb Hide password from database 'show' view (#355) 2016-04-14 21:23:49 -07:00
Maxime Beauchemin e6e8ec9620 [bugfix] missing redirect when datasource is missing (#352) 2016-04-14 20:25:40 -07:00
Maxime Beauchemin 4b48e9f1e9 Updating CHANGELOG 2016-04-13 23:07:25 -07:00
Maxime Beauchemin ffdae19312 v0.8.7 2016-04-13 22:45:50 -07:00
Maxime Beauchemin e5fabf39df Adjusting positioning in the examples 2016-04-13 22:39:23 -07:00
LudovicandMaxime Beauchemin eb5a41728e Change the size of the column datasource_name in datasource creation … (#345)
* Change the size of the column datasource_name in datasource creation table to fix a Sql server specific issue.

* Change the model according to the change of the database script done in the PR 345
2016-04-13 22:32:48 -07:00
Maxime Beauchemin 91a3594be3 Fixing the thumbs and the galery (#346) 2016-04-13 22:32:03 -07:00
andrewhnandMaxime Beauchemin 52ebdc5017 add treemap (#344) 2016-04-13 20:27:00 -07:00
Maxime Beauchemin 5cadd6794c Allowing to specify schema for tables (#330)
* Allowing to specify schema for tables

* Installed postgres and tested/fixed
2016-04-13 17:28:12 -07:00
Maxime Beauchemin 0a94b36d3d Adding version subcommand to CLI (#329) 2016-04-13 17:27:20 -07:00
Maxime Beauchemin 21b3a5f199 [big_number*] fixing a few bugs (#342) 2016-04-13 17:27:00 -07:00
Maxime Beauchemin a76ccf462d [welcome page] shows the most recently updated items first (#343) 2016-04-13 17:26:44 -07:00
Denis ZgonjaninandMaxime Beauchemin 8fe5790ec3 Don't die on malformed json in the extras field. Give feedback to user (#338) 2016-04-13 16:41:55 -07:00
Chris WilliamsandMaxime Beauchemin 1e08b3e8c5 add tooltips to sankey (#341)
* add tooltips to sankey

* update tooltip language ('count' --> 'value', 'Link Weight' --> 'Path Value').
2016-04-13 15:12:11 -07:00
Maxime Beauchemin 77828b630a [bugfix] druid granularity form field should be select2_freeform 2016-04-13 13:58:28 -07:00
Maxime Beauchemin 3c72751c26 [bugfix] druid granularity form field should be select2Sortable 2016-04-13 13:16:19 -07:00
Maxime Beauchemin af417b6b58 Adding expression column description in the CRUD 2016-04-12 10:41:23 -07:00
Maxime Beauchemin 3d1fc99353 Adding not in docs about connecting to dbs over SSL 2016-04-11 21:41:32 -07:00
Maxime Beauchemin 1dd416570a Json dumps iso date for Table view (#328) 2016-04-11 21:22:54 -07:00
Maxime Beauchemin 54fb76e680 Getting the SQL view back in a working state (#327) 2016-04-11 21:20:42 -07:00
Maxime Beauchemin 74975a1606 Getting error messages to show up on the interactive debugger 2016-04-11 21:17:57 -07:00
Denis ZgonjaninandMaxime Beauchemin 6d0b5767b3 Include connection parameters in call to Test Connection for a new database (#326) 2016-04-11 15:39:50 -07:00
Maxime Beauchemin 9ac979a336 Tweaks for the doc's gallery 2016-04-11 12:22:20 -07:00
Maxime Beauchemin f32ebeeb98 Fixing the way tables overflow in dashboard view (#310) 2016-04-11 12:11:47 -07:00
Maxime Beauchemin 807d686312 Showing thumbsnails when switching viz (#313)
* Showing thumbsnails when switching viz

* Adding missing images

* linting
2016-04-11 12:11:34 -07:00
Maxime Beauchemin 5b822492c8 Linting to 99% (#317) 2016-04-10 22:49:08 -07:00
Maxime Beauchemin c6da8117b7 Adding missing dep to dev-reqs.txt 2016-04-10 16:59:28 -07:00
antbellandMaxime Beauchemin a9af6b1b96 Fix for undefined inner_time_filter on missing granularity in models.SqlaTable (#309) 2016-04-10 16:22:58 -07:00
andrewhnandMaxime Beauchemin fe045ad076 New viz: box plot (#312)
* add box plot

* changes for linters
2016-04-10 16:15:25 -07:00
Maxime Beauchemin dab31eb66d Bugfix, link pointing to json 2016-04-10 11:17:37 -07:00
Maxime Beauchemin da421bb9af Updating TODO 2016-04-09 20:17:43 -07:00
Maxime Beauchemin f8e5d30e2e Revert previous css commit 2016-04-09 14:37:44 -07:00
Maxime Beauchemin bfd1c8711b Forcing widget overflow to be visible 2016-04-09 14:20:01 -07:00
Maxime Beauchemin 542b66ef68 Giving credit where credit is due (#307) 2016-04-09 13:17:20 -07:00
Maxime Beauchemin 866e00d78c Detecting loops in Sankeys (#271)
* Detecting loops in Sankeys

* Fixing the algo
2016-04-09 00:17:31 -07:00
Maxime Beauchemin a3dcb0f309 closes #292 (#304) 2016-04-08 22:32:12 -07:00
Maxime Beauchemin 25831f0033 Making prod web server run by default 2016-04-08 22:09:01 -07:00
Alexander ManceviceandMaxime Beauchemin b47ca785c7 Preserve order of breakdowns in bar_dist (#302) 2016-04-08 21:27:32 -07:00
prihodaandMaxime Beauchemin ef992b6449 Fix week and month Time grain in MySQL (#297)
With mysql datetime and timestamp columns, currently the Time grain "week" and "month" options don't remove the time part. This results in groupings like this:

timestamp count
2015-04-05 07:00:00 1
2015-04-05 10:00:00 1
2015-04-05 11:00:00 2
2015-04-05 11:50:00 1
2015-04-05 12:00:00 5
2015-04-05 14:20:00 1
2015-04-05 14:30:00 1

and so on.

This is solved by wrapping the DATE_SUB with DATE().
2016-04-08 20:54:04 -07:00
Maxime Beauchemin fdcedd097f Adding edit link to datasource in explore view (#303) 2016-04-08 20:49:54 -07:00
Maxime Beauchemin 9a02c88afa Adding link to docs on navbar, re-indent 2016-04-08 18:13:24 -07:00
Igor P. LeroyandMaxime Beauchemin b2de935411 Add OS dependencies link in development env docs (#300) 2016-04-08 17:57:24 -07:00
Chris WilliamsandMaxime Beauchemin ef64884e53 [heatmap] fix bug to display this view properly in dashboards. fix bug to display their d3-tip tooltips in dashboards. don't show empty tooltips on heatmap. update logic for margins so they fit dynamically based on label size. (#301) 2016-04-08 17:54:59 -07:00
Maxime Beauchemin 0afa5d2cba Added FAQ and db dependencies to docs 2016-04-08 08:44:46 -07:00
Siddharth GuptaandMaxime Beauchemin eff0beb195 Optimizing import statements for better readability and to avoid unused, excessive and duplicating imports in the project. (#294) 2016-04-07 23:01:40 -07:00
Maxime Beauchemin ee42aa790a Updating CHANGELOG 2016-04-07 14:42:07 -07:00
Maxime Beauchemin 2972122f40 Adding link to Strata slides 2016-04-07 14:38:23 -07:00
Maxime Beauchemin c5dead4791 v0.8.6 2016-04-07 14:26:28 -07:00
Maxime Beauchemin d933a21216 Prettyfying an image in the docs 2016-04-07 14:26:28 -07:00
michellethomas 59169bfc96 Merge pull request #212 from airbnb/big_number_total
Adding a big number total viz type that is not a timeseries metric
2016-04-07 14:22:12 -07:00
Maxime Beauchemin bcca840f01 Adding from __future__ imports (#288)
* Adding from __future__ imports

* fixes

* Fixing doctests

* Removing unused ColorFactory (in js now)

* linting
2016-04-07 08:39:08 -07:00
mherrandMaxime Beauchemin 90a3b9f2c4 Update INTHEWILD.md
added #GfKDataLab as a Caravel-User
2016-04-06 23:56:19 -07:00
Maxime Beauchemin a37e431150 Adding _images to .gitignore 2016-04-06 23:32:35 -07:00
Maxime Beauchemin bf38c714a5 Adding missing images 2016-04-06 21:10:41 -07:00
Julian NadeauandMaxime Beauchemin 6b0b03e009 Fix localhost link in installation docs 2016-04-06 20:13:04 -07:00
Maxime Beauchemin 8556b098f9 Enable Time Grain Option for Redshift 2016-04-06 20:12:24 -07:00
Julian NadeauandMaxime Beauchemin d122b37f5d Add python-pip to the install docs 2016-04-06 18:11:24 -07:00
Maxime Beauchemin 1756c27930 Adding upgrade instructions to docs 2016-04-06 18:02:40 -07:00
Aaron CritchleyandMaxime Beauchemin 7867267608 SqlAlchemy -> SQLAlchemy in README.md
* SqlAlchemy -> SQLAlchemy in README.md

Source: http://www.sqlalchemy.org/

* SqlAlchemy -> SQLAlchemy in tutorial.rst
2016-04-06 17:54:41 -07:00
Maxime Beauchemin 92d588694b Improving the Installation docs 2016-04-06 08:46:32 -07:00
Maxime Beauchemin d10eaeccc9 Adding a Gallery to the docs 2016-04-06 08:46:21 -07:00
greens231andMaxime Beauchemin c2bb49fec5 Fix 4e6a06bad7a8_init.py migration script to work with Postgres
* Update 4e6a06bad7a8_init.py

* removed comments
2016-04-06 08:24:52 -07:00
Maxime Beauchemin 062f2b81cf Datasource dropdown in Explore view 2016-04-06 08:23:27 -07:00
andrewhnandMaxime Beauchemin 65e72d0d07 Csv download improvements
* name + extension for generated csv and json files

* write csv index where data is meaningful
2016-04-06 08:22:49 -07:00
Maxime Beauchemin 345727635e Adding y_axis_format to DistributionBarViz 2016-04-06 08:20:24 -07:00
Maxime Beauchemin c2baa53b06 bugfix datatables move to new package 2016-04-05 21:40:24 -07:00
Maxime Beauchemin 31758827ae + button on Slice list view redirects to Table view with alert 2016-04-05 13:33:02 -07:00
Maxime Beauchemin 81de51bf6f Minor tweaks 2016-04-04 21:39:33 -07:00
andrewhnandMaxime Beauchemin 0d1f27dbc1 add postgres grains 2016-04-04 20:56:10 -07:00
Maxime Beauchemin c7282882d5 Fixing the pagination display on welcome 2016-04-04 20:47:12 -07:00
Maxime Beauchemin f9d04e8a72 Fixed refresh_datasource redirect 2016-04-04 20:43:06 -07:00
Maxime Beauchemin bf2e804331 Removed trailing coma in Database.extra default 2016-04-04 17:42:31 -07:00
Maxime Beauchemin c349b0a1c1 Fixed link url in docs 2016-04-04 17:14:08 -07:00
Maxime Beauchemin 4d640b5a3d [fix] panel overflowing on welcome page 2016-04-04 16:56:10 -07:00
Maxime Beauchemin 380c3f0c75 Using boostrap panels for form fieldsets in explore view 2016-04-04 16:14:55 -07:00
andrewhnandMaxime Beauchemin e3e8202c98 clear element before redrawing sankey 2016-04-04 16:13:54 -07:00
Maxime Beauchemin 889844407f Adding extra options to deeper configure sqlalchemy 2016-04-04 16:13:08 -07:00
Maxime Beauchemin f1830c36cf A better welcome page 2016-04-04 16:12:28 -07:00
Chris WilliamsandMaxime Beauchemin 92f73b67ca Move window.alert() calls to bootstrap modals. Also log errors to console.
* Move window.alert() calls to bootstrap modals. Also log errors that occur to console.

* move misc modal to basic template so it's available on all pages.
2016-04-04 16:11:23 -07:00
skjeandMaxime Beauchemin 9c1af66ba4 Fix ignored SQL where clauses 2016-04-04 16:03:21 -07:00
Maxime Beauchemin 2b31ab498b [hotfix] fixing json endpoint 2016-04-04 15:20:10 -07:00
Maxime Beauchemin 034fd077e1 Doc formating fix 2016-04-04 10:36:51 -07:00
Maxime Beauchemin ca4443247e Prettyfying the Caravel on README 2016-04-03 20:08:36 -07:00
Maxime Beauchemin 6f96252e45 A logo on the navbar 2016-04-03 20:03:27 -07:00
Maxime Beauchemin 0b93fd373d [hotfix] hashing unicode in py3 2016-04-03 14:04:53 -07:00
Jiayu LiuandMaxime Beauchemin c3789d53b4 Removing duplicate get_table in fetch_metadata 2016-04-03 07:40:58 -07:00
Maxime Beauchemin aec3c0b358 Fixing bug when datasource has been deleted 2016-04-03 07:37:18 -07:00
Karel VervaekeandMaxime Beauchemin ef45c20558 Hash cache keys to avoid too keys being too long. Resolves #240 2016-04-03 07:33:43 -07:00
Maxime Beauchemin 10ab678fc6 Finishing up the tutorial 2016-04-02 23:34:47 -07:00
Maxime Beauchemin 87fb40ae26 Bumping version of npm up 2016-04-02 23:24:36 -07:00
Maxime Beauchemin d245fb91b5 travis tweaks 2016-04-02 23:20:05 -07:00
Maxime Beauchemin c60032acce Pillow with a capital P 2016-04-02 23:17:27 -07:00
Maxime Beauchemin d2f51900f1 Adding a tutorial 2016-04-02 23:11:52 -07:00
Maxime Beauchemin 93405dc23a Clarify SQLALCHEMY_DATABASE_URI in the docs 2016-04-01 16:41:02 -07:00
Maxime Beauchemin dafdb51f35 Adding Caravel Docker link to README 2016-04-01 16:16:21 -07:00
Maxime Beauchemin 2d0fdf7e59 Adding a CHANGELOG.md 2016-04-01 13:55:04 -07:00
Maxime Beauchemin 718de6cd50 v0.8.5 2016-04-01 13:30:12 -07:00
Maxime Beauchemin 38062f160a Adding an INTHEWILD file 2016-04-01 13:23:51 -07:00
Maxime Beauchemin 9a5a27a101 Merge pull request #234 from airbnb/pinpandas
Pin pandas, remove numpy
2016-04-01 11:52:41 -07:00
Maxime Beauchemin 481d821721 Tweaking docs 2016-04-01 08:37:19 -07:00
Maxime Beauchemin 7b111b790e Adding an OS dependencies section to the install docs 2016-04-01 08:33:28 -07:00
Maxime Beauchemin ab92e7a94d Pin pandas, remove numpy 2016-04-01 08:04:44 -07:00
Maxime Beauchemin 22d2b7fe0f Merge pull request #229 from jmcomets/patch-1
Remove "requirements.txt" mention from README
2016-04-01 00:23:51 -07:00
Jean-Marie Comets 23319eed10 Remove "requirements.txt" mention from README
I noticed that there isn't the file `requirements.txt` was removed when moving to PyPi. Plus there's no such thing as an open-source project without an "update README" PR. ;)
2016-04-01 09:05:12 +02:00
Maxime Beauchemin 12cc064059 Merge pull request #225 from airbnb/chris/remove-random-power-units
remove power units from sankey diagram
2016-03-31 23:23:42 -07:00
Maxime Beauchemin ffa29b3909 Merge pull request #219 from airbnb/chris/sunburst-conditional-percent
Add 'Percent of previous' to sunburst vis. Appease npm warnings for data tables and d3.layout.cloud
2016-03-31 23:23:27 -07:00
Maxime Beauchemin ee4e3c1b98 Merge pull request #224 from cyrusstoller/typo_fix
Fixing minor typos in the readme
2016-03-31 23:21:12 -07:00
Maxime Beauchemin ebc16bb3fa Merge pull request #214 from airbnb/kim/fix_druid_datasource_bug
Fix an installation bug.
2016-03-31 23:19:44 -07:00
Chris Williams 0e2c0ce858 remove power units from sankey diagram 2016-03-31 16:59:39 -07:00
Cyrus Stoller 807f4dd0e5 Fixing minor typos in the readme 2016-03-31 15:38:34 -04:00
Chris Williams b87d8a0fbf change 'of previous' to 'of parent' 2016-03-31 12:26:49 -07:00
Chris Williams 0b3e2e00cc Add 'Percent of previous' to sunburst vis. Appease npm warnings for data tables and d3-sankey. 2016-03-31 12:26:49 -07:00
Maxime Beauchemin 167fb64d0c Merge pull request #218 from airbnb/redirects
Redirecting URL from previous names to caravel
2016-03-31 12:24:16 -07:00
Maxime Beauchemin eeba80c487 Merge branch 'master' into redirects 2016-03-31 12:07:35 -07:00
Maxime Beauchemin a3f92f687d Merge pull request #223 from thebucknerlife/master
Fixed typo in README
2016-03-31 12:05:32 -07:00
Maxime Beauchemin a4b61e97db Merge pull request #222 from brchristian/patch-1
remove duplicate Druid.io section in README.md
2016-03-31 12:04:59 -07:00
Greg Buckner 9595dcff4d Fixed typo in README 2016-03-31 12:02:26 -07:00
brchristian 58ab4e2415 remove duplicate Druid.io section in README.md 2016-03-31 11:47:33 -07:00
Maxime Beauchemin 2b71b72065 Redirecting URL from previous names to caravel 2016-03-31 09:31:07 -07:00
Maxime Beauchemin bd9051a168 Fixing README link 2016-03-31 08:50:47 -07:00
Maxime Beauchemin 6f63b3033f Dedupping info in README by pointing to docs 2016-03-31 08:48:34 -07:00
Kim Pham f659caa06b Fix an installation bug. 2016-03-30 19:08:38 -07:00
Maxime Beauchemin 5b7fe2b643 Merge pull request #213 from airbnb/kim/fix_druid_datasource_bug
Fix a bug when loading DruidDatasource.
2016-03-30 17:02:16 -07:00
Kim Pham e5553ab45e Fix lint warning. 2016-03-30 16:38:02 -07:00
Kim Pham 4a77b70046 A better fix. 2016-03-30 16:28:08 -07:00
Kim Pham f67c6b5f46 Fix a bug when loading DruidDatasource. 2016-03-30 16:11:14 -07:00
Maxime Beauchemin fd407424ad A few replacements related to the rename
mostly just s/mistercrunch/airbnb/g
2016-03-30 14:29:07 -07:00
Maxime Beauchemin e1b871982e Adding docs link badge 2016-03-29 21:28:43 -07:00
Maxime Beauchemin b164244cd8 Renaming forgotten doc file 2016-03-29 21:24:01 -07:00
Maxime Beauchemin 00226cce7f Changing image size, second try 2016-03-29 21:18:17 -07:00
Maxime Beauchemin 3a3d5cd7fb Changing image size 2016-03-29 21:16:53 -07:00
Maxime Beauchemin c6b77206ea Adding build status badge and image to README 2016-03-29 21:14:44 -07:00
Maxime Beauchemin d885dd34f9 Getting coveralls to work 2016-03-29 12:24:00 -07:00
Maxime Beauchemin 54fe2348fc Dummy commit to trigger travis 2016-03-29 12:00:37 -07:00
Maxime Beauchemin 6e1413d2dd Adding dev-reqs.txt to build 2016-03-29 11:59:25 -07:00
Maxime Beauchemin 0296b839ec Changing repo token for coveralls 2016-03-29 11:28:06 -07:00
Maxime Beauchemin 1c44f34490 Merge pull request #204 from airbnb/fixes
Fixing the order and coverage report for the unit tests
2016-03-29 11:24:37 -07:00
Maxime Beauchemin 10f3991e1f Merge pull request #209 from airbnb/screenshots
Fresh screenshots
2016-03-29 11:12:10 -07:00
Maxime Beauchemin cda1bd59f9 Fresh screenshots 2016-03-29 11:11:13 -07:00
Maxime Beauchemin 8e27099866 Fixing the tests for py3 2016-03-29 10:02:15 -07:00
Maxime Beauchemin 60bce9ed59 Fixing the order and coverage report for the unit tests 2016-03-28 23:50:11 -07:00
Maxime Beauchemin 1b4e750b2a Merge pull request #206 from airbnb/caravel
Caravel
2016-03-28 23:45:38 -07:00
Maxime Beauchemin 619d35878f [dashed->caravel] Replace in files 2016-03-28 22:01:21 -07:00
Maxime Beauchemin d48796f00e Caravel - renaming files 2016-03-28 21:53:24 -07:00
Chris Williams 5561a4932a Merge pull request #205 from airbnb/chris/sunburst-fix
fix sunburst error. add `less` to package.json
2016-03-28 17:07:51 -07:00
Chris Williams 1aee5b7801 fix sunburst error. add less to package.json because less-loader complains if it's not there. 2016-03-28 15:20:08 -07:00
Maxime Beauchemin 74c72b3ce4 Merge pull request #203 from airbnb/fixes
Fixing mysql install
2016-03-27 23:03:19 -07:00
Maxime Beauchemin 09021aacad Adding LONG to list of numeric types, updating TODO 2016-03-27 22:51:45 -07:00
Maxime Beauchemin 26c725171b Fixing mysql install 2016-03-27 22:37:04 -07:00
Maxime Beauchemin 4a0ea5fff7 Merge pull request #202 from airbnb/better_tests
Using setup.py nosetests to run tests
2016-03-27 19:55:45 -07:00
Maxime Beauchemin 301dce2dd1 Using setup.py nosetests to run tests 2016-03-27 19:15:21 -07:00
Maxime Beauchemin 6dce6df6b2 JS Lint breaks the build 2016-03-27 15:36:32 -07:00
Maxime Beauchemin 2102e04fec Adding tests for ping and health enpoint 2016-03-27 14:23:49 -07:00
Maxime Beauchemin 2397645ed4 Fix intermitent bug with npm locks 2016-03-27 14:23:49 -07:00
Maxime Beauchemin 0a8a1eda94 Merge pull request #199 from airbnb/touchups
Fix a few minor bugs
2016-03-27 08:09:08 -07:00
Maxime Beauchemin 4d2492d8fd Merge pull request #200 from airbnb/sankey
Add a sankey example
2016-03-27 08:08:36 -07:00
Maxime Beauchemin 48210d5275 Add a sankey example 2016-03-27 00:27:48 -07:00
Maxime Beauchemin 5804991b19 Fix a few minor bugs 2016-03-27 00:18:26 -07:00
Maxime Beauchemin 5be7b03ba4 [hotfix] Fix tooltip overflow to be visible outside widget 2016-03-26 21:10:41 -07:00
Maxime Beauchemin a898c27403 Minor CSS for navbar brand to not decorate the link 2016-03-26 18:10:40 -07:00
Maxime Beauchemin 49747150ae [hotfix] merging 2 migration scripts 2016-03-26 15:15:21 -07:00
Maxime Beauchemin fdce2aac0d Merge pull request #192 from airbnb/kim/misc_hack
Fix Druid metadata refresh.
2016-03-25 22:16:54 -07:00
Maxime Beauchemin 1c19f7fc77 Merge pull request #198 from airbnb/welcome
A welcome page
2016-03-25 22:15:28 -07:00
Maxime Beauchemin 12e20ca440 Merge pull request #197 from NiharikaRay/master
Adding a DRUID_IS_ACTIVE flag and changing nav bar
2016-03-25 22:14:46 -07:00
Maxime Beauchemin 0ccc19ff9b Merge pull request #196 from airbnb/fix_audit
Fixing issues around fk nullable=False on audit fields
2016-03-25 22:13:45 -07:00
Maxime Beauchemin e7bed92519 [hotfix] can't back out of history after entering explore 2016-03-25 22:02:50 -07:00
Maxime Beauchemin 8c0870e6ea Linting to perfection 2016-03-25 21:55:28 -07:00
Maxime Beauchemin c9203554e7 a welcome page 2016-03-25 18:08:33 -07:00
Kim Pham 2378fdf9ce Disable polymorphism in DruidMetric as well 2016-03-25 16:45:35 -07:00
Kim Pham 23b6bca89e Fix style warning 2016-03-25 13:49:45 -07:00
Kim Pham 7a7eb33348 Disable Datasource sql polymorphism & Fix refresh Druid metadata. 2016-03-25 13:44:35 -07:00
Niharika Ray fee6b3fafa Adding a DRUID_IS_ACTIVE flag and changing nav bar 2016-03-25 11:26:59 -07:00
Maxime Beauchemin 0f637bdd2e Fixing issues around fk nullable=False on audit fields 2016-03-25 08:13:15 -07:00
Maxime Beauchemin 10a1eddaa7 Improving the docs build script 2016-03-24 08:08:05 -07:00
Maxime Beauchemin 21d1c0a1b5 0.8.4 2016-03-23 22:26:16 -07:00
Maxime Beauchemin 3118d1b302 Merge pull request #193 from airbnb/favstar
Adding favorites for Slices and Dashboards
2016-03-23 22:25:12 -07:00
Maxime Beauchemin 2362b5a157 Tunning tooltips 2016-03-23 22:23:29 -07:00
Maxime Beauchemin 7ede732892 Adding favorites for Slices and Dashboards 2016-03-23 22:15:23 -07:00
Maxime Beauchemin 5b10b19ed7 Fixing the docs 2016-03-23 21:41:37 -07:00
Maxime Beauchemin 14f298b385 dashboard bug fixes and better page titles 2016-03-23 21:27:45 -07:00
Maxime Beauchemin 89da51f8d7 Pointing landscape badge to the right branch 2016-03-23 16:16:20 -07:00
Maxime Beauchemin d5487c6b25 0.8.3 2016-03-23 14:11:37 -07:00
Maxime Beauchemin a244f3aafb Fixing build issues with preventive rm /Users/maxime_beauchemin/.npm/*.lock 2016-03-23 14:11:37 -07:00
Maxime Beauchemin 9d3bf7763c Fixing build issues with preventive rm /Users/maxime_beauchemin/.npm/*.lock 2016-03-23 11:14:29 -07:00
Maxime Beauchemin b0f10a90ce Merge pull request #188 from airbnb/caching
Introducing a caching layer!
2016-03-22 22:55:35 -07:00
Maxime Beauchemin 417749f880 Explore mode should only expose cache on first load 2016-03-22 22:09:02 -07:00
Maxime Beauchemin fded04a51d Hack to get the force refresh in the explore view 2016-03-22 18:11:10 -07:00
Maxime Beauchemin d8192eca0a Introducing a caching layer 2016-03-22 18:11:10 -07:00
Maxime Beauchemin 2d3edf3a2e js lint breaks the build 2016-03-22 08:16:23 -07:00
Maxime Beauchemin 0890d22899 Merge pull request #191 from airbnb/week-grain
Add week ending and week start to grain
2016-03-21 15:56:36 -07:00
Siddharth bad3128df9 Update grain label name 2016-03-21 15:41:49 -07:00
Siddharth 48c8a90247 Fix multi-line statement 2016-03-21 14:27:03 -07:00
Siddharth a9ba47fe12 Add week ending and week start to grain 2016-03-21 13:45:14 -07:00
Maxime Beauchemin f09f3d7c4b Merge pull request #190 from airbnb/vnum
Cranking up version numbers
2016-03-19 21:46:03 -07:00
Maxime Beauchemin e17d78e196 Cranking up version numbers 2016-03-19 21:33:39 -07:00
Maxime Beauchemin 9450c12552 note about the previous name in README 2016-03-19 16:09:08 -07:00
Maxime Beauchemin f01b41827e Adding reqs badge 2016-03-19 16:03:15 -07:00
Maxime Beauchemin b5f4d3b515 Adding reqs badge 2016-03-19 10:30:54 -07:00
Maxime Beauchemin 28e5a87cd0 pypi badges 2016-03-19 10:16:59 -07:00
Maxime Beauchemin 10c48f04cd [renaming] 2016-03-19 10:07:18 -07:00
Maxime Beauchemin f79aca1796 rename - 2nd phase 2016-03-18 08:52:50 -07:00
Maxime Beauchemin be6b2fe556 [panoramix] -> [dashed] 2016-03-17 23:44:58 -07:00
420 changed files with 40858 additions and 10264 deletions
+34
View File
@@ -0,0 +1,34 @@
engines:
csslint:
enabled: false
duplication:
enabled: false
eslint:
enabled: true
config:
config: caravel/assets/.eslintrc
pep8:
enabled: true
fixme:
enabled: false
radon:
enabled: true
checks:
Complexity:
enabled: false
ratings:
paths:
- "**.py"
- "caravel/assets/**.js"
- "caravel/assets/**.jsx"
exclude_paths:
- ".*"
- "**.pyc"
- "**.gz"
- "env/"
- "tests/"
- "caravel/assets/images/"
- "caravel/assets/vendor/"
- "caravel/assets/node_modules/"
- "caravel/assets/javascripts/dist/"
- "caravel/migrations"
+1 -1
View File
@@ -1 +1 @@
repo_token: EMkVRVEKYgUESKaNN9QyOhPnFnKNqyDcJ
repo_token: eESbYiv4An6KEvjpmguDs4L7YkubXbqn1
+9 -4
View File
@@ -1,20 +1,25 @@
*.pyc
babel
changelog.sh
.DS_Store
.coverage
_build
_static
panoramix/bin/panoramixc
_images
caravel/bin/caravelc
env_py3
.eggs
build
*.db
tmp
panoramix_config.py
caravel_config.py
local_config.py
env
dist
panoramix.egg-info/
caravel.egg-info/
app.db
*.bak
.idea
*.sqllite
# Node.js, webpack artifacts
*.entry.js
+3 -5
View File
@@ -9,17 +9,15 @@ pylint:
disable:
- cyclic-import
- invalid-name
- logging-format-interpolation
options:
docstring-min-length: 10
pep8:
full: true
ignore-paths:
- docs
- panoramix/migrations/env.py
- panoramix/ascii_art.py
- caravel/migrations/env.py
- caravel/ascii_art.py
ignore-patterns:
- ^example/doc_.*\.py$
- (^|/)docs(/|$)
python-targets:
- 2
- 3
+32 -14
View File
@@ -1,20 +1,38 @@
language: python
python:
- "2.7"
- "3.4"
addons:
code_climate:
repo_token: 5f3a06c425eef7be4b43627d7d07a3e46c45bdc07155217825ff7c49cb6a470c
apt:
sources:
- deadsnakes
packages:
- python3.5
cache:
directories:
- $HOME/.wheelhouse/
env:
global:
- TRAVIS_CACHE=$HOME/.travis_cache/
- TRAVIS_NODE_VERSION="5.11"
matrix:
- TOX_ENV=javascript
- TOX_ENV=py34-postgres
- TOX_ENV=py34-sqlite
- TOX_ENV=py27-mysql
- TOX_ENV=py27-sqlite
before_install:
- npm install -g npm@'>=3.9.5'
before_script:
- mysql -e 'drop database if exists caravel; create database caravel DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci' -u root
- mysql -u root -e "CREATE USER 'mysqluser'@'localhost' IDENTIFIED BY 'mysqluserpassword';"
- mysql -u root -e "GRANT ALL ON caravel.* TO 'mysqluser'@'localhost';"
- psql -c 'create database caravel;' -U postgres
- psql -c "CREATE USER postgresuser WITH PASSWORD 'pguserpassword';" -U postgres
- export PATH=${PATH}:/tmp/hive/bin
install:
- pip wheel -w $HOME/.wheelhouse -f $HOME/.wheelhouse -r requirements.txt
- pip install --find-links=$HOME/.wheelhouse --no-index -rrequirements.txt
- python setup.py install
- cd panoramix/assets
- pip install --upgrade pip
- pip install tox tox-travis
- rm -rf ~/.nvm && git clone https://github.com/creationix/nvm.git ~/.nvm && (cd ~/.nvm && git checkout `git describe --abbrev=0 --tags`) && source ~/.nvm/nvm.sh && nvm install $TRAVIS_NODE_VERSION
- npm install
- npm run prod
- cd $TRAVIS_BUILD_DIR
script: bash run_tests.sh
after_success:
- coveralls
- cd panoramix/assets
- npm run lint
script: tox -e $TOX_ENV
+1349
View File
File diff suppressed because it is too large Load Diff
+116 -27
View File
@@ -9,7 +9,7 @@ You can contribute in many ways:
### Report Bugs
Report bugs through Github
Report bugs through GitHub
If you are reporting a bug, please include:
@@ -30,14 +30,14 @@ Look through the GitHub issues for features. Anything tagged with
### Documentation
Panoramix could always use better documentation,
whether as part of the official Panoramix docs,
Caravel could always use better documentation,
whether as part of the official Caravel docs,
in docstrings, `docs/*.rst` or even on the web as blog posts or
articles.
### Submit Feedback
The best way to send feedback is to file an issue on Github.
The best way to send feedback is to file an issue on GitHub.
If you are proposing a feature:
@@ -49,14 +49,16 @@ If you are proposing a feature:
## Latest Documentation
[API Documentation](http://pythonhosted.com/panoramix)
Latest documentation and tutorial are available [here](http://airbnb.io/caravel)
## Setting up a Python development environment
# fork the repo on github and then clone it
Check the [OS dependencies](http://airbnb.io/caravel/installation.html#os-dependencies) before follows these steps.
# fork the repo on GitHub and then clone it
# alternatively you may want to clone the main repo but that won't work
# so well if you are planning on sending PRs
# git clone git@github.com:mistercrunch/panoramix.git
# git clone git@github.com:airbnb/caravel.git
# [optional] setup a virtual env and activate it
virtualenv env
@@ -66,28 +68,30 @@ If you are proposing a feature:
python setup.py develop
# Create an admin user
fabmanager create-admin --app panoramix
fabmanager create-admin --app caravel
# Initialize the database
panoramix db upgrade
caravel db upgrade
# Create default roles and permissions
panoramix init
caravel init
# Load some data to play with
panoramix load_examples
caravel load_examples
# start a dev web server
panoramix runserver -d
caravel runserver -d
## Setting up the node / npm javascript environment
`panoramix/assets` contains all npm-managed, front end assets.
`caravel/assets` contains all npm-managed, front end assets.
Flask-Appbuilder itself comes bundled with jQuery and bootstrap.
While these may be phased out over time, these packages are currently not
managed with npm.
### Node/npm versions
Make sure you are using recent versions of node and npm. No problems have been found with node>=5.10 and npm>=3.9.
### Using npm to generate bundled files
@@ -100,23 +104,22 @@ echo prefix=~/.npm-packages >> ~/.npmrc
curl -L https://www.npmjs.com/install.sh | sh
```
The final step is to add
`~/.node/bin` to your `PATH` so commands you install globally are usable.
Add something like this to your `.bashrc` file.
The final step is to add `~/.npm-packages/bin` to your `PATH` so commands you install globally are usable.
Add something like this to your `.bashrc` file, then `source ~/.bashrc` to reflect the change.
```
export PATH="$HOME/.node/bin:$PATH"
export PATH="$HOME/.npm-packages/bin:$PATH"
```
#### npm packages
To install third party libraries defined in `package.json`, run the
following within this directory which will install them in a
following within the `caravel/assets/` directory which will install them in a
new `node_modules/` folder within `assets/`.
```
npm install
```
To parse and generate bundled files for panoramix, run either of the
To parse and generate bundled files for caravel, run either of the
following commands. The `dev` flag will keep the npm script running and
re-run it upon any changes within the assets directory.
@@ -132,24 +135,57 @@ For every development session you will have to start a flask dev server
as well as an npm watcher
```
panoramix runserver -d -p 8081
caravel runserver -d -p 8081
npm run dev
```
## Testing
Tests can then be run with:
Python tests can be run with:
./run_unit_tests.sh
./run_tests.sh
We use [Mocha](https://mochajs.org/), [Chai](http://chaijs.com/) and [Enzyme](http://airbnb.io/enzyme/) to test Javascript. Tests can be run with:
cd /caravel/caravel/assets/javascripts
npm i
npm run test
## Linting
Lint the project with:
# for python changes
flake8 changes tests
flake8 changes caravel
# for javascript
npm run lint
## Linting with codeclimate
Codeclimate is a service we use to measure code quality and test coverage. To get codeclimate's report on your branch, ideally before sending your PR, you can setup codeclimate against your Caravel fork. After you push to your fork, you should be able to get the report at http://codeclimate.com . Alternatively, if you prefer to work locally, you can install the codeclimate cli tool.
*Install the codeclimate cli tool*
```
curl -L https://github.com/docker/machine/releases/download/v0.7.0/docker-machine-`uname -s`-`uname -m` > /usr/local/bin/docker-machine && chmod +x /usr/local/bin/docker-machine
brew install docker
docker-machine create --driver virtual box default
docker-machine env default
eval "$(docker-machine env default)"
docker pull codeclimate/codeclimate
brew tap codeclimate/formulae
brew install codeclimate
```
*Run the lint command:*
```
docker-machine start
eval "$(docker-machine env default)”
codeclimate analyze
```
More info can be found here: https://docs.codeclimate.com/docs/open-source-free
## API documentation
Generate the documentation with:
@@ -157,12 +193,12 @@ Generate the documentation with:
cd docs && ./build.sh
## CSS Themes
As part of the npm build process, CSS for Panoramix is compiled from ```Less```, a dynamic stylesheet language.
As part of the npm build process, CSS for Caravel is compiled from `Less`, a dynamic stylesheet language.
It's possible to customize or add your own theme to Panoramix, either by overriding CSS rules or preferably
by modifying the Less variables or files in ```assets/stylesheets/less/```.
It's possible to customize or add your own theme to Caravel, either by overriding CSS rules or preferably
by modifying the Less variables or files in `assets/stylesheets/less/`.
The ```variables.less``` and ```bootswatch.less``` files that ship with Panoramix are derived from
The `variables.less` and `bootswatch.less` files that ship with Caravel are derived from
[Bootswatch](https://bootswatch.com) and thus extend Bootstrap. Modify variables in these files directly, or
swap them out entirely with the equivalent files from other Bootswatch (themes)[https://github.com/thomaspark/bootswatch.git]
@@ -177,7 +213,60 @@ meets these guidelines:
as part of the same PR. Doc string are often sufficient, make
sure to follow the sphinx compatible standards.
3. The pull request should work for Python 2.6, 2.7, and ideally python 3.3.
`from __future__ import ` will be required in every `.py` file soon.
``from __future__ import`` will be required in every `.py` file soon.
4. Code will be reviewed by re running the unittests, flake8 and syntax
should be as rigorous as the core Python project.
5. Please rebase and resolve all conflicts before submitting.
## Translations
We use [Babel](http://babel.pocoo.org/en/latest/) to translate Caravel. The
key is to instrument the strings that need translation using
`from flask_babel import lazy_gettext as _`. Once this is imported in
a module, all you have to do is to `_("Wrap your strings")` using the
underscore `_` "function".
To enable changing language in your environment, you can simply add the
`LANGUAGES` parameter to your `caravel_config.py`. Having more than one
options here will add a language selection dropdown on the right side of the
navigation bar.
LANGUAGES = {
'en': {'flag': 'us', 'name': 'English'},
'fr': {'flag': 'fr', 'name': 'French'},
'zh': {'flag': 'cn', 'name': 'Chinese'},
}
As per the [Flask AppBuilder documentation] about translation, to create a
new language dictionary, run the following command:
pybabel init -i ./babel/messages.pot -d caravel/translations -l es
Then it's a matter of running the statement below to gather all stings that
need translation
fabmanager babel-extract --target caravel/translations/
You can then translate the strings gathered in files located under
`caravel/translation`, where there's one per language. For the translations
to take effect, they need to be compiled using this command:
fabmanager babel-compile --target caravel/translations/
## Adding new datasources
1. Create Models and Views for the datasource, add them under caravel folder, like a new my_models.py
with models for cluster, datasources, columns and metrics and my_views.py with clustermodelview
and datasourcemodelview.
2. Create db migration files for the new models
3. Specify this variable to add the datasource model and from which module it is from in config.py:
For example:
`ADDITIONAL_MODULE_DS_MAP = {'caravel.my_models': ['MyDatasource', 'MyOtherDatasource']}`
This means it'll register MyDatasource and MyOtherDatasource in caravel.my_models module in the source registry.
+14
View File
@@ -0,0 +1,14 @@
Please use [pull requests](https://github.com/airbnb/caravel/pull/new/master)
to add your organization and/or project to this document!
Organizations
----------
- [Airbnb](https://github.com/airbnb)
- [GfK Data Lab] (http://datalab.gfk.com)
- [Maieutical Labs] (https://cloudschooling.it)
- [Shopkick] (https://www.shopkick.com)
- [Amino] (https://amino.com)
Projects
----------
- None we know of yet
+8 -7
View File
@@ -1,8 +1,9 @@
recursive-include panoramix/templates *
recursive-include panoramix/static *
recursive-exclude panoramix/static/assets/node_modules *
recursive-include panoramix/static/assets/node_modules/font-awesome *
recursive-exclude panoramix/static/docs *
recursive-include caravel/templates *
recursive-include caravel/static *
recursive-exclude caravel/static/assets/node_modules *
recursive-include caravel/static/assets/node_modules/font-awesome *
recursive-exclude caravel/static/docs *
recursive-exclude caravel/static/spec *
recursive-exclude tests *
recursive-include panoramix/data *
recursive-include panoramix/migrations *
recursive-include caravel/data *
recursive-include caravel/migrations *
+83 -129
View File
@@ -1,183 +1,137 @@
Panoramix
Caravel
=========
<img src="http://i.imgur.com/H0Kyvyi.jpg" style="border-radius: 20px; box-shadow:5px 5px 5px gray;" alt="Caravel" width="500"/>
[![Join the chat at https://gitter.im/mistercrunch/panoramix](https://badges.gitter.im/mistercrunch/panoramix.svg)](https://gitter.im/mistercrunch/panoramix?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
![img](https://travis-ci.org/mistercrunch/panoramix.svg?branch=master)
[![Coverage Status](https://coveralls.io/repos/mistercrunch/panoramix/badge.svg?branch=master&service=github)](https://coveralls.io/github/mistercrunch/panoramix?branch=master)
[![Code Health](https://landscape.io/github/mistercrunch/panoramix/immune_to_filter/landscape.svg?style=flat)](https://landscape.io/github/mistercrunch/panoramix/master)
[![Build Status](https://travis-ci.org/airbnb/caravel.svg?branch=master)](https://travis-ci.org/airbnb/caravel)
[![PyPI version](https://badge.fury.io/py/caravel.svg)](https://badge.fury.io/py/caravel)
[![Coverage Status](https://coveralls.io/repos/airbnb/caravel/badge.svg?branch=master&service=github)](https://coveralls.io/github/airbnb/caravel?branch=master)
[![JS Test Coverage](https://codeclimate.com/github/airbnb/caravel/badges/coverage.svg)](https://codeclimate.com/github/airbnb/caravel/coverage)
[![Code Health](https://landscape.io/github/airbnb/caravel/master/landscape.svg?style=flat)](https://landscape.io/github/airbnb/caravel/master)
[![Code Climate](https://codeclimate.com/github/airbnb/caravel/badges/gpa.svg)](https://codeclimate.com/github/airbnb/caravel)
[![PyPI](https://img.shields.io/pypi/pyversions/caravel.svg?maxAge=2592000)](https://pypi.python.org/pypi/caravel)
[![Requirements Status](https://requires.io/github/airbnb/caravel/requirements.svg?branch=master)](https://requires.io/github/airbnb/caravel/requirements/?branch=master)
[![Join the chat at https://gitter.im/airbnb/caravel](https://badges.gitter.im/airbnb/caravel.svg)](https://gitter.im/airbnb/caravel?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[![Documentation](https://img.shields.io/badge/docs-airbnb.io-blue.svg)](http://airbnb.io/caravel/)
[![dependencies Status](https://david-dm.org/airbnb/caravel/status.svg?path=caravel/assets)](https://david-dm.org/airbnb/caravel?path=caravel/assets)
Panoramix is a data exploration platform designed to be visual, intuitive
Caravel is a data exploration platform designed to be visual, intuitive
and interactive.
[this project used to be named **Panoramix**]
Video - Introduction to Panoramix
---------------------------------
[![Panoramix - ](http://img.youtube.com/vi/3Txm_nj_R7M/0.jpg)](http://www.youtube.com/watch?v=3Txm_nj_R7M)
Screenshots
------------
![img](http://i.imgur.com/bi09J9X.png)
![img](http://i.imgur.com/aOaH0ty.png)
Screenshots & Gifs
------------------
![img](http://g.recordit.co/xFXSvaGUts.gif)
Panoramix
---
![img](http://g.recordit.co/uZggYOdR5g.gif)
---
![img](http://g.recordit.co/U70FWLpLvh.gif)
---
![img](http://i.imgur.com/x8t30YU.png)
---
![img](http://i.imgur.com/DRCnbq6.png)
Caravel
---------
Panoramix's main goal is to make it easy to slice, dice and visualize data.
It empowers its user to perform **analytics at the speed of thought**.
Caravel's main goal is to make it easy to slice, dice and visualize data.
It empowers users to perform **analytics at the speed of thought**.
Panoramix provides:
* A quick way to intuitively visualize datasets
* Create and share interactive dashboards
Caravel provides:
* A quick way to intuitively visualize datasets by allowing users to create
and share interactive dashboards
* A rich set of visualizations to analyze your data, as well as a flexible
way to extend the capabilities
* An extensible, high granularity security model allowing intricate rules
on who can access which features, and integration with major
authentication providers (database, OpenID, LDAP, OAuth & REMOTE_USER
through Flask AppBuiler)
* A simple semantic layer, allowing to control how data sources are
displayed in the UI,
by defining which fields should show up in which dropdown and which
aggregation and function (metrics) are made available to the user
* Deep integration with Druid allows for Panoramix to stay blazing fast while
* A simple semantic layer, allowing to control how data sources are
displayed in the UI, by defining which fields should show up in
which dropdown and which aggregation and function (metrics) are
made available to the user
* Deep integration with Druid allows for Caravel to stay blazing fast while
slicing and dicing large, realtime datasets
* Fast loading dashboards with configurable caching
Buzz Phrases
------------
* Analytics at the speed of thought!
* Instantaneous learning curve
* Realtime analytics when querying [Druid.io](http://druid.io)
* Extentsible to infinity
Database Support
----------------
Panoramix was originally designed on to of Druid.io, but quickly broadened
its scope to support other databases through the use of SqlAlchemy, a Python
Caravel was originally designed on top of Druid.io, but quickly broadened
its scope to support other databases through the use of SQLAlchemy, a Python
ORM that is compatible with
[most common databases](http://docs.sqlalchemy.org/en/rel_1_0/core/engines.html).
[most common databases](http://docs.sqlalchemy.org/en/rel_1_0/core/engines.html).
What is Druid?
-------------
From their website at http://druid.io
*Druid is an open-source analytics data store designed for
business intelligence (OLAP) queries on event data. Druid provides low
latency (real-time) data ingestion, flexible data exploration,
and fast data aggregation. Existing Druid deployments have scaled to
trillions of events and petabytes of data. Druid is best used to
*Druid is an open-source analytics data store designed for
business intelligence (OLAP) queries on event data. Druid provides low
latency (real-time) data ingestion, flexible data exploration,
and fast data aggregation. Existing Druid deployments have scaled to
trillions of events and petabytes of data. Druid is best used to
power analytic dashboards and applications.*
Installation
------------
Installation & Configuration
----------------------------
Panoramix is currently only tested using Python 2.7.*. Python 3 support is
on the roadmap, Python 2.6 won't be supported.
[See in the documentation](http://airbnb.io/caravel/installation.html)
Follow these few simple steps to install Panoramix.
```
# Install panoramix
pip install panoramix
# Create an admin user
fabmanager create-admin --app panoramix
# Initialize the database
panoramix db upgrade
# Create default roles and permissions
panoramix init
# Load some data to play with
panoramix load_examples
# Start the development web server
panoramix runserver -d
```
After installation, you should be able to point your browser to the right
hostname:port [http://localhost:8088](http://localhost:8088), login using
the credential you entered while creating the admin account, and navigate to
`Menu -> Admin -> Refresh Metadata`. This action should bring in all of
your datasources for Panoramix to be aware of, and they should show up in
`Menu -> Datasources`, from where you can start playing with your data!
Configuration
-------------
To configure your application, you need to create a file (module)
`panoramix_config.py` and make sure it is in your PYTHONPATH. Here are some
of the parameters you can copy / paste in that configuration module:
```
#---------------------------------------------------------
# Panoramix specifix config
#---------------------------------------------------------
ROW_LIMIT = 5000
WEBSERVER_THREADS = 8
PANORAMIX_WEBSERVER_PORT = 8088
#---------------------------------------------------------
#---------------------------------------------------------
# Flask App Builder configuration
#---------------------------------------------------------
# Your App secret key
SECRET_KEY = '\2\1thisismyscretkey\1\2\e\y\y\h'
# The SQLAlchemy connection string.
SQLALCHEMY_DATABASE_URI = 'sqlite:////tmp/panoramix.db'
# Flask-WTF flag for CSRF
CSRF_ENABLED = True
# Whether to run the web server in debug mode or not
DEBUG = True
```
This file also allows you to define configuration parameters used by
Flask App Builder, the web framework used by Panoramix. Please consult
the [Flask App Builder Documentation](http://flask-appbuilder.readthedocs.org/en/latest/config.html) for more information on how to configure Panoramix.
* From the UI, enter the information about your clusters in the
``Admin->Clusters`` menu by hitting the + sign.
* Once the Druid cluster connection information is entered, hit the
``Admin->Refresh Metadata`` menu item to populate
* Navigate to your datasources
More screenshots
----------------
![img](http://i.imgur.com/Rt6gNQ9.png)
![img](http://i.imgur.com/t7VOtqQ.png)
![img](http://i.imgur.com/PaiFQnH.png)
![img](http://i.imgur.com/CdcGHuC.png)
![img](http://i.imgur.com/SAhDJCI.png)
Related Links
---
![img](http://i.imgur.com/iuLpv1c.png)
---
![img](http://i.imgur.com/V2FWeZx.png)
---
![img](http://i.imgur.com/BeUtCzF.png)
---
![img](http://i.imgur.com/phoY7jI.png)
---
![img](http://i.imgur.com/NvIDgdC.png)
---
![img](http://i.imgur.com/DzwYyns.png)
Resources
-------------
* [Panoramix Google Group] (https://groups.google.com/forum/#!forum/airbnb_panoramix)
* [Gitter (live chat) Channel](https://gitter.im/mistercrunch/panoramix)
* [Caravel Google Group](https://groups.google.com/forum/#!forum/airbnb_caravel)
* [Gitter (live chat) Channel](https://gitter.im/airbnb/caravel)
* [Docker image 1](https://hub.docker.com/r/kochalex/caravel/)
[Docker image 2](https://hub.docker.com/r/amancevice/caravel/) (community contributed)
* [Slides from Strata (March 2016)](https://drive.google.com/open?id=0B5PVE0gzO81oOVJkdF9aNkJMSmM)
Tip of the Hat
--------------
Panoramix would not be possible without these great frameworks / libs
Caravel would not be possible without these great frameworks / libs
* Flask App Builder - Allowing us to focus on building the app quickly while
getting the foundation for free
* The Flask ecosystem - Simply amazing. So much Plug, easy play.
* NVD3 - One of the best charting library out there
* Much more, check out the requirements.txt file!
* NVD3 - One of the best charting libraries out there
* Much more, check out the `install_requires` section in the [setup.py](https://github.com/airbnb/caravel/blob/master/setup.py) file!
Contributing
------------
Interested in contributing? Casual hacking? Check out [Contributing.MD](https://github.com/mistercrunch/panoramix/blob/master/CONTRIBUTING.md)
Interested in contributing? Casual hacking? Check out [Contributing.MD](https://github.com/airbnb/caravel/blob/master/CONTRIBUTING.md)
+5 -14
View File
@@ -1,25 +1,18 @@
# TODO
List of TODO items for Panoramix
List of TODO items for Caravel
## Important
* **Caching:** integrate with flask-cache
* **Getting proper JS testing:** unit tests on the Python side are pretty
solid, but now we need a test suite for the JS part of the site,
testing all the ajax-type calls
* **Viz Plugins:** Allow people to define and share visualization plugins.
ideally one would only need to drop in a set of files in a folder and
Panoramix would discover and expose the plugins
Caravel would discover and expose the plugins
## Features
* **Stars:** set dashboards, slices and datasets as favorites
* **Homepage:** a page that has links to your Slices and Dashes, favorited
content, feed of recent actions (people viewing your objects)
* **Comments:** allow for people to comment on slices and dashes
* **Dashboard URL filters:** `{dash_url}#fltin__fieldname__value1,value2`
* **Default slice:** choose a default slice for the dataset instead of
default endpoint
* **refresh freq**: specifying the refresh frequency of a dashboard and
specific slices within it, some randomization would be nice
* **Widget sets / chart grids:** a way to have all charts support making
a series of charts and putting them in a grid. The same way that you
can groupby for series, you could chart by. The form field set would be
@@ -32,15 +25,14 @@ List of TODO items for Panoramix
some visualizations as annotations. An example of a layer might be
"holidays" or "site outages", ...
* **Slack integration** - TBD
* **Sexy Viz Selector:** the visualization selector should be a nice large
modal with nice thumbnails for each one of the viz
* **Comments:** allow for people to comment on slices and dashes
## Easy-ish fix
* Build matrix to include mysql using tox
* CREATE VIEW button from SQL editor
* Test button for when editing SQL expression
* Slider form element
* datasource in explore mode could be a dropdown
* [druid] Allow for post aggregations (ratios!)
* in/notin filters autocomplete (druid)
@@ -53,5 +45,4 @@ List of TODO items for Panoramix
* ...
## Community
* Create a proper user documentation (started using Sphinx and boostrap...)
* Usage vid
* Turorial vids
+1 -1
View File
@@ -29,7 +29,7 @@ script_location = migrations
# are written from script.py.mako
# output_encoding = utf-8
sqlalchemy.url = scheme://localhost/panoramix
sqlalchemy.url = scheme://localhost/caravel
# Logging configuration
[loggers]
+4
View File
@@ -0,0 +1,4 @@
[ignore: caravel/assets/node_modules/**]
[python: caravel/**.py]
[jinja2: caravel/**/templates/**.html]
encoding = utf-8
+1809
View File
File diff suppressed because it is too large Load Diff
+112
View File
@@ -0,0 +1,112 @@
"""Package's main module!"""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals
import logging
import os
from logging.handlers import TimedRotatingFileHandler
from flask import Flask, redirect
from flask_appbuilder import SQLA, AppBuilder, IndexView
from sqlalchemy import event, exc
from flask_appbuilder.baseviews import expose
from flask_cache import Cache
from flask_migrate import Migrate
from caravel.source_registry import SourceRegistry
from werkzeug.contrib.fixers import ProxyFix
APP_DIR = os.path.dirname(__file__)
CONFIG_MODULE = os.environ.get('CARAVEL_CONFIG', 'caravel.config')
app = Flask(__name__)
app.config.from_object(CONFIG_MODULE)
if not app.debug:
# In production mode, add log handler to sys.stderr.
app.logger.addHandler(logging.StreamHandler())
app.logger.setLevel(logging.INFO)
db = SQLA(app)
@event.listens_for(db.engine, 'checkout')
def checkout(dbapi_con, con_record, con_proxy):
"""
Making sure the connection is live, and preventing against:
'MySQL server has gone away'
Copied from:
http://stackoverflow.com/questions/30630120/mysql-keeps-losing-connection-during-celery-tasks
"""
try:
try:
if hasattr(dbapi_con, 'ping'):
dbapi_con.ping(False)
else:
cursor = dbapi_con.cursor()
cursor.execute("SELECT 1")
except TypeError:
app.logger.debug('MySQL connection died. Restoring...')
dbapi_con.ping()
except dbapi_con.OperationalError as e:
app.logger.warning(e)
if e.args[0] in (2006, 2013, 2014, 2045, 2055):
raise exc.DisconnectionError()
else:
raise
return db
cache = Cache(app, config=app.config.get('CACHE_CONFIG'))
migrate = Migrate(app, db, directory=APP_DIR + "/migrations")
# Logging configuration
logging.basicConfig(format=app.config.get('LOG_FORMAT'))
logging.getLogger().setLevel(app.config.get('LOG_LEVEL'))
if app.config.get('ENABLE_TIME_ROTATE'):
logging.getLogger().setLevel(app.config.get('TIME_ROTATE_LOG_LEVEL'))
handler = TimedRotatingFileHandler(app.config.get('FILENAME'),
when=app.config.get('ROLLOVER'),
interval=app.config.get('INTERVAL'),
backupCount=app.config.get('BACKUP_COUNT'))
logging.getLogger().addHandler(handler)
if app.config.get('ENABLE_CORS'):
from flask_cors import CORS
CORS(app, **app.config.get('CORS_OPTIONS'))
if app.config.get('ENABLE_PROXY_FIX'):
app.wsgi_app = ProxyFix(app.wsgi_app)
if app.config.get('UPLOAD_FOLDER'):
try:
os.makedirs(app.config.get('UPLOAD_FOLDER'))
except OSError:
pass
class MyIndexView(IndexView):
@expose('/')
def index(self):
return redirect('/caravel/welcome')
appbuilder = AppBuilder(
app, db.session,
base_template='caravel/base.html',
indexview=MyIndexView,
security_manager_class=app.config.get("CUSTOM_SECURITY_MANAGER"))
sm = appbuilder.sm
get_session = appbuilder.get_session
# Registering sources
module_datasource_map = app.config.get("DEFAULT_MODULE_DS_MAP")
module_datasource_map.update(app.config.get("ADDITIONAL_MODULE_DS_MAP"))
SourceRegistry.register_sources(module_datasource_map)
from caravel import views, config # noqa
@@ -1,3 +1,8 @@
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals
error = (
"MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\n"+
"MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMNNMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\n"+
@@ -66,3 +71,12 @@ stacktrace="""
=======================================================================================================
-------------------------------------------------------------------------------------------------------
"""
boat = """\
+ +
)`.).
)``)``) .~~
).-'.-')|)
|-).-).-'_'-/
~~~\ `o-o-o' /~~~~
~~~'---.____/~~~"""
+3
View File
@@ -0,0 +1,3 @@
{
"presets" : ["airbnb", "es2015", "react"]
}
+10
View File
@@ -0,0 +1,10 @@
**/*{.,-}min.js
**/*.sh
coverage/**
dist/*
images/*
node_modules/*
node_modules*/*
spec/*
stylesheets/*
vendor/*
+18
View File
@@ -0,0 +1,18 @@
{
"extends": "airbnb",
"parserOptions":{
"ecmaFeatures": {
"experimentalObjectRestSpread": true
}
},
"rules": {
"prefer-template": 0,
"new-cap": 0,
"no-restricted-syntax": 0,
"guard-for-in": 0,
"prefer-arrow-callback": 0,
"func-names": 0,
"react/jsx-no-bind": 0,
"no-confusing-arrow": 0,
}
}
+54
View File
@@ -0,0 +1,54 @@
verbose: true
instrumentation:
root: './javascripts'
extensions: ['.js', '.jsx']
excludes: [
'dist/**'
]
embed-source: false
variable: __coverage__
compact: true
preserve-comments: false
complete-copy: false
save-baseline: true
baseline-file: ./coverage/coverage-baseline.json
include-all-sources: true
include-pid: false
es-modules: true
reporting:
print: summary
reports:
- lcov
dir: ./coverage
watermarks:
statements: [50, 80]
lines: [50, 80]
functions: [50, 80]
branches: [50, 80]
report-config:
clover: {file: clover.xml}
cobertura: {file: cobertura-coverage.xml}
json: {file: coverage-final.json}
json-summary: {file: coverage-summary.json}
lcovonly: {file: lcov.info}
teamcity: {file: null, blockName: Code Coverage Summary}
text: {file: null, maxCols: 0}
text-lcov: {file: lcov.info}
text-summary: {file: null}
hooks:
hook-run-in-context: false
post-require-hook: null
handle-sigint: false
check:
global:
statements: 0
lines: 0
branches: 0
functions: 0
excludes: []
each:
statements: 0
lines: 0
branches: 0
functions: 0
excludes: []
Binary file not shown.

After

Width:  |  Height:  |  Size: 9.9 KiB

Before

Width:  |  Height:  |  Size: 459 KiB

After

Width:  |  Height:  |  Size: 459 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 144 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

Before

Width:  |  Height:  |  Size: 552 KiB

After

Width:  |  Height:  |  Size: 552 KiB

Before

Width:  |  Height:  |  Size: 236 KiB

After

Width:  |  Height:  |  Size: 236 KiB

Before

Width:  |  Height:  |  Size: 702 KiB

After

Width:  |  Height:  |  Size: 702 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Before

Width:  |  Height:  |  Size: 328 KiB

After

Width:  |  Height:  |  Size: 328 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 102 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Before

Width:  |  Height:  |  Size: 93 KiB

After

Width:  |  Height:  |  Size: 93 KiB

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Before

Width:  |  Height:  |  Size: 49 KiB

After

Width:  |  Height:  |  Size: 49 KiB

Before

Width:  |  Height:  |  Size: 121 KiB

After

Width:  |  Height:  |  Size: 121 KiB

Before

Width:  |  Height:  |  Size: 1.5 MiB

After

Width:  |  Height:  |  Size: 1.5 MiB

Before

Width:  |  Height:  |  Size: 147 KiB

After

Width:  |  Height:  |  Size: 147 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 154 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 190 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 245 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 133 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 128 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 141 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 106 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 132 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 253 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 242 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 425 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 100 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 738 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 314 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 220 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 222 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 460 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 270 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 200 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 170 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 107 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 94 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 115 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 133 KiB

+19
View File
@@ -0,0 +1,19 @@
# TODO
* Figure out how to organize the left panel, integrate Search
* collapse sql beyond 10 lines
* Security per-database (dropdown)
* Get a to work
## Cosmetic
* Result set font is too big
* lmiit/timer/buttons wrap
* table label is transparent
* SqlEditor buttons
* use react-bootstrap-prompt for query title input
* Make tabs look great
# PROJECT
* Write Runbook
* Confirm backups
* merge chef branch
@@ -0,0 +1,130 @@
export const RESET_STATE = 'RESET_STATE';
export const ADD_QUERY_EDITOR = 'ADD_QUERY_EDITOR';
export const CLONE_QUERY_TO_NEW_TAB = 'CLONE_QUERY_TO_NEW_TAB';
export const REMOVE_QUERY_EDITOR = 'REMOVE_QUERY_EDITOR';
export const MERGE_TABLE = 'MERGE_TABLE';
export const REMOVE_TABLE = 'REMOVE_TABLE';
export const START_QUERY = 'START_QUERY';
export const STOP_QUERY = 'STOP_QUERY';
export const END_QUERY = 'END_QUERY';
export const REMOVE_QUERY = 'REMOVE_QUERY';
export const EXPAND_TABLE = 'EXPAND_TABLE';
export const COLLAPSE_TABLE = 'COLLAPSE_TABLE';
export const QUERY_SUCCESS = 'QUERY_SUCCESS';
export const QUERY_FAILED = 'QUERY_FAILED';
export const QUERY_EDITOR_SETDB = 'QUERY_EDITOR_SETDB';
export const QUERY_EDITOR_SET_SCHEMA = 'QUERY_EDITOR_SET_SCHEMA';
export const QUERY_EDITOR_SET_TITLE = 'QUERY_EDITOR_SET_TITLE';
export const QUERY_EDITOR_SET_AUTORUN = 'QUERY_EDITOR_SET_AUTORUN';
export const QUERY_EDITOR_SET_SQL = 'QUERY_EDITOR_SET_SQL';
export const SET_DATABASES = 'SET_DATABASES';
export const ADD_WORKSPACE_QUERY = 'ADD_WORKSPACE_QUERY';
export const REMOVE_WORKSPACE_QUERY = 'REMOVE_WORKSPACE_QUERY';
export const SET_ACTIVE_QUERY_EDITOR = 'SET_ACTIVE_QUERY_EDITOR';
export const ADD_ALERT = 'ADD_ALERT';
export const REMOVE_ALERT = 'REMOVE_ALERT';
export const REFRESH_QUERIES = 'REFRESH_QUERIES';
export const SET_NETWORK_STATUS = 'SET_NETWORK_STATUS';
export function resetState() {
return { type: RESET_STATE };
}
export function setDatabases(databases) {
return { type: SET_DATABASES, databases };
}
export function addQueryEditor(queryEditor) {
return { type: ADD_QUERY_EDITOR, queryEditor };
}
export function cloneQueryToNewTab(query) {
return { type: CLONE_QUERY_TO_NEW_TAB, query };
}
export function setNetworkStatus(networkOn) {
return { type: SET_NETWORK_STATUS, networkOn };
}
export function addAlert(alert) {
return { type: ADD_ALERT, alert };
}
export function removeAlert(alert) {
return { type: REMOVE_ALERT, alert };
}
export function setActiveQueryEditor(queryEditor) {
return { type: SET_ACTIVE_QUERY_EDITOR, queryEditor };
}
export function removeQueryEditor(queryEditor) {
return { type: REMOVE_QUERY_EDITOR, queryEditor };
}
export function removeQuery(query) {
return { type: REMOVE_QUERY, query };
}
export function queryEditorSetDb(queryEditor, dbId) {
return { type: QUERY_EDITOR_SETDB, queryEditor, dbId };
}
export function queryEditorSetSchema(queryEditor, schema) {
return { type: QUERY_EDITOR_SET_SCHEMA, queryEditor, schema };
}
export function queryEditorSetAutorun(queryEditor, autorun) {
return { type: QUERY_EDITOR_SET_AUTORUN, queryEditor, autorun };
}
export function queryEditorSetTitle(queryEditor, title) {
return { type: QUERY_EDITOR_SET_TITLE, queryEditor, title };
}
export function queryEditorSetSql(queryEditor, sql) {
return { type: QUERY_EDITOR_SET_SQL, queryEditor, sql };
}
export function mergeTable(table) {
return { type: MERGE_TABLE, table };
}
export function expandTable(table) {
return { type: EXPAND_TABLE, table };
}
export function collapseTable(table) {
return { type: COLLAPSE_TABLE, table };
}
export function removeTable(table) {
return { type: REMOVE_TABLE, table };
}
export function startQuery(query) {
return { type: START_QUERY, query };
}
export function stopQuery(query) {
return { type: STOP_QUERY, query };
}
export function querySuccess(query, results) {
return { type: QUERY_SUCCESS, query, results };
}
export function queryFailed(query, msg) {
return { type: QUERY_FAILED, query, msg };
}
export function addWorkspaceQuery(query) {
return { type: ADD_WORKSPACE_QUERY, query };
}
export function removeWorkspaceQuery(query) {
return { type: REMOVE_WORKSPACE_QUERY, query };
}
export function refreshQueries(alteredQueries) {
return { type: REFRESH_QUERIES, alteredQueries };
}
@@ -0,0 +1,8 @@
export const STATE_BSSTYLE_MAP = {
failed: 'danger',
pending: 'info',
running: 'warning',
success: 'success',
};
export const STATUS_OPTIONS = ['success', 'failed', 'running'];
@@ -0,0 +1,41 @@
import React from 'react';
import { Alert } from 'react-bootstrap';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import * as Actions from '../actions';
class Alerts extends React.Component {
removeAlert(alert) {
this.props.actions.removeAlert(alert);
}
render() {
const alerts = this.props.alerts.map((alert) =>
<Alert
bsStyle={alert.bsStyle}
style={{ width: '500px', textAlign: 'midddle', margin: '10px auto' }}
>
{alert.msg}
<i
className="fa fa-close pull-right"
onClick={this.removeAlert.bind(this, alert)}
style={{ cursor: 'pointer' }}
/>
</Alert>
);
return (
<div>{alerts}</div>
);
}
}
Alerts.propTypes = {
alerts: React.PropTypes.array,
actions: React.PropTypes.object,
};
function mapDispatchToProps(dispatch) {
return {
actions: bindActionCreators(Actions, dispatch),
};
}
export default connect(null, mapDispatchToProps)(Alerts);
@@ -0,0 +1,71 @@
import * as Actions from '../actions';
import React from 'react';
import TabbedSqlEditors from './TabbedSqlEditors';
import QueryAutoRefresh from './QueryAutoRefresh';
import QuerySearch from './QuerySearch';
import Alerts from './Alerts';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
hash: window.location.hash,
};
}
componentDidMount() {
window.addEventListener('hashchange', this.onHashChanged.bind(this));
}
componentWillUnmount() {
window.removeEventListener('hashchange', this.onHashChanged.bind(this));
}
onHashChanged() {
this.setState({ hash: window.location.hash });
}
render() {
if (this.state.hash) {
return (
<div className="container-fluid">
<div className="row">
<div className="col-md-12">
<QuerySearch />
</div>
</div>
</div>
);
}
return (
<div className="App SqlLab">
<div className="container-fluid">
<QueryAutoRefresh />
<Alerts alerts={this.props.alerts} />
<div className="row">
<div className="col-md-12">
<TabbedSqlEditors />
</div>
</div>
</div>
</div>
);
}
}
App.propTypes = {
alerts: React.PropTypes.array,
};
function mapStateToProps(state) {
return {
alerts: state.alerts,
};
}
function mapDispatchToProps(dispatch) {
return {
actions: bindActionCreators(Actions, dispatch),
};
}
export default connect(mapStateToProps, mapDispatchToProps)(App);
@@ -0,0 +1,48 @@
import React from 'react';
import { Button, OverlayTrigger, Tooltip } from 'react-bootstrap';
const ButtonWithTooltip = (props) => {
let tooltip = (
<Tooltip id="tooltip">
{props.tooltip}
</Tooltip>
);
return (
<OverlayTrigger
overlay={tooltip}
delayShow={300}
placement={props.placement}
delayHide={150}
>
<Button
onClick={props.onClick}
bsStyle={props.bsStyle}
bsSize={props.bsSize}
disabled={props.disabled}
className={props.className}
>
{props.children}
</Button>
</OverlayTrigger>
);
};
ButtonWithTooltip.defaultProps = {
onClick: () => {},
disabled: false,
placement: 'top',
bsStyle: 'default',
};
ButtonWithTooltip.propTypes = {
bsSize: React.PropTypes.string,
bsStyle: React.PropTypes.string,
children: React.PropTypes.element,
className: React.PropTypes.string,
disabled: React.PropTypes.bool,
onClick: React.PropTypes.func,
placement: React.PropTypes.string,
tooltip: React.PropTypes.string,
};
export default ButtonWithTooltip;
@@ -0,0 +1,55 @@
import React from 'react';
import CopyToClipboard from '../../components/CopyToClipboard';
const propTypes = {
qe: React.PropTypes.object,
};
const defaultProps = {
qe: null,
};
export default class CopyQueryTabUrl extends React.Component {
constructor(props) {
super(props);
const uri = window.location.toString();
const search = window.location.search;
const cleanUri = search ? uri.substring(0, uri.indexOf('?')) : uri;
const query = search.substring(1);
this.state = {
uri,
cleanUri,
query,
};
}
getQueryLink() {
const params = [];
const qe = this.props.qe;
if (qe.dbId) params.push('dbid=' + qe.dbId);
if (qe.title) params.push('title=' + encodeURIComponent(qe.title));
if (qe.schema) params.push('schema=' + encodeURIComponent(qe.schema));
if (qe.autorun) params.push('autorun=' + qe.autorun);
if (qe.sql) params.push('sql=' + encodeURIComponent(qe.sql));
const queryString = params.join('&');
const queryLink = this.state.cleanUri + '?' + queryString;
return queryLink;
}
render() {
return (
<CopyToClipboard
inMenu
text={this.getQueryLink()}
copyNode={<span>share query</span>}
tooltipText="copy URL to clipboard"
shouldShowText={false}
/>
);
}
}
CopyQueryTabUrl.propTypes = propTypes;
CopyQueryTabUrl.defaultProps = defaultProps;
@@ -0,0 +1,65 @@
const $ = window.$ = require('jquery');
import React from 'react';
import { bindActionCreators } from 'redux';
import Select from 'react-select';
import { connect } from 'react-redux';
import * as Actions from '../actions';
class DatabaseSelect extends React.Component {
constructor(props) {
super(props);
this.state = {
databaseLoading: false,
databaseOptions: [],
};
}
componentDidMount() {
this.fetchDatabaseOptions();
}
changeDb(db) {
this.props.onChange(db);
}
fetchDatabaseOptions() {
this.setState({ databaseLoading: true });
const url = '/databaseasync/api/read?_flt_0_expose_in_sqllab=1';
$.get(url, (data) => {
const options = data.result.map((db) => ({ value: db.id, label: db.database_name }));
this.setState({ databaseOptions: options, databaseLoading: false });
this.props.actions.setDatabases(data.result);
});
}
render() {
return (
<div>
<Select
name="select-db"
placeholder={`Select a database (${this.state.databaseOptions.length})`}
options={this.state.databaseOptions}
value={this.props.databaseId}
isLoading={this.state.databaseLoading}
autosize={false}
onChange={this.changeDb.bind(this)}
/>
</div>
);
}
}
DatabaseSelect.propTypes = {
onChange: React.PropTypes.func,
actions: React.PropTypes.object,
databaseId: React.PropTypes.number,
};
DatabaseSelect.defaultProps = {
onChange: () => {},
databaseId: null,
};
function mapDispatchToProps(dispatch) {
return {
actions: bindActionCreators(Actions, dispatch),
};
}
export default connect(null, mapDispatchToProps)(DatabaseSelect);
@@ -0,0 +1,54 @@
import React from 'react';
import { OverlayTrigger, Tooltip } from 'react-bootstrap';
class Link extends React.Component {
render() {
let tooltip = (
<Tooltip id="tooltip">
{this.props.tooltip}
</Tooltip>
);
const link = (
<a
href={this.props.href}
onClick={this.props.onClick}
style={this.props.style}
className={'Link ' + this.props.className}
>
{this.props.children}
</a>
);
if (this.props.tooltip) {
return (
<OverlayTrigger
overlay={tooltip}
placement={this.props.placement}
delayShow={300}
delayHide={150}
>
{link}
</OverlayTrigger>
);
}
return link;
}
}
Link.propTypes = {
children: React.PropTypes.object,
className: React.PropTypes.string,
href: React.PropTypes.string,
onClick: React.PropTypes.func,
placement: React.PropTypes.string,
style: React.PropTypes.object,
tooltip: React.PropTypes.string,
};
Link.defaultProps = {
disabled: false,
href: '#',
tooltip: null,
placement: 'top',
onClick: () => {},
};
export default Link;
@@ -0,0 +1,69 @@
import React from 'react';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import * as Actions from '../actions';
const $ = require('jquery');
const QUERY_UPDATE_FREQ = 1000;
const QUERY_UPDATE_BUFFER_MS = 5000;
class QueryAutoRefresh extends React.Component {
componentWillMount() {
this.startTimer();
}
componentWillUnmount() {
this.stopTimer();
}
startTimer() {
if (!(this.timer)) {
this.timer = setInterval(this.stopwatch.bind(this), QUERY_UPDATE_FREQ);
}
}
stopTimer() {
clearInterval(this.timer);
this.timer = null;
}
stopwatch() {
const url = '/caravel/queries/' + (this.props.queriesLastUpdate - QUERY_UPDATE_BUFFER_MS);
// No updates in case of failure.
$.getJSON(url, (data) => {
if (Object.keys(data).length > 0) {
this.props.actions.refreshQueries(data);
}
if (!this.props.networkOn) {
this.props.actions.setNetworkStatus(true);
}
})
.fail(() => {
if (this.props.networkOn) {
this.props.actions.setNetworkStatus(false);
}
});
}
render() {
return null;
}
}
QueryAutoRefresh.propTypes = {
actions: React.PropTypes.object,
queriesLastUpdate: React.PropTypes.number,
networkOn: React.PropTypes.bool,
};
QueryAutoRefresh.defaultProps = {
// queries: null,
};
function mapStateToProps(state) {
return {
queriesLastUpdate: state.queriesLastUpdate,
networkOn: state.networkOn,
};
}
function mapDispatchToProps(dispatch) {
return {
actions: bindActionCreators(Actions, dispatch),
};
}
export default connect(mapStateToProps, mapDispatchToProps)(QueryAutoRefresh);
@@ -0,0 +1,58 @@
import React from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import * as Actions from '../actions';
import QueryTable from './QueryTable';
import { Alert } from 'react-bootstrap';
const QueryHistory = (props) => {
const activeQeId = props.tabHistory[props.tabHistory.length - 1];
const queriesArray = [];
for (const id in props.queries) {
if (props.queries[id].sqlEditorId === activeQeId) {
queriesArray.push(props.queries[id]);
}
}
if (queriesArray.length > 0) {
return (
<QueryTable
columns={[
'state', 'started', 'duration', 'progress',
'rows', 'sql', 'output', 'actions',
]}
queries={queriesArray}
/>
);
}
return (
<Alert bsStyle="info">
No query history yet...
</Alert>
);
};
QueryHistory.defaultProps = {
queries: {},
};
QueryHistory.propTypes = {
queries: React.PropTypes.object,
tabHistory: React.PropTypes.array,
actions: React.PropTypes.object,
};
function mapStateToProps(state) {
return {
queries: state.queries,
tabHistory: state.tabHistory,
};
}
function mapDispatchToProps(dispatch) {
return {
actions: bindActionCreators(Actions, dispatch),
};
}
export default connect(mapStateToProps, mapDispatchToProps)(QueryHistory);
@@ -0,0 +1,62 @@
import React from 'react';
import Link from './Link';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import * as Actions from '../actions';
import shortid from 'shortid';
class QueryLink extends React.Component {
popTab() {
const qe = {
id: shortid.generate(),
title: this.props.query.title,
dbId: this.props.query.dbId,
autorun: false,
sql: this.props.query.sql,
};
this.props.actions.addQueryEditor(qe);
}
render() {
return (
<div>
<div className="clearfix">
<div className="pull-left">
<a
href="#"
tooltip="Pop this query in a new tab"
onClick={this.popTab.bind(this)}
>
{this.props.query.title}
</a>
</div>
<div className="pull-right">
<Link
onClick={this.props.actions.removeWorkspaceQuery.bind(this, this.props.query)}
tooltip="Remove query from workspace"
href="#"
>
&times;
</Link>
</div>
</div>
<hr />
</div>
);
}
}
QueryLink.propTypes = {
query: React.PropTypes.object,
actions: React.PropTypes.object,
};
QueryLink.defaultProps = {
};
function mapDispatchToProps(dispatch) {
return {
actions: bindActionCreators(Actions, dispatch),
};
}
export default connect(null, mapDispatchToProps)(QueryLink);
@@ -0,0 +1,142 @@
const $ = window.$ = require('jquery');
import React from 'react';
import { Button } from 'react-bootstrap';
import Select from 'react-select';
import QueryTable from './QueryTable';
import DatabaseSelect from './DatabaseSelect';
import { STATUS_OPTIONS } from '../common';
class QuerySearch extends React.Component {
constructor(props) {
super(props);
this.state = {
userLoading: false,
userOptions: [],
databaseId: null,
userId: null,
searchText: null,
status: 'success',
queriesArray: [],
};
}
componentWillMount() {
this.fetchUsers();
this.refreshQueries();
}
onUserClicked(userId) {
this.setState({ userId }, () => { this.refreshQueries(); });
}
onDbClicked(dbId) {
this.setState({ databaseId: dbId }, () => { this.refreshQueries(); });
}
onChange(db) {
const val = (db) ? db.value : null;
this.setState({ databaseId: val });
}
insertParams(baseUrl, params) {
return baseUrl + '?' + params.join('&');
}
changeUser(user) {
const val = (user) ? user.value : null;
this.setState({ userId: val });
}
changeStatus(status) {
const val = (status) ? status.value : null;
this.setState({ status: val });
}
changeSearch(event) {
this.setState({ searchText: event.target.value });
}
fetchUsers() {
this.setState({ userLoading: true });
const url = '/users/api/read';
$.getJSON(url, (data, status) => {
if (status === 'success') {
const options = [];
for (let i = 0; i < data.pks.length; i++) {
options.push({ value: data.pks[i], label: data.result[i].username });
}
this.setState({ userOptions: options, userLoading: false });
}
});
}
refreshQueries() {
const params = [
`userId=${this.state.userId}`,
`databaseId=${this.state.databaseId}`,
`searchText=${this.state.searchText}`,
`status=${this.state.status}`,
];
const url = this.insertParams('/caravel/search_queries', params);
$.getJSON(url, (data, status) => {
if (status === 'success') {
const newQueriesArray = [];
for (const id in data) {
newQueriesArray.push(data[id]);
}
this.setState({ queriesArray: newQueriesArray });
}
});
}
render() {
return (
<div>
<div className="row space-1">
<div className="col-sm-2">
<Select
name="select-user"
placeholder="[User]"
options={this.state.userOptions}
value={this.state.userId}
isLoading={this.state.userLoading}
autosize={false}
onChange={this.changeUser.bind(this)}
/>
</div>
<div className="col-sm-2">
<DatabaseSelect
onChange={this.onChange.bind(this)}
databaseId={this.state.databaseId}
/>
</div>
<div className="col-sm-4">
<input
type="text"
onChange={this.changeSearch.bind(this)}
className="form-control input-sm"
placeholder="Search Results"
/>
</div>
<div className="col-sm-2">
<Select
name="select-state"
placeholder="[Query Status]"
options={STATUS_OPTIONS.map((s) => ({ value: s, label: s }))}
value={this.state.status}
isLoading={false}
autosize={false}
onChange={this.changeStatus.bind(this)}
/>
</div>
<Button bsSize="small" bsStyle="success" onClick={this.refreshQueries.bind(this)}>
Search
</Button>
</div>
<QueryTable
columns={[
'state', 'db', 'user',
'progress', 'rows', 'sql', 'querylink',
]}
onUserClicked={this.onUserClicked.bind(this)}
onDbClicked={this.onDbClicked.bind(this)}
queries={this.state.queriesArray}
/>
</div>
);
}
}
export default QuerySearch;
@@ -0,0 +1,177 @@
import React from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import * as Actions from '../actions';
import moment from 'moment';
import { Table } from 'reactable';
import { ProgressBar } from 'react-bootstrap';
import Link from './Link';
import VisualizeModal from './VisualizeModal';
import SqlShrink from './SqlShrink';
import { STATE_BSSTYLE_MAP } from '../common';
import { fDuration } from '../../modules/dates';
import { getLink } from '../../../utils/common';
class QueryTable extends React.Component {
constructor(props) {
super(props);
const uri = window.location.toString();
const cleanUri = uri.substring(0, uri.indexOf('#'));
this.state = {
cleanUri,
showVisualizeModal: false,
activeQuery: null,
};
}
getQueryLink(dbId, sql) {
const params = ['dbid=' + dbId, 'sql=' + sql, 'title=Untitled Query'];
const link = getLink(this.state.cleanUri, params);
return encodeURI(link);
}
hideVisualizeModal() {
this.setState({ showVisualizeModal: false });
}
showVisualizeModal(query) {
this.setState({ showVisualizeModal: true });
this.setState({ activeQuery: query });
}
restoreSql(query) {
this.props.actions.queryEditorSetSql({ id: query.sqlEditorId }, query.sql);
}
openQueryInNewTab(query) {
this.props.actions.cloneQueryToNewTab(query);
}
render() {
const data = this.props.queries.map((query) => {
const q = Object.assign({}, query);
if (q.endDttm) {
q.duration = fDuration(q.startDttm, q.endDttm);
}
q.user = (
<button
className="btn btn-link btn-xs"
onClick={this.props.onUserClicked.bind(this, q.userId)}
>
{q.user}
</button>
);
q.db = (
<button
className="btn btn-link btn-xs"
onClick={this.props.onDbClicked.bind(this, q.dbId)}
>
{q.db}
</button>
);
q.started = moment(q.startDttm).format('HH:mm:ss');
const source = (q.ctas) ? q.executedSql : q.sql;
q.sql = (
<SqlShrink sql={source} maxWidth={100} />
);
q.output = q.tempTable;
q.progress = (
<ProgressBar
style={{ width: '75px' }}
striped
now={q.progress}
label={`${q.progress}%`}
/>
);
let errorTooltip;
if (q.errorMessage) {
errorTooltip = (
<Link tooltip={q.errorMessage}>
<i className="fa fa-exclamation-circle text-danger" />
</Link>
);
}
q.state = (
<div>
<span className={'m-r-3 label label-' + STATE_BSSTYLE_MAP[q.state]}>
{q.state}
</span>
{errorTooltip}
</div>
);
q.actions = (
<div style={{ width: '75px' }}>
<Link
className="fa fa-line-chart m-r-3"
tooltip="Visualize the data out of this query"
onClick={this.showVisualizeModal.bind(this, query)}
/>
<Link
className="fa fa-pencil m-r-3"
onClick={this.restoreSql.bind(this, query)}
tooltip="Overwrite text in editor with a query on this table"
placement="top"
/>
<Link
className="fa fa-plus-circle m-r-3"
onClick={this.openQueryInNewTab.bind(this, query)}
tooltip="Run query in a new tab"
placement="top"
/>
<Link
className="fa fa-trash m-r-3"
tooltip="Remove query from log"
onClick={this.props.actions.removeQuery.bind(this, query)}
/>
</div>
);
q.querylink = (
<div style={{ width: '100px' }}>
<a
href={this.getQueryLink(q.dbId, source)}
className="btn btn-primary btn-xs"
>
<i className="fa fa-external-link" />Open in SQL Editor
</a>
</div>
);
return q;
}).reverse();
return (
<div>
<VisualizeModal
show={this.state.showVisualizeModal}
query={this.state.activeQuery}
onHide={this.hideVisualizeModal.bind(this)}
/>
<Table
columns={this.props.columns}
className="table table-condensed"
data={data}
/>
</div>
);
}
}
QueryTable.propTypes = {
columns: React.PropTypes.array,
actions: React.PropTypes.object,
queries: React.PropTypes.array,
onUserClicked: React.PropTypes.func,
onDbClicked: React.PropTypes.func,
};
QueryTable.defaultProps = {
columns: ['started', 'duration', 'rows'],
queries: [],
onUserClicked: () => {},
onDbClicked: () => {},
};
function mapStateToProps() {
return {};
}
function mapDispatchToProps(dispatch) {
return {
actions: bindActionCreators(Actions, dispatch),
};
}
export default connect(mapStateToProps, mapDispatchToProps)(QueryTable);
@@ -0,0 +1,95 @@
import React from 'react';
import { Alert, Button, ButtonGroup } from 'react-bootstrap';
import { Table } from 'reactable';
import VisualizeModal from './VisualizeModal';
class ResultSet extends React.Component {
constructor(props) {
super(props);
this.state = {
searchText: '',
showModal: false,
};
}
changeSearch(event) {
this.setState({ searchText: event.target.value });
}
showModal() {
this.setState({ showModal: true });
}
hideModal() {
this.setState({ showModal: false });
}
render() {
const results = this.props.query.results;
let controls = <div className="noControls" />;
if (this.props.showControls) {
controls = (
<div className="ResultSetControls">
<div className="clearfix">
<div className="pull-left">
<ButtonGroup>
<Button
bsSize="small"
onClick={this.showModal.bind(this)}
>
<i className="fa fa-line-chart m-l-1" /> Visualize
</Button>
<Button bsSize="small" href={'/caravel/csv/' + this.props.query.id}>
<i className="fa fa-file-text-o" /> .CSV
</Button>
</ButtonGroup>
</div>
<div className="pull-right">
<input
type="text"
onChange={this.changeSearch.bind(this)}
className="form-control input-sm"
placeholder="Search Results"
/>
</div>
</div>
</div>
);
}
if (results && results.data && results.data.length > 0) {
return (
<div>
<VisualizeModal
show={this.state.showModal}
query={this.props.query}
onHide={this.hideModal.bind(this)}
/>
{controls}
<div className="ResultSet">
<Table
data={results.data}
columns={results.columns.map((col) => col.name)}
sortable
className="table table-condensed table-bordered"
filterBy={this.state.searchText}
filterable={results.columns}
hideFilterInput
/>
</div>
</div>
);
}
return (<Alert bsStyle="warning">The query returned no data</Alert>);
}
}
ResultSet.propTypes = {
query: React.PropTypes.object,
showControls: React.PropTypes.bool,
search: React.PropTypes.bool,
searchText: React.PropTypes.string,
};
ResultSet.defaultProps = {
showControls: true,
search: true,
searchText: '',
};
export default ResultSet;
@@ -0,0 +1,85 @@
import { Alert, Button, Tab, Tabs } from 'react-bootstrap';
import QueryHistory from './QueryHistory';
import ResultSet from './ResultSet';
import React from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import * as Actions from '../actions';
import shortid from 'shortid';
class SouthPane extends React.Component {
popSelectStar() {
const qe = {
id: shortid.generate(),
title: this.props.latestQuery.tempTable,
autorun: false,
dbId: this.props.latestQuery.dbId,
sql: `SELECT * FROM ${this.props.latestQuery.tempTable}`,
};
this.props.actions.addQueryEditor(qe);
}
render() {
let results = <div />;
const latestQuery = this.props.latestQuery;
if (latestQuery) {
if (['running', 'pending'].includes(latestQuery.state)) {
results = (
<img className="loading" alt="Loading.." src="/static/assets/images/loading.gif" />
);
} else if (latestQuery.state === 'failed') {
results = <Alert bsStyle="danger">{latestQuery.errorMessage}</Alert>;
} else if (latestQuery.state === 'success' && latestQuery.ctas) {
results = (
<div>
<Alert bsStyle="info">
Table [<strong>{latestQuery.tempTable}</strong>] was created
</Alert>
<p>
<Button
bsSize="small"
className="m-r-5"
onClick={this.popSelectStar.bind(this)}
>
Query in a new tab
</Button>
<Button bsSize="small">Visualize</Button>
</p>
</div>);
} else if (latestQuery.state === 'success') {
results = <ResultSet showControls search query={latestQuery} />;
}
} else {
results = <Alert bsStyle="info">Run a query to display results here</Alert>;
}
return (
<div className="SouthPane">
<Tabs bsStyle="tabs" id={shortid.generate()}>
<Tab title="Results" eventKey={1}>
<div style={{ overflow: 'auto' }}>
{results}
</div>
</Tab>
<Tab title="Query History" eventKey={2}>
<QueryHistory />
</Tab>
</Tabs>
</div>
);
}
}
SouthPane.propTypes = {
latestQuery: React.PropTypes.object,
actions: React.PropTypes.object,
};
SouthPane.defaultProps = {
};
function mapDispatchToProps(dispatch) {
return {
actions: bindActionCreators(Actions, dispatch),
};
}
export default connect(null, mapDispatchToProps)(SouthPane);
@@ -0,0 +1,301 @@
const $ = require('jquery');
import { now } from '../../modules/dates';
import React from 'react';
import {
Button,
ButtonGroup,
Col,
FormGroup,
InputGroup,
Form,
FormControl,
Label,
OverlayTrigger,
Row,
Tooltip,
} from 'react-bootstrap';
import AceEditor from 'react-ace';
import 'brace/mode/sql';
import 'brace/theme/github';
import 'brace/ext/language_tools';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import * as Actions from '../actions';
import shortid from 'shortid';
import SouthPane from './SouthPane';
import Timer from './Timer';
import SqlEditorLeftBar from './SqlEditorLeftBar';
class SqlEditor extends React.Component {
constructor(props) {
super(props);
this.state = {
autorun: props.queryEditor.autorun,
sql: props.queryEditor.sql,
ctas: '',
};
}
componentDidMount() {
this.onMount();
}
onMount() {
if (this.state.autorun) {
this.setState({ autorun: false });
this.props.actions.queryEditorSetAutorun(this.props.queryEditor, false);
this.startQuery();
}
}
runQuery(runAsync = false) {
this.startQuery(runAsync);
}
startQuery(runAsync = false, ctas = false) {
const that = this;
const query = {
dbId: this.props.queryEditor.dbId,
id: shortid.generate(),
progress: 0,
sql: this.props.queryEditor.sql,
sqlEditorId: this.props.queryEditor.id,
startDttm: now(),
state: 'running',
tab: this.props.queryEditor.title,
};
if (runAsync) {
query.state = 'pending';
}
// Execute the Query
that.props.actions.startQuery(query);
const sqlJsonUrl = '/caravel/sql_json/';
const sqlJsonRequest = {
client_id: query.id,
database_id: this.props.queryEditor.dbId,
json: true,
runAsync,
schema: this.props.queryEditor.schema,
select_as_cta: ctas,
sql: this.props.queryEditor.sql,
sql_editor_id: this.props.queryEditor.id,
tab: this.props.queryEditor.title,
tmp_table_name: this.state.ctas,
};
$.ajax({
type: 'POST',
dataType: 'json',
url: sqlJsonUrl,
data: sqlJsonRequest,
success(results) {
if (!runAsync) {
that.props.actions.querySuccess(query, results);
}
},
error(err, textStatus, errorThrown) {
let msg;
try {
msg = err.responseJSON.error;
} catch (e) {
if (err.responseText !== undefined) {
msg = err.responseText;
}
}
if (textStatus === 'error' && errorThrown === '') {
msg = 'Could not connect to server';
} else if (msg === null) {
msg = `[${textStatus}] ${errorThrown}`;
}
that.props.actions.queryFailed(query, msg);
},
});
}
stopQuery() {
this.props.actions.stopQuery(this.props.latestQuery);
}
createTableAs() {
this.startQuery(true, true);
}
textChange(text) {
this.setState({ sql: text });
this.props.actions.queryEditorSetSql(this.props.queryEditor, text);
}
addWorkspaceQuery() {
this.props.actions.addWorkspaceQuery({
id: shortid.generate(),
sql: this.state.sql,
dbId: this.props.queryEditor.dbId,
schema: this.props.queryEditor.schema,
title: this.props.queryEditor.title,
});
}
ctasChange() {}
visualize() {}
ctasChanged(event) {
this.setState({ ctas: event.target.value });
}
sqlEditorHeight() {
// quick hack to make the white bg of the tab stretch full height.
const tabNavHeight = 40;
const navBarHeight = 56;
const mysteryVerticalHeight = 50;
return window.innerHeight - tabNavHeight - navBarHeight - mysteryVerticalHeight;
}
render() {
let runButtons = [];
if (this.props.database && this.props.database.allow_run_sync) {
runButtons.push(
<Button
bsSize="small"
bsStyle="primary"
style={{ width: '100px' }}
onClick={this.runQuery.bind(this, false)}
disabled={!(this.props.queryEditor.dbId)}
key={shortid.generate()}
>
<i className="fa fa-table" /> Run Query
</Button>
);
}
if (this.props.database && this.props.database.allow_run_async) {
runButtons.push(
<Button
bsSize="small"
bsStyle="primary"
style={{ width: '100px' }}
onClick={this.runQuery.bind(this, true)}
disabled={!(this.props.queryEditor.dbId)}
key={shortid.generate()}
>
<i className="fa fa-table" /> Run Async
</Button>
);
}
runButtons = (
<ButtonGroup bsSize="small" className="inline m-r-5 pull-left">
{runButtons}
</ButtonGroup>
);
if (this.props.latestQuery && this.props.latestQuery.state === 'running') {
runButtons = (
<ButtonGroup bsSize="small" className="inline m-r-5 pull-left">
<Button
bsStyle="primary"
bsSize="small"
style={{ width: '100px' }}
onClick={this.stopQuery.bind(this)}
>
<a className="fa fa-stop" /> Stop
</Button>
</ButtonGroup>
);
}
let limitWarning = null;
if (this.props.latestQuery && this.props.latestQuery.limit_reached) {
const tooltip = (
<Tooltip id="tooltip">
It appears that the number of rows in the query results displayed
was limited on the server side to
the {this.props.latestQuery.rows} limit.
</Tooltip>
);
limitWarning = (
<OverlayTrigger placement="left" overlay={tooltip}>
<Label bsStyle="warning" className="m-r-5">LIMIT</Label>
</OverlayTrigger>
);
}
let ctasControls;
if (this.props.database && this.props.database.allow_ctas) {
ctasControls = (
<FormGroup>
<InputGroup>
<FormControl
type="text"
bsSize="small"
className="input-sm"
placeholder="new table name"
onChange={this.ctasChanged.bind(this)}
/>
<InputGroup.Button>
<Button
bsSize="small"
disabled={this.state.ctas.length === 0}
onClick={this.createTableAs.bind(this)}
>
<i className="fa fa-table" /> CTAS
</Button>
</InputGroup.Button>
</InputGroup>
</FormGroup>
);
}
const editorBottomBar = (
<div className="sql-toolbar clearfix">
<div className="pull-left">
<Form inline>
{runButtons}
{ctasControls}
</Form>
</div>
<div className="pull-right">
{limitWarning}
<Timer query={this.props.latestQuery} />
</div>
</div>
);
return (
<div className="SqlEditor" style={{ minHeight: this.sqlEditorHeight() }}>
<Row>
<Col md={3}>
<SqlEditorLeftBar queryEditor={this.props.queryEditor} />
</Col>
<Col md={9}>
<AceEditor
mode="sql"
name={this.props.queryEditor.id}
theme="github"
minLines={7}
maxLines={30}
onChange={this.textChange.bind(this)}
height="200px"
width="100%"
editorProps={{ $blockScrolling: true }}
enableBasicAutocompletion
value={this.props.queryEditor.sql}
/>
{editorBottomBar}
<br />
<SouthPane latestQuery={this.props.latestQuery} sqlEditor={this} />
</Col>
</Row>
</div>
);
}
}
SqlEditor.propTypes = {
actions: React.PropTypes.object,
database: React.PropTypes.object,
latestQuery: React.PropTypes.object,
queryEditor: React.PropTypes.object,
};
SqlEditor.defaultProps = {
};
function mapStateToProps() {
return {};
}
function mapDispatchToProps(dispatch) {
return {
actions: bindActionCreators(Actions, dispatch),
};
}
export default connect(mapStateToProps, mapDispatchToProps)(SqlEditor);
@@ -0,0 +1,195 @@
const $ = window.$ = require('jquery');
import React from 'react';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import * as Actions from '../actions';
import Select from 'react-select';
import { Label, Button } from 'react-bootstrap';
import TableElement from './TableElement';
import DatabaseSelect from './DatabaseSelect';
class SqlEditorLeftBar extends React.Component {
constructor(props) {
super(props);
this.state = {
schemaLoading: false,
schemaOptions: [],
tableLoading: false,
tableOptions: [],
};
}
componentWillMount() {
this.fetchSchemas();
this.fetchTables();
}
onChange(db) {
const val = (db) ? db.value : null;
this.setState({ schemaOptions: [] });
this.props.actions.queryEditorSetDb(this.props.queryEditor, val);
if (!(db)) {
this.setState({ tableOptions: [] });
} else {
this.fetchTables(val, this.props.queryEditor.schema);
this.fetchSchemas(val);
}
}
resetState() {
this.props.actions.resetState();
}
fetchTables(dbId, schema) {
const actualDbId = dbId || this.props.queryEditor.dbId;
if (actualDbId) {
const actualSchema = schema || this.props.queryEditor.schema;
this.setState({ tableLoading: true });
this.setState({ tableOptions: [] });
const url = `/caravel/tables/${actualDbId}/${actualSchema}`;
$.get(url, (data) => {
let tableOptions = data.tables.map((s) => ({ value: s, label: s }));
const views = data.views.map((s) => ({ value: s, label: '[view] ' + s }));
tableOptions = [...tableOptions, ...views];
this.setState({ tableOptions });
this.setState({ tableLoading: false });
});
}
}
changeSchema(schemaOpt) {
const schema = (schemaOpt) ? schemaOpt.value : null;
this.props.actions.queryEditorSetSchema(this.props.queryEditor, schema);
this.fetchTables(this.props.queryEditor.dbId, schema);
}
fetchSchemas(dbId) {
const actualDbId = dbId || this.props.queryEditor.dbId;
if (actualDbId) {
this.setState({ schemaLoading: true });
const url = `/databasetablesasync/api/read?_flt_0_id=${actualDbId}`;
$.get(url, (data) => {
const schemas = data.result[0].all_schema_names;
const schemaOptions = schemas.map((s) => ({ value: s, label: s }));
this.setState({ schemaOptions });
this.setState({ schemaLoading: false });
});
}
}
closePopover(ref) {
this.refs[ref].hide();
}
changeTable(tableOpt) {
const tableName = tableOpt.value;
const qe = this.props.queryEditor;
let url = `/caravel/table/${qe.dbId}/${tableName}/${qe.schema}/`;
this.setState({ tableLoading: true });
$.get(url, (data) => {
this.props.actions.mergeTable({
dbId: this.props.queryEditor.dbId,
queryEditorId: this.props.queryEditor.id,
name: data.name,
indexes: data.indexes,
schema: qe.schema,
columns: data.columns,
expanded: true,
});
this.setState({ tableLoading: false });
})
.fail(() => {
this.props.actions.addAlert({
msg: 'Error occurred while fetching metadata',
bsStyle: 'danger',
});
this.setState({ tableLoading: false });
});
url = `/caravel/extra_table_metadata/${qe.dbId}/${tableName}/${qe.schema}/`;
$.get(url, (data) => {
const table = {
dbId: this.props.queryEditor.dbId,
queryEditorId: this.props.queryEditor.id,
schema: qe.schema,
name: tableName,
};
Object.assign(table, data);
this.props.actions.mergeTable(table);
});
}
render() {
let networkAlert = null;
if (!this.props.networkOn) {
networkAlert = <p><Label bsStyle="danger">OFFLINE</Label></p>;
}
const tables = this.props.tables.filter((t) => (t.queryEditorId === this.props.queryEditor.id));
const shouldShowReset = window.location.search === '?reset=1';
return (
<div className="clearfix sql-toolbar">
{networkAlert}
<div>
<DatabaseSelect
onChange={this.onChange.bind(this)}
databaseId={this.props.queryEditor.dbId}
/>
</div>
<div className="m-t-5">
<Select
name="select-schema"
placeholder={`Select a schema (${this.state.schemaOptions.length})`}
options={this.state.schemaOptions}
value={this.props.queryEditor.schema}
isLoading={this.state.schemaLoading}
autosize={false}
onChange={this.changeSchema.bind(this)}
/>
</div>
<div className="m-t-5">
<Select
name="select-table"
ref="selectTable"
isLoading={this.state.tableLoading}
placeholder={`Add a table (${this.state.tableOptions.length})`}
autosize={false}
value={this.state.tableName}
onChange={this.changeTable.bind(this)}
options={this.state.tableOptions}
/>
</div>
<hr />
<div className="m-t-5">
{tables.map((table) => (
<TableElement table={table} queryEditor={this.props.queryEditor} key={table.id} />
))}
</div>
{shouldShowReset &&
<Button bsSize="small" bsStyle="danger" onClick={this.resetState.bind(this)}>
<i className="fa fa-bomb" /> Reset State
</Button>
}
</div>
);
}
}
SqlEditorLeftBar.propTypes = {
queryEditor: React.PropTypes.object,
tables: React.PropTypes.array,
actions: React.PropTypes.object,
networkOn: React.PropTypes.bool,
};
SqlEditorLeftBar.defaultProps = {
tables: [],
};
function mapStateToProps(state) {
return {
tables: state.tables,
networkOn: state.networkOn,
};
}
function mapDispatchToProps(dispatch) {
return {
actions: bindActionCreators(Actions, dispatch),
};
}
export default connect(mapStateToProps, mapDispatchToProps)(SqlEditorLeftBar);
@@ -0,0 +1,39 @@
import React from 'react';
import SyntaxHighlighter from 'react-syntax-highlighter';
import { github } from 'react-syntax-highlighter/dist/styles';
const SqlShrink = (props) => {
const sql = props.sql || '';
let lines = sql.split('\n');
if (lines.length >= props.maxLines) {
lines = lines.slice(0, props.maxLines);
lines.push('{...}');
}
const shrunk = lines.map((line) => {
if (line.length > props.maxWidth) {
return line.slice(0, props.maxWidth) + '{...}';
}
return line;
})
.join('\n');
return (
<div>
<SyntaxHighlighter language="sql" style={github}>
{shrunk}
</SyntaxHighlighter>
</div>
);
};
SqlShrink.defaultProps = {
maxWidth: 60,
maxLines: 6,
};
SqlShrink.propTypes = {
sql: React.PropTypes.string,
maxWidth: React.PropTypes.number,
maxLines: React.PropTypes.number,
};
export default SqlShrink;
@@ -0,0 +1,170 @@
import React from 'react';
import { DropdownButton, MenuItem, Tab, Tabs } from 'react-bootstrap';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import * as Actions from '../actions';
import SqlEditor from './SqlEditor';
import shortid from 'shortid';
import { getParamFromQuery, getLink } from '../../../utils/common';
import CopyQueryTabUrl from './CopyQueryTabUrl';
let queryCount = 1;
class TabbedSqlEditors extends React.Component {
constructor(props) {
super(props);
const uri = window.location.toString();
const search = window.location.search;
const cleanUri = search ? uri.substring(0, uri.indexOf('?')) : uri;
const query = search.substring(1);
this.state = {
uri,
cleanUri,
query,
};
}
componentWillMount() {
if (this.state.query) {
queryCount++;
const queryEditorProps = {
id: shortid.generate(),
title: getParamFromQuery(this.state.query, 'title'),
dbId: getParamFromQuery(this.state.query, 'dbid'),
schema: getParamFromQuery(this.state.query, 'schema'),
autorun: getParamFromQuery(this.state.query, 'autorun'),
sql: getParamFromQuery(this.state.query, 'sql'),
};
this.props.actions.addQueryEditor(queryEditorProps);
// Clean the url in browser history
window.history.replaceState({}, document.title, this.state.cleanUri);
}
}
getQueryLink(qe) {
const params = [];
if (qe.dbId) params.push('dbid=' + qe.dbId);
if (qe.title) params.push('title=' + qe.title);
if (qe.schema) params.push('schema=' + qe.schema);
if (qe.autorun) params.push('autorun=' + qe.autorun);
if (qe.sql) params.push('sql=' + qe.sql);
return getLink(this.state.cleanUri, params);
}
renameTab(qe) {
/* eslint no-alert: 0 */
const newTitle = prompt('Enter a new title for the tab');
if (newTitle) {
this.props.actions.queryEditorSetTitle(qe, newTitle);
}
}
activeQueryEditor() {
const qeid = this.props.tabHistory[this.props.tabHistory.length - 1];
for (let i = 0; i < this.props.queryEditors.length; i++) {
const qe = this.props.queryEditors[i];
if (qe.id === qeid) {
return qe;
}
}
return null;
}
newQueryEditor() {
queryCount++;
const activeQueryEditor = this.activeQueryEditor();
const qe = {
id: shortid.generate(),
title: `Untitled Query ${queryCount}`,
dbId: (activeQueryEditor) ? activeQueryEditor.dbId : null,
schema: (activeQueryEditor) ? activeQueryEditor.schema : null,
autorun: false,
sql: 'SELECT ...',
};
this.props.actions.addQueryEditor(qe);
}
handleSelect(key) {
if (key === 'add_tab') {
this.newQueryEditor();
} else {
this.props.actions.setActiveQueryEditor({ id: key });
}
}
render() {
const editors = this.props.queryEditors.map((qe, i) => {
let latestQuery = this.props.queries[qe.latestQueryId];
const database = this.props.databases[qe.dbId];
const state = (latestQuery) ? latestQuery.state : '';
const tabTitle = (
<div>
<div className={'circle ' + state} /> {qe.title} {' '}
<DropdownButton
bsSize="small"
id={'ddbtn-tab-' + i}
title=""
>
<MenuItem eventKey="1" onClick={this.props.actions.removeQueryEditor.bind(this, qe)}>
<i className="fa fa-close" /> close tab
</MenuItem>
<MenuItem eventKey="2" onClick={this.renameTab.bind(this, qe)}>
<i className="fa fa-i-cursor" /> rename tab
</MenuItem>
<MenuItem eventKey="3">
<i className="fa fa-clipboard" /> <CopyQueryTabUrl qe={qe} />
</MenuItem>
</DropdownButton>
</div>
);
return (
<Tab
key={qe.id}
title={tabTitle}
eventKey={qe.id}
>
<div className="panel panel-default">
<div className="panel-body">
<SqlEditor
queryEditor={qe}
latestQuery={latestQuery}
database={database}
/>
</div>
</div>
</Tab>);
});
return (
<Tabs
bsStyle="tabs"
activeKey={this.props.tabHistory[this.props.tabHistory.length - 1]}
onSelect={this.handleSelect.bind(this)}
id="a11y-query-editor-tabs"
>
{editors}
<Tab title={<div><i className="fa fa-plus-circle" />&nbsp;</div>} eventKey="add_tab" />
</Tabs>
);
}
}
TabbedSqlEditors.propTypes = {
actions: React.PropTypes.object,
databases: React.PropTypes.object,
queries: React.PropTypes.object,
queryEditors: React.PropTypes.array,
tabHistory: React.PropTypes.array,
};
TabbedSqlEditors.defaultProps = {
tabHistory: [],
queryEditors: [],
};
function mapStateToProps(state) {
return {
databases: state.databases,
queryEditors: state.queryEditors,
queries: state.queries,
tabHistory: state.tabHistory,
};
}
function mapDispatchToProps(dispatch) {
return {
actions: bindActionCreators(Actions, dispatch),
};
}
export default connect(mapStateToProps, mapDispatchToProps)(TabbedSqlEditors);
@@ -0,0 +1,214 @@
import React from 'react';
import { ButtonGroup, Well } from 'react-bootstrap';
import Link from './Link';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import * as Actions from '../actions';
import shortid from 'shortid';
import ModalTrigger from '../../components/ModalTrigger';
import CopyToClipboard from '../../components/CopyToClipboard';
const propTypes = {
table: React.PropTypes.object,
queryEditor: React.PropTypes.object,
actions: React.PropTypes.object,
};
const defaultProps = {
table: null,
actions: {},
};
class TableElement extends React.Component {
setSelectStar() {
this.props.actions.queryEditorSetSql(this.props.queryEditor, this.selectStar());
}
selectStar() {
let cols = '';
this.props.table.columns.forEach((col, i) => {
cols += col.name;
if (i < this.props.table.columns.length - 1) {
cols += ', ';
}
});
let tableName = this.props.table.name;
if (this.props.table.schema) {
tableName = this.props.table.schema + '.' + tableName;
}
return `SELECT ${cols}\nFROM ${tableName}`;
}
popSelectStar() {
const qe = {
id: shortid.generate(),
title: this.props.table.name,
dbId: this.props.table.dbId,
autorun: true,
sql: this.selectStar(),
};
this.props.actions.addQueryEditor(qe);
}
collapseTable(e) {
e.preventDefault();
this.props.actions.collapseTable(this.props.table);
}
expandTable(e) {
e.preventDefault();
this.props.actions.expandTable(this.props.table);
}
removeTable() {
this.props.actions.removeTable(this.props.table);
}
render() {
const table = this.props.table;
let metadata = null;
let buttonToggle;
let header;
if (table.partitions) {
let partitionQuery;
let partitionClipBoard;
if (table.partitions.partitionQuery) {
partitionQuery = table.partitions.partitionQuery;
const tt = 'Copy partition query to clipboard';
partitionClipBoard = (
<CopyToClipboard
text={partitionQuery}
shouldShowText={false}
tooltipText={tt}
copyNode={<i className="fa fa-clipboard" />}
/>
);
}
let latest = [];
for (const k in table.partitions.latest) {
latest.push(`${k}=${table.partitions.latest[k]}`);
}
latest = latest.join('/');
header = (
<Well bsSize="small">
<div>
<small>
latest partition: {latest}
</small> {partitionClipBoard}
</div>
</Well>
);
}
if (table.expanded) {
buttonToggle = (
<a
href="#"
onClick={(e) => { this.collapseTable(e); }}
>
<strong>{table.name}</strong>
<small className="m-l-5"><i className="fa fa-minus" /></small>
</a>
);
metadata = (
<div>
{header}
<div className="table-columns">
{table.columns.map((col) => {
let name = col.name;
if (col.indexed) {
name = <strong>{col.name}</strong>;
}
return (
<div className="clearfix table-column" key={shortid.generate()}>
<div className="pull-left m-l-10">
{name}
</div>
<div className="pull-right text-muted">
<small> {col.type}</small>
</div>
</div>);
})}
<hr />
</div>
</div>
);
} else {
buttonToggle = (
<a
href="#"
onClick={(e) => { this.expandTable(e); }}
>
{table.name}
<small className="m-l-5"><i className="fa fa-plus" /></small>
</a>
);
}
let keyLink;
if (table.indexes && table.indexes.length > 0) {
keyLink = (
<ModalTrigger
modalTitle={
<div>
Keys for table <strong>{table.name}</strong>
</div>
}
modalBody={
<pre>{JSON.stringify(table.indexes, null, 4)}</pre>
}
triggerNode={
<Link
className="fa fa-key pull-left m-l-2"
tooltip={`View indexes (${table.indexes.length})`}
/>
}
/>
);
}
return (
<div className="TableElement">
<div className="clearfix">
<div className="pull-left">
{buttonToggle}
</div>
<div className="pull-right">
<ButtonGroup className="ws-el-controls pull-right">
{keyLink}
<Link
className="fa fa-pencil pull-left m-l-2"
onClick={this.setSelectStar.bind(this)}
tooltip="Run query in this tab"
href="#"
/>
<Link
className="fa fa-plus-circle pull-left m-l-2"
onClick={this.popSelectStar.bind(this)}
tooltip="Run query in a new tab"
href="#"
/>
<Link
className="fa fa-trash pull-left m-l-2"
onClick={this.removeTable.bind(this)}
tooltip="Remove from workspace"
href="#"
/>
</ButtonGroup>
</div>
</div>
<div>
{metadata}
</div>
</div>
);
}
}
TableElement.propTypes = propTypes;
TableElement.defaultProps = defaultProps;
function mapDispatchToProps(dispatch) {
return {
actions: bindActionCreators(Actions, dispatch),
};
}
export default connect(null, mapDispatchToProps)(TableElement);
export { TableElement };
@@ -0,0 +1,23 @@
import React from 'react';
import { BootstrapTable, TableHeaderColumn } from 'react-bootstrap-table';
const TableMetadata = function (props) {
return (
<BootstrapTable
condensed
data={props.table.columns}
>
<TableHeaderColumn dataField="id" isKey hidden>
id
</TableHeaderColumn>
<TableHeaderColumn dataField="name">Name</TableHeaderColumn>
<TableHeaderColumn dataField="type">Type</TableHeaderColumn>
</BootstrapTable>
);
};
TableMetadata.propTypes = {
table: React.PropTypes.object,
};
export default TableMetadata;

Some files were not shown because too many files have changed in this diff Show More