diff --git a/caravel/assets/javascripts/dashboard/Dashboard.jsx b/caravel/assets/javascripts/dashboard/Dashboard.jsx index 15bdfbf8f5db7..2507e21ecbec5 100644 --- a/caravel/assets/javascripts/dashboard/Dashboard.jsx +++ b/caravel/assets/javascripts/dashboard/Dashboard.jsx @@ -45,7 +45,6 @@ function dashboardContainer(dashboardData) { filters: {}, init() { this.initDashboardView(); - this.firstLoad = true; px.initFavStars(); const sliceObjects = []; const dash = this; @@ -64,7 +63,7 @@ function dashboardContainer(dashboardData) { this.slices = sliceObjects; this.refreshTimer = null; this.loadPreSelectFilters(); - this.startPeriodicRender(0); + this.startPeriodicRender(); this.bindResizeToWindowResize(); }, loadPreSelectFilters() { @@ -131,14 +130,12 @@ function dashboardContainer(dashboardData) { 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 () { @@ -149,7 +146,9 @@ function dashboardContainer(dashboardData) { }, interval); } }; - fetchAndRender(); + if (interval > 0){ + fetchAndRender(); + } }, refreshExcept(sliceId) { const immune = this.metadata.filter_immune_slices || []; @@ -244,6 +243,8 @@ function dashboardContainer(dashboardData) { positions, css: this.editor.getValue(), expanded_slices: expandedSlices, + autorefresh_seconds: dashboard.autorefresh_seconds, + autorefresh_from_cache: dashboard.autorefresh_from_cache }; $.ajax({ type: 'POST', @@ -323,9 +324,10 @@ function dashboardContainer(dashboardData) { dashboard.readFilters(), }); }); - $('#refresh_dash_interval').on('change', function () { - const interval = $(this).find('option:selected').val() * 1000; - dashboard.startPeriodicRender(interval); + $("#refresh_dash_apply").click(function () { + dashboard.autorefresh_seconds = $("#refresh_dash_interval").val(); + dashboard.autorefresh_from_cache = $("#refresh_dach_from_cache").is(':checked'); + dashboard.startPeriodicRender(); }); $('#refresh_dash').click(() => { dashboard.slices.forEach((slice) => { diff --git a/caravel/migrations/versions/27ae655e4247_make_creator_owners.py b/caravel/migrations/versions/27ae655e4247_make_creator_owners.py index 71c627305dbc7..c4add0eec9835 100644 --- a/caravel/migrations/versions/27ae655e4247_make_creator_owners.py +++ b/caravel/migrations/versions/27ae655e4247_make_creator_owners.py @@ -11,18 +11,67 @@ down_revision = 'd8bc074f7aad' from alembic import op -from caravel import db, models +from caravel import db + +from sqlalchemy.ext.declarative import declarative_base +from sqlalchemy.orm import relationship +from sqlalchemy import ( + Column, Integer, ForeignKey, Table) + +Base = declarative_base() + +slice_user = Table( + 'slice_user', Base.metadata, + Column('id', Integer, primary_key=True), + Column('user_id', Integer, ForeignKey('ab_user.id')), + Column('slice_id', Integer, ForeignKey('slices.id')) +) + +dashboard_user = Table( + 'dashboard_user', Base.metadata, + Column('id', Integer, primary_key=True), + Column('user_id', Integer, ForeignKey('ab_user.id')), + Column('dashboard_id', Integer, ForeignKey('dashboards.id')) +) + + +class User(Base): + + """Declarative class to do query in upgrade""" + + __tablename__ = 'ab_user' + id = Column(Integer, primary_key=True) + + +class Slice(Base): + + """Declarative class to do query in upgrade""" + + __tablename__ = 'slices' + id = Column(Integer, primary_key=True) + owners = relationship("User", secondary=slice_user) + created_by_fk = Column(Integer) + + +class Dashboard(Base): + + """Declarative class to do query in upgrade""" + + __tablename__ = 'dashboards' + id = Column(Integer, primary_key=True) + owners = relationship("User", secondary=dashboard_user) + created_by_fk = Column(Integer) def upgrade(): bind = op.get_bind() session = db.Session(bind=bind) - objects = session.query(models.Slice).all() - objects += session.query(models.Dashboard).all() + objects = session.query(Slice).all() + objects += session.query(Dashboard).all() for obj in objects: - if obj.created_by and obj.created_by not in obj.owners: - obj.owners.append(obj.created_by) + if obj.created_by_fk and obj.created_by_fk not in obj.owners: + obj.owners.append(obj.created_by_fk) session.commit() session.close() diff --git a/caravel/migrations/versions/79aef3baedae_adding_columns_for_dashboard_refresh_.py b/caravel/migrations/versions/79aef3baedae_adding_columns_for_dashboard_refresh_.py new file mode 100644 index 0000000000000..bb35bc83aaccd --- /dev/null +++ b/caravel/migrations/versions/79aef3baedae_adding_columns_for_dashboard_refresh_.py @@ -0,0 +1,29 @@ +"""Adding Columns for Dashboard Refresh Properties + +Revision ID: 79aef3baedae +Revises: f162a1dea4c4 +Create Date: 2016-07-02 14:51:00.106192 + +""" + +# revision identifiers, used by Alembic. +revision = '79aef3baedae' +down_revision = 'f162a1dea4c4' + +from alembic import op +import sqlalchemy as sa + + +def upgrade(): + try: + op.add_column('dashboards', sa.Column('autorefresh_from_cache', sa.Boolean(), nullable=False, server_default='True')) + except: + # To pick up databases (like some MySQL variants) without a true Boolean value + op.add_column('dashboards', sa.Column('autorefresh_from_cache', sa.Boolean(), nullable=False, server_default='1')) + + op.add_column('dashboards', sa.Column('autorefresh_seconds', sa.Integer(), nullable=False, server_default='0')) + + +def downgrade(): + op.drop_column('dashboards', 'autorefresh_seconds') + op.drop_column('dashboards', 'autorefresh_from_cache') diff --git a/caravel/models.py b/caravel/models.py index 444a4da6b7e13..8a8e909ee040a 100644 --- a/caravel/models.py +++ b/caravel/models.py @@ -291,6 +291,9 @@ class Dashboard(Model, AuditMixinNullable): slices = relationship( 'Slice', secondary=dashboard_slices, backref='dashboards') owners = relationship("User", secondary=dashboard_user) + # A zero for autorefresh seconds implies no autorefresh + autorefresh_seconds = Column(Integer, default=0, nullable=False) + autorefresh_from_cache = Column(Boolean, default=True, nullable=False) def __repr__(self): return self.dashboard_title @@ -315,6 +318,7 @@ def dashboard_link(self): @property def json_data(self): + """Returns the configuration data for the dashboard as json""" d = { 'id': self.id, 'metadata': self.metadata_dejson, @@ -322,6 +326,8 @@ def json_data(self): 'slug': self.slug, 'slices': [slc.data for slc in self.slices], 'position_json': json.loads(self.position_json) if self.position_json else [], + 'autorefresh_seconds': self.autorefresh_seconds, + 'autorefresh_from_cache': self.autorefresh_from_cache, } return json.dumps(d) diff --git a/caravel/templates/caravel/dashboard.html b/caravel/templates/caravel/dashboard.html index afdf144114d8d..28b49e17c048a 100644 --- a/caravel/templates/caravel/dashboard.html +++ b/caravel/templates/caravel/dashboard.html @@ -44,21 +44,22 @@