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/10/21 14:40:14 UTC
[airflow] branch main updated: Fix some bug in web ui dags list page (auto-refresh & jump search null state) (#27141)
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 ebd34cbd9f Fix some bug in web ui dags list page (auto-refresh & jump search null state) (#27141)
ebd34cbd9f is described below
commit ebd34cbd9f62d086bb39727d85fd58a0758edba3
Author: Bob Du <i...@bobdu.cc>
AuthorDate: Fri Oct 21 22:39:59 2022 +0800
Fix some bug in web ui dags list page (auto-refresh & jump search null state) (#27141)
* Fix some bug in web ui dags list page
Signed-off-by: BobDu <i...@bobdu.cc>
* use switch case & fix remove loading dot
Signed-off-by: BobDu <i...@bobdu.cc>
* rename drawDagStats & selectors constants
Signed-off-by: BobDu <i...@bobdu.cc>
* Further clean up of duplicate code
Signed-off-by: BobDu <i...@bobdu.cc>
Signed-off-by: BobDu <i...@bobdu.cc>
---
airflow/www/static/js/dags.js | 145 ++++++++------------------------
airflow/www/templates/airflow/dags.html | 6 +-
2 files changed, 37 insertions(+), 114 deletions(-)
diff --git a/airflow/www/static/js/dags.js b/airflow/www/static/js/dags.js
index 3acd8a4742..5872f8f27f 100644
--- a/airflow/www/static/js/dags.js
+++ b/airflow/www/static/js/dags.js
@@ -44,6 +44,9 @@ const datasetsUrl = getMetaValue('datasets_url');
const nextDatasets = {};
let nextDatasetsError;
+const DAG_RUN = 'dag-run';
+const TASK_INSTANCE = 'task-instance';
+
// auto refresh interval in milliseconds
// (x2 the interval in tree/graph view since this page can take longer to refresh )
const refreshIntervalMs = 2000;
@@ -189,10 +192,10 @@ d3.selectAll('.js-last-run-tooltip')
d3.select(this).attr('data-original-title', tiTooltip(lastRunData));
});
-function drawDagStatsForDag(dagId, states) {
- const g = d3.select(`svg#dag-run-${dagId.replace(/\./g, '__dot__')}`)
+function drawDagStats(selector, dagId, states) {
+ const g = d3.select(`svg#${selector}-${dagId.replace(/\./g, '__dot__')}`)
.attr('height', diameter + (strokeWidthHover * 2))
- .attr('width', '120px')
+ .attr('width', (states.length * (diameter + circleMargin)) + circleMargin)
.selectAll('g')
.data(states)
.enter()
@@ -204,103 +207,41 @@ function drawDagStatsForDag(dagId, states) {
});
g.append('svg:a')
- .attr('href', (d) => `${dagRunUrl}?_flt_3_dag_id=${dagId}&_flt_3_state=${d.state}`)
- .append('circle')
- .attr('id', (d) => `run-${dagId.replace(/\./g, '_')}${d.state || 'none'}`)
- .attr('class', 'has-svg-tooltip')
- .attr('stroke-width', (d) => {
- if (d.count > 0) return strokeWidth;
-
- return 1;
- })
- .attr('stroke', (d) => {
- if (d.count > 0) return STATE_COLOR[d.state];
-
- return 'gainsboro';
- })
- .attr('fill', '#fff')
- .attr('r', diameter / 2)
- .attr('title', (d) => d.state)
- .on('mouseover', (d) => {
- if (d.count > 0) {
- d3.select(this).transition().duration(400)
- .attr('fill', '#e2e2e2')
- .style('stroke-width', strokeWidthHover);
+ .attr('href', (d) => {
+ const params = new URLSearchParams();
+ params.append('_flt_3_dag_id', dagId);
+ /* eslint no-unused-expressions: ["error", { "allowTernary": true }] */
+ d.state ? params.append('_flt_3_state', d.state) : params.append('_flt_8_state', '');
+ switch (selector) {
+ case DAG_RUN: return `${dagRunUrl}?${params.toString()}`;
+ case TASK_INSTANCE: return `${taskInstanceUrl}?${params.toString()}`;
+ default: return '';
}
})
- .on('mouseout', (d) => {
- if (d.count > 0) {
- d3.select(this).transition().duration(400)
- .attr('fill', '#fff')
- .style('stroke-width', strokeWidth);
- }
- })
- .style('opacity', 0)
- .transition()
- .duration(300)
- .delay((d, i) => i * 50)
- .style('opacity', 1);
- d3.select('.js-loading-dag-stats').remove();
-
- g.append('text')
- .attr('fill', '#51504f')
- .attr('text-anchor', 'middle')
- .attr('vertical-align', 'middle')
- .attr('font-size', 9)
- .attr('y', 3)
- .style('pointer-events', 'none')
- .text((d) => (d.count > 0 ? d.count : ''));
-}
-
-function dagStatsHandler(error, json) {
- Object.keys(json).forEach((dagId) => {
- const states = json[dagId];
- drawDagStatsForDag(dagId, states);
- });
-}
-
-function drawTaskStatsForDag(dagId, states) {
- const g = d3.select(`svg#task-run-${dagId.replace(/\./g, '__dot__')}`)
- .attr('height', diameter + (strokeWidthHover * 2))
- .attr('width', (states.length * (diameter + circleMargin)) + circleMargin)
- .selectAll('g')
- .data(states)
- .enter()
- .append('g')
- .attr('transform', (d, i) => {
- const x = (i * (diameter + circleMargin)) + (diameter / 2 + circleMargin);
- const y = (diameter / 2) + strokeWidthHover;
- return `translate(${x},${y})`;
- });
-
- g.append('svg:a')
- .attr('href', (d) => `${taskInstanceUrl}?_flt_3_dag_id=${dagId}&_flt_3_state=${d.state}`)
.append('circle')
- .attr('id', (d) => `task-${dagId.replace(/\./g, '_')}${d.state || 'none'}`)
+ .attr('id', (d) => `${selector}-${dagId.replace(/\./g, '_')}-${d.state || 'none'}`)
.attr('class', 'has-svg-tooltip')
.attr('stroke-width', (d) => {
if (d.count > 0) return strokeWidth;
-
return 1;
})
.attr('stroke', (d) => {
if (d.count > 0) return STATE_COLOR[d.state];
-
return 'gainsboro';
})
.attr('fill', '#fff')
.attr('r', diameter / 2)
.attr('title', (d) => d.state || 'none')
- .on('mouseover', function mouseOver(d) {
+ .on('mouseover', (d) => {
if (d.count > 0) {
- d3.select(this).transition().duration(400)
+ d3.select(d3.event.currentTarget).transition().duration(400)
.attr('fill', '#e2e2e2')
.style('stroke-width', strokeWidthHover);
}
})
- .on('mouseout', function mouseOut(d) {
+ .on('mouseout', (d) => {
if (d.count > 0) {
- d3.select(this).transition().duration(400)
+ d3.select(d3.event.currentTarget).transition().duration(400)
.attr('fill', '#fff')
.style('stroke-width', strokeWidth);
}
@@ -311,7 +252,7 @@ function drawTaskStatsForDag(dagId, states) {
.delay((d, i) => i * 50)
.style('opacity', 1);
- d3.select('.js-loading-task-stats').remove();
+ d3.select(`.js-loading-${selector}-stats`).remove();
g.append('text')
.attr('fill', '#51504f')
@@ -323,10 +264,10 @@ function drawTaskStatsForDag(dagId, states) {
.text((d) => (d.count > 0 ? d.count : ''));
}
-function taskStatsHandler(error, json) {
+function dagStatsHandler(selector, json) {
Object.keys(json).forEach((dagId) => {
const states = json[dagId];
- drawTaskStatsForDag(dagId, states);
+ drawDagStats(selector, dagId, states);
});
}
@@ -356,14 +297,14 @@ function getDagStats() {
.post(params, lastDagRunsHandler);
d3.json(dagStatsUrl)
.header('X-CSRFToken', csrfToken)
- .post(params, dagStatsHandler);
+ .post(params, (error, json) => dagStatsHandler(DAG_RUN, json));
d3.json(taskStatsUrl)
.header('X-CSRFToken', csrfToken)
- .post(params, taskStatsHandler);
+ .post(params, (error, json) => dagStatsHandler(TASK_INSTANCE, json));
} else {
// no dags, hide the loading dots
- $('.js-loading-task-stats').remove();
- $('.js-loading-dag-stats').remove();
+ $(`.js-loading-${DAG_RUN}-stats`).remove();
+ $(`.js-loading-${TASK_INSTANCE}-stats`).remove();
}
}
@@ -382,7 +323,7 @@ function hideSvgTooltip() {
$('#svg-tooltip').css('display', 'none');
}
-function refreshDagRunsAndTasks(selector, dagId, states) {
+function refreshDagStats(selector, dagId, states) {
d3.select(`svg#${selector}-${dagId.replace(/\./g, '__dot__')}`)
.selectAll('circle')
.data(states)
@@ -392,19 +333,9 @@ function refreshDagRunsAndTasks(selector, dagId, states) {
})
.attr('stroke', (d) => {
if (d.count > 0) return STATE_COLOR[d.state];
-
return 'gainsboro';
- })
- .attr('fill', '#fff')
- .attr('r', diameter / 2)
- .attr('title', (d) => d.state)
- .on('mouseover', (d) => {
- if (d.count > 0) {
- d3.select(this).transition().duration(400)
- .attr('fill', '#e2e2e2')
- .style('stroke-width', strokeWidthHover);
- }
});
+
d3.select(`svg#${selector}-${dagId.replace(/\./g, '__dot__')}`)
.selectAll('text')
.data(states)
@@ -416,13 +347,6 @@ function refreshDagRunsAndTasks(selector, dagId, states) {
});
}
-function refreshTaskStateHandler(error, ts) {
- Object.keys(ts).forEach((dagId) => {
- const states = ts[dagId];
- refreshDagRunsAndTasks('task-run', dagId, states);
- });
-}
-
let refreshInterval;
function checkActiveRuns(json) {
@@ -438,12 +362,11 @@ function checkActiveRuns(json) {
}
}
-function refreshDagRuns(error, json) {
- checkActiveRuns(json);
+function refreshDagStatsHandler(selector, json) {
+ if (selector === DAG_RUN) checkActiveRuns(json);
Object.keys(json).forEach((dagId) => {
const states = json[dagId];
- drawDagStatsForDag(dagId, states);
- refreshDagRunsAndTasks('dag-run', dagId, states);
+ refreshDagStats(selector, dagId, states);
});
}
@@ -460,10 +383,10 @@ function handleRefresh({ activeDagsOnly = false } = {}) {
.post(params, lastDagRunsHandler);
d3.json(dagStatsUrl)
.header('X-CSRFToken', csrfToken)
- .post(params, refreshDagRuns);
+ .post(params, (error, json) => refreshDagStatsHandler(DAG_RUN, json));
d3.json(taskStatsUrl)
.header('X-CSRFToken', csrfToken)
- .post(params, refreshTaskStateHandler);
+ .post(params, (error, json) => refreshDagStatsHandler(TASK_INSTANCE, json));
}
setTimeout(() => {
$('#loading-dots').css('display', 'none');
diff --git a/airflow/www/templates/airflow/dags.html b/airflow/www/templates/airflow/dags.html
index 4639c17ace..72c875330e 100644
--- a/airflow/www/templates/airflow/dags.html
+++ b/airflow/www/templates/airflow/dags.html
@@ -268,7 +268,7 @@
{% endfor %}
</td>
<td style="padding:0; width:130px;">
- {{ loading_dots(classes='js-loading-dag-stats text-muted') }}
+ {{ loading_dots(classes='js-loading-dag-run-stats text-muted') }}
<svg height="10" width="10" id="dag-run-{{ dag.safe_dag_id }}" style="display: block;"></svg>
</td>
<td>
@@ -342,8 +342,8 @@
{% endif %}
</td>
<td style="padding:0; width:323px; height:10px;">
- {{ loading_dots(classes='js-loading-task-stats text-muted') }}
- <svg height="10" width="10" id='task-run-{{ dag.safe_dag_id }}' style="display: block;"></svg>
+ {{ loading_dots(classes='js-loading-task-instance-stats text-muted') }}
+ <svg height="10" width="10" id='task-instance-{{ dag.safe_dag_id }}' style="display: block;"></svg>
</td>
<td class="text-center">
<div class="btn-group">