mirror of
https://github.com/shlinkio/shlink-web-client.git
synced 2024-12-22 17:10:26 +03:00
Remove sidebar reducer, which couple web-client with web-component
This commit is contained in:
parent
c3b6ce34ba
commit
5a9640bd57
10 changed files with 38 additions and 87 deletions
|
@ -3,8 +3,8 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
|||
import { useToggle } from '@shlinkio/shlink-frontend-kit';
|
||||
import classNames from 'classnames';
|
||||
import type { FC, ReactNode } from 'react';
|
||||
import { useEffect } from 'react';
|
||||
import { Navigate, Route, Routes, useLocation } from 'react-router-dom';
|
||||
import { Fragment, useEffect, useMemo } from 'react';
|
||||
import { BrowserRouter, Navigate, Route, Routes, useInRouterContext, useLocation } from 'react-router-dom';
|
||||
import { AsideMenu } from './common/AsideMenu';
|
||||
import { useFeature } from './utils/features';
|
||||
import { useSwipeable } from './utils/helpers/hooks';
|
||||
|
@ -30,6 +30,9 @@ export const Main = (
|
|||
): FC<MainProps> => ({ createNotFound }) => {
|
||||
const location = useLocation();
|
||||
const routesPrefix = useRoutesPrefix();
|
||||
const inRouterContext = useInRouterContext();
|
||||
const Wrapper = useMemo(() => (inRouterContext ? Fragment : BrowserRouter), [inRouterContext]);
|
||||
|
||||
const [sidebarVisible, toggleSidebar, showSidebar, hideSidebar] = useToggle();
|
||||
useEffect(() => hideSidebar(), [location]);
|
||||
|
||||
|
@ -37,10 +40,10 @@ export const Main = (
|
|||
const burgerClasses = classNames('menu-layout__burger-icon', { 'menu-layout__burger-icon--active': sidebarVisible });
|
||||
const swipeableProps = useSwipeable(showSidebar, hideSidebar);
|
||||
|
||||
// FIXME Check if this is already wrapped by a router, and wrap otherwise
|
||||
// FIXME Check if this works when not currently wrapped in a router
|
||||
|
||||
return (
|
||||
<>
|
||||
<Wrapper basename={routesPrefix}>
|
||||
<FontAwesomeIcon icon={burgerIcon} className={burgerClasses} onClick={toggleSidebar} />
|
||||
|
||||
<div {...swipeableProps} className="menu-layout__swipeable">
|
||||
|
@ -67,6 +70,6 @@ export const Main = (
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
</Wrapper>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -1,17 +1,22 @@
|
|||
import classNames from 'classnames';
|
||||
import { useMemo } from 'react';
|
||||
import { useLocation } from 'react-router-dom';
|
||||
import type { SelectedServer } from '../servers/data';
|
||||
import type { Sidebar } from './reducers/sidebar';
|
||||
import { ShlinkVersions } from './ShlinkVersions';
|
||||
import './ShlinkVersionsContainer.scss';
|
||||
|
||||
export interface ShlinkVersionsContainerProps {
|
||||
export type ShlinkVersionsContainerProps = {
|
||||
selectedServer: SelectedServer;
|
||||
sidebar: Sidebar;
|
||||
}
|
||||
};
|
||||
|
||||
const SHLINK_CONTAINER_PATH_PATTERN = /^\/server\/[a-zA-Z0-9-]*\/(?!edit)/;
|
||||
|
||||
export const ShlinkVersionsContainer = ({ selectedServer }: ShlinkVersionsContainerProps) => {
|
||||
const { pathname } = useLocation();
|
||||
const withPadding = useMemo(() => SHLINK_CONTAINER_PATH_PATTERN.test(pathname), [pathname]);
|
||||
|
||||
export const ShlinkVersionsContainer = ({ selectedServer, sidebar }: ShlinkVersionsContainerProps) => {
|
||||
const classes = classNames('text-center', {
|
||||
'shlink-versions-container--with-sidebar': sidebar.sidebarPresent,
|
||||
'shlink-versions-container--with-sidebar': withPadding,
|
||||
});
|
||||
|
||||
return (
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import type { Settings, ShlinkWebComponentType, TagColorsStorage } from '@shlinkio/shlink-web-component';
|
||||
import type { FC } from 'react';
|
||||
import { useEffect } from 'react';
|
||||
import type { ShlinkApiClientBuilder } from '../api/services/ShlinkApiClientBuilder';
|
||||
import { isReachableServer } from '../servers/data';
|
||||
import { withSelectedServer } from '../servers/helpers/withSelectedServer';
|
||||
|
@ -8,8 +7,6 @@ import { NotFound } from './NotFound';
|
|||
import './ShlinkWebComponentContainer.scss';
|
||||
|
||||
interface ShlinkWebComponentContainerProps {
|
||||
sidebarPresent: Function;
|
||||
sidebarNotPresent: Function;
|
||||
settings: Settings;
|
||||
}
|
||||
|
||||
|
@ -18,17 +15,10 @@ export const ShlinkWebComponentContainer = (
|
|||
tagColorsStorage: TagColorsStorage,
|
||||
ShlinkWebComponent: ShlinkWebComponentType,
|
||||
ServerError: FC,
|
||||
) => withSelectedServer<ShlinkWebComponentContainerProps>((
|
||||
{ selectedServer, sidebarNotPresent, sidebarPresent, settings },
|
||||
) => {
|
||||
) => withSelectedServer<ShlinkWebComponentContainerProps>(({ selectedServer, settings }) => {
|
||||
const selectedServerIsReachable = isReachableServer(selectedServer);
|
||||
const routesPrefix = selectedServerIsReachable ? `/server/${selectedServer.id}` : '';
|
||||
|
||||
useEffect(() => {
|
||||
selectedServerIsReachable && sidebarPresent();
|
||||
return () => sidebarNotPresent();
|
||||
}, []);
|
||||
|
||||
if (!selectedServerIsReachable) {
|
||||
return <ServerError />;
|
||||
}
|
||||
|
|
|
@ -1,26 +0,0 @@
|
|||
import { createSlice } from '@reduxjs/toolkit';
|
||||
|
||||
// FIXME This is only used for some components to have extra paddings/styles if existing section has a side menu
|
||||
// Now that's basically the route which renders ShlinkWebComponent, so maybe there's some way to re-think this
|
||||
// logic, and perhaps get rid of a reducer just for that
|
||||
|
||||
export interface Sidebar {
|
||||
sidebarPresent: boolean;
|
||||
}
|
||||
|
||||
const initialState: Sidebar = {
|
||||
sidebarPresent: false,
|
||||
};
|
||||
|
||||
const { actions, reducer } = createSlice({
|
||||
name: 'shlink/sidebar',
|
||||
initialState,
|
||||
reducers: {
|
||||
sidebarPresent: () => ({ sidebarPresent: true }),
|
||||
sidebarNotPresent: () => ({ sidebarPresent: false }),
|
||||
},
|
||||
});
|
||||
|
||||
export const { sidebarPresent, sidebarNotPresent } = actions;
|
||||
|
||||
export const sidebarReducer = reducer;
|
|
@ -5,7 +5,6 @@ import { withoutSelectedServer } from '../../servers/helpers/withoutSelectedServ
|
|||
import { ErrorHandler } from '../ErrorHandler';
|
||||
import { Home } from '../Home';
|
||||
import { MainHeader } from '../MainHeader';
|
||||
import { sidebarNotPresent, sidebarPresent } from '../reducers/sidebar';
|
||||
import { ScrollToTop } from '../ScrollToTop';
|
||||
import { ShlinkVersionsContainer } from '../ShlinkVersionsContainer';
|
||||
import { ShlinkWebComponentContainer } from '../ShlinkWebComponentContainer';
|
||||
|
@ -36,17 +35,10 @@ export const provideServices = (bottle: Bottle, connect: ConnectDecorator) => {
|
|||
'ShlinkWebComponent',
|
||||
'ServerError',
|
||||
);
|
||||
bottle.decorator('ShlinkWebComponentContainer', connect(
|
||||
['selectedServer', 'settings'],
|
||||
['selectServer', 'sidebarPresent', 'sidebarNotPresent'],
|
||||
));
|
||||
bottle.decorator('ShlinkWebComponentContainer', connect(['selectedServer', 'settings'], ['selectServer']));
|
||||
|
||||
bottle.serviceFactory('ShlinkVersionsContainer', () => ShlinkVersionsContainer);
|
||||
bottle.decorator('ShlinkVersionsContainer', connect(['selectedServer', 'sidebar']));
|
||||
bottle.decorator('ShlinkVersionsContainer', connect(['selectedServer']));
|
||||
|
||||
bottle.serviceFactory('ErrorHandler', ErrorHandler, 'window', 'console');
|
||||
|
||||
// Actions
|
||||
bottle.serviceFactory('sidebarPresent', () => sidebarPresent);
|
||||
bottle.serviceFactory('sidebarNotPresent', () => sidebarNotPresent);
|
||||
};
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import type { Settings } from '@shlinkio/shlink-web-component';
|
||||
import type { Sidebar } from '../common/reducers/sidebar';
|
||||
import type { SelectedServer, ServersMap } from '../servers/data';
|
||||
|
||||
export interface ShlinkState {
|
||||
|
@ -7,7 +6,6 @@ export interface ShlinkState {
|
|||
selectedServer: SelectedServer;
|
||||
settings: Settings;
|
||||
appUpdated: boolean;
|
||||
sidebar: Sidebar;
|
||||
}
|
||||
|
||||
export type ConnectDecorator = (props: string[] | null, actions?: string[]) => any;
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import { combineReducers } from '@reduxjs/toolkit';
|
||||
import type { IContainer } from 'bottlejs';
|
||||
import { appUpdatesReducer } from '../app/reducers/appUpdates';
|
||||
import { sidebarReducer } from '../common/reducers/sidebar';
|
||||
import type { ShlinkState } from '../container/types';
|
||||
import { serversReducer } from '../servers/reducers/servers';
|
||||
import { settingsReducer } from '../settings/reducers/settings';
|
||||
|
@ -11,5 +10,4 @@ export const initReducers = (container: IContainer) => combineReducers<ShlinkSta
|
|||
servers: serversReducer,
|
||||
selectedServer: container.selectedServerReducer,
|
||||
settings: settingsReducer,
|
||||
sidebar: sidebarReducer,
|
||||
});
|
||||
|
|
|
@ -1,16 +1,25 @@
|
|||
import { render } from '@testing-library/react';
|
||||
import { fromPartial } from '@total-typescript/shoehorn';
|
||||
import type { Sidebar } from '../../src/common/reducers/sidebar';
|
||||
import { createMemoryHistory } from 'history';
|
||||
import { Router } from 'react-router-dom';
|
||||
import { ShlinkVersionsContainer } from '../../src/common/ShlinkVersionsContainer';
|
||||
|
||||
describe('<ShlinkVersionsContainer />', () => {
|
||||
const setUp = (sidebar: Sidebar) => render(
|
||||
<ShlinkVersionsContainer selectedServer={fromPartial({})} sidebar={sidebar} />,
|
||||
);
|
||||
const setUp = (activeRoute: string) => {
|
||||
const history = createMemoryHistory();
|
||||
history.push(activeRoute);
|
||||
|
||||
return render(
|
||||
<Router location={history.location} navigator={history}>
|
||||
<ShlinkVersionsContainer selectedServer={fromPartial({})} />
|
||||
</Router>,
|
||||
);
|
||||
};
|
||||
|
||||
it.each([
|
||||
[{ sidebarPresent: false }, 'text-center'],
|
||||
[{ sidebarPresent: true }, 'text-center shlink-versions-container--with-sidebar'],
|
||||
['/something', 'text-center'],
|
||||
['/server/foo/edit', 'text-center'],
|
||||
['/server/foo/bar', 'text-center shlink-versions-container--with-sidebar'],
|
||||
])('renders proper col classes based on sidebar status', (sidebar, expectedClasses) => {
|
||||
const { container } = setUp(sidebar);
|
||||
expect(container.firstChild).toHaveAttribute('class', `${expectedClasses}`);
|
||||
|
|
|
@ -17,13 +17,7 @@ describe('<ShlinkWebComponentContainer />', () => {
|
|||
() => <>ServerError</>,
|
||||
);
|
||||
const setUp = (selectedServer: SelectedServer) => render(
|
||||
<ShlinkWebComponentContainer
|
||||
sidebarNotPresent={vi.fn()}
|
||||
sidebarPresent={vi.fn()}
|
||||
selectServer={vi.fn()}
|
||||
selectedServer={selectedServer}
|
||||
settings={{}}
|
||||
/>,
|
||||
<ShlinkWebComponentContainer selectServer={vi.fn()} selectedServer={selectedServer} settings={{}} />,
|
||||
);
|
||||
|
||||
beforeEach(() => {
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
import { sidebarNotPresent, sidebarPresent, sidebarReducer } from '../../../src/common/reducers/sidebar';
|
||||
|
||||
describe('sidebarReducer', () => {
|
||||
describe('reducer', () => {
|
||||
it.each([
|
||||
[sidebarPresent, { sidebarPresent: true }],
|
||||
[sidebarNotPresent, { sidebarPresent: false }],
|
||||
])('returns expected on %s', (actionCreator, expected) => {
|
||||
expect(sidebarReducer(undefined, actionCreator())).toEqual(expected);
|
||||
});
|
||||
});
|
||||
});
|
Loading…
Reference in a new issue