You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@airflow.apache.org by bb...@apache.org on 2022/08/17 14:54:53 UTC

[airflow] branch main updated: Next run datasets tooltip preview (#25694)

This is an automated email from the ASF dual-hosted git repository.

bbovenzi pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/airflow.git


The following commit(s) were added to refs/heads/main by this push:
     new aac2b1f6b7 Next run datasets tooltip preview (#25694)
aac2b1f6b7 is described below

commit aac2b1f6b73f443e3cd8454e53d5e474396cbd64
Author: Brent Bovenzi <br...@gmail.com>
AuthorDate: Wed Aug 17 15:54:45 2022 +0100

    Next run datasets tooltip preview (#25694)
    
    * create dataset triggered preview tooltip
    
    * share datasets data btwn tooltip+modal
    
    * add backup tooltip message
---
 airflow/www/static/js/dag.js                       | 25 ++++++---
 airflow/www/static/js/dags.js                      | 19 ++++++-
 .../js/{openDatasetModal.js => datasetUtils.js}    | 65 ++++++++++++++--------
 airflow/www/templates/airflow/dag.html             |  5 +-
 airflow/www/templates/airflow/dags.html            |  6 +-
 5 files changed, 83 insertions(+), 37 deletions(-)

diff --git a/airflow/www/static/js/dag.js b/airflow/www/static/js/dag.js
index d4e5dc2255..8bf69aa67f 100644
--- a/airflow/www/static/js/dag.js
+++ b/airflow/www/static/js/dag.js
@@ -21,7 +21,7 @@
 
 import { getMetaValue } from './utils';
 import { approxTimeFromNow, formatDateTime } from './datetime_utils';
-import openDatasetModal from './openDatasetModal';
+import { openDatasetModal, getDatasetTooltipInfo } from './datasetUtils';
 
 function updateQueryStringParameter(uri, key, value) {
   const re = new RegExp(`([?&])${key}=.*?(&|$)`, 'i');
@@ -33,12 +33,6 @@ function updateQueryStringParameter(uri, key, value) {
   return `${uri}${separator}${key}=${value}`;
 }
 
-// Pills highlighting
-$(window).on('load', function onLoad() {
-  $(`a[href*="${this.location.pathname}"]`).parent().addClass('active');
-  $('.never_active').removeClass('active');
-});
-
 const dagId = getMetaValue('dag_id');
 export const dagTZ = getMetaValue('dag_timezone');
 const logsWithMetadataUrl = getMetaValue('logs_with_metadata_url');
@@ -58,6 +52,21 @@ let mapIndex;
 let mapStates = [];
 let extraLinks;
 const showExternalLogRedirect = getMetaValue('show_external_log_redirect') === 'True';
+let nextDatasets = [];
+let nextDatasetsError;
+
+const setNextDatasets = (datasets, error) => {
+  nextDatasets = datasets;
+  nextDatasetsError = error;
+};
+
+// Pills highlighting
+$(window).on('load', function onLoad() {
+  $(`a[href*="${this.location.pathname}"]`).parent().addClass('active');
+  $('.never_active').removeClass('active');
+  const run = $('#next-dataset-tooltip');
+  getDatasetTooltipInfo(dagId, run, setNextDatasets);
+});
 
 const buttons = Array.from(document.querySelectorAll('a[id^="btn_"][data-base-url]')).reduce((obj, elm) => {
   obj[elm.id.replace('btn_', '')] = elm;
@@ -403,5 +412,5 @@ $('#next-run').on('mouseover', () => {
 
 $('.next-dataset-triggered').on('click', (e) => {
   const summary = $(e.target).data('summary');
-  openDatasetModal(dagId, summary || '');
+  openDatasetModal(dagId, summary, nextDatasets, nextDatasetsError);
 });
diff --git a/airflow/www/static/js/dags.js b/airflow/www/static/js/dags.js
index 85b5e435e7..db8f19b203 100644
--- a/airflow/www/static/js/dags.js
+++ b/airflow/www/static/js/dags.js
@@ -23,7 +23,7 @@
 import { getMetaValue } from './utils';
 import tiTooltip from './task_instances';
 import { approxTimeFromNow, formatDateTime } from './datetime_utils';
-import openDatasetModal from './openDatasetModal';
+import { openDatasetModal, getDatasetTooltipInfo } from './datasetUtils';
 
 const DAGS_INDEX = getMetaValue('dags_index');
 const ENTER_KEY_CODE = 13;
@@ -40,6 +40,9 @@ const dagStatsUrl = getMetaValue('dag_stats_url');
 const taskStatsUrl = getMetaValue('task_stats_url');
 const gridUrl = getMetaValue('grid_url');
 
+const nextDatasets = {};
+let nextDatasetsError;
+
 // auto refresh interval in milliseconds
 // (x2 the interval in tree/graph view since this page can take longer to refresh )
 const refreshIntervalMs = 2000;
@@ -542,5 +545,17 @@ $('#auto_refresh').change(() => {
 $('.next-dataset-triggered').on('click', (e) => {
   const dagId = $(e.target).data('dag-id');
   const summary = $(e.target).data('summary');
-  if (dagId) openDatasetModal(dagId, summary || '');
+  if (dagId) openDatasetModal(dagId, summary, nextDatasets[dagId], nextDatasetsError);
+});
+
+$('.js-dataset-triggered').each((i, cell) => {
+  $(cell).on('mouseover', () => {
+    const run = $(cell).children();
+    const dagId = $(run).data('dag-id');
+    const setNextDatasets = (datasets, error) => {
+      nextDatasets[dagId] = datasets;
+      nextDatasetsError = error;
+    };
+    getDatasetTooltipInfo(dagId, run, setNextDatasets);
+  });
 });
diff --git a/airflow/www/static/js/openDatasetModal.js b/airflow/www/static/js/datasetUtils.js
similarity index 54%
rename from airflow/www/static/js/openDatasetModal.js
rename to airflow/www/static/js/datasetUtils.js
index 6e6c824e1d..82e9771ae4 100644
--- a/airflow/www/static/js/openDatasetModal.js
+++ b/airflow/www/static/js/datasetUtils.js
@@ -21,15 +21,38 @@
 
 import { getMetaValue } from './utils';
 
-function openDatasetModal(dagId, summary) {
+export function openDatasetModal(dagId, summary = '', nextDatasets = [], error = null) {
   const datasetsUrl = getMetaValue('datasets_url');
-  let nextRunUrl = getMetaValue('next_run_datasets_url');
   $('#datasets_tbody').empty();
   $('#datasets_error').hide();
-  $('#datasetNextRunModal').modal({});
   $('#dag_id').text(dagId);
+  $('#datasetNextRunModal').modal({});
   $('#next_run_summary').text(summary);
-  $('#datasets-loading-dots').css('display', 'inline-block');
+  nextDatasets.forEach((d) => {
+    const row = document.createElement('tr');
+
+    const uriCell = document.createElement('td');
+    const datasetLink = document.createElement('a');
+    datasetLink.href = `${datasetsUrl}?dataset_id=${d.id}`;
+    datasetLink.innerText = d.uri;
+    uriCell.append(datasetLink);
+
+    const timeCell = document.createElement('td');
+    if (d.created_at) timeCell.append(isoDateToTimeEl(d.created_at));
+
+    row.append(uriCell);
+    row.append(timeCell);
+    $('#datasets_tbody').append(row);
+  });
+
+  if (error) {
+    $('#datasets_error_msg').text(error);
+    $('#datasets_error').show();
+  }
+}
+
+export function getDatasetTooltipInfo(dagId, run, setNextDatasets) {
+  let nextRunUrl = getMetaValue('next_run_datasets_url');
   if (dagId) {
     if (nextRunUrl.includes('__DAG_ID__')) {
       nextRunUrl = nextRunUrl.replace('__DAG_ID__', dagId);
@@ -37,31 +60,25 @@ function openDatasetModal(dagId, summary) {
     $.get(nextRunUrl)
       .done(
         (datasets) => {
+          let count = 0;
+          let title = '<strong>Pending datasets:</strong><br>';
+          setNextDatasets(datasets);
           datasets.forEach((d) => {
-            const row = document.createElement('tr');
-
-            const uriCell = document.createElement('td');
-            const datasetLink = document.createElement('a');
-            datasetLink.href = `${datasetsUrl}?dataset_id=${d.id}`;
-            datasetLink.innerText = d.uri;
-            uriCell.append(datasetLink);
-
-            const timeCell = document.createElement('td');
-            if (d.created_at) timeCell.append(isoDateToTimeEl(d.created_at));
-
-            row.append(uriCell);
-            row.append(timeCell);
-            $('#datasets-loading-dots').hide();
-            $('#datasets_tbody').append(row);
+            if (!d.created_at) {
+              if (count < 4) title += `${d.uri}<br>`;
+              count += 1;
+            }
           });
+          if (count > 4) {
+            title += `<br>And ${count - 4} more.`;
+          }
+          title += '<br>Click to see more details.';
+          $(run).attr('data-original-title', () => title);
         },
       ).fail((response, textStatus, err) => {
-        $('#datasets-loading-dots').hide();
         const description = (response.responseJSON && response.responseJSON.error) || 'Something went wrong.';
-        $('#datasets_error_msg').text(`${textStatus}: ${err} ${description}`);
-        $('#datasets_error').show();
+        const error = `${textStatus}: ${err} ${description}`;
+        setNextDatasets([], error);
       });
   }
 }
-
-export default openDatasetModal;
diff --git a/airflow/www/templates/airflow/dag.html b/airflow/www/templates/airflow/dag.html
index 848a9b8413..d55c5506f4 100644
--- a/airflow/www/templates/airflow/dag.html
+++ b/airflow/www/templates/airflow/dag.html
@@ -122,7 +122,7 @@
         <span class="text-muted">ROOT:</span> {{ root }}
       {% endif %}
     </h3>
-    <h4 class="pull-right" style="user-select: none;-moz-user-select: auto;">
+    <h4 class="pull-right js-dataset-triggered" style="user-select: none;-moz-user-select: auto;">
       {% if state_token is defined and state_token %}
         {{ state_token }}
       {% endif %}
@@ -139,8 +139,11 @@
       {% endif %}
       {% if dag_model is defined and dag_model.schedule_interval is defined and dag_model.schedule_interval == 'Dataset' %}
         <span
+          id="next-dataset-tooltip"
           class="js-tooltip"
           title="Click to see dataset details."
+          data-html="true"
+          data-placement="bottom"
         >
           <p
             class="label label-default next-dataset-triggered"
diff --git a/airflow/www/templates/airflow/dags.html b/airflow/www/templates/airflow/dags.html
index 92132ab517..0884a06c17 100644
--- a/airflow/www/templates/airflow/dags.html
+++ b/airflow/www/templates/airflow/dags.html
@@ -295,11 +295,13 @@
                     info
                   </span>
             </td>
-            <td class="text-nowrap">
+            <td class="text-nowrap {{ 'js-dataset-triggered' if dag.dag_id in dataset_triggered_next_run_info }}">
               {% if dag.dag_id in dataset_triggered_next_run_info %}
                 <span
-                  class="js-tooltip"
+                  data-dag-id="{{ dag.dag_id }}"
+                  class="js-tooltip js-next-dataset-run-tooltip"
                   title="Click to see dataset details."
+                  data-html="true"
                 >
                   <div
                     class="label label-default next-dataset-triggered"