mirror of
https://github.com/shlinkio/shlink-web-client.git
synced 2024-12-23 09:30:31 +03:00
Ensured versions footer has proper classes based on sidebar status, not selected server
This commit is contained in:
parent
4f731d9de8
commit
73d4707420
11 changed files with 76 additions and 22 deletions
|
@ -11,6 +11,11 @@ import NotFound from './NotFound';
|
|||
import { AsideMenuProps } from './AsideMenu';
|
||||
import './MenuLayout.scss';
|
||||
|
||||
interface MenuLayoutProps {
|
||||
sidebarRendered: Function;
|
||||
sidebarNotRendered: Function;
|
||||
}
|
||||
|
||||
const MenuLayout = (
|
||||
TagsList: FC,
|
||||
ShortUrlsList: FC,
|
||||
|
@ -24,13 +29,19 @@ const MenuLayout = (
|
|||
Overview: FC,
|
||||
EditShortUrl: FC,
|
||||
ManageDomains: FC,
|
||||
) => withSelectedServer(({ selectedServer }) => {
|
||||
) => withSelectedServer<MenuLayoutProps>(({ selectedServer, sidebarNotRendered, sidebarRendered }) => {
|
||||
const location = useLocation();
|
||||
const [ sidebarVisible, toggleSidebar, showSidebar, hideSidebar ] = useToggle();
|
||||
const showContent = isReachableServer(selectedServer);
|
||||
|
||||
useEffect(() => hideSidebar(), [ location ]);
|
||||
useEffect(() => {
|
||||
showContent && sidebarRendered();
|
||||
|
||||
if (!isReachableServer(selectedServer)) {
|
||||
return () => sidebarNotRendered();
|
||||
}, []);
|
||||
|
||||
if (!showContent) {
|
||||
return <ServerError />;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
import { pipe } from 'ramda';
|
||||
import { ExternalLink } from 'react-external-link';
|
||||
import { versionToPrintable, versionToSemVer } from '../utils/helpers/version';
|
||||
import { isReachableServer } from '../servers/data';
|
||||
import { ShlinkVersionsContainerProps } from './ShlinkVersionsContainer';
|
||||
import { isReachableServer, SelectedServer } from '../servers/data';
|
||||
|
||||
const SHLINK_WEB_CLIENT_VERSION = '%_VERSION_%';
|
||||
const normalizeVersion = pipe(versionToSemVer(), versionToPrintable);
|
||||
|
||||
export interface ShlinkVersionsProps extends ShlinkVersionsContainerProps {
|
||||
export interface ShlinkVersionsProps {
|
||||
selectedServer: SelectedServer;
|
||||
clientVersion?: string;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
@import '../utils/base';
|
||||
|
||||
.shlink-versions-container--with-server {
|
||||
.shlink-versions-container--with-sidebar {
|
||||
margin-left: 0;
|
||||
|
||||
@media (min-width: $mdMin) {
|
||||
|
|
|
@ -1,15 +1,17 @@
|
|||
import classNames from 'classnames';
|
||||
import { isReachableServer, SelectedServer } from '../servers/data';
|
||||
import { SelectedServer } from '../servers/data';
|
||||
import ShlinkVersions from './ShlinkVersions';
|
||||
import { Sidebar } from './reducers/sidebar';
|
||||
import './ShlinkVersionsContainer.scss';
|
||||
|
||||
export interface ShlinkVersionsContainerProps {
|
||||
selectedServer: SelectedServer;
|
||||
sidebar: Sidebar;
|
||||
}
|
||||
|
||||
const ShlinkVersionsContainer = ({ selectedServer }: ShlinkVersionsContainerProps) => {
|
||||
const ShlinkVersionsContainer = ({ selectedServer, sidebar }: ShlinkVersionsContainerProps) => {
|
||||
const classes = classNames('text-center', {
|
||||
'shlink-versions-container--with-server': isReachableServer(selectedServer),
|
||||
'shlink-versions-container--with-sidebar': sidebar.hasSidebar,
|
||||
});
|
||||
|
||||
return (
|
||||
|
|
27
src/common/reducers/sidebar.ts
Normal file
27
src/common/reducers/sidebar.ts
Normal file
|
@ -0,0 +1,27 @@
|
|||
import { Action } from 'redux';
|
||||
import { buildActionCreator, buildReducer } from '../../utils/helpers/redux';
|
||||
|
||||
/* eslint-disable padding-line-between-statements */
|
||||
export const SIDEBAR_RENDERED = 'shlink/common/SIDEBAR_RENDERED';
|
||||
export const SIDEBAR_NOT_RENDERED = 'shlink/common/SIDEBAR_NOT_RENDERED';
|
||||
/* eslint-enable padding-line-between-statements */
|
||||
|
||||
export interface Sidebar {
|
||||
hasSidebar: boolean;
|
||||
}
|
||||
|
||||
type SidebarRenderedAction = Action<string>;
|
||||
type SidebarNotRenderedAction = Action<string>;
|
||||
|
||||
const initialState: Sidebar = {
|
||||
hasSidebar: false,
|
||||
};
|
||||
|
||||
export default buildReducer<Sidebar, SidebarRenderedAction & SidebarNotRenderedAction>({
|
||||
[SIDEBAR_RENDERED]: () => ({ hasSidebar: true }),
|
||||
[SIDEBAR_NOT_RENDERED]: () => ({ hasSidebar: false }),
|
||||
}, initialState);
|
||||
|
||||
export const sidebarRendered = buildActionCreator(SIDEBAR_RENDERED);
|
||||
|
||||
export const sidebarNotRendered = buildActionCreator(SIDEBAR_NOT_RENDERED);
|
|
@ -9,6 +9,7 @@ import ErrorHandler from '../ErrorHandler';
|
|||
import ShlinkVersionsContainer from '../ShlinkVersionsContainer';
|
||||
import { ConnectDecorator } from '../../container/types';
|
||||
import { withoutSelectedServer } from '../../servers/helpers/withoutSelectedServer';
|
||||
import { sidebarNotRendered, sidebarRendered } from '../reducers/sidebar';
|
||||
import { ImageDownloader } from './ImageDownloader';
|
||||
|
||||
const provideServices = (bottle: Bottle, connect: ConnectDecorator) => {
|
||||
|
@ -44,14 +45,18 @@ const provideServices = (bottle: Bottle, connect: ConnectDecorator) => {
|
|||
'EditShortUrl',
|
||||
'ManageDomains',
|
||||
);
|
||||
bottle.decorator('MenuLayout', connect([ 'selectedServer' ], [ 'selectServer' ]));
|
||||
bottle.decorator('MenuLayout', connect([ 'selectedServer' ], [ 'selectServer', 'sidebarRendered', 'sidebarNotRendered' ]));
|
||||
|
||||
bottle.serviceFactory('AsideMenu', AsideMenu, 'DeleteServerButton');
|
||||
|
||||
bottle.serviceFactory('ShlinkVersionsContainer', () => ShlinkVersionsContainer);
|
||||
bottle.decorator('ShlinkVersionsContainer', connect([ 'selectedServer' ]));
|
||||
bottle.decorator('ShlinkVersionsContainer', connect([ 'selectedServer', 'sidebar' ]));
|
||||
|
||||
bottle.serviceFactory('ErrorHandler', ErrorHandler, 'window', 'console');
|
||||
|
||||
// Actions
|
||||
bottle.serviceFactory('sidebarRendered', () => sidebarRendered);
|
||||
bottle.serviceFactory('sidebarNotRendered', () => sidebarNotRendered);
|
||||
};
|
||||
|
||||
export default provideServices;
|
||||
|
|
|
@ -14,6 +14,7 @@ import { TagVisits } from '../visits/reducers/tagVisits';
|
|||
import { DomainsList } from '../domains/reducers/domainsList';
|
||||
import { VisitsOverview } from '../visits/reducers/visitsOverview';
|
||||
import { VisitsInfo } from '../visits/types';
|
||||
import { Sidebar } from '../common/reducers/sidebar';
|
||||
|
||||
export interface ShlinkState {
|
||||
servers: ServersMap;
|
||||
|
@ -35,6 +36,7 @@ export interface ShlinkState {
|
|||
domainsList: DomainsList;
|
||||
visitsOverview: VisitsOverview;
|
||||
appUpdated: boolean;
|
||||
sidebar: Sidebar;
|
||||
}
|
||||
|
||||
export type ConnectDecorator = (props: string[] | null, actions?: string[]) => any;
|
||||
|
|
|
@ -18,6 +18,7 @@ import settingsReducer from '../settings/reducers/settings';
|
|||
import domainsListReducer from '../domains/reducers/domainsList';
|
||||
import visitsOverviewReducer from '../visits/reducers/visitsOverview';
|
||||
import appUpdatesReducer from '../app/reducers/appUpdates';
|
||||
import sidebarReducer from '../common/reducers/sidebar';
|
||||
import { ShlinkState } from '../container/types';
|
||||
|
||||
export default combineReducers<ShlinkState>({
|
||||
|
@ -40,4 +41,5 @@ export default combineReducers<ShlinkState>({
|
|||
domainsList: domainsListReducer,
|
||||
visitsOverview: visitsOverviewReducer,
|
||||
appUpdated: appUpdatesReducer,
|
||||
sidebar: sidebarReducer,
|
||||
});
|
||||
|
|
|
@ -43,7 +43,6 @@ const provideServices = (bottle: Bottle, connect: ConnectDecorator) => {
|
|||
bottle.decorator('CreateServer', connect([ 'selectedServer', 'servers' ], [ 'createServer', 'resetSelectedServer' ]));
|
||||
|
||||
bottle.serviceFactory('EditServer', EditServer, 'ServerError');
|
||||
bottle.decorator('EditServer', withoutSelectedServer);
|
||||
bottle.decorator('EditServer', connect([ 'selectedServer' ], [ 'editServer', 'selectServer', 'resetSelectedServer' ]));
|
||||
|
||||
bottle.serviceFactory('ServersDropdown', () => ServersDropdown);
|
||||
|
|
|
@ -20,7 +20,14 @@ describe('<MenuLayout />', () => {
|
|||
const createWrapper = (selectedServer: SelectedServer) => {
|
||||
(useParams as any).mockReturnValue({ serverId: 'abc123' });
|
||||
|
||||
wrapper = shallow(<MenuLayout selectServer={jest.fn()} selectedServer={selectedServer} />);
|
||||
wrapper = shallow(
|
||||
<MenuLayout
|
||||
sidebarNotRendered={jest.fn()}
|
||||
sidebarRendered={jest.fn}
|
||||
selectServer={jest.fn()}
|
||||
selectedServer={selectedServer}
|
||||
/>,
|
||||
);
|
||||
|
||||
return wrapper;
|
||||
};
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
import { shallow, ShallowWrapper } from 'enzyme';
|
||||
import { Mock } from 'ts-mockery';
|
||||
import ShlinkVersionsContainer from '../../src/common/ShlinkVersionsContainer';
|
||||
import { NonReachableServer, NotFoundServer, ReachableServer, SelectedServer } from '../../src/servers/data';
|
||||
import { SelectedServer } from '../../src/servers/data';
|
||||
import { Sidebar } from '../../src/common/reducers/sidebar';
|
||||
|
||||
describe('<ShlinkVersionsContainer />', () => {
|
||||
let wrapper: ShallowWrapper;
|
||||
|
||||
const createWrapper = (selectedServer: SelectedServer) => {
|
||||
wrapper = shallow(<ShlinkVersionsContainer selectedServer={selectedServer} />);
|
||||
const createWrapper = (sidebar: Sidebar) => {
|
||||
wrapper = shallow(<ShlinkVersionsContainer selectedServer={Mock.all<SelectedServer>()} sidebar={sidebar} />);
|
||||
|
||||
return wrapper;
|
||||
};
|
||||
|
@ -15,12 +16,10 @@ describe('<ShlinkVersionsContainer />', () => {
|
|||
afterEach(() => wrapper?.unmount());
|
||||
|
||||
it.each([
|
||||
[ null, 'text-center' ],
|
||||
[ Mock.of<NotFoundServer>({ serverNotFound: true }), 'text-center' ],
|
||||
[ Mock.of<NonReachableServer>({ serverNotReachable: true }), 'text-center' ],
|
||||
[ Mock.of<ReachableServer>({ version: '1.0.0' }), 'text-center shlink-versions-container--with-server' ],
|
||||
])('renders proper col classes based on type of selected server', (selectedServer, expectedClasses) => {
|
||||
const wrapper = createWrapper(selectedServer);
|
||||
[{ hasSidebar: false }, 'text-center' ],
|
||||
[{ hasSidebar: true }, 'text-center shlink-versions-container--with-sidebar' ],
|
||||
])('renders proper col classes based on sidebar status', (sidebar, expectedClasses) => {
|
||||
const wrapper = createWrapper(sidebar);
|
||||
|
||||
expect(wrapper.find('div').prop('className')).toEqual(`${expectedClasses}`);
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue