mirror of
https://github.com/shlinkio/shlink-web-client.git
synced 2026-04-18 12:36:20 +00:00
Refactor DI approach for components
This commit is contained in:
@@ -1,17 +1,19 @@
|
||||
import { SimpleCard } from '@shlinkio/shlink-frontend-kit';
|
||||
import type { ReactNode } from 'react';
|
||||
import type { PropsWithChildren, ReactNode } from 'react';
|
||||
import { Component } from 'react';
|
||||
import { Button } from 'reactstrap';
|
||||
|
||||
interface ErrorHandlerState {
|
||||
hasError: boolean;
|
||||
}
|
||||
type ErrorHandlerProps = PropsWithChildren<{
|
||||
location?: typeof window.location;
|
||||
console?: typeof window.console;
|
||||
}>;
|
||||
|
||||
export const ErrorHandler = (
|
||||
{ location }: Window,
|
||||
{ error }: Console,
|
||||
) => class extends Component<any, ErrorHandlerState> {
|
||||
public constructor(props: object) {
|
||||
type ErrorHandlerState = {
|
||||
hasError: boolean;
|
||||
};
|
||||
|
||||
export class ErrorHandler extends Component<ErrorHandlerProps, ErrorHandlerState> {
|
||||
public constructor(props: ErrorHandlerProps) {
|
||||
super(props);
|
||||
this.state = { hasError: false };
|
||||
}
|
||||
@@ -21,13 +23,14 @@ export const ErrorHandler = (
|
||||
}
|
||||
|
||||
public componentDidCatch(e: Error): void {
|
||||
if (process.env.NODE_ENV !== 'development') {
|
||||
error(e);
|
||||
}
|
||||
const { console = globalThis.console } = this.props;
|
||||
console.error(e);
|
||||
}
|
||||
|
||||
public render(): ReactNode {
|
||||
const { hasError } = this.state;
|
||||
const { location = globalThis.location } = this.props;
|
||||
|
||||
if (hasError) {
|
||||
return (
|
||||
<div className="home">
|
||||
@@ -44,4 +47,4 @@ export const ErrorHandler = (
|
||||
const { children } = this.props;
|
||||
return children;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -6,10 +6,17 @@ import type { FC } from 'react';
|
||||
import { useEffect } from 'react';
|
||||
import { Link, useLocation } from 'react-router-dom';
|
||||
import { Collapse, Nav, Navbar, NavbarBrand, NavbarToggler, NavItem, NavLink } from 'reactstrap';
|
||||
import type { FCWithDeps } from '../container/utils';
|
||||
import { componentFactory, useDependencies } from '../container/utils';
|
||||
import { ShlinkLogo } from './img/ShlinkLogo';
|
||||
import './MainHeader.scss';
|
||||
|
||||
export const MainHeader = (ServersDropdown: FC) => () => {
|
||||
type MainHeaderDeps = {
|
||||
ServersDropdown: FC;
|
||||
};
|
||||
|
||||
const MainHeader: FCWithDeps<{}, MainHeaderDeps> = () => {
|
||||
const { ServersDropdown } = useDependencies(MainHeader);
|
||||
const [isNotCollapsed, toggleCollapse, , collapse] = useToggle();
|
||||
const location = useLocation();
|
||||
const { pathname } = location;
|
||||
@@ -43,3 +50,5 @@ export const MainHeader = (ServersDropdown: FC) => () => {
|
||||
</Navbar>
|
||||
);
|
||||
};
|
||||
|
||||
export const MainHeaderFactory = componentFactory(MainHeader, ['ServersDropdown']);
|
||||
|
||||
@@ -2,7 +2,7 @@ import type { FC, PropsWithChildren } from 'react';
|
||||
import { useEffect } from 'react';
|
||||
import { useLocation } from 'react-router-dom';
|
||||
|
||||
export const ScrollToTop: FC<PropsWithChildren<unknown>> = ({ children }) => {
|
||||
export const ScrollToTop: FC<PropsWithChildren> = ({ children }) => {
|
||||
const location = useLocation();
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
@@ -1,20 +1,34 @@
|
||||
import type { Settings, ShlinkWebComponentType, TagColorsStorage } from '@shlinkio/shlink-web-component';
|
||||
import type { FC } from 'react';
|
||||
import type { ShlinkApiClientBuilder } from '../api/services/ShlinkApiClientBuilder';
|
||||
import type { FCWithDeps } from '../container/utils';
|
||||
import { componentFactory, useDependencies } from '../container/utils';
|
||||
import { isReachableServer } from '../servers/data';
|
||||
import type { WithSelectedServerProps } from '../servers/helpers/withSelectedServer';
|
||||
import { withSelectedServer } from '../servers/helpers/withSelectedServer';
|
||||
import { NotFound } from './NotFound';
|
||||
|
||||
interface ShlinkWebComponentContainerProps {
|
||||
type ShlinkWebComponentContainerProps = WithSelectedServerProps & {
|
||||
settings: Settings;
|
||||
}
|
||||
};
|
||||
|
||||
export const ShlinkWebComponentContainer = (
|
||||
type ShlinkWebComponentContainerDeps = {
|
||||
buildShlinkApiClient: ShlinkApiClientBuilder,
|
||||
tagColorsStorage: TagColorsStorage,
|
||||
TagColorsStorage: TagColorsStorage,
|
||||
ShlinkWebComponent: ShlinkWebComponentType,
|
||||
ServerError: FC,
|
||||
) => withSelectedServer<ShlinkWebComponentContainerProps>(({ selectedServer, settings }) => {
|
||||
};
|
||||
|
||||
const ShlinkWebComponentContainer: FCWithDeps<
|
||||
ShlinkWebComponentContainerProps,
|
||||
ShlinkWebComponentContainerDeps
|
||||
> = withSelectedServer(({ selectedServer, settings }) => {
|
||||
const {
|
||||
buildShlinkApiClient,
|
||||
TagColorsStorage: tagColorsStorage,
|
||||
ShlinkWebComponent,
|
||||
ServerError,
|
||||
} = useDependencies(ShlinkWebComponentContainer);
|
||||
const selectedServerIsReachable = isReachableServer(selectedServer);
|
||||
const routesPrefix = selectedServerIsReachable ? `/server/${selectedServer.id}` : '';
|
||||
|
||||
@@ -34,4 +48,11 @@ export const ShlinkWebComponentContainer = (
|
||||
)}
|
||||
/>
|
||||
);
|
||||
}, ServerError);
|
||||
});
|
||||
|
||||
export const ShlinkWebComponentContainerFactory = componentFactory(ShlinkWebComponentContainer, [
|
||||
'buildShlinkApiClient',
|
||||
'TagColorsStorage',
|
||||
'ShlinkWebComponent',
|
||||
'ServerError',
|
||||
]);
|
||||
|
||||
@@ -5,10 +5,10 @@ import type { ConnectDecorator } from '../../container/types';
|
||||
import { withoutSelectedServer } from '../../servers/helpers/withoutSelectedServer';
|
||||
import { ErrorHandler } from '../ErrorHandler';
|
||||
import { Home } from '../Home';
|
||||
import { MainHeader } from '../MainHeader';
|
||||
import { MainHeaderFactory } from '../MainHeader';
|
||||
import { ScrollToTop } from '../ScrollToTop';
|
||||
import { ShlinkVersionsContainer } from '../ShlinkVersionsContainer';
|
||||
import { ShlinkWebComponentContainer } from '../ShlinkWebComponentContainer';
|
||||
import { ShlinkWebComponentContainerFactory } from '../ShlinkWebComponentContainer';
|
||||
|
||||
export const provideServices = (bottle: Bottle, connect: ConnectDecorator) => {
|
||||
// Services
|
||||
@@ -20,25 +20,18 @@ export const provideServices = (bottle: Bottle, connect: ConnectDecorator) => {
|
||||
// Components
|
||||
bottle.serviceFactory('ScrollToTop', () => ScrollToTop);
|
||||
|
||||
bottle.serviceFactory('MainHeader', MainHeader, 'ServersDropdown');
|
||||
bottle.factory('MainHeader', MainHeaderFactory);
|
||||
|
||||
bottle.serviceFactory('Home', () => Home);
|
||||
bottle.decorator('Home', withoutSelectedServer);
|
||||
bottle.decorator('Home', connect(['servers'], ['resetSelectedServer']));
|
||||
|
||||
bottle.serviceFactory('ShlinkWebComponent', () => ShlinkWebComponent);
|
||||
bottle.serviceFactory(
|
||||
'ShlinkWebComponentContainer',
|
||||
ShlinkWebComponentContainer,
|
||||
'buildShlinkApiClient',
|
||||
'TagColorsStorage',
|
||||
'ShlinkWebComponent',
|
||||
'ServerError',
|
||||
);
|
||||
bottle.factory('ShlinkWebComponentContainer', ShlinkWebComponentContainerFactory);
|
||||
bottle.decorator('ShlinkWebComponentContainer', connect(['selectedServer', 'settings'], ['selectServer']));
|
||||
|
||||
bottle.serviceFactory('ShlinkVersionsContainer', () => ShlinkVersionsContainer);
|
||||
bottle.decorator('ShlinkVersionsContainer', connect(['selectedServer']));
|
||||
|
||||
bottle.serviceFactory('ErrorHandler', ErrorHandler, 'window', 'console');
|
||||
bottle.serviceFactory('ErrorHandler', () => ErrorHandler);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user