Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Upgrade API files to typescript #25098

Merged
merged 10 commits into from
Aug 29, 2022
Original file line number Diff line number Diff line change
Expand Up @@ -17,30 +17,31 @@
* under the License.
*/

import axios from 'axios';
import axios, { AxiosResponse } from 'axios';
import { useMutation, useQueryClient } from 'react-query';
import URLSearchParamsWrapper from 'src/utils/URLSearchParamWrapper';
import { getMetaValue } from '../utils';
import { useAutoRefresh } from '../context/autorefresh';
import useErrorToast from '../utils/useErrorToast';

const csrfToken = getMetaValue('csrf_token');
const clearRunUrl = getMetaValue('dagrun_clear_url');

export default function useClearRun(dagId, runId) {
export default function useClearRun(dagId: string, runId: string) {
const queryClient = useQueryClient();
const errorToast = useErrorToast();
const { startRefresh } = useAutoRefresh();
return useMutation(
['dagRunClear', dagId, runId],
({ confirmed = false }) => {
const params = new URLSearchParams({
({ confirmed = false }: { confirmed: boolean }) => {
const params = new URLSearchParamsWrapper({
csrf_token: csrfToken,
confirmed,
dag_id: dagId,
dag_run_id: runId,
}).toString();

return axios.post(clearRunUrl, params, {
return axios.post<AxiosResponse, string>(clearRunUrl, params, {
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
Expand All @@ -52,7 +53,7 @@ export default function useClearRun(dagId, runId) {
queryClient.invalidateQueries('gridData');
startRefresh();
},
onError: (error) => errorToast({ error }),
onError: (error: Error) => errorToast({ error }),
},
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,9 @@
* under the License.
*/

import axios from 'axios';
import axios, { AxiosResponse } from 'axios';
import { useMutation, useQueryClient } from 'react-query';
import URLSearchParamsWrapper from 'src/utils/URLSearchParamWrapper';
import { getMetaValue } from '../utils';
import { useAutoRefresh } from '../context/autorefresh';
import useErrorToast from '../utils/useErrorToast';
Expand All @@ -28,7 +29,10 @@ const clearUrl = getMetaValue('clear_url');

export default function useClearTask({
dagId, runId, taskId, executionDate,
}) {
}: { dagId: string,
runId: string,
taskId: string,
executionDate: string }) {
const queryClient = useQueryClient();
const errorToast = useErrorToast();
const { startRefresh } = useAutoRefresh();
Expand All @@ -37,8 +41,15 @@ export default function useClearTask({
['clearTask', dagId, runId, taskId],
({
past, future, upstream, downstream, recursive, failed, confirmed, mapIndexes = [],
}) => {
const params = new URLSearchParams({
}: { past: boolean,
future: boolean,
upstream: boolean,
downstream: boolean,
recursive: boolean,
failed: boolean,
confirmed: boolean,
mapIndexes: number[] }) => {
const params = new URLSearchParamsWrapper({
csrf_token: csrfToken,
dag_id: dagId,
dag_run_id: runId,
Expand All @@ -53,11 +64,11 @@ export default function useClearTask({
only_failed: failed,
});

mapIndexes.forEach((mi) => {
params.append('map_index', mi);
mapIndexes.forEach((mi: number) => {
params.append('map_index', mi.toString());
});

return axios.post(clearUrl, params.toString(), {
return axios.post<AxiosResponse, string>(clearUrl, params.toString(), {
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
Expand All @@ -69,7 +80,7 @@ export default function useClearTask({
queryClient.invalidateQueries(['mappedInstances', dagId, runId, taskId]);
startRefresh();
},
onError: (error) => errorToast({ error }),
onError: (error: Error) => errorToast({ error }),
},
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,23 +17,31 @@
* under the License.
*/

import axios from 'axios';
import axios, { AxiosResponse } from 'axios';
import { useMutation } from 'react-query';
import type { TaskState } from 'src/types';
import URLSearchParamsWrapper from 'src/utils/URLSearchParamWrapper';
import { getMetaValue } from '../utils';
import useErrorToast from '../utils/useErrorToast';

const confirmUrl = getMetaValue('confirm_url');

export default function useConfirmMarkTask({
dagId, runId, taskId, state,
}) {
}: { dagId: string, runId: string, taskId: string, state: TaskState }) {
const errorToast = useErrorToast();
return useMutation(
['confirmStateChange', dagId, runId, taskId, state],
({
past, future, upstream, downstream, mapIndexes = [],
}: {
past: boolean,
future: boolean,
upstream: boolean,
downstream: boolean,
mapIndexes: number[],
}) => {
const params = new URLSearchParams({
const params = new URLSearchParamsWrapper({
dag_id: dagId,
dag_run_id: runId,
task_id: taskId,
Expand All @@ -44,14 +52,13 @@ export default function useConfirmMarkTask({
state,
});

mapIndexes.forEach((mi) => {
params.append('map_index', mi);
mapIndexes.forEach((mi: number) => {
params.append('map_index', mi.toString());
});

return axios.get(confirmUrl, { params });
return axios.get<AxiosResponse, string[]>(confirmUrl, { params });
},
{
onError: (error) => errorToast({ error }),
onError: (error: Error) => errorToast({ error }),
},
);
}
10 changes: 3 additions & 7 deletions airflow/www/static/js/api/useDataset.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,11 @@ import { useQuery } from 'react-query';
import { getMetaValue } from 'src/utils';
import type { API } from 'src/types';

interface Props {
datasetUri: string;
}

export default function useDataset({ datasetUri }: Props) {
export default function useDataset({ uri }: API.GetDatasetVariables) {
return useQuery(
['dataset', datasetUri],
['dataset', uri],
() => {
const datasetUrl = `${getMetaValue('datasets_api') || '/api/v1/datasets'}/${encodeURIComponent(datasetUri)}`;
const datasetUrl = `${getMetaValue('datasets_api') || '/api/v1/datasets'}/${encodeURIComponent(uri)}`;
return axios.get<AxiosResponse, API.Dataset>(datasetUrl);
},
);
Expand Down
37 changes: 11 additions & 26 deletions airflow/www/static/js/api/useDatasetEvents.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,43 +22,28 @@ import { useQuery } from 'react-query';

import { getMetaValue } from 'src/utils';
import type { API } from 'src/types';

interface DatasetEventsData {
datasetEvents: API.DatasetEvent[];
totalEntries: number;
}

interface Props {
datasetId?: number;
dagId?: string;
taskId?: string;
runId?: string;
mapIndex?: number;
limit?: number;
offset?: number;
order?: string;
}
import URLSearchParamsWrapper from 'src/utils/URLSearchParamWrapper';

export default function useDatasetEvents({
datasetId, dagId, runId, taskId, mapIndex, limit, offset, order,
}: Props) {
datasetId, sourceDagId, sourceRunId, sourceTaskId, sourceMapIndex, limit, offset, orderBy,
}: API.GetDatasetEventsVariables) {
const query = useQuery(
['datasets-events', datasetId, dagId, runId, taskId, mapIndex, limit, offset, order],
['datasets-events', datasetId, sourceDagId, sourceRunId, sourceTaskId, sourceMapIndex, limit, offset, orderBy],
() => {
const datasetsUrl = getMetaValue('dataset_events_api') || '/api/v1/datasets/events';

const params = new URLSearchParams();
const params = new URLSearchParamsWrapper();

if (limit) params.set('limit', limit.toString());
if (offset) params.set('offset', offset.toString());
if (order) params.set('order_by', order);
if (orderBy) params.set('order_by', orderBy);
if (datasetId) params.set('dataset_id', datasetId.toString());
if (dagId) params.set('source_dag_id', dagId);
if (runId) params.set('source_run_id', runId);
if (taskId) params.set('source_task_id', taskId);
if (mapIndex) params.set('source_map_index', mapIndex.toString());
if (sourceDagId) params.set('source_dag_id', sourceDagId);
if (sourceRunId) params.set('source_run_id', sourceRunId);
if (sourceTaskId) params.set('source_task_id', sourceTaskId);
if (sourceMapIndex) params.set('source_map_index', sourceMapIndex.toString());

return axios.get<AxiosResponse, DatasetEventsData>(datasetsUrl, {
return axios.get<AxiosResponse, API.DatasetEventCollection>(datasetsUrl, {
params,
});
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,21 @@
* under the License.
*/

import axios from 'axios';
import axios, { AxiosResponse } from 'axios';
import { useQuery } from 'react-query';
import { getMetaValue } from '../utils';

const extraLinksUrl = getMetaValue('extra_links_url');

interface LinkData {
url: string | null;
error: string | null;
}

export default function useExtraLinks({
dagId, taskId, executionDate, extraLinks,
}: {
dagId: string, taskId: string, executionDate: string, extraLinks: string[],
}) {
return useQuery(
['extraLinks', dagId, taskId, executionDate],
Expand All @@ -36,7 +43,7 @@ export default function useExtraLinks({
}&execution_date=${encodeURIComponent(executionDate)
}&link_name=${encodeURIComponent(link)}`;
try {
const datum = await axios.get(url);
const datum = await axios.get<AxiosResponse, LinkData>(url);
return {
name: link,
url: datum.url,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,42 +19,53 @@

/* global describe, test, expect */

import type { DagRun } from 'src/types';
import { areActiveRuns } from './useGridData';

const commonDagRunParams = {
runId: 'runId',
executionDate: '2022-01-01T10:00+00:00',
dataIntervalStart: '2022-01-01T05:00+00:00',
dataIntervalEnd: '2022-01-01T10:00+00:00',
startDate: null,
endDate: null,
lastSchedulingDecision: null,
};

describe('Test areActiveRuns()', () => {
test('Correctly detects active runs', () => {
const runs = [
{ runType: 'scheduled', state: 'success' },
{ runType: 'manual', state: 'queued' },
const runs: DagRun[] = [
{ runType: 'scheduled', state: 'success', ...commonDagRunParams },
{ runType: 'manual', state: 'queued', ...commonDagRunParams },
];
expect(areActiveRuns(runs)).toBe(true);
});

test('Returns false when all runs are resolved', () => {
const runs = [
{ runType: 'scheduled', state: 'success' },
{ runType: 'manual', state: 'failed' },
{ runType: 'manual', state: 'failed' },
const runs: DagRun[] = [
{ runType: 'scheduled', state: 'success', ...commonDagRunParams },
{ runType: 'manual', state: 'failed', ...commonDagRunParams },
{ runType: 'manual', state: 'failed', ...commonDagRunParams },
];
const result = areActiveRuns(runs);
expect(result).toBe(false);
});

test('Returns false when filtering runs runtype ["backfill"] and state ["failed"]', () => {
const runs = [
{ runType: 'scheduled', state: 'success' },
{ runType: 'manual', state: 'failed' },
{ runType: 'backfill', state: 'failed' },
test('Returns false when filtering runs runtype ["backfill"]', () => {
const runs: DagRun[] = [
{ runType: 'scheduled', state: 'success', ...commonDagRunParams },
{ runType: 'manual', state: 'failed', ...commonDagRunParams },
{ runType: 'backfill', state: 'failed', ...commonDagRunParams },
];
const result = areActiveRuns(runs);
expect(result).toBe(false);
});

test('Returns false when filtering runs runtype ["backfill"] and state ["queued"]', () => {
const runs = [
{ runType: 'scheduled', state: 'success' },
{ runType: 'manual', state: 'failed' },
{ runType: 'backfill', state: 'queued' },
const runs: DagRun[] = [
{ runType: 'scheduled', state: 'success', ...commonDagRunParams },
{ runType: 'manual', state: 'failed', ...commonDagRunParams },
{ runType: 'backfill', state: 'queued', ...commonDagRunParams },
];
const result = areActiveRuns(runs);
expect(result).toBe(false);
Expand Down Expand Up @@ -87,7 +98,7 @@ describe('Test areActiveRuns()', () => {
},
].forEach(({ state, runType, expectedResult }) => {
test(`Returns ${expectedResult} when filtering runs with runtype ["${runType}"] and state ["${state}"]`, () => {
const runs = [{ runType, state }];
const runs: DagRun[] = [{ runType, state, ...commonDagRunParams } as DagRun];
const result = areActiveRuns(runs);
expect(result).toBe(expectedResult);
});
Expand Down
28 changes: 7 additions & 21 deletions airflow/www/static/js/api/useMappedInstances.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,33 +22,19 @@ import { useQuery } from 'react-query';

import { getMetaValue } from 'src/utils';
import { useAutoRefresh } from 'src/context/autorefresh';
import type { API, DagRun } from 'src/types';
import type { API } from 'src/types';

const mappedInstancesUrl = getMetaValue('mapped_instances_api');

interface MappedInstanceData {
taskInstances: API.TaskInstance[];
totalEntries: number;
}

interface Props {
dagId: string;
runId: DagRun['runId'];
taskId: string;
limit?: number;
offset?: number;
order?: string;
}

export default function useMappedInstances({
dagId, runId, taskId, limit, offset, order,
}: Props) {
const url = mappedInstancesUrl.replace('_DAG_RUN_ID_', runId).replace('_TASK_ID_', taskId);
const orderParam = order && order !== 'map_index' ? { order_by: order } : {};
dagId, dagRunId, taskId, limit, offset, orderBy,
}: API.GetMappedTaskInstancesVariables) {
const url = mappedInstancesUrl.replace('_DAG_RUN_ID_', dagRunId).replace('_TASK_ID_', taskId);
const orderParam = orderBy && orderBy !== 'map_index' ? { order_by: orderBy } : {};
const { isRefreshOn } = useAutoRefresh();
return useQuery(
['mappedInstances', dagId, runId, taskId, offset, order],
() => axios.get<AxiosResponse, MappedInstanceData>(url, {
['mappedInstances', dagId, dagRunId, taskId, offset, orderBy],
() => axios.get<AxiosResponse, API.TaskInstanceCollection>(url, {
params: { offset, limit, ...orderParam },
}),
{
Expand Down
Loading