Skip to content

Commit

Permalink
Add task documentation to details tab in grid view. (apache#39899)
Browse files Browse the repository at this point in the history
* Add task documentation to details tab in grid view.

* Fix tests.

* Fix tests.

* Fix PR comments.
  • Loading branch information
tirkarthi authored and romsharon98 committed Jul 26, 2024
1 parent 3782f30 commit 1910de0
Show file tree
Hide file tree
Showing 10 changed files with 146 additions and 2 deletions.
8 changes: 8 additions & 0 deletions airflow/api_connexion/openapi/v1.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4124,6 +4124,14 @@ components:
readOnly: true
items:
type: string
doc_md:
type: string
readOnly: true
nullable: true
description: |
Task documentation in markdown.
*New in version 2.10.0*
TaskCollection:
type: object
Expand Down
1 change: 1 addition & 0 deletions airflow/api_connexion/schemas/task_schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ class TaskSchema(Schema):
downstream_task_ids = fields.List(fields.String(), dump_only=True)
params = fields.Method("_get_params", dump_only=True)
is_mapped = fields.Method("_get_is_mapped", dump_only=True)
doc_md = fields.String(dump_only=True)

@staticmethod
def _get_class_reference(obj):
Expand Down
2 changes: 2 additions & 0 deletions airflow/www/static/js/api/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ import useEventLogs from "./useEventLogs";
import useCalendarData from "./useCalendarData";
import useCreateDatasetEvent from "./useCreateDatasetEvent";
import useRenderedK8s from "./useRenderedK8s";
import useTaskDetail from "./useTaskDetail";

axios.interceptors.request.use((config) => {
config.paramsSerializer = {
Expand Down Expand Up @@ -106,4 +107,5 @@ export {
useCalendarData,
useCreateDatasetEvent,
useRenderedK8s,
useTaskDetail,
};
33 changes: 33 additions & 0 deletions airflow/www/static/js/api/useTaskDetail.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*!
* 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.
*/

import axios, { AxiosResponse } from "axios";
import type { API } from "src/types";
import { useQuery } from "react-query";
import { getMetaValue } from "../utils";

const taskDetailURI = getMetaValue("task_detail_api");

export default function useTaskDetail({ taskId }: { taskId: string }) {
return useQuery(["taskDetails", taskId], async () => {
const url = taskDetailURI.replace("_TASK_ID_", taskId);

return axios.get<AxiosResponse, API.Task>(url);
});
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/*!
* 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.
*/

import React from "react";
import {
Accordion,
AccordionItem,
AccordionButton,
AccordionPanel,
AccordionIcon,
Alert,
AlertIcon,
Box,
Spinner,
Text,
} from "@chakra-ui/react";

import { useTaskDetail } from "src/api";
import ReactMarkdown from "src/components/ReactMarkdown";

interface Props {
taskId: string;
}

const TaskDocumentation = ({ taskId }: Props) => {
const { data, isLoading, error } = useTaskDetail({
taskId,
});

if (isLoading) {
return <Spinner size="md" thickness="4px" speed="0.65s" />;
}

if (error) {
return (
<Alert status="error" marginBottom="10px">
<AlertIcon />
An error occurred while fetching task documentation.
</Alert>
);
}

if (data && data.docMd) {
return (
<Box mt={3} flexGrow={1}>
<Accordion defaultIndex={[0]} allowToggle>
<AccordionItem>
<AccordionButton p={0} fontSize="inherit">
<Box flex="1" textAlign="left">
<Text as="strong" size="lg">
Task Documentation
</Text>
</Box>
<AccordionIcon />
</AccordionButton>
<AccordionPanel>
<ReactMarkdown>{data.docMd}</ReactMarkdown>
</AccordionPanel>
</AccordionItem>
</Accordion>
</Box>
);
}
return null;
};

export default TaskDocumentation;
2 changes: 2 additions & 0 deletions airflow/www/static/js/dag/details/taskInstance/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import Details from "./Details";
import DatasetUpdateEvents from "./DatasetUpdateEvents";
import TriggererInfo from "./TriggererInfo";
import TaskFailedDependency from "./TaskFailedDependency";
import TaskDocumentation from "./TaskDocumentation";

const dagId = getMetaValue("dag_id")!;

Expand Down Expand Up @@ -90,6 +91,7 @@ const TaskInstance = ({ taskId, runId, mapIndex }: Props) => {
operator={operator}
/>
)}
{!isGroupOrMappedTaskSummary && <TaskDocumentation taskId={taskId} />}
{!isGroupOrMappedTaskSummary && (
<NotesAccordion
dagId={dagId}
Expand Down
6 changes: 6 additions & 0 deletions airflow/www/static/js/types/api-generated.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1700,6 +1700,12 @@ export interface components {
template_fields?: string[];
sub_dag?: components["schemas"]["DAG"];
downstream_task_ids?: string[];
/**
* @description Task documentation in markdown.
*
* *New in version 2.10.0*
*/
doc_md?: string | null;
};
/** @description Collection of tasks. */
TaskCollection: {
Expand Down
4 changes: 2 additions & 2 deletions airflow/www/templates/airflow/dag.html
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,8 @@
<meta name="audit_log_url" content="{{ url_for('LogModelView.list') }}">
<meta name="dag_run_url" content="{{ url_for('/api/v1.airflow_api_connexion_endpoints_dag_run_endpoint_get_dag_run', dag_id='__DAG_ID__', dag_run_id='__DAG_RUN_ID__') }}">
<meta name="task_dependency_api" content="{{ url_for('/api/v1.airflow_api_connexion_endpoints_task_instance_endpoint_get_task_instance_dependencies', dag_id=dag.dag_id, dag_run_id='_DAG_RUN_ID_', task_id='_TASK_ID_') }}">
<meta name="mapped_task_dependency_api" content="{{ url_for('/api/v1.airflow_api_connexion_endpoints_task_instance_endpoint_get_mapped_task_instance_dependencies', dag_id=dag.dag_id, dag_run_id='_DAG_RUN_ID_', task_id='_TASK_ID_', map_index=0) }}">

<meta name="mapped_task_dependency_api" content="{{ url_for('/api/v1.airflow_api_connexion_endpoints_task_instance_endpoint_get_mapped_task_instance_dependencies', dag_id=dag.dag_id, dag_run_id='_DAG_RUN_ID_', task_id='_TASK_ID_', map_index=0) }}">
<meta name="task_detail_api" content="{{ url_for('/api/v1.airflow_api_connexion_endpoints_task_endpoint_get_task', dag_id=dag.dag_id, task_id='_TASK_ID_') }}">

<!-- End Urls -->
<meta name="is_paused" content="{{ dag_is_paused }}">
Expand Down
7 changes: 7 additions & 0 deletions tests/api_connexion/endpoints/test_task_endpoint.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ def test_should_respond_200(self):
"wait_for_downstream": False,
"weight_rule": "downstream",
"is_mapped": False,
"doc_md": None,
}
response = self.client.get(
f"/api/v1/dags/{self.dag_id}/tasks/{self.task_id}", environ_overrides={"REMOTE_USER": "test"}
Expand Down Expand Up @@ -172,6 +173,7 @@ def test_mapped_task(self):
"ui_fgcolor": "#000",
"wait_for_downstream": False,
"weight_rule": "downstream",
"doc_md": None,
}
response = self.client.get(
f"/api/v1/dags/{self.mapped_dag_id}/tasks/{self.mapped_task_id}",
Expand Down Expand Up @@ -225,6 +227,7 @@ def test_should_respond_200_serialized(self):
"wait_for_downstream": False,
"weight_rule": "downstream",
"is_mapped": False,
"doc_md": None,
}
response = self.client.get(
f"/api/v1/dags/{self.dag_id}/tasks/{self.task_id}", environ_overrides={"REMOTE_USER": "test"}
Expand Down Expand Up @@ -301,6 +304,7 @@ def test_should_respond_200(self):
"wait_for_downstream": False,
"weight_rule": "downstream",
"is_mapped": False,
"doc_md": None,
},
{
"class_ref": {
Expand Down Expand Up @@ -332,6 +336,7 @@ def test_should_respond_200(self):
"wait_for_downstream": False,
"weight_rule": "downstream",
"is_mapped": False,
"doc_md": None,
},
],
"total_entries": 2,
Expand Down Expand Up @@ -372,6 +377,7 @@ def test_get_tasks_mapped(self):
"ui_fgcolor": "#000",
"wait_for_downstream": False,
"weight_rule": "downstream",
"doc_md": None,
},
{
"class_ref": {
Expand Down Expand Up @@ -403,6 +409,7 @@ def test_get_tasks_mapped(self):
"wait_for_downstream": False,
"weight_rule": "downstream",
"is_mapped": False,
"doc_md": None,
},
],
"total_entries": 2,
Expand Down
2 changes: 2 additions & 0 deletions tests/api_connexion/schemas/test_task_schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ def test_serialize(self):
"wait_for_downstream": False,
"weight_rule": "downstream",
"is_mapped": False,
"doc_md": None,
}
assert expected == result

Expand Down Expand Up @@ -108,6 +109,7 @@ def test_serialize(self):
"wait_for_downstream": False,
"weight_rule": "downstream",
"is_mapped": False,
"doc_md": None,
}
],
"total_entries": 1,
Expand Down

0 comments on commit 1910de0

Please sign in to comment.