From c6dca0f27d6abcbeb392b33b6e9bc2952f247ccd Mon Sep 17 00:00:00 2001 From: Maxime Date: Tue, 21 Jul 2015 18:56:05 +0000 Subject: [PATCH] Improvements --- .gitignore | 1 + TODO.md | 7 +- app.db | Bin 60416 -> 71680 bytes app/__init__.py | 15 ---- app/models.py | 8 ++- app/templates/appbuilder/baselayout.html | 6 +- app/templates/index.html | 14 ++-- app/templates/panoramix/base.html | 3 + app/templates/panoramix/datasource.html | 10 ++- app/templates/panoramix/viz_highcharts.html | 14 +++- app/views.py | 68 ++---------------- app/viz.py | 76 +++++++++++++++++++- config.py | 15 +++- requirements.txt | 1 + 14 files changed, 137 insertions(+), 101 deletions(-) diff --git a/.gitignore b/.gitignore index 57c945dd2..ef242d231 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ *.pyc *.db tmp +local_config diff --git a/TODO.md b/TODO.md index 8ac2b7988..f6a28803f 100644 --- a/TODO.md +++ b/TODO.md @@ -1,8 +1,5 @@ # TODO -* STOCK CHART + compare time ranges -* Save a chart -* Datasource + Owner -* Column description +* compare time ranges * Label * CSV -* Bookmarks / url shortener +* Save / bookmark / url shortener diff --git a/app.db b/app.db index 7d4b7d04657811761204190fa7e0a22ccb751c84..9b459d8478dfd13b1e44d1cfba29cb771b800a26 100644 GIT binary patch literal 71680 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 z z_$ZDnuwvIdPVUkpb4o}HSN05$QXwgtab&?LH#|wGO}SWI-);$7o+jvSV#rsPD7ZXmT;{Q2r0I{n0u6C<}#c6H1I!(V>Hskwh}H z1hky^`NJ93N>7GfrRm!>k2AVP zb)$)mW!N>WMu_b>fqs<{DrRpLkF&W(b+b3D)*|q#LfDe z!c1Q|8>KCSopTjp7bzRIW3oT%WmzbCMm=?A3K^vCpzFMsnM=VXudTw!5U z$b3+am|dhoEeeT`#}z_!oR_UfS8!=9IT_ET7XhTxCPo4n3p~wxoRhr{bcK>)X9=S# zATdwTJK5fcMrhvSyzF(L!!C&~y|a-sszVp(7hnDhhIoH_{@*lB!4lD?IsAaPRhdd#hZ7hL0U-CG?Y*ZJA zLu^X5Jc!{Xh!d!Dxi6jK>GSWB$2nzsj3|kws7FT_0m*AH%9FgB$LVCFx)?3&BbMou z<3-!B6goU6DK(E%yVrrnR_$Ekj@j6`)M+YwG=ZB|^Gc-I^k|T0tJpD5XaFg8?M=Xb zOCG0g>xZe3cNC>}7!CFVDtZ%(&`9yw7d%eb9@WKXk$_NEEQ>QnTEp(7UtEpK^E6-n z>$LyxDE9v?SQ+z2&6CDwjd~CHf3=`lkCWy`b(2AC%0gWW75@<=uNbjFgGO_~Yu;IA z4xRVlAdx_^+7B8ML@CalQ^AJEsd1yasUUX$Ws!uc(1QdiDm0XA8GNmA#p5ivQC&!q zoKD5gD()EE(Ih*zCxTV)6cbJtxXrmGSM5aS+%lH=JDD$v+g|ZF!A;u-TucLiLI+bfTST!xW!2*ZWetUw*Y2

v|O^)b2e-bvcp(^yM5Tb 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∾`U}fPfO*+!dkVJFV{+|^-8Vf18&y_#OF_+c>Me<`yifRPhr1K(VcpO2imoZ zg8%<*ufk?z@ZtXip+?{O{FG1|f2v(zZm)~baDEN?lc94r;C-vjyO#qzPk z%E9Z9>v7LotyQTWtJSZ;lXP?NWA2zJ$k1`UnR}|0l}hWFlD%gU6b*JG&u8hAfsaiA zupwaf*gow+_(y-2pNHT6D++xjI*RsQQ(~_v!E0&)B{lYn8oZ(gje*~ zD|+yXk?@KUd&LM|$tAp!i@lNyUNIA1F=MZo!7En6D^~0kD|p3Dc*TyrVjpw;|FQsQ zdfW^9e=UfABmR)MSNLtAoU9DD40*z#3FPA(uMkd_fiaD*L7@d02+4&80A8T3;Lt4b zagHabX)pw2&cq``3wg`b@sGyj79E-iKF$dnXfUj0Z6^dCIY4wZaF&x?u`3Qu0Uzf? z-(c%bn?0gMh#B(AKuj~l#dxr0(V-i~Oz?s=xQ`bz#*RCDX<-W3PK-EO!J(VNOz@&Luxk%% zTUjvN05P>tRgh3LTvK%D1~6PPfYwQfJi)%nZ42Z!5G!7D!J(VKbk3xQ@|tE+&j65i z&)`z=12(AteS#v8_mKV2|6hRo-w%in3ttg_7;dsY7af|m&Q#%CMpdVEYg#v_V8R!6 z+VDj(1~JvpSLDU82oI<#p;17F;h+K4N0y>tQ zja{?xghsl!ClG2EJM4d+ozkW93OAg%+rgK&~79ZTafa@W@5+M;|g&NKZlT{tMDa-`NH-k+jaGIGB0z`-zVH8jb zyBZPaY{{Yf!tg2vCkMh787y)LQR1eH<(=XAe}sGkHQjd4|6?hA_guGv`mAJMiF%v*%8nK7KC4erPg^%ZsSJv=_ttd#5vdi-krBHg<;4==HsaGJA1q zfZkqL5%7)0O1WA(4X-ufy{GrGi?R3F8_wY^y~4~4)bDt-OnFE=UASB>;^||tIt75& zs~!PHM%hEaXKy^Txknfo8<}{VmewuUy>2l=-fxJJ$g!JPxcA2FCW>b~2~T06SSs_; zJid{lu^DK*Mvbog;G=wMh@zb9h?2QjijVuuAjNI06E`2><$+#dVq)uXq+x)rQ@7EMg>hNlM;}Xe#yW@uUko1ZrAYQMkc3k?`G`*UP(&I75hFdFkME&0 z#m6!iA$)v1CsP#9K}NY^J6G{>o!>xl%`k8!Z;Ho9dzMhN$8G^FAL+vqMapW}a9R0? zW<-i;C%bfTVHbOUm#g=LRu9*4}ad$$Jw!?S1^pp3FlzEtHTj&tdqlAvF

qy7yTZ!(we_X$kfmfE4t-88G{cYqcWI zp&ux&H5zbs%%MzSGDANvWg2Ceimzqbkj%l1dNgyxBUn3LUs-@@#=Y=x7*F9)W??ep zzg#%D5PoSMPQPs7E76zQBg=wsC04oeJ zLkqnF-~73LL^_v@)Phx((P*WI6d@KfO)iuhaDD*s+a2)3258YEr+xf*YC|a9CcLij z#2}&_Peu!ee?o>nix&t9PavNhLR1qSP{E`^Gz{sL5EevgW_bP#`+rILq(I8>)%|oi zaK~}L$?WPCY#TgKE#4!$Gc>VY*u5F+dD#x(`n*sVA)~`>1Hft6u`|g@#tEue0rA%B zSUg0>C>*`*_WvTug8zTVHT)a9z*6OnUB5fDcFw7dxDXUN-@%tRhn$)mIyG5)T2ZE8 zM`k?w(VGOcGO9AIz&2I-6l`e&`<8@k4SOwU_yOi}&?aL&sFpq0EW>%xrDm`wbh*C9 zS`><^-(CWm#r|I;?}zh$@6ZP67Q4%VH!cUBbLe3d6MJA?Nqom4clC%it!1Y)15S<% en;cxVV&IAxI5`<$A&Y`@39xzL%Bs8I@c#jN{lM7( diff --git a/app/__init__.py b/app/__init__.py index 8c8ef8829..9bbdd8ea9 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -19,20 +19,5 @@ class MyIndexView(IndexView): appbuilder = AppBuilder( app, db.session, base_template='panoramix/base.html', indexview=MyIndexView) -#appbuilder.app_name = 'Panoramix' - - -""" -from sqlalchemy.engine import Engine -from sqlalchemy import event - -#Only include this for SQLLite constraints -@event.listens_for(Engine, "connect") -def set_sqlite_pragma(dbapi_connection, connection_record): - # Will force sqllite contraint foreign keys - cursor = dbapi_connection.cursor() - cursor.execute("PRAGMA foreign_keys=ON") - cursor.close() -""" from app import views diff --git a/app/models.py b/app/models.py index 221e73c6f..82cc38797 100644 --- a/app/models.py +++ b/app/models.py @@ -1,6 +1,7 @@ from flask.ext.appbuilder import Model from datetime import datetime, timedelta from flask.ext.appbuilder.models.mixins import AuditMixin, FileColumn, ImageColumn +from flask.ext.appbuilder.security.sqla.models import User from sqlalchemy import Column, Integer, String, ForeignKey, Text, Boolean from sqlalchemy.orm import relationship from app import db, utils @@ -18,6 +19,9 @@ class Datasource(Model, AuditMixin): is_hidden = Column(Boolean, default=False) description = Column(Text) default_endpoint = Column(Text) + user_id = Column(Integer, + ForeignKey('ab_user.id')) + owner = relationship('User', backref='datasources', foreign_keys=[user_id]) @property def metrics_combo(self): @@ -111,6 +115,7 @@ class Metric(Model): ForeignKey('datasources.datasource_name')) datasource = relationship('Datasource', backref='metrics') json = Column(Text) + description = Column(Text) @property def json_obj(self): @@ -132,6 +137,7 @@ class Column(Model, AuditMixin): max = Column(Boolean, default=False) min = Column(Boolean, default=False) filterable = Column(Boolean, default=False) + description = Column(Text) def __repr__(self): return self.column_name @@ -150,8 +156,6 @@ class Column(Model, AuditMixin): json=json.dumps({ 'type': 'count', 'name': 'count'}) )) - if self.datasource.datasource_name == 'platform' and self.column_name=='subject_id': - print((self.column_name, self.type, self.isnum)) if self.sum and self.isnum: mt = self.type.lower() + 'Sum' diff --git a/app/templates/appbuilder/baselayout.html b/app/templates/appbuilder/baselayout.html index 60b151f9b..c45c3a386 100644 --- a/app/templates/appbuilder/baselayout.html +++ b/app/templates/appbuilder/baselayout.html @@ -11,7 +11,7 @@ {% endblock %} -
+
{% block messages %} {% include 'appbuilder/flash.html' %} @@ -20,6 +20,10 @@ {% endblock %}
+
+ {% block content_fluid %} + {% endblock %} +
{% block footer %}