forked from sombochea/verdaccio-ui
fix: package list refresh based on logged-in user (#415)
* fix: package list refresh based on logged-in user description: In `pages/home/Home.tsx` now monitoring any change in a user log-in/out which will trigger a new `API.request` to get the _packages_ from the Verdaccio-server. This is done by creating a `useEffect` on **isUserLoggedIn**. Code has been transplanted from `App/App.tsx` including the use of the Loading component during the XHR. The use of **packages** was removed from other components as no longer needed and tests updated. Resolves issue #414 * fix: package list refresh based on logged-in user description: In `pages/home/Home.tsx` now monitoring any change in a user log-in/out which will trigger a new `API.request` to get the _packages_ from the Verdaccio-server. This is done by creating a `useEffect` on **isUserLoggedIn**. Code has been transplanted from `App/App.tsx` including the use of the Loading component during the XHR. The use of **packages** was removed from other components as no longer needed and tests updated. Test snapshots updated Resolves issue #414 Co-authored-by: Juan Picado @jotadeveloper <juanpicado19@gmail.com>
This commit is contained in:
parent
ee1c3f08eb
commit
222ffed022
@ -5,11 +5,9 @@ import { Router } from 'react-router-dom';
|
|||||||
|
|
||||||
import storage from '../utils/storage';
|
import storage from '../utils/storage';
|
||||||
import { isTokenExpire } from '../utils/login';
|
import { isTokenExpire } from '../utils/login';
|
||||||
import API from '../utils/api';
|
|
||||||
import Header from '../components/Header';
|
import Header from '../components/Header';
|
||||||
import Footer from '../components/Footer';
|
import Footer from '../components/Footer';
|
||||||
import Box from '../muiComponents/Box';
|
import Box from '../muiComponents/Box';
|
||||||
import Loading from '../components/Loading';
|
|
||||||
import StyleBaseline from '../design-tokens/StyleBaseline';
|
import StyleBaseline from '../design-tokens/StyleBaseline';
|
||||||
import { Theme } from '../design-tokens/theme';
|
import { Theme } from '../design-tokens/theme';
|
||||||
|
|
||||||
@ -33,11 +31,9 @@ const StyledBoxContent = styled(Box)<{ theme?: Theme }>(({ theme }) => ({
|
|||||||
/* eslint-disable react-hooks/exhaustive-deps */
|
/* eslint-disable react-hooks/exhaustive-deps */
|
||||||
const App: React.FC = () => {
|
const App: React.FC = () => {
|
||||||
const [user, setUser] = useState();
|
const [user, setUser] = useState();
|
||||||
const [packages, setPackages] = useState([]);
|
|
||||||
const [isLoading, setIsLoading] = useState(true);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Logouts user
|
* Logout user
|
||||||
* Required by: <Header />
|
* Required by: <Header />
|
||||||
*/
|
*/
|
||||||
const logout = () => {
|
const logout = () => {
|
||||||
@ -59,46 +55,26 @@ const App: React.FC = () => {
|
|||||||
setUser({ username });
|
setUser({ username });
|
||||||
};
|
};
|
||||||
|
|
||||||
const loadOnHandler = async () => {
|
|
||||||
try {
|
|
||||||
const packages = await API.request('packages', 'GET');
|
|
||||||
// FIXME add correct type for package
|
|
||||||
setPackages(packages as never[]);
|
|
||||||
} catch (error) {
|
|
||||||
// FIXME: add dialog
|
|
||||||
console.error({
|
|
||||||
title: 'Warning',
|
|
||||||
message: `Unable to load package list: ${error.message}`,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
setIsLoading(false);
|
|
||||||
};
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
checkUserAlreadyLoggedIn();
|
checkUserAlreadyLoggedIn();
|
||||||
loadOnHandler();
|
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<StyleBaseline />
|
<StyleBaseline />
|
||||||
<StyledBox display="flex" flexDirection="column" height="100%">
|
<StyledBox display="flex" flexDirection="column" height="100%">
|
||||||
{isLoading ? (
|
|
||||||
<Loading />
|
|
||||||
) : (
|
|
||||||
<>
|
<>
|
||||||
<Router history={history}>
|
<Router history={history}>
|
||||||
<AppContextProvider packages={packages} user={user}>
|
<AppContextProvider user={user}>
|
||||||
<Header />
|
<Header />
|
||||||
<StyledBoxContent flexGrow={1}>
|
<StyledBoxContent flexGrow={1}>
|
||||||
|
{/* eslint-disable-next-line react/jsx-max-depth */}
|
||||||
<AppRoute />
|
<AppRoute />
|
||||||
</StyledBoxContent>
|
</StyledBoxContent>
|
||||||
</AppContextProvider>
|
</AppContextProvider>
|
||||||
</Router>
|
</Router>
|
||||||
<Footer />
|
<Footer />
|
||||||
</>
|
</>
|
||||||
)}
|
|
||||||
</StyledBox>
|
</StyledBox>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
@ -3,7 +3,6 @@ import { createContext } from 'react';
|
|||||||
export interface AppProps {
|
export interface AppProps {
|
||||||
user?: User;
|
user?: User;
|
||||||
scope: string;
|
scope: string;
|
||||||
packages: any[];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface User {
|
export interface User {
|
||||||
|
@ -3,15 +3,13 @@ import React, { useState, useEffect } from 'react';
|
|||||||
import AppContext, { AppProps, User } from './AppContext';
|
import AppContext, { AppProps, User } from './AppContext';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
packages: any[];
|
|
||||||
user?: User;
|
user?: User;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* eslint-disable react-hooks/exhaustive-deps */
|
/* eslint-disable react-hooks/exhaustive-deps */
|
||||||
const AppContextProvider: React.FC<Props> = ({ children, packages, user }) => {
|
const AppContextProvider: React.FC<Props> = ({ children, user }) => {
|
||||||
const [state, setState] = useState<AppProps>({
|
const [state, setState] = useState<AppProps>({
|
||||||
scope: window.VERDACCIO_SCOPE || '',
|
scope: window.VERDACCIO_SCOPE || '',
|
||||||
packages,
|
|
||||||
user,
|
user,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -22,13 +20,6 @@ const AppContextProvider: React.FC<Props> = ({ children, packages, user }) => {
|
|||||||
});
|
});
|
||||||
}, [user]);
|
}, [user]);
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
setState({
|
|
||||||
...state,
|
|
||||||
packages,
|
|
||||||
});
|
|
||||||
}, [packages]);
|
|
||||||
|
|
||||||
const setUser = (user?: User) => {
|
const setUser = (user?: User) => {
|
||||||
setState({
|
setState({
|
||||||
...state,
|
...state,
|
||||||
|
@ -30,7 +30,7 @@ const AppRoute: React.FC = () => {
|
|||||||
throw Error('The app Context was not correct used');
|
throw Error('The app Context was not correct used');
|
||||||
}
|
}
|
||||||
|
|
||||||
const { user, packages } = appContext;
|
const { user } = appContext;
|
||||||
|
|
||||||
const isUserLoggedIn = user && user.username;
|
const isUserLoggedIn = user && user.username;
|
||||||
|
|
||||||
@ -39,7 +39,7 @@ const AppRoute: React.FC = () => {
|
|||||||
<Suspense fallback={<Loading />}>
|
<Suspense fallback={<Loading />}>
|
||||||
<Switch>
|
<Switch>
|
||||||
<ReactRouterDomRoute exact={true} path={Route.ROOT}>
|
<ReactRouterDomRoute exact={true} path={Route.ROOT}>
|
||||||
<HomePage isUserLoggedIn={!!isUserLoggedIn} packages={packages || []} />
|
<HomePage isUserLoggedIn={!!isUserLoggedIn} />
|
||||||
</ReactRouterDomRoute>
|
</ReactRouterDomRoute>
|
||||||
<ReactRouterDomRoute exact={true} path={Route.PACKAGE}>
|
<ReactRouterDomRoute exact={true} path={Route.PACKAGE}>
|
||||||
<VersionContextProvider>
|
<VersionContextProvider>
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -18,7 +18,7 @@ describe('<Header /> component with logged in state', () => {
|
|||||||
test('should load the component in logged out state', () => {
|
test('should load the component in logged out state', () => {
|
||||||
const { container, queryByTestId, getByText } = render(
|
const { container, queryByTestId, getByText } = render(
|
||||||
<Router>
|
<Router>
|
||||||
<AppContextProvider packages={props.packages}>
|
<AppContextProvider>
|
||||||
<Header />
|
<Header />
|
||||||
</AppContextProvider>
|
</AppContextProvider>
|
||||||
</Router>
|
</Router>
|
||||||
@ -32,7 +32,7 @@ describe('<Header /> component with logged in state', () => {
|
|||||||
test('should load the component in logged in state', () => {
|
test('should load the component in logged in state', () => {
|
||||||
const { container, getByTestId, queryByText } = render(
|
const { container, getByTestId, queryByText } = render(
|
||||||
<Router>
|
<Router>
|
||||||
<AppContextProvider packages={props.packages} user={props.user}>
|
<AppContextProvider user={props.user}>
|
||||||
<Header />
|
<Header />
|
||||||
</AppContextProvider>
|
</AppContextProvider>
|
||||||
</Router>
|
</Router>
|
||||||
@ -46,7 +46,7 @@ describe('<Header /> component with logged in state', () => {
|
|||||||
test('should open login dialog', async () => {
|
test('should open login dialog', async () => {
|
||||||
const { getByText } = render(
|
const { getByText } = render(
|
||||||
<Router>
|
<Router>
|
||||||
<AppContextProvider packages={props.packages}>
|
<AppContextProvider>
|
||||||
<Header />
|
<Header />
|
||||||
</AppContextProvider>
|
</AppContextProvider>
|
||||||
</Router>
|
</Router>
|
||||||
@ -61,7 +61,7 @@ describe('<Header /> component with logged in state', () => {
|
|||||||
test('should logout the user', async () => {
|
test('should logout the user', async () => {
|
||||||
const { getByText, getByTestId } = render(
|
const { getByText, getByTestId } = render(
|
||||||
<Router>
|
<Router>
|
||||||
<AppContextProvider packages={props.packages} user={props.user}>
|
<AppContextProvider user={props.user}>
|
||||||
<Header />
|
<Header />
|
||||||
</AppContextProvider>
|
</AppContextProvider>
|
||||||
</Router>
|
</Router>
|
||||||
@ -79,7 +79,7 @@ describe('<Header /> component with logged in state', () => {
|
|||||||
test("The question icon should open a new tab of verdaccio's website - installation doc", () => {
|
test("The question icon should open a new tab of verdaccio's website - installation doc", () => {
|
||||||
const { getByTestId } = render(
|
const { getByTestId } = render(
|
||||||
<Router>
|
<Router>
|
||||||
<AppContextProvider packages={props.packages} user={props.user}>
|
<AppContextProvider user={props.user}>
|
||||||
<Header />
|
<Header />
|
||||||
</AppContextProvider>
|
</AppContextProvider>
|
||||||
</Router>
|
</Router>
|
||||||
@ -92,7 +92,7 @@ describe('<Header /> component with logged in state', () => {
|
|||||||
test('should open the registrationInfo modal when clicking on the info icon', async () => {
|
test('should open the registrationInfo modal when clicking on the info icon', async () => {
|
||||||
const { getByTestId } = render(
|
const { getByTestId } = render(
|
||||||
<Router>
|
<Router>
|
||||||
<AppContextProvider packages={props.packages} user={props.user}>
|
<AppContextProvider user={props.user}>
|
||||||
<Header />
|
<Header />
|
||||||
</AppContextProvider>
|
</AppContextProvider>
|
||||||
</Router>
|
</Router>
|
||||||
@ -109,7 +109,7 @@ describe('<Header /> component with logged in state', () => {
|
|||||||
test('should close the registrationInfo modal when clicking on the button close', async () => {
|
test('should close the registrationInfo modal when clicking on the button close', async () => {
|
||||||
const { getByTestId, getByText, queryByTestId } = render(
|
const { getByTestId, getByText, queryByTestId } = render(
|
||||||
<Router>
|
<Router>
|
||||||
<AppContextProvider packages={props.packages} user={props.user}>
|
<AppContextProvider user={props.user}>
|
||||||
<Header />
|
<Header />
|
||||||
</AppContextProvider>
|
</AppContextProvider>
|
||||||
</Router>
|
</Router>
|
||||||
|
@ -8,7 +8,6 @@ import LoginDialog from './LoginDialog';
|
|||||||
|
|
||||||
const appContextValue: AppContextProps = {
|
const appContextValue: AppContextProps = {
|
||||||
scope: '',
|
scope: '',
|
||||||
packages: [],
|
|
||||||
setUser: jest.fn(),
|
setUser: jest.fn(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,17 +1,35 @@
|
|||||||
import React from 'react';
|
import React, { useEffect, useState } from 'react';
|
||||||
|
|
||||||
import { PackageList } from '../../components/PackageList';
|
import { PackageList } from '../../components/PackageList';
|
||||||
import { PackageInterface } from '../../components/Package/Package';
|
import API from '../../utils/api';
|
||||||
|
import Loading from '../../components/Loading';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
isUserLoggedIn: boolean;
|
isUserLoggedIn: boolean;
|
||||||
packages: PackageInterface[];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const Home: React.FC<Props> = ({ packages }) => (
|
const Home: React.FC<Props> = ({ isUserLoggedIn }) => {
|
||||||
<div className="container content">
|
const [packages, setPackages] = useState([]);
|
||||||
<PackageList packages={packages} />
|
const [isLoading, setIsLoading] = useState(true);
|
||||||
</div>
|
const loadPackages = async () => {
|
||||||
);
|
try {
|
||||||
|
const packages = await API.request('packages', 'GET');
|
||||||
|
// FIXME add correct type for package
|
||||||
|
setPackages(packages as never[]);
|
||||||
|
} catch (error) {
|
||||||
|
// FIXME: add dialog
|
||||||
|
console.error({
|
||||||
|
title: 'Warning',
|
||||||
|
message: `Unable to load package list: ${error.message}`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
setIsLoading(false);
|
||||||
|
};
|
||||||
|
useEffect(() => {
|
||||||
|
loadPackages().then();
|
||||||
|
}, [isUserLoggedIn]);
|
||||||
|
|
||||||
|
return <div className="container content">{isLoading ? <Loading /> : <PackageList packages={packages} />}</div>;
|
||||||
|
};
|
||||||
|
|
||||||
export default Home;
|
export default Home;
|
||||||
|
Loading…
Reference in New Issue
Block a user