Compare commits
847 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bfc6b1cca9 | ||
|
|
62fcdf2a92 | ||
|
|
48821b5101 | ||
|
|
3b129253a3 | ||
|
|
48760849ec | ||
|
|
9c1ca07c40 | ||
|
|
774ad45efb | ||
|
|
299e9ce6b8 | ||
|
|
219f33f0d1 | ||
|
|
58a704b84c | ||
|
|
b58cfbcb91 | ||
|
|
1e325d9645 | ||
|
|
ad5a4389a2 | ||
|
|
e4fba0ffb7 | ||
|
|
e584a9673f | ||
|
|
b888802e05 | ||
|
|
25c599d040 | ||
|
|
fb866a937b | ||
|
|
aa95e03eb9 | ||
|
|
cf1d0f38ad | ||
|
|
fca982c609 | ||
|
|
747bf80474 | ||
|
|
4f7fd65c8b | ||
|
|
6045063e78 | ||
|
|
0ec9cd4ad2 | ||
|
|
4268513653 | ||
|
|
7654eef110 | ||
|
|
b301ba1f57 | ||
|
|
95509f2000 | ||
|
|
49ab09101b | ||
|
|
40d9e15126 | ||
|
|
a141695b2b | ||
|
|
d01e67a159 | ||
|
|
c34df3eea4 | ||
|
|
56bcbb0f8e | ||
|
|
51f1aa3106 | ||
|
|
d7e419127c | ||
|
|
27fab0d54f | ||
|
|
091e93c831 | ||
|
|
bb6b2da267 | ||
|
|
7abe2d5eee | ||
|
|
7b015faae9 | ||
|
|
e834154030 | ||
|
|
256a521bf1 | ||
|
|
a626f994bf | ||
|
|
76dda688b1 | ||
|
|
163a6a20e5 | ||
|
|
3d136aa0a4 | ||
|
|
ff3057de5d | ||
|
|
7045018d86 | ||
|
|
a55f963e52 | ||
|
|
8dfe2b70b2 | ||
|
|
fdbb569c3e | ||
|
|
cc3e63f1de | ||
|
|
a48e246aa0 | ||
|
|
6eba6cac0b | ||
|
|
bd706ebbd1 | ||
|
|
abbf138cfb | ||
|
|
de346a3eba | ||
|
|
99e1de58bc | ||
|
|
5344a80535 | ||
|
|
0b09a74d37 | ||
|
|
e21745ac9d | ||
|
|
593861eac6 | ||
|
|
53dead9c29 | ||
|
|
f64e2ba7d5 | ||
|
|
80515d2a92 | ||
|
|
4d72afb54b | ||
|
|
06fcaa3095 | ||
|
|
de88764e93 | ||
|
|
9051e1f3e2 | ||
|
|
ba93e6a2d1 | ||
|
|
7e5e229f48 | ||
|
|
b9915e7ecf | ||
|
|
3e51c61dbf | ||
|
|
591e512327 | ||
|
|
fc5db474b7 | ||
|
|
c083aec8e8 | ||
|
|
1ce3b81d01 | ||
|
|
89cd10b3ce | ||
|
|
712297480c | ||
|
|
6ddccaaa9b | ||
|
|
1dcf2c4326 | ||
|
|
f0a8ea644b | ||
|
|
fb6ef26a24 | ||
|
|
00b34d7fbd | ||
|
|
8329ea2b9b | ||
|
|
da0a87a735 | ||
|
|
7aeca39c46 | ||
|
|
e1751c065c | ||
|
|
e5151cb915 | ||
|
|
24e3c7f89a | ||
|
|
987cb9978d | ||
|
|
274d21795f | ||
|
|
0d2c2b0681 | ||
|
|
1eff48facb | ||
|
|
17bd7512ff | ||
|
|
16141ecb94 | ||
|
|
34f381bc25 | ||
|
|
24292dbc11 | ||
|
|
24a2f5b8f0 | ||
|
|
0e6f754af9 | ||
|
|
fb85f008fa | ||
|
|
85fb4a933d | ||
|
|
d3ace6d63f | ||
|
|
205eed8350 | ||
|
|
5bf40e2256 | ||
|
|
7c28e4eace | ||
|
|
a882f7a55f | ||
|
|
9aba77db74 | ||
|
|
c9e5fbb09b | ||
|
|
65f25a1e5a | ||
|
|
e0dd5d9d1d | ||
|
|
737db25b6e | ||
|
|
bea702269c | ||
|
|
d78da8a9bf | ||
|
|
ed8153ff8b | ||
|
|
f7ce100180 | ||
|
|
72291d65c9 | ||
|
|
0d3f57a78d | ||
|
|
04fb0e2c2d | ||
|
|
155fec0a6b | ||
|
|
d90044cd52 | ||
|
|
62bd4eb211 | ||
|
|
677c427b16 | ||
|
|
52b0716571 | ||
|
|
04b662ea11 | ||
|
|
db052b17ea | ||
|
|
e300273e71 | ||
|
|
c5f2eafc90 | ||
|
|
90e4d6469d | ||
|
|
1e7773eb16 | ||
|
|
3c89c8cc46 | ||
|
|
74086dae2b | ||
|
|
66403f1876 | ||
|
|
3a4cd3ae24 | ||
|
|
4ffc1f613e | ||
|
|
dfbba84400 | ||
|
|
77864e6cf4 | ||
|
|
4d12251806 | ||
|
|
0c9f9b695b | ||
|
|
a4a2bf7ae9 | ||
|
|
d0a04cde49 | ||
|
|
69685b9dcc | ||
|
|
b308a3eb4e | ||
|
|
bfa40bd360 | ||
|
|
b0e2904c24 | ||
|
|
ce506bdf65 | ||
|
|
922cc037bf | ||
|
|
8252ada1f9 | ||
|
|
a2d2f8bb8c | ||
|
|
7c5f61d6a6 | ||
|
|
841e18a08c | ||
|
|
dbc7fef7f5 | ||
|
|
cbfe3cb2dc | ||
|
|
5fcd25def1 | ||
|
|
fe3f5f69ae | ||
|
|
2395fbbdaa | ||
|
|
960b26c7a2 | ||
|
|
28ac3504d6 | ||
|
|
ecc00bdd26 | ||
|
|
e7946451d6 | ||
|
|
9b34600c8e | ||
|
|
884610861b | ||
|
|
d9bd3d6460 | ||
|
|
38375be5c3 | ||
|
|
91d951ac42 | ||
|
|
d79a45ff32 | ||
|
|
818251fc85 | ||
|
|
75abd1f44a | ||
|
|
f55df3b18b | ||
|
|
5dbfdefae8 | ||
|
|
e5584440ce | ||
|
|
d5e9d5d045 | ||
|
|
3208a014ff | ||
|
|
874c12ad2d | ||
|
|
22d8075c53 | ||
|
|
baebba1159 | ||
|
|
04748b4cda | ||
|
|
a471afe206 | ||
|
|
5d0a01d0d0 | ||
|
|
9e1272e97c | ||
|
|
aeebd8840d | ||
|
|
55d3b012e5 | ||
|
|
a6e1e18244 | ||
|
|
46d7a925bb | ||
|
|
5929ab7689 | ||
|
|
fffb7b500a | ||
|
|
cb14640a82 | ||
|
|
d65054e015 | ||
|
|
5d5060eca6 | ||
|
|
9ff351532a | ||
|
|
59a6f447ec | ||
|
|
1887b5e934 | ||
|
|
33758bfff5 | ||
|
|
2d5beb1f91 | ||
|
|
5fd0e7d028 | ||
|
|
ef0c4be067 | ||
|
|
ac3aba7c7d | ||
|
|
0fdb57a181 | ||
|
|
3e7b5df287 | ||
|
|
3cd16cf368 | ||
|
|
a58adc862e | ||
|
|
7d88f80a9b | ||
|
|
09be02f70a | ||
|
|
50fcdd3a34 | ||
|
|
dee36491c5 | ||
|
|
903612ac6c | ||
|
|
ce705054fa | ||
|
|
c589616883 | ||
|
|
58309f275f | ||
|
|
edf4e4f24e | ||
|
|
b3e0b5b586 | ||
|
|
68802989bc | ||
|
|
70887d72e2 | ||
|
|
1922225042 | ||
|
|
0bdc3010d8 | ||
|
|
1df37e6e4d | ||
|
|
e9ed416654 | ||
|
|
03c42b5b87 | ||
|
|
e055e6d2c2 | ||
|
|
29780821e8 | ||
|
|
f10ee13901 | ||
|
|
cdfc4a35b2 | ||
|
|
eb762c8bfe | ||
|
|
83abfef830 | ||
|
|
54137ad023 | ||
|
|
4be6bfafaa | ||
|
|
9ba6d489f3 | ||
|
|
af4bd40853 | ||
|
|
84fa0d1940 | ||
|
|
938e13a429 | ||
|
|
dc364daffd | ||
|
|
1cadfecd4b | ||
|
|
5b26667fd5 | ||
|
|
899caf9449 | ||
|
|
e6063f2ddf | ||
|
|
46486f82d9 | ||
|
|
0089762955 | ||
|
|
2bd60c0747 | ||
|
|
db6cd21504 | ||
|
|
f40499e550 | ||
|
|
67a85b9831 | ||
|
|
cb3384b3b2 | ||
|
|
ac51a30f98 | ||
|
|
91fe02cdc8 | ||
|
|
76042be7c3 | ||
|
|
d3f55a0905 | ||
|
|
efaef8fe09 | ||
|
|
8757a24d89 | ||
|
|
63785f039c | ||
|
|
d6689ee700 | ||
|
|
787daf6005 | ||
|
|
23aeee5a9c | ||
|
|
70c6cad0e3 | ||
|
|
6b1bf3b395 | ||
|
|
f5216f6047 | ||
|
|
15654a3082 | ||
|
|
baff0cba38 | ||
|
|
c4ee098bb7 | ||
|
|
612b8ca3d7 | ||
|
|
c43a9fd554 | ||
|
|
6c68a21e4f | ||
|
|
db02b33e09 | ||
|
|
2df6baa7a7 | ||
|
|
fc7bd63039 | ||
|
|
959a09cc92 | ||
|
|
366ecefbaa | ||
|
|
a2b30f35fc | ||
|
|
8bceda8134 | ||
|
|
bae1067015 | ||
|
|
116dca3e6f | ||
|
|
b448394077 | ||
|
|
09f407f553 | ||
|
|
0479118efc | ||
|
|
c93411b1e7 | ||
|
|
31283f1424 | ||
|
|
93c6597cf4 | ||
|
|
4446c745a8 | ||
|
|
38e90fe309 | ||
|
|
f5489467e5 | ||
|
|
ab0bc5a3fa | ||
|
|
412634cb57 | ||
|
|
a0ddbb9ec9 | ||
|
|
a803705ddc | ||
|
|
75a358c616 | ||
|
|
493ba18362 | ||
|
|
5e4fca4ea4 | ||
|
|
d289783b67 | ||
|
|
ac84fc2b65 | ||
|
|
40b3d3b3ef | ||
|
|
50a9e13f9b | ||
|
|
66bff01b45 | ||
|
|
9691234b7e | ||
|
|
ddeabdd048 | ||
|
|
3ed45ab98c | ||
|
|
ca08e7051e | ||
|
|
1fb21b8b45 | ||
|
|
c581ea8661 | ||
|
|
f19d1958c5 | ||
|
|
9c99be510b | ||
|
|
7a08cdcb1c | ||
|
|
f24ddfd467 | ||
|
|
23a8ea5636 | ||
|
|
2c04d3c250 | ||
|
|
337454b646 | ||
|
|
b7f46ebe75 | ||
|
|
10773f96a7 | ||
|
|
b97a8275d4 | ||
|
|
081bdca71e | ||
|
|
62959ca38b | ||
|
|
fe68bc31c3 | ||
|
|
3d2c791ff1 | ||
|
|
d40ce52139 | ||
|
|
122891c29b | ||
|
|
c1d9918abe | ||
|
|
d93b1fc686 | ||
|
|
02c5cac26f | ||
|
|
6566377740 | ||
|
|
db6b2f3ae1 | ||
|
|
c31210b96d | ||
|
|
dcc6f2a18f | ||
|
|
0c0666caa0 | ||
|
|
243eeadfd6 | ||
|
|
9ba5b49d8a | ||
|
|
c870bd414e | ||
|
|
4b01e92509 | ||
|
|
513a090cdc | ||
|
|
abe79d1427 | ||
|
|
b81968dc20 | ||
|
|
66cc546a30 | ||
|
|
6e899ac55f | ||
|
|
6b52384024 | ||
|
|
0a1d8db357 | ||
|
|
6f68ddb505 | ||
|
|
4f59abf189 | ||
|
|
5c441f4ddb | ||
|
|
be023aba8d | ||
|
|
53990201bc | ||
|
|
37783d685f | ||
|
|
25fdcaca8b | ||
|
|
ce6e7c1359 | ||
|
|
91167665b1 | ||
|
|
f374345860 | ||
|
|
d3b50cb92e | ||
|
|
a58194bdb0 | ||
|
|
5f3484ac59 | ||
|
|
e14b74fdbf | ||
|
|
56f28859b7 | ||
|
|
f3cdb3b787 | ||
|
|
b35f6b0a94 | ||
|
|
5574cfef59 | ||
|
|
c3015583ce | ||
|
|
7cc2c930ed | ||
|
|
2662bf19df | ||
|
|
62e3fe2345 | ||
|
|
7d25d171e2 | ||
|
|
c5859c7254 | ||
|
|
dd7b4b8310 | ||
|
|
93551a65b8 | ||
|
|
7eafbabe65 | ||
|
|
43dd948476 | ||
|
|
75e7f2d22c | ||
|
|
26662eed9e | ||
|
|
121b1d0951 | ||
|
|
398036d77e | ||
|
|
59d5fcf88c | ||
|
|
1f8e48b374 | ||
|
|
7bf19b1232 | ||
|
|
1590b8c7e5 | ||
|
|
22522fc05f | ||
|
|
c9b59fab1f | ||
|
|
69152e087a | ||
|
|
652e572b56 | ||
|
|
65c89f54dc | ||
|
|
edf5c0e83b | ||
|
|
a4abbfe126 | ||
|
|
7b28bcef15 | ||
|
|
8042ac876e | ||
|
|
82bc907088 | ||
|
|
e2b572d9e2 | ||
|
|
e71596dc45 | ||
|
|
c3be58db43 | ||
|
|
3d77a12aa9 | ||
|
|
36deb8da71 | ||
|
|
05ee8c0e36 | ||
|
|
5ca55a5585 | ||
|
|
1b330a8c55 | ||
|
|
696678c981 | ||
|
|
20aec3cfca | ||
|
|
4ded37e71e | ||
|
|
0674ed846c | ||
|
|
3107152f5b | ||
|
|
5b19528662 | ||
|
|
357773c631 | ||
|
|
5e43d074c3 | ||
|
|
08bdcd52b8 | ||
|
|
0b8522be50 | ||
|
|
c02a7fe763 | ||
|
|
dcd5bdeb00 | ||
|
|
562b4f0415 | ||
|
|
6160a3fdff | ||
|
|
0779da6d24 | ||
|
|
740624ba01 | ||
|
|
2969cc9993 | ||
|
|
9a8c3a0447 | ||
|
|
e817382efd | ||
|
|
422d1feb3e | ||
|
|
2b0cb2b0a5 | ||
|
|
705d09d3d0 | ||
|
|
9114d86ecd | ||
|
|
ad4a950b56 | ||
|
|
bd480e0c6b | ||
|
|
af3415b040 | ||
|
|
b4a96bd840 | ||
|
|
9d8d421384 | ||
|
|
f6ffc00748 | ||
|
|
e35016f07d | ||
|
|
af8e2523a8 | ||
|
|
492df94b2a | ||
|
|
b62f7e2820 | ||
|
|
5cc2fc157c | ||
|
|
266c049f2d | ||
|
|
4e848c8cb5 | ||
|
|
efff1ac4a1 | ||
|
|
fc64a75fbd | ||
|
|
dd9f431b6f | ||
|
|
c894c54d00 | ||
|
|
4d349c7885 | ||
|
|
675b819e0a | ||
|
|
09f1083c50 | ||
|
|
47be3ef3ea | ||
|
|
9dd7778597 | ||
|
|
efffa925ed | ||
|
|
fa9bc92c95 | ||
|
|
227c66c2c5 | ||
|
|
e91bc9dfcc | ||
|
|
bc29035bda | ||
|
|
f10e453c9b | ||
|
|
d4b59b36a8 | ||
|
|
4f644cd0ca | ||
|
|
ed2935ec69 | ||
|
|
ea72c6b018 | ||
|
|
2df6ab36bf | ||
|
|
10ea63557a | ||
|
|
55e462d90b | ||
|
|
73393925c0 | ||
|
|
f9852bc807 | ||
|
|
6e1901e8e8 | ||
|
|
87582962d9 | ||
|
|
3de2698657 | ||
|
|
ec1f0221cd | ||
|
|
4d900c9ee1 | ||
|
|
3a758900eb | ||
|
|
1ea7178d17 | ||
|
|
c85c9988df | ||
|
|
34f68073a2 | ||
|
|
acc880c4df | ||
|
|
557b557503 | ||
|
|
3018356588 | ||
|
|
ede4dffcb7 | ||
|
|
cad392eb76 | ||
|
|
0296158100 | ||
|
|
b2a4692a02 | ||
|
|
2fbadea9e3 | ||
|
|
dc05be36a6 | ||
|
|
dac0d1d0dc | ||
|
|
459f7160ac | ||
|
|
aff524d843 | ||
|
|
3a91667e92 | ||
|
|
3e0d3584f7 | ||
|
|
1e47d6fb41 | ||
|
|
d5ba88b407 | ||
|
|
ce1e18b31b | ||
|
|
ec84aa7577 | ||
|
|
8b4d72cf32 | ||
|
|
85e6e65a47 | ||
|
|
7cad3655f5 | ||
|
|
b9e7f292c3 | ||
|
|
fc85034c60 | ||
|
|
f5e3d0cc02 | ||
|
|
fe377e8b94 | ||
|
|
5bb87138e9 | ||
|
|
579e58206e | ||
|
|
172b6ce892 | ||
|
|
0cc8eff1c3 | ||
|
|
3b023e5eaa | ||
|
|
615d8f1624 | ||
|
|
b4409ace21 | ||
|
|
dbee6aca1f | ||
|
|
acfe62eaf7 | ||
|
|
527a8af060 | ||
|
|
a5a931a670 | ||
|
|
2f05efaf12 | ||
|
|
83ef8a2e12 | ||
|
|
c564881867 | ||
|
|
b16930f35d | ||
|
|
2d910e3f07 | ||
|
|
daa1420c8e | ||
|
|
cea310e50b | ||
|
|
fcdd5c6752 | ||
|
|
2ace73e9a1 | ||
|
|
80cfb08794 | ||
|
|
1edc2b91cf | ||
|
|
1f58e18b6f | ||
|
|
f2bf316058 | ||
|
|
9cd38fa1ed | ||
|
|
edb0111775 | ||
|
|
de4f9e8d1a | ||
|
|
461e41cd61 | ||
|
|
716406198e | ||
|
|
68592aeddf | ||
|
|
b927ff6eef | ||
|
|
ce50e6e4fe | ||
|
|
167ed33bba | ||
|
|
0ee1abf31a | ||
|
|
6a0a1af67e | ||
|
|
f85481d51b | ||
|
|
00b6b0ac68 | ||
|
|
1546b1ae71 | ||
|
|
1e94498d9d | ||
|
|
0f7189b859 | ||
|
|
a6e0f1b75a | ||
|
|
543c22bb50 | ||
|
|
07e067cf0b | ||
|
|
6c256a34a9 | ||
|
|
6b2eb04a73 | ||
|
|
898d80ba38 | ||
|
|
ea8e4ad05b | ||
|
|
27aeac6859 | ||
|
|
8da371e324 | ||
|
|
0c59fe933d | ||
|
|
e169c67760 | ||
|
|
3a5a927dc6 | ||
|
|
2d419e4253 | ||
|
|
87869a29c9 | ||
|
|
544211f5ec | ||
|
|
f6ac95e2dd | ||
|
|
63bef2f844 | ||
|
|
4a8cd04de6 | ||
|
|
85806624db | ||
|
|
1ac2273984 | ||
|
|
a8c29c4ffe | ||
|
|
31af01c4f2 | ||
|
|
b1bba96d04 | ||
|
|
c5c730224e | ||
|
|
7441cf7d39 | ||
|
|
45c72d25df | ||
|
|
3fff631b32 | ||
|
|
bfa2891b23 | ||
|
|
5715f52fef | ||
|
|
1f2126f463 | ||
|
|
27ed0b37bf | ||
|
|
cdbd2f8507 | ||
|
|
e46ba2b4a4 | ||
|
|
1c338ba742 | ||
|
|
2b7673ad5d | ||
|
|
2f27353015 | ||
|
|
1b8c3f420a | ||
|
|
a3a070855c | ||
|
|
e84c6393b8 | ||
|
|
7413dd9f4b | ||
|
|
9cbd667eb7 | ||
|
|
37fb56c61c | ||
|
|
404a94cadb | ||
|
|
0807a8d016 | ||
|
|
4a9888157e | ||
|
|
83fbdcceac | ||
|
|
b070ef5fdb | ||
|
|
7d380dcd14 | ||
|
|
a15dbd992d | ||
|
|
52c5d235af | ||
|
|
495f6460a4 | ||
|
|
a96024d0e7 | ||
|
|
99b84d2909 | ||
|
|
24728b8b47 | ||
|
|
9750e49df8 | ||
|
|
bf31783d0c | ||
|
|
87eacf88c3 | ||
|
|
1dbfb99ead | ||
|
|
ff4020ea73 | ||
|
|
0ce7fc18a8 | ||
|
|
470a6e9d76 | ||
|
|
fc74fbeeaa | ||
|
|
9c6a5793b9 | ||
|
|
49b6b38741 | ||
|
|
a385ee9e97 | ||
|
|
f0917c62f2 | ||
|
|
94d20168da | ||
|
|
2d866e3ffa | ||
|
|
5d94d7067e | ||
|
|
7323f4c2ab | ||
|
|
eca6dfef6a | ||
|
|
761462ef93 | ||
|
|
98e83255e6 | ||
|
|
cbf3562a6f | ||
|
|
a2c41bbace | ||
|
|
2a12a3c702 | ||
|
|
2ab6a411f4 | ||
|
|
14ed10bdb0 | ||
|
|
49e6fd5bfb | ||
|
|
af872fa4d4 | ||
|
|
cec4cf014c | ||
|
|
783ad703d0 | ||
|
|
222671675c | ||
|
|
9a62d94630 | ||
|
|
c3edc6e24b | ||
|
|
119b0c55e9 | ||
|
|
c14c7edc5e | ||
|
|
e3b296c558 | ||
|
|
c2d29fb54b | ||
|
|
7aab8b0ae3 | ||
|
|
861a3bd4ae | ||
|
|
9bc7ad9cd5 | ||
|
|
a1e3fc1c23 | ||
|
|
242869db3a | ||
|
|
8924bb79e7 | ||
|
|
a0d103dac3 | ||
|
|
d52b299df8 | ||
|
|
092432f04f | ||
|
|
ea8e6634d6 | ||
|
|
3e6f90cf72 | ||
|
|
16731056ed | ||
|
|
0712894353 | ||
|
|
36fad803ed | ||
|
|
6732f01cb7 | ||
|
|
bb04e6fcfa | ||
|
|
007ee88d33 | ||
|
|
7a5bb94754 | ||
|
|
e06a0cd89b | ||
|
|
b6cba13293 | ||
|
|
d929bbfe30 | ||
|
|
bf67d64708 | ||
|
|
92aa1a6124 | ||
|
|
733ab8014b | ||
|
|
6aaa49f0bf | ||
|
|
638f27c2df | ||
|
|
84a3b55912 | ||
|
|
552d46479b | ||
|
|
fa9c066ffe | ||
|
|
e1e20b8757 | ||
|
|
2fb94a89e2 | ||
|
|
7a9604a3c9 | ||
|
|
e099088012 | ||
|
|
34e107e7d3 | ||
|
|
2254a4d0b4 | ||
|
|
9f7486f402 | ||
|
|
699602d1c5 | ||
|
|
2993ff1d75 | ||
|
|
afb3c24d5a | ||
|
|
8ef730b5fe | ||
|
|
866cfe5279 | ||
|
|
68c2eab6b9 | ||
|
|
aeda5bd260 | ||
|
|
a95cd71456 | ||
|
|
34d0dd9d6e | ||
|
|
401d9afd54 | ||
|
|
74edb936a5 | ||
|
|
c1558578d7 | ||
|
|
3597fdb7f8 | ||
|
|
43f2a379a1 | ||
|
|
69702e3a19 | ||
|
|
eb0655cf85 | ||
|
|
d8864bc92b | ||
|
|
89fc9d7c80 | ||
|
|
76aa9f7e10 | ||
|
|
abd0974897 | ||
|
|
c4e943a24f | ||
|
|
a3106bcb3d | ||
|
|
b045075a96 | ||
|
|
09d597f3ad | ||
|
|
9d4c3d83d0 | ||
|
|
95580a004f | ||
|
|
723f90755e | ||
|
|
324205f77a | ||
|
|
0a40d8ce8f | ||
|
|
168a25239e | ||
|
|
7eef46e941 | ||
|
|
50da4f8c07 | ||
|
|
2d0ebeae1b | ||
|
|
1a16491971 | ||
|
|
7f4f250970 | ||
|
|
25acb78071 | ||
|
|
e822d5a1b7 | ||
|
|
32fc0ff6d0 | ||
|
|
94dde075b3 | ||
|
|
65e92327ab | ||
|
|
0be02e67a5 | ||
|
|
7327c97e4c | ||
|
|
03b21dcf0a | ||
|
|
dc98c6739f | ||
|
|
fcb870728d | ||
|
|
7919428a1e | ||
|
|
3496a80f5a | ||
|
|
56b917a5c2 | ||
|
|
18c43aaea2 | ||
|
|
c43fc38f69 | ||
|
|
c07f0ab9c7 | ||
|
|
1c429b27bc | ||
|
|
b7019ad4f3 | ||
|
|
84e8f741ae | ||
|
|
e3a9b393c2 | ||
|
|
16aba517e4 | ||
|
|
205928e6df | ||
|
|
39ce4aa049 | ||
|
|
cef4a8296a | ||
|
|
b370ef0229 | ||
|
|
6b80f5bb35 | ||
|
|
bdae570a69 | ||
|
|
face5245a9 | ||
|
|
db1ed2a765 | ||
|
|
10982dec3c | ||
|
|
6825e75681 | ||
|
|
bd6a439e0b | ||
|
|
c90dd4902f | ||
|
|
868e5c45fe | ||
|
|
7e1852ee88 | ||
|
|
5ae98bc7c9 | ||
|
|
1624e7de7d | ||
|
|
7a98f84890 | ||
|
|
9b181280d4 | ||
|
|
38e94b9e43 | ||
|
|
dc25bc6f4d | ||
|
|
f64a205603 | ||
|
|
a8480f5492 | ||
|
|
0acf26b37c | ||
|
|
2c068a1a15 | ||
|
|
b961c95121 | ||
|
|
82693211f0 | ||
|
|
e5467462cb | ||
|
|
ab5a4102cd | ||
|
|
d5ef937b31 | ||
|
|
bce02e3f51 | ||
|
|
aad9744d85 | ||
|
|
506b781f3a | ||
|
|
267fd5b9bc | ||
|
|
c362f2869e | ||
|
|
4f7f437527 | ||
|
|
ab5da5ba28 | ||
|
|
7531bb8942 | ||
|
|
811ee8ccdc | ||
|
|
51cb485ce3 | ||
|
|
83d08b8b8f | ||
|
|
ed3d44d591 | ||
|
|
895fe23203 | ||
|
|
af04a560c8 | ||
|
|
9124a17e86 | ||
|
|
99b0d4c111 | ||
|
|
84b98c234f | ||
|
|
bcc1428ebf | ||
|
|
2133056c04 | ||
|
|
4155a9d7f9 | ||
|
|
ed4825523c | ||
|
|
fdbb2bbdab | ||
|
|
c064d6d847 | ||
|
|
d33874bd3d | ||
|
|
96d32dd11f | ||
|
|
d6bc354ff3 | ||
|
|
7325a4fb4b | ||
|
|
90f00c5b29 | ||
|
|
8539c423ea | ||
|
|
e9bfbfce84 | ||
|
|
6e4f0664cb | ||
|
|
3c920c9d94 | ||
|
|
15b67b2c6c | ||
|
|
973537fd9a | ||
|
|
d70a74479d | ||
|
|
946e4b750a | ||
|
|
9789e3fb9b | ||
|
|
6a15679d87 | ||
|
|
ad1cd5577c | ||
|
|
55668ca621 | ||
|
|
0c221a28d1 | ||
|
|
a475551b23 | ||
|
|
bad7676414 | ||
|
|
51c0470f0b | ||
|
|
4530047c76 | ||
|
|
1bf83c3bf7 | ||
|
|
bb6ab11001 | ||
|
|
e4bd1884d3 | ||
|
|
4014a48f7d | ||
|
|
97ded32415 | ||
|
|
593ac081f0 | ||
|
|
69f0a4e1cb | ||
|
|
757e7de60c | ||
|
|
1d7d5469a9 | ||
|
|
98afc3e590 | ||
|
|
ea189790f1 | ||
|
|
62987077fa | ||
|
|
3b9f7cb3f1 | ||
|
|
5882c7e344 | ||
|
|
77b6e2cd2e | ||
|
|
88b1f956c7 | ||
|
|
d9b49ca2bc | ||
|
|
4156ad5a30 | ||
|
|
ae46561648 | ||
|
|
1700a807e9 | ||
|
|
0bab15b213 | ||
|
|
38d3075554 | ||
|
|
1b124bfb87 | ||
|
|
cdf4dd0302 | ||
|
|
a13bed2db6 | ||
|
|
26318f94fe | ||
|
|
769fb0820f | ||
|
|
52380534f3 | ||
|
|
2fd2526046 | ||
|
|
61509bbd44 | ||
|
|
76499afd8d | ||
|
|
4023f328f7 | ||
|
|
4f49cb555b | ||
|
|
4dc959a3e4 | ||
|
|
518fbf562c | ||
|
|
49828d3d9d | ||
|
|
248e6a7b05 | ||
|
|
5561e6b770 | ||
|
|
ab083b86f3 | ||
|
|
4bf525222a | ||
|
|
45efcb381c | ||
|
|
07a7736c71 | ||
|
|
d2826ab7af | ||
|
|
6ab769f382 | ||
|
|
3e1cd2bdca | ||
|
|
22784b7f06 | ||
|
|
c4922615eb | ||
|
|
7307ddad3c | ||
|
|
c7ba143d03 | ||
|
|
b24206387b | ||
|
|
64d196442f | ||
|
|
5944643da6 | ||
|
|
8c5e495272 | ||
|
|
bb23685b9d | ||
|
|
940659bc14 | ||
|
|
7c5933732b | ||
|
|
89df2fcf76 | ||
|
|
174a199c30 | ||
|
|
6f1e7c3016 | ||
|
|
9f81e23f8f | ||
|
|
19fab6eea7 | ||
|
|
63161b11c3 | ||
|
|
4f886d65ec | ||
|
|
62e0e195e8 | ||
|
|
e9d4749f44 | ||
|
|
93f8e7d8e9 | ||
|
|
3dea6e0da5 | ||
|
|
6fb3b305ad | ||
|
|
7dfe891cc1 | ||
|
|
5c3966a32d |
@@ -5,8 +5,13 @@ engines:
|
||||
enabled: false
|
||||
eslint:
|
||||
enabled: true
|
||||
checks:
|
||||
import/extensions:
|
||||
enabled: false
|
||||
import/no-extraneous-dependencies:
|
||||
enabled: false
|
||||
config:
|
||||
config: caravel/assets/.eslintrc
|
||||
config: superset/assets/.eslintrc
|
||||
pep8:
|
||||
enabled: true
|
||||
fixme:
|
||||
@@ -19,16 +24,17 @@ engines:
|
||||
ratings:
|
||||
paths:
|
||||
- "**.py"
|
||||
- "caravel/assets/**.js"
|
||||
- "caravel/assets/**.jsx"
|
||||
- "superset/assets/**.js"
|
||||
- "superset/assets/**.jsx"
|
||||
exclude_paths:
|
||||
- ".*"
|
||||
- "**.pyc"
|
||||
- "**.gz"
|
||||
- "env/"
|
||||
- "tests/"
|
||||
- "caravel/assets/images/"
|
||||
- "caravel/assets/vendor/"
|
||||
- "caravel/assets/node_modules/"
|
||||
- "caravel/assets/javascripts/dist/"
|
||||
- "caravel/migrations"
|
||||
- "superset/assets/images/"
|
||||
- "superset/assets/vendor/"
|
||||
- "superset/assets/node_modules/"
|
||||
- "superset/assets/javascripts/dist/"
|
||||
- "superset/migrations"
|
||||
- "docs/"
|
||||
|
||||
@@ -1 +1 @@
|
||||
repo_token: eESbYiv4An6KEvjpmguDs4L7YkubXbqn1
|
||||
repo_token: 4P9MpvLrZfJKzHdGZsdV3MzO43OZJgYFn
|
||||
|
||||
15
.gitignore
vendored
@@ -1,28 +1,37 @@
|
||||
*.pyc
|
||||
yarn-error.log
|
||||
_modules
|
||||
superset/assets/coverage/*
|
||||
changelog.sh
|
||||
.DS_Store
|
||||
.coverage
|
||||
_build
|
||||
_static
|
||||
_images
|
||||
caravel/bin/caravelc
|
||||
_modules
|
||||
superset/bin/supersetc
|
||||
env_py3
|
||||
.eggs
|
||||
build
|
||||
*.db
|
||||
tmp
|
||||
caravel_config.py
|
||||
superset_config.py
|
||||
local_config.py
|
||||
env
|
||||
dist
|
||||
caravel.egg-info/
|
||||
superset.egg-info/
|
||||
app.db
|
||||
*.bak
|
||||
.idea
|
||||
*.sqllite
|
||||
.vscode
|
||||
.python-version
|
||||
|
||||
# Node.js, webpack artifacts
|
||||
*.entry.js
|
||||
*.js.map
|
||||
node_modules
|
||||
npm-debug.log
|
||||
yarn.lock
|
||||
superset/assets/version_info.json
|
||||
|
||||
|
||||
@@ -16,8 +16,7 @@ pep8:
|
||||
full: true
|
||||
ignore-paths:
|
||||
- docs
|
||||
- caravel/migrations/env.py
|
||||
- caravel/ascii_art.py
|
||||
- superset/migrations/env.py
|
||||
ignore-patterns:
|
||||
- ^example/doc_.*\.py$
|
||||
- (^|/)docs(/|$)
|
||||
|
||||
2
.pycodestyle
Normal file
@@ -0,0 +1,2 @@
|
||||
[pycodestyle]
|
||||
max-line-length = 90
|
||||
407
.pylintrc
Normal file
@@ -0,0 +1,407 @@
|
||||
[MASTER]
|
||||
|
||||
# Specify a configuration file.
|
||||
#rcfile=
|
||||
|
||||
# Python code to execute, usually for sys.path manipulation such as
|
||||
# pygtk.require().
|
||||
#init-hook=
|
||||
|
||||
# Add files or directories to the blacklist. They should be base names, not
|
||||
# paths.
|
||||
ignore=CVS
|
||||
|
||||
# Add files or directories matching the regex patterns to the blacklist. The
|
||||
# regex matches against base names, not paths.
|
||||
ignore-patterns=
|
||||
|
||||
# Pickle collected data for later comparisons.
|
||||
persistent=yes
|
||||
|
||||
# List of plugins (as comma separated values of python modules names) to load,
|
||||
# usually to register additional checkers.
|
||||
load-plugins=
|
||||
|
||||
# Use multiple processes to speed up Pylint.
|
||||
jobs=1
|
||||
|
||||
# Allow loading of arbitrary C extensions. Extensions are imported into the
|
||||
# active Python interpreter and may run arbitrary code.
|
||||
unsafe-load-any-extension=no
|
||||
|
||||
# A comma-separated list of package or module names from where C extensions may
|
||||
# be loaded. Extensions are loading into the active Python interpreter and may
|
||||
# run arbitrary code
|
||||
extension-pkg-whitelist=
|
||||
|
||||
# Allow optimization of some AST trees. This will activate a peephole AST
|
||||
# optimizer, which will apply various small optimizations. For instance, it can
|
||||
# be used to obtain the result of joining multiple strings with the addition
|
||||
# operator. Joining a lot of strings can lead to a maximum recursion error in
|
||||
# Pylint and this flag can prevent that. It has one side effect, the resulting
|
||||
# AST will be different than the one from reality. This option is deprecated
|
||||
# and it will be removed in Pylint 2.0.
|
||||
optimize-ast=no
|
||||
|
||||
|
||||
[MESSAGES CONTROL]
|
||||
|
||||
# Only show warnings with the listed confidence levels. Leave empty to show
|
||||
# all. Valid levels: HIGH, INFERENCE, INFERENCE_FAILURE, UNDEFINED
|
||||
confidence=
|
||||
|
||||
# Enable the message, report, category or checker with the given id(s). You can
|
||||
# either give multiple identifier separated by comma (,) or put this option
|
||||
# multiple time (only on the command line, not in the configuration file where
|
||||
# it should appear only once). See also the "--disable" option for examples.
|
||||
#enable=
|
||||
|
||||
# Disable the message, report, category or checker with the given id(s). You
|
||||
# can either give multiple identifiers separated by comma (,) or put this
|
||||
# option multiple times (only on the command line, not in the configuration
|
||||
# file where it should appear only once).You can also use "--disable=all" to
|
||||
# disable everything first and then reenable specific checks. For example, if
|
||||
# you want to run only the similarities checker, you can use "--disable=all
|
||||
# --enable=similarities". If you want to run only the classes checker, but have
|
||||
# no Warning level messages displayed, use"--disable=all --enable=classes
|
||||
# --disable=W"
|
||||
disable=standarderror-builtin,long-builtin,dict-view-method,intern-builtin,suppressed-message,no-absolute-import,unpacking-in-except,apply-builtin,delslice-method,indexing-exception,old-raise-syntax,print-statement,cmp-builtin,reduce-builtin,useless-suppression,coerce-method,input-builtin,cmp-method,raw_input-builtin,nonzero-method,backtick,basestring-builtin,setslice-method,reload-builtin,oct-method,map-builtin-not-iterating,execfile-builtin,old-octal-literal,zip-builtin-not-iterating,buffer-builtin,getslice-method,metaclass-assignment,xrange-builtin,long-suffix,round-builtin,range-builtin-not-iterating,next-method-called,dict-iter-method,parameter-unpacking,unicode-builtin,unichr-builtin,import-star-module-level,raising-string,filter-builtin-not-iterating,old-ne-operator,using-cmp-argument,coerce-builtin,file-builtin,old-division,hex-method,invalid-unary-operand-type
|
||||
|
||||
|
||||
[REPORTS]
|
||||
|
||||
# Set the output format. Available formats are text, parseable, colorized, msvs
|
||||
# (visual studio) and html. You can also give a reporter class, eg
|
||||
# mypackage.mymodule.MyReporterClass.
|
||||
output-format=text
|
||||
|
||||
# Put messages in a separate file for each module / package specified on the
|
||||
# command line instead of printing them on stdout. Reports (if any) will be
|
||||
# written in a file name "pylint_global.[txt|html]". This option is deprecated
|
||||
# and it will be removed in Pylint 2.0.
|
||||
files-output=no
|
||||
|
||||
# Tells whether to display a full report or only the messages
|
||||
reports=yes
|
||||
|
||||
# Python expression which should return a note less than 10 (10 is the highest
|
||||
# note). You have access to the variables errors warning, statement which
|
||||
# respectively contain the number of errors / warnings messages and the total
|
||||
# number of statements analyzed. This is used by the global evaluation report
|
||||
# (RP0004).
|
||||
evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10)
|
||||
|
||||
# Template used to display messages. This is a python new-style format string
|
||||
# used to format the message information. See doc for all details
|
||||
#msg-template=
|
||||
|
||||
|
||||
[BASIC]
|
||||
|
||||
# Good variable names which should always be accepted, separated by a comma
|
||||
good-names=i,j,k,ex,Run,_,d,e,v,o,l,x,ts
|
||||
|
||||
# Bad variable names which should always be refused, separated by a comma
|
||||
bad-names=foo,bar,baz,toto,tutu,tata
|
||||
|
||||
# Colon-delimited sets of names that determine each other's naming style when
|
||||
# the name regexes allow several styles.
|
||||
name-group=
|
||||
|
||||
# Include a hint for the correct naming format with invalid-name
|
||||
include-naming-hint=no
|
||||
|
||||
# List of decorators that produce properties, such as abc.abstractproperty. Add
|
||||
# to this list to register other decorators that produce valid properties.
|
||||
property-classes=abc.abstractproperty
|
||||
|
||||
# Regular expression matching correct argument names
|
||||
argument-rgx=[a-z_][a-z0-9_]{2,30}$
|
||||
|
||||
# Naming hint for argument names
|
||||
argument-name-hint=[a-z_][a-z0-9_]{2,30}$
|
||||
|
||||
# Regular expression matching correct method names
|
||||
method-rgx=[a-z_][a-z0-9_]{2,30}$
|
||||
|
||||
# Naming hint for method names
|
||||
method-name-hint=[a-z_][a-z0-9_]{2,30}$
|
||||
|
||||
# Regular expression matching correct variable names
|
||||
variable-rgx=[a-z_][a-z0-9_]{1,30}$
|
||||
|
||||
# Naming hint for variable names
|
||||
variable-name-hint=[a-z_][a-z0-9_]{2,30}$
|
||||
|
||||
# Regular expression matching correct inline iteration names
|
||||
inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$
|
||||
|
||||
# Naming hint for inline iteration names
|
||||
inlinevar-name-hint=[A-Za-z_][A-Za-z0-9_]*$
|
||||
|
||||
# Regular expression matching correct constant names
|
||||
const-rgx=(([A-Za-z_][A-Za-z0-9_]*)|(__.*__))$
|
||||
|
||||
# Naming hint for constant names
|
||||
const-name-hint=(([A-Z_][A-Z0-9_]*)|(__.*__))$
|
||||
|
||||
# Regular expression matching correct class names
|
||||
class-rgx=[A-Z_][a-zA-Z0-9]+$
|
||||
|
||||
# Naming hint for class names
|
||||
class-name-hint=[A-Z_][a-zA-Z0-9]+$
|
||||
|
||||
# Regular expression matching correct class attribute names
|
||||
class-attribute-rgx=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$
|
||||
|
||||
# Naming hint for class attribute names
|
||||
class-attribute-name-hint=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$
|
||||
|
||||
# Regular expression matching correct module names
|
||||
module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$
|
||||
|
||||
# Naming hint for module names
|
||||
module-name-hint=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$
|
||||
|
||||
# Regular expression matching correct attribute names
|
||||
attr-rgx=[a-z_][a-z0-9_]{2,30}$
|
||||
|
||||
# Naming hint for attribute names
|
||||
attr-name-hint=[a-z_][a-z0-9_]{2,30}$
|
||||
|
||||
# Regular expression matching correct function names
|
||||
function-rgx=[a-z_][a-z0-9_]{2,30}$
|
||||
|
||||
# Naming hint for function names
|
||||
function-name-hint=[a-z_][a-z0-9_]{2,30}$
|
||||
|
||||
# Regular expression which should only match function or class names that do
|
||||
# not require a docstring.
|
||||
no-docstring-rgx=^_
|
||||
|
||||
# Minimum line length for functions/classes that require docstrings, shorter
|
||||
# ones are exempt.
|
||||
docstring-min-length=10
|
||||
|
||||
|
||||
[ELIF]
|
||||
|
||||
# Maximum number of nested blocks for function / method body
|
||||
max-nested-blocks=5
|
||||
|
||||
|
||||
[FORMAT]
|
||||
|
||||
# Maximum number of characters on a single line.
|
||||
max-line-length=90
|
||||
|
||||
# Regexp for a line that is allowed to be longer than the limit.
|
||||
ignore-long-lines=^\s*(# )?<?https?://\S+>?$
|
||||
|
||||
# Allow the body of an if to be on the same line as the test if there is no
|
||||
# else.
|
||||
single-line-if-stmt=no
|
||||
|
||||
# List of optional constructs for which whitespace checking is disabled. `dict-
|
||||
# separator` is used to allow tabulation in dicts, etc.: {1 : 1,\n222: 2}.
|
||||
# `trailing-comma` allows a space between comma and closing bracket: (a, ).
|
||||
# `empty-line` allows space-only lines.
|
||||
no-space-check=trailing-comma,dict-separator
|
||||
|
||||
# Maximum number of lines in a module
|
||||
max-module-lines=1000
|
||||
|
||||
# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1
|
||||
# tab).
|
||||
indent-string=' '
|
||||
|
||||
# Number of spaces of indent required inside a hanging or continued line.
|
||||
indent-after-paren=4
|
||||
|
||||
# Expected format of line ending, e.g. empty (any line ending), LF or CRLF.
|
||||
expected-line-ending-format=
|
||||
|
||||
|
||||
[LOGGING]
|
||||
|
||||
# Logging modules to check that the string format arguments are in logging
|
||||
# function parameter format
|
||||
logging-modules=logging
|
||||
|
||||
|
||||
[MISCELLANEOUS]
|
||||
|
||||
# List of note tags to take in consideration, separated by a comma.
|
||||
notes=FIXME,XXX,TODO
|
||||
|
||||
|
||||
[SIMILARITIES]
|
||||
|
||||
# Minimum lines number of a similarity.
|
||||
min-similarity-lines=4
|
||||
|
||||
# Ignore comments when computing similarities.
|
||||
ignore-comments=yes
|
||||
|
||||
# Ignore docstrings when computing similarities.
|
||||
ignore-docstrings=yes
|
||||
|
||||
# Ignore imports when computing similarities.
|
||||
ignore-imports=no
|
||||
|
||||
|
||||
[SPELLING]
|
||||
|
||||
# Spelling dictionary name. Available dictionaries: none. To make it working
|
||||
# install python-enchant package.
|
||||
spelling-dict=
|
||||
|
||||
# List of comma separated words that should not be checked.
|
||||
spelling-ignore-words=
|
||||
|
||||
# A path to a file that contains private dictionary; one word per line.
|
||||
spelling-private-dict-file=
|
||||
|
||||
# Tells whether to store unknown words to indicated private dictionary in
|
||||
# --spelling-private-dict-file option instead of raising a message.
|
||||
spelling-store-unknown-words=no
|
||||
|
||||
|
||||
[TYPECHECK]
|
||||
|
||||
# Tells whether missing members accessed in mixin class should be ignored. A
|
||||
# mixin class is detected if its name ends with "mixin" (case insensitive).
|
||||
ignore-mixin-members=yes
|
||||
|
||||
# List of module names for which member attributes should not be checked
|
||||
# (useful for modules/projects where namespaces are manipulated during runtime
|
||||
# and thus existing member attributes cannot be deduced by static analysis. It
|
||||
# supports qualified module names, as well as Unix pattern matching.
|
||||
ignored-modules=numpy,pandas,alembic.op,sqlalchemy,alembic.context,flask_appbuilder.security.sqla.PermissionView.role,flask_appbuilder.Model.metadata,flask_appbuilder.Base.metadata
|
||||
|
||||
# List of class names for which member attributes should not be checked (useful
|
||||
# for classes with dynamically set attributes). This supports the use of
|
||||
# qualified names.
|
||||
ignored-classes=optparse.Values,thread._local,_thread._local
|
||||
|
||||
# List of members which are set dynamically and missed by pylint inference
|
||||
# system, and so shouldn't trigger E1101 when accessed. Python regular
|
||||
# expressions are accepted.
|
||||
generated-members=
|
||||
|
||||
# List of decorators that produce context managers, such as
|
||||
# contextlib.contextmanager. Add to this list to register other decorators that
|
||||
# produce valid context managers.
|
||||
contextmanager-decorators=contextlib.contextmanager
|
||||
|
||||
|
||||
[VARIABLES]
|
||||
|
||||
# Tells whether we should check for unused import in __init__ files.
|
||||
init-import=no
|
||||
|
||||
# A regular expression matching the name of dummy variables (i.e. expectedly
|
||||
# not used).
|
||||
dummy-variables-rgx=(_+[a-zA-Z0-9]*?$)|dummy
|
||||
|
||||
# List of additional names supposed to be defined in builtins. Remember that
|
||||
# you should avoid to define new builtins when possible.
|
||||
additional-builtins=
|
||||
|
||||
# List of strings which can identify a callback function by name. A callback
|
||||
# name must start or end with one of those strings.
|
||||
callbacks=cb_,_cb
|
||||
|
||||
# List of qualified module names which can have objects that can redefine
|
||||
# builtins.
|
||||
redefining-builtins-modules=six.moves,future.builtins
|
||||
|
||||
|
||||
[CLASSES]
|
||||
|
||||
# List of method names used to declare (i.e. assign) instance attributes.
|
||||
defining-attr-methods=__init__,__new__,setUp
|
||||
|
||||
# List of valid names for the first argument in a class method.
|
||||
valid-classmethod-first-arg=cls
|
||||
|
||||
# List of valid names for the first argument in a metaclass class method.
|
||||
valid-metaclass-classmethod-first-arg=mcs
|
||||
|
||||
# List of member names, which should be excluded from the protected access
|
||||
# warning.
|
||||
exclude-protected=_asdict,_fields,_replace,_source,_make
|
||||
|
||||
|
||||
[DESIGN]
|
||||
|
||||
# Maximum number of arguments for function / method
|
||||
max-args=5
|
||||
|
||||
# Argument names that match this expression will be ignored. Default to name
|
||||
# with leading underscore
|
||||
ignored-argument-names=_.*
|
||||
|
||||
# Maximum number of locals for function / method body
|
||||
max-locals=15
|
||||
|
||||
# Maximum number of return / yield for function / method body
|
||||
max-returns=6
|
||||
|
||||
# Maximum number of branch for function / method body
|
||||
max-branches=12
|
||||
|
||||
# Maximum number of statements in function / method body
|
||||
max-statements=50
|
||||
|
||||
# Maximum number of parents for a class (see R0901).
|
||||
max-parents=7
|
||||
|
||||
# Maximum number of attributes for a class (see R0902).
|
||||
max-attributes=7
|
||||
|
||||
# Minimum number of public methods for a class (see R0903).
|
||||
min-public-methods=2
|
||||
|
||||
# Maximum number of public methods for a class (see R0904).
|
||||
max-public-methods=20
|
||||
|
||||
# Maximum number of boolean expressions in a if statement
|
||||
max-bool-expr=5
|
||||
|
||||
|
||||
[IMPORTS]
|
||||
|
||||
# Deprecated modules which should not be used, separated by a comma
|
||||
deprecated-modules=optparse
|
||||
|
||||
# Create a graph of every (i.e. internal and external) dependencies in the
|
||||
# given file (report RP0402 must not be disabled)
|
||||
import-graph=
|
||||
|
||||
# Create a graph of external dependencies in the given file (report RP0402 must
|
||||
# not be disabled)
|
||||
ext-import-graph=
|
||||
|
||||
# Create a graph of internal dependencies in the given file (report RP0402 must
|
||||
# not be disabled)
|
||||
int-import-graph=
|
||||
|
||||
# Force import order to recognize a module as part of the standard
|
||||
# compatibility libraries.
|
||||
known-standard-library=
|
||||
|
||||
# Force import order to recognize a module as part of a third party library.
|
||||
known-third-party=enchant
|
||||
|
||||
# Analyse import fallback blocks. This can be used to support both Python 2 and
|
||||
# 3 compatible code, which means that the block might have code that exists
|
||||
# only in one or another interpreter, leading to false positives when analysed.
|
||||
analyse-fallback-blocks=no
|
||||
|
||||
|
||||
[EXCEPTIONS]
|
||||
|
||||
# Exceptions that will emit a warning when being caught. Defaults to
|
||||
# "Exception"
|
||||
overgeneral-exceptions=Exception
|
||||
20
.travis.yml
@@ -1,38 +1,34 @@
|
||||
|
||||
language: python
|
||||
services:
|
||||
- redis-server
|
||||
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"
|
||||
- TRAVIS_NODE_VERSION="7.10.0"
|
||||
matrix:
|
||||
- TOX_ENV=javascript
|
||||
- TOX_ENV=pylint
|
||||
- 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'
|
||||
- npm install -g npm@'>=5.0.3'
|
||||
before_script:
|
||||
- mysql -e 'drop database if exists caravel; create database caravel DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci' -u root
|
||||
- mysql -e 'drop database if exists superset; create database superset 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
|
||||
- mysql -u root -e "GRANT ALL ON superset.* TO 'mysqluser'@'localhost';"
|
||||
- psql -c 'create database superset;' -U postgres
|
||||
- psql -c "CREATE USER postgresuser WITH PASSWORD 'pguserpassword';" -U postgres
|
||||
- export PATH=${PATH}:/tmp/hive/bin
|
||||
install:
|
||||
- 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
|
||||
script: tox -e $TOX_ENV
|
||||
|
||||
851
CHANGELOG.md
@@ -1,5 +1,854 @@
|
||||
## Change Log
|
||||
|
||||
## Change Log
|
||||
|
||||
### 0.18.3 (2017/06/02 15:27 +00:00)
|
||||
- [d90044c](https://github.com/airbnb/superset/commit/d90044cd523253aa01b5cdf6509b43abeef34079) 0.18.3 (@mistercrunch)
|
||||
- [62bd4eb](https://github.com/airbnb/superset/commit/62bd4eb2118e4f1e771b58cd455b928be002a461) Converting filter argument to number if column is number (#2891) (@fabianmenges)
|
||||
- [677c427](https://github.com/airbnb/superset/commit/677c427b1615a2a9b9054932b5e07868d7d63e42) delete DataPreviewModal, it doesn't get used anywhere (#2882) (@ascott)
|
||||
- [52b0716](https://github.com/airbnb/superset/commit/52b0716571c5b68f65d08719e54343e0a6ec8c8e) [bugfix] allow database macro to work when CSRF is diabled (#2884) (@justinr1234)
|
||||
- [04b662e](https://github.com/airbnb/superset/commit/04b662ea1154b75e2c362aed97e33946251d1bed) Fix a type error in rst' sub list. (#2881) (@xiaohanyu)
|
||||
- [db052b1](https://github.com/airbnb/superset/commit/db052b17ea1782c472687095e1365d071e592dd0) Add visualize advise for long query (#2879) (@graceguo-supercat)
|
||||
- [e300273](https://github.com/airbnb/superset/commit/e300273e71f0b6ca8b63ae974cc13534d94c56de) [explore] adding y_axis_bounds to force Y axis bounds (#2878) (@mistercrunch)
|
||||
- [c5f2eaf](https://github.com/airbnb/superset/commit/c5f2eafc906bebf1d238e62ff5a8821cf549220c) [explore] 'Save as' -> 'Save' as it can be used to overwrite (#2875) (@mistercrunch)
|
||||
- [90e4d64](https://github.com/airbnb/superset/commit/90e4d6469d3d420cf839a4c9f3a2408ab0ff0a42) [js-testing] more tests for SelectControl (#2877) (@ascott)
|
||||
- [1e7773e](https://github.com/airbnb/superset/commit/1e7773eb169d29607991d0c4619ee930104e18de) Improve visualize modal test coverage (#2811) (@graceguo-supercat)
|
||||
- [3c89c8c](https://github.com/airbnb/superset/commit/3c89c8cc4613d938e4e8726c30142fa32b1249f7) 0.18.3-alpha.3 (@mistercrunch)
|
||||
- [74086da](https://github.com/airbnb/superset/commit/74086dae2ba66029917a7ed640cfcfc7555c0520) [bars] fix sort numeric bar on x axis (#2812) (@mistercrunch)
|
||||
- [66403f1](https://github.com/airbnb/superset/commit/66403f1876bb7bcf31eb8187517c116a2d5b6b96) [explore] viz type selector as modal (#2787) (@mistercrunch)
|
||||
- [3a4cd3a](https://github.com/airbnb/superset/commit/3a4cd3ae24c811e21fb76c5f9efecb2a6c4a6da2) Applying specified limit in bubble plot (#2815) (@mistercrunch)
|
||||
- [4ffc1f6](https://github.com/airbnb/superset/commit/4ffc1f613e1d2bf012dc5eb66751fea8c698804e) Fix filter values populating for views (#2816) (@mistercrunch)
|
||||
- [dfbba84](https://github.com/airbnb/superset/commit/dfbba84400986451f5068354a7626537e7b377a4) 0.18.3-alpha.2 (@mistercrunch)
|
||||
- [77864e6](https://github.com/airbnb/superset/commit/77864e6cf4d5394a5080300097ae21cf9abfcc53) reduce clientside timeout limit (#2820) (@graceguo-supercat)
|
||||
- [4d12251](https://github.com/airbnb/superset/commit/4d1225180618b4c4f05c67f6534bf273692a9243) [explore] include ControlHeader as part of Control interface (#2809) (@mistercrunch)
|
||||
- [0c9f9b6](https://github.com/airbnb/superset/commit/0c9f9b695b921c7e17cec83e1d51e4aa3cae7cc9) [clarity/consistency] rename /explorev2/ -> /explore/ (#2802) (@ascott)
|
||||
- [a4a2bf7](https://github.com/airbnb/superset/commit/a4a2bf7ae9cc1075a38cc980bb696d6512125f2b) filter_box: allow creatable entries (#2804) (@vavrusa)
|
||||
- [d0a04cd](https://github.com/airbnb/superset/commit/d0a04cde49c86185b779b16f1da05450b1ccf571) apply redux for VisualizeModal (#2795) (@graceguo-supercat)
|
||||
- [69685b9](https://github.com/airbnb/superset/commit/69685b9dcc0c26f819ff7edeedc10ee302e97f83) Fixing country maps (#2801) (@mistercrunch)
|
||||
- [b308a3e](https://github.com/airbnb/superset/commit/b308a3eb4eb08de39edbff6490c06a6bef7b7ce1) Added Country Map : New Visualization tools (#2708) (@ymatagne)
|
||||
- [bfa40bd](https://github.com/airbnb/superset/commit/bfa40bd360021874628477ee3eb2272033cd2d54) [hotfix] 'filter box from and to date filter #2649' (#2785) (@yamdraco)
|
||||
- [b0e2904](https://github.com/airbnb/superset/commit/b0e2904c245e5569473f425af2806271e33a5176) Updating permission when refreshing druid datasource (#2655) (@ShengyaoQian)
|
||||
- [ce506bd](https://github.com/airbnb/superset/commit/ce506bdf65b46f5bccee84ca8254417f63b124a5) Logging a few more actions (#2783) (@mistercrunch)
|
||||
- [922cc03](https://github.com/airbnb/superset/commit/922cc037bf859c935cc5eacbcd96bf6fa004c5fe) 0.18.3-alpha.1 (@mistercrunch)
|
||||
- [8252ada](https://github.com/airbnb/superset/commit/8252ada1f9ac94866b91eac55b77ed6d0ef7d02f) [docs] more details on how filters are applied (#2778) (@mistercrunch)
|
||||
- [a2d2f8b](https://github.com/airbnb/superset/commit/a2d2f8bb8c006adcf80bb2ac18b82f3b486f366a) Enable filter value autocomplete in examples (#2781) (@mistercrunch)
|
||||
- [7c5f61d](https://github.com/airbnb/superset/commit/7c5f61d6a61e1a3cb6d20d0918610abafa2cd326) Adding some STATSD logging (#2715) (@mistercrunch)
|
||||
- [841e18a](https://github.com/airbnb/superset/commit/841e18a08c4b375fdff5b846f5d9f108903a3eb6) [sql lab] make database ordering alphabetical in left panel (#2769) (@mistercrunch)
|
||||
- [dbc7fef](https://github.com/airbnb/superset/commit/dbc7fef7f501cd59ebd99524fa171d9e4dee0325) [sql lab] fix user timestamp is off (#2774) (@mistercrunch)
|
||||
|
||||
### 0.18.2 (2017/05/17 06:08 +00:00)
|
||||
- [cbfe3cb](https://github.com/airbnb/superset/commit/cbfe3cb2dcadedeedfcf55f2bb4883b76a484b36) 0.18.2 (@mistercrunch)
|
||||
- [5fcd25d](https://github.com/airbnb/superset/commit/5fcd25def15b5990c10b5045cb89b88f94ba8716) 0.18.1-alpha.2 (@mistercrunch)
|
||||
- [fe3f5f6](https://github.com/airbnb/superset/commit/fe3f5f69ae83eaf96415926661b272ebb460a4e0) [hotfix] 'No numeric types to aggregate' (@mistercrunch)
|
||||
- [2395fbb](https://github.com/airbnb/superset/commit/2395fbbdaaa5c81c3559f17cedf2e998b8341cb9) Adding `end_result_backend_time` to Query model (#2766) (@mistercrunch)
|
||||
- [960b26c](https://github.com/airbnb/superset/commit/960b26c7a2cad58b39c359f44c385980434dacb8) Show clear and actionable query timeout error message (#2763) (@graceguo-supercat)
|
||||
- [28ac350](https://github.com/airbnb/superset/commit/28ac3504d67f76c31aac23435dd15d76e0ca75bf) 0.18.1-alpha.1 (@mistercrunch)
|
||||
- [ecc00bd](https://github.com/airbnb/superset/commit/ecc00bdd26517a832a35529f0fdd7d17972e6f8f) [explore] a bit less margin in left panel (#2758) (@mistercrunch)
|
||||
- [e794645](https://github.com/airbnb/superset/commit/e7946451d6aa84229d0c70b7a683b29b784ca1a1) fixed 500 error when export dashboard (#2760) (@eeve)
|
||||
- [9b34600](https://github.com/airbnb/superset/commit/9b34600c8e8df72ecbdfaaf94bdf023c08e26701) Remove duplicate text (#2761) (@awbush)
|
||||
- [8846108](https://github.com/airbnb/superset/commit/884610861b8d39da91e4c1bce7934172d2486da9) 0.18.0 (@mistercrunch)
|
||||
- [d9bd3d6](https://github.com/airbnb/superset/commit/d9bd3d646006d9e6ddf2ccded21d7984935c98c8) fix percentage change viz (#2757) (@yileic)
|
||||
- [38375be](https://github.com/airbnb/superset/commit/38375be5c3062caf9f6cd4d6ac62109e1940bd10) Fix issues around % signs and Presto (#2755) (@mistercrunch)
|
||||
- [91d951a](https://github.com/airbnb/superset/commit/91d951ac422a6411e59b2ec195011ea4dc44b0b1) Change hardcoded references to 'User' security model to allow custom class override (#2728) (@RichRadics)
|
||||
|
||||
### 0.18.0 (2017/05/12 03:36 +00:00)
|
||||
- [d79a45f](https://github.com/airbnb/superset/commit/d79a45ff32ff8e2b5d601601507680dccf693bbc) add number format to pivot table (#2703) (@yileic)
|
||||
- [818251f](https://github.com/airbnb/superset/commit/818251fc8519167be7e0730083c4a694972fb06b) make margin consistent (#2753) (@yileic)
|
||||
- [75abd1f](https://github.com/airbnb/superset/commit/75abd1f44a12208fd54f28a1185d40ea8639396a) 0.18.0-alpha.4 (@mistercrunch)
|
||||
- [f55df3b](https://github.com/airbnb/superset/commit/f55df3b18b67ff58d5ad3f6f12f7fe76e9697084) [sql lab] fix responsivity of grid (#2742) (@mistercrunch)
|
||||
- [5dbfdef](https://github.com/airbnb/superset/commit/5dbfdefae82674d71ab1f1464622d199a6f72f30) [sql lab] fix partitionned table has no partitions (#2740) (@mistercrunch)
|
||||
- [e558444](https://github.com/airbnb/superset/commit/e5584440cecdb0d9a79ba6c4ff1050e73e774035) Speed up all CRUD list views (#2747) (@mistercrunch)
|
||||
- [d5e9d5d](https://github.com/airbnb/superset/commit/d5e9d5d045d342ef203c7d7cd480011626b6d7a1) fix auto select override pre-selected value bug (#2745) (@graceguo-supercat)
|
||||
- [3208a01](https://github.com/airbnb/superset/commit/3208a014ffccfe44238fb5982f6e391a1764d4b3) fix dual line chart margin (#2737) (@yileic)
|
||||
- [874c12a](https://github.com/airbnb/superset/commit/874c12ad2d99059b2f8f979bdd05e77d8768db03) 0.18.0-alpha.3 (@mistercrunch)
|
||||
- [22d8075](https://github.com/airbnb/superset/commit/22d8075c536bdfc1790b23381e0017720cc921a5) Making the stop button instantaneous (#2738) (@mistercrunch)
|
||||
- [baebba1](https://github.com/airbnb/superset/commit/baebba115930e95076e9252987fb4e107ddd23d5) 0.18.0-alpha.2 (@mistercrunch)
|
||||
- [04748b4](https://github.com/airbnb/superset/commit/04748b4cdac7a4fd53f5d7716a36ceebea7bf7ca) [SQL Lab] fix gamma metadata access (#2702) (@mistercrunch)
|
||||
- [a471afe](https://github.com/airbnb/superset/commit/a471afe206ca3357ea4c27c1accf94d44c8f5122) [sql lab] improvements to the left panel (#2709) (@mistercrunch)
|
||||
- [5d0a01d](https://github.com/airbnb/superset/commit/5d0a01d0d099a9d73ba04fded7cad223a10e86f2) Decimal is a valid numeric type (#2720) (@hajdbo)
|
||||
- [9e1272e](https://github.com/airbnb/superset/commit/9e1272e97c88a3ce2e8dfd15fa819de52e331342) 0.18.0-alpha.1 (@mistercrunch)
|
||||
- [aeebd88](https://github.com/airbnb/superset/commit/aeebd8840d0551a7cd9a2d43039dcd07648d66ed) [table] fixing CSS glitches on table view (#2725) (@mistercrunch)
|
||||
- [55d3b01](https://github.com/airbnb/superset/commit/55d3b012e504f788732488bf11a1ec7ef223a821) refactor: recentActions ajax call is redundant (#2722) (@S-YOU)
|
||||
- [a6e1e18](https://github.com/airbnb/superset/commit/a6e1e18244951b5bf68ac76e897a16713c7d279b) [sql lab] fix CREATE TABLE AS (#2719) (@mistercrunch)
|
||||
- [46d7a92](https://github.com/airbnb/superset/commit/46d7a925bb4be8891c89ac05d2f447e5ec750bf5) chore: remove unused methods with invalid models.Query usage (#2721) (@S-YOU)
|
||||
- [5929ab7](https://github.com/airbnb/superset/commit/5929ab76890232068bef5412f23a54226dbed0ec) [dashboard] fix missing datasource issue (#2718) (@mistercrunch)
|
||||
- [fffb7b5](https://github.com/airbnb/superset/commit/fffb7b500a313b9f9d76eecab18241bf0406c933) [sql lab]Add autoSelect (#2713) (@graceguo-supercat)
|
||||
- [cb14640](https://github.com/airbnb/superset/commit/cb14640a823c3c6cc768169391779064c2469a68) Removing uneeded results_backends.py (#2717) (@mistercrunch)
|
||||
- [d65054e](https://github.com/airbnb/superset/commit/d65054e01533f62e63e1c8788da4b97309f65cee) [sql lab] fix csv export where `%` in query (#2711) (@mistercrunch)
|
||||
- [5d5060e](https://github.com/airbnb/superset/commit/5d5060eca61ad1a7f6baf7adced2985088c82d95) Remove unecessary handling of %% (#2714) (@mistercrunch)
|
||||
- [9ff3515](https://github.com/airbnb/superset/commit/9ff351532ada993afc4da5060b9a942216e2a74b) Basic integration with ClickHouse (#1844) (@vavrusa)
|
||||
- [59a6f44](https://github.com/airbnb/superset/commit/59a6f447ec1e92a0319a617ecdf4e22847bf5d95) Fix missing curUserId from SliderAdder.jsx (#2705) (@songyanho)
|
||||
|
||||
### 0.17.6 (2017/05/01 20:13 +00:00)
|
||||
- [1887b5e](https://github.com/airbnb/superset/commit/1887b5e934b17864850a46d6e88a606b594e0634) 0.17.6 (@mistercrunch)
|
||||
- [33758bf](https://github.com/airbnb/superset/commit/33758bfff59b9cdc86b58973244ef0613942dc80) 0.17.6-alpha.2 (@mistercrunch)
|
||||
- [2d5beb1](https://github.com/airbnb/superset/commit/2d5beb1f91c304df948e943100cbfb66345a00e9) improve csrf expiration error handling (#2695) (@ascott)
|
||||
- [5fd0e7d](https://github.com/airbnb/superset/commit/5fd0e7d02828df4bb02b6a3b34779517fe637123) [vis] bar values should match y axis format (#2701) (@justinpark)
|
||||
- [ef0c4be](https://github.com/airbnb/superset/commit/ef0c4be06743083da5c33ed9ffbda7ff77b43e74) Fix for referring specific svg (#2612) (@songyanho)
|
||||
- [ac3aba7](https://github.com/airbnb/superset/commit/ac3aba7c7da905f0f4bfeb0f80efb87136812b90) [sql lab] visualization flow: fixing the groupby parameter (#2681) (@mistercrunch)
|
||||
- [0fdb57a](https://github.com/airbnb/superset/commit/0fdb57a18153912c2675b54a2c4e5e00691c7cc0) fix (#2696) (@yileic)
|
||||
- [3e7b5df](https://github.com/airbnb/superset/commit/3e7b5df2876d1014a8411a57cdd7bb18ce64e5d9) [explore] fix empty chart when changing viz type (#2698) (@mistercrunch)
|
||||
- [3cd16cf](https://github.com/airbnb/superset/commit/3cd16cf3680169dd17a542d83c84f94ca8220805) Fix test's warnings (#2697) (@dennybiasiolli)
|
||||
- [a58adc8](https://github.com/airbnb/superset/commit/a58adc862ec28842a3ac7f9f1f205fa1c173015e) Fix orm query in HiveEngineSpec.handle_cursor (#2699) (@xrmx)
|
||||
- [7d88f80](https://github.com/airbnb/superset/commit/7d88f80a9b2003f4529560160aea41c444283a9e) hack to dynamically adjust y axis left margin (#2689) (@yileic)
|
||||
- [09be02f](https://github.com/airbnb/superset/commit/09be02f70a716819332629144160360e21c8920b) fix x axis label (#2691) (@yileic)
|
||||
- [50fcdd3](https://github.com/airbnb/superset/commit/50fcdd3a34f3efe58435760ba0bf321d6767a3a5) Adding tails.com to inthewild (#2685) (@alanmcruickshank)
|
||||
- [dee3649](https://github.com/airbnb/superset/commit/dee36491c5e9394c19dfbc00def353675079aa83) Fix js warnings (#2693) (@dennybiasiolli)
|
||||
- [903612a](https://github.com/airbnb/superset/commit/903612ac6c802dd042417c1fa8a742812a2094bb) fix (#2692) (@yileic)
|
||||
- [ce70505](https://github.com/airbnb/superset/commit/ce705054fa2e738612d746c8f07b577f6941a6e3) fix a bug in 'getMaxLabelSize' and x axis label not shown problem (#2694) (@yileic)
|
||||
- [c589616](https://github.com/airbnb/superset/commit/c5896168830c0901a6488817d970a92ce3fa8f9a) [sql lab] Update event handler name (#2680) (@graceguo-supercat)
|
||||
- [58309f2](https://github.com/airbnb/superset/commit/58309f275f3b9d123f75e795fe3e42b918a66aab) Mark a few more string for translation (#2651) (@xrmx)
|
||||
- [edf4e4f](https://github.com/airbnb/superset/commit/edf4e4f24e9eeceb44e2b9a98d2cb02d8cefa6dd) Update README.md (#2676) (@aioue)
|
||||
- [b3e0b5b](https://github.com/airbnb/superset/commit/b3e0b5b586d530cdd1def10ef38550f680f1922b) Specifying cryptography version in install docs (@mistercrunch)
|
||||
- [6880298](https://github.com/airbnb/superset/commit/68802989bc8a13f76988eed004dc07fa06208733) Pinning cryptography lib to 1.7.2 (@mistercrunch)
|
||||
- [70887d7](https://github.com/airbnb/superset/commit/70887d72e2a54fdae2ba58ad8f408528bd694878) 0.17.6-alpha.1 (@ascott)
|
||||
- [1922225](https://github.com/airbnb/superset/commit/192222504292aed3ffa7368f85ca6cdc7f92aab5) Alternate fix for #2665 (#2671) (@mistercrunch)
|
||||
- [0bdc301](https://github.com/airbnb/superset/commit/0bdc3010d8da0789df99d588105d6e62cc6b3280) [vis] fix pivot table scrolling when using more than 1 groupy col (#2674) (@ascott)
|
||||
- [1df37e6](https://github.com/airbnb/superset/commit/1df37e6e4d609f7c0751faf2360a98a896e30f46) add option for pulling favourited dashboards by username (#2661) (@robert-digit)
|
||||
- [e9ed416](https://github.com/airbnb/superset/commit/e9ed4166549cb515f5c15357b2395c3858736df1) fix csrf error on import_dashboards (#2672) (@ascott)
|
||||
- [03c42b5](https://github.com/airbnb/superset/commit/03c42b5b87429f2a29ce1b5ef8c13e9a004b907e) Showing slices on datasource edit form (#2645) (@mistercrunch)
|
||||
- [e055e6d](https://github.com/airbnb/superset/commit/e055e6d2c22e6087bf7c906174c08d543617a514) Fixing PropTypes warning messages (#2670) (@mistercrunch)
|
||||
- [2978082](https://github.com/airbnb/superset/commit/29780821e8797fee3fbcbcfacbe3e0871750d19b) [druid] fixing the having clause in the explore view (#2648) (@mistercrunch)
|
||||
- [f10ee13](https://github.com/airbnb/superset/commit/f10ee139011767fd72e20ff0fb6a6411f6b06d6b) [druid] fix FilterBox viz gets timestamps as values if granularity != all (#2647) (@mistercrunch)
|
||||
- [cdfc4a3](https://github.com/airbnb/superset/commit/cdfc4a35b22e8b07bf2b0503214074761143e7d9) Optimizing the standalone view (#2663) (@mistercrunch)
|
||||
- [eb762c8](https://github.com/airbnb/superset/commit/eb762c8bfec56a0da664c4aa71baf2197f58042f) add the missing right bracket (#2662) (@yileic)
|
||||
- [83abfef](https://github.com/airbnb/superset/commit/83abfef8304a8fe83248d959136e7421ba0e04a8) superset: fix argument swap for SqliteEngineSpec.get_table_names (#2664) (@xrmx)
|
||||
- [54137ad](https://github.com/airbnb/superset/commit/54137ad023f046780bd0e2089ccc57620787f118) Updating CHANGELOG (@mistercrunch)
|
||||
|
||||
### 0.17.5 (2017/04/21 20:56 +00:00)
|
||||
- [4be6bfa](https://github.com/airbnb/superset/commit/4be6bfafaa07695cf47a9a27977855ab30ff87e4) 0.17.5 (@mistercrunch)
|
||||
- [9ba6d48](https://github.com/airbnb/superset/commit/9ba6d489f31d2aba38594dac3cb7d75fbabcdc78) v0.17.5-alpha.10 (#2654) (@ascott)
|
||||
- [af4bd40](https://github.com/airbnb/superset/commit/af4bd40853d477e5104d62c81931b65be0026b50) fix scrolling on markup vis (#2644) (@ascott)
|
||||
- [84fa0d1](https://github.com/airbnb/superset/commit/84fa0d19407d7fe662ea1945bb0f9e2570945e50) don't default sort by to first column (#2653) (@ascott)
|
||||
- [938e13a](https://github.com/airbnb/superset/commit/938e13a4297f13354ae7a989de1268cddbf042c4) [hotfix] Presto's latest_sub_partion rendering fail (@mistercrunch)
|
||||
- [dc364da](https://github.com/airbnb/superset/commit/dc364daffddd740bd827aaaa71d07c13a928c7ef) [query-search] fix scrolling on query search and pagination styling (#2646) (@ascott)
|
||||
- [1cadfec](https://github.com/airbnb/superset/commit/1cadfecd4bc0c69e0c66ddce12727fd5607b4364) update core.py label and zh po file (#2642) (@RoganW)
|
||||
- [5b26667](https://github.com/airbnb/superset/commit/5b26667fd520ccf2b668f9d3f7b1a928a1bdaba7) 0.17.5-alpha.9 (@ascott)
|
||||
- [899caf9](https://github.com/airbnb/superset/commit/899caf94497e22ab8d6a59f695d3805999ab2e4c) [sql-lab] fix scrolling in left hand panel for table meta data (#2641) (@ascott)
|
||||
- [e6063f2](https://github.com/airbnb/superset/commit/e6063f2ddf14ae9ddb8c9fd8b5ebd548e272e7d5) 0.17.5-alpha.8 (@mistercrunch)
|
||||
- [46486f8](https://github.com/airbnb/superset/commit/46486f82d9352cd7d340e4dfb6bd9ba2676b2c6c) Moving the warning message to the navbar (#2640) (@mistercrunch)
|
||||
- [0089762](https://github.com/airbnb/superset/commit/00897629558a4d89c5a500b173b345d8136f52fa) 0.17.5-alpha.7 (@ascott)
|
||||
- [2bd60c0](https://github.com/airbnb/superset/commit/2bd60c074716faf57a8a10e3a9c73b9fe500080f) [vis] fix line chart when slice is really narrow (#2620) (@ascott)
|
||||
- [db6cd21](https://github.com/airbnb/superset/commit/db6cd215040220f3cf3636f1decb25139f395cad) [sqllab] table refactor (#2587) (@ascott)
|
||||
- [f40499e](https://github.com/airbnb/superset/commit/f40499e550ae3ed7fea534b8c657c2c76d9f6070) [dashboard] improve error handling on dashboard (#2624) (@mistercrunch)
|
||||
- [67a85b9](https://github.com/airbnb/superset/commit/67a85b9831f86a78fe987037000c8f2e6bd9c7d7) Fix dashboard edit button is disabled (#2634) (@mistercrunch)
|
||||
- [cb3384b](https://github.com/airbnb/superset/commit/cb3384b3b225c1c392453616ce09c1c9e7136baa) Improving Presto error message in explore/dashboard (#2633) (@mistercrunch)
|
||||
- [ac51a30](https://github.com/airbnb/superset/commit/ac51a30f98019d8cc593f03cd0f542aa35646889) Remove metrics control non-null validator in Table context (#2635) (@mistercrunch)
|
||||
- [91fe02c](https://github.com/airbnb/superset/commit/91fe02cdc879097d517cddc06a8492536bc3b6ea) Setting adjust_database_uri for HiveEngineSpec (#2636) (@mistercrunch)
|
||||
- [76042be](https://github.com/airbnb/superset/commit/76042be7c3b52c5019114b372dc841137205e14f) [hotfix/sqllab] setting up the connection in the try: block (@mistercrunch)
|
||||
- [d3f55a0](https://github.com/airbnb/superset/commit/d3f55a0905e4aa7a2da22113ea8e25c174903c9f) 0.17.5-alpha.6 (@mistercrunch)
|
||||
- [efaef8f](https://github.com/airbnb/superset/commit/efaef8fe0924ff39e77edbe8fe5e2ed337adccf3) [hotfix] fix endpoint (@mistercrunch)
|
||||
- [8757a24](https://github.com/airbnb/superset/commit/8757a24d89e44c13b44b8ae84be9ae12a50b8d48) 0.17.5-alpha.5 (@mistercrunch)
|
||||
- [63785f0](https://github.com/airbnb/superset/commit/63785f039c0f7763c410c9e7a40a0d477b9bf23a) [hotfix] using UTC for caching timestamps (@mistercrunch)
|
||||
- [d6689ee](https://github.com/airbnb/superset/commit/d6689ee700102926ebd7efa352cb3c66d970445f) 0.17.5-alpha.4 (@mistercrunch)
|
||||
- [787daf6](https://github.com/airbnb/superset/commit/787daf6005d325b68a52644804d802a1168cf314) A nice CacheLabel React component (#2628) (@mistercrunch)
|
||||
- [23aeee5](https://github.com/airbnb/superset/commit/23aeee5a9c1c17ef486fa5106da964acc0b4bd43) Slice level cache_timeout isn't taken into consideration (#2631) (@mistercrunch)
|
||||
- [70c6cad](https://github.com/airbnb/superset/commit/70c6cad0e3b5e276158c1d9057de40b6fd9498eb) Add UNIX socket option to runserver (#2627) (@scaba)
|
||||
- [6b1bf3b](https://github.com/airbnb/superset/commit/6b1bf3b395a61a8549b9f3297c8411bb41db52fa) [hotfix] missing explore's main.css (@mistercrunch)
|
||||
- [f5216f6](https://github.com/airbnb/superset/commit/f5216f60479a2580b5a5532ec8c1b0882905d7a0) Adding owner(s) to dashboard makes them own underlying slices (#2610) (@mistercrunch)
|
||||
- [15654a3](https://github.com/airbnb/superset/commit/15654a3082f4d6030fafd38d671299670443374e) fix filters on dashboard (#2619) (@ascott)
|
||||
- [baff0cb](https://github.com/airbnb/superset/commit/baff0cba38554ae28e1024f2114ee5765648c45b) Fix separator widget CSS (#2623) (@mistercrunch)
|
||||
- [c4ee098](https://github.com/airbnb/superset/commit/c4ee098bb7ffc0db970eba608bfe464ee7b3e60b) 0.17.5-alpha.3 (@mistercrunch)
|
||||
- [612b8ca](https://github.com/airbnb/superset/commit/612b8ca3d7de9988f22b8f7f81c583ff0b8b19bc) [hotfix] legacy url not handled properly (@mistercrunch)
|
||||
- [c43a9fd](https://github.com/airbnb/superset/commit/c43a9fd5541d5de0987607d913eddd899ee84e75) [hotfix] fixing the build (@mistercrunch)
|
||||
- [6c68a21](https://github.com/airbnb/superset/commit/6c68a21e4f77757df57042eedbb91a96b21fa040) [sql lab] fix alt-enter runs out-of-date SQL (#2603) (@mistercrunch)
|
||||
- [db02b33](https://github.com/airbnb/superset/commit/db02b33e09dd6391fb1d8f777b19d5c16a511abe) [explore] fix query text modal while loading (#2596) (@mistercrunch)
|
||||
- [2df6baa](https://github.com/airbnb/superset/commit/2df6baa7a741a4bfff786b0f675f1165b122aaac) [sql lab] sorting database names in dropdowns (#2611) (@mistercrunch)
|
||||
- [fc7bd63](https://github.com/airbnb/superset/commit/fc7bd630399c9f4f936b59be347d5d4d0e516744) [sql lab] fixes issues specific to Sqlite (#2606) (@mistercrunch)
|
||||
- [959a09c](https://github.com/airbnb/superset/commit/959a09cc92682854e0051fae302bd866d9d5b8b5) [dashboard] fix css padding for markup viz (#2602) (@mistercrunch)
|
||||
- [366ecef](https://github.com/airbnb/superset/commit/366ecefbaaf4cc31234cc981ebab7eb420efe019) Bumping the JS libs to fix the build (#2616) (@mistercrunch)
|
||||
- [a2b30f3](https://github.com/airbnb/superset/commit/a2b30f35fcc3c081448d55df31ad445d4d9cec6c) 0.17.5-alpha.2 (@mistercrunch)
|
||||
- [8bceda8](https://github.com/airbnb/superset/commit/8bceda8134c6e53f62b5b30910ec0eeb02f051e7) [hotfix] fix iframe viz (@mistercrunch)
|
||||
- [bae1067](https://github.com/airbnb/superset/commit/bae1067015a4b8041d39b806062a45c1950e3f7c) 0.17.5-alpha.1 (@mistercrunch)
|
||||
- [116dca3](https://github.com/airbnb/superset/commit/116dca3e6fc78ef109f0385b6c4dbf2650dda080) validationErrors is undedfined (@mistercrunch)
|
||||
- [b448394](https://github.com/airbnb/superset/commit/b448394077eef18b9ed01c9703c58cf05f14d34c) 0.17.5-alpha.0 (@mistercrunch)
|
||||
- [09f407f](https://github.com/airbnb/superset/commit/09f407f553eb8bca90f6da79cf60c742296488c7) add tooltips to big number vis (#2599) (@ascott)
|
||||
- [0479118](https://github.com/airbnb/superset/commit/0479118efc0069da2b62c20dc631ebbd00493758) 0.17.5.dev0 (@mistercrunch)
|
||||
- [c93411b](https://github.com/airbnb/superset/commit/c93411b1e75bc59b174d1256f3108d783eea3264) Fix for merge string as array (#2597) (@songyanho)
|
||||
- [31283f1](https://github.com/airbnb/superset/commit/31283f14246ccd9f7cac4df238bd65cdd68c840b) Fix metric formating in Dashboard view + some refactoring (#2598) (@mistercrunch)
|
||||
- [93c6597](https://github.com/airbnb/superset/commit/93c6597cf4f2c47869f9cf4f62cfdbe80cd37760) Adding docs/ to .eslintignore (@mistercrunch)
|
||||
- [4446c74](https://github.com/airbnb/superset/commit/4446c745a88d4b31de8a30ccb45b4cd6dcc49dae) Fix backend-sync 2 (@mistercrunch)
|
||||
- [38e90fe](https://github.com/airbnb/superset/commit/38e90fe3098018655a8e2206a053c60c8d7e64aa) Fix backend-sync (@mistercrunch)
|
||||
- [f548946](https://github.com/airbnb/superset/commit/f5489467e534f3625079843cad82ae12de6cbf3a) Use correct dialect for escaping functions. (#2593) (@steveniemitz)
|
||||
- [ab0bc5a](https://github.com/airbnb/superset/commit/ab0bc5a3fa81f3951b50828400de6bfc54235860) handle percentage case for tooltips (#2570) (@ascott)
|
||||
- [412634c](https://github.com/airbnb/superset/commit/412634cb57f6094bbba168d252b8b5dbd56da954) Add missing flask-wtf dependency (#2586) (@xrmx)
|
||||
- [a0ddbb9](https://github.com/airbnb/superset/commit/a0ddbb9ec954a65a77350bc054b83e35bc4dffeb) Make form_data dict a macro (#2585) (@mistercrunch)
|
||||
- [a803705](https://github.com/airbnb/superset/commit/a803705ddca1c869ccd50977d033faa5c8a0464b) [bugfix] clarifying how to create a slice (#2565) (@mistercrunch)
|
||||
- [75a358c](https://github.com/airbnb/superset/commit/75a358c616bf30e15dc752da59de1c3cd333a89c) [explore] force control validation before runQuery (#2544) (@mistercrunch)
|
||||
- [493ba18](https://github.com/airbnb/superset/commit/493ba1836241146502d5dfa4d5c9ea57f4d8ad6c) Adding macros current_user_id & current_username (#2582) (@mistercrunch)
|
||||
- [5e4fca4](https://github.com/airbnb/superset/commit/5e4fca4ea4b896a9c427032f30a30b59efbcec63) Bumping a set of Python libraries to the latest release (#2575) (@mistercrunch)
|
||||
- [d289783](https://github.com/airbnb/superset/commit/d289783b67ef6503f58a330bcd729e3301c20393) Adding Vertica to installation docs (#2581) (@mistercrunch)
|
||||
- [ac84fc2](https://github.com/airbnb/superset/commit/ac84fc2b65976c1473488e2ed47979d880df34f5) Fixing confusion when selecting schema across engines (#2572) (@mistercrunch)
|
||||
- [40b3d3b](https://github.com/airbnb/superset/commit/40b3d3b3ef61124ec38d49130b57d751b98a1a67) [hotfix] add csrf_token api endpoint (@mistercrunch)
|
||||
- [50a9e13](https://github.com/airbnb/superset/commit/50a9e13f9bb9bf0c10ca3b748e1989a15c97ee8a) [hotfix] add csrf_token api endpoint (@mistercrunch)
|
||||
- [66bff01](https://github.com/airbnb/superset/commit/66bff01b45658547d9853e0d0c22e788550d8267) Changelog for 0.17.4 (@mistercrunch)
|
||||
- [9691234](https://github.com/airbnb/superset/commit/9691234b7e33d8162253a6971f6eb298c037b748) [hotfix] casting db_id to int (@mistercrunch)
|
||||
|
||||
### 0.17.4 (2017/04/07 17:57 +00:00)
|
||||
- [ddeabdd](https://github.com/airbnb/superset/commit/ddeabdd048296732c24bb7ca2317e5d3683fa17d) Fixing CSRF issues (#2569) (@mistercrunch)
|
||||
- [3ed45ab](https://github.com/airbnb/superset/commit/3ed45ab98c2e351ced9520bcfce222dd34d45a94) [bugfix] saved query restore wouldn't pick the db (#2568) (@mistercrunch)
|
||||
- [ca08e70](https://github.com/airbnb/superset/commit/ca08e7051ef47b5a8693dc5088c3af23b582b267) 0.17.4rc5 (@mistercrunch)
|
||||
- [1fb21b8](https://github.com/airbnb/superset/commit/1fb21b8b45f1bdde4e89386ec791cfa7620986c4) [revert] reverting big num changes (#2567) (@ascott)
|
||||
- [c581ea8](https://github.com/airbnb/superset/commit/c581ea8661dd229f42d5959a6745a26ce8f03289) Alternative PR for: Some bytes/str issues in py3 w/ zlib and json (#2558) (@rumbin)
|
||||
- [f19d195](https://github.com/airbnb/superset/commit/f19d1958c51212ae19cef98cfa135b8898cb6bea) INTHEWILD: added Endress+Hauser (#2562) (@rumbin)
|
||||
- [9c99be5](https://github.com/airbnb/superset/commit/9c99be510b3aaeb4329e1a33413129e1aaacebdd) [hotfix] iframe viz is broken (@mistercrunch)
|
||||
- [7a08cdc](https://github.com/airbnb/superset/commit/7a08cdcb1c4378986cb1dc6934143a684ab49502) 0.17.4rc3 (@ascott)
|
||||
- [f24ddfd](https://github.com/airbnb/superset/commit/f24ddfd467731d82206b5cf8185ac0c576a8a6f9) [big num] make sure scatterplot dots align properly (#2559) (@ascott)
|
||||
- [23a8ea5](https://github.com/airbnb/superset/commit/23a8ea563693bd10635e0dadd97403958ca9d891) v0.17.4rc2 (@mistercrunch)
|
||||
- [2c04d3c](https://github.com/airbnb/superset/commit/2c04d3c25098d15c9cc6f30a70f787eae6899c74) [bugfix] save dash fails with CSRF related error (#2552) (@mistercrunch)
|
||||
- [337454b](https://github.com/airbnb/superset/commit/337454b646c71bc313714b849dec49b4d7459a4d) [hotfix] slice with missing datasource related (@mistercrunch)
|
||||
- [b7f46eb](https://github.com/airbnb/superset/commit/b7f46ebe75b23d5a26d3c17fd219e1b05bff9327) [hotfix] dashboard fails when a slice is missing its datasource (@mistercrunch)
|
||||
- [10773f9](https://github.com/airbnb/superset/commit/10773f96a7197197bcd5d6dea6d959c081d23156) URL Params macro (#2537) (@mistercrunch)
|
||||
- [b97a827](https://github.com/airbnb/superset/commit/b97a8275d48c40beaff0a6fb7cf56257dd281fe6) Clarify docs on Redis package required for caching (#2557) (@rhunwicks)
|
||||
- [081bdca](https://github.com/airbnb/superset/commit/081bdca71ef4979b77e0b7d5f9ab5cc8e6cde2dc) [hotfix] [sql lab] fix sqlite errors when schema is selected (@mistercrunch)
|
||||
- [62959ca](https://github.com/airbnb/superset/commit/62959ca38ba31e5cc5a1d2b7b9e16bf981f97300) Db2 Grain Correct Data Format (#2545) (@openmax)
|
||||
- [fe68bc3](https://github.com/airbnb/superset/commit/fe68bc31c334e553131cf6e7f6da7d2359646f6c) Revert "measure x axis labels too and use the longest to determine margins" (#2550) (@ascott)
|
||||
- [3d2c791](https://github.com/airbnb/superset/commit/3d2c791ff1279af4c19108ee220a37c24710686a) [bug num vis] fix sizing for single digits (#2548) (@ascott)
|
||||
- [d40ce52](https://github.com/airbnb/superset/commit/d40ce52139d7b9319ac8b86e5d77d3f4998b5926) v0.17.4rc1 (@mistercrunch)
|
||||
- [122891c](https://github.com/airbnb/superset/commit/122891c29b8f46c986207d4903ae584b0ac44a8e) [sql lab] allow users to save their queries (#2528) (@mistercrunch)
|
||||
- [c1d9918](https://github.com/airbnb/superset/commit/c1d9918abeb3bca33721fc5af9be59e89fffccbf) [vis] bug num improvements (#2523) (@ascott)
|
||||
- [d93b1fc](https://github.com/airbnb/superset/commit/d93b1fc686e0f0518b04203e1b65967f6b84d441) [sql-lab] make query history scrollable (#2499) (@ascott)
|
||||
- [02c5cac](https://github.com/airbnb/superset/commit/02c5cac26f853634bb0d244579c366abcb400c77) [hotfix] adding filterable to DruidColumnInlineView.edit_columns (@mistercrunch)
|
||||
- [6566377](https://github.com/airbnb/superset/commit/65663777402c6770b796ca3f65fedc59d756da82) [sql lab] fix table dropdown with large schema make UI unresponsive (#2547) (@mistercrunch)
|
||||
- [db6b2f3](https://github.com/airbnb/superset/commit/db6b2f3ae19740c86a537f031ec7fbee4b341742) pylint errors will now break the build (#2543) (@mistercrunch)
|
||||
- [c31210b](https://github.com/airbnb/superset/commit/c31210b96d0b3aa96e826657da6e6754c87e59a0) Some column description clarifications (#2536) (@mistercrunch)
|
||||
- [dcc6f2a](https://github.com/airbnb/superset/commit/dcc6f2a18fadda5ddb1a507508cf049b9932f02b) serve roboto font locally (#2519) (@ascott)
|
||||
- [0c0666c](https://github.com/airbnb/superset/commit/0c0666caa0e7ce5725416115389fe797113b731c) druid: use six.string_types instead of basestring (#2541) (@xrmx)
|
||||
- [243eead](https://github.com/airbnb/superset/commit/243eeadfd6994c6ac93467a334601fb23278888f) installation instructions for AWS Athena (#2538) (@dwa)
|
||||
- [9ba5b49](https://github.com/airbnb/superset/commit/9ba5b49d8ac197a5ba908b229bd9061ce98c5fca) WIP: Initial commit to support the athena DB (#2531) (@dwa)
|
||||
|
||||
### 0.17.3 (2017/04/01 23:55 +00:00)
|
||||
- [c870bd4](https://github.com/airbnb/superset/commit/c870bd414ecafe9b83f223dd5894544dc34fba0f) 0.17.3 (@mistercrunch)
|
||||
- [4b01e92](https://github.com/airbnb/superset/commit/4b01e92509a903bcc25260749ee055be12e5949c) [dashboard] allow bar charts to scroll on x axis (#2513) (@mistercrunch)
|
||||
- [513a090](https://github.com/airbnb/superset/commit/513a090cdc852c287c62c5d4dc47d6168974251c) [sql lab] address lingering spinner in schema select (#2512) (@mistercrunch)
|
||||
- [abe79d1](https://github.com/airbnb/superset/commit/abe79d1427b94fb126bd3aec5511bbe2c905d94c) Deprecate is_featured as a datasource attribute (#2485) (@mistercrunch)
|
||||
- [b81968d](https://github.com/airbnb/superset/commit/b81968dc2051d0cef22da1633fb315f076c7d94c) Redirect to explore view when saving a table (#2479) (@mistercrunch)
|
||||
- [66cc546](https://github.com/airbnb/superset/commit/66cc546a300d63dd06385a0c35e2268453f70fd6) [hotfix] fixing the (one js lint err in the) build (@mistercrunch)
|
||||
- [6e899ac](https://github.com/airbnb/superset/commit/6e899ac55f5fe093a9081c4001e28b945bc0f8f6) added tobii (#2526) (@dwa)
|
||||
- [6b52384](https://github.com/airbnb/superset/commit/6b523840244ae55519641e621d83aac1342fc51b) [hotfix] fix pending queries race condition (@mistercrunch)
|
||||
- [0a1d8db](https://github.com/airbnb/superset/commit/0a1d8db35783d37c2eea774f2e0c3b4d6a064fde) v0.17.3rc3 (@mistercrunch)
|
||||
- [6f68ddb](https://github.com/airbnb/superset/commit/6f68ddb50516efff1525f6aebc28f67dbad8c38b) Adding to polling states (@mistercrunch)
|
||||
- [4f59abf](https://github.com/airbnb/superset/commit/4f59abf189f9b34654854607c5f943e774fbccbe) v0.17.3rc2 (@mistercrunch)
|
||||
- [5c441f4](https://github.com/airbnb/superset/commit/5c441f4ddb84a58080b577497760ea65b7537f53) [hotfix] queries trigger polling (#2517) (@mistercrunch)
|
||||
- [be023ab](https://github.com/airbnb/superset/commit/be023aba8d972ad5460beed07f768f10398621c4) 0.17.3rc1 (@mistercrunch)
|
||||
- [5399020](https://github.com/airbnb/superset/commit/53990201bc97ad2035e10500eda0d4c935f3bfb1) forgotten query_datasources_by_name function (#2497) (@wyndhblb)
|
||||
- [37783d6](https://github.com/airbnb/superset/commit/37783d685fe7c7b52a3188ace5f1504f8e2eb367) Updating CHANGELOG (@mistercrunch)
|
||||
|
||||
### 0.17.2 (2017/03/29 14:46 +00:00)
|
||||
- [25fdcac](https://github.com/airbnb/superset/commit/25fdcaca8b1dd32c05ecd7fd57d4cf32e8f72447) v0.17.2 (@mistercrunch)
|
||||
- [ce6e7c1](https://github.com/airbnb/superset/commit/ce6e7c135943130fb104b10d284aca93e4f2d4dc) [hotfix] missing logging import in db_engined_specs (@mistercrunch)
|
||||
- [9116766](https://github.com/airbnb/superset/commit/91167665b19ca094fd51dadf9538c12fd61bc55a) Track both query start time and button push time to track delay (#2502) (@mistercrunch)
|
||||
- [f374345](https://github.com/airbnb/superset/commit/f374345860f4a3e307ea1772b099ce038868aa71) Adding a .pylintrc file and a bit of linting (#2507) (@mistercrunch)
|
||||
- [d3b50cb](https://github.com/airbnb/superset/commit/d3b50cb92e046de316725f0e02fdd816573b6234) [explore] remove grey background in standalone mode (#2503) (@mistercrunch)
|
||||
- [a58194b](https://github.com/airbnb/superset/commit/a58194bdb06a966c6d642bdfa7c80195cc9cf996) 0.17.2rc4 (@mistercrunch)
|
||||
- [5f3484a](https://github.com/airbnb/superset/commit/5f3484ac5981f2dd6aa447cbc2e4f2a9afe4518c) Handle errors when the MQ is down (#2494) (@mistercrunch)
|
||||
- [e14b74f](https://github.com/airbnb/superset/commit/e14b74fdbf876aeeeea7baa125926dcf719a0098) [explore] fixing bugs in controls (#2496) (@mistercrunch)
|
||||
- [56f2885](https://github.com/airbnb/superset/commit/56f28859b7315767d3e312aa3777b777156a658d) Fixing filter_box css padding (#2498) (@mistercrunch)
|
||||
- [f3cdb3b](https://github.com/airbnb/superset/commit/f3cdb3b787b804071a8f183569027169e432cb46) Add ibm_db_sa TimeStamp and Datatime Grain Spec. (#2500) (@openmax)
|
||||
- [b35f6b0](https://github.com/airbnb/superset/commit/b35f6b0a94df2017b3bd908c6589d786f9feec6b) 0.17.2rc3 (@mistercrunch)
|
||||
- [5574cfe](https://github.com/airbnb/superset/commit/5574cfef59a7326487f7cebf9a575070ab19a3c2) Fixing out-of-sync security (#2493) (@mistercrunch)
|
||||
- [c301558](https://github.com/airbnb/superset/commit/c3015583ce09f259bf36e018ebd0820f9c0cb92f) Stabilizing master (#2478) (@mistercrunch)
|
||||
- [7cc2c93](https://github.com/airbnb/superset/commit/7cc2c930ede176242cc9066baf16c00fccd23e01) [docs] adding notes on the Public role (#2486) (@mistercrunch)
|
||||
- [2662bf1](https://github.com/airbnb/superset/commit/2662bf19df690c0a133318406a6935a27245a82f) v0.17.2rc2 (@mistercrunch)
|
||||
- [62e3fe2](https://github.com/airbnb/superset/commit/62e3fe2345afa6fa8b8cb0da7f20bb44b48a0e54) [hotfix] SqlaTable has no attribute column_cls (@mistercrunch)
|
||||
- [7d25d17](https://github.com/airbnb/superset/commit/7d25d171e29dce859c455a03d33cc4c3054775c7) [release] update to 0.17.2rc1 (#2492) (@ascott)
|
||||
- [c5859c7](https://github.com/airbnb/superset/commit/c5859c7254448d2cdbc877b00580bd95fa6e7e2e) [hotfix] druid queries 'There was no query executed' issue (@mistercrunch)
|
||||
- [dd7b4b8](https://github.com/airbnb/superset/commit/dd7b4b8310e27310f80a0415a2bd877f3098127b) Revert "[sql-lab] revert react-virtualized-select (#2489)" (#2491) (@ascott)
|
||||
- [93551a6](https://github.com/airbnb/superset/commit/93551a65b845f430aaefaa50f75a40857f1b6ed6) only fetch tables if we have a schema, otherwise reset options. (#2490) (@ascott)
|
||||
- [7eafbab](https://github.com/airbnb/superset/commit/7eafbabe65b430a2347ed6bba3e08d1f4d8c1946) [sql-lab] revert react-virtualized-select (#2489) (@ascott)
|
||||
- [43dd948](https://github.com/airbnb/superset/commit/43dd948476190cf75649164f57a9b73687ca3d99) [sql-lab] performance updates - make ui more responsive (#2469) (@ascott)
|
||||
- [75e7f2d](https://github.com/airbnb/superset/commit/75e7f2d22c7185f2a6393b7ded7a2b5d0558cfca) [hotfix] bumping QUERY_UPDATE_FREQ from 1000 to 2000ms (@mistercrunch)
|
||||
- [26662ee](https://github.com/airbnb/superset/commit/26662eed9e08475a4c41d715f5a3608876a1afd1) Fixed CSS syntax for background linear-gradient (#2482) (@songyanho)
|
||||
- [121b1d0](https://github.com/airbnb/superset/commit/121b1d0951049ac30ab35a225269c03451d14bbc) Refactoring more in the connector base classes (#2431) (@mistercrunch)
|
||||
- [398036d](https://github.com/airbnb/superset/commit/398036d77e0c817796e3735797eae56e80dce437) [hotfix] 'NoneType' object has no attribute 'upper' (@mistercrunch)
|
||||
- [59d5fcf](https://github.com/airbnb/superset/commit/59d5fcf88c0f484a189c7f02968982b2d39512ad) [hotfix] fixing checkboxes in Tables->Columns (@mistercrunch)
|
||||
- [1f8e48b](https://github.com/airbnb/superset/commit/1f8e48b374adb091bf41e60634e99b132a37bf62) [sqllab] assign types for visualize flow (#2458) (@mistercrunch)
|
||||
- [7bf19b1](https://github.com/airbnb/superset/commit/7bf19b12327504aec2be2c2fd36404efb1faec05) [WiP] making doubling '%' not required (#2459) (@mistercrunch)
|
||||
- [1590b8c](https://github.com/airbnb/superset/commit/1590b8c7e5a070183a3c0e3153aec63992e3c60f) Speeding up polling by not checking access (#2466) (@mistercrunch)
|
||||
- [22522fc](https://github.com/airbnb/superset/commit/22522fc05f8859b94299576f4a8b07bd42eaba00) [sql-lab] improve table select performance (#2457) (@ascott)
|
||||
- [c9b59fa](https://github.com/airbnb/superset/commit/c9b59fab1fded7fa08fc9d44a8c18427865e11dd) Update INTHEWILD.md (#2455) (@jakubczaplicki)
|
||||
- [69152e0](https://github.com/airbnb/superset/commit/69152e087a2b9900e53a8a97ed318c271f725649) [explore] remove 'SQL Clauses' section when using Druid (#2449) (@mistercrunch)
|
||||
- [652e572](https://github.com/airbnb/superset/commit/652e572b56054cefdfe83403db2125a9d85f5a6a) [sql-lab] make results table scroll in static container (#2426) (@ascott)
|
||||
- [65c89f5](https://github.com/airbnb/superset/commit/65c89f54dc845ee4f77b230fb334eba225bb14e6) [hotfix] merging db migration scripts (#2448) (@mistercrunch)
|
||||
- [edf5c0e](https://github.com/airbnb/superset/commit/edf5c0e83b2c9023ef3ad9cabc7ce19d32551d84) [dist_bar] fix x scroll when overflowing (#2440) (@mistercrunch)
|
||||
- [a4abbfe](https://github.com/airbnb/superset/commit/a4abbfe1266ab1593ba82ef23d6e733b3d8e8e33) Fix formatting in README.md (#2441) (@imagejan)
|
||||
- [7b28bce](https://github.com/airbnb/superset/commit/7b28bcef15cd37284780e605f5076ede2864afb4) Fix documentation for adding a Redshift database (#2447) (@alexdebrie)
|
||||
- [8042ac8](https://github.com/airbnb/superset/commit/8042ac876e80c08d72489287777cb1e9672b177a) [explore] improved filters (#2330) (@mistercrunch)
|
||||
- [82bc907](https://github.com/airbnb/superset/commit/82bc907088be26206a7c8d1c84311ca399eb73b9) fix a bug in pie chart (#2423) (@yileic)
|
||||
- [e2b572d](https://github.com/airbnb/superset/commit/e2b572d9e229fee503128cab8d7bff02a9cd881b) Prevent alarming users with stacktrace when using sqlite (@mistercrunch)
|
||||
- [e71596d](https://github.com/airbnb/superset/commit/e71596dc45f96e6a3fdfb09f5ee6b00a9cdd018c) make dualline thumbnail have consistent size as other thumbnails (#2434) (@yileic)
|
||||
- [c3be58d](https://github.com/airbnb/superset/commit/c3be58db437746c168e706e8a5710e2a1d363d0d) Add verbose name to db and druid cluster (#2429) (@bkyryliuk)
|
||||
- [3d77a12](https://github.com/airbnb/superset/commit/3d77a12aa9b27375a02f7092c16a2883bd171913) Display the first partition. (#2425) (@bkyryliuk)
|
||||
- [36deb8d](https://github.com/airbnb/superset/commit/36deb8da7157893d08d01148ab538f963aacf140) Allow users to alter column types (#2424) (@mistercrunch)
|
||||
|
||||
### 0.17.1 (2017/03/16 15:44 +00:00)
|
||||
- [05ee8c0](https://github.com/airbnb/superset/commit/05ee8c0e3675b0ab88cf85d061971177ed871144) v0.17.1 (@mistercrunch)
|
||||
- [5ca55a5](https://github.com/airbnb/superset/commit/5ca55a55858a59f6340284cfe4081fd26d2be489) [hotfix on dist_bar] bringing back overwritten handling of ints and tuples (@mistercrunch)
|
||||
- [1b330a8](https://github.com/airbnb/superset/commit/1b330a8c55f0ec114970855c6682627434216ab5) Use connector registry for metrics (#2420) (@bkyryliuk)
|
||||
- [696678c](https://github.com/airbnb/superset/commit/696678c9816d934c10243395e12e8483e2a42df0) Replace query once query response returned (#2415) (@vera-liu)
|
||||
- [20aec3c](https://github.com/airbnb/superset/commit/20aec3cfcad082f921cdfc347382b2d0d4a4fd54) Use connector registry to fetch the table column class. (#2419) (@bkyryliuk)
|
||||
- [4ded37e](https://github.com/airbnb/superset/commit/4ded37e71edf1306ee9652cf32324b5dc14a1328) [hotfix] handle missing or empty column type (@mistercrunch)
|
||||
- [0674ed8](https://github.com/airbnb/superset/commit/0674ed846c478bd97e7b6953c375b5a3ab26802b) Use list instead of numpy array (#2412) (@bkyryliuk)
|
||||
- [3107152](https://github.com/airbnb/superset/commit/3107152f5bb973b8b1a9c5cf3bc2bee1d7f47e0d) Revert "Preprocess the where clauses." (#2411) (@bkyryliuk)
|
||||
- [5b19528](https://github.com/airbnb/superset/commit/5b19528662f5ea645ead5b066144d69469ecbf7c) Display full name. (#2378) (@bkyryliuk)
|
||||
- [357773c](https://github.com/airbnb/superset/commit/357773c631ad39260109ec45d9c313d6d45cea89) Preprocess the where clauses. (#2405) (@bkyryliuk)
|
||||
- [5e43d07](https://github.com/airbnb/superset/commit/5e43d074c3be9b909fe0b473f00e743b4ba9d56e) [explore ] templating can now reference query elements (#2388) (@mistercrunch)
|
||||
- [08bdcd5](https://github.com/airbnb/superset/commit/08bdcd52b856f5ed6c91ab9c3805cf259223da0a) Fix bad d3.format metric setting and/or value === Infinity (#2399) (@mistercrunch)
|
||||
- [0b8522b](https://github.com/airbnb/superset/commit/0b8522be502988d8b9bf64a8ea203068adf5957d) [filter_box] fix time filter and inverted instantFilter (#2402) (@mistercrunch)
|
||||
- [c02a7fe](https://github.com/airbnb/superset/commit/c02a7fe7634b311c6f42968a9f7bafef147092e1) Add more tests to Save Modal specs (#2313) (@vera-liu)
|
||||
- [dcd5bde](https://github.com/airbnb/superset/commit/dcd5bdeb00b8333d67234bde79397b5195fbb8f9) fix unicode issues (#2308 #2282) (#2401) (@asdf2014)
|
||||
- [562b4f0](https://github.com/airbnb/superset/commit/562b4f04156f20a2aeec8d2c27758571d0aaa514) Do not silence error message for query. (#2396) (@bkyryliuk)
|
||||
- [6160a3f](https://github.com/airbnb/superset/commit/6160a3fdffdcebe618191462633414c0dff7de30) Implement stop query functionality. (#2387) (@bkyryliuk)
|
||||
- [0779da6](https://github.com/airbnb/superset/commit/0779da6d244c5686f6ab5faf2ef5067019266460) Keep column order in .csv (#2377) (@bkyryliuk)
|
||||
- [740624b](https://github.com/airbnb/superset/commit/740624ba01edcfa305d6ff0a2676d413e59377f4) Fix monthly time grain in sqllite (#2380) (@bkyryliuk)
|
||||
- [2969cc9](https://github.com/airbnb/superset/commit/2969cc9993325acc730b794f9d0d0b07fe1a60ec) Refactoring Druid & SQLa into a proper "Connector" interface (#2362) (@mistercrunch)
|
||||
- [9a8c3a0](https://github.com/airbnb/superset/commit/9a8c3a044710bcfc578b77b498af1f15685f2bca) [table] metric ordering is wrong in some cases (#2373) (@mistercrunch)
|
||||
- [e817382](https://github.com/airbnb/superset/commit/e817382efd5f18e09534a70f95cc47332288356e) Add more tests to Filter spec (#2315) (@vera-liu)
|
||||
- [422d1fe](https://github.com/airbnb/superset/commit/422d1feb3e2ac964b77cd9756ed0fc1293056373) 0.17.1rc2 (@mistercrunch)
|
||||
- [2b0cb2b](https://github.com/airbnb/superset/commit/2b0cb2b0a56d033cd59c13ae3326c3d922d53b22) Fix partition query (#2353) (@bkyryliuk)
|
||||
- [705d09d](https://github.com/airbnb/superset/commit/705d09d3d07e05e3a5e070d25a348a45288d7721) Remove duplicate (#2351) (@bkyryliuk)
|
||||
- [9114d86](https://github.com/airbnb/superset/commit/9114d86ecd0dbd0ad20c24d56f1fd29604de2047) Add hive to superset + monkey patch the pyhive (#2134) (@bkyryliuk)
|
||||
- [ad4a950](https://github.com/airbnb/superset/commit/ad4a950b5646abef823357274298014292af091f) Fixes filters emitted from table viz (#2335) (@mistercrunch)
|
||||
- [bd480e0](https://github.com/airbnb/superset/commit/bd480e0c6b9d5127d96d8c18fd53ebe6193aec70) Fix duplicate property DruidDatasource.database (#2348) (@mistercrunch)
|
||||
- [af3415b](https://github.com/airbnb/superset/commit/af3415b0406399ba41c1592d31440b722556f90b) [filter_box] option to delay filtering with apply button (#2338) (@mistercrunch)
|
||||
- [b4a96bd](https://github.com/airbnb/superset/commit/b4a96bd8409d38462ea14d2fbafa2f975defd741) Fix for RuntimeError: dictionary changed size during iteration (#2320) (@moranrf)
|
||||
- [9d8d421](https://github.com/airbnb/superset/commit/9d8d4213840cc07d95ac971437632aeae4ff58b5) [hotfix] fix world map (@mistercrunch)
|
||||
- [f6ffc00](https://github.com/airbnb/superset/commit/f6ffc007481c658293ae209982dfc369c0f82f95) Allow running Flask Blueprints alongside Superset (#2337) (@mistercrunch)
|
||||
- [e35016f](https://github.com/airbnb/superset/commit/e35016f07d3880cd557f48c72c617e68d61b125d) remove unneeded tooltip/description text (#2303) (@ascott)
|
||||
- [af8e252](https://github.com/airbnb/superset/commit/af8e2523a820080e06aaf3e50ff309ada1422bc6) fix version (#2336) (@ascott)
|
||||
- [492df94](https://github.com/airbnb/superset/commit/492df94b2a3a4767af40edfb5ab074632baaea4d) [sqllab] reserved words should be upper case (#2316) (@mistercrunch)
|
||||
- [b62f7e2](https://github.com/airbnb/superset/commit/b62f7e2820fc140a318b69b84c54a8a5fe965ed0) [version] use rc for production only releases (#2334) (@ascott)
|
||||
- [5cc2fc1](https://github.com/airbnb/superset/commit/5cc2fc157cfc2dc14363424533eade67e1f48543) v0.17.1 (#2333) (@ascott)
|
||||
- [266c049](https://github.com/airbnb/superset/commit/266c049f2df96bb7c815c91dd9f650fbefd6b513) Fix bug with breakdown (#2312) (@vera-liu)
|
||||
- [4e848c8](https://github.com/airbnb/superset/commit/4e848c8cb55be50c5c5ddbb58694b20d4223a2a3) Updating CHANGELOG (@mistercrunch)
|
||||
- [efff1ac](https://github.com/airbnb/superset/commit/efff1ac4a1d2b26ef932ac6937be0456fb901c09) Temp hack to make druid filters work in dashboard (#2300) (@vera-liu)
|
||||
- [fc64a75](https://github.com/airbnb/superset/commit/fc64a75fbd5a3aed7a62b741a9a057acb2b9dca8) v0.17.0 (#2298) (@vera-liu)
|
||||
|
||||
### 0.17.0 (2017/02/28 19:47 +00:00)
|
||||
0.17.0 introduces major changes that **YOU CANNOT ROLLBACK FROM**, take
|
||||
a backup of your app's database before starting the upgrade progress.
|
||||
|
||||
* **bookmarks:** the URL scheme for the explore view changed, but previous
|
||||
URLs are still supported, though there may be some edge cases there
|
||||
* **translations**: 0.17.0 has a major regression around translations as
|
||||
much of the logic in the explore view moved from the backend to the frontend
|
||||
where we currently do not have a translation framework setup. If
|
||||
translations are important to you, you should skip 0.17.* and get involved
|
||||
in getting translations to work well in future versions. `1.0` will have
|
||||
translations
|
||||
|
||||
- [dd9f431](https://github.com/airbnb/superset/commit/dd9f431b6fe6179ebdae015a375640adccb388c0) v0.17.0 (@mistercrunch)
|
||||
- [c894c54](https://github.com/airbnb/superset/commit/c894c54d00af8b6981c8aafcde02be7195973a38) [table] Allowing to show the time grain in table view (#2294) (@mistercrunch)
|
||||
- [4d349c7](https://github.com/airbnb/superset/commit/4d349c788559ee3fd7de6792d0e153b98d799487) [hotfix] Fix filter for sqlalchemy and druid (#2293) (@vera-liu)
|
||||
- [675b819](https://github.com/airbnb/superset/commit/675b819e0a2601b23e21b37aedf0b49757e218f4) Revert "[hotfix] Fix druid filters" (#2292) (@vera-liu)
|
||||
- [09f1083](https://github.com/airbnb/superset/commit/09f1083c509a690c1f5fcf68f9823fea661ba80f) [table viz] allow showing time granularity in table (#2284) (#2291) (@vera-liu)
|
||||
- [47be3ef](https://github.com/airbnb/superset/commit/47be3ef3ea385925b5ef67cdecb0ba36adc2b3db) Fixing bugs in Sankey diagrams (#2290) (@mistercrunch)
|
||||
- [9dd7778](https://github.com/airbnb/superset/commit/9dd7778597e3429c7bb93788172a2850dd33656e) [table viz] allow showing time granularity in table (#2284) (@mistercrunch)
|
||||
- [efffa92](https://github.com/airbnb/superset/commit/efffa925edf3f54f76acb03660a5b85728133004) rc7 (@mistercrunch)
|
||||
- [fa9bc92](https://github.com/airbnb/superset/commit/fa9bc92c9551669d5dc1fb99f06e8d49052938d1) [hotfix] filters broken on multi-datasource dashboards (@mistercrunch)
|
||||
- [227c66c](https://github.com/airbnb/superset/commit/227c66c2c50dd88bdc1ae4eb81dcd2f8189aea98) [hotfix] add regex for druid filters (#2288) (@vera-liu)
|
||||
- [e91bc9d](https://github.com/airbnb/superset/commit/e91bc9dfcceeb22b88efd57e6defe80d520079f0) added gcc-c++ for RHEL OS dependencies (#2286) (@soccerties)
|
||||
- [bc29035](https://github.com/airbnb/superset/commit/bc29035bdadad7c2df6d430661314a02d1bafea4) 0.16.1rc6 (@mistercrunch)
|
||||
- [f10e453](https://github.com/airbnb/superset/commit/f10e453c9bf0a0988769e7a5f126e94e40b50a49) Fixing bar charts x_axis labels (#2280) (@mistercrunch)
|
||||
- [d4b59b3](https://github.com/airbnb/superset/commit/d4b59b36a801e0f50cde85c15da0538848a5a202) Fixed a bug when querying with schema path to Redshift/Postgresql (#1789) (@sungjuly)
|
||||
- [4f644cd](https://github.com/airbnb/superset/commit/4f644cd0cae02af685cb12e42edc2875cb32acca) 0.16.1rc5 (@mistercrunch)
|
||||
- [ed2935e](https://github.com/airbnb/superset/commit/ed2935ec69d72765d66d8c9afe45e0a0b070cc6a) Fixing multi value parsing on old URL (#2277) (@mistercrunch)
|
||||
- [ea72c6b](https://github.com/airbnb/superset/commit/ea72c6b0188e9c5a662358e89c95801b319296f8) [bugfix] css editor dooesn't pop up (#2243) (@mistercrunch)
|
||||
- [2df6ab3](https://github.com/airbnb/superset/commit/2df6ab36bf5dab7366ff76fc8d9454cb62a49046) Add Udemy to INTHEWILD (#2275) (@sungjuly)
|
||||
- [10ea635](https://github.com/airbnb/superset/commit/10ea63557a29859e09cbc5bf93a539a9b9f3ea55) [hotfix] not grouped by -2 (@mistercrunch)
|
||||
- [55e462d](https://github.com/airbnb/superset/commit/55e462d90b0d01baca8d5c5f2877220b039524ce) 0.16.1rc3 (@mistercrunch)
|
||||
- [7339392](https://github.com/airbnb/superset/commit/73393925c0482007e498afa745be6d20d8c49b83) [hotfix] Table view doesn't allow SELECT (no group by) (#2274) (@mistercrunch)
|
||||
- [f9852bc](https://github.com/airbnb/superset/commit/f9852bc807f5335987d0d3d46c665b975a5fb0c1) v0.16.1rc2 (#2272) (@ascott)
|
||||
- [6e1901e](https://github.com/airbnb/superset/commit/6e1901e8e83d9e2a6e5fc20e3f8e3e996e1ea712) d is not defined, fix (#2270) (@ascott)
|
||||
- [8758296](https://github.com/airbnb/superset/commit/87582962d98424050ff6f61794fd42fe1f5c0c2f) [Hotfix] access slice_id when slice exists (#2268) (@vera-liu)
|
||||
- [3de2698](https://github.com/airbnb/superset/commit/3de2698657b389476a9778754fcbc6fb5acc6853) Introducing support for pre-depercate_v1 URL scheme (#2267) (@mistercrunch)
|
||||
- [ec1f022](https://github.com/airbnb/superset/commit/ec1f0221cd48bb168d0280f55082832d73583f04) Parse filter values for possible integers and floats (#2263) (@vera-liu)
|
||||
- [4d900c9](https://github.com/airbnb/superset/commit/4d900c9ee1e2ab2db0bf42a2c14268cf4ce91186) Do not add slice_name when slice doesn't exist (#2265) (@vera-liu)
|
||||
- [3a75890](https://github.com/airbnb/superset/commit/3a758900eb295039c52be89ecfc13e1260c9b1da) [hotfix] separator renders markdown (@mistercrunch)
|
||||
- [1ea7178](https://github.com/airbnb/superset/commit/1ea7178d17c5b2459e36d213611abcaac0b05620) v0.16.1rc1 (#2260) (@ascott)
|
||||
- [c85c998](https://github.com/airbnb/superset/commit/c85c9988df3d4bba2a9bce36ebfa681225400e42) fix index error for bar charts (#2258) (@ascott)
|
||||
- [34f6807](https://github.com/airbnb/superset/commit/34f68073a28d3dacc4162df7c0e2421cb527afe1) Default action to overwrite for users with overwrite permissions (#2257) (@vera-liu)
|
||||
|
||||
### 0.16.1 (2017/02/24 18:56 +00:00)
|
||||
- [acc880c](https://github.com/airbnb/superset/commit/acc880c4dfc2a02b8d46249895259961e2574c42) [v0.16.1] bump version for prod release (#2250) (@ascott)
|
||||
- [557b557](https://github.com/airbnb/superset/commit/557b557503b1835412337a4d0d4a574535133ec1) [bugfix] avoid caching errors (#2244) (@mistercrunch)
|
||||
- [3018356](https://github.com/airbnb/superset/commit/301835658838fc0d9cb2d807ee8fa06b0ed44550) Support more druid postaggregations. (#2235) (@bkyryliuk)
|
||||
- [ede4dff](https://github.com/airbnb/superset/commit/ede4dffcb71f6d31f9c062af4bcdeeaa9d4ca252) Add trailing slash (#2236) (@bkyryliuk)
|
||||
- [cad392e](https://github.com/airbnb/superset/commit/cad392eb768e65f11b664ad1e2aeffa9741e1bd4) Fetch schemas separately. (#2227) (@bkyryliuk)
|
||||
- [0296158](https://github.com/airbnb/superset/commit/02961581005ddb3abea89b38b1cce6af9247b8db) [docs] more specific about python versions (@mistercrunch)
|
||||
- [b2a4692](https://github.com/airbnb/superset/commit/b2a4692a02a2e6864aa1a8c66f7f63502be3e40e) 0.16.0rc3 (@mistercrunch)
|
||||
- [2fbadea](https://github.com/airbnb/superset/commit/2fbadea9e328554312742d7a8259d7f773ad314a) Fixing exploring a table (#2233) (@mistercrunch)
|
||||
- [dc05be3](https://github.com/airbnb/superset/commit/dc05be36a60237c930ca60184bbbc054182eeab1) Check if the query is in state first. (#2226) (@bkyryliuk)
|
||||
- [dac0d1d](https://github.com/airbnb/superset/commit/dac0d1d0dce2f5ab0c1d5b43814773688ef033c3) 0.16.0rc2 (@mistercrunch)
|
||||
- [459f716](https://github.com/airbnb/superset/commit/459f7160ac7587f92c8213b496fb64518329c1be) Fixing filtering issues (#2223) (@mistercrunch)
|
||||
- [aff524d](https://github.com/airbnb/superset/commit/aff524d84389b605e2f390350f4608f12ed67241) **Allow user to put dbname in url (#2209) (@vera-liu)
|
||||
- [3a91667](https://github.com/airbnb/superset/commit/3a91667e92e0b3bbadd0df4d35d03558268fb6d3) Update cache for the command line command. (#2213) (@bkyryliuk)
|
||||
- [3e0d358](https://github.com/airbnb/superset/commit/3e0d3584f77b2f493687c1c61af63fb4f321bd36) v0.16.0rc1 (@mistercrunch)
|
||||
- [1e47d6f](https://github.com/airbnb/superset/commit/1e47d6fb41b8095e2ab24704c8340c16cf8c13e6) Renaming field to control (#2210) (@mistercrunch)
|
||||
- [d5ba88b](https://github.com/airbnb/superset/commit/d5ba88b4072d45efbb82cc6492645627560794c1) Fixing the CACHING (#2203) (@mistercrunch)
|
||||
- [#2202](https://github.com/airbnb/superset/pull/2202) Merge pull request #2202 from mistercrunch/clean_cli (@mistercrunch)
|
||||
- [ec84aa7](https://github.com/airbnb/superset/commit/ec84aa75770b8a6c8f40f6519596571a5dfb48b5) Fixing typo (@mistercrunch)
|
||||
- [8b4d72c](https://github.com/airbnb/superset/commit/8b4d72cf32fbaa05a196995246090907e197bf7f) Reverting react-select to rc2 (@mistercrunch)
|
||||
- [85e6e65](https://github.com/airbnb/superset/commit/85e6e65a47e5d419b181876f2659038461b24974) Fixing the build (@mistercrunch)
|
||||
- [7cad365](https://github.com/airbnb/superset/commit/7cad3655f5f0638acc76e2a0396baeb28702906a) Bumping react-select to 1.0.0-rc.3 (@mistercrunch)
|
||||
- [b9e7f29](https://github.com/airbnb/superset/commit/b9e7f292c38610a23b75b57cf2ba04d1722fa94f) Cleaning up CLI stdout on startup (@mistercrunch)
|
||||
- [fc85034](https://github.com/airbnb/superset/commit/fc85034c60422d3b504e039e6af87dfd2608d12a) Better error handling for presto (#2161) (@vera-liu)
|
||||
- [f5e3d0c](https://github.com/airbnb/superset/commit/f5e3d0cc02628a51178001eecb65eaa6f04ec667) [hotfix] incompatible diamond flask-sqlalchemy version (@mistercrunch)
|
||||
- [fe377e8](https://github.com/airbnb/superset/commit/fe377e8b9472cc6d16cb2034c2876c758df7ba34) [hotfix] dashboard won't load, error in fields.js (@mistercrunch)
|
||||
- [5bb8713](https://github.com/airbnb/superset/commit/5bb87138e95a07f604e5b82dbac460b6ece06a40) [hotfix] Trends example slice is broken (@mistercrunch)
|
||||
- [579e582](https://github.com/airbnb/superset/commit/579e58206e16b53e49fc736569d6d4ab4e234f70) Bumping up some of the python lib deps (@mistercrunch)
|
||||
|
||||
### 0.16.0 (2017/02/17 01:48 +00:00)
|
||||
- [172b6ce](https://github.com/airbnb/superset/commit/172b6ce8920f79a78e19d49197864ac72ea6647a) v0.16.0 (@mistercrunch)
|
||||
- [0cc8eff](https://github.com/airbnb/superset/commit/0cc8eff1c3f4296bccf495c9deba01eb73b72b83) [WiP] Deprecate Explore v1 (#2064) (@mistercrunch)
|
||||
- [3b023e5](https://github.com/airbnb/superset/commit/3b023e5eaa7e5a4be7957a2a48a90672d2c65e71) add css to the data object to be saved (#2188) (@ascott)
|
||||
- [615d8f1](https://github.com/airbnb/superset/commit/615d8f1624d890f6ce0d5bfe7469394a9245759b) Moving branding assets to folder (@mistercrunch)
|
||||
- [b4409ac](https://github.com/airbnb/superset/commit/b4409ace2171158350ac6243e6b72bce6f89a864) Adding branding assets in the repo (@mistercrunch)
|
||||
- [dbee6ac](https://github.com/airbnb/superset/commit/dbee6aca1fbe2d48c685b3976acbb8dfff3f0624) use pre-wrap for long lines (#2181) (@ascott)
|
||||
- [acfe62e](https://github.com/airbnb/superset/commit/acfe62eaf793da4711a90cdb69aa6ec1ea292447) Add command to refresh datasources (#2180) (@bkyryliuk)
|
||||
- [527a8af](https://github.com/airbnb/superset/commit/527a8af060798c014cde0f9b32d31a2e6540dd57) Return original state for query if query was stopped (#2164) (@vera-liu)
|
||||
- [a5a931a](https://github.com/airbnb/superset/commit/a5a931a670871a9d6f1db9310512c5a064f005a0) Fix werkzeug instance was created twice in Debug Mode (#2135) (#2136) (@asdf2014)
|
||||
- [2f05efa](https://github.com/airbnb/superset/commit/2f05efaf121f6bbcd091f88630115a7e006717c4) Set default time range of query search to the past month (#2162) (@vera-liu)
|
||||
- [83ef8a2](https://github.com/airbnb/superset/commit/83ef8a2e1274ba57f1a64e5e71c94b021da4d933) Add parsing for nested json objects in resultset (#2163) (@vera-liu)
|
||||
- [c564881](https://github.com/airbnb/superset/commit/c564881867abcda7b8dc354e6e2205371ab0a97c) Implement caching and dynamic data fetching. (#1466) (@bkyryliuk)
|
||||
- [b16930f](https://github.com/airbnb/superset/commit/b16930f35dbba1a7d5e3a625dfb4a181cc3aa182) Keep order of axis data when storing df (#2092) (@vera-liu)
|
||||
- [2d910e3](https://github.com/airbnb/superset/commit/2d910e3f07b1e86efba69c6d8e07dbdb5f63ce37) [vis] render line breaks in TableViz (#2118) (@ascott)
|
||||
- [daa1420](https://github.com/airbnb/superset/commit/daa1420c8ec31a813d836474e3e2b04c4db54ab7) adding tests for #1131 (#1902) (@SalehHindi)
|
||||
- [cea310e](https://github.com/airbnb/superset/commit/cea310e50b61f3c8c37d86207dd982d35ba19e28) Using the time zone with specific name for querying Druid (#2143) (@asdf2014)
|
||||
- [fcdd5c6](https://github.com/airbnb/superset/commit/fcdd5c67523a81ffc6db68dbe27d13deb00b6084) [slices axis] fix axis spacing on dashboard and explore slices (#2145) (@ascott)
|
||||
- [2ace73e](https://github.com/airbnb/superset/commit/2ace73e9a1f1cf1a20eff632d08ea440f5f88607) [sql-lab] make datasource name in visualize flow more descriptive (#2103) (@ascott)
|
||||
- [80cfb08](https://github.com/airbnb/superset/commit/80cfb08794d3c8d91514f9b7731b057664628cf3) only call drawGraph once (#2132) (@ascott)
|
||||
- [1edc2b9](https://github.com/airbnb/superset/commit/1edc2b91cf15f669097939c36c6bc8acef5b5913) Fix ExtDeprecationWarning (#2137) (#2138) (@asdf2014)
|
||||
- [1f58e18](https://github.com/airbnb/superset/commit/1f58e18b6f134e2ad4c6865c6b63b40135889ebc) Some code refactoring (#2139) (@asdf2014)
|
||||
- [f2bf316](https://github.com/airbnb/superset/commit/f2bf3160583533bd0dc5004f248f81251aa8c57e) Add NUMERIC num_type (#2127) (@auxsvr)
|
||||
- [9cd38fa](https://github.com/airbnb/superset/commit/9cd38fa1eda63152c27b76c29dd948f29444b686) little code refactor in models.py (#2124) (@asdf2014)
|
||||
- [edb0111](https://github.com/airbnb/superset/commit/edb0111775a05ed164019246ee3d7764a9fdba67) Increase query limit to 1M, add separate display limit. (#2111) (@bkyryliuk)
|
||||
- [#2113](https://github.com/airbnb/superset/pull/2113) Merge pull request #2113 from airbnb/byolken/s3_cache_implementation (@airbnb)
|
||||
- [461e41c](https://github.com/airbnb/superset/commit/461e41cd610d1bff33ac10c6ea5879b498a16f41) Use BytesIO instead of StringIO for python2/3 compatibility
|
||||
- [7164061](https://github.com/airbnb/superset/commit/716406198e50b04d2f6600c518b01f65ad690748) Clean up imports of cPickle and StringIO
|
||||
- [68592ae](https://github.com/airbnb/superset/commit/68592aeddfdd88a2cb291533a9e595cff9b5d6d2) Fix StringIO import in results_backends module
|
||||
- [b927ff6](https://github.com/airbnb/superset/commit/b927ff6eef7e948be1f2a7e828f0d7de9458d2c2) Fix indentation errors in results_backends module
|
||||
- [ce50e6e](https://github.com/airbnb/superset/commit/ce50e6e4fe2147cdf61288d687d49e174f3b7b1d) Fix python3 cPickle import errors
|
||||
- [167ed33](https://github.com/airbnb/superset/commit/167ed33bba160f091e613bc2a351ca5ddc7c8189) Fix name of test in results_backends_tests module
|
||||
- [0ee1abf](https://github.com/airbnb/superset/commit/0ee1abf31a021d2c9e40d9b3c321fce14d4d7179) Misc. fixes in response to code review feedback
|
||||
- [6a0a1af](https://github.com/airbnb/superset/commit/6a0a1af67ebfc11fde51eb3d77db7b9ac6569c3c) Fix misc. style issues
|
||||
- [f85481d](https://github.com/airbnb/superset/commit/f85481d51b3481d7e0ee7f9b73991fb5e2b219ef) Fix long lines in superset/results_backends.py
|
||||
- [00b6b0a](https://github.com/airbnb/superset/commit/00b6b0ac68571df1a7c8e16fd0e79c64cbfe0a60) Misc. style tweaks to S3Cache changes and tests
|
||||
- [1546b1a](https://github.com/airbnb/superset/commit/1546b1ae716d47dad7c583100dbf73665d88aa3b) Add tests for S3Cache
|
||||
- [1e94498](https://github.com/airbnb/superset/commit/1e94498d9d548cbea6466a45dafa3b919c65bd1f) Add initial implementation of S3Cache
|
||||
- [0f7189b](https://github.com/airbnb/superset/commit/0f7189b859f4a782fd43af694012029645f81b44) Do not fail is the filter cannot be parsed. (#2105) (@bkyryliuk)
|
||||
- [a6e0f1b](https://github.com/airbnb/superset/commit/a6e0f1b75a5b60dbb81288b22d78d9686c3b565c) Add an option to configure celery workers size. (#2085) (@bkyryliuk)
|
||||
- [543c22b](https://github.com/airbnb/superset/commit/543c22bb508a90741ff770e50670b412a45e1871) [dashboard] fix nvd3 tooltips (#2096) (@ascott)
|
||||
- [07e067c](https://github.com/airbnb/superset/commit/07e067cf0b8fae39e5e7093914f0fc1795b15f41) Revert "Bump version to 0.15.4.1" (#2095) (@bkyryliuk)
|
||||
- [6c256a3](https://github.com/airbnb/superset/commit/6c256a34a98a9323f1044b138c458d5c60e0e01f) Bump version to 0.15.4.1 (#2094) (@bkyryliuk)
|
||||
- [6b2eb04](https://github.com/airbnb/superset/commit/6b2eb04a73a475b1d597076b15bc39c5e0156842) Put back a default count * metric (#2091) (@bkyryliuk)
|
||||
- [898d80b](https://github.com/airbnb/superset/commit/898d80ba3837b44c00092f9339fc0ba25efc3162) Viz the compiled query rather than user input. (#2086) (@bkyryliuk)
|
||||
- [ea8e4ad](https://github.com/airbnb/superset/commit/ea8e4ad05b7298db023c3cfb5079dff92a5da1d3) Display all columns if none are specified. (#2077) (@bkyryliuk)
|
||||
- [27aeac6](https://github.com/airbnb/superset/commit/27aeac6859da39fea0aebc4920c1fce08fde61e5) Remove fetch results button for async queries (#2084) (@vera-liu)
|
||||
- [8da371e](https://github.com/airbnb/superset/commit/8da371e324e490bec74d80eb84ca040c86dd6765) Make show query button work for v1 (#2080) (@vera-liu)
|
||||
- [0c59fe9](https://github.com/airbnb/superset/commit/0c59fe933d0012eb63acfa02bb51273327b4e218) Only call topn when having_filters don't exist (#2075) (@vera-liu)
|
||||
- [e169c67](https://github.com/airbnb/superset/commit/e169c67760b8ef3b0cafa3eebaf17ea662589ea4) [vis] fix axis labels display (#2066) (@ascott)
|
||||
- [3a5a927](https://github.com/airbnb/superset/commit/3a5a927dc6e43fe095a0b5592505cea09c42f5e4) check if tempTable exists for ctas queries (#2073) (@vera-liu)
|
||||
- [2d419e4](https://github.com/airbnb/superset/commit/2d419e4253c8a8874c1a913b4193402c3a4e0187) Return alert instead of fetch button when async results has no data (#2072) (@vera-liu)
|
||||
- [87869a2](https://github.com/airbnb/superset/commit/87869a29c98b3fadbe1d6879437530f5623d774f) Customize tooltip with axis format (#2068) (@vera-liu)
|
||||
- [544211f](https://github.com/airbnb/superset/commit/544211f5ecbe63958de72bcc014bc4de23f30bb7) Revert "Display no data alert when async result has zero rows" (#2069) (@vera-liu)
|
||||
- [f6ac95e](https://github.com/airbnb/superset/commit/f6ac95e2dd14eff2ba6c86cc1512a88992e18538) Convert objects to json (#2050) (@bkyryliuk)
|
||||
- [63bef2f](https://github.com/airbnb/superset/commit/63bef2f8440620407b6dfe9ebadf8305450fce28) [bugfix] only pop slice_id when it exists in url (#2065) (@vera-liu)
|
||||
- [4a8cd04](https://github.com/airbnb/superset/commit/4a8cd04de6f1fd6aea060ee62968903dc3892fb8) Display no data when async result has zero rows (#2055) (@vera-liu)
|
||||
- [8580662](https://github.com/airbnb/superset/commit/85806624db3d4651bc9d1b15e32b34c9d644cfdd) Use a key-value store model for sharing long queries (#1951) (@vera-liu)
|
||||
- [1ac2273](https://github.com/airbnb/superset/commit/1ac22739848fef09b663ca3fbad9bf84eb706211) Reimplement has_access. (#2028) (@bkyryliuk)
|
||||
- [a8c29c4](https://github.com/airbnb/superset/commit/a8c29c4ffec1bcf631cea0afbb40e95a4817cf07) Change validator of timeshift to allow for strings (#2051) (@vera-liu)
|
||||
- [31af01c](https://github.com/airbnb/superset/commit/31af01c4f2b54c05a0f4bc66c7fcaaa9fe0b0681) Splitting dev-reqs.txt into requirements for development and docs (dev-reqs-for-docs.txt). Updating CONTRIBUTING.md accordingly (#2049) (@dylburger)
|
||||
- [b1bba96](https://github.com/airbnb/superset/commit/b1bba96d04b636d77d557ca066e22d3f2bd3289b) Fix csv download. (#2036) (@bkyryliuk)
|
||||
- [c5c7302](https://github.com/airbnb/superset/commit/c5c730224e6ab89cfbffb26f1c9a1fc0429e2299) Check datasource level perms for downloading csv and fetching results (#2032) (@bkyryliuk)
|
||||
- [7441cf7](https://github.com/airbnb/superset/commit/7441cf7d39ffcdab4def1c9b098203610a067794) Fix inner query labels for Vertica (#2041) (@0x0ece)
|
||||
- [45c72d2](https://github.com/airbnb/superset/commit/45c72d25df68dfceb1bcf5d305700c0972d48407) New administrator tutorial (#2046) (@dylburger)
|
||||
- [3fff631](https://github.com/airbnb/superset/commit/3fff631b32579ed1d3fa5b50349542b83dc62fda) Expanded on documentation section, running through an example of committing a change to the docs end-to-end and describing the process for adding static assets (#2047) (@dylburger)
|
||||
- [bfa2891](https://github.com/airbnb/superset/commit/bfa2891b23426740836226be31e160f0d6e132ae) models: add real to numeric types (#2044) (@xrmx)
|
||||
- [5715f52](https://github.com/airbnb/superset/commit/5715f52fef633473d5e7e1d554a7be97c0840fa8) [hotfix] delete DAR when datasource requested does not exist anymore (#2040) (@vera-liu)
|
||||
- [1f2126f](https://github.com/airbnb/superset/commit/1f2126f4637d6099bb1591f4c7715bd3c4385878) Fix Druid granularity timeZone (#2037) (@0x0ece)
|
||||
- [27ed0b3](https://github.com/airbnb/superset/commit/27ed0b37bf3291a688124be5687738ecb37fa8b3) Cleanup fulfilled requests after approve (#1953) (@vera-liu)
|
||||
- [cdbd2f8](https://github.com/airbnb/superset/commit/cdbd2f850706825f16a08afc40682237d6f6d54f) Guess the filter value type (#1978) (@bkyryliuk)
|
||||
- [e46ba2b](https://github.com/airbnb/superset/commit/e46ba2b4a4f5ccc9f584db0a3c7c1fbaf2b7fdf0) Simplifying the viz interface (#2005) (@mistercrunch)
|
||||
- [1c338ba](https://github.com/airbnb/superset/commit/1c338ba742108139c3fe5885765633f298734be5) [WIP] [explorev2] Refactor filter into FieldSet (#1981) (@vera-liu)
|
||||
- [2b7673a](https://github.com/airbnb/superset/commit/2b7673ad5d95f63b3e251f08f6141f82447d0e23) Fixing pypi_push.sh (@mistercrunch)
|
||||
|
||||
### 0.15.4 (2017/01/24 19:33 +00:00)
|
||||
- [2f27353](https://github.com/airbnb/superset/commit/2f27353015e18a1eab8ca415131023e91adf5399) v0.15.4 (@mistercrunch)
|
||||
- [1b8c3f4](https://github.com/airbnb/superset/commit/1b8c3f420a6f74fa8dd6e5a0762e14d9ba5f7426) avoid py3 error in setup.py (#2030) (@wyndhblb)
|
||||
- [a3a0708](https://github.com/airbnb/superset/commit/a3a070855ccea84e75f89389c835772bbde66d10) Use dist instead of src in mapbox (#2027) (@0x0ece)
|
||||
- [e84c639](https://github.com/airbnb/superset/commit/e84c6393b8658c7e8d9b321c08f0dea33335aa28) Correcting docs to `run npm build` instead of prod (@mistercrunch)
|
||||
|
||||
### 0.15.3 (2017/01/24 16:10 +00:00)
|
||||
- [7413dd9](https://github.com/airbnb/superset/commit/7413dd9f4b99752d064024e764284beabb82a3cc) v0.15.3 (@mistercrunch)
|
||||
- [9cbd667](https://github.com/airbnb/superset/commit/9cbd667eb7af96cb2cafaf05778906110cf50520) [explore-v2] Fix edit datasource link for druid datasources (#1982) (@ascott)
|
||||
- [37fb56c](https://github.com/airbnb/superset/commit/37fb56c61ceb339079ff117971fc91bdd678db80) Week beginning Monday time grain for MySQL (#2014) (@alanmcruickshank)
|
||||
- [404a94c](https://github.com/airbnb/superset/commit/404a94cadbe44a463bda2201b22f268201a7474c) [hotfix] fixing the hotfix (@mistercrunch)
|
||||
- [0807a8d](https://github.com/airbnb/superset/commit/0807a8d0162ff824151df70e7d045f9179668ac0) [hotfix] load selectors in render (@mistercrunch)
|
||||
- [4a98881](https://github.com/airbnb/superset/commit/4a9888157ebcd8513c083f381fdb417fc5f700de) Update INTHEWILD.md (#2000) (@silashundt)
|
||||
- [83fbdcc](https://github.com/airbnb/superset/commit/83fbdcceac0c5ee836345ff6b0fe03b1c2c6d69f) Add Qunar to INTHEWILD (#2001) (@flametest)
|
||||
- [b070ef5](https://github.com/airbnb/superset/commit/b070ef5fdb2ce61b288362878cfd7622d6e1270c) added Digit to inthewild (#1997) (@robert-digit)
|
||||
- [7d380dc](https://github.com/airbnb/superset/commit/7d380dcd14939f8100405f9f1551a3e2a74054ce) Adding Clark.de and Yahoo to INTHEWILD (@mistercrunch)
|
||||
- [a15dbd9](https://github.com/airbnb/superset/commit/a15dbd992d53870280700e6dd15f604bd76aa4fc) Adding Clark.de to INTHEWILD (@mistercrunch)
|
||||
- [52c5d23](https://github.com/airbnb/superset/commit/52c5d235af43f659a36ddd0baeece95756395f1b) Add analysisTypes to refresh druid (#1983) (@noppanit)
|
||||
- [495f646](https://github.com/airbnb/superset/commit/495f6460a40f4a2622f52c03f511778c4060b1f5) Add email functionality (#1914) (@bkyryliuk)
|
||||
- [a96024d](https://github.com/airbnb/superset/commit/a96024d0e7c54e5559205beb4f770db1e0ff85bb) [explorev2] Fields can validate input and handle errors (#1980) (@mistercrunch)
|
||||
- [99b84d2](https://github.com/airbnb/superset/commit/99b84d29091fcbdd233c91cc239cc6d2cf4b2e74) Reverting CLI changes in #1713 (#1964) (@mistercrunch)
|
||||
- [24728b8](https://github.com/airbnb/superset/commit/24728b8b47037ba809be95e759dc73ce7a8f73a5) Permissions cleanup: remove none and duplicates. (#1967) (@bkyryliuk)
|
||||
- [9750e49](https://github.com/airbnb/superset/commit/9750e49df8ff95d9dcbd25bea426eaa1ddcb67bd) Add the missing argument (#1969) (@flametest)
|
||||
- [bf31783](https://github.com/airbnb/superset/commit/bf31783d0ccc62712800ed3cc7caf63890ba36b5) v0.15.2 (@ascott)
|
||||
|
||||
### 0.15.2 (2017/01/13 07:05 +00:00)
|
||||
- [87eacf8](https://github.com/airbnb/superset/commit/87eacf88c3ee82f6fe3cf79c54672f6c64b7f3fb) fix timestamp error in table view (#1960) (@flametest)
|
||||
- [1dbfb99](https://github.com/airbnb/superset/commit/1dbfb99ead4be6669752853e58504b0f0eab351d) Leave metrics empty if not specified (#1965) (@vera-liu)
|
||||
- [ff4020e](https://github.com/airbnb/superset/commit/ff4020ea732de873feb82d94971cadcc5d5c0e74) [explorev2] using label in 'Visualization Type' Select instead of key (#1927) (@mistercrunch)
|
||||
- [0ce7fc1](https://github.com/airbnb/superset/commit/0ce7fc18a883af3ba9d35a498912fcf49ab1e70c) Adding a way to see the git SHA from the website (#1956) (@mistercrunch)
|
||||
- [470a6e9](https://github.com/airbnb/superset/commit/470a6e9d768493e7f9671d3cbe436e03ff15f137) [explorev2] adding support for client side validators on controls (#1920) (@mistercrunch)
|
||||
- [fc74fbe](https://github.com/airbnb/superset/commit/fc74fbeeaa0834f1dcf5f83b25d3b709b1b9fd95) [explore-v2] make control panel sections and fields more dense (#1954) (@ascott)
|
||||
- [9c6a579](https://github.com/airbnb/superset/commit/9c6a5793b9841686c483f818f9ef1af4cf0b9b73) Fix none view_menues. (#1950) (@bkyryliuk)
|
||||
- [49b6b38](https://github.com/airbnb/superset/commit/49b6b387410987ef19da36118fc06b4a52d69c85) Pass query instead of slice to Action buttons to prevent lagging query (#1948) (@vera-liu)
|
||||
- [a385ee9](https://github.com/airbnb/superset/commit/a385ee9e978c1175f95b3704669ab70489469860) Use POST in sqllab_viz instead of url params to avoid error with long queries (#1933) (@vera-liu)
|
||||
- [f0917c6](https://github.com/airbnb/superset/commit/f0917c62f20e5f1a36e3fa99f155787ff5e54afd) Add a Async Select that fetches options from given endpoint (#1909) (@vera-liu)
|
||||
- [94d2016](https://github.com/airbnb/superset/commit/94d20168dab4b85fc3f2d2172a2ae899de5aa2ba) Change fields for dual_line to match with new SelectField structure (#1932) (@vera-liu)
|
||||
- [2d866e3](https://github.com/airbnb/superset/commit/2d866e3ffa9bfedd3b3dad0d3463767aae879a14) [hotfix] fix the logging fix that broke the build (#1940) (@mistercrunch)
|
||||
- [5d94d70](https://github.com/airbnb/superset/commit/5d94d7067e3cc052f27c736c46a0d74c270ca387) [explore-v2] add edit link below datasource select (#1919) (@ascott)
|
||||
- [7323f4c](https://github.com/airbnb/superset/commit/7323f4c2ab2eda54e91274a6e9281f0a98160850) Make up the user link string (#1947) (@flametest)
|
||||
- [eca6dfe](https://github.com/airbnb/superset/commit/eca6dfef6afa05929fa240177e389e6c9a989aaf) switch order of period compare and rolling periods (#1946) (@patrickleotardif)
|
||||
- [761462e](https://github.com/airbnb/superset/commit/761462ef930fa8ac1094629b403d0ec09bb5c0ab) Revert "#views users for created dashboards on profile page" (#1943) (@vera-liu)
|
||||
- [98e8325](https://github.com/airbnb/superset/commit/98e83255e6efa18b72b7b17413d55d49ee9213b9) Added extra details around setting up admin user (#1937) (@mobcdi)
|
||||
- [cbf3562](https://github.com/airbnb/superset/commit/cbf3562a6f4d2edaaf14592c0bee6cab8394108c) Fix double scrollbar in pivot table (UI bug) (#1931) (@SalehHindi)
|
||||
- [a2c41bb](https://github.com/airbnb/superset/commit/a2c41bbace99eb3e749c59a3b2805c6e8e2b7130) viz: hotfix for saving in cache (#1922) (@xrmx)
|
||||
- [2a12a3c](https://github.com/airbnb/superset/commit/2a12a3c70267987c4bc3ecfad08aba4a5769fa10) [hotfix] logging is down (@mistercrunch)
|
||||
- [2ab6a41](https://github.com/airbnb/superset/commit/2ab6a411f4b9fa75bc86b83f4aa4e3707e90e002) Druid dashboard import/export. (#1930) (@bkyryliuk)
|
||||
- [14ed10b](https://github.com/airbnb/superset/commit/14ed10bdb0f6868e87c8cf39d770fcc616273e72) Fixing docs generation (@mistercrunch)
|
||||
- [49e6fd5](https://github.com/airbnb/superset/commit/49e6fd5bfbdb90020bf821f843a7e850e70a4c6b) Revert "Druid dashboard import/export. " (#1923) (@mistercrunch)
|
||||
- [af872fa](https://github.com/airbnb/superset/commit/af872fa4d4fbafb29bf47418c7c2b6716846f509) Druid dashboard import/export. (#1811) (@bkyryliuk)
|
||||
- [cec4cf0](https://github.com/airbnb/superset/commit/cec4cf014c91e5b664cc3dbfba34619388fd492e) #views users for created dashboards on profile page (#1667) (@vera-liu)
|
||||
- [783ad70](https://github.com/airbnb/superset/commit/783ad703d06a1e3b75c76307174af02d843cda0d) [hotfix] delete ipdb breakpoint (#1917) (@vera-liu)
|
||||
- [2226716](https://github.com/airbnb/superset/commit/222671675c31bdad9b8e2c8f3a5b814a02d85bee) [exploreV2] mapStateToProps for fields (#1882) (@mistercrunch)
|
||||
- [9a62d94](https://github.com/airbnb/superset/commit/9a62d9463005631f2d43b57a0d782453db98931e) [sqllab] bugfix visualizing a query with a semi-colon (#1869) (@mistercrunch)
|
||||
- [c3edc6e](https://github.com/airbnb/superset/commit/c3edc6e24bb55dcf26d29603b624ba513a562232) [WIP] Add dual-axis line chart to viz (#1782) (@vera-liu)
|
||||
- [119b0c5](https://github.com/airbnb/superset/commit/119b0c55e972d4b4b93ff9df4d7e99d14b9b8453) [explore] fix height in embed mode (#1898) (@mistercrunch)
|
||||
- [c14c7ed](https://github.com/airbnb/superset/commit/c14c7edc5ee798eb24b53ae65fec9a876fbe1fd9) [explore] show the broken query when failing (#1871) (@mistercrunch)
|
||||
- [e3b296c](https://github.com/airbnb/superset/commit/e3b296c558dcad4f77b6c82c37ed20903b1699bf) utils: teach our json serializer to handle more types (#1907) (@xrmx)
|
||||
- [c2d29fb](https://github.com/airbnb/superset/commit/c2d29fb54bbe8e57bdee03f4f4940469b48c2a92) Change ordering of fields when adding a table (#1899) (@mistercrunch)
|
||||
- [7aab8b0](https://github.com/airbnb/superset/commit/7aab8b0ae3d6816cf861c09193c9e2e166e2d18a) Simplifying the Fields (Controls) interface (#1868) (@mistercrunch)
|
||||
- [861a3bd](https://github.com/airbnb/superset/commit/861a3bd4ae85da2bb227c3d44a4ff56b9a836caf) docs: 8088 is the default port, no need to specify it (#1861) (@andreamelloncelli)
|
||||
- [9bc7ad9](https://github.com/airbnb/superset/commit/9bc7ad9cd53b9204a044c5dff16185ca49bd66a4) Do not use persistState for explorev2 (#1894) (@vera-liu)
|
||||
- [a1e3fc1](https://github.com/airbnb/superset/commit/a1e3fc1c230239c5535573cf708ff0e03d5eaa8a) [explorev2] giving more room for long textboxes (#1881) (@mistercrunch)
|
||||
- [242869d](https://github.com/airbnb/superset/commit/242869db3aa8eab99558d19f0e99923a78fb9840) [sql lab] only show single run query button (#1858) (@ascott)
|
||||
- [8924bb7](https://github.com/airbnb/superset/commit/8924bb79e74704632cc4401f0ed1f7134be11a1d) [explorev2] moving the "Time" section up to 2nd section (#1885) (@mistercrunch)
|
||||
- [a0d103d](https://github.com/airbnb/superset/commit/a0d103dac33201b55b2587d10d11f293bed0a0e7) Fix small typo (#1888) (@davejm)
|
||||
- [d52b299](https://github.com/airbnb/superset/commit/d52b299df8812ff4af5fb05ded2c1b3aedaae865) Updating CHANGELOG (@mistercrunch)
|
||||
|
||||
### 0.15.1 (2016/12/28 21:29 +00:00)
|
||||
- [092432f](https://github.com/airbnb/superset/commit/092432f04f0033e60493f009728a7bfd6a744b22) v0.15.1 (@mistercrunch)
|
||||
- [ea8e663](https://github.com/airbnb/superset/commit/ea8e6634d6c304cde3a42c65d37ec694f76b8cec) read anon user role from config, remove reference to public role (#1878) (@willgroves)
|
||||
- [3e6f90c](https://github.com/airbnb/superset/commit/3e6f90cf722f205e1f13ef7228be6d0d767c1d1d) Upgrading pydruid version and adopt 'merge' flag during refresh_druid operation (#1879) (@dkhwangbo)
|
||||
- [1673105](https://github.com/airbnb/superset/commit/16731056edf25cd4422fa674de827215df9027b1) [sqllab] async queries - better error handling (#1853) (@mistercrunch)
|
||||
- [0712894](https://github.com/airbnb/superset/commit/0712894353825ea2faa19d8000ca031c44debf39) Improving database logging by adding duration, referrer and post data (#1830) (@mistercrunch)
|
||||
- [36fad80](https://github.com/airbnb/superset/commit/36fad803edf6666188746f270e498e03c2df363c) sqllab: don't hold database deletion because of query reference (#1863) (@xrmx)
|
||||
- [6732f01](https://github.com/airbnb/superset/commit/6732f01cb7bb08e1b180bb74f263bf50317d7462) Enable freeform-select with fetched column values for filter values (#1697) (@vera-liu)
|
||||
- [bb04e6f](https://github.com/airbnb/superset/commit/bb04e6fcfa1042b4532b50d8898555813be7fa29) Use APP_ICON in template (#1855) (@szmate1618)
|
||||
- [007ee88](https://github.com/airbnb/superset/commit/007ee88d33f92e6d052122b35ccad84d176029a7) [explorev2] improving the scrolling/scrollbars placement (#1840) (@mistercrunch)
|
||||
|
||||
- [7a5bb94](https://github.com/airbnb/superset/commit/7a5bb947542fdc20e2ec70e18b1cf418b8d1dba8) Stop ChartContainer from rendering twice on chartStatus change (#1828) (@vera-liu)
|
||||
- [e06a0cd](https://github.com/airbnb/superset/commit/e06a0cd89bc84f3a7e75ee6f03df8c9c3a2badeb) Add force_ctas_schema to query model when enabled (#1825) (@vera-liu)
|
||||
- [b6cba13](https://github.com/airbnb/superset/commit/b6cba13293101f3022c16e120e96383b59cae03e) [explorev2] enabling redux dev tools (#1842) (@mistercrunch)
|
||||
- [d929bbf](https://github.com/airbnb/superset/commit/d929bbfe3010f795cdf9ef28b48e9e249cf7ef86) [explorev2] making QueryAndSaveBtns disabled while running queries (#1841) (@mistercrunch)
|
||||
- [bf67d64](https://github.com/airbnb/superset/commit/bf67d64708834800669e8be30ffa695d7a6db022) [explorev2] making Datasource an Viz controls not clearable (#1845) (@mistercrunch)
|
||||
- [92aa1a6](https://github.com/airbnb/superset/commit/92aa1a612476fdef5f19eb68f961324a333b346c) Permissions refactoring, optimizations and unit testing. (#1798) (@bkyryliuk)
|
||||
- [733ab80](https://github.com/airbnb/superset/commit/733ab8014bd83ae4e0e4961b9c454ad238556bd8) [explorev2] using a loader to load the explorev2 specific css (#1843) (@mistercrunch)
|
||||
- [6aaa49f](https://github.com/airbnb/superset/commit/6aaa49f0bf182f449a970a1e15d86111987dde32) Change default gunicorn address (#1838) (@amancevice)
|
||||
- [638f27c](https://github.com/airbnb/superset/commit/638f27c2df6540a50d5cba92847bc7000b33cb1b) [sqllab] Fix sql expression bug with count distinct metrics (#1805) (@vera-liu)
|
||||
- [84a3b55](https://github.com/airbnb/superset/commit/84a3b559128bb7717869f5fa7339bfe1ac4003cc) [explorev2] remove unused file SqlClause.jsx (#1839) (@mistercrunch)
|
||||
- [552d464](https://github.com/airbnb/superset/commit/552d46479bbf819e4fa7fb811ec05cff104a840c) [explorev2] no bootstrap data, just metadata in exploreV2 (#1827) (@mistercrunch)
|
||||
- [fa9c066](https://github.com/airbnb/superset/commit/fa9c066ffe6b71a36f97e2e0d9fdb94b94183ca6) Add email-to option in action buttons for dashboard and slice (#1705) (@vera-liu)
|
||||
- [e1e20b8](https://github.com/airbnb/superset/commit/e1e20b875748f677312d8c5ed3daf87113143b63) Sort searched queries by recency (#1735) (@vera-liu)
|
||||
- [2fb94a8](https://github.com/airbnb/superset/commit/2fb94a89e2538710c5293404acaf6d8f0ef847ea) Add ADDITIONAL_MIDDLEWARE option to config (#1832) (@jr-minnaar)
|
||||
- [7a9604a](https://github.com/airbnb/superset/commit/7a9604a3c918ce5fad1010e9e95fbf961a95420d) Workaround for slices "Not Found" issue in IE 11 (#1821) (@rlei)
|
||||
- [e099088](https://github.com/airbnb/superset/commit/e0990880121643b63f66cc18fe917ea9fbe98554) [hotfix] fixing the build (@mistercrunch)
|
||||
- [34e107e](https://github.com/airbnb/superset/commit/34e107e7d35b7d48385a13268b2ed713a2808114) [explore-v2] add config option for explore v2 beta users, and send through v2 path (#1671) (@ascott)
|
||||
|
||||
### 0.15.0 (2016/12/12 19:30 +00:00)
|
||||
- [2254a4d](https://github.com/airbnb/superset/commit/2254a4d0b4480da7563c7c3afdeadecf66b08cf5) v0.15.0 (@mistercrunch)
|
||||
- [9f7486f](https://github.com/airbnb/superset/commit/9f7486f4029fcbc18dfdeaeb4ff3c3c07242ad2b) remove extra call to get_viz in explorev2 (#1812) (@vera-liu)
|
||||
- [699602d](https://github.com/airbnb/superset/commit/699602d1c5bdd7d15f6adb5f22e458c268bc1306) Add tooltips to RunAsync and CTAS button (#1792) (@vera-liu)
|
||||
- [2993ff1](https://github.com/airbnb/superset/commit/2993ff1d75ff2391ffab388544f198cbb78364a9) Add NVD3's bullet chart (#1775) (@darabos)
|
||||
- [afb3c24](https://github.com/airbnb/superset/commit/afb3c24d5a4951e7cc5a5714a79eb201e0b1aa24) Showing more fields in DatabaseView (@mistercrunch)
|
||||
- [8ef730b](https://github.com/airbnb/superset/commit/8ef730b5feb8e27116552ca863e8dac42b1aa6ec) Added timer to explore v2 and share it with sqllab (#1802) (@vera-liu)
|
||||
- [866cfe5](https://github.com/airbnb/superset/commit/866cfe52794d5c6df9f85f088243fa85f66eaec7) Add schema name to output column in query history (#1790) (@vera-liu)
|
||||
- [68c2eab](https://github.com/airbnb/superset/commit/68c2eab6b93a13966b19aae20fb6c82fc34e3bcf) [hotfix] handling 0% change in big number with trendline (#1801) (@mistercrunch)
|
||||
- [aeda5bd](https://github.com/airbnb/superset/commit/aeda5bd2606946a5cb6fd7dd5ecd4b73413c79a9) [sqllab] config item for SQLLAB_DEFAULT_DBID (#1793) (@mistercrunch)
|
||||
- [a95cd71](https://github.com/airbnb/superset/commit/a95cd71456a0b24c08d4d020238fd9d89b2c9cd7) Add viz thumbnails to viz_type select (#1794) (@vera-liu)
|
||||
- [34d0dd9](https://github.com/airbnb/superset/commit/34d0dd9d6e074e41968c39247d66e19fd551c57b) adjust header nav links so they are all aligned on the base line (#1786) (@ascott)
|
||||
- [401d9af](https://github.com/airbnb/superset/commit/401d9afd54ce46f5c63a821094350098f07823a1) [ui] update logo, favicon, and new primary color (#1781) (@ascott)
|
||||
- [74edb93](https://github.com/airbnb/superset/commit/74edb936a599ed54528389814ddf83e74f8452fd) [WIP] Add http to copied url and move function to componentWillReceiveProps (#1780) (@vera-liu)
|
||||
- [c155857](https://github.com/airbnb/superset/commit/c1558578d7c555fb7bb9ee30eb98bad4d28fbd07) [explorev2] Breaking down large files, fixing JS warnings (#1773) (@mistercrunch)
|
||||
|
||||
- [3597fdb](https://github.com/airbnb/superset/commit/3597fdb7f869929e0b09ff0144ff430b81e67853) Filter table list based on the user permissions. (#1769) (@bkyryliuk)
|
||||
|
||||
- [43f2a37](https://github.com/airbnb/superset/commit/43f2a379a1b88b260d0a4bdeac97b3cb4478afcf) Make cell-click filter in table viz optional (#1762) (@vera-liu)
|
||||
- [69702e3](https://github.com/airbnb/superset/commit/69702e3a1956ef5587e5aea2bffb3720b9b4cd35) Create users if not found. (#1753) (@bkyryliuk)
|
||||
- [eb0655c](https://github.com/airbnb/superset/commit/eb0655cf85daad4329cf8630fe99e2a50d0e7e5a) [sqllab] Fixed js error when results are not available (#1715) (@vera-liu)
|
||||
- [d8864bc](https://github.com/airbnb/superset/commit/d8864bc92b7566fa4ebb9d4863d75bd5eaa1e9c4) Enable overwrite sql in QueryHistory (#1731) (@vera-liu)
|
||||
- [89fc9d7](https://github.com/airbnb/superset/commit/89fc9d7c80564e2f02949ed33113a63fc1e898e4) Make entire menuitem clickable for copy query (#1747) (@vera-liu)
|
||||
- [76aa9f7](https://github.com/airbnb/superset/commit/76aa9f7e1047de5e41e8bd5bfee610fcd569b8ad) [explorev2] fix textfield and druid bug (#1732) (@vera-liu)
|
||||
- [abd0974](https://github.com/airbnb/superset/commit/abd097489738eacc37fcd5dc9605d483c84071f6) Fix superset cli for python3 (#1760) (@xrmx)
|
||||
- [c4e943a](https://github.com/airbnb/superset/commit/c4e943a24fe89824e59a105d6ce6e5d9255717c1) [sqllab] making 'click to retrieve results' a button (#1737) (@mistercrunch)
|
||||
- [a3106bc](https://github.com/airbnb/superset/commit/a3106bcb3d0bc6fb0e5df2c356d453563a07c8a2) [bugfix] bignumber comparison wrong with neg values (#1743) (@mistercrunch)
|
||||
- [b045075](https://github.com/airbnb/superset/commit/b045075a96232f1e2f2e14bdaa171eba67b0fa29) Sankey Tooltip fix (#1748) (#1750) (@ddol)
|
||||
- [09d597f](https://github.com/airbnb/superset/commit/09d597f3adf4b238dc2a43b802fdda22b451dfe5) Prevent duplicated view_menu perms (#1751) (@bkyryliuk)
|
||||
- [9d4c3d8](https://github.com/airbnb/superset/commit/9d4c3d83d0907925f1f37cbe48c5decd2c54639f) Update role based on usernames not emails. (#1749) (@bkyryliuk)
|
||||
- [95580a0](https://github.com/airbnb/superset/commit/95580a004fe3322ff1c623ac4eec72150e1355b5) [explorev2] cosmetic, smaller size for input text (#1746) (@mistercrunch)
|
||||
- [723f907](https://github.com/airbnb/superset/commit/723f90755e89e46287e212b18844c9f7abc6cf60) Fixing the sourcemap in dev mode (#1744) (@mistercrunch)
|
||||
- [324205f](https://github.com/airbnb/superset/commit/324205f77ac7a77b6546da482979842d58ce9fbb) [sqllab] bugfix where a query has the same alias twice as output (#1734) (@mistercrunch)
|
||||
- [0a40d8c](https://github.com/airbnb/superset/commit/0a40d8ce8f08ba6edc18370032aa85571495b570) Rremove unused symlinks (#1736) (@yolken)
|
||||
- [168a252](https://github.com/airbnb/superset/commit/168a25239e712fe9eccf676f26df75fd91bd126f) State that npm should be between 3.9 and 4 (@bkyryliuk)
|
||||
- [7eef46e](https://github.com/airbnb/superset/commit/7eef46e9413b01ec15be515567a9619c695d5501) Adding links pointing to the new user profile page (#1704) (@mistercrunch)
|
||||
- [50da4f8](https://github.com/airbnb/superset/commit/50da4f8c0708f91ff24c0abd7189a137a1415bf6) Support running superset via pex (#1713) (@yolken)
|
||||
- [2d0ebea](https://github.com/airbnb/superset/commit/2d0ebeae1bfd5e385000c9aa952891cf474821c6) [explorev2] Make chart container more responsive (#1724) (@vera-liu)
|
||||
- [1a16491](https://github.com/airbnb/superset/commit/1a164919715d6eaf1a999b97daaa53acb94a827d) Display full table name (schema + name) if possible. (#1728) (@bkyryliuk)
|
||||
- [7f4f250](https://github.com/airbnb/superset/commit/7f4f25097046dac9b436ef87f041debe2713827a) Redirects to login page if user not logged in at welcome page (#1723) (@vera-liu)
|
||||
- [25acb78](https://github.com/airbnb/superset/commit/25acb78071acc2eec8b44cb7019f269c1b2a6deb) Pass schema to the select star query. (#1714) (@bkyryliuk)
|
||||
- [e822d5a](https://github.com/airbnb/superset/commit/e822d5a1b7eb8f0cabcfcc85f5201df8199db796) Make edit / add / delete perms available to all users. (#1722) (@bkyryliuk)
|
||||
- [32fc0ff](https://github.com/airbnb/superset/commit/32fc0ff6d0b437766d16db128a7b1d40a09080bb) [Bugfix] autocomplete in sqleditor doesnot use newly loaded table columns (#1712) (@vera-liu)
|
||||
|
||||
### 0.14.1 (2016/11/29 23:57 +00:00)
|
||||
- [94dde07](https://github.com/airbnb/superset/commit/94dde075b3eab41797725e1e02c7f87b6b45471a) v0.14.1 (@mistercrunch)
|
||||
- [65e9232](https://github.com/airbnb/superset/commit/65e92327abdd0d521a9dcb65319165b163da356c) Druid hotfix. (#1710) (@bkyryliuk)
|
||||
- [0be02e6](https://github.com/airbnb/superset/commit/0be02e67a554d323efe4ed119a59bba53c559477) Updating CHANGELOG 0.14.0 (@mistercrunch)
|
||||
- [7327c97](https://github.com/airbnb/superset/commit/7327c97e4c5efcf7c5b080a1e534d7b44129bb8b) v0.14.0 (@mistercrunch)
|
||||
|
||||
### 0.14.0 (2016/11/29 23:03 +00:00)
|
||||
- [03b21dc](https://github.com/airbnb/superset/commit/03b21dcf0a3fc18e1290f7770004d3b74df8cef3) [explorev2] Bug fixes in Save Modal (#1707) (@vera-liu)
|
||||
- [dc98c67](https://github.com/airbnb/superset/commit/dc98c6739fcccc8edc60ef7e761cb1491005f644) Implement table name extraction. (#1598) (@bkyryliuk)
|
||||
- [fcb8707](https://github.com/airbnb/superset/commit/fcb870728db69bbee092d20c3f78cb7785fe2e61) Add per schema permissions. (#1698) (@bkyryliuk)
|
||||
- [7919428](https://github.com/airbnb/superset/commit/7919428a1e02457a50ae00439e827f996403f71c) Vliu explorev2 bugs (#1701) (@vera-liu)
|
||||
- [3496a80](https://github.com/airbnb/superset/commit/3496a80f5a85a0b66e59ec259ed13ca9ba3d5ba0) make stack trace more readable (#1672) (@ascott)
|
||||
- [56b917a](https://github.com/airbnb/superset/commit/56b917a5c206d3083d9d9d3d0606b976c64b6044) [explore-v2] fix errors on table view (#1675) (@ascott)
|
||||
- [18c43aa](https://github.com/airbnb/superset/commit/18c43aaea2f889e50211b22f0a68269f314bcafa) make chart title larger, fix explore actions btn spacing (#1680) (@ascott)
|
||||
- [c43fc38](https://github.com/airbnb/superset/commit/c43fc38f69d6284729cd47368e796117adcc1d1b) [druid] fix having clause (#1694) (@mistercrunch)
|
||||
- [c07f0ab](https://github.com/airbnb/superset/commit/c07f0ab9c72430f5892f701d6cba35718ef322ad) Config programmatic roles in the config.py (#1664) (@bkyryliuk)
|
||||
- [1c429b2](https://github.com/airbnb/superset/commit/1c429b27bc425aa8ba0f8cc6b43887cfb91dcd15) Fixing issue #1689 (#1696) (@mistercrunch)
|
||||
- [b7019ad](https://github.com/airbnb/superset/commit/b7019ad4f343ecbd5d33ce4a5800a72a9f4301b6) [sqllab] bugfix SouthPane doesn't update as expected (#1699) (@mistercrunch)
|
||||
- [84e8f74](https://github.com/airbnb/superset/commit/84e8f741ae969888c4f2501ada132f58bdcfb249) Add 'Save As' feature for dashboards (#1669) (@the-dcruz)
|
||||
- [e3a9b39](https://github.com/airbnb/superset/commit/e3a9b393c26ab173fe3ffe3dd14191705cab7119) Missing merge_perm function. Fixes 1691. (#1692) (@niconoe)
|
||||
- [16aba51](https://github.com/airbnb/superset/commit/16aba517e4640300c9a71f6186776671540bc488) Use smaller size for node max_old_space_size (#1679) (@xrmx)
|
||||
- [205928e](https://github.com/airbnb/superset/commit/205928e6df892060cdd3ffe0af6a1217a848f301) docs: fix python-redis link markup (#1683) (@xrmx)
|
||||
- [39ce4aa](https://github.com/airbnb/superset/commit/39ce4aa049fffef3b9f6e368d64130ae85cb86d8) Added filter in ControlPanelsContainer for explore V2 (#1647) (@vera-liu)
|
||||
- [cef4a82](https://github.com/airbnb/superset/commit/cef4a8296a6a9d46503dd63e268be3a35e9e8e91) [sqllab] adding a sql preprocessor for Presto (#1670) (@mistercrunch)
|
||||
- [b370ef0](https://github.com/airbnb/superset/commit/b370ef0229377c6b85f78d9ba080d00ff6dba58e) Rerender chart without clicking query button for fields (#1658) (@vera-liu)
|
||||
- [6b80f5b](https://github.com/airbnb/superset/commit/6b80f5bb35e497c79fe458b25ba87266e3c0f3bf) Get sections to render when switching datasource (#1660) (@vera-liu)
|
||||
- [bdae570](https://github.com/airbnb/superset/commit/bdae570a69cd948987b05fed2e7653a221ef0d80) Temperary fix of a slice bug (#1648) (@vera-liu)
|
||||
- [face524](https://github.com/airbnb/superset/commit/face5245a99d13089b9fa4cfa7521ee2ca6b209c) Make explore container resize with browser window (#1608) (@vera-liu)
|
||||
- [db1ed2a](https://github.com/airbnb/superset/commit/db1ed2a765d317e55377f2550f169b78f981b4a0) Calculate height dynamically using jquery for scrollable sqllab (#1611) (@vera-liu)
|
||||
- [10982de](https://github.com/airbnb/superset/commit/10982dec3c69f1bed709b38616417eada995d2f4) Make QueryTable scrollable in Query Search page (#1656) (@vera-liu)
|
||||
- [6825e75](https://github.com/airbnb/superset/commit/6825e75681b1249d066d9fa0bf0dca9f1824bb24) Fixed bug with querylink passing sql object instead of string (#1659) (@vera-liu)
|
||||
- [bd6a439](https://github.com/airbnb/superset/commit/bd6a439e0b2a3a76f8aece91f11a7eee2ebf6d29) [QuerySearch] Add loading status to QuerySearch page (#1657) (@vera-liu)
|
||||
- [c90dd49](https://github.com/airbnb/superset/commit/c90dd4902f18bb11c46bc38b8f70bfc14cfc2171) Programatically sync the role with user list. (#1619) (@bkyryliuk)
|
||||
- [868e5c4](https://github.com/airbnb/superset/commit/868e5c45fed8e090750dffe88660f3943f373c19) Redirect URL requests with "caravel" to "superset" (#1651) (@kingo55)
|
||||
- [7e1852e](https://github.com/airbnb/superset/commit/7e1852ee883628d38b2e3bb71e2b2b03fad41ba3) User profile pages (favorites, created content, recent activity, security & access) (#1615) (@mistercrunch)
|
||||
- [5ae98bc](https://github.com/airbnb/superset/commit/5ae98bc7c9b432683d03d30a30631a6efd7a78a3) Improving jinja2 security by using SandboxedEnvironment (#1632) (@mistercrunch)
|
||||
- [1624e7d](https://github.com/airbnb/superset/commit/1624e7de7dd50f1c4f5fdd9153adac4ba5b983d2) Add all_tables endpoint to allow airpal / superset perm sync. (#1614) (@bkyryliuk)
|
||||
- [7a98f84](https://github.com/airbnb/superset/commit/7a98f848909ca2099e29d3f485fd299037142e65) Admin / Alpha permission cleanup and fixes. (#1645) (@bkyryliuk)
|
||||
- [9b18128](https://github.com/airbnb/superset/commit/9b181280d44171cb0c724a07f50488eb08f98e72) include jQuery and bootstrap (#1642) (@ascott)
|
||||
- [38e94b9](https://github.com/airbnb/superset/commit/38e94b9e43f82c682f311fe1563c8f502ae4157a) Save modal component for explore v2 (#1612) (@vera-liu)
|
||||
- [dc25bc6](https://github.com/airbnb/superset/commit/dc25bc6f4d5eeb74665dd353bafda5d97ef5faa1) Fix alpha permission checks. (#1641) (@bkyryliuk)
|
||||
- [f64a205](https://github.com/airbnb/superset/commit/f64a2056038e96883e31419df5fcd4fa396dffb6) Use Alert for visualization error (#1639) (@vera-liu)
|
||||
- [a8480f5](https://github.com/airbnb/superset/commit/a8480f54922775992a28edd7878b1cfa7690264e) Added Alert for ControlPanel and ChartContainer (#1626) (@vera-liu)
|
||||
- [0acf26b](https://github.com/airbnb/superset/commit/0acf26b37c7a59cb976cf7a929caf7cc5a1a968e) Fixed a bug with switching viz_type in exploreV2 (#1631) (@vera-liu)
|
||||
- [2c068a1](https://github.com/airbnb/superset/commit/2c068a1a1583fa61db2f1797b0fcb2618cd6dbe3) increase space between fieldsset rows (#1629) (@ascott)
|
||||
- [b961c95](https://github.com/airbnb/superset/commit/b961c95121e5e4d4342a2926746dbf8a62bd77ea) dim visualization during refresh (#1636) (@mistercrunch)
|
||||
- [8269321](https://github.com/airbnb/superset/commit/82693211f0545affbdc306561a1abb4478c2de9a) Update faq.rst (#1637) (@dodysw)
|
||||
- [e546746](https://github.com/airbnb/superset/commit/e5467462cb73630a9b487891845ab1f01245f2a8) Make nvd3 refresh smoother. (#1618) (@the-dcruz)
|
||||
- [ab5a410](https://github.com/airbnb/superset/commit/ab5a4102cd8921ca2df234bfa6133973ba83a425) [dashboard] give user feedback when there are unsaved changes (#1633) (@ascott)
|
||||
- [d5ef937](https://github.com/airbnb/superset/commit/d5ef937b315f4afc679349369b4e7ac7455748f0) Fixed bugs with viz in exploreV2 (#1609) (@vera-liu)
|
||||
- [bce02e3](https://github.com/airbnb/superset/commit/bce02e3f518237c03273e3ed4d9d1a13d9f8f6a9) [security] improving the security scheme (#1587) (@mistercrunch)
|
||||
- [aad9744](https://github.com/airbnb/superset/commit/aad9744d85b50721d55d5770aad70ba1ee397ede) add new screenshots (#1589) (@ascott)
|
||||
- [506b781](https://github.com/airbnb/superset/commit/506b781f3a6048b433c12d25c1dbce614b5bd31b) [explore-v2] add fave star and edit button to chart header (#1623) (@ascott)
|
||||
- [267fd5b](https://github.com/airbnb/superset/commit/267fd5b9bc4f21a55c4664ae8c3ee717cc1be82c) [table viz] adding support for pagination (#1616) (@mistercrunch)
|
||||
- [c362f28](https://github.com/airbnb/superset/commit/c362f2869e012a4eeb9b76ff654ee3e82a190979) More Dashboard UX unit tests (#1603) (@mistercrunch)
|
||||
- [4f7f437](https://github.com/airbnb/superset/commit/4f7f43752798f57daa8cd8b8ed8a9cbc9c948000) Vliu put datasource in store (#1610) (@vera-liu)
|
||||
- [ab5da5b](https://github.com/airbnb/superset/commit/ab5da5ba2811ac6c2350c7d0534dd209906318af) [table viz] allow sorting on any column (#1601) (@mistercrunch)
|
||||
- [7531bb8](https://github.com/airbnb/superset/commit/7531bb89429547fb541c36fe365791cd742d82a1) Fixed dashboard controls for standalone bug (#1617) (@vera-liu)
|
||||
- [811ee8c](https://github.com/airbnb/superset/commit/811ee8ccdc76a2630a4c8014df26558391b981fe) Deleted unused components in exploreV2 (#1613) (@vera-liu)
|
||||
- [51cb485](https://github.com/airbnb/superset/commit/51cb485ce3e8cb80c72ec8c732281a78441396fd) Add standalone to reactified dashboard page (#1596) (@vera-liu)
|
||||
- [83d08b8](https://github.com/airbnb/superset/commit/83d08b8b8f7c73cbf4de25cadeab93dd3fdfc2fc) Get query button working in explorev2 (#1581) (@vera-liu)
|
||||
- [ed3d44d](https://github.com/airbnb/superset/commit/ed3d44d5919fc2ba739cf8d82e75e2680630646d) Changelog entries for 0.13.2 (@mistercrunch)
|
||||
|
||||
|
||||
### 0.13.2 (2016/11/16 00:23 +00:00)
|
||||
- [895fe23](https://github.com/airbnb/superset/commit/895fe23203a85a4590f84625507849ce63d69f30) v0.13.2 (@mistercrunch)
|
||||
- [af04a56](https://github.com/airbnb/superset/commit/af04a560c887ecbcee40b53c358ee9c2ad2f44ad) Moved check to the correct place. (#1606) (@edevil)
|
||||
- [9124a17](https://github.com/airbnb/superset/commit/9124a17e864b8b2eb109af33fe1b8aad809069da) Removing ascii_art.p from code coverage analysis (@mistercrunch)
|
||||
- [99b0d4c](https://github.com/airbnb/superset/commit/99b0d4c111b66f6da0eb9991b54b375e2fbeecc4) Fix MySql time grain issue (#1590) (@mistercrunch)
|
||||
- [84b98c2](https://github.com/airbnb/superset/commit/84b98c234f852550ecf536e4a6e7ce2d7ebc5df6) Adding Greenplum to supported dbs (@mistercrunch)
|
||||
- [bcc1428](https://github.com/airbnb/superset/commit/bcc1428ebf1cf7e83c93e351858bee3cfbb2e9c2) Updating CODECLIMATE_REPO_TOKEN to new location (@mistercrunch)
|
||||
- [2133056](https://github.com/airbnb/superset/commit/2133056c04d20807ea0c503d0fed235ee20e94bb) Added different Select Fields (#1583) (@vera-liu)
|
||||
- [4155a9d](https://github.com/airbnb/superset/commit/4155a9d7f996d09ebdfc8df0db3dcbe9ccf9b529) Removing broken link to old docker image (#1591) (@kingo55)
|
||||
- [ed48255](https://github.com/airbnb/superset/commit/ed4825523ca54309272f044826f383c2606456a1) Fixed a bug with new dashboard (#1585) (@vera-liu)
|
||||
- [fdbb2bb](https://github.com/airbnb/superset/commit/fdbb2bbdab5e5dbb2f3496b67eb227dc3dc5f2a7) fixing the build (@mistercrunch)
|
||||
- [c064d6d](https://github.com/airbnb/superset/commit/c064d6d8475b07a63a3b5ca7b4dbd248a437f6ed) Correct part_fields variable name (#1586) (@geraneum)
|
||||
- [d33874b](https://github.com/airbnb/superset/commit/d33874bd3d9ffffca7f4726a29c3eb9de2a68d42) [hotfix] postgres issue when slice_id is missing (@mistercrunch)
|
||||
- [96d32dd](https://github.com/airbnb/superset/commit/96d32dd11f29afa3590b79d8683aaddd05f48a02) Improve Druid metadata fetching resilience (#1584) (@mistercrunch)
|
||||
- [d6bc354](https://github.com/airbnb/superset/commit/d6bc354ff3e2f24aeb459dbc1413371f2b072306) [hotfix] fix support for presto DATE and TIMESTAMP type (@mistercrunch)
|
||||
- [7325a4f](https://github.com/airbnb/superset/commit/7325a4fb4ba08f554454534fe9efe3d0eea5a6ce) [hotfix] table view not group by without orderby fails (@mistercrunch)
|
||||
- [90f00c5](https://github.com/airbnb/superset/commit/90f00c5b292ff83802d35bac49a26e6b257de409) Minor documentation touchups (@mistercrunch)
|
||||
|
||||
### 0.13.1 (2016/11/10 18:01 +00:00)
|
||||
- [8539c42](https://github.com/airbnb/superset/commit/8539c423ea61d84e8e0a81317275713103f99a8a) v0.13.1 (@mistercrunch)
|
||||
- [e9bfbfc](https://github.com/airbnb/superset/commit/e9bfbfce84b5ab851c839c70adf5298b2538e9dc) Removing boat pic from README (@mistercrunch)
|
||||
- [6e4f066](https://github.com/airbnb/superset/commit/6e4f0664cb49d5e7144dadba7ccda548cf58e905) [hotfix] lint (@mistercrunch)
|
||||
- [3c920c9](https://github.com/airbnb/superset/commit/3c920c9d943540cc8ed0d6e3dfd2ae0eba3acb70) [hotfix] datatables import issues (@mistercrunch)
|
||||
- [15b67b2](https://github.com/airbnb/superset/commit/15b67b2c6c3c2982f6620fce5d30bd05951458f7) [WiP] rename project from Caravel to Superset (#1576) (@mistercrunch)
|
||||
|
||||
### 0.13.0 (2016/11/10 05:37 +00:00)
|
||||
- [973537f](https://github.com/airbnb/superset/commit/973537fd9a60766a6ee99bd2e7080aa7db21f540) [hotfix] resizing widgets (@mistercrunch)
|
||||
- [d70a744](https://github.com/airbnb/superset/commit/d70a74479df87908de7a7b4df7c24c6b267bf9e3) Make Sqllab a one-page app -- body not scrollable (#1551) (@vera-liu)
|
||||
- [946e4b7](https://github.com/airbnb/superset/commit/946e4b750afeebbfa16e6ce7e9fc61575136b237) Reactifying the dashboard (#1572) (@mistercrunch)
|
||||
- [9789e3f](https://github.com/airbnb/superset/commit/9789e3fb9b658e1f38080915132ae43c541e68e9) Bind data preview tabs to sql editor (#1573) (@vera-liu)
|
||||
- [6a15679](https://github.com/airbnb/superset/commit/6a15679d876c5c76d177b624a5d69da80ac75a3f) [hotfix] encode csv to utf-8 (@mistercrunch)
|
||||
- [ad1cd55](https://github.com/airbnb/superset/commit/ad1cd5577c231e4100f5a214fe7a4d372de96a04) Pass values from global store to fields in exploreV2 (#1561) (@vera-liu)
|
||||
- [55668ca](https://github.com/airbnb/superset/commit/55668ca6217f52924288f3849a0aa54c28d40ce1) Link to database-urls in databaseadd view (#1480) (@dirkkelly)
|
||||
- [0c221a2](https://github.com/airbnb/superset/commit/0c221a28d10abc8cf4e929e50fd788a56136a9cf) add slice_name and table_name for title (#1567) (@ascott)
|
||||
- [a475551](https://github.com/airbnb/superset/commit/a475551b23d5830ab2945f615328f31d48df36ca) [sqllab] bind alt+enter shortcut in AceEditor to run a query (#1554) (@mistercrunch)
|
||||
- [bad7676](https://github.com/airbnb/superset/commit/bad7676414662b28a4b72eb680fbf42a5c6281a5) Bump cryptography dependency to 1.5.3 (#1569) (@xrmx)
|
||||
|
||||
- [51c0470](https://github.com/airbnb/superset/commit/51c0470f0be438312e90f2efb1f2e37291a30ce4) [explore v2] populate dynamic select field options (#1543) (@ascott)
|
||||
- [4530047](https://github.com/airbnb/superset/commit/4530047c769ba6d5953ef1547b8507c62f657942) Added action buttons to Chart Container of explore V2 (#1562) (@vera-liu)
|
||||
- [1bf83c3](https://github.com/airbnb/superset/commit/1bf83c3bf78de422df1b21c3049d106b1cb29385) [explore-v2] render columns based on length of fieldSets array (#1559) (@ascott)
|
||||
- [bb6ab11](https://github.com/airbnb/superset/commit/bb6ab110013f2e29933fb9a70d6891d4486eb49d) Vliu link form data explore v2 (#1540) (@vera-liu)
|
||||
- [e4bd188](https://github.com/airbnb/superset/commit/e4bd1884d34a1949b986410ebc385b75945afff8) [druid] adding support for dimensionspecs (#1545) (@mistercrunch)
|
||||
- [4014a48](https://github.com/airbnb/superset/commit/4014a48f7df9fe166c77132f3d8d83cf615ac176) Added cache prop to ResultSet (#1552) (@vera-liu)
|
||||
- [97ded32](https://github.com/airbnb/superset/commit/97ded32415e9e32ba2c6a7e4556a0ed96034244a) Update linting instructions. (#1478) (@pinkythalli97)
|
||||
- [593ac08](https://github.com/airbnb/superset/commit/593ac081f06af5e95dc784597473d42aea52cf28) Added scroll bar and option to collapse for Sql Editor tool bar (#1532) (@vera-liu)
|
||||
- [69f0a4e](https://github.com/airbnb/superset/commit/69f0a4e1cb2c7775617a15a5ba709836a568210c) Put data preview in south pane (#1486) (@vera-liu)
|
||||
- [757e7de](https://github.com/airbnb/superset/commit/757e7de60cf7aa04f15160942ceaadb46daa15b5) add oracle time_grains (#1544) (@gschrader)
|
||||
- [1d7d546](https://github.com/airbnb/superset/commit/1d7d5469a925690d4b4fd1e7a3cdf37779acffb6) [hotfix] remove failing Druid test (@mistercrunch)
|
||||
- [98afc3e](https://github.com/airbnb/superset/commit/98afc3e590ef25d08fecf159bf4411ac292e95f0) Added setFilter(), containerID and getFilter() to (#1360) (@vera-liu)
|
||||
- [ea18979](https://github.com/airbnb/superset/commit/ea189790f160dc6419ac97d8f6740afa62ba6e78) [hotfix] druid dist_bar viz issues with non-str x values (@mistercrunch)
|
||||
- [6298707](https://github.com/airbnb/superset/commit/62987077fa31ebbedafbaa745b36527b7df0c9f7) Read the user origin specification. (#1541) (@bkyryliuk)
|
||||
- [3b9f7cb](https://github.com/airbnb/superset/commit/3b9f7cb3f1d0dd1387d01204259b5ce7f2469793) [hotfix] groupby may be a set (@mistercrunch)
|
||||
- [5882c7e](https://github.com/airbnb/superset/commit/5882c7e3447a06875e63b4424994a0a5e5fc58a5) Added jquery methods to ChartContainer to get world_map viz working in exploreV2 (#1443) (@vera-liu)
|
||||
- [77b6e2c](https://github.com/airbnb/superset/commit/77b6e2cd2e796d063dbc6d42934143bf45bba8b0) Get pivot table working in explore v2 (#1432) (@vera-liu)
|
||||
- [88b1f95](https://github.com/airbnb/superset/commit/88b1f956c7cd8bd457d04648447fb23700b859ae) [explore-v2] handle field overrides (#1535) (@ascott)
|
||||
- [d9b49ca](https://github.com/airbnb/superset/commit/d9b49ca2bc1eab3221fc329d0ab5a9b421746110) [exploreV2] remove /exploreV2 endpoint, add v2 bootstrap data to /explore endpoint (#1536) (@ascott)
|
||||
- [4156ad5](https://github.com/airbnb/superset/commit/4156ad5a3054f5194ea94b6fc146e53e4ccb0b57) [explore-v2] control panel fixes (#1529) (@ascott)
|
||||
- [ae46561](https://github.com/airbnb/superset/commit/ae465616482c8e76634728bcd6990fcfb3b752ad) Support week_ending_saturday for Druid. (#1491) (@bkyryliuk)
|
||||
- [1700a80](https://github.com/airbnb/superset/commit/1700a807e9a8ebc4cfb2749293308be733e42473) [sqllab] templating refactor (#1504) (@mistercrunch)
|
||||
- [0bab15b](https://github.com/airbnb/superset/commit/0bab15b2132ae769ce81519f2d27858ad6d0b187) Update INTHEWILD.md (#1526) (@shashanksingh)
|
||||
- [38d3075](https://github.com/airbnb/superset/commit/38d307555487d84b60dd6169006bbb6aa9fc87a5) [explore V2] render all control panels and fields dynamically for each vis type (#1493) (@ascott)
|
||||
- [1b124bf](https://github.com/airbnb/superset/commit/1b124bfb87862a25a7b904e05929c23f0c61d0e2) [druid] optimize Druid queries where possible (#1517) (@mistercrunch)
|
||||
- [cdf4dd0](https://github.com/airbnb/superset/commit/cdf4dd03024cff40f17845ab9b57ae6a6070e197) Add yearly and quarterly granularities to mysql engine backend (#1518) (@plumbeo)
|
||||
- [a13bed2](https://github.com/airbnb/superset/commit/a13bed2db685a9fa913676bd71b570c81a190c6e) Moved sqllab tests from core_tests to sqllab_tests (#1502) (@vera-liu)
|
||||
- [26318f9](https://github.com/airbnb/superset/commit/26318f94fef888a4b54a022bbbd44f269cfbf9b3) Moved queriesArray from render() to local state (#1505) (@vera-liu)
|
||||
- [769fb08](https://github.com/airbnb/superset/commit/769fb0820fbefd1e58ced40fa79d2d7c923091e4) Strip sql and remove ; for csv download. (#1508) (@bkyryliuk)
|
||||
- [5238053](https://github.com/airbnb/superset/commit/52380534f360cbb0e3d7ab46889066cd2df47440) Moved ajax call for fetching table metadata from SqlEditorLeftBar to actions (#1494) (@vera-liu)
|
||||
- [2fd2526](https://github.com/airbnb/superset/commit/2fd252604689693c957a1b6875a18872a59d5ec8) Add support for jinja templates in WHERE/HAVING clauses (#1442) (@mistercrunch)
|
||||
- [61509bb](https://github.com/airbnb/superset/commit/61509bbd446bbcc21f4f79229c88d82441d1fb98) [sqllab] surfacing more table metadata (indices, pk, fks) (#1485) (@mistercrunch)
|
||||
- [76499af](https://github.com/airbnb/superset/commit/76499afd8d28289cac0cf0f2d7316e6e64bab089) [pep8] allowing 90 chars per line (@mistercrunch)
|
||||
- [4023f32](https://github.com/airbnb/superset/commit/4023f328f7893fbe4b0e0af1612d598e1c931f72) [sqllab] run only the part of the query that is selected (#1479) (@mistercrunch)
|
||||
- [4f49cb5](https://github.com/airbnb/superset/commit/4f49cb555be68c5e1daed817d1137fbd1c3f4e3f) Celery uses separate db engine with NullPool. (#1492) (@bkyryliuk)
|
||||
- [4dc959a](https://github.com/airbnb/superset/commit/4dc959a3e4464ed38d4b5e580ae1fc009178e185) Revert "NullPool for the celery worker." (#1488) (@bkyryliuk)
|
||||
- [518fbf5](https://github.com/airbnb/superset/commit/518fbf562cca638cf14d97dfae92756091630eb2) Minor Fixes (#1484) (@ronbak)
|
||||
- [49828d3](https://github.com/airbnb/superset/commit/49828d3d9d51c02b13ce916a85cfe912bee43c54) add step to pypi build/push (@mistercrunch)
|
||||
- [248e6a7](https://github.com/airbnb/superset/commit/248e6a7b05fd4ef30c4f2c006d0df935da84e052) fix name for postgresql (#1482) (@willgroves)
|
||||
- [5561e6b](https://github.com/airbnb/superset/commit/5561e6b77086ffafb58c363a22e97a5800590e47) Fix celery module import in comments. (#1474) (@bkyryliuk)
|
||||
- [ab083b8](https://github.com/airbnb/superset/commit/ab083b86f35c6f01dfa16bf84c8c212bf21743cf) [sqllab] slide animations when adding/removing/toggling TableElement (#1472) (@mistercrunch)
|
||||
- [4bf5252](https://github.com/airbnb/superset/commit/4bf525222a609320acc28232f25b7651c54cfda0) [sqllab] add autocomplete to AceEditor for table and column names (#1475) (@mistercrunch)
|
||||
- [45efcb3](https://github.com/airbnb/superset/commit/45efcb381c0d0b53b9de72a3437ec980b201bab0) Added time filter to query search page (#1329) (@vera-liu)
|
||||
- [07a7736](https://github.com/airbnb/superset/commit/07a7736c71050c20dc04661ab3f1d21f58cb3b39) NullPool for the celery worker. (#1465) (@bkyryliuk)
|
||||
- [d2826ab](https://github.com/airbnb/superset/commit/d2826ab7af4da1b36816150b71002ed966c553cd) Added checkbox in dist_bar viz to enable sorting of bars based on x axis labels (#1379) (@vera-liu)
|
||||
- [6ab769f](https://github.com/airbnb/superset/commit/6ab769f38227788fbffb1eadb0e43c656f7c1da0) CHANGELOG for 0.12.0 (@mistercrunch)
|
||||
|
||||
### 0.12.0 (2016/10/28 16:40 +00:00)
|
||||
- [3e1cd2b](https://github.com/airbnb/caravel/commit/3e1cd2bdcabce219dc01c6ce7b80850ecd50f9ba) v0.12.0 (@mistercrunch)
|
||||
- [22784b7](https://github.com/airbnb/caravel/commit/22784b7f069d59e3fa7df03cfea84df9e147af13) run_specific_test: take the test as parameter (#1469) (@xrmx)
|
||||
- [c492261](https://github.com/airbnb/caravel/commit/c4922615eb707228cdc1badd49bf2d293c74a699) [sqllab] add column sort feature to TableElement (#1467) (@mistercrunch)
|
||||
- [7307dda](https://github.com/airbnb/caravel/commit/7307ddad3c9b60ec2178286cbc27a302e158de83) Highlight affected slices for filter change in dashboard view (#1439) (@vera-liu)
|
||||
- [c7ba143](https://github.com/airbnb/caravel/commit/c7ba143d039aff61302017329860cd3db432b0f6) Fix typo in sqllab docs (@mistercrunch)
|
||||
- [b242063](https://github.com/airbnb/caravel/commit/b24206387b09946df40a834db2d3b1deae21f865) [sqllab] optimizing React (#1438) (@mistercrunch)
|
||||
- [64d1964](https://github.com/airbnb/caravel/commit/64d196442fcd17f098ba6d71da8bad1f84bdbb5a) Added dashboard standalone page (#1429) (@vera-liu)
|
||||
- [5944643](https://github.com/airbnb/caravel/commit/5944643da67acb1ec38ed8d52f9ae6f58d7549ac) [sqllab] add support for Jinja templating (#1426) (@mistercrunch)
|
||||
- [8c5e495](https://github.com/airbnb/caravel/commit/8c5e4952727d7ff6e96e61c1a38de2e600b02208) Add github issue template (#1436) (@xrmx)
|
||||
- [bb23685](https://github.com/airbnb/caravel/commit/bb23685b9db623be89714153361ee3b03b46a39d) Added average metric AVG() to default metrics (#1413) (@vera-liu)
|
||||
- [940659b](https://github.com/airbnb/caravel/commit/940659bc14ed276a68478b66055356cf3b48ba29) [sqllab] some frontend tests (#1400) (@mistercrunch)
|
||||
- [7c59337](https://github.com/airbnb/caravel/commit/7c5933732bcb199e486ac8c4bf7ecec71013117d) Filter immune slices array stores strings. (#1402) (@bkyryliuk)
|
||||
- [89df2fc](https://github.com/airbnb/caravel/commit/89df2fcf76bdaca34dfef19a9d5bb752a9859c6d) Adjusted top margin of heatmap plot to get it working in V2 (#1361) (@vera-liu)
|
||||
- [174a199](https://github.com/airbnb/caravel/commit/174a199c30ad6c24505092975b814688e8a37292) [hotfix] Query search is unreachable (@mistercrunch)
|
||||
- [6f1e7c3](https://github.com/airbnb/caravel/commit/6f1e7c3016b53cf8d3c0e28dba3538861fe56086) Added url shortner for sharing query link (#1314) (@vera-liu)
|
||||
- [9f81e23](https://github.com/airbnb/caravel/commit/9f81e23f8f0698c94a9f4c34b49cbf3dda1e2e87) Fixed css class not being used by slice container (#1359) (@vera-liu)
|
||||
- [19fab6e](https://github.com/airbnb/caravel/commit/19fab6eea71bbd97974a0ef8dd74451011f3862f) Get table viz work in explore v2: Added d3 format to mock slice (#1353) (@vera-liu)
|
||||
- [63161b1](https://github.com/airbnb/caravel/commit/63161b11c347d5a6d62f7ae7dc91fa3c30b5dc93) [sqllab] proper, quoted, select * on the server side (#1404) (@mistercrunch)
|
||||
- [4f886d6](https://github.com/airbnb/caravel/commit/4f886d65ecc208149cf9b7663492a81df868dcc2) Fix None view_menues in permissions. (#1409) (@bkyryliuk)
|
||||
- [62e0e19](https://github.com/airbnb/caravel/commit/62e0e195e8eaa53afa41a5fec89cc4486a7114a3) [docfix] d3.format docs have moved (@mistercrunch)
|
||||
- [e9d4749](https://github.com/airbnb/caravel/commit/e9d4749f4470aee294f1351baa9422173a2a62c8) [hotfix] sqllab presto (@mistercrunch)
|
||||
- [93f8e7d](https://github.com/airbnb/caravel/commit/93f8e7d8e9b25a1aaf07e2b0c3772c327e523f0e) Fix the js build running out of heap space (#1408) (@mistercrunch)
|
||||
- [3dea6e0](https://github.com/airbnb/caravel/commit/3dea6e0da538ed1c0a7761ccbf97bd8f12ac7f2f) [sqllab] adding more descriptive labels to left panel (#1407) (@mistercrunch)
|
||||
- [6fb3b30](https://github.com/airbnb/caravel/commit/6fb3b305ad23c27d0555ded2ab80820000fdec50) [sqllab] add support for results backends (#1377) (@mistercrunch)
|
||||
- [7dfe891](https://github.com/airbnb/caravel/commit/7dfe891cc1d294bd55982d63c9c1eb8f9e9e4c25) [hotfix] timeseries_limit_metric: Not a valid choice (@mistercrunch)
|
||||
- [5c3966a](https://github.com/airbnb/caravel/commit/5c3966a32d454a2fc7fcabd75c66594662361586) Override the role with perms for given datasources. (#1399) (@bkyryliuk)
|
||||
- [c198535](https://github.com/airbnb/caravel/commit/c198535292869ae1ced6d66d08de536188be7e05) Change slice ids in the position json during dashboard import. (#1380) (@bkyryliuk)
|
||||
- [ece69fb](https://github.com/airbnb/caravel/commit/ece69fbb75086cb8855789881a32c6daca4be483) Fix migration for make creator owners (#1262) (@ShengyaoQian)
|
||||
- [458651f](https://github.com/airbnb/caravel/commit/458651fa3e0098f35412772b622e7c0b63d34299) Add parens for custom where and having (#1337) (@yejianye)
|
||||
- [b2f7081](https://github.com/airbnb/caravel/commit/b2f7081c6f3dde80846493330f1ec1e5fa3a414c) bumping versions of JS packages to latest (#1352) (@mistercrunch)
|
||||
- [c255e89](https://github.com/airbnb/caravel/commit/c255e89219c209b5a5371134fbb9a9b90036ded4) [sqllab] show partition metadata for Presto (#1342) (@mistercrunch)
|
||||
- [2edce5b](https://github.com/airbnb/caravel/commit/2edce5bf8afa7b74fdafd8ab8a2e6394d46e6391) Enable "Run Query in New Tab" in SQL Lab (#1343) (@nickbarnwell)
|
||||
- [8f29944](https://github.com/airbnb/caravel/commit/8f299448ea954f75f576399f6bc113dd8ac1c824) [bugfix] text as subquery fails with 'Series Limit' (#1347) (@mistercrunch)
|
||||
- [ecb951b](https://github.com/airbnb/caravel/commit/ecb951bb7474b9c829d0eef12792f6c146757dba) Specify the metric to order by for Series Limit (#1351) (@mistercrunch)
|
||||
- [0dff6a9](https://github.com/airbnb/caravel/commit/0dff6a9030d8f2ff7a03654258f3b02f01d9d57e) Add quarter time grain to postgresql (#1362) (@xrmx)
|
||||
- [2095095](https://github.com/airbnb/caravel/commit/2095095895d9cf5bc8131fb51fbb4868fae124dc) Fixed big number issue (#1355) (@vera-liu)
|
||||
- [4fc8a17](https://github.com/airbnb/caravel/commit/4fc8a17f2ae18dcc2be778e52b3d3ed7be29e95a) [hotfix] use instead of prod for Travis build, take 3 (@mistercrunch)
|
||||
- [3cb737f](https://github.com/airbnb/caravel/commit/3cb737f8c890b018bd6b3275047a02f79abb7444) [hotfix] use instead of prod for Travis build, take2 (@mistercrunch)
|
||||
- [7449aa8](https://github.com/airbnb/caravel/commit/7449aa813b8b695e6dc3b06eb25004bc2a55614f) [hotfix] use instead of prod for Travis build (@mistercrunch)
|
||||
- [7a3bcc2](https://github.com/airbnb/caravel/commit/7a3bcc227cccdec756404ab6140a6ba0d3882419) [bugfix] NaN issue in Big Number viz (#1346) (@mistercrunch)
|
||||
- [b669a14](https://github.com/airbnb/caravel/commit/b669a140816b950237b7d66b73ac6af392f28d8a) [explore-v2] make chart container work with existing visualization files (#1333) (@ascott)
|
||||
- [9db4cc8](https://github.com/airbnb/caravel/commit/9db4cc8c6d0422f28357dc4283089ee3dde9a08e) add node/npm versions to contributing.md (#1344) (@ascott)
|
||||
- [65c744f](https://github.com/airbnb/caravel/commit/65c744f2424d111e950b385630bd8a13b3fa003e) Fix utc time calculation if provided datetime has tz info (#1287) (@labeneator)
|
||||
- [82bcadf](https://github.com/airbnb/caravel/commit/82bcadf7f829183fbf6feca81dcc6c69f08c358c) Moving 'CSS TEmplates' to the Manage menu category (#1336) (@mistercrunch)
|
||||
- [f0f8478](https://github.com/airbnb/caravel/commit/f0f8478922cbe8e4ac754fddcfd6183032bbb893) Revert "Override the role with perms for give datasources." (#1345) (@bkyryliuk)
|
||||
- [40e7057](https://github.com/airbnb/caravel/commit/40e7057bcec55421275d0121d365a2e4f2d38a29) Override the role with perms for give datasources. (#1335) (@bkyryliuk)
|
||||
- [11a8e35](https://github.com/airbnb/caravel/commit/11a8e3591d281a8cde6fb0ab57ed54ec97035e23) Some dashboard import/export fixes. (#1340) (@bkyryliuk)
|
||||
- [5bea398](https://github.com/airbnb/caravel/commit/5bea3986b26359eb98c62246c34729e2d0cc5a1b) [hotfix] handling json errors in explore view (@mistercrunch)
|
||||
- [89cb726](https://github.com/airbnb/caravel/commit/89cb726284b2a4f2707f26d3004ef9ae59b33970) [hotfix] explore errors are not raise properly 2 (@mistercrunch)
|
||||
- [4e9392d](https://github.com/airbnb/caravel/commit/4e9392d21bf7f43e8189eb4478cf9d737c3616bd) [hotfix] explore errors are not raise properly (@mistercrunch)
|
||||
- [b785d27](https://github.com/airbnb/caravel/commit/b785d27241e9f22dcb6a880414500ce8f9e67eb3) Taking out object spread operator (#1311) (@vera-liu)
|
||||
- [451860a](https://github.com/airbnb/caravel/commit/451860afcab971a0a16b521a7c884d1c4d910986) remove #app styling (#1312) (@ascott)
|
||||
- [4cf4e38](https://github.com/airbnb/caravel/commit/4cf4e3805c4d0a217fa6232ba1d6ee3a68c86ed2) Bugfix when there's only date filter in FilterBox (no groupby) (#1326) (@yejianye)
|
||||
- [ef2670c](https://github.com/airbnb/caravel/commit/ef2670ca32e8ba0a04f9dc7899db55812e2f9b46) Using inheritance scheme to organize db specific code (#1294) (@mistercrunch)
|
||||
- [8626c80](https://github.com/airbnb/caravel/commit/8626c80d3a491b842f8262c5807154903c107747) Stop duplicating datasources (#1321) (@bkyryliuk)
|
||||
- [5cb3cc2](https://github.com/airbnb/caravel/commit/5cb3cc2ed8c8c2f0295da7ecdf8ec33a526acee1) polyfill es2015 in older browsers and for phantomjs (#1323) (@ascott)
|
||||
- [73cd2ea](https://github.com/airbnb/caravel/commit/73cd2ea3b17574f8fef1112aa5e5b39f843882f6) Import / export of the dashboards. (#1197) (@bkyryliuk)
|
||||
- [cd2ab42](https://github.com/airbnb/caravel/commit/cd2ab42abcd2ea5f93dd285321c448c97abf4580) do not overwrite the stored password with the masked password (#1209) (@dennisobrien)
|
||||
- [bf1f5ea](https://github.com/airbnb/caravel/commit/bf1f5ea3de23a62eca4f823474119e4c15270738) [sqllab] use encodeURIComponent for copy query URL (#1317) (@mistercrunch)
|
||||
- [79460ab](https://github.com/airbnb/caravel/commit/79460abdd230b2d53a9f2da15ac5160ba6db400b) [SQLLab] Fix the usage of Redux DevTools Enhancer (#1278) (@zalmoxisus)
|
||||
- [1e6e144](https://github.com/airbnb/caravel/commit/1e6e144d24da38aef0d306889dc3b8f962ca4b32) Fixed viewing dashboards as anonymous (#1320) (@Rapsutin)
|
||||
- [fe66557](https://github.com/airbnb/caravel/commit/fe66557bbb4848feed762e859abcd5884d72d369) [explore-v2] hook up ExploreViewContainer to state and add specs (#1300) (@ascott)
|
||||
- [f8e2ce6](https://github.com/airbnb/caravel/commit/f8e2ce6ff367047405be60d7cbcfd68e4f4521d8) Change status color in tab to match with success (#1247) (@vera-liu)
|
||||
- [1967743](https://github.com/airbnb/caravel/commit/19677438c23a9beab907b5b51d99f54ef62c8f92) Add cascade delete to the 1 to composite relationships. (#1295) (@bkyryliuk)
|
||||
- [9012b11](https://github.com/airbnb/caravel/commit/9012b11101805c9810745f049363223f110bc93e) add ImmutableMultiDict back to views.py (#1298) (@ascott)
|
||||
- [f70d301](https://github.com/airbnb/caravel/commit/f70d301f0d37fe6c4f94cd7d6026a72a56087d34) Refactor the explore view (#1252) (@mistercrunch)
|
||||
- [b7d1f78](https://github.com/airbnb/caravel/commit/b7d1f78f5e38bdcc99c7b6a15645092f5d76ca4a) Put formData in store (#1281) (@vera-liu)
|
||||
- [3384e75](https://github.com/airbnb/caravel/commit/3384e7598ee9e82f8b83ae71e3e5b587c6546443) Fixing explore actions & slice controller interactions (#1292) (@mistercrunch)
|
||||
- [382b8e8](https://github.com/airbnb/caravel/commit/382b8e85da36ed1a8f235775b883e54f5db90ab7) [explore v2] add scrollbar to control panel container (#1284) (@ascott)
|
||||
- [0a3121c](https://github.com/airbnb/caravel/commit/0a3121c2438f74ab1bd3730eac7a11bad0b317f5) [doc] installation, load examples before init (@mistercrunch)
|
||||
- [ecfe1a2](https://github.com/airbnb/caravel/commit/ecfe1a241786bc1fae1d5d3c45b45e21703e33a7) Updated eslinter for object rest spread (#1289) (@vera-liu)
|
||||
- [609ae22](https://github.com/airbnb/caravel/commit/609ae22bdabfb9a9cb99d1a4bfba62367f03a8d5) less number of default workers. (#1206) (@StefanoOrdine)
|
||||
- [94578cb](https://github.com/airbnb/caravel/commit/94578cb6a7e91cb4ca741a8f437636d264b56322) reduce chunk size for countries table (#1279) (@vivo75)
|
||||
- [8a5f050](https://github.com/airbnb/caravel/commit/8a5f050f6cbf2a4eca7f2799a244f94218bb11c1) [explore v2] fix explorev2 chart errors (#1277) (@ascott)
|
||||
- [5c5b393](https://github.com/airbnb/caravel/commit/5c5b393f2fd7be5a4496c0ea0a0808f720fdc904) Change userId, dbId to username and dbname (#1274) (@vera-liu)
|
||||
- [f837733](https://github.com/airbnb/caravel/commit/f837733d858643152304469c899c096e31d2bf24) [explorev2] chart and controls (#1251) (@ascott)
|
||||
- [66b498d](https://github.com/airbnb/caravel/commit/66b498de25b6bb3145eb441f64ef7fdaffc5a747) Added controls for Table Viz (#1253) (@vera-liu)
|
||||
- [659bf6d](https://github.com/airbnb/caravel/commit/659bf6d7e80d70def5b6c46a9d8a3a262e37a13e) Moved time column and grains to models.py (#1255) (@vera-liu)
|
||||
- [a8a1690](https://github.com/airbnb/caravel/commit/a8a16900e7497083f14de3b6dc50063f845401b7) docs: add libsasl as system requirement on linux (#1257) (@xrmx)
|
||||
- [e50b59e](https://github.com/airbnb/caravel/commit/e50b59e5535bc653e3321a2630287540ef99df86) docs: document that gunicorn does not work on windows (#1258) (@xrmx)
|
||||
- [231804e](https://github.com/airbnb/caravel/commit/231804e2b47771ed6b31cb48e36c2f417973cad1) CHANGELOG: Add proper credit to tan31989 for #744 (#1259) (@xrmx)
|
||||
- [421a86a](https://github.com/airbnb/caravel/commit/421a86ade5ac5ec4d147bdfb913ce32a7004b455) Some polish on query search (#1222) (@vera-liu)
|
||||
- [140a055](https://github.com/airbnb/caravel/commit/140a055e4ef85080bbe3e7defdfeb2dd7b828b58) [docs] add line in installation instructions (@mistercrunch)
|
||||
- [5bf86d9](https://github.com/airbnb/caravel/commit/5bf86d91ec9911e6155335ff1f97dc48c2c16a21) [docs] suggest to upgrade pip and setuptools (@mistercrunch)
|
||||
- [715cdd9](https://github.com/airbnb/caravel/commit/715cdd98fb213e06c687ee8587ded9437039fb2d) Changelog for 0.11.0 (@mistercrunch)
|
||||
|
||||
### 0.11.0 (2016/10/05 04:27 +00:00)
|
||||
- [7a01d9d](https://github.com/airbnb/caravel/commit/7a01d9dbcbbd7678960c33c8cca1b13680290ac7) v0.11.0 (@mistercrunch)
|
||||
- [58dfa43](https://github.com/airbnb/caravel/commit/58dfa436ee53aac185b457e721bfe2303b8d006a) Do not shadow _ function. (#1254) (@bkyryliuk)
|
||||
@@ -100,7 +949,6 @@
|
||||
- [508feb2](https://github.com/airbnb/caravel/commit/508feb2bad581068a47193e06d35ed5926b25191) [hotfix] getting presto on track
|
||||
- [9f8eef4](https://github.com/airbnb/caravel/commit/9f8eef498c93ce2945e3d17cda1c3d2a24d05c92) [theme] a little bit less blue (#1024) (@mistercrunch)
|
||||
|
||||
### airbnb_prod.0.10.0.2 (2016/08/30 18:08 +00:00)
|
||||
- [561828c](https://github.com/airbnb/caravel/commit/561828c2f890e179c4116f773cc7507103804dc6) [SQL Lab] moving the db/schema/table select to the left (#1038) (@mistercrunch)
|
||||
- [fc1e637](https://github.com/airbnb/caravel/commit/fc1e63761cc86a5673433b0e2efc0081325684d3) Adding celery_tests.py (@mistercrunch)
|
||||
- [38b8db8](https://github.com/airbnb/caravel/commit/38b8db8051490375d021c51fb76a9f1bdc3ccf1f) SQL Lab - A multi-tab SQL editor (#514) (@mistercrunch)
|
||||
@@ -123,7 +971,6 @@
|
||||
- [c7467f5](https://github.com/airbnb/caravel/commit/c7467f544c10281538b8504add9510f3fcf20e60) Documenting making your own build (#990) (@mistercrunch)
|
||||
- [30ef8eb](https://github.com/airbnb/caravel/commit/30ef8eba37073c2cb0d2a6356fe3a9bcabab4913) [ui] hack bootswatch/cosmo theme to get better tabs for sql-lab (and other things) (#975) (@ascott)
|
||||
|
||||
### airbnb_prod.0.10.0.1 (2016/08/18 07:02 +00:00)
|
||||
- [23a5463](https://github.com/airbnb/caravel/commit/23a54632081aa589e05a820ac774c8b4f6993252) Hack around the "last migration doesn't stamp" Alembic bug (#967) (@mistercrunch)
|
||||
- [84213ab](https://github.com/airbnb/caravel/commit/84213ab8cd27369f796131c68c075f12f8bd0ce2) [line] growth vs factor option for 'Period Ratio' (#970) (@mistercrunch)
|
||||
- [379cf6c](https://github.com/airbnb/caravel/commit/379cf6cbd9527617b6aae60501ad2fa4e252bb8f) [ui] tweaks and improvements (#965) (@ascott)
|
||||
|
||||
212
CONTRIBUTING.md
@@ -18,6 +18,9 @@ If you are reporting a bug, please include:
|
||||
troubleshooting.
|
||||
- Detailed steps to reproduce the bug.
|
||||
|
||||
When you post python stack traces please quote them using
|
||||
[markdown blocks](https://help.github.com/articles/creating-and-highlighting-code-blocks/).
|
||||
|
||||
### Fix Bugs
|
||||
|
||||
Look through the GitHub issues for bugs. Anything tagged with "bug" is
|
||||
@@ -26,12 +29,12 @@ open to whoever wants to implement it.
|
||||
### Implement Features
|
||||
|
||||
Look through the GitHub issues for features. Anything tagged with
|
||||
"feature" is open to whoever wants to implement it.
|
||||
"feature" or "starter_task" is open to whoever wants to implement it.
|
||||
|
||||
### Documentation
|
||||
|
||||
Caravel could always use better documentation,
|
||||
whether as part of the official Caravel docs,
|
||||
Superset could always use better documentation,
|
||||
whether as part of the official Superset docs,
|
||||
in docstrings, `docs/*.rst` or even on the web as blog posts or
|
||||
articles.
|
||||
|
||||
@@ -47,18 +50,123 @@ If you are proposing a feature:
|
||||
- Remember that this is a volunteer-driven project, and that
|
||||
contributions are welcome :)
|
||||
|
||||
## Latest Documentation
|
||||
## Pull Request Guidelines
|
||||
|
||||
Latest documentation and tutorial are available [here](http://airbnb.io/caravel)
|
||||
Before you submit a pull request from your forked repo, check that it
|
||||
meets these guidelines:
|
||||
|
||||
1. The pull request should include tests, either as doctests,
|
||||
unit tests, or both.
|
||||
2. If the pull request adds functionality, the docs should be updated
|
||||
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.7, and ideally python 3.4+.
|
||||
``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.
|
||||
6. If you are asked to update your pull request with some changes there's
|
||||
no need to create a new one. Push your changes to the same branch.
|
||||
|
||||
## Documentation
|
||||
|
||||
The latest documentation and tutorial are available [here](https://superset.incubator.apache.org/).
|
||||
|
||||
Contributing to the official documentation is relatively easy, once you've setup
|
||||
your environment and done an edit end-to-end. The docs can be found in the
|
||||
`docs/` subdirectory of the repository, and are written in the
|
||||
[reStructuredText format](https://en.wikipedia.org/wiki/ReStructuredText) (.rst).
|
||||
If you've written Markdown before, you'll find the reStructuredText format familiar.
|
||||
|
||||
Superset uses [Sphinx](http://www.sphinx-doc.org/en/1.5.1/) to convert the rst files
|
||||
in `docs/` to the final HTML output users see.
|
||||
|
||||
Before you start changing the docs, you'll want to
|
||||
[fork the Superset project on Github](https://help.github.com/articles/fork-a-repo/).
|
||||
Once that new repository has been created, clone it on your local machine:
|
||||
|
||||
git clone git@github.com:your_username/superset.git
|
||||
|
||||
At this point, you may also want to create a
|
||||
[Python virtual environment](http://docs.python-guide.org/en/latest/dev/virtualenvs/)
|
||||
to manage the Python packages you're about to install:
|
||||
|
||||
virtualenv superset-dev
|
||||
source superset-dev/bin/activate
|
||||
|
||||
Finally, to make changes to the rst files and build the docs using Sphinx,
|
||||
you'll need to install a handful of dependencies from the repo you cloned:
|
||||
|
||||
cd superset
|
||||
pip install -r dev-reqs-for-docs.txt
|
||||
|
||||
To get the feel for how to edit and build the docs, let's edit a file, build
|
||||
the docs and see our changes in action. First, you'll want to
|
||||
[create a new branch](https://git-scm.com/book/en/v2/Git-Branching-Basic-Branching-and-Merging)
|
||||
to work on your changes:
|
||||
|
||||
git checkout -b changes-to-docs
|
||||
|
||||
Now, go ahead and edit one of the files under `docs/`, say `docs/tutorial.rst`
|
||||
- change it however you want. Check out the
|
||||
[ReStructuredText Primer](http://docutils.sourceforge.net/docs/user/rst/quickstart.html)
|
||||
for a reference on the formatting of the rst files.
|
||||
|
||||
Once you've made your changes, run this command from the root of the Superset
|
||||
repo to convert the docs into HTML:
|
||||
|
||||
python setup.py build_sphinx
|
||||
|
||||
You'll see a lot of output as Sphinx handles the conversion. After it's done, the
|
||||
HTML Sphinx generated should be in `docs/_build/html`. Go ahead and navigate there
|
||||
and start a simple web server so we can check out the docs in a browser:
|
||||
|
||||
cd docs/_build/html
|
||||
python -m SimpleHTTPServer
|
||||
|
||||
This will start a small Python web server listening on port 8000. Point your
|
||||
browser to [http://localhost:8000/](http://localhost:8000/), find the file
|
||||
you edited earlier, and check out your changes!
|
||||
|
||||
If you've made a change you'd like to contribute to the actual docs, just commit
|
||||
your code, push your new branch to Github:
|
||||
|
||||
git add docs/tutorial.rst
|
||||
git commit -m 'Awesome new change to tutorial'
|
||||
git push origin changes-to-docs
|
||||
|
||||
Then, [open a pull request](https://help.github.com/articles/about-pull-requests/).
|
||||
|
||||
If you're adding new images to the documentation, you'll notice that the images
|
||||
referenced in the rst, e.g.
|
||||
|
||||
.. image:: _static/img/tutorial/tutorial_01_sources_database.png
|
||||
|
||||
aren't actually included in that directory. _Instead_, you'll want to add and commit
|
||||
images (and any other static assets) to the _superset/assets/images_ directory.
|
||||
When the docs are being pushed to [Apache Superset (incubating)](https://superset.incubator.apache.org/), images
|
||||
will be moved from there to the _\_static/img_ directory, just like they're referenced
|
||||
in the docs.
|
||||
|
||||
For example, the image referenced above actually lives in
|
||||
|
||||
superset/assets/images/tutorial
|
||||
|
||||
Since the image is moved during the documentation build process, the docs reference the
|
||||
image in
|
||||
|
||||
_static/img/tutorial
|
||||
|
||||
instead.
|
||||
|
||||
## Setting up a Python development environment
|
||||
|
||||
Check the [OS dependencies](http://airbnb.io/caravel/installation.html#os-dependencies) before follows these steps.
|
||||
Check the [OS dependencies](https://superset.incubator.apache.org/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:airbnb/caravel.git
|
||||
# git clone git@github.com:apache/incubator-superset.git
|
||||
|
||||
# [optional] setup a virtual env and activate it
|
||||
virtualenv env
|
||||
@@ -68,30 +176,30 @@ Check the [OS dependencies](http://airbnb.io/caravel/installation.html#os-depend
|
||||
python setup.py develop
|
||||
|
||||
# Create an admin user
|
||||
fabmanager create-admin --app caravel
|
||||
fabmanager create-admin --app superset
|
||||
|
||||
# Initialize the database
|
||||
caravel db upgrade
|
||||
superset db upgrade
|
||||
|
||||
# Create default roles and permissions
|
||||
caravel init
|
||||
superset init
|
||||
|
||||
# Load some data to play with
|
||||
caravel load_examples
|
||||
superset load_examples
|
||||
|
||||
# start a dev web server
|
||||
caravel runserver -d
|
||||
superset runserver -d
|
||||
|
||||
|
||||
## Setting up the node / npm javascript environment
|
||||
|
||||
`caravel/assets` contains all npm-managed, front end assets.
|
||||
`superset/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.
|
||||
Make sure you are using recent versions of node and npm. No problems have been found with node>=5.10 and 4.0. > npm>=3.9.
|
||||
|
||||
### Using npm to generate bundled files
|
||||
|
||||
@@ -112,18 +220,26 @@ export PATH="$HOME/.npm-packages/bin:$PATH"
|
||||
|
||||
#### npm packages
|
||||
To install third party libraries defined in `package.json`, run the
|
||||
following within the `caravel/assets/` directory which will install them in a
|
||||
following within the `superset/assets/` directory which will install them in a
|
||||
new `node_modules/` folder within `assets/`.
|
||||
|
||||
```
|
||||
npm install
|
||||
```bash
|
||||
# from the root of the repository, move to where our JS package.json lives
|
||||
cd superset/assets/
|
||||
# install yarn, a replacement for `npm install` that is faster and more deterministic
|
||||
npm install -g yarn
|
||||
# run yarn to fetch all the dependencies
|
||||
yarn
|
||||
```
|
||||
|
||||
To parse and generate bundled files for caravel, run either of the
|
||||
To parse and generate bundled files for superset, 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.
|
||||
|
||||
```
|
||||
# Copies a conf file from the frontend to the backend
|
||||
npm run sync-backend
|
||||
|
||||
# Compiles the production / optimized js & css
|
||||
npm run prod
|
||||
|
||||
@@ -135,19 +251,24 @@ For every development session you will have to start a flask dev server
|
||||
as well as an npm watcher
|
||||
|
||||
```
|
||||
caravel runserver -d -p 8081
|
||||
superset runserver -d -p 8081
|
||||
npm run dev
|
||||
```
|
||||
|
||||
## Testing
|
||||
|
||||
Before running python unit tests, please setup local testing environment:
|
||||
```
|
||||
pip install -r dev-reqs.txt
|
||||
```
|
||||
|
||||
Python tests can be run with:
|
||||
|
||||
./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
|
||||
cd /superset/superset/assets/javascripts
|
||||
npm i
|
||||
npm run test
|
||||
|
||||
@@ -157,13 +278,13 @@ Lint the project with:
|
||||
|
||||
# for python changes
|
||||
flake8 changes tests
|
||||
flake8 changes caravel
|
||||
flake8 changes superset
|
||||
|
||||
# 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.
|
||||
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 Superset 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*
|
||||
```
|
||||
@@ -193,42 +314,25 @@ Generate the documentation with:
|
||||
cd docs && ./build.sh
|
||||
|
||||
## CSS Themes
|
||||
As part of the npm build process, CSS for Caravel is compiled from `Less`, a dynamic stylesheet language.
|
||||
As part of the npm build process, CSS for Superset is compiled from `Less`, a dynamic stylesheet language.
|
||||
|
||||
It's possible to customize or add your own theme to Caravel, either by overriding CSS rules or preferably
|
||||
It's possible to customize or add your own theme to Superset, 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 Caravel are derived from
|
||||
The `variables.less` and `bootswatch.less` files that ship with Superset 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]
|
||||
|
||||
## Pull Request Guidelines
|
||||
|
||||
Before you submit a pull request from your forked repo, check that it
|
||||
meets these guidelines:
|
||||
|
||||
1. The pull request should include tests, either as doctests,
|
||||
unit tests, or both.
|
||||
2. If the pull request adds functionality, the docs should be updated
|
||||
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.
|
||||
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
|
||||
We use [Babel](http://babel.pocoo.org/en/latest/) to translate Superset. 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
|
||||
`LANGUAGES` parameter to your `superset_config.py`. Having more than one
|
||||
options here will add a language selection dropdown on the right side of the
|
||||
navigation bar.
|
||||
|
||||
@@ -241,23 +345,23 @@ navigation bar.
|
||||
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
|
||||
pybabel init -i ./babel/messages.pot -d superset/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/
|
||||
fabmanager babel-extract --target superset/translations/
|
||||
|
||||
You can then translate the strings gathered in files located under
|
||||
`caravel/translation`, where there's one per language. For the translations
|
||||
`superset/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/
|
||||
fabmanager babel-compile --target superset/translations/
|
||||
|
||||
|
||||
## Adding new datasources
|
||||
|
||||
1. Create Models and Views for the datasource, add them under caravel folder, like a new my_models.py
|
||||
1. Create Models and Views for the datasource, add them under superset folder, like a new my_models.py
|
||||
with models for cluster, datasources, columns and metrics and my_views.py with clustermodelview
|
||||
and datasourcemodelview.
|
||||
|
||||
@@ -267,6 +371,12 @@ to take effect, they need to be compiled using this command:
|
||||
|
||||
For example:
|
||||
|
||||
`ADDITIONAL_MODULE_DS_MAP = {'caravel.my_models': ['MyDatasource', 'MyOtherDatasource']}`
|
||||
`ADDITIONAL_MODULE_DS_MAP = {'superset.my_models': ['MyDatasource', 'MyOtherDatasource']}`
|
||||
|
||||
This means it'll register MyDatasource and MyOtherDatasource in caravel.my_models module in the source registry.
|
||||
This means it'll register MyDatasource and MyOtherDatasource in superset.my_models module in the source registry.
|
||||
|
||||
## Creating a new visualization type
|
||||
|
||||
Here's an example as a Github PR with comments that describe what the
|
||||
different sections of the code do:
|
||||
https://github.com/apache/incubator-superset/pull/3013
|
||||
|
||||
14
INTHEWILD.md
@@ -1,14 +0,0 @@
|
||||
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
|
||||
19
ISSUE_TEMPLATE.md
Normal file
@@ -0,0 +1,19 @@
|
||||
Make sure these boxes are checked before submitting your issue - thank you!
|
||||
|
||||
- [ ] I have checked the superset logs for python stacktraces and included it here as text if any
|
||||
- [ ] I have reproduced the issue with at least the latest released version of superset
|
||||
- [ ] I have checked the issue tracker for the same issue and I haven't found one similar
|
||||
|
||||
|
||||
### Superset version
|
||||
|
||||
|
||||
### Expected results
|
||||
|
||||
|
||||
### Actual results
|
||||
|
||||
|
||||
### Steps to reproduce
|
||||
|
||||
|
||||
16
MANIFEST.in
@@ -1,9 +1,9 @@
|
||||
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-include superset/templates *
|
||||
recursive-include superset/static *
|
||||
recursive-exclude superset/static/assets/node_modules *
|
||||
recursive-include superset/static/assets/node_modules/font-awesome *
|
||||
recursive-exclude superset/static/docs *
|
||||
recursive-exclude superset/static/spec *
|
||||
recursive-exclude tests *
|
||||
recursive-include caravel/data *
|
||||
recursive-include caravel/migrations *
|
||||
recursive-include superset/data *
|
||||
recursive-include superset/migrations *
|
||||
|
||||
208
README.md
@@ -1,60 +1,75 @@
|
||||
Caravel
|
||||
Superset
|
||||
=========
|
||||
<img src="http://i.imgur.com/H0Kyvyi.jpg" style="border-radius: 20px; box-shadow:5px 5px 5px gray;" alt="Caravel" width="500"/>
|
||||
|
||||
[](https://travis-ci.org/airbnb/caravel)
|
||||
[](https://badge.fury.io/py/caravel)
|
||||
[](https://coveralls.io/github/airbnb/caravel?branch=master)
|
||||
[](https://codeclimate.com/github/airbnb/caravel/coverage)
|
||||
[](https://landscape.io/github/airbnb/caravel/master)
|
||||
[](https://codeclimate.com/github/airbnb/caravel)
|
||||
[](https://pypi.python.org/pypi/caravel)
|
||||
[](https://requires.io/github/airbnb/caravel/requirements/?branch=master)
|
||||
[](https://gitter.im/airbnb/caravel?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
[](http://airbnb.io/caravel/)
|
||||
[](https://david-dm.org/airbnb/caravel?path=caravel/assets)
|
||||
[](https://travis-ci.org/apache/incubator-superset)
|
||||
[](https://badge.fury.io/py/superset)
|
||||
[](https://coveralls.io/github/apache/incubator-superset?branch=master)
|
||||
[](https://pypi.python.org/pypi/superset)
|
||||
[](https://requires.io/github/apache/incubator-superset/requirements/?branch=master)
|
||||
[](https://gitter.im/apache/incubator-superset?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
[](https://superset.incubator.apache.org)
|
||||
[](https://david-dm.org/apache/incubator-superset?path=superset/assets)
|
||||
|
||||
Caravel is a data exploration platform designed to be visual, intuitive
|
||||
and interactive.
|
||||
<img
|
||||
src="https://cloud.githubusercontent.com/assets/130878/20946612/49a8a25c-bbc0-11e6-8314-10bef902af51.png"
|
||||
alt="Superset"
|
||||
width="500"
|
||||
/>
|
||||
|
||||
[this project used to be named **Panoramix**]
|
||||
**Apache Superset** (incubating) is a modern, enterprise-ready
|
||||
business intelligence web application
|
||||
|
||||
[this project used to be named **Caravel**, and **Panoramix** in the past]
|
||||
|
||||
|
||||
Screenshots & Gifs
|
||||
------------------
|
||||

|
||||
|
||||
---
|
||||

|
||||
**View Dashboards**
|
||||
|
||||
---
|
||||

|
||||

|
||||
|
||||
---
|
||||

|
||||
<br/>
|
||||
|
||||
---
|
||||

|
||||
**View/Edit a Slice**
|
||||
|
||||
Caravel
|
||||
---------
|
||||
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**.
|
||||

|
||||
|
||||
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
|
||||
<br/>
|
||||
|
||||
**Query and Visualize with SQL Lab**
|
||||
|
||||

|
||||
|
||||
<br/>
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
Apache Superset
|
||||
---------------
|
||||
Apache Superset is a data exploration and visualization web application.
|
||||
|
||||
Superset provides:
|
||||
* An intuitive interface to explore and visualize datasets, and
|
||||
create interactive dashboards.
|
||||
* A wide array of beautiful visualizations to showcase your data.
|
||||
* Easy, code-free, user flows to drill down and slice and dice the data
|
||||
underlying exposed dashboards. The dashboards and charts acts as a starting
|
||||
point for deeper analysis.
|
||||
* A state of the art SQL editor/IDE exposing a rich metadata browser, and
|
||||
an easy workflow to create visualizations out of any result set.
|
||||
* 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 Caravel to stay blazing fast while
|
||||
on who can access which product features and datasets.
|
||||
Integration with major
|
||||
authentication backends (database, OpenID, LDAP, OAuth, REMOTE_USER, ...)
|
||||
* A lightweight semantic layer, allowing to control how data sources are
|
||||
exposed to the user by defining dimensions and metrics
|
||||
* Out of the box support for most SQL-speaking databases
|
||||
* Deep integration with Druid allows for Superset to stay blazing fast while
|
||||
slicing and dicing large, realtime datasets
|
||||
* Fast loading dashboards with configurable caching
|
||||
|
||||
@@ -62,15 +77,41 @@ Caravel provides:
|
||||
Database Support
|
||||
----------------
|
||||
|
||||
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
|
||||
Superset speaks many SQL dialects through SQLAlchemy, a Python
|
||||
ORM that is compatible with
|
||||
[most common databases](http://docs.sqlalchemy.org/en/rel_1_0/core/engines.html).
|
||||
|
||||
Superset can be used to visualize data out of most databases:
|
||||
* MySQL
|
||||
* Postgres
|
||||
* Vertica
|
||||
* Oracle
|
||||
* Microsoft SQL Server
|
||||
* SQLite
|
||||
* Greenplum
|
||||
* Firebird
|
||||
* MariaDB
|
||||
* Sybase
|
||||
* IBM DB2
|
||||
* Exasol
|
||||
* MonetDB
|
||||
* Snowflake
|
||||
* Redshift
|
||||
* **more!** look for the availability of a SQLAlchemy dialect for your database
|
||||
to find out whether it will work with Superset
|
||||
|
||||
What is Druid?
|
||||
-------------
|
||||
From their website at http://druid.io
|
||||
|
||||
Druid!
|
||||
------
|
||||
|
||||
On top of having the ability to query your relational databases,
|
||||
Superset has ships with deep integration with Druid (a real time distributed
|
||||
column-store). When querying Druid,
|
||||
Superset can query humongous amounts of data on top of real time dataset.
|
||||
Note that Superset does not require Druid in any way to function, it's simply
|
||||
another database backend that it can query.
|
||||
|
||||
Here's a description of Druid from the http://druid.io website:
|
||||
|
||||
*Druid is an open-source analytics data store designed for
|
||||
business intelligence (OLAP) queries on event data. Druid provides low
|
||||
@@ -83,55 +124,66 @@ power analytic dashboards and applications.*
|
||||
Installation & Configuration
|
||||
----------------------------
|
||||
|
||||
[See in the documentation](http://airbnb.io/caravel/installation.html)
|
||||
[See in the documentation](https://superset.incubator.apache.org/installation.html)
|
||||
|
||||
|
||||
More screenshots
|
||||
----------------
|
||||
|
||||

|
||||

|
||||
|
||||
---
|
||||

|
||||

|
||||
|
||||
---
|
||||

|
||||

|
||||
|
||||
---
|
||||

|
||||

|
||||
|
||||
---
|
||||

|
||||

|
||||
|
||||
---
|
||||

|
||||

|
||||
|
||||
---
|
||||

|
||||

|
||||
|
||||

|
||||
|
||||
|
||||
Resources
|
||||
-------------
|
||||
* [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)
|
||||
* [Superset Google Group](https://groups.google.com/forum/#!forum/airbnb_superset)
|
||||
* [Gitter (live chat) Channel](https://gitter.im/airbnb/superset)
|
||||
* [Docker image](https://hub.docker.com/r/amancevice/superset/) (community contributed)
|
||||
* [Slides from Strata (March 2016)](https://drive.google.com/open?id=0B5PVE0gzO81oOVJkdF9aNkJMSmM)
|
||||
|
||||
|
||||
Tip of the Hat
|
||||
--------------
|
||||
|
||||
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 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/airbnb/caravel/blob/master/CONTRIBUTING.md)
|
||||
Interested in contributing? Casual hacking? Check out
|
||||
[Contributing.MD](https://github.com/airbnb/superset/blob/master/CONTRIBUTING.md)
|
||||
|
||||
|
||||
Who uses Apache Superset (incubating)?
|
||||
--------------------------------------
|
||||
|
||||
Here's a list of organizations who have taken the time to send a PR to let
|
||||
the world know they are using Superset. Join our growing community!
|
||||
|
||||
- [Airbnb](https://github.com/airbnb)
|
||||
- [Amino](https://amino.com)
|
||||
- [Brilliant.org](https://brilliant.org/)
|
||||
- [Clark.de](http://clark.de/)
|
||||
- [Digit Game Studios](https://www.digitgaming.com/)
|
||||
- [Douban](https://www.douban.com/)
|
||||
- [Endress+Hauser](http://www.endress.com/)
|
||||
- [FBK - ICT center](http://ict.fbk.eu)
|
||||
- [Faasos](http://faasos.com/)
|
||||
- [GfK Data Lab](http://datalab.gfk.com)
|
||||
- [Maieutical Labs](https://cloudschooling.it)
|
||||
- [Qunar](https://www.qunar.com/)
|
||||
- [Shopkick](https://www.shopkick.com)
|
||||
- [Tails.com](https://tails.com)
|
||||
- [Tobii](http://www.tobii.com/)
|
||||
- [Tooploox](https://www.tooploox.com/)
|
||||
- [Udemy](https://www.udemy.com/)
|
||||
- [Yahoo!](www.yahoo.com)
|
||||
- [Zalando](https://www.zalando.com)
|
||||
|
||||
4
TODO.md
@@ -1,5 +1,5 @@
|
||||
# TODO
|
||||
List of TODO items for Caravel
|
||||
List of TODO items for Superset
|
||||
|
||||
## Important
|
||||
* **Getting proper JS testing:** unit tests on the Python side are pretty
|
||||
@@ -7,7 +7,7 @@ List of TODO items for Caravel
|
||||
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
|
||||
Caravel would discover and expose the plugins
|
||||
Superset would discover and expose the plugins
|
||||
|
||||
## Features
|
||||
* **Dashboard URL filters:** `{dash_url}#fltin__fieldname__value1,value2`
|
||||
|
||||
@@ -29,7 +29,7 @@ script_location = migrations
|
||||
# are written from script.py.mako
|
||||
# output_encoding = utf-8
|
||||
|
||||
sqlalchemy.url = scheme://localhost/caravel
|
||||
sqlalchemy.url = scheme://localhost/superset
|
||||
|
||||
# Logging configuration
|
||||
[loggers]
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
[ignore: caravel/assets/node_modules/**]
|
||||
[python: caravel/**.py]
|
||||
[jinja2: caravel/**/templates/**.html]
|
||||
[ignore: superset/assets/node_modules/**]
|
||||
[python: superset/**.py]
|
||||
[jinja2: superset/**/templates/**.html]
|
||||
encoding = utf-8
|
||||
|
||||
2347
babel/messages.pot
@@ -1,112 +0,0 @@
|
||||
"""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,82 +0,0 @@
|
||||
from __future__ import absolute_import
|
||||
from __future__ import division
|
||||
from __future__ import print_function
|
||||
from __future__ import unicode_literals
|
||||
|
||||
error = (
|
||||
"MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\n"+
|
||||
"MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMNNMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\n"+
|
||||
"MMMMMMMMMMMMMMMMMMMMMMMMMMMMMM8OI++=~~~~~~=+?IODMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\n"+
|
||||
"MMMMMMMMMMMMMMMMMMMMMMMMMD$~~~~~~~~~~~~~~~~~~~~~~~=$MMMMMMMMMMMMMMMMMMMMMMMMMMMM\n"+
|
||||
"MMMMMMMMMMMMMMMMMMMMMMN8?:~~~~~~~~~~~~~~~~~~~~~~~~~~=+8NMMMMMMMMMMMMMMMMMMMMMMMM\n"+
|
||||
"MMMMMMMMMMMMMMMMMMMMO=~~~~~~~~~~~~~~~~~+I??~~~~~~~~~~~~~+DMMMMMMMMMMMMMMMMMMMMMM\n"+
|
||||
"MMMMMMMMMMMMMMMMMMNI~~~~~~~~~~~~~~~~~~IIIII=~~~~~~~~~~~~~~=NMMMMMMMMMMMMMMMMMMMM\n"+
|
||||
"MMMMMMMMMMMMMMMMM+=~~~~~~~~~~~~~~~~~~~=III+~~~~~~~~~~~~~~~~~?8MMMMMMMMMMMMMMMMMM\n"+
|
||||
"MMMMMMMMMMMMMMMM?~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+++=~~~~8MMMMMMMMMMMMMMMMM\n"+
|
||||
"MMMMMMMMMMMMMMI=~~~~~~~~~~~~~~~~~~~~~~~~~III?I~~~~~~~~,:++++++~~8MMMMMMMMMMMMMMM\n"+
|
||||
"MMMMMMMMMMMMN7~~~~~~~~~~~~~~~~==+=~~~~~~=IIIII~~~~~~:. ..:=++=~=MMMMMMMMMMMMMMM\n"+
|
||||
"MMMMMMMMMMMO=~~~~~~~~~~~~~~~~+++=~~~~~~~~??I?I~~~~~~. ...,~~~~IMMMMMMMMMMMMM\n"+
|
||||
"MMMMMMMMMMM~~~~~~~~~~~~~~~~~+++:,~~~~~~~~~~~?=~~~~~:. ..~~~~~OMMMMMMMMMMMM\n"+
|
||||
"MMMMMMMMM$=~~~~~~~~~~~~~~~=++:.. ..~~~~~~~~~~~~~~~~,. . . :~~~~~OMMMMMMMMMMM\n"+
|
||||
"MMMMMMMMM~~~~~~~~~~~~~~~~+++,. .~~~~~~~~~~~~~~~.. .. . .~~~~~=OMMMMMMMMMM\n"+
|
||||
"MMMMMMMM?~~~~~~~~~~~~~~~=+~. .~~~~~~~~~~~~~~. ,MMMMM,=~~~~~~NMMMMMMMMM\n"+
|
||||
"MMMMMMMN~~~~~~~~~~~~~~~~~,. .,~~~~~~~~~~~~~.. ZMMM,+Z:~~~~~~$MMMMMMMMM\n"+
|
||||
"MMMMMM8?~~~~~~~~~~~~~~~~~.. ..~~~~~~~~~~~~~:. DMMM,+D~~~~~~~~IMMMMMMMM\n"+
|
||||
"MMMMMMI~~~~~~~~~~~~~~~~~~.. :MMMO~~~~~~~~~~~~~~~,.. ?MMMMMI~~~~~~~~~MMMMMMMM\n"+
|
||||
"MMMMMM=~~~~~~~~~~~~~~~~~~.. MMM+=M:~~~~~~~~~~~~~:. .:IM$~~~~~~~~~~~8MMMMMMM\n"+
|
||||
"MMMMMD~~~~~~~~~~~~~~~~~~~:. MMM:,M:~~~~~~~~~~~~~~~.......:~~~~~~~~~~$MMMMMMM\n"+
|
||||
"MMMMMI~~~~~~~~~~~~~~~~~~~~, MMMMMM~~~~~~~~~~~~~~~~~~,..:~~~~~~~~~~~~+MMMMMMM\n"+
|
||||
"MMMMD+~~~~~~~~~~~~~~~~~~~~~. $MMMM$~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~=MMMMMMM\n"+
|
||||
"MMMM8~~~~~~~~~~~~~~~~~~~~~~:. . .:~~~~~~,..:. .=~~~~~~~~~~~~~~~~~~~~MMMMMMM\n"+
|
||||
"MMMMO~~~~~~~~~~~~~~~~~~~~~~~:, .:~~~~~=8.. .+ . =8ZI~~~~~~~~~~~~~~~~=MMMMMMM\n"+
|
||||
"MMMMZ=~~~~~~~~~~~~~~~~~~~~~~~~:,,,:~~~~~~IZ8:. .O....888?~~~~~~~~~~~~~~~+MMMMMMM\n"+
|
||||
"MMMMO=~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~?888=...I~I88888O?~~~~~~~~~~~~~~7MMMMMMM\n"+
|
||||
"MMMMO~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~Z888OO88888888888O?~~~~~~~~~~~~~OMMMMMMM\n"+
|
||||
"MMMMD+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~=8888888888888888888~~~~~~~~~~~~+MMMMMMMM\n"+
|
||||
"MMMMM7~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~?8888888888888888888?~~~~~~~~~~=$MMMMMMMM\n"+
|
||||
"MMMMMD~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~=$8888888888888888888O~~~~~~~~~~8MMMMMMMMM\n"+
|
||||
"MMMMMN=~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+Z88888888888888888ZZ7=~~~~~~~~?MMMMMMMMMM\n"+
|
||||
"MMMMMMZ=~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+Z88888888Z7I===~~~~~~~~~~~~~=OMMMMMMMMMMM\n"+
|
||||
"MMMMMMN$~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~=$88888O7?=~~~~~~~~~~~~~~~~~~OMMMMMMMMMMMM\n"+
|
||||
"MMMMMMMM?~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~I8OZ+~~~~~~~~~~~~~~~~~~~~=DMMMMMMMMMMMMMM\n"+
|
||||
"MMMMMMMM8=~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+$+=~~~~~~~~~~~~~~~~~~~~+MMMMMMMMMMMMMMMM\n"+
|
||||
"MMMMMMMMMD7~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~=$DMMMMMMMMMMMMMMMMMM\n"+
|
||||
"MMMMMMMMMMM?~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~=$OMMMMMMMMMMMMMMMMMMMMM\n"+
|
||||
"MMMMMMMMMMMMD7=~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+ZMMMMMMMMMMMMMMMMMMMMMMMMMM\n"+
|
||||
"MMMMMMMMMMMMMMZ7=~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~78MMMMMMMMMMMMMMMMMMMMMMMMMMMMM\n"+
|
||||
"MMMMMMMMMMMMMMMMM8OI=~~~~~~~~~~~~~~~~~~~=+?ZDNMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\n"+
|
||||
"MMMMMMMMMMMMMMMMMMMMNDZ7?++~=~==~+?IONMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\n"+
|
||||
"MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\n"+
|
||||
"MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\n"+
|
||||
"MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\n"+
|
||||
"MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM")
|
||||
|
||||
stacktrace="""
|
||||
-------------------------------------------------------------------------------------------------------
|
||||
=======================================================================================================
|
||||
-------------------------------------------------------------------------------------------------------
|
||||
___ ___ ___
|
||||
( ) ( ) ( )
|
||||
.--. | |_ .---. .--. | | ___ | |_ ___ .-. .---. .--. .--.
|
||||
/ _ \ ( __) / .-, \ / \ | | ( ) ( __) ( ) \ / .-, \ / \ / \\
|
||||
. .' `. ; | | (__) ; | | .-. ; | | ' / | | | ' .-. ; (__) ; | | .-. ; | .-. ;
|
||||
| ' | | | | ___ .'` | | |(___) | |,' / | | ___ | / (___) .'` | | |(___) | | | |
|
||||
_\_`.(___) | |( ) / .'| | | | | . '. | |( ) | | / .'| | | | | |/ |
|
||||
( ). '. | | | | | / | | | | ___ | | `. \ | | | | | | | / | | | | ___ | ' _.'
|
||||
| | `\ | | ' | | ; | ; | | '( ) | | \ \ | ' | | | | ; | ; | | '( ) | .'.-.
|
||||
; '._,' ' ' `-' ; ' `-' | ' `-' | | | \ . ' `-' ; | | ' `-' | ' `-' | ' `-' /
|
||||
'.___.' `.__. `.__.'_. `.__,' (___ ) (___) `.__. (___) `.__.'_. `.__,' `.__.'
|
||||
|
||||
-------------------------------------------------------------------------------------------------------
|
||||
=======================================================================================================
|
||||
-------------------------------------------------------------------------------------------------------
|
||||
"""
|
||||
|
||||
boat = """\
|
||||
+ +
|
||||
)`.).
|
||||
)``)``) .~~
|
||||
).-'.-')|)
|
||||
|-).-).-'_'-/
|
||||
~~~\ `o-o-o' /~~~~
|
||||
~~~'---.____/~~~"""
|
||||
@@ -1,3 +0,0 @@
|
||||
{
|
||||
"presets" : ["airbnb", "es2015", "react"]
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
{
|
||||
"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,
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 144 KiB |
|
Before Width: | Height: | Size: 3.0 KiB |
|
Before Width: | Height: | Size: 6.1 KiB |
|
Before Width: | Height: | Size: 236 KiB |
|
Before Width: | Height: | Size: 2.8 KiB |
|
Before Width: | Height: | Size: 93 KiB |
|
Before Width: | Height: | Size: 49 KiB |
|
Before Width: | Height: | Size: 121 KiB |
|
Before Width: | Height: | Size: 1.5 MiB |
|
Before Width: | Height: | Size: 147 KiB |
|
Before Width: | Height: | Size: 190 KiB |
|
Before Width: | Height: | Size: 245 KiB |
|
Before Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 33 KiB |
|
Before Width: | Height: | Size: 133 KiB |
|
Before Width: | Height: | Size: 128 KiB |
|
Before Width: | Height: | Size: 141 KiB |
|
Before Width: | Height: | Size: 49 KiB |
|
Before Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 106 KiB |
|
Before Width: | Height: | Size: 100 KiB |
@@ -1,130 +0,0 @@
|
||||
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 };
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
export const STATE_BSSTYLE_MAP = {
|
||||
failed: 'danger',
|
||||
pending: 'info',
|
||||
running: 'warning',
|
||||
success: 'success',
|
||||
};
|
||||
|
||||
export const STATUS_OPTIONS = ['success', 'failed', 'running'];
|
||||
@@ -1,41 +0,0 @@
|
||||
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);
|
||||
@@ -1,71 +0,0 @@
|
||||
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);
|
||||
@@ -1,48 +0,0 @@
|
||||
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;
|
||||
@@ -1,55 +0,0 @@
|
||||
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;
|
||||
@@ -1,65 +0,0 @@
|
||||
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);
|
||||
@@ -1,69 +0,0 @@
|
||||
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);
|
||||
@@ -1,58 +0,0 @@
|
||||
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);
|
||||
@@ -1,62 +0,0 @@
|
||||
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="#"
|
||||
>
|
||||
×
|
||||
</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);
|
||||
|
||||
@@ -1,142 +0,0 @@
|
||||
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;
|
||||
@@ -1,95 +0,0 @@
|
||||
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;
|
||||
@@ -1,85 +0,0 @@
|
||||
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);
|
||||
@@ -1,301 +0,0 @@
|
||||
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);
|
||||
@@ -1,195 +0,0 @@
|
||||
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);
|
||||
@@ -1,39 +0,0 @@
|
||||
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;
|
||||
@@ -1,170 +0,0 @@
|
||||
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" /> </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);
|
||||
@@ -1,214 +0,0 @@
|
||||
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 };
|
||||
@@ -1,23 +0,0 @@
|
||||
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;
|
||||
@@ -1,61 +0,0 @@
|
||||
import React from 'react';
|
||||
import { now, fDuration } from '../../modules/dates';
|
||||
|
||||
import { STATE_BSSTYLE_MAP } from '../common.js';
|
||||
|
||||
class Timer extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
clockStr: '',
|
||||
};
|
||||
}
|
||||
componentWillMount() {
|
||||
this.startTimer();
|
||||
}
|
||||
componentWillUnmount() {
|
||||
this.stopTimer();
|
||||
}
|
||||
startTimer() {
|
||||
if (!(this.timer)) {
|
||||
this.timer = setInterval(this.stopwatch.bind(this), 30);
|
||||
}
|
||||
}
|
||||
stopTimer() {
|
||||
clearInterval(this.timer);
|
||||
this.timer = null;
|
||||
}
|
||||
stopwatch() {
|
||||
if (this.props && this.props.query) {
|
||||
const endDttm = this.props.query.endDttm || now();
|
||||
const clockStr = fDuration(this.props.query.startDttm, endDttm);
|
||||
this.setState({ clockStr });
|
||||
if (this.props.query.state !== 'running') {
|
||||
this.stopTimer();
|
||||
}
|
||||
}
|
||||
}
|
||||
render() {
|
||||
if (this.props.query && this.props.query.state === 'running') {
|
||||
this.startTimer();
|
||||
}
|
||||
let timerSpan = null;
|
||||
if (this.props && this.props.query) {
|
||||
const bsStyle = STATE_BSSTYLE_MAP[this.props.query.state];
|
||||
timerSpan = (
|
||||
<span className={'inlineBlock m-r-5 label label-' + bsStyle}>
|
||||
{this.state.clockStr}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
return timerSpan;
|
||||
}
|
||||
}
|
||||
Timer.propTypes = {
|
||||
query: React.PropTypes.object,
|
||||
};
|
||||
Timer.defaultProps = {
|
||||
query: null,
|
||||
};
|
||||
|
||||
export default Timer;
|
||||
@@ -1,27 +0,0 @@
|
||||
const $ = window.$ = require('jquery');
|
||||
const jQuery = window.jQuery = $; // eslint-disable-line
|
||||
require('bootstrap');
|
||||
|
||||
import React from 'react';
|
||||
import { render } from 'react-dom';
|
||||
import { initialState, sqlLabReducer } from './reducers';
|
||||
import { enhancer } from '../reduxUtils';
|
||||
import { createStore } from 'redux';
|
||||
import { Provider } from 'react-redux';
|
||||
|
||||
import App from './components/App';
|
||||
|
||||
|
||||
require('./main.css');
|
||||
|
||||
let store = createStore(sqlLabReducer, initialState, enhancer());
|
||||
|
||||
// jquery hack to highlight the navbar menu
|
||||
$('a:contains("SQL Lab")').parent().addClass('active');
|
||||
|
||||
render(
|
||||
<Provider store={store}>
|
||||
<App />
|
||||
</Provider>,
|
||||
document.getElementById('app')
|
||||
);
|
||||
@@ -1,5 +0,0 @@
|
||||
require('../node_modules/select2/select2.css');
|
||||
require('../node_modules/select2-bootstrap-css/select2-bootstrap.min.css');
|
||||
require('../node_modules/jquery-ui/themes/base/jquery-ui.css');
|
||||
require('select2');
|
||||
require('../vendor/select2.sortable.js');
|
||||
@@ -1,59 +0,0 @@
|
||||
import React, { PropTypes } from 'react';
|
||||
import { Modal } from 'react-bootstrap';
|
||||
import cx from 'classnames';
|
||||
|
||||
const propTypes = {
|
||||
triggerNode: PropTypes.node.isRequired,
|
||||
modalTitle: PropTypes.node.isRequired,
|
||||
modalBody: PropTypes.node.isRequired,
|
||||
beforeOpen: PropTypes.func,
|
||||
isButton: PropTypes.bool,
|
||||
};
|
||||
|
||||
const defaultProps = {
|
||||
beforeOpen: () => {},
|
||||
isButton: false,
|
||||
};
|
||||
|
||||
export default class ModalTrigger extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
showModal: false,
|
||||
};
|
||||
this.open = this.open.bind(this);
|
||||
this.close = this.close.bind(this);
|
||||
}
|
||||
|
||||
close() {
|
||||
this.setState({ showModal: false });
|
||||
}
|
||||
|
||||
open(e) {
|
||||
e.preventDefault();
|
||||
this.props.beforeOpen();
|
||||
this.setState({ showModal: true });
|
||||
}
|
||||
|
||||
render() {
|
||||
const classNames = cx({
|
||||
'btn btn-default btn-sm': this.props.isButton,
|
||||
});
|
||||
return (
|
||||
<a href="#" className={classNames} onClick={this.open}>
|
||||
{this.props.triggerNode}
|
||||
<Modal show={this.state.showModal} onHide={this.close}>
|
||||
<Modal.Header closeButton>
|
||||
<Modal.Title>{this.props.modalTitle}</Modal.Title>
|
||||
</Modal.Header>
|
||||
<Modal.Body>
|
||||
{this.props.modalBody}
|
||||
</Modal.Body>
|
||||
</Modal>
|
||||
</a>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ModalTrigger.propTypes = propTypes;
|
||||
ModalTrigger.defaultProps = defaultProps;
|
||||
@@ -1,2 +0,0 @@
|
||||
require('../stylesheets/less/index.less');
|
||||
require('../stylesheets/react-select/select.less');
|
||||
@@ -1,411 +0,0 @@
|
||||
const $ = window.$ = require('jquery');
|
||||
const jQuery = window.jQuery = require('jquery'); // eslint-disable-line
|
||||
const px = require('../modules/caravel.js');
|
||||
const d3 = require('d3');
|
||||
const urlLib = require('url');
|
||||
const utils = require('../modules/utils.js');
|
||||
|
||||
import React from 'react';
|
||||
import { render } from 'react-dom';
|
||||
import SliceAdder from './components/SliceAdder.jsx';
|
||||
import GridLayout from './components/GridLayout.jsx';
|
||||
|
||||
const ace = require('brace');
|
||||
require('bootstrap');
|
||||
require('brace/mode/css');
|
||||
require('brace/theme/crimson_editor');
|
||||
require('../../stylesheets/dashboard.css');
|
||||
require('../caravel-select2.js');
|
||||
|
||||
// Injects the passed css string into a style sheet with the specified className
|
||||
// If a stylesheet doesn't exist with the passed className, one will be injected into <head>
|
||||
function injectCss(className, css) {
|
||||
const head = document.head || document.getElementsByTagName('head')[0];
|
||||
let style = document.querySelector('.' + className);
|
||||
|
||||
if (!style) {
|
||||
if (className.split(' ').length > 1) {
|
||||
throw new Error('This method only supports selections with a single class name.');
|
||||
}
|
||||
style = document.createElement('style');
|
||||
style.className = className;
|
||||
style.type = 'text/css';
|
||||
head.appendChild(style);
|
||||
}
|
||||
|
||||
if (style.styleSheet) {
|
||||
style.styleSheet.cssText = css;
|
||||
} else {
|
||||
style.innerHTML = css;
|
||||
}
|
||||
}
|
||||
|
||||
function dashboardContainer(dashboardData) {
|
||||
let dashboard = Object.assign({}, utils.controllerInterface, dashboardData, {
|
||||
type: 'dashboard',
|
||||
filters: {},
|
||||
init() {
|
||||
this.initDashboardView();
|
||||
this.firstLoad = true;
|
||||
px.initFavStars();
|
||||
const sliceObjects = [];
|
||||
const dash = this;
|
||||
dashboard.slices.forEach((data) => {
|
||||
if (data.error) {
|
||||
const html = '<div class="alert alert-danger">' + data.error + '</div>';
|
||||
$('#slice_' + data.slice_id).find('.token').html(html);
|
||||
} else {
|
||||
const slice = px.Slice(data, dash);
|
||||
$('#slice_' + data.slice_id).find('a.refresh').click(() => {
|
||||
slice.render(true);
|
||||
});
|
||||
sliceObjects.push(slice);
|
||||
}
|
||||
});
|
||||
this.slices = sliceObjects;
|
||||
this.refreshTimer = null;
|
||||
this.loadPreSelectFilters();
|
||||
this.startPeriodicRender(0);
|
||||
this.bindResizeToWindowResize();
|
||||
},
|
||||
loadPreSelectFilters() {
|
||||
try {
|
||||
const filters = JSON.parse(px.getParam('preselect_filters') || '{}');
|
||||
for (const sliceId in filters) {
|
||||
for (const col in filters[sliceId]) {
|
||||
this.setFilter(sliceId, col, filters[sliceId][col], false, false);
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
// console.error(e);
|
||||
}
|
||||
},
|
||||
setFilter(sliceId, col, vals, refresh) {
|
||||
this.addFilter(sliceId, col, vals, false, refresh);
|
||||
},
|
||||
done(slice) {
|
||||
const refresh = slice.getWidgetHeader().find('.refresh');
|
||||
const data = slice.data;
|
||||
if (data !== undefined && data.is_cached) {
|
||||
refresh
|
||||
.addClass('danger')
|
||||
.attr('title',
|
||||
'Served from data cached at ' + data.cached_dttm +
|
||||
'. Click to force refresh')
|
||||
.tooltip('fixTitle');
|
||||
} else {
|
||||
refresh
|
||||
.removeClass('danger')
|
||||
.attr('title', 'Click to force refresh')
|
||||
.tooltip('fixTitle');
|
||||
}
|
||||
},
|
||||
effectiveExtraFilters(sliceId) {
|
||||
// Summarized filter, not defined by sliceId
|
||||
// returns k=field, v=array of values
|
||||
const f = {};
|
||||
const immuneSlices = this.metadata.filter_immune_slices || [];
|
||||
if (sliceId && immuneSlices.includes(sliceId)) {
|
||||
// The slice is immune to dashboard fiterls
|
||||
return f;
|
||||
}
|
||||
|
||||
// Building a list of fields the slice is immune to filters on
|
||||
let immuneToFields = [];
|
||||
if (
|
||||
sliceId &&
|
||||
this.metadata.filter_immune_slice_fields &&
|
||||
this.metadata.filter_immune_slice_fields[sliceId]) {
|
||||
immuneToFields = this.metadata.filter_immune_slice_fields[sliceId];
|
||||
}
|
||||
for (const filteringSliceId in this.filters) {
|
||||
for (const field in this.filters[filteringSliceId]) {
|
||||
if (!immuneToFields.includes(field)) {
|
||||
f[field] = this.filters[filteringSliceId][field];
|
||||
}
|
||||
}
|
||||
}
|
||||
return f;
|
||||
},
|
||||
addFilter(sliceId, col, vals, merge = true, refresh = true) {
|
||||
if (!(sliceId in this.filters)) {
|
||||
this.filters[sliceId] = {};
|
||||
}
|
||||
if (!(col in this.filters[sliceId]) || !merge) {
|
||||
this.filters[sliceId][col] = vals;
|
||||
} else {
|
||||
this.filters[sliceId][col] = d3.merge([this.filters[sliceId][col], vals]);
|
||||
}
|
||||
if (refresh) {
|
||||
this.refreshExcept(sliceId);
|
||||
}
|
||||
this.updateFilterParamsInUrl();
|
||||
},
|
||||
readFilters() {
|
||||
// Returns a list of human readable active filters
|
||||
return JSON.stringify(this.filters, null, 4);
|
||||
},
|
||||
updateFilterParamsInUrl() {
|
||||
const urlObj = urlLib.parse(location.href, true);
|
||||
urlObj.query = urlObj.query || {};
|
||||
urlObj.query.preselect_filters = this.readFilters();
|
||||
urlObj.search = null;
|
||||
history.pushState(urlObj.query, window.title, urlLib.format(urlObj));
|
||||
},
|
||||
bindResizeToWindowResize() {
|
||||
let resizeTimer;
|
||||
const dash = this;
|
||||
$(window).on('resize', () => {
|
||||
clearTimeout(resizeTimer);
|
||||
resizeTimer = setTimeout(() => {
|
||||
dash.slices.forEach((slice) => {
|
||||
slice.resize();
|
||||
});
|
||||
}, 500);
|
||||
});
|
||||
},
|
||||
stopPeriodicRender() {
|
||||
if (this.refreshTimer) {
|
||||
clearTimeout(this.refreshTimer);
|
||||
this.refreshTimer = null;
|
||||
}
|
||||
},
|
||||
startPeriodicRender(interval) {
|
||||
this.stopPeriodicRender();
|
||||
const dash = this;
|
||||
const maxRandomDelay = Math.min(interval * 0.2, 5000);
|
||||
const refreshAll = function () {
|
||||
dash.slices.forEach(function (slice) {
|
||||
const force = !dash.firstLoad;
|
||||
setTimeout(function () {
|
||||
slice.render(force);
|
||||
},
|
||||
// Randomize to prevent all widgets refreshing at the same time
|
||||
maxRandomDelay * Math.random());
|
||||
});
|
||||
dash.firstLoad = false;
|
||||
};
|
||||
|
||||
const fetchAndRender = function () {
|
||||
refreshAll();
|
||||
if (interval > 0) {
|
||||
dash.refreshTimer = setTimeout(function () {
|
||||
fetchAndRender();
|
||||
}, interval);
|
||||
}
|
||||
};
|
||||
fetchAndRender();
|
||||
},
|
||||
refreshExcept(sliceId) {
|
||||
const immune = this.metadata.filter_immune_slices || [];
|
||||
this.slices.forEach(function (slice) {
|
||||
if (slice.data.slice_id !== sliceId && immune.indexOf(slice.data.slice_id) === -1) {
|
||||
slice.render();
|
||||
}
|
||||
});
|
||||
},
|
||||
clearFilters(sliceId) {
|
||||
delete this.filters[sliceId];
|
||||
this.refreshExcept(sliceId);
|
||||
this.updateFilterParamsInUrl();
|
||||
},
|
||||
removeFilter(sliceId, col, vals) {
|
||||
if (sliceId in this.filters) {
|
||||
if (col in this.filters[sliceId]) {
|
||||
const a = [];
|
||||
this.filters[sliceId][col].forEach(function (v) {
|
||||
if (vals.indexOf(v) < 0) {
|
||||
a.push(v);
|
||||
}
|
||||
});
|
||||
this.filters[sliceId][col] = a;
|
||||
}
|
||||
}
|
||||
this.refreshExcept(sliceId);
|
||||
this.updateFilterParamsInUrl();
|
||||
},
|
||||
getSlice(sliceId) {
|
||||
const id = parseInt(sliceId, 10);
|
||||
let i = 0;
|
||||
let slice = null;
|
||||
while (i < this.slices.length) {
|
||||
// when the slice is found, assign to slice and break;
|
||||
if (this.slices[i].data.slice_id === id) {
|
||||
slice = this.slices[i];
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return slice;
|
||||
},
|
||||
showAddSlice() {
|
||||
const slicesOnDashMap = {};
|
||||
const layoutPositions = this.reactGridLayout.serialize();
|
||||
layoutPositions.forEach((position) => {
|
||||
slicesOnDashMap[position.slice_id] = true;
|
||||
});
|
||||
render(
|
||||
<SliceAdder dashboard={dashboard} slicesOnDashMap={slicesOnDashMap} caravel={px} />,
|
||||
document.getElementById('add-slice-container')
|
||||
);
|
||||
},
|
||||
getAjaxErrorMsg(error) {
|
||||
const respJSON = error.responseJSON;
|
||||
return (respJSON && respJSON.message) ? respJSON.message :
|
||||
error.responseText;
|
||||
},
|
||||
addSlicesToDashboard(sliceIds) {
|
||||
const getAjaxErrorMsg = this.getAjaxErrorMsg;
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: '/caravel/add_slices/' + dashboard.id + '/',
|
||||
data: {
|
||||
data: JSON.stringify({ slice_ids: sliceIds }),
|
||||
},
|
||||
success() {
|
||||
// Refresh page to allow for slices to re-render
|
||||
window.location.reload();
|
||||
},
|
||||
error(error) {
|
||||
const errorMsg = getAjaxErrorMsg(error);
|
||||
utils.showModal({
|
||||
title: 'Error',
|
||||
body: 'Sorry, there was an error adding slices to this dashboard: </ br>' + errorMsg,
|
||||
});
|
||||
},
|
||||
});
|
||||
},
|
||||
saveDashboard() {
|
||||
const expandedSlices = {};
|
||||
$.each($('.slice_info'), function () {
|
||||
const widget = $(this).parents('.widget');
|
||||
const sliceDescription = widget.find('.slice_description');
|
||||
if (sliceDescription.is(':visible')) {
|
||||
expandedSlices[$(widget).attr('data-slice-id')] = true;
|
||||
}
|
||||
});
|
||||
const positions = this.reactGridLayout.serialize();
|
||||
const data = {
|
||||
positions,
|
||||
css: this.editor.getValue(),
|
||||
expanded_slices: expandedSlices,
|
||||
};
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: '/caravel/save_dash/' + dashboard.id + '/',
|
||||
data: {
|
||||
data: JSON.stringify(data),
|
||||
},
|
||||
success() {
|
||||
utils.showModal({
|
||||
title: 'Success',
|
||||
body: 'This dashboard was saved successfully.',
|
||||
});
|
||||
},
|
||||
error(error) {
|
||||
const errorMsg = this.getAjaxErrorMsg(error);
|
||||
utils.showModal({
|
||||
title: 'Error',
|
||||
body: 'Sorry, there was an error saving this dashboard: </ br>' + errorMsg,
|
||||
});
|
||||
},
|
||||
});
|
||||
},
|
||||
initDashboardView() {
|
||||
this.posDict = {};
|
||||
this.position_json.forEach(function (position) {
|
||||
this.posDict[position.slice_id] = position;
|
||||
}, this);
|
||||
|
||||
this.reactGridLayout = render(
|
||||
<GridLayout slices={this.slices} posDict={this.posDict} dashboard={dashboard} />,
|
||||
document.getElementById('grid-container')
|
||||
);
|
||||
|
||||
this.curUserId = $('.dashboard').data('user');
|
||||
|
||||
dashboard = this;
|
||||
|
||||
// Displaying widget controls on hover
|
||||
$('.react-grid-item').hover(
|
||||
function () {
|
||||
$(this).find('.chart-controls').fadeIn(300);
|
||||
},
|
||||
function () {
|
||||
$(this).find('.chart-controls').fadeOut(300);
|
||||
}
|
||||
);
|
||||
$('div.grid-container').css('visibility', 'visible');
|
||||
$('#savedash').click(this.saveDashboard.bind(this));
|
||||
$('#add-slice').click(this.showAddSlice.bind(this));
|
||||
|
||||
const editor = ace.edit('dash_css');
|
||||
this.editor = editor;
|
||||
editor.$blockScrolling = Infinity;
|
||||
|
||||
editor.setTheme('ace/theme/crimson_editor');
|
||||
editor.setOptions({
|
||||
minLines: 16,
|
||||
maxLines: Infinity,
|
||||
useWorker: false,
|
||||
});
|
||||
editor.getSession().setMode('ace/mode/css');
|
||||
|
||||
$('.select2').select2({
|
||||
dropdownAutoWidth: true,
|
||||
});
|
||||
$('#css_template').on('change', function () {
|
||||
const css = $(this).find('option:selected').data('css');
|
||||
editor.setValue(css);
|
||||
|
||||
$('#dash_css').val(css);
|
||||
injectCss('dashboard-template', css);
|
||||
});
|
||||
$('#filters').click(() => {
|
||||
utils.showModal({
|
||||
title: '<span class="fa fa-info-circle"></span> Current Global Filters',
|
||||
body: 'The following global filters are currently applied:<br/>' +
|
||||
dashboard.readFilters(),
|
||||
});
|
||||
});
|
||||
$('#refresh_dash_interval').on('change', function () {
|
||||
const interval = $(this).find('option:selected').val() * 1000;
|
||||
dashboard.startPeriodicRender(interval);
|
||||
});
|
||||
$('#refresh_dash').click(() => {
|
||||
dashboard.slices.forEach((slice) => {
|
||||
slice.render(true);
|
||||
});
|
||||
});
|
||||
|
||||
$('div.widget').click(function (e) {
|
||||
const $this = $(this);
|
||||
const $target = $(e.target);
|
||||
|
||||
if ($target.hasClass('slice_info')) {
|
||||
$this.find('.slice_description').slideToggle(0, function () {
|
||||
$this.find('.refresh').click();
|
||||
});
|
||||
} else if ($target.hasClass('controls-toggle')) {
|
||||
$this.find('.chart-controls').toggle();
|
||||
}
|
||||
});
|
||||
|
||||
editor.on('change', function () {
|
||||
const css = editor.getValue();
|
||||
$('#dash_css').val(css);
|
||||
injectCss('dashboard-template', css);
|
||||
});
|
||||
|
||||
const css = $('.dashboard').data('css');
|
||||
injectCss('dashboard-template', css);
|
||||
},
|
||||
});
|
||||
dashboard.init();
|
||||
return dashboard;
|
||||
}
|
||||
|
||||
$(document).ready(() => {
|
||||
dashboardContainer($('.dashboard').data('dashboard'));
|
||||
$('[data-toggle="tooltip"]').tooltip({ container: 'body' });
|
||||
});
|
||||
@@ -1,42 +0,0 @@
|
||||
import React, { PropTypes } from 'react';
|
||||
|
||||
const propTypes = {
|
||||
modalId: PropTypes.string.isRequired,
|
||||
title: PropTypes.string,
|
||||
modalContent: PropTypes.node,
|
||||
customButton: PropTypes.node,
|
||||
};
|
||||
|
||||
function Modal({ modalId, title, modalContent, customButton }) {
|
||||
return (
|
||||
<div className="modal fade" id={modalId} role="dialog">
|
||||
<div className="modal-dialog" role="document">
|
||||
<div className="modal-content">
|
||||
<div className="modal-header">
|
||||
<button type="button" className="close" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
<h4 className="modal-title">{title}</h4>
|
||||
</div>
|
||||
<div className="modal-body">
|
||||
{modalContent}
|
||||
</div>
|
||||
<div className="modal-footer">
|
||||
<button
|
||||
type="button"
|
||||
className="btn btn-default"
|
||||
data-dismiss="modal"
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
{customButton}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Modal.propTypes = propTypes;
|
||||
|
||||
export default Modal;
|
||||
@@ -1,37 +0,0 @@
|
||||
import React, { PropTypes } from 'react';
|
||||
import ModalTrigger from './../../components/ModalTrigger';
|
||||
|
||||
const propTypes = {
|
||||
slice: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
export default class DisplayQueryButton extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
viewSqlQuery: '',
|
||||
};
|
||||
this.beforeOpen = this.beforeOpen.bind(this);
|
||||
}
|
||||
|
||||
beforeOpen() {
|
||||
this.setState({
|
||||
viewSqlQuery: this.props.slice.viewSqlQuery,
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
const modalBody = (<pre>{this.state.viewSqlQuery}</pre>);
|
||||
return (
|
||||
<ModalTrigger
|
||||
isButton
|
||||
triggerNode={<span>Query</span>}
|
||||
modalTitle="Query"
|
||||
modalBody={modalBody}
|
||||
beforeOpen={this.beforeOpen}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
DisplayQueryButton.propTypes = propTypes;
|
||||
@@ -1,45 +0,0 @@
|
||||
import React, { PropTypes } from 'react';
|
||||
import cx from 'classnames';
|
||||
import URLShortLinkButton from './URLShortLinkButton';
|
||||
import EmbedCodeButton from './EmbedCodeButton';
|
||||
import DisplayQueryButton from './DisplayQueryButton';
|
||||
|
||||
const propTypes = {
|
||||
canDownload: PropTypes.string.isRequired,
|
||||
slice: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
export default function ExploreActionButtons({ canDownload, slice }) {
|
||||
const exportToCSVClasses = cx('btn btn-default btn-sm', {
|
||||
'disabled disabledButton': !canDownload,
|
||||
});
|
||||
return (
|
||||
<div className="btn-group results" role="group">
|
||||
<URLShortLinkButton slice={slice} />
|
||||
|
||||
<EmbedCodeButton slice={slice} />
|
||||
|
||||
<a
|
||||
href={slice.data.json_endpoint}
|
||||
className="btn btn-default btn-sm"
|
||||
title="Export to .json"
|
||||
target="_blank"
|
||||
>
|
||||
<i className="fa fa-file-code-o"></i> .json
|
||||
</a>
|
||||
|
||||
<a
|
||||
href={slice.data.csv_endpoint}
|
||||
className={exportToCSVClasses}
|
||||
title="Export to .csv format"
|
||||
target="_blank"
|
||||
>
|
||||
<i className="fa fa-file-text-o"></i> .csv
|
||||
</a>
|
||||
|
||||
<DisplayQueryButton slice={slice} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
ExploreActionButtons.propTypes = propTypes;
|
||||
@@ -1,31 +0,0 @@
|
||||
import React, { PropTypes } from 'react';
|
||||
import classnames from 'classnames';
|
||||
|
||||
const propTypes = {
|
||||
canAdd: PropTypes.string.isRequired,
|
||||
onQuery: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
export default function QueryAndSaveBtns({ canAdd, onQuery }) {
|
||||
const saveClasses = classnames('btn btn-default btn-sm', {
|
||||
'disabled disabledButton': canAdd !== 'True',
|
||||
});
|
||||
|
||||
return (
|
||||
<div className="btn-group query-and-save">
|
||||
<button type="button" className="btn btn-primary btn-sm" onClick={onQuery}>
|
||||
<i className="fa fa-bolt"></i> Query
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className={saveClasses}
|
||||
data-target="#save_modal"
|
||||
data-toggle="modal"
|
||||
>
|
||||
<i className="fa fa-plus-circle"></i> Save as
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
QueryAndSaveBtns.propTypes = propTypes;
|
||||
@@ -1,401 +0,0 @@
|
||||
// Javascript for the explorer page
|
||||
// Init explorer view -> load vis dependencies -> read data (from dynamic html) -> render slice
|
||||
// nb: to add a new vis, you must also add a Python fn in viz.py
|
||||
//
|
||||
// js
|
||||
const $ = window.$ = require('jquery');
|
||||
const px = require('./../modules/caravel.js');
|
||||
const utils = require('./../modules/utils.js');
|
||||
const jQuery = window.jQuery = require('jquery'); // eslint-disable-line
|
||||
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import QueryAndSaveBtns from './components/QueryAndSaveBtns.jsx';
|
||||
import ExploreActionButtons from './components/ExploreActionButtons.jsx';
|
||||
|
||||
require('jquery-ui');
|
||||
$.widget.bridge('uitooltip', $.ui.tooltip); // Shutting down jq-ui tooltips
|
||||
require('bootstrap');
|
||||
|
||||
require('./../caravel-select2.js');
|
||||
|
||||
// css
|
||||
require('../../vendor/pygments.css');
|
||||
require('../../stylesheets/explore.css');
|
||||
|
||||
let slice;
|
||||
|
||||
const getPanelClass = function (fieldPrefix) {
|
||||
return (fieldPrefix === 'flt' ? 'filter' : 'having') + '_panel';
|
||||
};
|
||||
|
||||
function prepForm() {
|
||||
// Assigning the right id to form elements in filters
|
||||
const fixId = function ($filter, fieldPrefix, i) {
|
||||
$filter.attr('id', function () {
|
||||
return fieldPrefix + '_' + i;
|
||||
});
|
||||
|
||||
['col', 'op', 'eq'].forEach(function (fieldMiddle) {
|
||||
const fieldName = fieldPrefix + '_' + fieldMiddle;
|
||||
$filter.find('[id^=' + fieldName + '_]')
|
||||
.attr('id', function () {
|
||||
return fieldName + '_' + i;
|
||||
})
|
||||
.attr('name', function () {
|
||||
return fieldName + '_' + i;
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
['flt', 'having'].forEach(function (fieldPrefix) {
|
||||
let i = 1;
|
||||
$('#' + getPanelClass(fieldPrefix) + ' #filters > div').each(function () {
|
||||
fixId($(this), fieldPrefix, i);
|
||||
i++;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function query(forceUpdate, pushState) {
|
||||
let force = forceUpdate;
|
||||
if (force === undefined) {
|
||||
force = false;
|
||||
}
|
||||
$('.query-and-save button').attr('disabled', 'disabled');
|
||||
if (force) { // Don't hide the alert message when the page is just loaded
|
||||
$('div.alert').remove();
|
||||
}
|
||||
$('#is_cached').hide();
|
||||
prepForm();
|
||||
|
||||
if (pushState !== false) {
|
||||
// update the url after prepForm() fix the field ids
|
||||
history.pushState({}, document.title, slice.querystring());
|
||||
}
|
||||
slice.render(force);
|
||||
}
|
||||
|
||||
function saveSlice() {
|
||||
const action = $('input[name=rdo_save]:checked').val();
|
||||
if (action === 'saveas') {
|
||||
const sliceName = $('input[name=new_slice_name]').val();
|
||||
if (sliceName === '') {
|
||||
utils.showModal({
|
||||
title: 'Error',
|
||||
body: 'You must pick a name for the new slice',
|
||||
});
|
||||
return;
|
||||
}
|
||||
document.getElementById('slice_name').value = sliceName;
|
||||
}
|
||||
const addToDash = $('input[name=addToDash]:checked').val();
|
||||
if (addToDash === 'existing' && $('#save_to_dashboard_id').val() === '') {
|
||||
utils.showModal({
|
||||
title: 'Error',
|
||||
body: 'You must pick an existing dashboard',
|
||||
});
|
||||
return;
|
||||
} else if (addToDash === 'new' && $('input[name=new_dashboard_name]').val() === '') {
|
||||
utils.showModal({
|
||||
title: 'Error',
|
||||
body: 'Please enter a name for the new dashboard',
|
||||
});
|
||||
return;
|
||||
}
|
||||
$('#action').val(action);
|
||||
prepForm();
|
||||
$('#query').submit();
|
||||
}
|
||||
|
||||
function initExploreView() {
|
||||
function getCollapsedFieldsets() {
|
||||
let collapsedFieldsets = $('#collapsedFieldsets').val();
|
||||
|
||||
if (collapsedFieldsets !== undefined && collapsedFieldsets !== '') {
|
||||
collapsedFieldsets = collapsedFieldsets.split('||');
|
||||
} else {
|
||||
collapsedFieldsets = [];
|
||||
}
|
||||
return collapsedFieldsets;
|
||||
}
|
||||
|
||||
function toggleFieldset(legend, animation) {
|
||||
const parent = legend.parent();
|
||||
const fieldset = parent.find('.legend_label').text();
|
||||
const collapsedFieldsets = getCollapsedFieldsets();
|
||||
let index;
|
||||
|
||||
if (parent.hasClass('collapsed')) {
|
||||
if (animation) {
|
||||
parent.find('.panel-body').slideDown();
|
||||
} else {
|
||||
parent.find('.panel-body').show();
|
||||
}
|
||||
parent.removeClass('collapsed');
|
||||
parent.find('span.collapser').text('[-]');
|
||||
|
||||
// removing from array, js is overcomplicated
|
||||
index = collapsedFieldsets.indexOf(fieldset);
|
||||
if (index !== -1) {
|
||||
collapsedFieldsets.splice(index, 1);
|
||||
}
|
||||
} else { // not collapsed
|
||||
if (animation) {
|
||||
parent.find('.panel-body').slideUp();
|
||||
} else {
|
||||
parent.find('.panel-body').hide();
|
||||
}
|
||||
|
||||
parent.addClass('collapsed');
|
||||
parent.find('span.collapser').text('[+]');
|
||||
index = collapsedFieldsets.indexOf(fieldset);
|
||||
if (index === -1 && fieldset !== '' && fieldset !== undefined) {
|
||||
collapsedFieldsets.push(fieldset);
|
||||
}
|
||||
}
|
||||
|
||||
$('#collapsedFieldsets').val(collapsedFieldsets.join('||'));
|
||||
}
|
||||
|
||||
px.initFavStars();
|
||||
|
||||
$('#viz_type').change(function () {
|
||||
$('#query').submit();
|
||||
});
|
||||
|
||||
$('#datasource_id').change(function () {
|
||||
window.location = $(this).find('option:selected').attr('url');
|
||||
});
|
||||
|
||||
const collapsedFieldsets = getCollapsedFieldsets();
|
||||
for (let i = 0; i < collapsedFieldsets.length; i++) {
|
||||
toggleFieldset($('legend:contains("' + collapsedFieldsets[i] + '")'), false);
|
||||
}
|
||||
function formatViz(viz) {
|
||||
const url = `/static/assets/images/viz_thumbnails/${viz.id}.png`;
|
||||
const noImg = '/static/assets/images/noimg.png';
|
||||
return $(
|
||||
`<img class="viz-thumb-option" src="${url}" onerror="this.src='${noImg}';">` +
|
||||
`<span>${viz.text}</span>`
|
||||
);
|
||||
}
|
||||
|
||||
$('.select2').select2({
|
||||
dropdownAutoWidth: true,
|
||||
});
|
||||
$('.select2Sortable').select2({
|
||||
dropdownAutoWidth: true,
|
||||
});
|
||||
$('.select2-with-images').select2({
|
||||
dropdownAutoWidth: true,
|
||||
dropdownCssClass: 'bigdrop',
|
||||
formatResult: formatViz,
|
||||
});
|
||||
$('.select2Sortable').select2Sortable({
|
||||
bindOrder: 'sortableStop',
|
||||
});
|
||||
$('form').show();
|
||||
$('[data-toggle="tooltip"]').tooltip({ container: 'body' });
|
||||
$('.ui-helper-hidden-accessible').remove(); // jQuery-ui 1.11+ creates a div for every tooltip
|
||||
|
||||
function addFilter(i, fieldPrefix) {
|
||||
const cp = $('#' + fieldPrefix + '0').clone();
|
||||
$(cp).appendTo('#' + getPanelClass(fieldPrefix) + ' #filters');
|
||||
$(cp).show();
|
||||
if (i !== undefined) {
|
||||
$(cp).find('#' + fieldPrefix + '_eq_0').val(px.getParam(fieldPrefix + '_eq_' + i));
|
||||
$(cp).find('#' + fieldPrefix + '_op_0').val(px.getParam(fieldPrefix + '_op_' + i));
|
||||
$(cp).find('#' + fieldPrefix + '_col_0').val(px.getParam(fieldPrefix + '_col_' + i));
|
||||
}
|
||||
$(cp).find('select').select2();
|
||||
$(cp).find('.remove').click(function () {
|
||||
$(this)
|
||||
.parent()
|
||||
.parent()
|
||||
.remove();
|
||||
});
|
||||
}
|
||||
|
||||
function setFilters() {
|
||||
['flt', 'having'].forEach(function (prefix) {
|
||||
for (let i = 1; i < 10; i++) {
|
||||
const col = px.getParam(prefix + '_col_' + i);
|
||||
if (col !== '') {
|
||||
addFilter(i, prefix);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
setFilters();
|
||||
|
||||
$(window).bind('popstate', function () {
|
||||
// Browser back button
|
||||
const returnLocation = history.location || document.location;
|
||||
// Could do something more lightweight here, but we're not optimizing
|
||||
// for the use of the back button anyways
|
||||
returnLocation.reload();
|
||||
});
|
||||
|
||||
$('#filter_panel #plus').click(function () {
|
||||
addFilter(undefined, 'flt');
|
||||
});
|
||||
$('#having_panel #plus').click(function () {
|
||||
addFilter(undefined, 'having');
|
||||
});
|
||||
|
||||
function createChoices(term, data) {
|
||||
const filtered = $(data).filter(function () {
|
||||
return this.text.localeCompare(term) === 0;
|
||||
});
|
||||
if (filtered.length === 0) {
|
||||
return {
|
||||
id: term,
|
||||
text: term,
|
||||
};
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
function initSelectionToValue(element, callback) {
|
||||
callback({
|
||||
id: element.val(),
|
||||
text: element.val(),
|
||||
});
|
||||
}
|
||||
|
||||
$('.select2_freeform').each(function () {
|
||||
const parent = $(this).parent();
|
||||
const name = $(this).attr('name');
|
||||
const l = [];
|
||||
let selected = '';
|
||||
for (let i = 0; i < this.options.length; i++) {
|
||||
l.push({
|
||||
id: this.options[i].value,
|
||||
text: this.options[i].text,
|
||||
});
|
||||
if (this.options[i].selected) {
|
||||
selected = this.options[i].value;
|
||||
}
|
||||
}
|
||||
parent.append(
|
||||
`<input class="${$(this).attr('class')}" ` +
|
||||
`name="${name}" type="text" value="${selected}">`
|
||||
);
|
||||
$(`input[name='${name}']`).select2({
|
||||
createSearchChoice: createChoices,
|
||||
initSelection: initSelectionToValue,
|
||||
dropdownAutoWidth: true,
|
||||
multiple: false,
|
||||
data: l,
|
||||
});
|
||||
$(this).remove();
|
||||
});
|
||||
|
||||
function prepSaveDialog() {
|
||||
const setButtonsState = function () {
|
||||
const addToDash = $('input[name=addToDash]:checked').val();
|
||||
if (addToDash === 'existing' || addToDash === 'new') {
|
||||
$('.gotodash').removeAttr('disabled');
|
||||
} else {
|
||||
$('.gotodash').prop('disabled', true);
|
||||
}
|
||||
};
|
||||
const url = '/dashboardmodelviewasync/api/read?_flt_0_owners=' + $('#userid').val();
|
||||
$.get(url, function (data) {
|
||||
const choices = [];
|
||||
for (let i = 0; i < data.pks.length; i++) {
|
||||
choices.push({ id: data.pks[i], text: data.result[i].dashboard_title });
|
||||
}
|
||||
$('#save_to_dashboard_id').select2({
|
||||
data: choices,
|
||||
dropdownAutoWidth: true,
|
||||
}).on('select2-selecting', function () {
|
||||
$('#addToDash_existing').prop('checked', true);
|
||||
setButtonsState();
|
||||
});
|
||||
});
|
||||
|
||||
$('input[name=addToDash]').change(setButtonsState);
|
||||
$("input[name='new_dashboard_name']").on('focus', function () {
|
||||
$('#add_to_new_dash').prop('checked', true);
|
||||
setButtonsState();
|
||||
});
|
||||
$("input[name='new_slice_name']").on('focus', function () {
|
||||
$('#save_as_new').prop('checked', true);
|
||||
setButtonsState();
|
||||
});
|
||||
|
||||
$('#btn_modal_save').on('click', () => saveSlice());
|
||||
|
||||
$('#btn_modal_save_goto_dash').click(() => {
|
||||
document.getElementById('goto_dash').value = 'true';
|
||||
saveSlice();
|
||||
});
|
||||
}
|
||||
prepSaveDialog();
|
||||
}
|
||||
|
||||
function renderExploreActions() {
|
||||
const exploreActionsEl = document.getElementById('js-explore-actions');
|
||||
ReactDOM.render(
|
||||
<ExploreActionButtons
|
||||
canDownload={exploreActionsEl.getAttribute('data-can-download')}
|
||||
slice={slice}
|
||||
/>,
|
||||
exploreActionsEl
|
||||
);
|
||||
}
|
||||
|
||||
function initComponents() {
|
||||
const queryAndSaveBtnsEl = document.getElementById('js-query-and-save-btns');
|
||||
ReactDOM.render(
|
||||
<QueryAndSaveBtns
|
||||
canAdd={queryAndSaveBtnsEl.getAttribute('data-can-add')}
|
||||
onQuery={() => query(true)}
|
||||
/>,
|
||||
queryAndSaveBtnsEl
|
||||
);
|
||||
renderExploreActions();
|
||||
}
|
||||
|
||||
let exploreController = {
|
||||
type: 'slice',
|
||||
done: (sliceObj) => {
|
||||
slice = sliceObj;
|
||||
renderExploreActions();
|
||||
const cachedSelector = $('#is_cached');
|
||||
if (slice.data !== undefined && slice.data.is_cached) {
|
||||
cachedSelector
|
||||
.attr(
|
||||
'title',
|
||||
`Served from data cached at ${slice.data.cached_dttm}. Click [Query] to force refresh`)
|
||||
.show()
|
||||
.tooltip('fixTitle');
|
||||
} else {
|
||||
cachedSelector.hide();
|
||||
}
|
||||
},
|
||||
error: (sliceObj) => {
|
||||
slice = sliceObj;
|
||||
renderExploreActions();
|
||||
},
|
||||
};
|
||||
exploreController = Object.assign({}, utils.controllerInterface, exploreController);
|
||||
|
||||
|
||||
$(document).ready(function () {
|
||||
const data = $('.slice').data('slice');
|
||||
|
||||
initExploreView();
|
||||
|
||||
slice = px.Slice(data, exploreController);
|
||||
|
||||
// call vis render method, which issues ajax
|
||||
// calls render on the slice for the first time
|
||||
query(false, false);
|
||||
|
||||
slice.bindResizeToWindowResize();
|
||||
|
||||
initComponents();
|
||||
});
|
||||
@@ -1,148 +0,0 @@
|
||||
const $ = window.$ = require('jquery');
|
||||
export const SET_DATASOURCE = 'SET_DATASOURCE';
|
||||
export const SET_TIME_COLUMN_OPTS = 'SET_TIME_COLUMN_OPTS';
|
||||
export const SET_TIME_GRAIN_OPTS = 'SET_TIME_GRAIN_OPTS';
|
||||
export const SET_GROUPBY_COLUMN_OPTS = 'SET_GROUPBY_COLUMN_OPTS';
|
||||
export const SET_METRICS_OPTS = 'SET_METRICS_OPTS';
|
||||
export const SET_COLUMN_OPTS = 'SET_COLUMN_OPTS';
|
||||
export const SET_ORDERING_OPTS = 'SET_ORDERING_OPTS';
|
||||
export const TOGGLE_SEARCHBOX = 'TOGGLE_SEARCHBOX';
|
||||
export const SET_FILTER_COLUMN_OPTS = 'SET_FILTER_COLUMN_OPTS';
|
||||
export const ADD_FILTER = 'ADD_FILTER';
|
||||
export const SET_FILTER = 'SET_FILTER';
|
||||
export const REMOVE_FILTER = 'REMOVE_FILTER';
|
||||
export const CHANGE_FILTER_FIELD = 'CHANGE_FILTER_FIELD';
|
||||
export const CHANGE_FILTER_OP = 'CHANGE_FILTER_OP';
|
||||
export const CHANGE_FILTER_VALUE = 'CHANGE_FILTER_VALUE';
|
||||
export const RESET_FORM_DATA = 'RESET_FORM_DATA';
|
||||
export const CLEAR_ALL_OPTS = 'CLEAR_ALL_OPTS';
|
||||
export const SET_DATASOURCE_TYPE = 'SET_DATASOURCE_TYPE';
|
||||
export const SET_FORM_DATA = 'SET_FORM_DATA';
|
||||
|
||||
export function setTimeColumnOpts(timeColumnOpts) {
|
||||
return { type: SET_TIME_COLUMN_OPTS, timeColumnOpts };
|
||||
}
|
||||
|
||||
export function setTimeGrainOpts(timeGrainOpts) {
|
||||
return { type: SET_TIME_GRAIN_OPTS, timeGrainOpts };
|
||||
}
|
||||
|
||||
export function setGroupByColumnOpts(groupByColumnOpts) {
|
||||
return { type: SET_GROUPBY_COLUMN_OPTS, groupByColumnOpts };
|
||||
}
|
||||
|
||||
export function setMetricsOpts(metricsOpts) {
|
||||
return { type: SET_METRICS_OPTS, metricsOpts };
|
||||
}
|
||||
|
||||
export function setColumnOpts(columnOpts) {
|
||||
return { type: SET_COLUMN_OPTS, columnOpts };
|
||||
}
|
||||
|
||||
export function setOrderingOpts(orderingOpts) {
|
||||
return { type: SET_ORDERING_OPTS, orderingOpts };
|
||||
}
|
||||
|
||||
export function setFilterColumnOpts(filterColumnOpts) {
|
||||
return { type: SET_FILTER_COLUMN_OPTS, filterColumnOpts };
|
||||
}
|
||||
|
||||
export function resetFormData() {
|
||||
// Clear all form data when switching datasource
|
||||
return { type: RESET_FORM_DATA };
|
||||
}
|
||||
|
||||
export function clearAllOpts() {
|
||||
return { type: CLEAR_ALL_OPTS };
|
||||
}
|
||||
|
||||
export function setDatasourceType(datasourceType) {
|
||||
return { type: SET_DATASOURCE_TYPE, datasourceType };
|
||||
}
|
||||
|
||||
export function setFormOpts(datasourceId, datasourceType) {
|
||||
return function (dispatch) {
|
||||
const timeColumnOpts = [];
|
||||
const groupByColumnOpts = [];
|
||||
const metricsOpts = [];
|
||||
const filterColumnOpts = [];
|
||||
const timeGrainOpts = [];
|
||||
const columnOpts = [];
|
||||
const orderingOpts = [];
|
||||
|
||||
if (datasourceId) {
|
||||
const params = [`datasource_id=${datasourceId}`, `datasource_type=${datasourceType}`];
|
||||
const url = '/caravel/fetch_datasource_metadata?' + params.join('&');
|
||||
|
||||
$.get(url, (data, status) => {
|
||||
if (status === 'success') {
|
||||
data.time_columns.forEach((d) => {
|
||||
if (d) timeColumnOpts.push({ value: d, label: d });
|
||||
});
|
||||
data.groupby_cols.forEach((d) => {
|
||||
if (d) groupByColumnOpts.push({ value: d, label: d });
|
||||
});
|
||||
data.metrics.forEach((d) => {
|
||||
if (d) metricsOpts.push({ value: d[1], label: d[0] });
|
||||
});
|
||||
data.filter_cols.forEach((d) => {
|
||||
if (d) filterColumnOpts.push({ value: d, label: d });
|
||||
});
|
||||
data.time_grains.forEach((d) => {
|
||||
if (d) timeGrainOpts.push({ value: d, label: d });
|
||||
});
|
||||
data.columns.forEach((d) => {
|
||||
if (d) columnOpts.push({ value: d, label: d });
|
||||
});
|
||||
data.ordering_cols.forEach((d) => {
|
||||
if (d) orderingOpts.push({ value: d, label: d });
|
||||
});
|
||||
|
||||
// Repopulate options for controls
|
||||
dispatch(setTimeColumnOpts(timeColumnOpts));
|
||||
dispatch(setTimeGrainOpts(timeGrainOpts));
|
||||
dispatch(setGroupByColumnOpts(groupByColumnOpts));
|
||||
dispatch(setMetricsOpts(metricsOpts));
|
||||
dispatch(setFilterColumnOpts(filterColumnOpts));
|
||||
dispatch(setColumnOpts(columnOpts));
|
||||
dispatch(setOrderingOpts(orderingOpts));
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// Clear all Select options
|
||||
dispatch(clearAllOpts());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export function setDatasource(datasourceId) {
|
||||
return { type: SET_DATASOURCE, datasourceId };
|
||||
}
|
||||
|
||||
export function toggleSearchBox(searchBox) {
|
||||
return { type: TOGGLE_SEARCHBOX, searchBox };
|
||||
}
|
||||
|
||||
export function addFilter(filter) {
|
||||
return { type: ADD_FILTER, filter };
|
||||
}
|
||||
|
||||
export function removeFilter(filter) {
|
||||
return { type: REMOVE_FILTER, filter };
|
||||
}
|
||||
|
||||
export function changeFilterField(filter, field) {
|
||||
return { type: CHANGE_FILTER_FIELD, filter, field };
|
||||
}
|
||||
|
||||
export function changeFilterOp(filter, op) {
|
||||
return { type: CHANGE_FILTER_OP, filter, op };
|
||||
}
|
||||
|
||||
export function changeFilterValue(filter, value) {
|
||||
return { type: CHANGE_FILTER_VALUE, filter, value };
|
||||
}
|
||||
|
||||
export function setFormData(key, value) {
|
||||
return { type: SET_FORM_DATA, key, value };
|
||||
}
|
||||
@@ -1,90 +0,0 @@
|
||||
import React, { PropTypes } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { Panel } from 'react-bootstrap';
|
||||
import visMap from '../../../visualizations/main';
|
||||
|
||||
const propTypes = {
|
||||
sliceName: PropTypes.string.isRequired,
|
||||
vizType: PropTypes.string.isRequired,
|
||||
height: PropTypes.string.isRequired,
|
||||
sliceContainerId: PropTypes.string.isRequired,
|
||||
jsonEndpoint: PropTypes.string.isRequired,
|
||||
};
|
||||
|
||||
class ChartContainer extends React.Component {
|
||||
componentDidMount() {
|
||||
this.renderVis();
|
||||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
this.renderVis();
|
||||
}
|
||||
|
||||
getMockedSliceObject() {
|
||||
return {
|
||||
jsonEndpoint: () => this.props.jsonEndpoint,
|
||||
|
||||
container: {
|
||||
html: () => {
|
||||
// this should be a callback to clear the contents of the slice container
|
||||
},
|
||||
|
||||
css: () => {
|
||||
// dimension can be 'height'
|
||||
// pixel string can be '300px'
|
||||
// should call callback to adjust height of chart
|
||||
},
|
||||
},
|
||||
|
||||
width: () => this.chartContainerRef.getBoundingClientRect().width,
|
||||
|
||||
height: () => parseInt(this.props.height, 10) - 100,
|
||||
|
||||
selector: `#${this.props.sliceContainerId}`,
|
||||
|
||||
done: () => {
|
||||
// finished rendering callback
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
renderVis() {
|
||||
const slice = this.getMockedSliceObject();
|
||||
visMap[this.props.vizType](slice).render();
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div className="chart-container">
|
||||
<Panel
|
||||
style={{ height: this.props.height }}
|
||||
header={
|
||||
<div className="panel-title">{this.props.sliceName}</div>
|
||||
}
|
||||
>
|
||||
<div
|
||||
id={this.props.sliceContainerId}
|
||||
ref={(ref) => { this.chartContainerRef = ref; }}
|
||||
/>
|
||||
</Panel>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ChartContainer.propTypes = propTypes;
|
||||
|
||||
function mapStateToProps(state) {
|
||||
return {
|
||||
sliceName: state.sliceName,
|
||||
vizType: state.viz.formData.vizType,
|
||||
sliceContainerId: `slice-container-${state.viz.formData.sliceId}`,
|
||||
jsonEndpoint: state.viz.jsonEndPoint,
|
||||
};
|
||||
}
|
||||
|
||||
function mapDispatchToProps() {
|
||||
return {};
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(ChartContainer);
|
||||
@@ -1,89 +0,0 @@
|
||||
import React from 'react';
|
||||
import Select from 'react-select';
|
||||
import { bindActionCreators } from 'redux';
|
||||
import * as actions from '../actions/exploreActions';
|
||||
import { connect } from 'react-redux';
|
||||
import { VIZ_TYPES } from '../constants';
|
||||
|
||||
const propTypes = {
|
||||
actions: React.PropTypes.object,
|
||||
datasources: React.PropTypes.array,
|
||||
datasourceId: React.PropTypes.number,
|
||||
datasourceType: React.PropTypes.string,
|
||||
vizType: React.PropTypes.string,
|
||||
};
|
||||
|
||||
const defaultProps = {
|
||||
datasources: [],
|
||||
datasourceId: null,
|
||||
datasourceType: null,
|
||||
vizType: null,
|
||||
};
|
||||
|
||||
class ChartControl extends React.Component {
|
||||
componentWillMount() {
|
||||
if (this.props.datasourceId) {
|
||||
this.props.actions.setFormOpts(this.props.datasourceId, this.props.datasourceType);
|
||||
}
|
||||
}
|
||||
changeDatasource(datasourceOpt) {
|
||||
const val = (datasourceOpt) ? datasourceOpt.value : null;
|
||||
this.props.actions.setDatasource(val);
|
||||
this.props.actions.resetFormData();
|
||||
this.props.actions.setFormOpts(val, this.props.datasourceType);
|
||||
}
|
||||
changeViz(opt) {
|
||||
const val = opt ? opt.value : null;
|
||||
this.props.actions.setFormData('vizType', val);
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<div className="panel">
|
||||
<div className="panel-header">Chart Options</div>
|
||||
<div className="panel-body">
|
||||
<h5 className="section-heading">Datasource</h5>
|
||||
<div className="row">
|
||||
<Select
|
||||
name="select-datasource"
|
||||
placeholder="Select a datasource"
|
||||
options={this.props.datasources.map((d) => ({ value: d[0], label: d[1] }))}
|
||||
value={this.props.datasourceId}
|
||||
autosize={false}
|
||||
onChange={this.changeDatasource.bind(this)}
|
||||
/>
|
||||
</div>
|
||||
<h5 className="section-heading">Viz Type</h5>
|
||||
<div className="row">
|
||||
<Select
|
||||
name="select-viztype"
|
||||
placeholder="Select a viz type"
|
||||
options={VIZ_TYPES}
|
||||
value={this.props.vizType}
|
||||
autosize={false}
|
||||
onChange={this.changeViz.bind(this)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ChartControl.propTypes = propTypes;
|
||||
ChartControl.defaultProps = defaultProps;
|
||||
|
||||
function mapStateToProps(state) {
|
||||
return {
|
||||
datasources: state.datasources,
|
||||
datasourceId: state.datasourceId,
|
||||
datasourceType: state.datasourceType,
|
||||
vizType: state.viz.formData.vizType,
|
||||
};
|
||||
}
|
||||
|
||||
function mapDispatchToProps(dispatch) {
|
||||
return {
|
||||
actions: bindActionCreators(actions, dispatch),
|
||||
};
|
||||
}
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(ChartControl);
|
||||
@@ -1,40 +0,0 @@
|
||||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { Panel } from 'react-bootstrap';
|
||||
import { DefaultControls, VIZ_CONTROL_MAPPING } from '../constants';
|
||||
|
||||
const propTypes = {
|
||||
vizType: React.PropTypes.string,
|
||||
};
|
||||
|
||||
const defaultProps = {
|
||||
vizType: null,
|
||||
};
|
||||
|
||||
function ControlPanelsContainer(props) {
|
||||
return (
|
||||
<Panel>
|
||||
<div className="scrollbar-container">
|
||||
<div className="scrollbar-content">
|
||||
{DefaultControls}
|
||||
{VIZ_CONTROL_MAPPING[props.vizType]}
|
||||
</div>
|
||||
</div>
|
||||
</Panel>
|
||||
);
|
||||
}
|
||||
|
||||
ControlPanelsContainer.propTypes = propTypes;
|
||||
ControlPanelsContainer.defaultProps = defaultProps;
|
||||
|
||||
function mapStateToProps(state) {
|
||||
return {
|
||||
vizType: state.viz.formData.vizType,
|
||||
};
|
||||
}
|
||||
|
||||
function mapDispatchToProps() {
|
||||
return {};
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(ControlPanelsContainer);
|
||||
@@ -1,46 +0,0 @@
|
||||
import React from 'react';
|
||||
import ChartContainer from './ChartContainer';
|
||||
import ControlPanelsContainer from './ControlPanelsContainer';
|
||||
import QueryAndSaveBtns from '../../explore/components/QueryAndSaveBtns';
|
||||
|
||||
export default class ExploreViewContainer extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
height: this.getHeight(),
|
||||
};
|
||||
}
|
||||
|
||||
getHeight() {
|
||||
const navHeight = 90;
|
||||
return `${window.innerHeight - navHeight}px`;
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div
|
||||
className="container-fluid"
|
||||
style={{
|
||||
height: this.state.height,
|
||||
overflow: 'hidden',
|
||||
}}
|
||||
>
|
||||
<div className="row">
|
||||
<div className="col-sm-4">
|
||||
<QueryAndSaveBtns
|
||||
canAdd="True"
|
||||
onQuery={() => {}}
|
||||
/>
|
||||
<br /><br />
|
||||
<ControlPanelsContainer />
|
||||
</div>
|
||||
<div className="col-sm-8">
|
||||
<ChartContainer
|
||||
height={this.state.height}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,127 +0,0 @@
|
||||
import React from 'react';
|
||||
// import { Tab, Row, Col, Nav, NavItem } from 'react-bootstrap';
|
||||
import Select from 'react-select';
|
||||
import { Button } from 'react-bootstrap';
|
||||
import { connect } from 'react-redux';
|
||||
import { bindActionCreators } from 'redux';
|
||||
import * as actions from '../actions/exploreActions';
|
||||
import shortid from 'shortid';
|
||||
|
||||
const propTypes = {
|
||||
actions: React.PropTypes.object,
|
||||
filterColumnOpts: React.PropTypes.array,
|
||||
filters: React.PropTypes.array,
|
||||
};
|
||||
|
||||
const defaultProps = {
|
||||
filterColumnOpts: [],
|
||||
filters: [],
|
||||
};
|
||||
|
||||
class Filters extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
opOpts: ['in', 'not in'],
|
||||
};
|
||||
}
|
||||
changeField(filter, fieldOpt) {
|
||||
const val = (fieldOpt) ? fieldOpt.value : null;
|
||||
this.props.actions.changeFilterField(filter, val);
|
||||
}
|
||||
changeOp(filter, opOpt) {
|
||||
const val = (opOpt) ? opOpt.value : null;
|
||||
this.props.actions.changeFilterOp(filter, val);
|
||||
}
|
||||
changeValue(filter, value) {
|
||||
this.props.actions.changeFilterValue(filter, value);
|
||||
}
|
||||
removeFilter(filter) {
|
||||
this.props.actions.removeFilter(filter);
|
||||
}
|
||||
addFilter() {
|
||||
this.props.actions.addFilter({
|
||||
id: shortid.generate(),
|
||||
field: null,
|
||||
op: null,
|
||||
value: null,
|
||||
});
|
||||
}
|
||||
render() {
|
||||
const filters = this.props.filters.map((filter) => (
|
||||
<div>
|
||||
<Select
|
||||
className="row"
|
||||
multi={false}
|
||||
name="select-column"
|
||||
placeholder="Select column"
|
||||
options={this.props.filterColumnOpts}
|
||||
value={filter.field}
|
||||
autosize={false}
|
||||
onChange={this.changeField.bind(this, filter)}
|
||||
/>
|
||||
<div className="row">
|
||||
<Select
|
||||
className="col-sm-3"
|
||||
multi={false}
|
||||
name="select-op"
|
||||
placeholder="Select operator"
|
||||
options={this.state.opOpts.map((o) => ({ value: o, label: o }))}
|
||||
value={filter.op}
|
||||
autosize={false}
|
||||
onChange={this.changeOp.bind(this, filter)}
|
||||
/>
|
||||
<div className="col-sm-6">
|
||||
<input
|
||||
type="text"
|
||||
onChange={this.changeValue.bind(this, filter)}
|
||||
className="form-control input-sm"
|
||||
placeholder="Filter value"
|
||||
/>
|
||||
</div>
|
||||
<div className="col-sm-3">
|
||||
<Button
|
||||
bsStyle="primary"
|
||||
onClick={this.removeFilter.bind(this, filter)}
|
||||
>
|
||||
<i className="fa fa-minus" />
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
);
|
||||
return (
|
||||
<div className="panel space-1">
|
||||
<div className="panel-header">Filters</div>
|
||||
<div className="panel-body">
|
||||
{filters}
|
||||
<Button
|
||||
bsStyle="primary"
|
||||
onClick={this.addFilter.bind(this)}
|
||||
>
|
||||
<i className="fa fa-plus" />Add Filter
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Filters.propTypes = propTypes;
|
||||
Filters.defaultProps = defaultProps;
|
||||
|
||||
function mapStateToProps(state) {
|
||||
return {
|
||||
filterColumnOpts: state.filterColumnOpts,
|
||||
filters: state.filters,
|
||||
};
|
||||
}
|
||||
|
||||
function mapDispatchToProps(dispatch) {
|
||||
return {
|
||||
actions: bindActionCreators(actions, dispatch),
|
||||
};
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(Filters);
|
||||
@@ -1,68 +0,0 @@
|
||||
import React from 'react';
|
||||
import { bindActionCreators } from 'redux';
|
||||
import * as actions from '../actions/exploreActions';
|
||||
import { connect } from 'react-redux';
|
||||
import SelectArray from './SelectArray';
|
||||
|
||||
const propTypes = {
|
||||
actions: React.PropTypes.object,
|
||||
metricsOpts: React.PropTypes.array,
|
||||
metrics: React.PropTypes.array,
|
||||
groupByColumnOpts: React.PropTypes.array,
|
||||
groupByColumns: React.PropTypes.array,
|
||||
};
|
||||
|
||||
const defaultProps = {
|
||||
metricsOpts: [],
|
||||
metrics: [],
|
||||
groupByColumnOpts: [],
|
||||
groupByColumns: [],
|
||||
};
|
||||
|
||||
const GroupBy = (props) => {
|
||||
const selects = [
|
||||
{
|
||||
key: 'groupByColumns',
|
||||
title: 'Group By',
|
||||
options: props.groupByColumnOpts,
|
||||
value: props.groupByColumns,
|
||||
multi: true,
|
||||
width: '12',
|
||||
},
|
||||
{
|
||||
key: 'metrics',
|
||||
title: 'Metrics',
|
||||
options: props.metricsOpts,
|
||||
value: props.metrics,
|
||||
multi: true,
|
||||
width: '12',
|
||||
}];
|
||||
return (
|
||||
<div className="panel">
|
||||
<div className="panel-header">GroupBy</div>
|
||||
<div className="panel-body">
|
||||
<SelectArray selectArray={selects} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
GroupBy.propTypes = propTypes;
|
||||
GroupBy.defaultProps = defaultProps;
|
||||
|
||||
function mapStateToProps(state) {
|
||||
return {
|
||||
metricsOpts: state.metricsOpts,
|
||||
metrics: state.viz.formData.metrics,
|
||||
groupByColumnOpts: state.groupByColumnOpts,
|
||||
groupByColumns: state.viz.formData.groupByColumns,
|
||||
};
|
||||
}
|
||||
|
||||
function mapDispatchToProps(dispatch) {
|
||||
return {
|
||||
actions: bindActionCreators(actions, dispatch),
|
||||
};
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(GroupBy);
|
||||
@@ -1,68 +0,0 @@
|
||||
import React from 'react';
|
||||
import SelectArray from './SelectArray';
|
||||
import { bindActionCreators } from 'redux';
|
||||
import * as actions from '../actions/exploreActions';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
const propTypes = {
|
||||
actions: React.PropTypes.object,
|
||||
columnOpts: React.PropTypes.array,
|
||||
columns: React.PropTypes.array,
|
||||
orderingOpts: React.PropTypes.array,
|
||||
orderings: React.PropTypes.array,
|
||||
};
|
||||
|
||||
const defaultProps = {
|
||||
columnOpts: [],
|
||||
columns: [],
|
||||
orderingOpts: [],
|
||||
orderings: [],
|
||||
};
|
||||
|
||||
const NotGroupBy = (props) => {
|
||||
const selects = [
|
||||
{
|
||||
key: 'columns',
|
||||
title: 'Columns',
|
||||
options: props.columnOpts,
|
||||
value: props.columns,
|
||||
multi: true,
|
||||
width: '12',
|
||||
},
|
||||
{
|
||||
key: 'orderings',
|
||||
title: 'Orderings',
|
||||
options: props.orderingOpts,
|
||||
value: props.orderings,
|
||||
multi: true,
|
||||
width: '12',
|
||||
}];
|
||||
return (
|
||||
<div className="panel">
|
||||
<div className="panel-header">Not GroupBy</div>
|
||||
<div className="panel-body">
|
||||
<SelectArray selectArray={selects} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
NotGroupBy.propTypes = propTypes;
|
||||
NotGroupBy.defaultProps = defaultProps;
|
||||
|
||||
function mapStateToProps(state) {
|
||||
return {
|
||||
columnOpts: state.columnOpts,
|
||||
columns: state.viz.formData.columns,
|
||||
orderingOpts: state.orderingOpts,
|
||||
orderings: state.viz.formData.orderings,
|
||||
};
|
||||
}
|
||||
|
||||
function mapDispatchToProps(dispatch) {
|
||||
return {
|
||||
actions: bindActionCreators(actions, dispatch),
|
||||
};
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(NotGroupBy);
|
||||
@@ -1,61 +0,0 @@
|
||||
import React from 'react';
|
||||
import SelectArray from './SelectArray';
|
||||
import { bindActionCreators } from 'redux';
|
||||
import * as actions from '../actions/exploreActions';
|
||||
import { connect } from 'react-redux';
|
||||
import { timestampOptions, rowLimitOptions } from '../constants';
|
||||
|
||||
const propTypes = {
|
||||
actions: React.PropTypes.object,
|
||||
timeStampFormat: React.PropTypes.string,
|
||||
rowLimit: React.PropTypes.number,
|
||||
};
|
||||
|
||||
const defaultProps = {
|
||||
timeStampFormat: null,
|
||||
rowLimit: null,
|
||||
};
|
||||
|
||||
const Options = (props) => {
|
||||
const selects = [
|
||||
{
|
||||
key: 'timeStampFormat',
|
||||
title: 'Timestamp Format',
|
||||
options: timestampOptions.map((t) => ({ value: t[0], label: t[1] })),
|
||||
value: props.timeStampFormat,
|
||||
width: '12',
|
||||
},
|
||||
{
|
||||
key: 'rowLimit',
|
||||
title: 'Row Limit',
|
||||
options: rowLimitOptions.map((r) => ({ value: r, label: r })),
|
||||
value: props.rowLimit,
|
||||
width: '12',
|
||||
}];
|
||||
return (
|
||||
<div className="panel">
|
||||
<div className="panel-header">Options</div>
|
||||
<div className="panel-body">
|
||||
<SelectArray selectArray={selects} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
Options.propTypes = propTypes;
|
||||
Options.defaultProps = defaultProps;
|
||||
|
||||
function mapStateToProps(state) {
|
||||
return {
|
||||
timeStampFormat: state.viz.formData.timeStampFormat,
|
||||
rowLimit: state.viz.formData.rowLimit,
|
||||
};
|
||||
}
|
||||
|
||||
function mapDispatchToProps(dispatch) {
|
||||
return {
|
||||
actions: bindActionCreators(actions, dispatch),
|
||||
};
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(Options);
|
||||
@@ -1,74 +0,0 @@
|
||||
import React from 'react';
|
||||
import Select from 'react-select';
|
||||
import { bindActionCreators } from 'redux';
|
||||
import * as actions from '../actions/exploreActions';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
const propTypes = {
|
||||
actions: React.PropTypes.object,
|
||||
selectArray: React.PropTypes.arrayOf(
|
||||
React.PropTypes.shape({
|
||||
key: React.PropTypes.string.isRequired,
|
||||
title: React.PropTypes.string.isRequired,
|
||||
options: React.PropTypes.array.isRequired,
|
||||
value: React.PropTypes.oneOfType([
|
||||
React.PropTypes.string,
|
||||
React.PropTypes.array,
|
||||
]),
|
||||
width: React.PropTypes.string,
|
||||
multi: React.PropTypes.bool,
|
||||
})
|
||||
).isRequired,
|
||||
};
|
||||
|
||||
const defaultProps = {
|
||||
selectArray: [],
|
||||
};
|
||||
|
||||
class SelectArray extends React.Component {
|
||||
changeSelectData(key, multi, opt) {
|
||||
if (multi) this.props.actions.setFormData(key, opt);
|
||||
else {
|
||||
const val = opt ? opt.value : null;
|
||||
this.props.actions.setFormData(key, val);
|
||||
}
|
||||
}
|
||||
render() {
|
||||
const selects = this.props.selectArray.map((obj) => (
|
||||
<div
|
||||
className={(obj.width) ? `col-sm-${obj.width}` : 'col-sm-6'}
|
||||
key={obj.key}
|
||||
>
|
||||
<h5 className="section-heading">{obj.title}</h5>
|
||||
<Select
|
||||
multi={obj.multi}
|
||||
name={`select-${obj.key}`}
|
||||
options={obj.options}
|
||||
value={obj.value}
|
||||
autosize={false}
|
||||
onChange={this.changeSelectData.bind(this, obj.key, obj.multi)}
|
||||
/>
|
||||
</div>
|
||||
));
|
||||
return (
|
||||
<div>
|
||||
{selects}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
SelectArray.propTypes = propTypes;
|
||||
SelectArray.defaultProps = defaultProps;
|
||||
|
||||
function mapStateToProps() {
|
||||
return {};
|
||||
}
|
||||
|
||||
function mapDispatchToProps(dispatch) {
|
||||
return {
|
||||
actions: bindActionCreators(actions, dispatch),
|
||||
};
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(SelectArray);
|
||||
@@ -1,55 +0,0 @@
|
||||
import React from 'react';
|
||||
import { bindActionCreators } from 'redux';
|
||||
import * as actions from '../actions/exploreActions';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
const propTypes = {
|
||||
actions: React.PropTypes.object,
|
||||
};
|
||||
|
||||
class SqlClause extends React.Component {
|
||||
onChange(key, event) {
|
||||
this.props.actions.setFormData(key, event.target.value);
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<div className="panel">
|
||||
<div className="panel-header">SQL</div>
|
||||
<div className="panel-body">
|
||||
<div className="row">
|
||||
<h5 className="section-heading">Where</h5>
|
||||
<input
|
||||
type="text"
|
||||
onChange={this.onChange.bind(this, 'where')}
|
||||
className="form-control input-sm"
|
||||
placeholder="Where Clause"
|
||||
/>
|
||||
</div>
|
||||
<div className="row">
|
||||
<h5 className="section-heading">Having</h5>
|
||||
<input
|
||||
type="text"
|
||||
onChange={this.onChange.bind(this, 'having')}
|
||||
className="form-control input-sm"
|
||||
placeholder="Having Clause"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
SqlClause.propTypes = propTypes;
|
||||
|
||||
function mapStateToProps() {
|
||||
return {};
|
||||
}
|
||||
|
||||
function mapDispatchToProps(dispatch) {
|
||||
return {
|
||||
actions: bindActionCreators(actions, dispatch),
|
||||
};
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(SqlClause);
|
||||
@@ -1,88 +0,0 @@
|
||||
import React from 'react';
|
||||
import { bindActionCreators } from 'redux';
|
||||
import * as actions from '../actions/exploreActions';
|
||||
import { connect } from 'react-redux';
|
||||
import { sinceOptions, untilOptions } from '../constants';
|
||||
import SelectArray from './SelectArray';
|
||||
|
||||
const propTypes = {
|
||||
actions: React.PropTypes.object,
|
||||
datasourceType: React.PropTypes.string,
|
||||
timeColumnOpts: React.PropTypes.array,
|
||||
timeColumn: React.PropTypes.string,
|
||||
timeGrainOpts: React.PropTypes.array,
|
||||
timeGrain: React.PropTypes.string,
|
||||
since: React.PropTypes.string,
|
||||
until: React.PropTypes.string,
|
||||
};
|
||||
|
||||
const defaultProps = {
|
||||
timeColumnOpts: [],
|
||||
timeColumn: null,
|
||||
timeGrainOpts: [],
|
||||
timeGrain: null,
|
||||
since: null,
|
||||
until: null,
|
||||
};
|
||||
|
||||
const TimeFilter = (props) => {
|
||||
const isDatasourceTypeTable = props.datasourceType === 'table';
|
||||
const timeColumnTitle = isDatasourceTypeTable ? 'Time Column' : 'Time Granularity';
|
||||
const timeGrainTitle = isDatasourceTypeTable ? 'Time Grain' : 'Origin';
|
||||
const selects = [
|
||||
{
|
||||
key: 'timeColumn',
|
||||
title: timeColumnTitle,
|
||||
options: props.timeColumnOpts,
|
||||
value: props.timeColumn,
|
||||
},
|
||||
{
|
||||
key: 'timeGrain',
|
||||
title: timeGrainTitle,
|
||||
options: props.timeGrainOpts,
|
||||
value: props.timeGrain,
|
||||
},
|
||||
{
|
||||
key: 'since',
|
||||
title: 'Since',
|
||||
options: sinceOptions.map((s) => ({ value: s, label: s })),
|
||||
value: props.since,
|
||||
},
|
||||
{
|
||||
key: 'until',
|
||||
title: 'Until',
|
||||
options: untilOptions.map((u) => ({ value: u, label: u })),
|
||||
value: props.until,
|
||||
}];
|
||||
return (
|
||||
<div className="panel">
|
||||
<div className="panel-header">Time Filter</div>
|
||||
<div className="panel-body">
|
||||
<SelectArray selectArray={selects} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
TimeFilter.propTypes = propTypes;
|
||||
TimeFilter.defaultProps = defaultProps;
|
||||
|
||||
function mapStateToProps(state) {
|
||||
return {
|
||||
datasourceType: state.datasourceType,
|
||||
timeColumnOpts: state.timeColumnOpts,
|
||||
timeColumn: state.viz.formData.timeColumn,
|
||||
timeGrainOpts: state.timeGrainOpts,
|
||||
timeGrain: state.viz.formData.timeGrain,
|
||||
since: state.viz.formData.since,
|
||||
until: state.viz.formData.until,
|
||||
};
|
||||
}
|
||||
|
||||
function mapDispatchToProps(dispatch) {
|
||||
return {
|
||||
actions: bindActionCreators(actions, dispatch),
|
||||
};
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(TimeFilter);
|
||||
@@ -1,76 +0,0 @@
|
||||
import React from 'react';
|
||||
import TimeFilter from './components/TimeFilter';
|
||||
import ChartControl from './components/ChartControl';
|
||||
import GroupBy from './components/GroupBy';
|
||||
import SqlClause from './components/SqlClause';
|
||||
import Filters from './components/Filters';
|
||||
import NotGroupBy from './components/NotGroupBy';
|
||||
import Options from './components/Options';
|
||||
|
||||
export const VIZ_TYPES = [
|
||||
{ value: 'dist_bar', label: 'Distribution - Bar Chart', requiresTime: false },
|
||||
{ value: 'pie', label: 'Pie Chart', requiresTime: false },
|
||||
{ value: 'line', label: 'Time Series - Line Chart', requiresTime: true },
|
||||
{ value: 'bar', label: 'Time Series - Bar Chart', requiresTime: true },
|
||||
{ value: 'compare', label: 'Time Series - Percent Change', requiresTime: true },
|
||||
{ value: 'area', label: 'Time Series - Stacked', requiresTime: true },
|
||||
{ value: 'table', label: 'Table View', requiresTime: false },
|
||||
{ value: 'markup', label: 'Markup', requiresTime: false },
|
||||
{ value: 'pivot_table', label: 'Pivot Table', requiresTime: false },
|
||||
{ value: 'separator', label: 'Separator', requiresTime: false },
|
||||
{ value: 'word_cloud', label: 'Word Cloud', requiresTime: false },
|
||||
{ value: 'treemap', label: 'Treemap', requiresTime: false },
|
||||
{ value: 'cal_heatmap', label: 'Calendar Heatmap', requiresTime: true },
|
||||
{ value: 'box_plot', label: 'Box Plot', requiresTime: false },
|
||||
{ value: 'bubble', label: 'Bubble Chart', requiresTime: false },
|
||||
{ value: 'big_number', label: 'Big Number with Trendline', requiresTime: false },
|
||||
{ value: 'bubble', label: 'Bubble Chart', requiresTime: false },
|
||||
{ value: 'histogram', label: 'Histogram', requiresTime: false },
|
||||
{ value: 'sunburst', label: 'Sunburst', requiresTime: false },
|
||||
{ value: 'sankey', label: 'Sankey', requiresTime: false },
|
||||
{ value: 'directed_force', label: 'Directed Force Layout', requiresTime: false },
|
||||
{ value: 'world_map', label: 'World Map', requiresTime: false },
|
||||
{ value: 'filter_box', label: 'Filter Box', requiresTime: false },
|
||||
{ value: 'iframe', label: 'iFrame', requiresTime: false },
|
||||
{ value: 'para', label: 'Parallel Coordinates', requiresTime: false },
|
||||
{ value: 'heatmap', label: 'Heatmap', requiresTime: false },
|
||||
{ value: 'horizon', label: 'Horizon', requiresTime: false },
|
||||
{ value: 'mapbox', label: 'Mapbox', requiresTime: false },
|
||||
];
|
||||
|
||||
export const sinceOptions = ['1 hour ago', '12 hours ago', '1 day ago',
|
||||
'7 days ago', '28 days ago', '90 days ago', '1 year ago'];
|
||||
export const untilOptions = ['now', '1 day ago', '7 days ago',
|
||||
'28 days ago', '90 days ago', '1 year ago'];
|
||||
|
||||
export const timestampOptions = [
|
||||
['smart_date', 'Adaptative formating'],
|
||||
['%m/%d/%Y', '"%m/%d/%Y" | 01/14/2019'],
|
||||
['%Y-%m-%d', '"%Y-%m-%d" | 2019-01-14'],
|
||||
['%Y-%m-%d %H:%M:%S',
|
||||
'"%Y-%m-%d %H:%M:%S" | 2019-01-14 01:32:10'],
|
||||
['%H:%M:%S', '"%H:%M:%S" | 01:32:10'],
|
||||
];
|
||||
|
||||
export const rowLimitOptions = [10, 50, 100, 250, 500, 1000, 5000, 10000, 50000];
|
||||
|
||||
export const DefaultControls = (
|
||||
<div>
|
||||
<ChartControl />
|
||||
<TimeFilter />
|
||||
<GroupBy />
|
||||
<SqlClause />
|
||||
<Filters />
|
||||
</div>
|
||||
);
|
||||
|
||||
export const TableVizControls = (
|
||||
<div>
|
||||
<NotGroupBy />
|
||||
<Options />
|
||||
</div>
|
||||
);
|
||||
|
||||
export const VIZ_CONTROL_MAPPING = {
|
||||
table: TableVizControls,
|
||||
};
|
||||
@@ -1,48 +0,0 @@
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import ExploreViewContainer from './components/ExploreViewContainer';
|
||||
import { createStore, applyMiddleware, compose } from 'redux';
|
||||
import { Provider } from 'react-redux';
|
||||
import thunk from 'redux-thunk';
|
||||
|
||||
import { initialState } from './stores/store';
|
||||
|
||||
const exploreViewContainer = document.getElementById('js-explore-view-container');
|
||||
const bootstrapData = JSON.parse(exploreViewContainer.getAttribute('data-bootstrap'));
|
||||
|
||||
import { exploreReducer } from './reducers/exploreReducer';
|
||||
|
||||
const bootstrappedState = Object.assign(initialState, {
|
||||
datasources: bootstrapData.datasources,
|
||||
datasourceId: parseInt(bootstrapData.datasource_id, 10),
|
||||
datasourceType: bootstrapData.datasource_type,
|
||||
sliceName: bootstrapData.viz.form_data.slice_name,
|
||||
viz: {
|
||||
jsonEndPoint: bootstrapData.viz.json_endpoint,
|
||||
data: bootstrapData.viz.data,
|
||||
formData: {
|
||||
sliceId: bootstrapData.viz.form_data.slice_id,
|
||||
vizType: bootstrapData.viz.form_data.viz_type,
|
||||
timeColumn: bootstrapData.viz.form_data.granularity_sqla,
|
||||
timeGrain: bootstrapData.viz.form_data.time_grain_sqla,
|
||||
metrics: [bootstrapData.viz.form_data.metrics].map((m) => ({ value: m, label: m })),
|
||||
since: bootstrapData.viz.form_data.since,
|
||||
until: bootstrapData.viz.form_data.until,
|
||||
having: bootstrapData.viz.form_data.having,
|
||||
where: bootstrapData.viz.form_data.where,
|
||||
rowLimit: bootstrapData.viz.form_data.row_limit,
|
||||
timeStampFormat: bootstrapData.viz.form_data.table_timestamp_format,
|
||||
},
|
||||
},
|
||||
});
|
||||
const store = createStore(exploreReducer, bootstrappedState,
|
||||
compose(applyMiddleware(thunk))
|
||||
);
|
||||
|
||||
ReactDOM.render(
|
||||
<Provider store={store}>
|
||||
<ExploreViewContainer />
|
||||
</Provider>,
|
||||
exploreViewContainer
|
||||
);
|
||||
|
||||
@@ -1,89 +0,0 @@
|
||||
import { defaultFormData, defaultOpts } from '../stores/store';
|
||||
import * as actions from '../actions/exploreActions';
|
||||
import { addToArr, removeFromArr, alterInArr } from '../../../utils/reducerUtils';
|
||||
|
||||
const setFormInViz = function (state, action) {
|
||||
const newFormData = Object.assign({}, state);
|
||||
newFormData[action.key] = action.value;
|
||||
return newFormData;
|
||||
};
|
||||
|
||||
const setVizInState = function (state, action) {
|
||||
switch (action.type) {
|
||||
case actions.SET_FORM_DATA:
|
||||
return Object.assign(
|
||||
{},
|
||||
state,
|
||||
{ formData: setFormInViz(state.formData, action) }
|
||||
);
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
};
|
||||
|
||||
export const exploreReducer = function (state, action) {
|
||||
const actionHandlers = {
|
||||
[actions.SET_DATASOURCE]() {
|
||||
return Object.assign({}, state, { datasourceId: action.datasourceId });
|
||||
},
|
||||
[actions.SET_TIME_COLUMN_OPTS]() {
|
||||
return Object.assign({}, state, { timeColumnOpts: action.timeColumnOpts });
|
||||
},
|
||||
[actions.SET_TIME_GRAIN_OPTS]() {
|
||||
return Object.assign({}, state, { timeGrainOpts: action.timeGrainOpts });
|
||||
},
|
||||
[actions.SET_GROUPBY_COLUMN_OPTS]() {
|
||||
return Object.assign({}, state, { groupByColumnOpts: action.groupByColumnOpts });
|
||||
},
|
||||
[actions.SET_METRICS_OPTS]() {
|
||||
return Object.assign({}, state, { metricsOpts: action.metricsOpts });
|
||||
},
|
||||
[actions.SET_COLUMN_OPTS]() {
|
||||
return Object.assign({}, state, { columnOpts: action.columnOpts });
|
||||
},
|
||||
[actions.SET_ORDERING_OPTS]() {
|
||||
return Object.assign({}, state, { orderingOpts: action.orderingOpts });
|
||||
},
|
||||
[actions.TOGGLE_SEARCHBOX]() {
|
||||
return Object.assign({}, state, { searchBox: action.searchBox });
|
||||
},
|
||||
[actions.SET_FILTER_COLUMN_OPTS]() {
|
||||
return Object.assign({}, state, { filterColumnOpts: action.filterColumnOpts });
|
||||
},
|
||||
[actions.ADD_FILTER]() {
|
||||
return addToArr(state, 'filters', action.filter);
|
||||
},
|
||||
[actions.REMOVE_FILTER]() {
|
||||
return removeFromArr(state, 'filters', action.filter);
|
||||
},
|
||||
[actions.CHANGE_FILTER_FIELD]() {
|
||||
return alterInArr(state, 'filters', action.filter, { field: action.field });
|
||||
},
|
||||
[actions.CHANGE_FILTER_OP]() {
|
||||
return alterInArr(state, 'filters', action.filter, { op: action.op });
|
||||
},
|
||||
[actions.CHANGE_FILTER_VALUE]() {
|
||||
return alterInArr(state, 'filters', action.filter, { value: action.value });
|
||||
},
|
||||
[actions.RESET_FORM_DATA]() {
|
||||
return Object.assign({}, state, defaultFormData);
|
||||
},
|
||||
[actions.CLEAR_ALL_OPTS]() {
|
||||
return Object.assign({}, state, defaultOpts);
|
||||
},
|
||||
[actions.SET_DATASOURCE_TYPE]() {
|
||||
return Object.assign({}, state, { datasourceType: action.datasourceType });
|
||||
},
|
||||
[actions.SET_FORM_DATA]() {
|
||||
return Object.assign(
|
||||
{},
|
||||
state,
|
||||
{ viz: setVizInState(state.viz, action) }
|
||||
);
|
||||
},
|
||||
};
|
||||
if (action.type in actionHandlers) {
|
||||
return actionHandlers[action.type]();
|
||||
}
|
||||
return state;
|
||||
};
|
||||
@@ -1,52 +0,0 @@
|
||||
// TODO: add datasource_type here after druid support is added
|
||||
export const defaultFormData = {
|
||||
sliceId: null,
|
||||
vizType: null,
|
||||
timeColumn: null,
|
||||
timeGrain: null,
|
||||
groupByColumns: [],
|
||||
metrics: [],
|
||||
since: null,
|
||||
until: null,
|
||||
having: null,
|
||||
where: null,
|
||||
columns: [],
|
||||
orderings: [],
|
||||
timeStampFormat: 'smart_date',
|
||||
rowLimit: 50000,
|
||||
searchBox: false,
|
||||
whereClause: '',
|
||||
havingClause: '',
|
||||
filters: [],
|
||||
};
|
||||
|
||||
export const initialState = {
|
||||
datasources: null,
|
||||
datasourceId: null,
|
||||
datasourceType: null,
|
||||
timeColumnOpts: [],
|
||||
timeGrainOpts: [],
|
||||
timeGrain: null,
|
||||
groupByColumnOpts: [],
|
||||
metricsOpts: [],
|
||||
columnOpts: [],
|
||||
orderingOpts: [],
|
||||
searchBox: false,
|
||||
whereClause: '',
|
||||
havingClause: '',
|
||||
filters: [],
|
||||
filterColumnOpts: [],
|
||||
viz: {
|
||||
formData: defaultFormData,
|
||||
},
|
||||
};
|
||||
|
||||
export const defaultOpts = {
|
||||
timeColumnOpts: [],
|
||||
timeGrainOpts: [],
|
||||
groupByColumnOpts: [],
|
||||
metricsOpts: [],
|
||||
filterColumnOpts: [],
|
||||
columnOpts: [],
|
||||
orderingOpts: [],
|
||||
};
|
||||
@@ -1,14 +0,0 @@
|
||||
import React from 'react';
|
||||
import { render } from 'react-dom';
|
||||
import { Jumbotron } from 'react-bootstrap';
|
||||
|
||||
function App() {
|
||||
return (
|
||||
<Jumbotron>
|
||||
<h1>Caravel</h1>
|
||||
<p>Extensible visualization tool for exploring data from any database.</p>
|
||||
</Jumbotron>
|
||||
);
|
||||
}
|
||||
|
||||
render(<App />, document.getElementById('app'));
|
||||
@@ -1,129 +0,0 @@
|
||||
const d3 = require('d3');
|
||||
const $ = require('jquery');
|
||||
/*
|
||||
Utility function that takes a d3 svg:text selection and a max width, and splits the
|
||||
text's text across multiple tspan lines such that any given line does not exceed max width
|
||||
|
||||
If text does not span multiple lines AND adjustedY is passed,
|
||||
will set the text to the passed val
|
||||
*/
|
||||
export function wrapSvgText(text, width, adjustedY) {
|
||||
const lineHeight = 1;
|
||||
// ems
|
||||
text.each(function () {
|
||||
const d3Text = d3.select(this);
|
||||
const words = d3Text.text().split(/\s+/);
|
||||
let word;
|
||||
let line = [];
|
||||
let lineNumber = 0;
|
||||
const x = d3Text.attr('x');
|
||||
const y = d3Text.attr('y');
|
||||
const dy = parseFloat(d3Text.attr('dy'));
|
||||
let tspan =
|
||||
d3Text.text(null).append('tspan').attr('x', x)
|
||||
.attr('y', y)
|
||||
.attr('dy', dy + 'em');
|
||||
|
||||
let didWrap = false;
|
||||
for (let i = 0; i < words.length; i++) {
|
||||
word = words[i];
|
||||
line.push(word);
|
||||
tspan.text(line.join(' '));
|
||||
if (tspan.node().getComputedTextLength() > width) {
|
||||
line.pop();
|
||||
// remove word that pushes over the limit
|
||||
tspan.text(line.join(' '));
|
||||
line = [word];
|
||||
tspan =
|
||||
d3Text.append('tspan').attr('x', x).attr('y', y)
|
||||
.attr('dy', ++lineNumber * lineHeight + dy + 'em')
|
||||
.text(word);
|
||||
didWrap = true;
|
||||
}
|
||||
}
|
||||
if (!didWrap && typeof adjustedY !== 'undefined') {
|
||||
tspan.attr('y', adjustedY);
|
||||
}
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Sets the body and title content of a modal, and shows it. Assumes HTML for modal exists and that
|
||||
* it handles closing (i.e., works with bootstrap)
|
||||
*
|
||||
* @param {object} options object of the form
|
||||
* {
|
||||
* title: {string},
|
||||
* body: {string},
|
||||
* modalSelector: {string, default: '.misc-modal' },
|
||||
* titleSelector: {string, default: '.misc-modal .modal-title' },
|
||||
* bodySelector: {string, default: '.misc-modal .modal-body' },
|
||||
* }
|
||||
*/
|
||||
function showModal(options) {
|
||||
/* eslint no-param-reassign: 0 */
|
||||
options.modalSelector = options.modalSelector || '.misc-modal';
|
||||
options.titleSelector = options.titleSelector || '.misc-modal .modal-title';
|
||||
options.bodySelector = options.bodySelector || '.misc-modal .modal-body';
|
||||
$(options.titleSelector).html(options.title || '');
|
||||
$(options.bodySelector).html(options.body || '');
|
||||
$(options.modalSelector).modal('show');
|
||||
}
|
||||
const showApiMessage = function (resp) {
|
||||
const template =
|
||||
'<div class="alert"> ' +
|
||||
'<button type="button" class="close" ' +
|
||||
'data-dismiss="alert">\xD7</button> </div>';
|
||||
const severity = resp.severity || 'info';
|
||||
$(template).addClass('alert-' + severity)
|
||||
.append(resp.message)
|
||||
.appendTo($('#alert-container'));
|
||||
};
|
||||
const toggleCheckbox = function (apiUrlPrefix, selector) {
|
||||
const apiUrl = apiUrlPrefix + $(selector)[0].checked;
|
||||
$.get(apiUrl).fail(function (xhr) {
|
||||
const resp = xhr.responseJSON;
|
||||
if (resp && resp.message) {
|
||||
showApiMessage(resp);
|
||||
}
|
||||
});
|
||||
};
|
||||
/**
|
||||
* Fix the height of the table body of a DataTable with scrollY set
|
||||
*/
|
||||
const fixDataTableBodyHeight = function ($tableDom, height) {
|
||||
const headHeight = $tableDom.find('.dataTables_scrollHead').height();
|
||||
$tableDom.find('.dataTables_scrollBody').css('max-height', height - headHeight);
|
||||
};
|
||||
const formatters = {};
|
||||
function d3format(format, number) {
|
||||
// Formats a number and memoizes formatters to be reused
|
||||
format = format || '.3s';
|
||||
if (!(format in formatters)) {
|
||||
formatters[format] = d3.format(format);
|
||||
}
|
||||
return formatters[format](number);
|
||||
}
|
||||
|
||||
// Slice objects interact with their context through objects that implement
|
||||
// this controllerInterface (dashboard, explore, standalone)
|
||||
const controllerInterface = {
|
||||
type: null,
|
||||
done: () => {},
|
||||
error: () => {},
|
||||
always: () => {},
|
||||
addFiler: () => {},
|
||||
setFilter: () => {},
|
||||
getFilters: () => false,
|
||||
clearFilter: () => {},
|
||||
removeFilter: () => {},
|
||||
filters: {},
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
controllerInterface,
|
||||
d3format,
|
||||
fixDataTableBodyHeight,
|
||||
showModal,
|
||||
toggleCheckbox,
|
||||
wrapSvgText,
|
||||
};
|
||||
@@ -1,17 +0,0 @@
|
||||
const $ = window.$ = require('jquery');
|
||||
/* eslint no-unused-vars: 0 */
|
||||
const jQuery = window.jQuery = $;
|
||||
const px = require('./modules/caravel.js');
|
||||
const utils = require('./modules/utils.js');
|
||||
|
||||
require('bootstrap');
|
||||
|
||||
const standaloneController = Object.assign(
|
||||
{}, utils.controllerInterface, { type: 'standalone' });
|
||||
|
||||
$(document).ready(function () {
|
||||
const data = $('.slice').data('slice');
|
||||
const slice = px.Slice(data, standaloneController);
|
||||
slice.render();
|
||||
slice.bindResizeToWindowResize();
|
||||
});
|
||||
@@ -1,11 +0,0 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
cd "$(dirname "$0")"
|
||||
npm --version
|
||||
node --version
|
||||
npm install
|
||||
npm run lint
|
||||
npm run test
|
||||
npm run build
|
||||
npm run cover
|
||||
CODECLIMATE_REPO_TOKEN=5f3a06c425eef7be4b43627d7d07a3e46c45bdc07155217825ff7c49cb6a470c ./node_modules/.bin/codeclimate-test-reporter < ./coverage/lcov.info
|
||||
@@ -1,124 +0,0 @@
|
||||
{
|
||||
"name": "caravel",
|
||||
"version": "0.11.0",
|
||||
"description": "Caravel is a data exploration platform designed to be visual, intuitive, and interactive.",
|
||||
"license": "Apache-2.0",
|
||||
"directories": {
|
||||
"doc": "docs",
|
||||
"test": "spec"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "npm run lint && mocha --compilers js:babel-core/register --require spec/helpers/browser.js --recursive spec/**/*_spec.*",
|
||||
"cover": "babel-node ./node_modules/.bin/istanbul cover _mocha -- --require spec/helpers/browser.js --recursive spec/**/*_spec.*",
|
||||
"dev": "NODE_ENV=dev webpack -d --watch --colors --progress",
|
||||
"prod": "NODE_ENV=production webpack -p --colors --progress",
|
||||
"build": "NODE_ENV=production webpack --colors --progress",
|
||||
"lint": "eslint --ignore-path=.eslintignore --ext .js,.jsx ."
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/airbnb/caravel.git"
|
||||
},
|
||||
"keywords": [
|
||||
"big",
|
||||
"data",
|
||||
"exploratory",
|
||||
"analysis",
|
||||
"react",
|
||||
"d3",
|
||||
"airbnb",
|
||||
"nerds",
|
||||
"database",
|
||||
"flask"
|
||||
],
|
||||
"author": "Airbnb",
|
||||
"bugs": {
|
||||
"url": "https://github.com/airbnb/caravel/issues"
|
||||
},
|
||||
"homepage": "https://github.com/airbnb/caravel#readme",
|
||||
"dependencies": {
|
||||
"autobind-decorator": "^1.3.3",
|
||||
"bootstrap": "^3.3.6",
|
||||
"bootstrap-datepicker": "^1.6.0",
|
||||
"brace": "^0.8.0",
|
||||
"brfs": "^1.4.3",
|
||||
"cal-heatmap": "3.6.2",
|
||||
"classnames": "^2.2.5",
|
||||
"d3": "^3.5.15",
|
||||
"d3-cloud": "^1.2.1",
|
||||
"d3-sankey": "^0.4.1",
|
||||
"d3-scale": "^1.0.3",
|
||||
"d3-tip": "^0.7.1",
|
||||
"datamaps": "^0.5.8",
|
||||
"datatables-bootstrap3-plugin": "^0.5.0",
|
||||
"datatables.net-bs": "^1.10.11",
|
||||
"font-awesome": "^4.6.3",
|
||||
"gridster": "^0.5.6",
|
||||
"immutability-helper": "^2.0.0",
|
||||
"jquery": "^2.2.1",
|
||||
"jquery-ui": "1.10.5",
|
||||
"mapbox-gl": "^0.26.0",
|
||||
"moment": "^2.14.1",
|
||||
"moments": "0.0.2",
|
||||
"mustache": "^2.2.1",
|
||||
"nvd3": "1.8.4",
|
||||
"react": "^15.3.2",
|
||||
"react-ace": "^3.4.1",
|
||||
"react-bootstrap": "^0.30.3",
|
||||
"react-bootstrap-table": "^2.3.8",
|
||||
"react-dom": "^15.3.2",
|
||||
"react-draggable": "^2.1.2",
|
||||
"react-grid-layout": "^0.13.1",
|
||||
"react-map-gl": "^1.7.0",
|
||||
"react-redux": "^4.4.5",
|
||||
"react-resizable": "^1.3.3",
|
||||
"react-select": "^1.0.0-rc.2",
|
||||
"react-syntax-highlighter": "^2.3.0",
|
||||
"reactable": "^0.14.0",
|
||||
"redux": "^3.5.2",
|
||||
"redux-localstorage": "^0.4.1",
|
||||
"redux-thunk": "^2.1.0",
|
||||
"select2": "3.5",
|
||||
"select2-bootstrap-css": "^1.4.6",
|
||||
"shortid": "^2.2.6",
|
||||
"style-loader": "^0.13.0",
|
||||
"supercluster": "https://github.com/georgeke/supercluster/tarball/ac3492737e7ce98e07af679623aad452373bbc40",
|
||||
"topojson": "^1.6.22",
|
||||
"victory": "^0.12.1",
|
||||
"viewport-mercator-project": "^2.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"babel": "^6.3.26",
|
||||
"babel-cli": "^6.14.0",
|
||||
"babel-polyfill": "^6.14.0",
|
||||
"babel-preset-es2015": "^6.14.0",
|
||||
"babel-core": "^6.10.4",
|
||||
"babel-loader": "^6.2.4",
|
||||
"babel-preset-airbnb": "^2.1.1",
|
||||
"babel-preset-react": "^6.11.1",
|
||||
"chai": "^3.5.0",
|
||||
"codeclimate-test-reporter": "^0.3.3",
|
||||
"css-loader": "^0.23.1",
|
||||
"enzyme": "^2.0.0",
|
||||
"eslint": "^2.13.1",
|
||||
"eslint-config-airbnb": "^9.0.1",
|
||||
"eslint-plugin-import": "^1.11.1",
|
||||
"eslint-plugin-jsx-a11y": "^1.2.0",
|
||||
"eslint-plugin-react": "^5.2.2",
|
||||
"exports-loader": "^0.6.3",
|
||||
"file-loader": "^0.8.5",
|
||||
"imports-loader": "^0.6.5",
|
||||
"istanbul": "^1.0.0-alpha",
|
||||
"jsdom": "^8.0.1",
|
||||
"json-loader": "^0.5.4",
|
||||
"less": "^2.6.1",
|
||||
"less-loader": "^2.2.2",
|
||||
"mocha": "^2.4.5",
|
||||
"react-addons-test-utils": "^15.3.2",
|
||||
"style-loader": "^0.13.0",
|
||||
"transform-loader": "^0.2.3",
|
||||
"url-loader": "^0.5.7",
|
||||
"webpack": "^1.13.1",
|
||||
"webworkify-webpack": "1.0.6"
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
/* eslint no-undef: 0, no-native-reassign: 0 */
|
||||
|
||||
require('babel-register')();
|
||||
|
||||
const jsdom = require('jsdom').jsdom;
|
||||
|
||||
const exposedProperties = ['window', 'navigator', 'document'];
|
||||
|
||||
global.document = jsdom('');
|
||||
global.window = document.defaultView;
|
||||
Object.keys(document.defaultView).forEach((property) => {
|
||||
if (typeof global[property] === 'undefined') {
|
||||
exposedProperties.push(property);
|
||||
global[property] = document.defaultView[property];
|
||||
}
|
||||
});
|
||||
|
||||
global.navigator = {
|
||||
userAgent: 'node.js',
|
||||
};
|
||||
@@ -1,17 +0,0 @@
|
||||
import React from 'react';
|
||||
import { expect } from 'chai';
|
||||
import { describe, it } from 'mocha';
|
||||
|
||||
import DisplayQueryButton from '../../../../javascripts/explore/components/DisplayQueryButton';
|
||||
|
||||
describe('DisplayQueryButton', () => {
|
||||
const defaultProps = {
|
||||
slice: {
|
||||
viewSqlQuery: 'sql query string',
|
||||
},
|
||||
};
|
||||
|
||||
it('renders', () => {
|
||||
expect(React.isValidElement(<DisplayQueryButton {...defaultProps} />)).to.equal(true);
|
||||
});
|
||||
});
|
||||
@@ -1,50 +0,0 @@
|
||||
import { it, describe } from 'mocha';
|
||||
import { expect } from 'chai';
|
||||
import shortid from 'shortid';
|
||||
import * as actions from '../../../../javascripts/explorev2/actions/exploreActions';
|
||||
import { initialState } from '../../../../javascripts/explorev2/stores/store';
|
||||
import { exploreReducer } from '../../../../javascripts/explorev2/reducers/exploreReducer';
|
||||
|
||||
describe('reducers', () => {
|
||||
it('should return new state with datasource id', () => {
|
||||
const newState = exploreReducer(initialState, actions.setDatasource(1));
|
||||
expect(newState.datasourceId).to.equal(1);
|
||||
});
|
||||
|
||||
it('should return new state with search box toggled', () => {
|
||||
const newState = exploreReducer(initialState, actions.toggleSearchBox(true));
|
||||
expect(newState.searchBox).to.equal(true);
|
||||
});
|
||||
|
||||
it('should return new state with added filter', () => {
|
||||
const newFilter = {
|
||||
id: shortid.generate(),
|
||||
eq: 'value',
|
||||
op: 'in',
|
||||
col: 'vals',
|
||||
};
|
||||
const newState = exploreReducer(initialState, actions.addFilter(newFilter));
|
||||
expect(newState.filters).to.deep.equal([newFilter]);
|
||||
});
|
||||
|
||||
it('should return new state with removed filter', () => {
|
||||
const filter1 = {
|
||||
id: shortid.generate(),
|
||||
eq: 'value',
|
||||
op: 'in',
|
||||
col: 'vals1',
|
||||
};
|
||||
const filter2 = {
|
||||
id: shortid.generate(),
|
||||
eq: 'value',
|
||||
op: 'not in',
|
||||
col: 'vals2',
|
||||
};
|
||||
const testState = {
|
||||
initialState,
|
||||
filters: [filter1, filter2],
|
||||
};
|
||||
const newState = exploreReducer(testState, actions.removeFilter(filter1));
|
||||
expect(newState.filters).to.deep.equal([filter2]);
|
||||
});
|
||||
});
|
||||
@@ -1,30 +0,0 @@
|
||||
import React from 'react';
|
||||
import Select from 'react-select';
|
||||
import { Button } from 'react-bootstrap';
|
||||
import QuerySearch from '../../../javascripts/SqlLab/components/QuerySearch';
|
||||
import { shallow } from 'enzyme';
|
||||
import { describe, it } from 'mocha';
|
||||
import { expect } from 'chai';
|
||||
|
||||
describe('QuerySearch', () => {
|
||||
it('should render', () => {
|
||||
expect(
|
||||
React.isValidElement(<QuerySearch />)
|
||||
).to.equal(true);
|
||||
});
|
||||
|
||||
it('should have two Select', () => {
|
||||
const wrapper = shallow(<QuerySearch />);
|
||||
expect(wrapper.find(Select)).to.have.length(2);
|
||||
});
|
||||
|
||||
it('should have one input for searchText', () => {
|
||||
const wrapper = shallow(<QuerySearch />);
|
||||
expect(wrapper.find('input')).to.have.length(1);
|
||||
});
|
||||
|
||||
it('should have one Button', () => {
|
||||
const wrapper = shallow(<QuerySearch />);
|
||||
expect(wrapper.find(Button)).to.have.length(1);
|
||||
});
|
||||
});
|
||||
@@ -1,158 +0,0 @@
|
||||
import React from 'react';
|
||||
import Link from '../../../javascripts/SqlLab/components/Link';
|
||||
import { Button } from 'react-bootstrap';
|
||||
import { TableElement } from '../../../javascripts/SqlLab/components/TableElement';
|
||||
import { shallow } from 'enzyme';
|
||||
import { describe, it } from 'mocha';
|
||||
import { expect } from 'chai';
|
||||
|
||||
|
||||
describe('TableElement', () => {
|
||||
|
||||
const mockedProps = {
|
||||
'table': {
|
||||
"dbId": 1,
|
||||
"queryEditorId": "rJ-KP47a",
|
||||
"schema": "caravel",
|
||||
"name": "ab_user",
|
||||
"id": "r11Vgt60",
|
||||
"indexes": [
|
||||
{
|
||||
"unique": true,
|
||||
"column_names": [
|
||||
"username"
|
||||
],
|
||||
"type": "UNIQUE",
|
||||
"name": "username"
|
||||
},
|
||||
{
|
||||
"unique": true,
|
||||
"column_names": [
|
||||
"email"
|
||||
],
|
||||
"type": "UNIQUE",
|
||||
"name": "email"
|
||||
},
|
||||
{
|
||||
"unique": false,
|
||||
"column_names": [
|
||||
"created_by_fk"
|
||||
],
|
||||
"name": "created_by_fk"
|
||||
},
|
||||
{
|
||||
"unique": false,
|
||||
"column_names": [
|
||||
"changed_by_fk"
|
||||
],
|
||||
"name": "changed_by_fk"
|
||||
}
|
||||
],
|
||||
"columns": [
|
||||
{
|
||||
"indexed": false,
|
||||
"longType": "INTEGER(11)",
|
||||
"type": "INTEGER",
|
||||
"name": "id"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"longType": "VARCHAR(64)",
|
||||
"type": "VARCHAR",
|
||||
"name": "first_name"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"longType": "VARCHAR(64)",
|
||||
"type": "VARCHAR",
|
||||
"name": "last_name"
|
||||
},
|
||||
{
|
||||
"indexed": true,
|
||||
"longType": "VARCHAR(64)",
|
||||
"type": "VARCHAR",
|
||||
"name": "username"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"longType": "VARCHAR(256)",
|
||||
"type": "VARCHAR",
|
||||
"name": "password"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"longType": "TINYINT(1)",
|
||||
"type": "TINYINT",
|
||||
"name": "active"
|
||||
},
|
||||
{
|
||||
"indexed": true,
|
||||
"longType": "VARCHAR(64)",
|
||||
"type": "VARCHAR",
|
||||
"name": "email"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"longType": "DATETIME",
|
||||
"type": "DATETIME",
|
||||
"name": "last_login"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"longType": "INTEGER(11)",
|
||||
"type": "INTEGER",
|
||||
"name": "login_count"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"longType": "INTEGER(11)",
|
||||
"type": "INTEGER",
|
||||
"name": "fail_login_count"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"longType": "DATETIME",
|
||||
"type": "DATETIME",
|
||||
"name": "created_on"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"longType": "DATETIME",
|
||||
"type": "DATETIME",
|
||||
"name": "changed_on"
|
||||
},
|
||||
{
|
||||
"indexed": true,
|
||||
"longType": "INTEGER(11)",
|
||||
"type": "INTEGER",
|
||||
"name": "created_by_fk"
|
||||
},
|
||||
{
|
||||
"indexed": true,
|
||||
"longType": "INTEGER(11)",
|
||||
"type": "INTEGER",
|
||||
"name": "changed_by_fk"
|
||||
}
|
||||
],
|
||||
"expanded": true
|
||||
}
|
||||
}
|
||||
it('should just render', () => {
|
||||
expect(
|
||||
React.isValidElement(<TableElement />)
|
||||
).to.equal(true);
|
||||
});
|
||||
it('should render with props', () => {
|
||||
expect(
|
||||
React.isValidElement(<TableElement {...mockedProps} />)
|
||||
).to.equal(true);
|
||||
});
|
||||
it('has 3 Link elements', () => {
|
||||
const wrapper = shallow(<TableElement {...mockedProps} />);
|
||||
expect(wrapper.find(Link)).to.have.length(3);
|
||||
});
|
||||
it('has 14 columns', () => {
|
||||
const wrapper = shallow(<TableElement {...mockedProps} />);
|
||||
expect(wrapper.find('div.table-column')).to.have.length(14);
|
||||
});
|
||||
});
|
||||
@@ -1,28 +0,0 @@
|
||||
import * as r from '../../../javascripts/SqlLab/reducers';
|
||||
import * as actions from '../../../javascripts/SqlLab/actions';
|
||||
import { describe, it } from 'mocha';
|
||||
import { expect } from 'chai';
|
||||
|
||||
describe('sqlLabReducer', () => {
|
||||
describe('CLONE_QUERY_TO_NEW_TAB', () => {
|
||||
const testQuery = { sql: 'SELECT * FROM...', dbId: 1, id: 1 };
|
||||
const state = Object.assign(r.initialState, { queries: [testQuery] });
|
||||
const newState = r.sqlLabReducer(state, actions.cloneQueryToNewTab(testQuery));
|
||||
|
||||
it('should have at most one more tab', () => {
|
||||
expect(newState.queryEditors).have.length(2);
|
||||
});
|
||||
|
||||
it('should have the same SQL as the cloned query', () => {
|
||||
expect(newState.queryEditors[1].sql).to.equal(testQuery.sql);
|
||||
});
|
||||
|
||||
it('should prefix the new tab title with "Copy of"', () => {
|
||||
expect(newState.queryEditors[1].title).to.include('Copy of');
|
||||
});
|
||||
|
||||
it('should push the cloned tab onto tab history stack', () => {
|
||||
expect(newState.tabHistory[1]).to.eq(newState.queryEditors[1].id);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,17 +0,0 @@
|
||||
.scrollbar-container {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.scrollbar-content {
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
right: 0px;
|
||||
bottom: 0px;
|
||||
overflow: scroll;
|
||||
margin-right: 0px;
|
||||
margin-bottom: 100px;
|
||||
}
|
||||