Skip to content

Commit

Permalink
frontend: Use react-query for backend requests, api v2
Browse files Browse the repository at this point in the history
This commit replaces fetch calls with react-query, and introduces v2 of
api client code, simplifying the way we do requests to the backend

Signed-off-by: Oleksandr Dubenko <oldubenko@microsoft.com>
  • Loading branch information
sniok committed Sep 17, 2024
1 parent 6de5b59 commit 2415b97
Show file tree
Hide file tree
Showing 43 changed files with 1,521 additions and 570 deletions.
20 changes: 17 additions & 3 deletions frontend/.storybook/preview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,34 @@ import { initialize, mswLoader } from 'msw-storybook-addon';
import '../src/index.css';
import { Title, Subtitle, Description, Primary, Controls } from '@storybook/blocks';
import { baseMocks } from './baseMocks';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';

// https://github.com/mswjs/msw-storybook-addon
initialize({
onUnhandledRequest: 'warn',
waitUntilReady: true,
});

export const queryClient = new QueryClient({
defaultOptions: {
queries: {
refetchOnMount: 'always',
staleTime: 0,
retry: false,
gcTime: 0,
},
},
});

const withThemeProvider = (Story: any, context: any) => {
const theme = themesConf[context.globals.backgrounds?.value === '#1f1f1f' ? 'dark' : 'light'];

const ourThemeProvider = (
<ThemeProvider theme={theme}>
<Story {...context} />
</ThemeProvider>
<QueryClientProvider client={queryClient}>
<ThemeProvider theme={theme}>
<Story {...context} />
</ThemeProvider>
</QueryClientProvider>
);
return ourThemeProvider;
};
Expand Down
55 changes: 55 additions & 0 deletions frontend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
"@mui/x-tree-view": "^6.17.0",
"@reduxjs/toolkit": "^1.9.3",
"@storybook/blocks": "^8.2.9",
"@tanstack/react-query": "^5.51.24",
"@tanstack/react-query-devtools": "^5.51.24",
"@testing-library/dom": "^10.1.0",
"@testing-library/react": "^16.0.0",
"@types/glob": "^8.1.0",
Expand Down
22 changes: 19 additions & 3 deletions frontend/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import './i18n/config';
import './components/App/icons';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { ReactQueryDevtools } from '@tanstack/react-query-devtools';
import React from 'react';
import { I18nextProvider } from 'react-i18next';
import { Provider } from 'react-redux';
Expand Down Expand Up @@ -29,13 +31,27 @@ function AppWithRedux(props: React.PropsWithChildren<{}>) {
);
}

const queryClient = new QueryClient({
defaultOptions: {
queries: {
staleTime: 3 * 60_000,
refetchOnWindowFocus: false,
},
},
});
const queryDevtoolsEnabled = false;

function App() {
return (
<ErrorBoundary fallback={<ErrorComponent />}>
<Provider store={store}>
<AppWithRedux>
<AppContainer />
</AppWithRedux>
<QueryClientProvider client={queryClient}>
{queryDevtoolsEnabled && <ReactQueryDevtools initialIsOpen={false} />}

<AppWithRedux>
<AppContainer />
</AppWithRedux>
</QueryClientProvider>
</Provider>
</ErrorBoundary>
);
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/App/Home/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ export default function Home() {
return null;
}

return <HomeComponent clusters={clusters} />;
return <HomeComponent clusters={clusters} key={Object.keys(clusters).join('')} />;
}

interface HomeComponentProps {
Expand Down
91 changes: 33 additions & 58 deletions frontend/src/components/Sidebar/VersionButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import DialogActions from '@mui/material/DialogActions';
import DialogContent from '@mui/material/DialogContent';
import DialogTitle from '@mui/material/DialogTitle';
import { styled, useTheme } from '@mui/system';
import { useQuery } from '@tanstack/react-query';
import { useSnackbar } from 'notistack';
import React from 'react';
import { useTranslation } from 'react-i18next';
Expand All @@ -27,7 +28,6 @@ const VersionIcon = styled(Icon)({
export default function VersionButton() {
const isSidebarOpen = useTypedSelector(state => state.sidebar.isSidebarOpen);
const { enqueueSnackbar } = useSnackbar();
const [clusterVersion, setClusterVersion] = React.useState<StringDict | null>(null);
const cluster = useCluster();
const theme = useTheme();
const [open, setOpen] = React.useState(false);
Expand Down Expand Up @@ -62,68 +62,43 @@ export default function VersionButton() {
];
}

React.useEffect(
() => {
let stillAlive = true;
function fetchVersion() {
getVersion()
.then((results: StringDict) => {
if (!stillAlive) {
return;
}

setClusterVersion(results);
let versionChange = 0;
if (clusterVersion && results && results.gitVersion) {
versionChange = semver.compare(results.gitVersion, clusterVersion.gitVersion);
const { data: clusterVersion } = useQuery({
placeholderData: null as any,
queryKey: ['version', cluster ?? ''],
queryFn: () => {
return getVersion()
.then((results: StringDict) => {
let versionChange = 0;
if (clusterVersion && results && results.gitVersion) {
versionChange = semver.compare(results.gitVersion, clusterVersion.gitVersion);

let msg = '';
if (versionChange > 0) {
msg = t('translation|Cluster version upgraded to {{ gitVersion }}', {
gitVersion: results.gitVersion,
});
} else if (versionChange < 0) {
msg = t('translation|Cluster version downgraded to {{ gitVersion }}', {
gitVersion: results.gitVersion,
});
}

if (msg) {
enqueueSnackbar(msg, {
key: 'version',
preventDuplicate: true,
autoHideDuration: versionSnackbarHideTimeout,
variant: 'info',
});
}
let msg = '';
if (versionChange > 0) {
msg = t('translation|Cluster version upgraded to {{ gitVersion }}', {
gitVersion: results.gitVersion,
});
} else if (versionChange < 0) {
msg = t('translation|Cluster version downgraded to {{ gitVersion }}', {
gitVersion: results.gitVersion,
});
}
})
.catch((error: Error) => console.error('Getting the cluster version:', error));
}

if (!clusterVersion) {
fetchVersion();
}

const intervalHandler = setInterval(() => {
fetchVersion();
}, versionFetchInterval);
if (msg) {
enqueueSnackbar(msg, {
key: 'version',
preventDuplicate: true,
autoHideDuration: versionSnackbarHideTimeout,
variant: 'info',
});
}
}

return function cleanup() {
stillAlive = false;
clearInterval(intervalHandler);
};
return results;
})
.catch((error: Error) => console.error('Getting the cluster version:', error));
},
// eslint-disable-next-line
[clusterVersion]
);

// Use the location to make sure the version is changed, as it depends on the cluster
// (defined in the URL ATM).
// @todo: Update this if the active cluster management is changed.
React.useEffect(() => {
setClusterVersion(null);
}, [cluster]);
refetchInterval: versionFetchInterval,
});

function handleClose() {
setOpen(false);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@
<desc />
<defs>
<clippath
id="recharts1-clip"
id="recharts3-clip"
>
<rect
height="102"
Expand Down Expand Up @@ -191,7 +191,7 @@
<desc />
<defs>
<clippath
id="recharts3-clip"
id="recharts5-clip"
>
<rect
height="102"
Expand Down Expand Up @@ -293,7 +293,7 @@
<desc />
<defs>
<clippath
id="recharts5-clip"
id="recharts1-clip"
>
<rect
height="102"
Expand All @@ -308,18 +308,33 @@
tabindex="0"
>
<g
class="recharts-layer"
class="recharts-layer recharts-pie-sector"
tabindex="-1"
/>
<g
class="recharts-layer recharts-pie-sector"
tabindex="-1"
/>
<g
class="recharts-layer recharts-pie-sector"
tabindex="-1"
>
<g
class="recharts-layer recharts-pie-sector"
tabindex="-1"
/>
<g
class="recharts-layer recharts-pie-sector"
tabindex="-1"
/>
<g
class="recharts-layer recharts-pie-sector"
<path
class="recharts-sector"
cx="61"
cy="61"
d="M 61,16.199999999999996
A 44.800000000000004,44.800000000000004,0,
1,1,
60.99921809249515,16.20000000682343
L 60.999410078712856,27.200000005148027
A 33.800000000000004,33.800000000000004,0,
1,0,
61,27.199999999999996 Z"
fill="#e0e0e0"
name="total"
role="img"
stroke="#e0e0e0"
tabindex="-1"
/>
</g>
Expand Down
12 changes: 6 additions & 6 deletions frontend/src/components/common/NamespacesAutocomplete.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import Checkbox from '@mui/material/Checkbox';
import { useTheme } from '@mui/material/styles';
import TextField from '@mui/material/TextField';
import Typography from '@mui/material/Typography';
import React from 'react';
import React, { useMemo } from 'react';
import { useTranslation } from 'react-i18next';
import { useDispatch } from 'react-redux';
import { useHistory, useLocation } from 'react-router-dom';
Expand Down Expand Up @@ -154,11 +154,11 @@ export function NamespacesAutocomplete() {
function NamespacesFromClusterAutocomplete(
props: Omit<PureNamespacesAutocompleteProps, 'namespaceNames'>
) {
const [namespaceNames, setNamespaceNames] = React.useState<string[]>([]);

Namespace.useApiList((namespaces: Namespace[]) => {
setNamespaceNames(namespaces.map(namespace => namespace.metadata.name));
});
const [namespacesList] = Namespace.useList();
const namespaceNames = useMemo(
() => namespacesList?.map(namespace => namespace.metadata.name) ?? [],
[namespacesList]
);

return <PureNamespacesAutocomplete namespaceNames={namespaceNames} {...props} />;
}
Loading

0 comments on commit 2415b97

Please sign in to comment.