diff --git a/panoramix/migrations/versions/2929af7925ed_tz_offsets_in_data_sources.py b/panoramix/migrations/versions/2929af7925ed_tz_offsets_in_data_sources.py new file mode 100644 index 000000000..784657753 --- /dev/null +++ b/panoramix/migrations/versions/2929af7925ed_tz_offsets_in_data_sources.py @@ -0,0 +1,24 @@ +"""TZ offsets in data sources + +Revision ID: 2929af7925ed +Revises: 1e2841a4128 +Create Date: 2015-10-19 20:54:00.565633 + +""" + +# revision identifiers, used by Alembic. +revision = '2929af7925ed' +down_revision = '1e2841a4128' + +from alembic import op +import sqlalchemy as sa +from sqlalchemy.dialects import mysql + +def upgrade(): + op.add_column('datasources', sa.Column('offset', sa.Integer(), nullable=True)) + op.add_column('tables', sa.Column('offset', sa.Integer(), nullable=True)) + + +def downgrade(): + op.drop_column('tables', 'offset') + op.drop_column('datasources', 'offset') diff --git a/panoramix/models.py b/panoramix/models.py index cf5f82b44..7cd97295e 100644 --- a/panoramix/models.py +++ b/panoramix/models.py @@ -11,9 +11,8 @@ from sqlalchemy import ( from sqlalchemy import Table from sqlalchemy import create_engine, MetaData, desc, select, and_ from sqlalchemy.orm import relationship -from sqlalchemy.sql import table, literal_column, text, column +from sqlalchemy.sql import table, literal_column, text from sqlalchemy.sql.elements import ColumnClause -from flask import request from copy import deepcopy, copy from collections import namedtuple @@ -201,7 +200,7 @@ class Database(Model, AuditMixinNullable): autoload_with=self.get_sqla_engine()) -class SqlaTable(Model, Queryable, AuditMixinNullable): +class SqlaTable(Model, Queryable): type = "table" __tablename__ = 'tables' @@ -212,6 +211,7 @@ class SqlaTable(Model, Queryable, AuditMixinNullable): database_id = Column(Integer, ForeignKey('dbs.id'), nullable=False) database = relationship( 'Database', backref='tables', foreign_keys=[database_id]) + offset = Column(Integer, default=0) baselink = "tableview" @@ -655,6 +655,7 @@ class Datasource(Model, AuditMixin, Queryable): String(250), ForeignKey('clusters.cluster_name')) cluster = relationship( 'Cluster', backref='datasources', foreign_keys=[cluster_name]) + offset = Column(Integer, default=0) @property def metrics_combo(self): diff --git a/panoramix/views.py b/panoramix/views.py index 9a36c1cd1..da5dbc330 100644 --- a/panoramix/views.py +++ b/panoramix/views.py @@ -126,10 +126,14 @@ appbuilder.add_view( class TableView(PanoramixModelView, DeleteMixin): datamodel = SQLAInterface(models.SqlaTable) list_columns = ['table_link', 'database'] - add_columns = ['table_name', 'database', 'default_endpoint'] + add_columns = ['table_name', 'database', 'default_endpoint', 'offset'] edit_columns = [ - 'table_name', 'database', 'main_dttm_col', 'default_endpoint'] + 'table_name', 'database', 'main_dttm_col', 'default_endpoint', + 'offset'] related_views = [TableColumnInlineView, SqlMetricInlineView] + description_columns = { + 'offset': "Timezone offset (in hours) for this datasource" + } def post_add(self, table): try: @@ -219,13 +223,17 @@ appbuilder.add_view( class DatasourceModelView(PanoramixModelView, DeleteMixin): datamodel = SQLAInterface(models.Datasource) list_columns = [ - 'datasource_link', 'cluster', 'owner', 'is_featured', 'is_hidden'] + 'datasource_link', 'cluster', 'owner', 'is_featured', 'is_hidden', + 'offset'] related_views = [ColumnInlineView, MetricInlineView] edit_columns = [ 'datasource_name', 'cluster', 'description', 'owner', - 'is_featured', 'is_hidden', 'default_endpoint'] + 'is_featured', 'is_hidden', 'default_endpoint', 'offset'] page_size = 100 base_order = ('datasource_name', 'asc') + description_columns = { + 'offset': "Timezone offset (in hours) for this datasource" + } def post_add(self, datasource): datasource.generate_metrics() diff --git a/panoramix/viz.py b/panoramix/viz.py index 4c766f654..d45a40097 100644 --- a/panoramix/viz.py +++ b/panoramix/viz.py @@ -1,6 +1,5 @@ from collections import OrderedDict, defaultdict -from copy import copy -from datetime import datetime +from datetime import datetime, timedelta import json import uuid @@ -110,6 +109,8 @@ class BaseViz(object): else: if 'timestamp' in df.columns: df.timestamp = pd.to_datetime(df.timestamp) + if self.datasource.offset: + df.timestamp += timedelta(hours=self.datasource.offset) return df @property