diff --git a/superset-frontend/src/components/ReportModal/index.tsx b/superset-frontend/src/components/ReportModal/index.tsx index 178e394125746..fc5469d17c174 100644 --- a/superset-frontend/src/components/ReportModal/index.tsx +++ b/superset-frontend/src/components/ReportModal/index.tsx @@ -71,6 +71,7 @@ export interface ReportObject { validator_type: string; working_timeout: number; creation_method: string; + force_screenshot: boolean; } interface ChartObject { @@ -227,6 +228,7 @@ const ReportModal: FunctionComponent = ({ active: true, report_format: currentReport?.report_format || defaultNotificationFormat, timezone: currentReport?.timezone, + force_screenshot: false, }; if (isEditMode) { diff --git a/superset-frontend/src/views/CRUD/alert/AlertReportModal.tsx b/superset-frontend/src/views/CRUD/alert/AlertReportModal.tsx index 5dfeeecfafc9f..506a2c9ebb665 100644 --- a/superset-frontend/src/views/CRUD/alert/AlertReportModal.tsx +++ b/superset-frontend/src/views/CRUD/alert/AlertReportModal.tsx @@ -154,6 +154,7 @@ const DEFAULT_ALERT = { sql: '', validator_config_json: {}, validator_type: '', + force_screenshot: true, grace_period: undefined, }; @@ -512,6 +513,7 @@ const AlertReportModal: FunctionComponent = ({ const data: any = { ...currentAlert, type: isReport ? 'Report' : 'Alert', + force_screenshot: isReport ? 'false' : 'true', validator_type: conditionNotNull ? 'not null' : 'operator', validator_config_json: conditionNotNull ? {} diff --git a/superset/migrations/versions/bb38f40aa3ff_add_force_screenshot_to_alerts_reports.py b/superset/migrations/versions/bb38f40aa3ff_add_force_screenshot_to_alerts_reports.py new file mode 100644 index 0000000000000..57913febdfab5 --- /dev/null +++ b/superset/migrations/versions/bb38f40aa3ff_add_force_screenshot_to_alerts_reports.py @@ -0,0 +1,61 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +"""Add force_screenshot to alerts/reports + +Revision ID: bb38f40aa3ff +Revises: abe27eaf93db +Create Date: 2021-12-10 19:25:29.802949 + +""" + +# revision identifiers, used by Alembic. +revision = "bb38f40aa3ff" +down_revision = "abe27eaf93db" + +import sqlalchemy as sa +from alembic import op +from sqlalchemy.ext.declarative import declarative_base + +from superset import db + +Base = declarative_base() + + +class ReportSchedule(Base): + __tablename__ = "report_schedule" + + id = sa.Column(sa.Integer, primary_key=True) + type = sa.Column(sa.String(50), nullable=False) + force_screenshot = sa.Column(sa.Boolean, default=False) + + +def upgrade(): + with op.batch_alter_table("report_schedule") as batch_op: + batch_op.add_column(sa.Column("force_screenshot", sa.Boolean(), default=False)) + + bind = op.get_bind() + session = db.Session(bind=bind) + + for report in session.query(ReportSchedule).all(): + report.force_screenshot = report.type == "Alert" + + session.commit() + + +def downgrade(): + with op.batch_alter_table("report_schedule") as batch_op: + batch_op.drop_column("force_screenshot") diff --git a/superset/models/reports.py b/superset/models/reports.py index a0dc59917a42c..1ecf698afd6e4 100644 --- a/superset/models/reports.py +++ b/superset/models/reports.py @@ -148,6 +148,10 @@ class ReportSchedule(Model, AuditMixinNullable): # Store the selected dashboard tabs etc. extra = Column(Text, default="{}") + # (Reports) When generating a screenshot, bypass the cache? This is always true for + # Alerts. + force_screenshot = Column(Boolean, default=False) + def __repr__(self) -> str: return str(self.name) diff --git a/superset/reports/commands/execute.py b/superset/reports/commands/execute.py index 2789bb20fbaa1..2574ed525c32e 100644 --- a/superset/reports/commands/execute.py +++ b/superset/reports/commands/execute.py @@ -148,13 +148,7 @@ def _get_url( """ # For alerts we always want to send a fresh screenshot, bypassing # the cache. - # TODO (betodealmeida): allow to specify per report if users want - # to bypass the cache as well. - force = ( - "true" - if self._report_schedule.type == ReportScheduleType.ALERT - else "false" - ) + force = "true" if self._report_schedule.force_screenshot else "false" if self._report_schedule.chart: if result_format in { diff --git a/superset/reports/schemas.py b/superset/reports/schemas.py index 3f2fb4416dbe0..f4c85484aa149 100644 --- a/superset/reports/schemas.py +++ b/superset/reports/schemas.py @@ -202,6 +202,7 @@ class ReportSchedulePostSchema(Schema): default=ReportDataFormat.VISUALIZATION, validate=validate.OneOf(choices=tuple(key.value for key in ReportDataFormat)), ) + force_screenshot = fields.Boolean(default=False) @validates_schema def validate_report_references( # pylint: disable=unused-argument,no-self-use @@ -292,3 +293,4 @@ class ReportSchedulePutSchema(Schema): default=ReportDataFormat.VISUALIZATION, validate=validate.OneOf(choices=tuple(key.value for key in ReportDataFormat)), ) + force_screenshot = fields.Boolean(default=False)