diff --git a/app/soapbox/components/ui/layout/layout.tsx b/app/soapbox/components/ui/layout/layout.tsx index 0959fe060..d22afe0a1 100644 --- a/app/soapbox/components/ui/layout/layout.tsx +++ b/app/soapbox/components/ui/layout/layout.tsx @@ -2,7 +2,13 @@ import classNames from 'classnames'; import React from 'react'; import StickyBox from 'react-sticky-box'; -const Layout: React.FC = ({ children }) => ( +interface LayoutType extends React.FC { + Sidebar: React.FC, + Main: React.FC>, + Aside: React.FC, +} + +const Layout: LayoutType = ({ children }) => (
{children} @@ -10,7 +16,6 @@ const Layout: React.FC = ({ children }) => (
); - const Sidebar: React.FC = ({ children }) => (
@@ -37,11 +42,8 @@ const Aside: React.FC = ({ children }) => ( ); -// @ts-ignore Layout.Sidebar = Sidebar; -// @ts-ignore Layout.Main = Main; -// @ts-ignore Layout.Aside = Aside; export default Layout; diff --git a/app/soapbox/features/ui/components/columns_area.js b/app/soapbox/features/ui/components/columns_area.js deleted file mode 100644 index eddfa29a6..000000000 --- a/app/soapbox/features/ui/components/columns_area.js +++ /dev/null @@ -1,40 +0,0 @@ -import PropTypes from 'prop-types'; -import React from 'react'; -import ImmutablePropTypes from 'react-immutable-proptypes'; -import ImmutablePureComponent from 'react-immutable-pure-component'; -import { injectIntl } from 'react-intl'; - -import { Layout } from '../../../components/ui'; - -export default @(component => injectIntl(component, { withRef: true })) -class ColumnsArea extends ImmutablePureComponent { - - static propTypes = { - intl: PropTypes.object.isRequired, - columns: ImmutablePropTypes.list.isRequired, - children: PropTypes.node, - layout: PropTypes.object, - }; - - render() { - const { children } = this.props; - const layout = this.props.layout || { LEFT: null, RIGHT: null }; - - return ( - - - {layout.LEFT} - - - - {children} - - - - {layout.RIGHT} - - - ); - } - -} diff --git a/app/soapbox/features/ui/components/columns_area.tsx b/app/soapbox/features/ui/components/columns_area.tsx new file mode 100644 index 000000000..f6e2f01fc --- /dev/null +++ b/app/soapbox/features/ui/components/columns_area.tsx @@ -0,0 +1,30 @@ +import React from 'react'; + +import { Layout } from '../../../components/ui'; + +interface IColumnsArea { + layout: any, +} + +const ColumnsArea: React.FC = (props) => { + const { children } = props; + const layout = props.layout || { LEFT: null, RIGHT: null }; + + return ( + + + {layout.LEFT} + + + + {children} + + + + {layout.RIGHT} + + + ); +}; + +export default ColumnsArea; diff --git a/app/soapbox/features/ui/containers/columns_area_container.js b/app/soapbox/features/ui/containers/columns_area_container.js deleted file mode 100644 index 184a831fa..000000000 --- a/app/soapbox/features/ui/containers/columns_area_container.js +++ /dev/null @@ -1,11 +0,0 @@ -import { connect } from 'react-redux'; - -import { getSettings } from 'soapbox/actions/settings'; - -import ColumnsArea from '../components/columns_area'; - -const mapStateToProps = state => ({ - columns: getSettings(state).get('columns'), -}); - -export default connect(mapStateToProps, null, null, { forwardRef: true })(ColumnsArea); diff --git a/app/soapbox/features/ui/util/react_router_helpers.js b/app/soapbox/features/ui/util/react_router_helpers.js deleted file mode 100644 index 8a7e7ed87..000000000 --- a/app/soapbox/features/ui/util/react_router_helpers.js +++ /dev/null @@ -1,131 +0,0 @@ -import PropTypes from 'prop-types'; -import React from 'react'; -import ImmutablePropTypes from 'react-immutable-proptypes'; -import { connect } from 'react-redux'; -import { Redirect, Route } from 'react-router-dom'; - -import { getSettings } from 'soapbox/actions/settings'; - -import BundleColumnError from '../components/bundle_column_error'; -import ColumnForbidden from '../components/column_forbidden'; -import ColumnLoading from '../components/column_loading'; -import BundleContainer from '../containers/bundle_container'; -import ColumnsAreaContainer from '../containers/columns_area_container'; - -const mapStateToProps = state => { - const me = state.get('me'); - - return { - account: state.getIn(['accounts', me]), - settings: getSettings(state), - }; -}; - -class WrappedRoute extends React.Component { - - static propTypes = { - component: PropTypes.func.isRequired, - page: PropTypes.oneOfType([PropTypes.object, PropTypes.func]), - content: PropTypes.node, - componentParams: PropTypes.object, - layout: PropTypes.object, - account: ImmutablePropTypes.record, - settings: ImmutablePropTypes.map.isRequired, - publicRoute: PropTypes.bool, - staffOnly: PropTypes.bool, - adminOnly: PropTypes.bool, - developerOnly: PropTypes.bool, - }; - - static defaultProps = { - componentParams: {}, - }; - - renderComponent = ({ match }) => { - const { component, content, componentParams, layout, page: Page } = this.props; - - if (Page) { - return ( - - {Component => - ( - - - {content} - - - ) - } - - ); - } - - return ( - - {Component => - ( - - - {content} - - - ) - } - - ); - } - - renderLoading = () => { - return ( - - - - ); - } - - renderForbidden = () => { - return ( - - - - ); - } - - renderError = (props) => { - return ( - - - - ); - } - - loginRedirect = () => { - const actualUrl = encodeURIComponent(`${this.props.computedMatch.url}${this.props.location.search}`); // eslint-disable-line react/prop-types - return ; - } - - render() { - const { component: Component, content, account, settings, publicRoute, developerOnly, staffOnly, adminOnly, ...rest } = this.props; - - 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 this.loginRedirect(); - } else { - return this.renderForbidden(); - } - } - - return ; - } - -} - -const wrappedRoute = connect(mapStateToProps)(WrappedRoute); -export { wrappedRoute as WrappedRoute }; diff --git a/app/soapbox/features/ui/util/react_router_helpers.tsx b/app/soapbox/features/ui/util/react_router_helpers.tsx new file mode 100644 index 000000000..47cec40c4 --- /dev/null +++ b/app/soapbox/features/ui/util/react_router_helpers.tsx @@ -0,0 +1,127 @@ +import React from 'react'; +import { Redirect, Route, useHistory, RouteComponentProps, match as MatchType } from 'react-router-dom'; + +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, +}; + +interface IWrappedRoute { + component: (...args: any[]) => any, + page: React.ComponentType, + content: React.ReactNode, + componentParams: Record, + layout: any, + publicRoute?: boolean, + staffOnly?: boolean, + adminOnly?: boolean, + developerOnly?: boolean, +} + +const WrappedRoute: React.FC = ({ + 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 ( + + {Component => + ( + + + {content} + + + ) + } + + ); + } + + return ( + + {Component => + ( + + + {content} + + + ) + } + + ); + }; + + const renderLoading = () => { + return ( + + + + ); + }; + + const renderForbidden = () => { + return ( + + + + ); + }; + + const renderError = (props: any) => { + return ( + + + + ); + }; + + const loginRedirect = () => { + const actualUrl = encodeURIComponent(`${history.location.pathname}${history.location.search}`); + return ; + }; + + 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(); + } + } + + return ; +}; + +export { + WrappedRoute, +};