1
0
mirror of https://github.com/SomboChea/ui synced 2024-11-24 06:54:27 +07:00

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:
coolsp 2020-01-12 22:21:29 +01:00 committed by Juan Picado @jotadeveloper
parent ee1c3f08eb
commit 222ffed022
8 changed files with 1319 additions and 128 deletions

View File

@ -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}>
) : ( <AppContextProvider user={user}>
<> <Header />
<Router history={history}> <StyledBoxContent flexGrow={1}>
<AppContextProvider packages={packages} user={user}> {/* eslint-disable-next-line react/jsx-max-depth */}
<Header /> <AppRoute />
<StyledBoxContent flexGrow={1}> </StyledBoxContent>
<AppRoute /> </AppContextProvider>
</StyledBoxContent> </Router>
</AppContextProvider> <Footer />
</Router> </>
<Footer />
</>
)}
</StyledBox> </StyledBox>
</> </>
); );

View File

@ -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 {

View File

@ -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,

View File

@ -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

View File

@ -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>

View File

@ -8,7 +8,6 @@ import LoginDialog from './LoginDialog';
const appContextValue: AppContextProps = { const appContextValue: AppContextProps = {
scope: '', scope: '',
packages: [],
setUser: jest.fn(), setUser: jest.fn(),
}; };

View File

@ -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;