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/07/13 18:05:01 UTC

[airflow] branch main updated: Refactor js file structure (#25003)

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 26175ee5d9 Refactor js file structure (#25003)
26175ee5d9 is described below

commit 26175ee5d931b8454d61ccbbd5dd585f7288c97b
Author: Brent Bovenzi <br...@gmail.com>
AuthorDate: Wed Jul 13 14:04:51 2022 -0400

    Refactor js file structure (#25003)
    
    * Add absolute paths for typescript files
    
    Update jest, webpack and ts config files to allow for two aliased paths:
    `app` = `static/js`
    `grid` = `static/js/grid`
    
    * remove extraneous path var
    
    * refactor js file structure
    
    get ready for graph view in grid and other react pages like datasets and dag dependencies
    
    * move instancetooltip and flatten details folder
    
    * DRY babel config
    
    * remove extraneous eslint disable
    
    * unDRY babel
    
    * fix children props
---
 airflow/www/jest.config.js                         |  3 +-
 airflow/www/static/js/{grid/index.jsx => App.tsx}  | 39 ++++++++++------------
 airflow/www/static/js/{grid => }/README.md         |  0
 airflow/www/static/js/{grid => }/api/index.ts      |  0
 .../www/static/js/{grid => }/api/useClearRun.js    |  2 +-
 .../www/static/js/{grid => }/api/useClearTask.js   |  2 +-
 .../static/js/{grid => }/api/useConfirmMarkTask.js |  2 +-
 .../www/static/js/{grid => }/api/useExtraLinks.js  |  2 +-
 .../static/js/{grid => }/api/useGridData.test.js   |  0
 .../www/static/js/{grid => }/api/useGridData.ts    | 10 +++---
 .../static/js/{grid => }/api/useMappedInstances.js |  2 +-
 .../static/js/{grid => }/api/useMarkFailedRun.js   |  2 +-
 .../static/js/{grid => }/api/useMarkFailedTask.js  |  2 +-
 .../static/js/{grid => }/api/useMarkSuccessRun.js  |  2 +-
 .../static/js/{grid => }/api/useMarkSuccessTask.js |  2 +-
 .../www/static/js/{grid => }/api/useQueueRun.js    |  2 +-
 airflow/www/static/js/{grid => }/api/useRunTask.js |  2 +-
 .../www/static/js/{grid => }/api/useTaskLog.tsx    |  2 +-
 .../www/static/js/{grid => }/api/useTasks.test.jsx |  2 +-
 airflow/www/static/js/{grid => }/api/useTasks.ts   |  2 +-
 .../static/js/{grid => components}/AutoRefresh.tsx |  2 +-
 .../js/{grid => }/components/Clipboard.test.tsx    |  0
 .../static/js/{grid => }/components/Clipboard.tsx  |  2 +-
 .../js/{grid => }/components/LinkButton.test.tsx   |  0
 .../static/js/{grid => }/components/LinkButton.tsx |  0
 .../js/{grid => }/components/MultiSelect.tsx       |  0
 .../www/static/js/{grid => }/components/Table.jsx  |  0
 .../static/js/{grid => }/components/Table.test.jsx |  0
 .../static/js/{grid => }/components/Time.test.tsx  |  4 +--
 .../www/static/js/{grid => }/components/Time.tsx   |  4 +--
 .../static/js/{grid => }/components/Tooltip.tsx    |  0
 .../static/js/{grid => }/context/autorefresh.tsx   | 10 ++----
 .../static/js/{grid => }/context/containerRef.tsx  |  8 ++---
 .../www/static/js/{grid => }/context/timezone.jsx  |  2 +-
 .../components => dag}/InstanceTooltip.test.tsx    |  4 +--
 .../{grid/components => dag}/InstanceTooltip.tsx   |  9 +++--
 airflow/www/static/js/{grid => dag}/Main.tsx       | 13 ++++----
 .../js/{grid/components => dag}/StatusBox.tsx      | 10 +++---
 .../js/{grid => dag}/details/BreadcrumbText.tsx    |  0
 .../content => dag/details}/ConfirmDialog.tsx      |  2 +-
 .../{grid/details/content => dag/details}/Dag.jsx  |  6 ++--
 .../www/static/js/{grid => dag}/details/Header.tsx |  9 ++---
 .../content => dag/details}/dagRun/ClearRun.jsx    |  2 +-
 .../details}/dagRun/MarkFailedRun.jsx              |  2 +-
 .../details}/dagRun/MarkSuccessRun.jsx             |  2 +-
 .../content => dag/details}/dagRun/QueueRun.jsx    |  2 +-
 .../content => dag/details}/dagRun/index.tsx       | 14 ++++----
 .../www/static/js/{grid => dag}/details/index.tsx  |  8 ++---
 .../details}/taskInstance/Details.tsx              | 12 +++----
 .../details}/taskInstance/ExtraLinks.tsx           |  4 +--
 .../details}/taskInstance/Logs/LogLink.test.tsx    |  0
 .../details}/taskInstance/Logs/LogLink.tsx         |  6 ++--
 .../details}/taskInstance/Logs/index.test.tsx      |  2 +-
 .../details}/taskInstance/Logs/index.tsx           | 12 +++----
 .../details}/taskInstance/Logs/utils.test.tsx      |  0
 .../details}/taskInstance/Logs/utils.ts            |  2 +-
 .../details}/taskInstance/MappedInstances.jsx      |  6 ++--
 .../content => dag/details}/taskInstance/Nav.tsx   |  6 ++--
 .../content => dag/details}/taskInstance/index.tsx |  6 ++--
 .../taskInstance/taskActions/ActionButton.jsx      |  0
 .../details}/taskInstance/taskActions/Clear.jsx    |  2 +-
 .../taskInstance/taskActions/MarkFailed.jsx        |  2 +-
 .../taskInstance/taskActions/MarkSuccess.jsx       |  2 +-
 .../details}/taskInstance/taskActions/Run.jsx      |  2 +-
 airflow/www/static/js/{ => dag}/grid/ResetRoot.tsx |  2 +-
 .../components => dag/grid}/TaskName.test.tsx      |  2 +-
 .../js/{grid/components => dag/grid}/TaskName.tsx  |  0
 .../www/static/js/{ => dag}/grid/ToggleGroups.tsx  |  3 +-
 .../www/static/js/{ => dag}/grid/dagRuns/Bar.tsx   |  8 ++---
 .../static/js/{ => dag}/grid/dagRuns/Tooltip.tsx   |  4 +--
 .../js/{ => dag}/grid/dagRuns/index.test.tsx       |  6 ++--
 .../www/static/js/{ => dag}/grid/dagRuns/index.tsx |  8 ++---
 .../Grid.test.jsx => dag/grid/index.test.jsx}      |  6 ++--
 .../js/{grid/Grid.tsx => dag/grid/index.tsx}       |  8 +++--
 .../js/{ => dag}/grid/renderTaskRows.test.tsx      |  5 +--
 .../static/js/{ => dag}/grid/renderTaskRows.tsx    |  8 ++---
 .../LinkButton.test.tsx => dag/index.tsx}          | 36 ++++++++++++--------
 .../www/static/js/{grid => dag/nav}/FilterBar.jsx  |  6 ++--
 .../static/js/{grid => dag/nav}/LegendRow.test.tsx |  0
 .../www/static/js/{grid => dag/nav}/LegendRow.tsx  |  0
 .../static/js/{grid/utils => dag}/useFilters.js    |  0
 .../js/{grid/utils => dag}/useFilters.test.jsx     |  2 +-
 .../js/{grid/utils => dag}/useSelection.test.tsx   |  8 ++---
 .../static/js/{grid/utils => dag}/useSelection.ts  |  0
 airflow/www/static/js/grid/utils/index.ts          | 26 ---------------
 airflow/www/static/js/{grid => }/index.d.ts        |  0
 airflow/www/static/js/{grid => }/theme.ts          |  0
 airflow/www/static/js/{grid => }/types/index.ts    |  0
 airflow/www/static/js/{utils.js => utils/index.ts} | 17 +++++++---
 .../www/static/js/{grid => }/utils/testUtils.jsx   |  0
 .../static/js/{grid => }/utils/useErrorToast.js    |  0
 .../js/{grid => }/utils/useErrorToast.test.jsx     |  0
 airflow/www/tsconfig.json                          |  3 +-
 airflow/www/webpack.config.js                      |  5 ++-
 94 files changed, 200 insertions(+), 222 deletions(-)

diff --git a/airflow/www/jest.config.js b/airflow/www/jest.config.js
index 6704331cb7..a01cc223c5 100644
--- a/airflow/www/jest.config.js
+++ b/airflow/www/jest.config.js
@@ -26,8 +26,7 @@ const config = {
   setupFilesAfterEnv: ['./jest-setup.js'],
   moduleDirectories: ['node_modules'],
   moduleNameMapper: { // Listing all aliases
-    '^app/(.*)$': '<rootDir>/static/js/$1',
-    '^grid/(.*)$': '<rootDir>/static/js/grid/$1',
+    '^src/(.*)$': '<rootDir>/static/js/$1',
   },
 };
 
diff --git a/airflow/www/static/js/grid/index.jsx b/airflow/www/static/js/App.tsx
similarity index 78%
rename from airflow/www/static/js/grid/index.jsx
rename to airflow/www/static/js/App.tsx
index 549c0b7b29..cbdd3fa096 100644
--- a/airflow/www/static/js/grid/index.jsx
+++ b/airflow/www/static/js/App.tsx
@@ -17,32 +17,22 @@
  * under the License.
  */
 
-/* global document */
+/*
+  Base setup for anywhere we add react to the UI
+*/
 
-import React from 'react';
-import { createRoot } from 'react-dom/client';
+import React, { PropsWithChildren } from 'react';
 import { BrowserRouter } from 'react-router-dom';
 import { ChakraProvider } from '@chakra-ui/react';
 import { CacheProvider } from '@emotion/react';
-import createCache from '@emotion/cache';
+import type { EmotionCache } from '@emotion/cache';
 import { QueryClient, QueryClientProvider } from 'react-query';
 
-import Main from './Main';
 import theme from './theme';
 import { ContainerRefProvider, useContainerRef } from './context/containerRef';
 import { TimezoneProvider } from './context/timezone';
 import { AutoRefreshProvider } from './context/autorefresh';
 
-// create shadowRoot
-const root = document.querySelector('#root');
-const shadowRoot = root.attachShadow({ mode: 'open' });
-const myCache = createCache({
-  container: shadowRoot,
-  key: 'c',
-});
-const mainElement = document.getElementById('react-container');
-shadowRoot.appendChild(mainElement);
-
 const queryClient = new QueryClient({
   defaultOptions: {
     queries: {
@@ -61,8 +51,12 @@ const queryClient = new QueryClient({
   },
 });
 
+interface AppProps extends PropsWithChildren {
+  cache: EmotionCache;
+}
+
 // Chakra needs to access the containerRef provider so our tooltips pick up the correct styles
-const ChakraApp = () => {
+const ChakraApp = ({ children }: PropsWithChildren) => {
   const containerRef = useContainerRef();
   return (
     <ChakraProvider theme={theme} toastOptions={{ portalProps: { containerRef } }}>
@@ -70,7 +64,7 @@ const ChakraApp = () => {
         <TimezoneProvider>
           <AutoRefreshProvider>
             <BrowserRouter>
-              <Main />
+              {children}
             </BrowserRouter>
           </AutoRefreshProvider>
         </TimezoneProvider>
@@ -79,17 +73,18 @@ const ChakraApp = () => {
   );
 };
 
-function App() {
+function App({ children, cache }: AppProps) {
   return (
     <React.StrictMode>
-      <CacheProvider value={myCache}>
+      <CacheProvider value={cache}>
         <ContainerRefProvider>
-          <ChakraApp />
+          <ChakraApp>
+            {children}
+          </ChakraApp>
         </ContainerRefProvider>
       </CacheProvider>
     </React.StrictMode>
   );
 }
 
-const reactRoot = createRoot(mainElement);
-reactRoot.render(<App />);
+export default App;
diff --git a/airflow/www/static/js/grid/README.md b/airflow/www/static/js/README.md
similarity index 100%
rename from airflow/www/static/js/grid/README.md
rename to airflow/www/static/js/README.md
diff --git a/airflow/www/static/js/grid/api/index.ts b/airflow/www/static/js/api/index.ts
similarity index 100%
rename from airflow/www/static/js/grid/api/index.ts
rename to airflow/www/static/js/api/index.ts
diff --git a/airflow/www/static/js/grid/api/useClearRun.js b/airflow/www/static/js/api/useClearRun.js
similarity index 97%
rename from airflow/www/static/js/grid/api/useClearRun.js
rename to airflow/www/static/js/api/useClearRun.js
index 1994453c66..f58fc45718 100644
--- a/airflow/www/static/js/grid/api/useClearRun.js
+++ b/airflow/www/static/js/api/useClearRun.js
@@ -19,7 +19,7 @@
 
 import axios from 'axios';
 import { useMutation, useQueryClient } from 'react-query';
-import { getMetaValue } from '../../utils';
+import { getMetaValue } from '../utils';
 import { useAutoRefresh } from '../context/autorefresh';
 import useErrorToast from '../utils/useErrorToast';
 
diff --git a/airflow/www/static/js/grid/api/useClearTask.js b/airflow/www/static/js/api/useClearTask.js
similarity index 98%
rename from airflow/www/static/js/grid/api/useClearTask.js
rename to airflow/www/static/js/api/useClearTask.js
index b9a1b389ac..8fe27198af 100644
--- a/airflow/www/static/js/grid/api/useClearTask.js
+++ b/airflow/www/static/js/api/useClearTask.js
@@ -19,7 +19,7 @@
 
 import axios from 'axios';
 import { useMutation, useQueryClient } from 'react-query';
-import { getMetaValue } from '../../utils';
+import { getMetaValue } from '../utils';
 import { useAutoRefresh } from '../context/autorefresh';
 import useErrorToast from '../utils/useErrorToast';
 
diff --git a/airflow/www/static/js/grid/api/useConfirmMarkTask.js b/airflow/www/static/js/api/useConfirmMarkTask.js
similarity index 97%
rename from airflow/www/static/js/grid/api/useConfirmMarkTask.js
rename to airflow/www/static/js/api/useConfirmMarkTask.js
index a095f5a674..68328ec7bc 100644
--- a/airflow/www/static/js/grid/api/useConfirmMarkTask.js
+++ b/airflow/www/static/js/api/useConfirmMarkTask.js
@@ -19,7 +19,7 @@
 
 import axios from 'axios';
 import { useMutation } from 'react-query';
-import { getMetaValue } from '../../utils';
+import { getMetaValue } from '../utils';
 import useErrorToast from '../utils/useErrorToast';
 
 const confirmUrl = getMetaValue('confirm_url');
diff --git a/airflow/www/static/js/grid/api/useExtraLinks.js b/airflow/www/static/js/api/useExtraLinks.js
similarity index 97%
rename from airflow/www/static/js/grid/api/useExtraLinks.js
rename to airflow/www/static/js/api/useExtraLinks.js
index ecc92ddc80..24262b6b7c 100644
--- a/airflow/www/static/js/grid/api/useExtraLinks.js
+++ b/airflow/www/static/js/api/useExtraLinks.js
@@ -19,7 +19,7 @@
 
 import axios from 'axios';
 import { useQuery } from 'react-query';
-import { getMetaValue } from '../../utils';
+import { getMetaValue } from '../utils';
 
 const extraLinksUrl = getMetaValue('extra_links_url');
 
diff --git a/airflow/www/static/js/grid/api/useGridData.test.js b/airflow/www/static/js/api/useGridData.test.js
similarity index 100%
rename from airflow/www/static/js/grid/api/useGridData.test.js
rename to airflow/www/static/js/api/useGridData.test.js
diff --git a/airflow/www/static/js/grid/api/useGridData.ts b/airflow/www/static/js/api/useGridData.ts
similarity index 92%
rename from airflow/www/static/js/grid/api/useGridData.ts
rename to airflow/www/static/js/api/useGridData.ts
index 38a78753db..f975e7d6b7 100644
--- a/airflow/www/static/js/grid/api/useGridData.ts
+++ b/airflow/www/static/js/api/useGridData.ts
@@ -20,13 +20,13 @@
 import { useQuery } from 'react-query';
 import axios, { AxiosResponse } from 'axios';
 
-import { getMetaValue } from 'app/utils';
-import { useAutoRefresh } from 'grid/context/autorefresh';
-import useErrorToast from 'grid/utils/useErrorToast';
+import { getMetaValue } from 'src/utils';
+import { useAutoRefresh } from 'src/context/autorefresh';
+import useErrorToast from 'src/utils/useErrorToast';
 import useFilters, {
   BASE_DATE_PARAM, NUM_RUNS_PARAM, RUN_STATE_PARAM, RUN_TYPE_PARAM, now,
-} from 'grid/utils/useFilters';
-import type { Task, DagRun } from 'grid/types';
+} from 'src/dag/useFilters';
+import type { Task, DagRun } from 'src/types';
 
 const DAG_ID_PARAM = 'dag_id';
 
diff --git a/airflow/www/static/js/grid/api/useMappedInstances.js b/airflow/www/static/js/api/useMappedInstances.js
similarity index 97%
rename from airflow/www/static/js/grid/api/useMappedInstances.js
rename to airflow/www/static/js/api/useMappedInstances.js
index cc42f2616d..e932f479af 100644
--- a/airflow/www/static/js/grid/api/useMappedInstances.js
+++ b/airflow/www/static/js/api/useMappedInstances.js
@@ -22,7 +22,7 @@
 import axios from 'axios';
 import { useQuery } from 'react-query';
 
-import { getMetaValue } from '../../utils';
+import { getMetaValue } from '../utils';
 import { useAutoRefresh } from '../context/autorefresh';
 
 const mappedInstancesUrl = getMetaValue('mapped_instances_api');
diff --git a/airflow/www/static/js/grid/api/useMarkFailedRun.js b/airflow/www/static/js/api/useMarkFailedRun.js
similarity index 97%
rename from airflow/www/static/js/grid/api/useMarkFailedRun.js
rename to airflow/www/static/js/api/useMarkFailedRun.js
index 6c5873a3ae..8e37bc4c1a 100644
--- a/airflow/www/static/js/grid/api/useMarkFailedRun.js
+++ b/airflow/www/static/js/api/useMarkFailedRun.js
@@ -19,7 +19,7 @@
 
 import axios from 'axios';
 import { useMutation, useQueryClient } from 'react-query';
-import { getMetaValue } from '../../utils';
+import { getMetaValue } from '../utils';
 import { useAutoRefresh } from '../context/autorefresh';
 import useErrorToast from '../utils/useErrorToast';
 
diff --git a/airflow/www/static/js/grid/api/useMarkFailedTask.js b/airflow/www/static/js/api/useMarkFailedTask.js
similarity index 98%
rename from airflow/www/static/js/grid/api/useMarkFailedTask.js
rename to airflow/www/static/js/api/useMarkFailedTask.js
index 5a5d8fbf50..31273f4ec4 100644
--- a/airflow/www/static/js/grid/api/useMarkFailedTask.js
+++ b/airflow/www/static/js/api/useMarkFailedTask.js
@@ -19,7 +19,7 @@
 
 import axios from 'axios';
 import { useMutation, useQueryClient } from 'react-query';
-import { getMetaValue } from '../../utils';
+import { getMetaValue } from '../utils';
 import { useAutoRefresh } from '../context/autorefresh';
 import useErrorToast from '../utils/useErrorToast';
 
diff --git a/airflow/www/static/js/grid/api/useMarkSuccessRun.js b/airflow/www/static/js/api/useMarkSuccessRun.js
similarity index 97%
rename from airflow/www/static/js/grid/api/useMarkSuccessRun.js
rename to airflow/www/static/js/api/useMarkSuccessRun.js
index 1009d78ea2..7b3cb77665 100644
--- a/airflow/www/static/js/grid/api/useMarkSuccessRun.js
+++ b/airflow/www/static/js/api/useMarkSuccessRun.js
@@ -19,7 +19,7 @@
 
 import axios from 'axios';
 import { useMutation, useQueryClient } from 'react-query';
-import { getMetaValue } from '../../utils';
+import { getMetaValue } from '../utils';
 import { useAutoRefresh } from '../context/autorefresh';
 import useErrorToast from '../utils/useErrorToast';
 
diff --git a/airflow/www/static/js/grid/api/useMarkSuccessTask.js b/airflow/www/static/js/api/useMarkSuccessTask.js
similarity index 98%
rename from airflow/www/static/js/grid/api/useMarkSuccessTask.js
rename to airflow/www/static/js/api/useMarkSuccessTask.js
index 3c7ea1e42a..db620866aa 100644
--- a/airflow/www/static/js/grid/api/useMarkSuccessTask.js
+++ b/airflow/www/static/js/api/useMarkSuccessTask.js
@@ -19,7 +19,7 @@
 
 import axios from 'axios';
 import { useMutation, useQueryClient } from 'react-query';
-import { getMetaValue } from '../../utils';
+import { getMetaValue } from '../utils';
 import { useAutoRefresh } from '../context/autorefresh';
 import useErrorToast from '../utils/useErrorToast';
 
diff --git a/airflow/www/static/js/grid/api/useQueueRun.js b/airflow/www/static/js/api/useQueueRun.js
similarity index 97%
rename from airflow/www/static/js/grid/api/useQueueRun.js
rename to airflow/www/static/js/api/useQueueRun.js
index 413a3ca571..5ab3879d07 100644
--- a/airflow/www/static/js/grid/api/useQueueRun.js
+++ b/airflow/www/static/js/api/useQueueRun.js
@@ -19,7 +19,7 @@
 
 import axios from 'axios';
 import { useMutation, useQueryClient } from 'react-query';
-import { getMetaValue } from '../../utils';
+import { getMetaValue } from '../utils';
 import { useAutoRefresh } from '../context/autorefresh';
 import useErrorToast from '../utils/useErrorToast';
 
diff --git a/airflow/www/static/js/grid/api/useRunTask.js b/airflow/www/static/js/api/useRunTask.js
similarity index 98%
rename from airflow/www/static/js/grid/api/useRunTask.js
rename to airflow/www/static/js/api/useRunTask.js
index abfa34f8dc..83607e13ed 100644
--- a/airflow/www/static/js/grid/api/useRunTask.js
+++ b/airflow/www/static/js/api/useRunTask.js
@@ -19,7 +19,7 @@
 
 import axios from 'axios';
 import { useMutation, useQueryClient } from 'react-query';
-import { getMetaValue } from '../../utils';
+import { getMetaValue } from '../utils';
 import { useAutoRefresh } from '../context/autorefresh';
 import useErrorToast from '../utils/useErrorToast';
 
diff --git a/airflow/www/static/js/grid/api/useTaskLog.tsx b/airflow/www/static/js/api/useTaskLog.tsx
similarity index 97%
rename from airflow/www/static/js/grid/api/useTaskLog.tsx
rename to airflow/www/static/js/api/useTaskLog.tsx
index 23aee4da07..b468c604af 100644
--- a/airflow/www/static/js/grid/api/useTaskLog.tsx
+++ b/airflow/www/static/js/api/useTaskLog.tsx
@@ -20,7 +20,7 @@
 import axios, { AxiosResponse } from 'axios';
 import { useQuery } from 'react-query';
 
-import { getMetaValue } from 'app/utils';
+import { getMetaValue } from 'src/utils';
 
 const taskLogApi = getMetaValue('task_log_api');
 
diff --git a/airflow/www/static/js/grid/api/useTasks.test.jsx b/airflow/www/static/js/api/useTasks.test.jsx
similarity index 98%
rename from airflow/www/static/js/grid/api/useTasks.test.jsx
rename to airflow/www/static/js/api/useTasks.test.jsx
index d642dae32a..290789d390 100644
--- a/airflow/www/static/js/grid/api/useTasks.test.jsx
+++ b/airflow/www/static/js/api/useTasks.test.jsx
@@ -25,7 +25,7 @@ import { QueryClient, QueryClientProvider } from 'react-query';
 import nock from 'nock';
 
 import useTasks from './useTasks';
-import * as metaUtils from '../../utils';
+import * as metaUtils from '../utils';
 
 const Wrapper = ({ children }) => {
   const queryClient = new QueryClient({
diff --git a/airflow/www/static/js/grid/api/useTasks.ts b/airflow/www/static/js/api/useTasks.ts
similarity index 96%
rename from airflow/www/static/js/grid/api/useTasks.ts
rename to airflow/www/static/js/api/useTasks.ts
index 2857a88ffe..ffea78a43e 100644
--- a/airflow/www/static/js/grid/api/useTasks.ts
+++ b/airflow/www/static/js/api/useTasks.ts
@@ -20,7 +20,7 @@
 import axios, { AxiosResponse } from 'axios';
 import { useQuery } from 'react-query';
 
-import { getMetaValue } from 'app/utils';
+import { getMetaValue } from 'src/utils';
 
 interface TaskData {
   tasks: any[];
diff --git a/airflow/www/static/js/grid/AutoRefresh.tsx b/airflow/www/static/js/components/AutoRefresh.tsx
similarity index 96%
rename from airflow/www/static/js/grid/AutoRefresh.tsx
rename to airflow/www/static/js/components/AutoRefresh.tsx
index b198647fb2..5bd24d2739 100644
--- a/airflow/www/static/js/grid/AutoRefresh.tsx
+++ b/airflow/www/static/js/components/AutoRefresh.tsx
@@ -25,7 +25,7 @@ import {
   Spinner,
 } from '@chakra-ui/react';
 
-import { useAutoRefresh } from './context/autorefresh';
+import { useAutoRefresh } from 'src/context/autorefresh';
 
 const AutoRefresh = () => {
   const { isRefreshOn, toggleRefresh, isPaused } = useAutoRefresh();
diff --git a/airflow/www/static/js/grid/components/Clipboard.test.tsx b/airflow/www/static/js/components/Clipboard.test.tsx
similarity index 100%
rename from airflow/www/static/js/grid/components/Clipboard.test.tsx
rename to airflow/www/static/js/components/Clipboard.test.tsx
diff --git a/airflow/www/static/js/grid/components/Clipboard.tsx b/airflow/www/static/js/components/Clipboard.tsx
similarity index 97%
rename from airflow/www/static/js/grid/components/Clipboard.tsx
rename to airflow/www/static/js/components/Clipboard.tsx
index d7e4efbdd9..eca0e94dbf 100644
--- a/airflow/www/static/js/grid/components/Clipboard.tsx
+++ b/airflow/www/static/js/components/Clipboard.tsx
@@ -27,7 +27,7 @@ import {
 } from '@chakra-ui/react';
 import { FiCopy } from 'react-icons/fi';
 
-import { useContainerRef } from 'grid/context/containerRef';
+import { useContainerRef } from 'src/context/containerRef';
 
 export const ClipboardButton = forwardRef(
   (
diff --git a/airflow/www/static/js/grid/components/LinkButton.test.tsx b/airflow/www/static/js/components/LinkButton.test.tsx
similarity index 100%
copy from airflow/www/static/js/grid/components/LinkButton.test.tsx
copy to airflow/www/static/js/components/LinkButton.test.tsx
diff --git a/airflow/www/static/js/grid/components/LinkButton.tsx b/airflow/www/static/js/components/LinkButton.tsx
similarity index 100%
rename from airflow/www/static/js/grid/components/LinkButton.tsx
rename to airflow/www/static/js/components/LinkButton.tsx
diff --git a/airflow/www/static/js/grid/components/MultiSelect.tsx b/airflow/www/static/js/components/MultiSelect.tsx
similarity index 100%
rename from airflow/www/static/js/grid/components/MultiSelect.tsx
rename to airflow/www/static/js/components/MultiSelect.tsx
diff --git a/airflow/www/static/js/grid/components/Table.jsx b/airflow/www/static/js/components/Table.jsx
similarity index 100%
rename from airflow/www/static/js/grid/components/Table.jsx
rename to airflow/www/static/js/components/Table.jsx
diff --git a/airflow/www/static/js/grid/components/Table.test.jsx b/airflow/www/static/js/components/Table.test.jsx
similarity index 100%
rename from airflow/www/static/js/grid/components/Table.test.jsx
rename to airflow/www/static/js/components/Table.test.jsx
diff --git a/airflow/www/static/js/grid/components/Time.test.tsx b/airflow/www/static/js/components/Time.test.tsx
similarity index 95%
rename from airflow/www/static/js/grid/components/Time.test.tsx
rename to airflow/www/static/js/components/Time.test.tsx
index 9c83ac1ad0..5e9f86ce13 100644
--- a/airflow/www/static/js/grid/components/Time.test.tsx
+++ b/airflow/www/static/js/components/Time.test.tsx
@@ -25,8 +25,8 @@ import {
 } from '@testing-library/react';
 import moment from 'moment-timezone';
 
-import { defaultFormatWithTZ, TimezoneEvent } from 'app/datetime_utils';
-import { Wrapper } from 'grid/utils/testUtils';
+import { defaultFormatWithTZ, TimezoneEvent } from 'src/datetime_utils';
+import { Wrapper } from 'src/utils/testUtils';
 
 import Time from './Time';
 
diff --git a/airflow/www/static/js/grid/components/Time.tsx b/airflow/www/static/js/components/Time.tsx
similarity index 93%
rename from airflow/www/static/js/grid/components/Time.tsx
rename to airflow/www/static/js/components/Time.tsx
index 5634652b39..cc048894d6 100644
--- a/airflow/www/static/js/grid/components/Time.tsx
+++ b/airflow/www/static/js/components/Time.tsx
@@ -20,8 +20,8 @@
 import React from 'react';
 import moment from 'moment-timezone';
 
-import { useTimezone } from 'grid/context/timezone';
-import { defaultFormatWithTZ } from 'app/datetime_utils';
+import { useTimezone } from 'src/context/timezone';
+import { defaultFormatWithTZ } from 'src/datetime_utils';
 
 interface Props {
   dateTime: string;
diff --git a/airflow/www/static/js/grid/components/Tooltip.tsx b/airflow/www/static/js/components/Tooltip.tsx
similarity index 100%
rename from airflow/www/static/js/grid/components/Tooltip.tsx
rename to airflow/www/static/js/components/Tooltip.tsx
diff --git a/airflow/www/static/js/grid/context/autorefresh.tsx b/airflow/www/static/js/context/autorefresh.tsx
similarity index 93%
rename from airflow/www/static/js/grid/context/autorefresh.tsx
rename to airflow/www/static/js/context/autorefresh.tsx
index 6f4296c2df..d2582bef31 100644
--- a/airflow/www/static/js/grid/context/autorefresh.tsx
+++ b/airflow/www/static/js/context/autorefresh.tsx
@@ -20,10 +20,10 @@
 /* global localStorage, document */
 
 import React, {
-  useMemo, useContext, useState, useEffect, useCallback,
+  useMemo, useContext, useState, useEffect, useCallback, PropsWithChildren,
 } from 'react';
 
-import { getMetaValue } from 'app/utils';
+import { getMetaValue } from 'src/utils';
 
 const autoRefreshKey = 'disabledAutoRefresh';
 
@@ -38,11 +38,7 @@ const AutoRefreshContext = React.createContext({
   startRefresh: () => {},
 });
 
-interface Props {
-  children: React.ReactNode;
-}
-
-export const AutoRefreshProvider = ({ children }: Props) => {
+export const AutoRefreshProvider = ({ children }: PropsWithChildren) => {
   const [isPaused, setIsPaused] = useState(initialIsPaused);
   const isRefreshAllowed = !(isPaused || isRefreshDisabled);
   const initialState = isRefreshAllowed;
diff --git a/airflow/www/static/js/grid/context/containerRef.tsx b/airflow/www/static/js/context/containerRef.tsx
similarity index 89%
rename from airflow/www/static/js/grid/context/containerRef.tsx
rename to airflow/www/static/js/context/containerRef.tsx
index 4ddc036428..8689947210 100644
--- a/airflow/www/static/js/grid/context/containerRef.tsx
+++ b/airflow/www/static/js/context/containerRef.tsx
@@ -17,18 +17,14 @@
  * under the License.
  */
 
-import React, { useContext, useRef } from 'react';
+import React, { PropsWithChildren, useContext, useRef } from 'react';
 
 // eslint-disable-next-line max-len
 const ContainerRefContext = React.createContext<React.RefObject<HTMLDivElement> | undefined>(undefined);
 
-interface Props {
-  children: React.ReactNode;
-}
-
 // containerRef is necessary to render for tooltips, modals, and dialogs
 // This provider allows the containerRef to be accessed by any react component
-export const ContainerRefProvider = ({ children }: Props) => {
+export const ContainerRefProvider = ({ children }: PropsWithChildren) => {
   const containerRef = useRef<HTMLDivElement>(null);
 
   return (
diff --git a/airflow/www/static/js/grid/context/timezone.jsx b/airflow/www/static/js/context/timezone.jsx
similarity index 96%
rename from airflow/www/static/js/grid/context/timezone.jsx
rename to airflow/www/static/js/context/timezone.jsx
index 99fee1a0fe..002c0309e2 100644
--- a/airflow/www/static/js/grid/context/timezone.jsx
+++ b/airflow/www/static/js/context/timezone.jsx
@@ -22,7 +22,7 @@
 import React, {
   useContext, useEffect, useState, useMemo,
 } from 'react';
-import { TimezoneEvent } from '../../datetime_utils';
+import { TimezoneEvent } from '../datetime_utils';
 
 const TimezoneContext = React.createContext({ timezone: 'UTC' });
 
diff --git a/airflow/www/static/js/grid/components/InstanceTooltip.test.tsx b/airflow/www/static/js/dag/InstanceTooltip.test.tsx
similarity index 96%
rename from airflow/www/static/js/grid/components/InstanceTooltip.test.tsx
rename to airflow/www/static/js/dag/InstanceTooltip.test.tsx
index 15f2db2c7e..89c369ef72 100644
--- a/airflow/www/static/js/grid/components/InstanceTooltip.test.tsx
+++ b/airflow/www/static/js/dag/InstanceTooltip.test.tsx
@@ -22,8 +22,8 @@
 import React from 'react';
 import { render } from '@testing-library/react';
 
-import { Wrapper } from 'grid/utils/testUtils';
-import type { TaskState } from 'grid/types';
+import { Wrapper } from 'src/utils/testUtils';
+import type { TaskState } from 'src/types';
 
 import InstanceTooltip from './InstanceTooltip';
 
diff --git a/airflow/www/static/js/grid/components/InstanceTooltip.tsx b/airflow/www/static/js/dag/InstanceTooltip.tsx
similarity index 93%
rename from airflow/www/static/js/grid/components/InstanceTooltip.tsx
rename to airflow/www/static/js/dag/InstanceTooltip.tsx
index e556d0ddde..4d20a973fe 100644
--- a/airflow/www/static/js/grid/components/InstanceTooltip.tsx
+++ b/airflow/www/static/js/dag/InstanceTooltip.tsx
@@ -20,11 +20,10 @@
 import React from 'react';
 import { Box, Text } from '@chakra-ui/react';
 
-import { finalStatesMap } from 'app/utils';
-import { formatDuration, getDuration } from 'app/datetime_utils';
-import type { TaskInstance, Task } from 'grid/types';
-
-import Time from './Time';
+import { finalStatesMap } from 'src/utils';
+import { formatDuration, getDuration } from 'src/datetime_utils';
+import type { TaskInstance, Task } from 'src/types';
+import Time from 'src/components/Time';
 
 interface Props {
   group: Task;
diff --git a/airflow/www/static/js/grid/Main.tsx b/airflow/www/static/js/dag/Main.tsx
similarity index 91%
rename from airflow/www/static/js/grid/Main.tsx
rename to airflow/www/static/js/dag/Main.tsx
index bde36c2984..551548f0de 100644
--- a/airflow/www/static/js/grid/Main.tsx
+++ b/airflow/www/static/js/dag/Main.tsx
@@ -29,13 +29,14 @@ import {
 } from '@chakra-ui/react';
 import { isEmpty, debounce } from 'lodash';
 
+import useSelection from 'src/dag/useSelection';
+import { useGridData } from 'src/api';
+import { hoverDelay } from 'src/utils';
+
 import Details from './details';
-import useSelection from './utils/useSelection';
-import Grid from './Grid';
-import FilterBar from './FilterBar';
-import LegendRow from './LegendRow';
-import { useGridData } from './api';
-import { hoverDelay } from './utils';
+import Grid from './grid';
+import FilterBar from './nav/FilterBar';
+import LegendRow from './nav/LegendRow';
 
 const detailsPanelKey = 'hideDetailsPanel';
 
diff --git a/airflow/www/static/js/grid/components/StatusBox.tsx b/airflow/www/static/js/dag/StatusBox.tsx
similarity index 92%
rename from airflow/www/static/js/grid/components/StatusBox.tsx
rename to airflow/www/static/js/dag/StatusBox.tsx
index a4f936e5e9..55f0a00cf3 100644
--- a/airflow/www/static/js/grid/components/StatusBox.tsx
+++ b/airflow/www/static/js/dag/StatusBox.tsx
@@ -25,12 +25,12 @@ import {
   BoxProps,
 } from '@chakra-ui/react';
 
-import { useContainerRef } from 'grid/context/containerRef';
-import type { Task, TaskInstance, TaskState } from 'grid/types';
-import type { SelectionProps } from 'grid/utils/useSelection';
-import { hoverDelay } from 'grid/utils';
+import { useContainerRef } from 'src/context/containerRef';
+import type { Task, TaskInstance, TaskState } from 'src/types';
+import type { SelectionProps } from 'src/dag/useSelection';
+import { hoverDelay } from 'src/utils';
+import Tooltip from 'src/components/Tooltip';
 
-import Tooltip from './Tooltip';
 import InstanceTooltip from './InstanceTooltip';
 
 export const boxSize = 10;
diff --git a/airflow/www/static/js/grid/details/BreadcrumbText.tsx b/airflow/www/static/js/dag/details/BreadcrumbText.tsx
similarity index 100%
rename from airflow/www/static/js/grid/details/BreadcrumbText.tsx
rename to airflow/www/static/js/dag/details/BreadcrumbText.tsx
diff --git a/airflow/www/static/js/grid/details/content/ConfirmDialog.tsx b/airflow/www/static/js/dag/details/ConfirmDialog.tsx
similarity index 97%
rename from airflow/www/static/js/grid/details/content/ConfirmDialog.tsx
rename to airflow/www/static/js/dag/details/ConfirmDialog.tsx
index b9e2a212a6..c2533579ff 100644
--- a/airflow/www/static/js/grid/details/content/ConfirmDialog.tsx
+++ b/airflow/www/static/js/dag/details/ConfirmDialog.tsx
@@ -30,7 +30,7 @@ import {
   Text,
 } from '@chakra-ui/react';
 
-import { useContainerRef } from 'grid/context/containerRef';
+import { useContainerRef } from 'src/context/containerRef';
 
 interface Props {
   isOpen: boolean;
diff --git a/airflow/www/static/js/grid/details/content/Dag.jsx b/airflow/www/static/js/dag/details/Dag.jsx
similarity index 95%
rename from airflow/www/static/js/grid/details/content/Dag.jsx
rename to airflow/www/static/js/dag/details/Dag.jsx
index 38f7411b17..128c7dc4cb 100644
--- a/airflow/www/static/js/grid/details/content/Dag.jsx
+++ b/airflow/www/static/js/dag/details/Dag.jsx
@@ -31,11 +31,11 @@ import {
 } from '@chakra-ui/react';
 import { mean } from 'lodash';
 
-import { getDuration, formatDuration } from '../../../datetime_utils';
-import { finalStatesMap, getMetaValue } from '../../../utils';
+import { getDuration, formatDuration } from '../../datetime_utils';
+import { finalStatesMap, getMetaValue } from '../../utils';
 import { useTasks, useGridData } from '../../api';
 import Time from '../../components/Time';
-import { SimpleStatus } from '../../components/StatusBox';
+import { SimpleStatus } from '../StatusBox';
 
 const dagDetailsUrl = getMetaValue('dag_details_url');
 
diff --git a/airflow/www/static/js/grid/details/Header.tsx b/airflow/www/static/js/dag/details/Header.tsx
similarity index 95%
rename from airflow/www/static/js/grid/details/Header.tsx
rename to airflow/www/static/js/dag/details/Header.tsx
index 1aa6633017..a7e60e409a 100644
--- a/airflow/www/static/js/grid/details/Header.tsx
+++ b/airflow/www/static/js/dag/details/Header.tsx
@@ -27,10 +27,11 @@ import {
 import { MdPlayArrow, MdOutlineSchedule } from 'react-icons/md';
 import { RiArrowGoBackFill } from 'react-icons/ri';
 
-import { getMetaValue } from 'app/utils';
-import useSelection from 'grid/utils/useSelection';
-import Time from 'grid/components/Time';
-import { useTasks, useGridData } from 'grid/api';
+import { getMetaValue } from 'src/utils';
+import useSelection from 'src/dag/useSelection';
+import Time from 'src/components/Time';
+import { useTasks, useGridData } from 'src/api';
+
 import BreadcrumbText from './BreadcrumbText';
 
 const dagId = getMetaValue('dag_id');
diff --git a/airflow/www/static/js/grid/details/content/dagRun/ClearRun.jsx b/airflow/www/static/js/dag/details/dagRun/ClearRun.jsx
similarity index 97%
rename from airflow/www/static/js/grid/details/content/dagRun/ClearRun.jsx
rename to airflow/www/static/js/dag/details/dagRun/ClearRun.jsx
index 97c9438184..ff573ae920 100644
--- a/airflow/www/static/js/grid/details/content/dagRun/ClearRun.jsx
+++ b/airflow/www/static/js/dag/details/dagRun/ClearRun.jsx
@@ -22,7 +22,7 @@ import { Button, useDisclosure } from '@chakra-ui/react';
 
 import { useClearRun } from '../../../api';
 import ConfirmDialog from '../ConfirmDialog';
-import { getMetaValue } from '../../../../utils';
+import { getMetaValue } from '../../../utils';
 
 const canEdit = getMetaValue('can_edit') === 'True';
 
diff --git a/airflow/www/static/js/grid/details/content/dagRun/MarkFailedRun.jsx b/airflow/www/static/js/dag/details/dagRun/MarkFailedRun.jsx
similarity index 97%
rename from airflow/www/static/js/grid/details/content/dagRun/MarkFailedRun.jsx
rename to airflow/www/static/js/dag/details/dagRun/MarkFailedRun.jsx
index 3de973fd11..a97349d0ae 100644
--- a/airflow/www/static/js/grid/details/content/dagRun/MarkFailedRun.jsx
+++ b/airflow/www/static/js/dag/details/dagRun/MarkFailedRun.jsx
@@ -22,7 +22,7 @@ import { Button, useDisclosure } from '@chakra-ui/react';
 
 import { useMarkFailedRun } from '../../../api';
 import ConfirmDialog from '../ConfirmDialog';
-import { getMetaValue } from '../../../../utils';
+import { getMetaValue } from '../../../utils';
 
 const canEdit = getMetaValue('can_edit') === 'True';
 
diff --git a/airflow/www/static/js/grid/details/content/dagRun/MarkSuccessRun.jsx b/airflow/www/static/js/dag/details/dagRun/MarkSuccessRun.jsx
similarity index 97%
rename from airflow/www/static/js/grid/details/content/dagRun/MarkSuccessRun.jsx
rename to airflow/www/static/js/dag/details/dagRun/MarkSuccessRun.jsx
index 97ce9d439d..bebf776a38 100644
--- a/airflow/www/static/js/grid/details/content/dagRun/MarkSuccessRun.jsx
+++ b/airflow/www/static/js/dag/details/dagRun/MarkSuccessRun.jsx
@@ -22,7 +22,7 @@ import { Button, useDisclosure } from '@chakra-ui/react';
 
 import { useMarkSuccessRun } from '../../../api';
 import ConfirmDialog from '../ConfirmDialog';
-import { getMetaValue } from '../../../../utils';
+import { getMetaValue } from '../../../utils';
 
 const canEdit = getMetaValue('can_edit') === 'True';
 
diff --git a/airflow/www/static/js/grid/details/content/dagRun/QueueRun.jsx b/airflow/www/static/js/dag/details/dagRun/QueueRun.jsx
similarity index 97%
rename from airflow/www/static/js/grid/details/content/dagRun/QueueRun.jsx
rename to airflow/www/static/js/dag/details/dagRun/QueueRun.jsx
index b974988c33..1591055de3 100644
--- a/airflow/www/static/js/grid/details/content/dagRun/QueueRun.jsx
+++ b/airflow/www/static/js/dag/details/dagRun/QueueRun.jsx
@@ -22,7 +22,7 @@ import { Button, useDisclosure } from '@chakra-ui/react';
 
 import { useQueueRun } from '../../../api';
 import ConfirmDialog from '../ConfirmDialog';
-import { getMetaValue } from '../../../../utils';
+import { getMetaValue } from '../../../utils';
 
 const canEdit = getMetaValue('can_edit') === 'True';
 
diff --git a/airflow/www/static/js/grid/details/content/dagRun/index.tsx b/airflow/www/static/js/dag/details/dagRun/index.tsx
similarity index 92%
rename from airflow/www/static/js/grid/details/content/dagRun/index.tsx
rename to airflow/www/static/js/dag/details/dagRun/index.tsx
index b8b4120b96..f28c575871 100644
--- a/airflow/www/static/js/grid/details/content/dagRun/index.tsx
+++ b/airflow/www/static/js/dag/details/dagRun/index.tsx
@@ -29,13 +29,13 @@ import {
 import { MdPlayArrow, MdOutlineSchedule, MdOutlineAccountTree } from 'react-icons/md';
 import { RiArrowGoBackFill } from 'react-icons/ri';
 
-import { useGridData } from 'grid/api';
-import { appendSearchParams, getMetaValue } from 'app/utils';
-import type { DagRun as DagRunType } from 'grid/types';
-import { SimpleStatus } from 'grid/components/StatusBox';
-import { ClipboardText } from 'grid/components/Clipboard';
-import { formatDuration, getDuration } from 'app/datetime_utils';
-import Time from 'grid/components/Time';
+import { useGridData } from 'src/api';
+import { appendSearchParams, getMetaValue } from 'src/utils';
+import type { DagRun as DagRunType } from 'src/types';
+import { SimpleStatus } from 'src/dag/StatusBox';
+import { ClipboardText } from 'src/components/Clipboard';
+import { formatDuration, getDuration } from 'src/datetime_utils';
+import Time from 'src/components/Time';
 
 import MarkFailedRun from './MarkFailedRun';
 import MarkSuccessRun from './MarkSuccessRun';
diff --git a/airflow/www/static/js/grid/details/index.tsx b/airflow/www/static/js/dag/details/index.tsx
similarity index 88%
rename from airflow/www/static/js/grid/details/index.tsx
rename to airflow/www/static/js/dag/details/index.tsx
index b0ab5cd49b..9ba19cabf2 100644
--- a/airflow/www/static/js/grid/details/index.tsx
+++ b/airflow/www/static/js/dag/details/index.tsx
@@ -24,12 +24,12 @@ import {
   Divider,
 } from '@chakra-ui/react';
 
-import useSelection from 'grid/utils/useSelection';
+import useSelection from 'src/dag/useSelection';
 
 import Header from './Header';
-import TaskInstanceContent from './content/taskInstance';
-import DagRunContent from './content/dagRun';
-import DagContent from './content/Dag';
+import TaskInstanceContent from './taskInstance';
+import DagRunContent from './dagRun';
+import DagContent from './Dag';
 
 const Details = () => {
   const { selected: { runId, taskId } } = useSelection();
diff --git a/airflow/www/static/js/grid/details/content/taskInstance/Details.tsx b/airflow/www/static/js/dag/details/taskInstance/Details.tsx
similarity index 92%
rename from airflow/www/static/js/grid/details/content/taskInstance/Details.tsx
rename to airflow/www/static/js/dag/details/taskInstance/Details.tsx
index f5a0a77ecb..bb9faeba97 100644
--- a/airflow/www/static/js/grid/details/content/taskInstance/Details.tsx
+++ b/airflow/www/static/js/dag/details/taskInstance/Details.tsx
@@ -24,12 +24,12 @@ import {
   Flex,
 } from '@chakra-ui/react';
 
-import { finalStatesMap } from 'app/utils';
-import { getDuration, formatDuration } from 'app/datetime_utils';
-import { SimpleStatus } from 'grid/components/StatusBox';
-import Time from 'grid/components/Time';
-import { ClipboardText } from 'grid/components/Clipboard';
-import type { Task, TaskInstance, TaskState } from 'grid/types';
+import { finalStatesMap } from 'src/utils';
+import { getDuration, formatDuration } from 'src/datetime_utils';
+import { SimpleStatus } from 'src/dag/StatusBox';
+import Time from 'src/components/Time';
+import { ClipboardText } from 'src/components/Clipboard';
+import type { Task, TaskInstance, TaskState } from 'src/types';
 
 interface Props {
   instance: TaskInstance;
diff --git a/airflow/www/static/js/grid/details/content/taskInstance/ExtraLinks.tsx b/airflow/www/static/js/dag/details/taskInstance/ExtraLinks.tsx
similarity index 95%
rename from airflow/www/static/js/grid/details/content/taskInstance/ExtraLinks.tsx
rename to airflow/www/static/js/dag/details/taskInstance/ExtraLinks.tsx
index e2e0c1b122..580d8c9bca 100644
--- a/airflow/www/static/js/grid/details/content/taskInstance/ExtraLinks.tsx
+++ b/airflow/www/static/js/dag/details/taskInstance/ExtraLinks.tsx
@@ -25,8 +25,8 @@ import {
   Divider,
 } from '@chakra-ui/react';
 
-import { useExtraLinks } from 'grid/api';
-import type { Task } from 'grid/types';
+import { useExtraLinks } from 'src/api';
+import type { Task } from 'src/types';
 
 interface Props {
   dagId: string;
diff --git a/airflow/www/static/js/grid/details/content/taskInstance/Logs/LogLink.test.tsx b/airflow/www/static/js/dag/details/taskInstance/Logs/LogLink.test.tsx
similarity index 100%
rename from airflow/www/static/js/grid/details/content/taskInstance/Logs/LogLink.test.tsx
rename to airflow/www/static/js/dag/details/taskInstance/Logs/LogLink.test.tsx
diff --git a/airflow/www/static/js/grid/details/content/taskInstance/Logs/LogLink.tsx b/airflow/www/static/js/dag/details/taskInstance/Logs/LogLink.tsx
similarity index 92%
rename from airflow/www/static/js/grid/details/content/taskInstance/Logs/LogLink.tsx
rename to airflow/www/static/js/dag/details/taskInstance/Logs/LogLink.tsx
index 9beaeb639c..49683112b5 100644
--- a/airflow/www/static/js/grid/details/content/taskInstance/Logs/LogLink.tsx
+++ b/airflow/www/static/js/dag/details/taskInstance/Logs/LogLink.tsx
@@ -19,9 +19,9 @@
 
 import React from 'react';
 
-import { getMetaValue } from 'app/utils';
-import LinkButton from 'grid/components/LinkButton';
-import type { Dag, DagRun, TaskInstance } from 'grid/types';
+import { getMetaValue } from 'src/utils';
+import LinkButton from 'src/components/LinkButton';
+import type { Dag, DagRun, TaskInstance } from 'src/types';
 
 const logsWithMetadataUrl = getMetaValue('logs_with_metadata_url');
 const externalLogUrl = getMetaValue('external_log_url');
diff --git a/airflow/www/static/js/grid/details/content/taskInstance/Logs/index.test.tsx b/airflow/www/static/js/dag/details/taskInstance/Logs/index.test.tsx
similarity index 99%
rename from airflow/www/static/js/grid/details/content/taskInstance/Logs/index.test.tsx
rename to airflow/www/static/js/dag/details/taskInstance/Logs/index.test.tsx
index ce9a3c3295..1f748a1df7 100644
--- a/airflow/www/static/js/grid/details/content/taskInstance/Logs/index.test.tsx
+++ b/airflow/www/static/js/dag/details/taskInstance/Logs/index.test.tsx
@@ -23,7 +23,7 @@ import React from 'react';
 import { render, fireEvent } from '@testing-library/react';
 import type { UseQueryResult } from 'react-query';
 
-import * as useTaskLogModule from 'grid/api/useTaskLog';
+import * as useTaskLogModule from 'src/api/useTaskLog';
 
 import Logs from './index';
 
diff --git a/airflow/www/static/js/grid/details/content/taskInstance/Logs/index.tsx b/airflow/www/static/js/dag/details/taskInstance/Logs/index.tsx
similarity index 96%
rename from airflow/www/static/js/grid/details/content/taskInstance/Logs/index.tsx
rename to airflow/www/static/js/dag/details/taskInstance/Logs/index.tsx
index 8944001b16..b86e69f9d3 100644
--- a/airflow/www/static/js/grid/details/content/taskInstance/Logs/index.tsx
+++ b/airflow/www/static/js/dag/details/taskInstance/Logs/index.tsx
@@ -30,12 +30,12 @@ import {
   Checkbox,
 } from '@chakra-ui/react';
 
-import { getMetaValue } from 'app/utils';
-import useTaskLog from 'grid/api/useTaskLog';
-import LinkButton from 'grid/components/LinkButton';
-import { useTimezone } from 'grid/context/timezone';
-import type { Dag, DagRun, TaskInstance } from 'grid/types';
-import MultiSelect from 'grid/components/MultiSelect';
+import { getMetaValue } from 'src/utils';
+import useTaskLog from 'src/api/useTaskLog';
+import LinkButton from 'src/components/LinkButton';
+import { useTimezone } from 'src/context/timezone';
+import type { Dag, DagRun, TaskInstance } from 'src/types';
+import MultiSelect from 'src/components/MultiSelect';
 
 import LogLink from './LogLink';
 import { LogLevel, logLevelColorMapping, parseLogs } from './utils';
diff --git a/airflow/www/static/js/grid/details/content/taskInstance/Logs/utils.test.tsx b/airflow/www/static/js/dag/details/taskInstance/Logs/utils.test.tsx
similarity index 100%
rename from airflow/www/static/js/grid/details/content/taskInstance/Logs/utils.test.tsx
rename to airflow/www/static/js/dag/details/taskInstance/Logs/utils.test.tsx
diff --git a/airflow/www/static/js/grid/details/content/taskInstance/Logs/utils.ts b/airflow/www/static/js/dag/details/taskInstance/Logs/utils.ts
similarity index 97%
rename from airflow/www/static/js/grid/details/content/taskInstance/Logs/utils.ts
rename to airflow/www/static/js/dag/details/taskInstance/Logs/utils.ts
index ed6acd6e99..4a5b8b8664 100644
--- a/airflow/www/static/js/grid/details/content/taskInstance/Logs/utils.ts
+++ b/airflow/www/static/js/dag/details/taskInstance/Logs/utils.ts
@@ -19,7 +19,7 @@
 
 /* global moment */
 
-import { defaultFormatWithTZ } from 'app/datetime_utils';
+import { defaultFormatWithTZ } from 'src/datetime_utils';
 
 export enum LogLevel {
   DEBUG = 'DEBUG',
diff --git a/airflow/www/static/js/grid/details/content/taskInstance/MappedInstances.jsx b/airflow/www/static/js/dag/details/taskInstance/MappedInstances.jsx
similarity index 96%
rename from airflow/www/static/js/grid/details/content/taskInstance/MappedInstances.jsx
rename to airflow/www/static/js/dag/details/taskInstance/MappedInstances.jsx
index 13c03b0435..d50f2c1e6e 100644
--- a/airflow/www/static/js/grid/details/content/taskInstance/MappedInstances.jsx
+++ b/airflow/www/static/js/dag/details/taskInstance/MappedInstances.jsx
@@ -30,10 +30,10 @@ import {
   MdDetails, MdCode, MdSyncAlt, MdReorder,
 } from 'react-icons/md';
 
-import { getMetaValue } from '../../../../utils';
-import { formatDuration, getDuration } from '../../../../datetime_utils';
+import { getMetaValue } from '../../../utils';
+import { formatDuration, getDuration } from '../../../datetime_utils';
 import { useMappedInstances } from '../../../api';
-import { SimpleStatus } from '../../../components/StatusBox';
+import { SimpleStatus } from '../../StatusBox';
 import Table from '../../../components/Table';
 import Time from '../../../components/Time';
 
diff --git a/airflow/www/static/js/grid/details/content/taskInstance/Nav.tsx b/airflow/www/static/js/dag/details/taskInstance/Nav.tsx
similarity index 95%
rename from airflow/www/static/js/grid/details/content/taskInstance/Nav.tsx
rename to airflow/www/static/js/dag/details/taskInstance/Nav.tsx
index 0f7e5a0ab8..1a795961b2 100644
--- a/airflow/www/static/js/grid/details/content/taskInstance/Nav.tsx
+++ b/airflow/www/static/js/dag/details/taskInstance/Nav.tsx
@@ -23,9 +23,9 @@ import {
   Divider,
 } from '@chakra-ui/react';
 
-import { getMetaValue, appendSearchParams } from 'app/utils';
-import LinkButton from 'grid/components/LinkButton';
-import type { Task, DagRun } from 'grid/types';
+import { getMetaValue, appendSearchParams } from 'src/utils';
+import LinkButton from 'src/components/LinkButton';
+import type { Task, DagRun } from 'src/types';
 
 const dagId = getMetaValue('dag_id') || '';
 const isK8sExecutor = getMetaValue('k8s_or_k8scelery_executor') === 'True';
diff --git a/airflow/www/static/js/grid/details/content/taskInstance/index.tsx b/airflow/www/static/js/dag/details/taskInstance/index.tsx
similarity index 97%
rename from airflow/www/static/js/grid/details/content/taskInstance/index.tsx
rename to airflow/www/static/js/dag/details/taskInstance/index.tsx
index cfc34f7c5d..34d1924a03 100644
--- a/airflow/www/static/js/grid/details/content/taskInstance/index.tsx
+++ b/airflow/www/static/js/dag/details/taskInstance/index.tsx
@@ -33,9 +33,9 @@ import {
   TabPanel,
 } from '@chakra-ui/react';
 
-import { useGridData, useTasks } from 'grid/api';
-import { getMetaValue } from 'app/utils';
-import type { Task, DagRun } from 'grid/types';
+import { useGridData, useTasks } from 'src/api';
+import { getMetaValue } from 'src/utils';
+import type { Task, DagRun } from 'src/types';
 
 import RunAction from './taskActions/Run';
 import ClearAction from './taskActions/Clear';
diff --git a/airflow/www/static/js/grid/details/content/taskInstance/taskActions/ActionButton.jsx b/airflow/www/static/js/dag/details/taskInstance/taskActions/ActionButton.jsx
similarity index 100%
rename from airflow/www/static/js/grid/details/content/taskInstance/taskActions/ActionButton.jsx
rename to airflow/www/static/js/dag/details/taskInstance/taskActions/ActionButton.jsx
diff --git a/airflow/www/static/js/grid/details/content/taskInstance/taskActions/Clear.jsx b/airflow/www/static/js/dag/details/taskInstance/taskActions/Clear.jsx
similarity index 98%
rename from airflow/www/static/js/grid/details/content/taskInstance/taskActions/Clear.jsx
rename to airflow/www/static/js/dag/details/taskInstance/taskActions/Clear.jsx
index 3bbfafdcec..e9de6626de 100644
--- a/airflow/www/static/js/grid/details/content/taskInstance/taskActions/Clear.jsx
+++ b/airflow/www/static/js/dag/details/taskInstance/taskActions/Clear.jsx
@@ -28,7 +28,7 @@ import {
 import ActionButton from './ActionButton';
 import ConfirmDialog from '../../ConfirmDialog';
 import { useClearTask } from '../../../../api';
-import { getMetaValue } from '../../../../../utils';
+import { getMetaValue } from '../../../../utils';
 
 const canEdit = getMetaValue('can_edit') === 'True';
 
diff --git a/airflow/www/static/js/grid/details/content/taskInstance/taskActions/MarkFailed.jsx b/airflow/www/static/js/dag/details/taskInstance/taskActions/MarkFailed.jsx
similarity index 98%
rename from airflow/www/static/js/grid/details/content/taskInstance/taskActions/MarkFailed.jsx
rename to airflow/www/static/js/dag/details/taskInstance/taskActions/MarkFailed.jsx
index 6dd0ac13e2..baa5282661 100644
--- a/airflow/www/static/js/grid/details/content/taskInstance/taskActions/MarkFailed.jsx
+++ b/airflow/www/static/js/dag/details/taskInstance/taskActions/MarkFailed.jsx
@@ -28,7 +28,7 @@ import {
 import ActionButton from './ActionButton';
 import { useConfirmMarkTask, useMarkFailedTask } from '../../../../api';
 import ConfirmDialog from '../../ConfirmDialog';
-import { getMetaValue } from '../../../../../utils';
+import { getMetaValue } from '../../../../utils';
 
 const canEdit = getMetaValue('can_edit') === 'True';
 
diff --git a/airflow/www/static/js/grid/details/content/taskInstance/taskActions/MarkSuccess.jsx b/airflow/www/static/js/dag/details/taskInstance/taskActions/MarkSuccess.jsx
similarity index 98%
rename from airflow/www/static/js/grid/details/content/taskInstance/taskActions/MarkSuccess.jsx
rename to airflow/www/static/js/dag/details/taskInstance/taskActions/MarkSuccess.jsx
index 56f2b9efe3..49174cda88 100644
--- a/airflow/www/static/js/grid/details/content/taskInstance/taskActions/MarkSuccess.jsx
+++ b/airflow/www/static/js/dag/details/taskInstance/taskActions/MarkSuccess.jsx
@@ -28,7 +28,7 @@ import {
 import ConfirmDialog from '../../ConfirmDialog';
 import ActionButton from './ActionButton';
 import { useMarkSuccessTask, useConfirmMarkTask } from '../../../../api';
-import { getMetaValue } from '../../../../../utils';
+import { getMetaValue } from '../../../../utils';
 
 const canEdit = getMetaValue('can_edit') === 'True';
 
diff --git a/airflow/www/static/js/grid/details/content/taskInstance/taskActions/Run.jsx b/airflow/www/static/js/dag/details/taskInstance/taskActions/Run.jsx
similarity index 98%
rename from airflow/www/static/js/grid/details/content/taskInstance/taskActions/Run.jsx
rename to airflow/www/static/js/dag/details/taskInstance/taskActions/Run.jsx
index 19559a8266..16bebc3161 100644
--- a/airflow/www/static/js/grid/details/content/taskInstance/taskActions/Run.jsx
+++ b/airflow/www/static/js/dag/details/taskInstance/taskActions/Run.jsx
@@ -25,7 +25,7 @@ import {
 } from '@chakra-ui/react';
 
 import { useRunTask } from '../../../../api';
-import { getMetaValue } from '../../../../../utils';
+import { getMetaValue } from '../../../../utils';
 
 const canEdit = getMetaValue('can_edit') === 'True';
 
diff --git a/airflow/www/static/js/grid/ResetRoot.tsx b/airflow/www/static/js/dag/grid/ResetRoot.tsx
similarity index 96%
rename from airflow/www/static/js/grid/ResetRoot.tsx
rename to airflow/www/static/js/dag/grid/ResetRoot.tsx
index 6e8ded9d89..2aa743645e 100644
--- a/airflow/www/static/js/grid/ResetRoot.tsx
+++ b/airflow/www/static/js/dag/grid/ResetRoot.tsx
@@ -20,7 +20,7 @@
 import React from 'react';
 import { Button, Link } from '@chakra-ui/react';
 
-import { getMetaValue } from 'app/utils';
+import { getMetaValue } from 'src/utils';
 
 const root = getMetaValue('root');
 const url = getMetaValue('grid_url_no_root');
diff --git a/airflow/www/static/js/grid/components/TaskName.test.tsx b/airflow/www/static/js/dag/grid/TaskName.test.tsx
similarity index 96%
rename from airflow/www/static/js/grid/components/TaskName.test.tsx
rename to airflow/www/static/js/dag/grid/TaskName.test.tsx
index d1c334afa4..b5e869add5 100644
--- a/airflow/www/static/js/grid/components/TaskName.test.tsx
+++ b/airflow/www/static/js/dag/grid/TaskName.test.tsx
@@ -22,7 +22,7 @@
 import React from 'react';
 import { render } from '@testing-library/react';
 
-import { ChakraWrapper } from 'grid/utils/testUtils';
+import { ChakraWrapper } from 'src/utils/testUtils';
 
 import TaskName from './TaskName';
 
diff --git a/airflow/www/static/js/grid/components/TaskName.tsx b/airflow/www/static/js/dag/grid/TaskName.tsx
similarity index 100%
rename from airflow/www/static/js/grid/components/TaskName.tsx
rename to airflow/www/static/js/dag/grid/TaskName.tsx
diff --git a/airflow/www/static/js/grid/ToggleGroups.tsx b/airflow/www/static/js/dag/grid/ToggleGroups.tsx
similarity index 98%
rename from airflow/www/static/js/grid/ToggleGroups.tsx
rename to airflow/www/static/js/dag/grid/ToggleGroups.tsx
index 9936042a86..34d35625d4 100644
--- a/airflow/www/static/js/grid/ToggleGroups.tsx
+++ b/airflow/www/static/js/dag/grid/ToggleGroups.tsx
@@ -20,7 +20,8 @@
 import React from 'react';
 import { Flex, IconButton } from '@chakra-ui/react';
 import { MdExpand, MdCompress } from 'react-icons/md';
-import type { Task } from './types';
+
+import type { Task } from 'src/types';
 
 const getGroupIds = (groups: Task[]) => {
   const groupIds: string[] = [];
diff --git a/airflow/www/static/js/grid/dagRuns/Bar.tsx b/airflow/www/static/js/dag/grid/dagRuns/Bar.tsx
similarity index 95%
rename from airflow/www/static/js/grid/dagRuns/Bar.tsx
rename to airflow/www/static/js/dag/grid/dagRuns/Bar.tsx
index 854338c204..302dac7983 100644
--- a/airflow/www/static/js/grid/dagRuns/Bar.tsx
+++ b/airflow/www/static/js/dag/grid/dagRuns/Bar.tsx
@@ -32,10 +32,10 @@ import {
 import { MdPlayArrow } from 'react-icons/md';
 import { RiArrowGoBackFill } from 'react-icons/ri';
 
-import { useContainerRef } from 'grid/context/containerRef';
-import Time from 'grid/components/Time';
-import type { SelectionProps } from 'grid/utils/useSelection';
-import { hoverDelay } from 'grid/utils';
+import { useContainerRef } from 'src/context/containerRef';
+import Time from 'src/components/Time';
+import type { SelectionProps } from 'src/dag/useSelection';
+import { hoverDelay } from 'src/utils';
 
 import DagRunTooltip from './Tooltip';
 import type { RunWithDuration } from '.';
diff --git a/airflow/www/static/js/grid/dagRuns/Tooltip.tsx b/airflow/www/static/js/dag/grid/dagRuns/Tooltip.tsx
similarity index 94%
rename from airflow/www/static/js/grid/dagRuns/Tooltip.tsx
rename to airflow/www/static/js/dag/grid/dagRuns/Tooltip.tsx
index d511e8f001..ae52d9bdaa 100644
--- a/airflow/www/static/js/grid/dagRuns/Tooltip.tsx
+++ b/airflow/www/static/js/dag/grid/dagRuns/Tooltip.tsx
@@ -20,8 +20,8 @@
 import React from 'react';
 import { Box, Text } from '@chakra-ui/react';
 
-import { formatDuration } from 'app/datetime_utils';
-import Time from 'grid/components/Time';
+import { formatDuration } from 'src/datetime_utils';
+import Time from 'src/components/Time';
 
 import type { RunWithDuration } from './index';
 
diff --git a/airflow/www/static/js/grid/dagRuns/index.test.tsx b/airflow/www/static/js/dag/grid/dagRuns/index.test.tsx
similarity index 96%
rename from airflow/www/static/js/grid/dagRuns/index.test.tsx
rename to airflow/www/static/js/dag/grid/dagRuns/index.test.tsx
index 5a927b7005..a03d380030 100644
--- a/airflow/www/static/js/grid/dagRuns/index.test.tsx
+++ b/airflow/www/static/js/dag/grid/dagRuns/index.test.tsx
@@ -23,9 +23,9 @@ import React from 'react';
 import { render } from '@testing-library/react';
 import moment from 'moment-timezone';
 
-import { TableWrapper } from 'grid/utils/testUtils';
-import * as useGridDataModule from 'grid/api/useGridData';
-import type { DagRun } from 'grid/types';
+import { TableWrapper } from 'src/utils/testUtils';
+import * as useGridDataModule from 'src/api/useGridData';
+import type { DagRun } from 'src/types';
 
 import DagRuns from './index';
 
diff --git a/airflow/www/static/js/grid/dagRuns/index.tsx b/airflow/www/static/js/dag/grid/dagRuns/index.tsx
similarity index 94%
rename from airflow/www/static/js/grid/dagRuns/index.tsx
rename to airflow/www/static/js/dag/grid/dagRuns/index.tsx
index 1867443692..b0e01e553f 100644
--- a/airflow/www/static/js/grid/dagRuns/index.tsx
+++ b/airflow/www/static/js/dag/grid/dagRuns/index.tsx
@@ -29,10 +29,10 @@ import {
   BoxProps,
 } from '@chakra-ui/react';
 
-import { useGridData } from 'grid/api';
-import { getDuration, formatDuration } from 'app/datetime_utils';
-import useSelection from 'grid/utils/useSelection';
-import type { DagRun } from 'grid/types';
+import { useGridData } from 'src/api';
+import { getDuration, formatDuration } from 'src/datetime_utils';
+import useSelection from 'src/dag/useSelection';
+import type { DagRun } from 'src/types';
 
 import DagRunBar from './Bar';
 
diff --git a/airflow/www/static/js/grid/Grid.test.jsx b/airflow/www/static/js/dag/grid/index.test.jsx
similarity index 98%
rename from airflow/www/static/js/grid/Grid.test.jsx
rename to airflow/www/static/js/dag/grid/index.test.jsx
index 9f16fe53d6..67a5cc55d8 100644
--- a/airflow/www/static/js/grid/Grid.test.jsx
+++ b/airflow/www/static/js/dag/grid/index.test.jsx
@@ -23,9 +23,9 @@
 import React from 'react';
 import { render, fireEvent, waitFor } from '@testing-library/react';
 
-import Grid from './Grid';
-import { Wrapper } from './utils/testUtils';
-import * as useGridDataModule from './api/useGridData';
+import Grid from '.';
+import { Wrapper } from '../../utils/testUtils';
+import * as useGridDataModule from '../../api/useGridData';
 
 const mockGridData = {
   groups: {
diff --git a/airflow/www/static/js/grid/Grid.tsx b/airflow/www/static/js/dag/grid/index.tsx
similarity index 96%
rename from airflow/www/static/js/grid/Grid.tsx
rename to airflow/www/static/js/dag/grid/index.tsx
index 6de3d0ecc2..215eb82fbe 100644
--- a/airflow/www/static/js/grid/Grid.tsx
+++ b/airflow/www/static/js/dag/grid/index.tsx
@@ -30,13 +30,15 @@ import {
 } from '@chakra-ui/react';
 
 import { MdReadMore } from 'react-icons/md';
-import { useGridData } from './api';
+
+import { useGridData } from 'src/api';
+import { getMetaValue } from 'src/utils';
+import AutoRefresh from 'src/components/AutoRefresh';
+
 import renderTaskRows from './renderTaskRows';
 import ResetRoot from './ResetRoot';
 import DagRuns from './dagRuns';
 import ToggleGroups from './ToggleGroups';
-import { getMetaValue } from '../utils';
-import AutoRefresh from './AutoRefresh';
 
 const dagId = getMetaValue('dag_id');
 
diff --git a/airflow/www/static/js/grid/renderTaskRows.test.tsx b/airflow/www/static/js/dag/grid/renderTaskRows.test.tsx
similarity index 97%
rename from airflow/www/static/js/grid/renderTaskRows.test.tsx
rename to airflow/www/static/js/dag/grid/renderTaskRows.test.tsx
index 4f5fabc920..a0ef4b5cae 100644
--- a/airflow/www/static/js/grid/renderTaskRows.test.tsx
+++ b/airflow/www/static/js/dag/grid/renderTaskRows.test.tsx
@@ -22,9 +22,10 @@
 import React from 'react';
 import { render } from '@testing-library/react';
 
+import { TableWrapper } from 'src/utils/testUtils';
+import type { Task } from 'src/types';
+
 import renderTaskRows from './renderTaskRows';
-import { TableWrapper } from './utils/testUtils';
-import type { Task } from './types';
 
 describe('Test renderTaskRows', () => {
   test('Renders name and task instance', () => {
diff --git a/airflow/www/static/js/grid/renderTaskRows.tsx b/airflow/www/static/js/dag/grid/renderTaskRows.tsx
similarity index 95%
rename from airflow/www/static/js/grid/renderTaskRows.tsx
rename to airflow/www/static/js/dag/grid/renderTaskRows.tsx
index 42ee268d3f..24ee8531c2 100644
--- a/airflow/www/static/js/grid/renderTaskRows.tsx
+++ b/airflow/www/static/js/dag/grid/renderTaskRows.tsx
@@ -26,11 +26,11 @@ import {
   useTheme,
 } from '@chakra-ui/react';
 
-import StatusBox, { boxSize, boxSizePx } from './components/StatusBox';
-import TaskName from './components/TaskName';
+import useSelection, { SelectionProps } from 'src/dag/useSelection';
+import type { Task, DagRun } from 'src/types';
 
-import useSelection, { SelectionProps } from './utils/useSelection';
-import type { Task, DagRun } from './types';
+import StatusBox, { boxSize, boxSizePx } from '../StatusBox';
+import TaskName from './TaskName';
 
 const boxPadding = 3;
 const boxPaddingPx = `${boxPadding}px`;
diff --git a/airflow/www/static/js/grid/components/LinkButton.test.tsx b/airflow/www/static/js/dag/index.tsx
similarity index 58%
rename from airflow/www/static/js/grid/components/LinkButton.test.tsx
rename to airflow/www/static/js/dag/index.tsx
index 0fc9181a58..32ae3f686d 100644
--- a/airflow/www/static/js/grid/components/LinkButton.test.tsx
+++ b/airflow/www/static/js/dag/index.tsx
@@ -17,22 +17,32 @@
  * under the License.
  */
 
-/* global describe, test, expect */
+/* global document */
 
 import React from 'react';
-import { render } from '@testing-library/react';
+import { createRoot } from 'react-dom/client';
+import createCache from '@emotion/cache';
 
-import LinkButton from './LinkButton';
+import App from 'src/App';
 
-describe('Test LinkButton Component.', () => {
-  test('LinkButton should be rendered as a link.', () => {
-    const { getByText, container } = render(
-      <LinkButton>
-        <div>The link</div>
-      </LinkButton>,
-    );
+import Main from './Main';
 
-    expect(getByText('The link')).toBeDefined();
-    expect(container.querySelector('a')).not.toBeNull();
-  });
+// create shadowRoot
+const root = document.querySelector('#root');
+const shadowRoot = root?.attachShadow({ mode: 'open' });
+const cache = createCache({
+  container: shadowRoot,
+  key: 'c',
 });
+const mainElement = document.getElementById('react-container');
+
+if (mainElement) {
+  shadowRoot?.appendChild(mainElement);
+
+  const reactRoot = createRoot(mainElement);
+  reactRoot.render(
+    <App cache={cache}>
+      <Main />
+    </App>,
+  );
+}
diff --git a/airflow/www/static/js/grid/FilterBar.jsx b/airflow/www/static/js/dag/nav/FilterBar.jsx
similarity index 95%
rename from airflow/www/static/js/grid/FilterBar.jsx
rename to airflow/www/static/js/dag/nav/FilterBar.jsx
index 8776be4c7f..2373e7636d 100644
--- a/airflow/www/static/js/grid/FilterBar.jsx
+++ b/airflow/www/static/js/dag/nav/FilterBar.jsx
@@ -27,10 +27,10 @@ import {
   Select,
 } from '@chakra-ui/react';
 import React from 'react';
-import { useTimezone } from './context/timezone';
-import { isoFormatWithoutTZ } from '../datetime_utils';
 
-import useFilters from './utils/useFilters';
+import { useTimezone } from '../../context/timezone';
+import { isoFormatWithoutTZ } from '../../datetime_utils';
+import useFilters from '../useFilters';
 
 const FilterBar = () => {
   const {
diff --git a/airflow/www/static/js/grid/LegendRow.test.tsx b/airflow/www/static/js/dag/nav/LegendRow.test.tsx
similarity index 100%
rename from airflow/www/static/js/grid/LegendRow.test.tsx
rename to airflow/www/static/js/dag/nav/LegendRow.test.tsx
diff --git a/airflow/www/static/js/grid/LegendRow.tsx b/airflow/www/static/js/dag/nav/LegendRow.tsx
similarity index 100%
rename from airflow/www/static/js/grid/LegendRow.tsx
rename to airflow/www/static/js/dag/nav/LegendRow.tsx
diff --git a/airflow/www/static/js/grid/utils/useFilters.js b/airflow/www/static/js/dag/useFilters.js
similarity index 100%
rename from airflow/www/static/js/grid/utils/useFilters.js
rename to airflow/www/static/js/dag/useFilters.js
diff --git a/airflow/www/static/js/grid/utils/useFilters.test.jsx b/airflow/www/static/js/dag/useFilters.test.jsx
similarity index 98%
rename from airflow/www/static/js/grid/utils/useFilters.test.jsx
rename to airflow/www/static/js/dag/useFilters.test.jsx
index e8873d3a64..9bbecfe8b9 100644
--- a/airflow/www/static/js/grid/utils/useFilters.test.jsx
+++ b/airflow/www/static/js/dag/useFilters.test.jsx
@@ -20,7 +20,7 @@
 /* global describe, expect, jest, test, moment */
 import { act, renderHook } from '@testing-library/react';
 
-import { RouterWrapper } from './testUtils';
+import { RouterWrapper } from '../utils/testUtils';
 
 const date = new Date();
 date.setMilliseconds(0);
diff --git a/airflow/www/static/js/grid/utils/useSelection.test.tsx b/airflow/www/static/js/dag/useSelection.test.tsx
similarity index 94%
rename from airflow/www/static/js/grid/utils/useSelection.test.tsx
rename to airflow/www/static/js/dag/useSelection.test.tsx
index a1fd90d79e..3cfe61d5db 100644
--- a/airflow/www/static/js/grid/utils/useSelection.test.tsx
+++ b/airflow/www/static/js/dag/useSelection.test.tsx
@@ -19,17 +19,13 @@
 
 /* global describe, test, expect */
 
-import React from 'react';
+import React, { PropsWithChildren } from 'react';
 import { act, renderHook } from '@testing-library/react';
 import { MemoryRouter } from 'react-router-dom';
 
 import useSelection from './useSelection';
 
-interface Props {
-  children: React.ReactNode;
-}
-
-const Wrapper = ({ children }: Props) => (
+const Wrapper = ({ children }: PropsWithChildren) => (
   <MemoryRouter>
     {children}
   </MemoryRouter>
diff --git a/airflow/www/static/js/grid/utils/useSelection.ts b/airflow/www/static/js/dag/useSelection.ts
similarity index 100%
rename from airflow/www/static/js/grid/utils/useSelection.ts
rename to airflow/www/static/js/dag/useSelection.ts
diff --git a/airflow/www/static/js/grid/utils/index.ts b/airflow/www/static/js/grid/utils/index.ts
deleted file mode 100644
index 165de55616..0000000000
--- a/airflow/www/static/js/grid/utils/index.ts
+++ /dev/null
@@ -1,26 +0,0 @@
-/* eslint-disable import/prefer-default-export */
-/*!
- * 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.
- */
-
-// Delay in ms for various hover actions
-const hoverDelay = 200;
-
-export {
-  hoverDelay,
-};
diff --git a/airflow/www/static/js/grid/index.d.ts b/airflow/www/static/js/index.d.ts
similarity index 100%
rename from airflow/www/static/js/grid/index.d.ts
rename to airflow/www/static/js/index.d.ts
diff --git a/airflow/www/static/js/grid/theme.ts b/airflow/www/static/js/theme.ts
similarity index 100%
rename from airflow/www/static/js/grid/theme.ts
rename to airflow/www/static/js/theme.ts
diff --git a/airflow/www/static/js/grid/types/index.ts b/airflow/www/static/js/types/index.ts
similarity index 100%
rename from airflow/www/static/js/grid/types/index.ts
rename to airflow/www/static/js/types/index.ts
diff --git a/airflow/www/static/js/utils.js b/airflow/www/static/js/utils/index.ts
similarity index 79%
rename from airflow/www/static/js/utils.js
rename to airflow/www/static/js/utils/index.ts
index 8bb563b053..dc08bfb8db 100644
--- a/airflow/www/static/js/utils.js
+++ b/airflow/www/static/js/utils/index.ts
@@ -17,9 +17,10 @@
  * under the License.
  */
 
-/* global document */
+// Delay in ms for various hover actions
+const hoverDelay = 200;
 
-export function getMetaValue(name) {
+function getMetaValue(name: string) {
   const elem = document.querySelector(`meta[name="${name}"]`);
   if (!elem) {
     return null;
@@ -27,7 +28,7 @@ export function getMetaValue(name) {
   return elem.getAttribute('content');
 }
 
-export const finalStatesMap = () => new Map([
+const finalStatesMap = () => new Map([
   ['success', 0],
   ['failed', 0],
   ['upstream_failed', 0],
@@ -42,7 +43,15 @@ export const finalStatesMap = () => new Map([
   ['no_status', 0],
 ]);
 
-export const appendSearchParams = (url, params) => {
+const appendSearchParams = (url: string | null, params: URLSearchParams | string) => {
+  if (!url) return '';
   const separator = url.includes('?') ? '&' : '?';
   return `${url}${separator}${params}`;
 };
+
+export {
+  hoverDelay,
+  finalStatesMap,
+  getMetaValue,
+  appendSearchParams,
+};
diff --git a/airflow/www/static/js/grid/utils/testUtils.jsx b/airflow/www/static/js/utils/testUtils.jsx
similarity index 100%
rename from airflow/www/static/js/grid/utils/testUtils.jsx
rename to airflow/www/static/js/utils/testUtils.jsx
diff --git a/airflow/www/static/js/grid/utils/useErrorToast.js b/airflow/www/static/js/utils/useErrorToast.js
similarity index 100%
rename from airflow/www/static/js/grid/utils/useErrorToast.js
rename to airflow/www/static/js/utils/useErrorToast.js
diff --git a/airflow/www/static/js/grid/utils/useErrorToast.test.jsx b/airflow/www/static/js/utils/useErrorToast.test.jsx
similarity index 100%
rename from airflow/www/static/js/grid/utils/useErrorToast.test.jsx
rename to airflow/www/static/js/utils/useErrorToast.test.jsx
diff --git a/airflow/www/tsconfig.json b/airflow/www/tsconfig.json
index b744f7cc5a..9267bbde3a 100644
--- a/airflow/www/tsconfig.json
+++ b/airflow/www/tsconfig.json
@@ -36,8 +36,7 @@
     "types": ["node", "jest"],
     "baseUrl": ".",
     "paths": { // Be sure to update aliases in webpack.config.js and jest.config.js
-      "app/*": ["static/js/*"],
-      "grid/*": ["static/js/grid/*"],
+      "src/*": ["static/js/*"],
     },
   },
   "include": [
diff --git a/airflow/www/webpack.config.js b/airflow/www/webpack.config.js
index c1e0fffb5b..b1379ddaa0 100644
--- a/airflow/www/webpack.config.js
+++ b/airflow/www/webpack.config.js
@@ -73,7 +73,7 @@ const config = {
     task: `${JS_DIR}/task.js`,
     taskInstances: `${JS_DIR}/task_instances.js`,
     tiLog: `${JS_DIR}/ti_log.js`,
-    grid: [`${JS_DIR}/grid/index.jsx`],
+    grid: `${JS_DIR}/dag/index.tsx`,
     calendar: [`${CSS_DIR}/calendar.css`, `${JS_DIR}/calendar.js`],
     durationChart: `${JS_DIR}/duration_chart.js`,
     trigger: `${JS_DIR}/trigger.js`,
@@ -89,8 +89,7 @@ const config = {
   },
   resolve: {
     alias: { // Be sure to update aliases in jest.config.js and tsconfig.json
-      app: path.resolve(__dirname, 'static/js'),
-      grid: path.resolve(__dirname, 'static/js/grid'),
+      src: path.resolve(__dirname, 'static/js'),
     },
     extensions: [
       '.js',