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/03/08 20:57:19 UTC
[airflow] 10/11: dag run actions
This is an automated email from the ASF dual-hosted git repository.
bbovenzi pushed a commit to branch mapped-task-drawer
in repository https://gitbox.apache.org/repos/asf/airflow.git
commit d86f6984393a45b74324943f04f47e8b808f61e2
Author: Brent Bovenzi <br...@gmail.com>
AuthorDate: Tue Mar 8 13:40:23 2022 -0500
dag run actions
---
airflow/www/static/js/tree/Tree.jsx | 12 +-
airflow/www/static/js/tree/api/index.js | 1 -
airflow/www/static/js/tree/api/useDag.js | 2 +-
airflow/www/static/js/tree/api/useTasks.js | 2 +-
.../www/static/js/tree/details/content/DagRun.jsx | 204 ++++++++++++++-------
airflow/www/templates/airflow/dag.html | 1 +
6 files changed, 148 insertions(+), 74 deletions(-)
diff --git a/airflow/www/static/js/tree/Tree.jsx b/airflow/www/static/js/tree/Tree.jsx
index 0d84639..b777d73 100644
--- a/airflow/www/static/js/tree/Tree.jsx
+++ b/airflow/www/static/js/tree/Tree.jsx
@@ -53,8 +53,12 @@ const Tree = () => {
const { isOpen, onToggle } = useDisclosure({ defaultIsOpen: isPanelOpen });
const toggleSidePanel = () => {
- if (!isOpen) localStorage.setItem(sidePanelKey, true);
- else localStorage.setItem(sidePanelKey, false);
+ if (!isOpen) {
+ localStorage.setItem(sidePanelKey, true);
+ } else {
+ setSelected({});
+ localStorage.setItem(sidePanelKey, false);
+ }
onToggle();
};
@@ -123,8 +127,8 @@ const Tree = () => {
pb="12px"
overflowX="auto"
ref={scrollRef}
- maxWidth={isOpen && '300px'}
- minWidth={isOpen && '300px'}
+ flexGrow={1}
+ width={isOpen && '300px'}
>
<Table height={0}>
<Thead>
diff --git a/airflow/www/static/js/tree/api/index.js b/airflow/www/static/js/tree/api/index.js
index 58edd88..3327fef 100644
--- a/airflow/www/static/js/tree/api/index.js
+++ b/airflow/www/static/js/tree/api/index.js
@@ -23,7 +23,6 @@ import camelcaseKeys from 'camelcase-keys';
import useDag from './useDag';
import useTasks from './useTasks';
-axios.defaults.baseURL = '/api/v1';
axios.interceptors.response.use(
(res) => (res.data ? camelcaseKeys(res.data, { deep: true }) : res),
);
diff --git a/airflow/www/static/js/tree/api/useDag.js b/airflow/www/static/js/tree/api/useDag.js
index 1343302..143bbe0 100644
--- a/airflow/www/static/js/tree/api/useDag.js
+++ b/airflow/www/static/js/tree/api/useDag.js
@@ -23,6 +23,6 @@ import { useQuery } from 'react-query';
export default function useDag(dagId) {
return useQuery(
['dag', dagId],
- () => axios.get(`/dags/${dagId}/details`),
+ () => axios.get(`/api/v1/dags/${dagId}/details`),
);
}
diff --git a/airflow/www/static/js/tree/api/useTasks.js b/airflow/www/static/js/tree/api/useTasks.js
index 3dd11e30..5edb137 100644
--- a/airflow/www/static/js/tree/api/useTasks.js
+++ b/airflow/www/static/js/tree/api/useTasks.js
@@ -23,6 +23,6 @@ import { useQuery } from 'react-query';
export default function useTasks(dagId) {
return useQuery(
['tasks', dagId],
- () => axios.get(`/dags/${dagId}/tasks`),
+ () => axios.get(`/api/v1/dags/${dagId}/tasks`),
);
}
diff --git a/airflow/www/static/js/tree/details/content/DagRun.jsx b/airflow/www/static/js/tree/details/content/DagRun.jsx
index abcf908..be06794 100644
--- a/airflow/www/static/js/tree/details/content/DagRun.jsx
+++ b/airflow/www/static/js/tree/details/content/DagRun.jsx
@@ -20,83 +20,153 @@
/* global moment */
import React from 'react';
+import axios from 'axios';
import {
+ Flex,
Text,
Box,
+ Button,
} from '@chakra-ui/react';
import { MdPlayArrow } from 'react-icons/md';
import { formatDateTime, formatDuration } from '../../../datetime_utils';
+import { getMetaValue } from '../../../utils';
const DagRun = ({
dagRun: {
- state, runId, duration, dataIntervalStart, dataIntervalEnd, startDate, endDate, runType,
+ dagId, state, runId, duration, dataIntervalStart, dataIntervalEnd, startDate, endDate, runType,
},
-}) => (
- <Box fontSize="12px" py="4px">
- <Text>
- <Text as="strong">Status:</Text>
- {' '}
- {state || 'no status'}
- </Text>
- <br />
- <Text whiteSpace="nowrap">
- Run Id:
- {' '}
- {runId}
- </Text>
- <Text>
- Run Type:
- {' '}
- {runType === 'manual' && <MdPlayArrow style={{ display: 'inline' }} />}
- {runType}
- </Text>
- <Text>
- Duration:
- {' '}
- {formatDuration(duration)}
- </Text>
- <br />
- <Text as="strong">Data Interval:</Text>
- <Text>
- Start:
- {' '}
- {formatDateTime(dataIntervalStart)}
- </Text>
- <Text>
- End:
- {' '}
- {formatDateTime(dataIntervalEnd)}
- </Text>
- <br />
- <Text as="strong">UTC</Text>
- <Text>
- Started:
- {' '}
- {formatDateTime(moment.utc(startDate))}
- </Text>
- <Text>
- Ended:
- {' '}
- {endDate && formatDateTime(moment.utc(endDate))}
- </Text>
- <br />
- <Text as="strong">
- Local:
- {' '}
- {moment().format('Z')}
- </Text>
- <Text>
- Started:
- {' '}
- {formatDateTime(startDate)}
- </Text>
- <Text>
- Ended:
- {' '}
- {endDate && formatDateTime(endDate)}
- </Text>
- </Box>
-);
+}) => {
+ const csrfToken = getMetaValue('csrf_token');
+
+ const onClear = async () => {
+ const params = new URLSearchParams({
+ csrf_token: csrfToken,
+ confirmed: true,
+ dag_id: dagId,
+ dag_run_id: runId,
+ }).toString();
+
+ try {
+ await axios.post('/dagrun_clear', params, {
+ headers: {
+ 'Content-Type': 'application/x-www-form-urlencoded',
+ },
+ });
+ } catch (e) {
+ console.error(e);
+ }
+ };
+
+ const markFailed = async () => {
+ const params = new URLSearchParams({
+ csrf_token: csrfToken,
+ confirmed: true,
+ dag_id: dagId,
+ dag_run_id: runId,
+ }).toString();
+
+ try {
+ await axios.post('/dagrun_failed', params, {
+ headers: {
+ 'Content-Type': 'application/x-www-form-urlencoded',
+ },
+ });
+ } catch (e) {
+ console.error(e);
+ }
+ };
+
+ const markSuccess = async () => {
+ const params = new URLSearchParams({
+ csrf_token: csrfToken,
+ confirmed: true,
+ dag_id: dagId,
+ dag_run_id: runId,
+ }).toString();
+
+ try {
+ await axios.post('/dagrun_success', params, {
+ headers: {
+ 'Content-Type': 'application/x-www-form-urlencoded',
+ },
+ });
+ } catch (e) {
+ console.error(e);
+ }
+ };
+
+ return (
+ <Box fontSize="12px" py="4px">
+ <Flex justifyContent="space-evenly">
+ <Button onClick={onClear}>Clear</Button>
+ <Button onClick={markFailed} colorScheme="red">Mark Failed</Button>
+ <Button onClick={markSuccess} colorScheme="green">Mark Success</Button>
+ </Flex>
+ <Text>
+ <Text as="strong">Status:</Text>
+ {' '}
+ {state || 'no status'}
+ </Text>
+ <br />
+ <Text whiteSpace="nowrap">
+ Run Id:
+ {' '}
+ {runId}
+ </Text>
+ <Text>
+ Run Type:
+ {' '}
+ {runType === 'manual' && <MdPlayArrow style={{ display: 'inline' }} />}
+ {runType}
+ </Text>
+ <Text>
+ Duration:
+ {' '}
+ {formatDuration(duration)}
+ </Text>
+ <br />
+ <Text as="strong">Data Interval:</Text>
+ <Text>
+ Start:
+ {' '}
+ {formatDateTime(dataIntervalStart)}
+ </Text>
+ <Text>
+ End:
+ {' '}
+ {formatDateTime(dataIntervalEnd)}
+ </Text>
+ <br />
+ <Text as="strong">UTC</Text>
+ <Text>
+ Started:
+ {' '}
+ {formatDateTime(moment.utc(startDate))}
+ </Text>
+ <Text>
+ Ended:
+ {' '}
+ {endDate && formatDateTime(moment.utc(endDate))}
+ </Text>
+ <br />
+ <Text as="strong">
+ Local:
+ {' '}
+ {moment().format('Z')}
+ </Text>
+ <Text>
+ Started:
+ {' '}
+ {formatDateTime(startDate)}
+ </Text>
+ <Text>
+ Ended:
+ {' '}
+ {endDate && formatDateTime(endDate)}
+ </Text>
+ </Box>
+ );
+};
export default DagRun;
diff --git a/airflow/www/templates/airflow/dag.html b/airflow/www/templates/airflow/dag.html
index f2444abab..0f3387a 100644
--- a/airflow/www/templates/airflow/dag.html
+++ b/airflow/www/templates/airflow/dag.html
@@ -39,6 +39,7 @@
<meta name="paused_url" content="{{ url_for('Airflow.paused') }}">
<meta name="tree_data" content="{{ url_for('Airflow.tree_data') }}">
<meta name="is_paused" content="{{ dag_is_paused }}">
+ <meta name="csrf_token" content="{{ csrf_token() }}">
{% if dag_model is defined and dag_model.next_dagrun_create_after is defined and dag_model.next_dagrun_create_after is not none %}
<meta name="next_dagrun_create_after" content="{{ dag_model.next_dagrun_create_after }}">
<meta name="next_dagrun_data_interval_start" content="{{ dag_model.next_dagrun_data_interval_start }}">