Skip to content

Commit

Permalink
Store grid view selection in url params (#23290)
Browse files Browse the repository at this point in the history
* Add url params for dag_run_id and task_id

* Persist other search params

* simplify useSelection

* delete extra params

* remove API change

(cherry picked from commit 4c1fcee)
  • Loading branch information
bbovenzi authored and ephraimbuddy committed May 21, 2022
1 parent a0a2ddf commit 8cc26f7
Show file tree
Hide file tree
Showing 26 changed files with 117 additions and 84 deletions.
1 change: 1 addition & 0 deletions airflow/www/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@
"react-dom": "^17.0.2",
"react-icons": "^4.3.1",
"react-query": "^3.34.16",
"react-router-dom": "^6.3.0",
"react-table": "^7.7.0",
"redoc": "^2.0.0-rc.63",
"url-search-params-polyfill": "^8.1.0"
Expand Down
2 changes: 1 addition & 1 deletion airflow/www/static/js/tree/Tree.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ import renderTaskRows from './renderTaskRows';
import ResetRoot from './ResetRoot';
import DagRuns from './dagRuns';
import Details from './details';
import { useSelection } from './context/selection';
import useSelection from './utils/useSelection';
import { useAutoRefresh } from './context/autorefresh';

const sidePanelKey = 'hideSidePanel';
Expand Down
2 changes: 1 addition & 1 deletion airflow/www/static/js/tree/api/useClearRun.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import axios from 'axios';
import { useMutation, useQueryClient } from 'react-query';
import { getMetaValue } from '../../utils';
import { useAutoRefresh } from '../context/autorefresh';
import useErrorToast from '../useErrorToast';
import useErrorToast from '../utils/useErrorToast';

const csrfToken = getMetaValue('csrf_token');
const clearRunUrl = getMetaValue('dagrun_clear_url');
Expand Down
2 changes: 1 addition & 1 deletion airflow/www/static/js/tree/api/useClearTask.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import axios from 'axios';
import { useMutation, useQueryClient } from 'react-query';
import { getMetaValue } from '../../utils';
import { useAutoRefresh } from '../context/autorefresh';
import useErrorToast from '../useErrorToast';
import useErrorToast from '../utils/useErrorToast';

const csrfToken = getMetaValue('csrf_token');
const clearUrl = getMetaValue('clear_url');
Expand Down
2 changes: 1 addition & 1 deletion airflow/www/static/js/tree/api/useConfirmMarkTask.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
import axios from 'axios';
import { useMutation } from 'react-query';
import { getMetaValue } from '../../utils';
import useErrorToast from '../useErrorToast';
import useErrorToast from '../utils/useErrorToast';

const confirmUrl = getMetaValue('confirm_url');

Expand Down
2 changes: 1 addition & 1 deletion airflow/www/static/js/tree/api/useMarkFailedRun.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import axios from 'axios';
import { useMutation, useQueryClient } from 'react-query';
import { getMetaValue } from '../../utils';
import { useAutoRefresh } from '../context/autorefresh';
import useErrorToast from '../useErrorToast';
import useErrorToast from '../utils/useErrorToast';

const csrfToken = getMetaValue('csrf_token');
const markFailedUrl = getMetaValue('dagrun_failed_url');
Expand Down
2 changes: 1 addition & 1 deletion airflow/www/static/js/tree/api/useMarkFailedTask.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import axios from 'axios';
import { useMutation, useQueryClient } from 'react-query';
import { getMetaValue } from '../../utils';
import { useAutoRefresh } from '../context/autorefresh';
import useErrorToast from '../useErrorToast';
import useErrorToast from '../utils/useErrorToast';

const failedUrl = getMetaValue('failed_url');
const csrfToken = getMetaValue('csrf_token');
Expand Down
2 changes: 1 addition & 1 deletion airflow/www/static/js/tree/api/useMarkSuccessRun.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import axios from 'axios';
import { useMutation, useQueryClient } from 'react-query';
import { getMetaValue } from '../../utils';
import { useAutoRefresh } from '../context/autorefresh';
import useErrorToast from '../useErrorToast';
import useErrorToast from '../utils/useErrorToast';

const markSuccessUrl = getMetaValue('dagrun_success_url');
const csrfToken = getMetaValue('csrf_token');
Expand Down
2 changes: 1 addition & 1 deletion airflow/www/static/js/tree/api/useMarkSuccessTask.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import axios from 'axios';
import { useMutation, useQueryClient } from 'react-query';
import { getMetaValue } from '../../utils';
import { useAutoRefresh } from '../context/autorefresh';
import useErrorToast from '../useErrorToast';
import useErrorToast from '../utils/useErrorToast';

const csrfToken = getMetaValue('csrf_token');
const successUrl = getMetaValue('success_url');
Expand Down
2 changes: 1 addition & 1 deletion airflow/www/static/js/tree/api/useQueueRun.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import axios from 'axios';
import { useMutation, useQueryClient } from 'react-query';
import { getMetaValue } from '../../utils';
import { useAutoRefresh } from '../context/autorefresh';
import useErrorToast from '../useErrorToast';
import useErrorToast from '../utils/useErrorToast';

const csrfToken = getMetaValue('csrf_token');
const queuedUrl = getMetaValue('dagrun_queued_url');
Expand Down
2 changes: 1 addition & 1 deletion airflow/www/static/js/tree/api/useRunTask.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import axios from 'axios';
import { useMutation, useQueryClient } from 'react-query';
import { getMetaValue } from '../../utils';
import { useAutoRefresh } from '../context/autorefresh';
import useErrorToast from '../useErrorToast';
import useErrorToast from '../utils/useErrorToast';

const csrfToken = getMetaValue('csrf_token');
const runUrl = getMetaValue('run_url');
Expand Down
3 changes: 3 additions & 0 deletions airflow/www/static/js/tree/api/useTasks.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,8 @@ export default function useTasks(dagId) {
return useQuery(
['tasks', dagId],
() => axios.get(tasksUrl),
{
placeholderData: { tasks: [] },
},
);
}
4 changes: 2 additions & 2 deletions airflow/www/static/js/tree/api/useTreeData.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ import axios from 'axios';

import { getMetaValue } from '../../utils';
import { useAutoRefresh } from '../context/autorefresh';
import { formatData, areActiveRuns } from '../treeDataUtils';
import useErrorToast from '../useErrorToast';
import { formatData, areActiveRuns } from '../utils/treeData';
import useErrorToast from '../utils/useErrorToast';

// dagId comes from dag.html
const dagId = getMetaValue('dag_id');
Expand Down
2 changes: 1 addition & 1 deletion airflow/www/static/js/tree/context/autorefresh.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@

import React, { useContext, useState, useEffect } from 'react';
import { getMetaValue } from '../../utils';
import { formatData, areActiveRuns } from '../treeDataUtils';
import { formatData, areActiveRuns } from '../utils/treeData';

const autoRefreshKey = 'disabledAutoRefresh';

Expand Down
56 changes: 0 additions & 56 deletions airflow/www/static/js/tree/context/selection.jsx

This file was deleted.

2 changes: 1 addition & 1 deletion airflow/www/static/js/tree/dagRuns/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ import {
import { useTreeData } from '../api';
import DagRunBar from './Bar';
import { getDuration, formatDuration } from '../../datetime_utils';
import { useSelection } from '../context/selection';
import useSelection from '../utils/useSelection';

const DurationTick = ({ children, ...rest }) => (
<Text fontSize="sm" color="gray.400" right={1} position="absolute" whiteSpace="nowrap" {...rest}>
Expand Down
6 changes: 3 additions & 3 deletions airflow/www/static/js/tree/dagRuns/index.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,10 @@ import { render } from '@testing-library/react';
import { ChakraProvider, Table, Tbody } from '@chakra-ui/react';
import moment from 'moment-timezone';
import { QueryClient, QueryClientProvider } from 'react-query';
import { MemoryRouter } from 'react-router-dom';

import DagRuns from './index';
import { ContainerRefProvider } from '../context/containerRef';
import { SelectionProvider } from '../context/selection';
import { TimezoneProvider } from '../context/timezone';
import { AutoRefreshProvider } from '../context/autorefresh';

Expand All @@ -42,13 +42,13 @@ const Wrapper = ({ children }) => {
<ContainerRefProvider value={{}}>
<TimezoneProvider value={{ timezone: 'UTC' }}>
<AutoRefreshProvider value={{ isRefreshOn: false, stopRefresh: () => {} }}>
<SelectionProvider value={{ onSelect: () => {}, selected: {} }}>
<MemoryRouter>
<Table>
<Tbody>
{children}
</Tbody>
</Table>
</SelectionProvider>
</MemoryRouter>
</AutoRefreshProvider>
</TimezoneProvider>
</ContainerRefProvider>
Expand Down
8 changes: 5 additions & 3 deletions airflow/www/static/js/tree/details/Header.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,9 @@ import {
import { MdPlayArrow } from 'react-icons/md';

import { getMetaValue } from '../../utils';
import { useSelection } from '../context/selection';
import useSelection from '../utils/useSelection';
import Time from '../Time';
import { useTreeData } from '../api';
import { useTasks, useTreeData } from '../api';

const dagId = getMetaValue('dag_id');

Expand All @@ -44,8 +44,10 @@ const LabelValue = ({ label, value }) => (

const Header = () => {
const { data: { dagRuns = [] } } = useTreeData();
const { selected: { taskId, runId, task }, onSelect, clearSelection } = useSelection();
const { selected: { taskId, runId }, onSelect, clearSelection } = useSelection();
const { data: { tasks } } = useTasks();
const dagRun = dagRuns.find((r) => r.runId === runId);
const task = tasks.find((t) => t.taskId === taskId);

let runLabel;
if (dagRun) {
Expand Down
2 changes: 1 addition & 1 deletion airflow/www/static/js/tree/details/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import Header from './Header';
import TaskInstanceContent from './content/taskInstance';
import DagRunContent from './content/dagRun';
import DagContent from './content/Dag';
import { useSelection } from '../context/selection';
import useSelection from '../utils/useSelection';

const Details = () => {
const { selected } = useSelection();
Expand Down
6 changes: 3 additions & 3 deletions airflow/www/static/js/tree/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,13 @@

import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter } from 'react-router-dom';
import { ChakraProvider, extendTheme } from '@chakra-ui/react';
import { CacheProvider } from '@emotion/react';
import createCache from '@emotion/cache';
import { QueryClient, QueryClientProvider } from 'react-query';

import Tree from './Tree';
import { SelectionProvider } from './context/selection';
import { ContainerRefProvider } from './context/containerRef';
import { TimezoneProvider } from './context/timezone';
import { AutoRefreshProvider } from './context/autorefresh';
Expand Down Expand Up @@ -77,9 +77,9 @@ function App() {
<QueryClientProvider client={queryClient}>
<TimezoneProvider>
<AutoRefreshProvider>
<SelectionProvider>
<BrowserRouter>
<Tree />
</SelectionProvider>
</BrowserRouter>
</AutoRefreshProvider>
</TimezoneProvider>
</QueryClientProvider>
Expand Down
2 changes: 1 addition & 1 deletion airflow/www/static/js/tree/renderTaskRows.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ import StatusBox, { boxSize, boxSizePx } from './StatusBox';
import TaskName from './TaskName';

import { getMetaValue } from '../utils';
import { useSelection } from './context/selection';
import useSelection from './utils/useSelection';

const boxPadding = 3;
const boxPaddingPx = `${boxPadding}px`;
Expand Down
6 changes: 3 additions & 3 deletions airflow/www/static/js/tree/renderTaskRows.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,10 @@ import { render, fireEvent } from '@testing-library/react';
import { ChakraProvider, Table, Tbody } from '@chakra-ui/react';
import moment from 'moment';
import { QueryClient, QueryClientProvider } from 'react-query';
import { MemoryRouter } from 'react-router-dom';

import renderTaskRows from './renderTaskRows';
import { ContainerRefProvider } from './context/containerRef';
import { SelectionProvider } from './context/selection';

global.moment = moment;

Expand Down Expand Up @@ -101,13 +101,13 @@ const Wrapper = ({ children }) => {
<ChakraProvider>
<QueryClientProvider client={queryClient}>
<ContainerRefProvider value={{}}>
<SelectionProvider value={{ onSelect: () => {}, selected: {} }}>
<MemoryRouter>
<Table>
<Tbody>
{children}
</Tbody>
</Table>
</SelectionProvider>
</MemoryRouter>
</ContainerRefProvider>
</QueryClientProvider>
</ChakraProvider>
Expand Down
File renamed without changes.
File renamed without changes.
54 changes: 54 additions & 0 deletions airflow/www/static/js/tree/utils/useSelection.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*!
* 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 { useSearchParams } from 'react-router-dom';

const RUN_ID = 'dag_run_id';
const TASK_ID = 'task_id';

const useSelection = () => {
const [searchParams, setSearchParams] = useSearchParams();

// Clear selection, but keep other search params
const clearSelection = () => {
searchParams.delete(RUN_ID);
searchParams.delete(TASK_ID);
setSearchParams(searchParams);
};

const onSelect = (payload) => {
const params = new URLSearchParams(searchParams);

if (payload.runId) params.set(RUN_ID, payload.runId);
else params.delete(RUN_ID);

if (payload.taskId) params.set(TASK_ID, payload.taskId);
else params.delete(TASK_ID);

setSearchParams(params);
};

const runId = searchParams.get(RUN_ID);
const taskId = searchParams.get(TASK_ID);
const selected = { runId, taskId };

return { selected, clearSelection, onSelect };
};

export default useSelection;
Loading

0 comments on commit 8cc26f7

Please sign in to comment.