bigbuffet-rw/app/soapbox/features/ui/util/react_router_helpers.tsx

132 lines
3.4 KiB
TypeScript
Raw Normal View History

2022-04-26 10:01:57 -07:00
import React from 'react';
2022-04-26 11:36:08 -07:00
import { Redirect, Route, useHistory, RouteProps, RouteComponentProps, match as MatchType } from 'react-router-dom';
2022-04-26 10:01:57 -07:00
import SidebarNavigation from 'soapbox/components/sidebar-navigation';
import { Layout } from 'soapbox/components/ui';
2022-04-26 10:01:57 -07:00
import { useOwnAccount, useSettings } from 'soapbox/hooks';
import BundleColumnError from '../components/bundle_column_error';
import ColumnForbidden from '../components/column_forbidden';
import ColumnLoading from '../components/column_loading';
import ColumnsArea from '../components/columns_area';
import BundleContainer from '../containers/bundle_container';
type PageProps = {
params?: MatchType['params'],
layout?: any,
};
2022-04-26 11:36:08 -07:00
interface IWrappedRoute extends RouteProps {
2022-04-26 10:01:57 -07:00
component: (...args: any[]) => any,
2022-04-26 11:36:08 -07:00
page?: React.ComponentType<PageProps>,
content?: React.ReactNode,
componentParams?: Record<string, any>,
layout?: any,
2022-04-26 10:01:57 -07:00
publicRoute?: boolean,
staffOnly?: boolean,
adminOnly?: boolean,
developerOnly?: boolean,
}
const WrappedRoute: React.FC<IWrappedRoute> = ({
component,
page: Page,
content,
componentParams = {},
layout,
publicRoute = false,
staffOnly = false,
adminOnly = false,
developerOnly = false,
...rest
}) => {
const history = useHistory();
const account = useOwnAccount();
const settings = useSettings();
const renderComponent = ({ match }: RouteComponentProps) => {
if (Page) {
return (
<BundleContainer fetchComponent={component} loading={renderLoading} error={renderError}>
{Component =>
(
<Page params={match.params} layout={layout} {...componentParams}>
<Component params={match.params} {...componentParams}>
{content}
</Component>
</Page>
)
}
</BundleContainer>
);
}
return (
<BundleContainer fetchComponent={component} loading={renderLoading} error={renderError}>
{Component =>
(
<ColumnsArea layout={layout}>
<Component params={match.params} {...componentParams}>
{content}
</Component>
</ColumnsArea>
)
}
</BundleContainer>
);
};
const renderWithLayout = (children: JSX.Element) => (
<>
<Layout.Main>
{children}
</Layout.Main>
2022-04-26 10:01:57 -07:00
<Layout.Aside />
</>
);
2022-04-26 10:01:57 -07:00
const renderLoading = () => renderWithLayout(<ColumnLoading />);
const renderForbidden = () => renderWithLayout(<ColumnForbidden />);
const renderError = (props: any) => renderWithLayout(<BundleColumnError {...props} />);
2022-04-26 10:01:57 -07:00
const loginRedirect = () => {
const actualUrl = encodeURIComponent(`${history.location.pathname}${history.location.search}`);
return <Redirect to={`/login?redirect_uri=${actualUrl}`} />;
};
const authorized = [
account || publicRoute,
developerOnly ? settings.get('isDeveloper') : true,
staffOnly ? account && account.staff : true,
adminOnly ? account && account.admin : true,
].every(c => c);
if (!authorized) {
if (!account) {
return loginRedirect();
} else {
return renderForbidden();
}
}
const renderBody = (props: RouteComponentProps) => {
return (
<Layout>
<Layout.Sidebar>
<SidebarNavigation />
</Layout.Sidebar>
{renderComponent(props)}
</Layout>
);
};
return <Route {...rest} render={renderBody} />;
2022-04-26 10:01:57 -07:00
};
export {
WrappedRoute,
};