From 19c6d331b6f2d22006bfcda3feab12c86c076afc Mon Sep 17 00:00:00 2001 From: Levko Kravets Date: Sun, 26 Jan 2020 14:53:40 +0200 Subject: [PATCH] Refine routes definitions (#4579) * Refine routes definitions * Replace HoC wrappers with functions to create route definition * Some updates for code consistency * ItemsList component: remove currentRoute dependency * Prepare route parametes in wrapper functions --- .../AuthenticatedPageWrapper.jsx | 59 ------------- .../ApplicationArea/SignedOutPageWrapper.jsx | 41 ---------- .../routeWithApiKeySession.jsx | 63 ++++++++++++++ .../ApplicationArea/routeWithUserSession.jsx | 82 +++++++++++++++++++ client/app/components/ErrorBoundary.jsx | 5 +- .../app/components/items-list/ItemsList.jsx | 26 +++--- client/app/pages/admin/Jobs.jsx | 15 +--- client/app/pages/admin/OutdatedQueries.jsx | 21 +---- client/app/pages/admin/SystemStatus.jsx | 15 +--- client/app/pages/alert/Alert.jsx | 41 +++------- client/app/pages/alerts/AlertsList.jsx | 27 ++---- client/app/pages/dashboards/DashboardList.jsx | 41 ++-------- client/app/pages/dashboards/DashboardPage.jsx | 15 +--- .../pages/dashboards/PublicDashboardPage.jsx | 17 ++-- .../pages/data-sources/DataSourcesList.jsx | 29 ++----- .../app/pages/data-sources/EditDataSource.jsx | 15 +--- .../pages/destinations/DestinationsList.jsx | 29 ++----- .../pages/destinations/EditDestination.jsx | 15 +--- client/app/pages/groups/GroupDataSources.jsx | 25 ++---- client/app/pages/groups/GroupMembers.jsx | 25 ++---- client/app/pages/groups/GroupsList.jsx | 25 ++---- client/app/pages/home/Home.jsx | 12 +-- client/app/pages/queries-list/QueriesList.jsx | 77 ++++------------- client/app/pages/queries/QuerySource.jsx | 29 ++----- client/app/pages/queries/QueryView.jsx | 15 +--- .../app/pages/queries/VisualizationEmbed.jsx | 19 ++--- .../query-snippets/QuerySnippetsList.jsx | 43 ++-------- .../pages/settings/OrganizationSettings.jsx | 15 +--- client/app/pages/users/UserProfile.jsx | 27 ++---- client/app/pages/users/UsersList.jsx | 79 ++++-------------- 30 files changed, 317 insertions(+), 630 deletions(-) delete mode 100644 client/app/components/ApplicationArea/AuthenticatedPageWrapper.jsx delete mode 100644 client/app/components/ApplicationArea/SignedOutPageWrapper.jsx create mode 100644 client/app/components/ApplicationArea/routeWithApiKeySession.jsx create mode 100644 client/app/components/ApplicationArea/routeWithUserSession.jsx diff --git a/client/app/components/ApplicationArea/AuthenticatedPageWrapper.jsx b/client/app/components/ApplicationArea/AuthenticatedPageWrapper.jsx deleted file mode 100644 index 1b7c483bd7..0000000000 --- a/client/app/components/ApplicationArea/AuthenticatedPageWrapper.jsx +++ /dev/null @@ -1,59 +0,0 @@ -import React, { useEffect, useState } from "react"; -import PropTypes from "prop-types"; -import ErrorBoundary from "@/components/ErrorBoundary"; -import { Auth } from "@/services/auth"; -import organizationStatus from "@/services/organizationStatus"; -import ApplicationHeader from "./ApplicationHeader"; -import ErrorMessage from "./ErrorMessage"; - -export default function AuthenticatedPageWrapper({ bodyClass, children }) { - const [isAuthenticated, setIsAuthenticated] = useState(!!Auth.isAuthenticated()); - - useEffect(() => { - let isCancelled = false; - Promise.all([Auth.requireSession(), organizationStatus.refresh()]) - .then(() => { - if (!isCancelled) { - setIsAuthenticated(!!Auth.isAuthenticated()); - } - }) - .catch(() => { - if (!isCancelled) { - setIsAuthenticated(false); - } - }); - return () => { - isCancelled = true; - }; - }, []); - - useEffect(() => { - if (bodyClass) { - document.body.classList.toggle(bodyClass, true); - return () => { - document.body.classList.toggle(bodyClass, false); - }; - } - }, [bodyClass]); - - if (!isAuthenticated) { - return null; - } - - return ( - <> - - }>{children} - - ); -} - -AuthenticatedPageWrapper.propTypes = { - bodyClass: PropTypes.string, - children: PropTypes.node, -}; - -AuthenticatedPageWrapper.defaultProps = { - bodyClass: null, - children: null, -}; diff --git a/client/app/components/ApplicationArea/SignedOutPageWrapper.jsx b/client/app/components/ApplicationArea/SignedOutPageWrapper.jsx deleted file mode 100644 index 62a5a69a9f..0000000000 --- a/client/app/components/ApplicationArea/SignedOutPageWrapper.jsx +++ /dev/null @@ -1,41 +0,0 @@ -import { useEffect, useState } from "react"; -import PropTypes from "prop-types"; -import { Auth } from "@/services/auth"; - -export default function SignedOutPageWrapper({ apiKey, children }) { - const [isAuthenticated, setIsAuthenticated] = useState(false); - - useEffect(() => { - let isCancelled = false; - Auth.setApiKey(apiKey); - Auth.loadConfig() - .then(() => { - if (!isCancelled) { - setIsAuthenticated(true); - } - }) - .catch(() => { - if (!isCancelled) { - setIsAuthenticated(false); - } - }); - return () => { - isCancelled = true; - }; - }, [apiKey]); - - if (!isAuthenticated) { - return null; - } - - return children; -} - -SignedOutPageWrapper.propTypes = { - apiKey: PropTypes.string.isRequired, - children: PropTypes.node, -}; - -SignedOutPageWrapper.defaultProps = { - children: null, -}; diff --git a/client/app/components/ApplicationArea/routeWithApiKeySession.jsx b/client/app/components/ApplicationArea/routeWithApiKeySession.jsx new file mode 100644 index 0000000000..895f4fb115 --- /dev/null +++ b/client/app/components/ApplicationArea/routeWithApiKeySession.jsx @@ -0,0 +1,63 @@ +import React, { useEffect, useState, useContext } from "react"; +import PropTypes from "prop-types"; +import { ErrorBoundaryContext } from "@/components/ErrorBoundary"; +import { Auth } from "@/services/auth"; + +// This wrapper modifies `route.render` function and instead of passing `currentRoute` passes an object +// that contains: +// - `currentRoute.routeParams` +// - `pageTitle` field which is equal to `currentRoute.title` +// - `onError` field which is a `handleError` method of nearest error boundary +// - `apiKey` field + +function ApiKeySessionWrapper({ apiKey, currentRoute, renderChildren }) { + const [isAuthenticated, setIsAuthenticated] = useState(false); + const { handleError } = useContext(ErrorBoundaryContext); + + useEffect(() => { + let isCancelled = false; + Auth.setApiKey(apiKey); + Auth.loadConfig() + .then(() => { + if (!isCancelled) { + setIsAuthenticated(true); + } + }) + .catch(() => { + if (!isCancelled) { + setIsAuthenticated(false); + } + }); + return () => { + isCancelled = true; + }; + }, [apiKey]); + + if (!isAuthenticated) { + return null; + } + + return ( + + {renderChildren({ ...currentRoute.routeParams, pageTitle: currentRoute.title, onError: handleError, apiKey })} + + ); +} + +ApiKeySessionWrapper.propTypes = { + apiKey: PropTypes.string.isRequired, + renderChildren: PropTypes.func, +}; + +ApiKeySessionWrapper.defaultProps = { + renderChildren: () => null, +}; + +export default function routeWithApiKeySession({ render, getApiKey, ...rest }) { + return { + ...rest, + render: currentRoute => ( + + ), + }; +} diff --git a/client/app/components/ApplicationArea/routeWithUserSession.jsx b/client/app/components/ApplicationArea/routeWithUserSession.jsx new file mode 100644 index 0000000000..a062f6981e --- /dev/null +++ b/client/app/components/ApplicationArea/routeWithUserSession.jsx @@ -0,0 +1,82 @@ +import React, { useEffect, useState } from "react"; +import PropTypes from "prop-types"; +import ErrorBoundary, { ErrorBoundaryContext } from "@/components/ErrorBoundary"; +import { Auth } from "@/services/auth"; +import organizationStatus from "@/services/organizationStatus"; +import ApplicationHeader from "./ApplicationHeader"; +import ErrorMessage from "./ErrorMessage"; + +// This wrapper modifies `route.render` function and instead of passing `currentRoute` passes an object +// that contains: +// - `currentRoute.routeParams` +// - `pageTitle` field which is equal to `currentRoute.title` +// - `onError` field which is a `handleError` method of nearest error boundary + +function UserSessionWrapper({ bodyClass, currentRoute, renderChildren }) { + const [isAuthenticated, setIsAuthenticated] = useState(!!Auth.isAuthenticated()); + + useEffect(() => { + let isCancelled = false; + Promise.all([Auth.requireSession(), organizationStatus.refresh()]) + .then(() => { + if (!isCancelled) { + setIsAuthenticated(!!Auth.isAuthenticated()); + } + }) + .catch(() => { + if (!isCancelled) { + setIsAuthenticated(false); + } + }); + return () => { + isCancelled = true; + }; + }, []); + + useEffect(() => { + if (bodyClass) { + document.body.classList.toggle(bodyClass, true); + return () => { + document.body.classList.toggle(bodyClass, false); + }; + } + }, [bodyClass]); + + if (!isAuthenticated) { + return null; + } + + return ( + + + + }> + + {({ handleError }) => + renderChildren({ ...currentRoute.routeParams, pageTitle: currentRoute.title, onError: handleError }) + } + + + + + ); +} + +UserSessionWrapper.propTypes = { + bodyClass: PropTypes.string, + renderChildren: PropTypes.func, +}; + +UserSessionWrapper.defaultProps = { + bodyClass: null, + renderChildren: () => null, +}; + +export default function routeWithUserSession({ render, bodyClass, ...rest }) { + return { + ...rest, + render: currentRoute => ( + + ), + }; +} diff --git a/client/app/components/ErrorBoundary.jsx b/client/app/components/ErrorBoundary.jsx index c6780799db..78e354efab 100644 --- a/client/app/components/ErrorBoundary.jsx +++ b/client/app/components/ErrorBoundary.jsx @@ -8,7 +8,10 @@ const logger = debug("redash:errors"); export const ErrorBoundaryContext = React.createContext({ handleError: error => { - throw error; + // Allow calling chain to roll up, and then throw the error in global context + setTimeout(() => { + throw error; + }); }, reset: () => {}, }); diff --git a/client/app/components/items-list/ItemsList.jsx b/client/app/components/items-list/ItemsList.jsx index fba0c13493..1d2de3f00e 100644 --- a/client/app/components/items-list/ItemsList.jsx +++ b/client/app/components/items-list/ItemsList.jsx @@ -5,7 +5,7 @@ import hoistNonReactStatics from "hoist-non-react-statics"; import { clientConfig } from "@/services/auth"; export const ControllerType = PropTypes.shape({ - // values of props declared by wrapped component, current route's locals (`resolve: { ... }`) and title + // values of props declared by wrapped component and some additional props from items list params: PropTypes.object.isRequired, isLoaded: PropTypes.bool.isRequired, @@ -38,13 +38,11 @@ export const ControllerType = PropTypes.shape({ export function wrap(WrappedComponent, createItemsSource, createStateStorage) { class ItemsListWrapper extends React.Component { static propTypes = { - ...omit(WrappedComponent.propTypes, ["controller"]), onError: PropTypes.func, children: PropTypes.node, }; static defaultProps = { - ...omit(WrappedComponent.defaultProps, ["controller"]), onError: error => { // Allow calling chain to roll up, and then throw the error in global context setTimeout(() => { @@ -102,20 +100,13 @@ export function wrap(WrappedComponent, createItemsSource, createStateStorage) { // eslint-disable-next-line class-methods-use-this getState({ isLoaded, totalCount, pageItems, params, ...rest }) { - params = { - // Custom params from items source - ...params, - - title: this.props.currentRoute.title, - ...this.props.routeParams, - - // Add to params all props except of own ones - ...omit(this.props, ["onError", "children", "currentRoute", "routeParams"]), - }; return { ...rest, - params, + params: { + ...params, // custom params from items source + ...omit(this.props, ["onError", "children"]), // add all props except of own ones + }, isLoaded, isEmpty: !isLoaded || totalCount === 0, @@ -128,8 +119,11 @@ export function wrap(WrappedComponent, createItemsSource, createStateStorage) { render() { // don't pass own props to wrapped component const { children, onError, ...props } = this.props; - props.controller = this.state; - return {children}; + return ( + + {children} + + ); } } diff --git a/client/app/pages/admin/Jobs.jsx b/client/app/pages/admin/Jobs.jsx index fa6e0a31c3..da7b86ddde 100644 --- a/client/app/pages/admin/Jobs.jsx +++ b/client/app/pages/admin/Jobs.jsx @@ -5,9 +5,8 @@ import { axios } from "@/services/axios"; import Alert from "antd/lib/alert"; import Tabs from "antd/lib/tabs"; import * as Grid from "antd/lib/grid"; -import AuthenticatedPageWrapper from "@/components/ApplicationArea/AuthenticatedPageWrapper"; +import routeWithUserSession from "@/components/ApplicationArea/routeWithUserSession"; import Layout from "@/components/admin/Layout"; -import { ErrorBoundaryContext } from "@/components/ErrorBoundary"; import { CounterCard, WorkersTable, QueuesTable, OtherJobsTable } from "@/components/admin/RQStatus"; import location from "@/services/location"; @@ -121,14 +120,8 @@ class Jobs extends React.Component { } } -export default { +export default routeWithUserSession({ path: "/admin/queries/jobs", title: "RQ Status", - render: currentRoute => ( - - - {({ handleError }) => } - - - ), -}; + render: pageProps => , +}); diff --git a/client/app/pages/admin/OutdatedQueries.jsx b/client/app/pages/admin/OutdatedQueries.jsx index a955700e46..a41afc16d7 100644 --- a/client/app/pages/admin/OutdatedQueries.jsx +++ b/client/app/pages/admin/OutdatedQueries.jsx @@ -4,13 +4,12 @@ import { axios } from "@/services/axios"; import Switch from "antd/lib/switch"; import * as Grid from "antd/lib/grid"; -import AuthenticatedPageWrapper from "@/components/ApplicationArea/AuthenticatedPageWrapper"; +import routeWithUserSession from "@/components/ApplicationArea/routeWithUserSession"; import Paginator from "@/components/Paginator"; import { QueryTagsControl } from "@/components/tags-control/TagsControl"; import SchedulePhrase from "@/components/queries/SchedulePhrase"; import TimeAgo from "@/components/TimeAgo"; import Layout from "@/components/admin/Layout"; -import { ErrorBoundaryContext } from "@/components/ErrorBoundary"; import { wrap as itemsList, ControllerType } from "@/components/items-list/ItemsList"; import { ItemsSource } from "@/components/items-list/classes/ItemsSource"; @@ -170,20 +169,8 @@ const OutdatedQueriesPage = itemsList( () => new StateStorage({ orderByField: "created_at", orderByReverse: true }) ); -export default { +export default routeWithUserSession({ path: "/admin/queries/outdated", title: "Outdated Queries", - render: currentRoute => ( - - - {({ handleError }) => ( - - )} - - - ), -}; + render: pageProps => , +}); diff --git a/client/app/pages/admin/SystemStatus.jsx b/client/app/pages/admin/SystemStatus.jsx index b1d37b354e..9d659738f4 100644 --- a/client/app/pages/admin/SystemStatus.jsx +++ b/client/app/pages/admin/SystemStatus.jsx @@ -3,9 +3,8 @@ import React from "react"; import { axios } from "@/services/axios"; import PropTypes from "prop-types"; -import AuthenticatedPageWrapper from "@/components/ApplicationArea/AuthenticatedPageWrapper"; +import routeWithUserSession from "@/components/ApplicationArea/routeWithUserSession"; import Layout from "@/components/admin/Layout"; -import { ErrorBoundaryContext } from "@/components/ErrorBoundary"; import * as StatusBlock from "@/components/admin/StatusBlock"; import recordEvent from "@/services/recordEvent"; @@ -81,14 +80,8 @@ class SystemStatus extends React.Component { } } -export default { +export default routeWithUserSession({ path: "/admin/status", title: "System Status", - render: currentRoute => ( - - - {({ handleError }) => } - - - ), -}; + render: pageProps => , +}); diff --git a/client/app/pages/alert/Alert.jsx b/client/app/pages/alert/Alert.jsx index 68edbb4a66..be147858dc 100644 --- a/client/app/pages/alert/Alert.jsx +++ b/client/app/pages/alert/Alert.jsx @@ -3,9 +3,8 @@ import React from "react"; import PropTypes from "prop-types"; import { currentUser } from "@/services/auth"; -import AuthenticatedPageWrapper from "@/components/ApplicationArea/AuthenticatedPageWrapper"; +import routeWithUserSession from "@/components/ApplicationArea/routeWithUserSession"; import navigateTo from "@/components/ApplicationArea/navigateTo"; -import { ErrorBoundaryContext } from "@/components/ErrorBoundary"; import notification from "@/services/notification"; import AlertService from "@/services/alert"; import { Query as QueryService } from "@/services/query"; @@ -31,7 +30,7 @@ export function getDefaultName(alert) { return defaultNameBuilder(alert); } -class AlertPage extends React.Component { +class Alert extends React.Component { static propTypes = { mode: PropTypes.oneOf(values(MODES)), alertId: PropTypes.string, @@ -253,37 +252,19 @@ class AlertPage extends React.Component { } export default [ - { + routeWithUserSession({ path: "/alerts/new", title: "New Alert", - render: currentRoute => ( - - - {({ handleError }) => } - - - ), - }, - { + render: pageProps => , + }), + routeWithUserSession({ path: "/alerts/:alertId([0-9]+)", title: "Alert", - render: currentRoute => ( - - - {({ handleError }) => } - - - ), - }, - { + render: pageProps => , + }), + routeWithUserSession({ path: "/alerts/:alertId([0-9]+)/edit", title: "Alert", - render: currentRoute => ( - - - {({ handleError }) => } - - - ), - }, + render: pageProps => , + }), ]; diff --git a/client/app/pages/alerts/AlertsList.jsx b/client/app/pages/alerts/AlertsList.jsx index 620a2aa3ea..2b67728f78 100644 --- a/client/app/pages/alerts/AlertsList.jsx +++ b/client/app/pages/alerts/AlertsList.jsx @@ -1,11 +1,10 @@ import { toUpper } from "lodash"; import React from "react"; -import AuthenticatedPageWrapper from "@/components/ApplicationArea/AuthenticatedPageWrapper"; +import routeWithUserSession from "@/components/ApplicationArea/routeWithUserSession"; import PageHeader from "@/components/PageHeader"; import Paginator from "@/components/Paginator"; import EmptyState from "@/components/empty-state/EmptyState"; -import { ErrorBoundaryContext } from "@/components/ErrorBoundary"; -import { wrap as liveItemsList, ControllerType } from "@/components/items-list/ItemsList"; +import { wrap as itemsList, ControllerType } from "@/components/items-list/ItemsList"; import { ResourceItemsSource } from "@/components/items-list/classes/ItemsSource"; import { StateStorage } from "@/components/items-list/classes/StateStorage"; @@ -70,7 +69,7 @@ class AlertsList extends React.Component { return (
- +
{!controller.isLoaded && } {controller.isLoaded && controller.isEmpty && ( @@ -106,7 +105,7 @@ class AlertsList extends React.Component { } } -const AlertsListPage = liveItemsList( +const AlertsListPage = itemsList( AlertsList, () => new ResourceItemsSource({ @@ -121,20 +120,8 @@ const AlertsListPage = liveItemsList( () => new StateStorage({ orderByField: "created_at", orderByReverse: true, itemsPerPage: 20 }) ); -export default { +export default routeWithUserSession({ path: "/alerts", title: "Alerts", - render: currentRoute => ( - - - {({ handleError }) => ( - - )} - - - ), -}; + render: pageProps => , +}); diff --git a/client/app/pages/dashboards/DashboardList.jsx b/client/app/pages/dashboards/DashboardList.jsx index a8937009e6..42df1ed83b 100644 --- a/client/app/pages/dashboards/DashboardList.jsx +++ b/client/app/pages/dashboards/DashboardList.jsx @@ -1,6 +1,6 @@ import React from "react"; -import AuthenticatedPageWrapper from "@/components/ApplicationArea/AuthenticatedPageWrapper"; +import routeWithUserSession from "@/components/ApplicationArea/routeWithUserSession"; import PageHeader from "@/components/PageHeader"; import Paginator from "@/components/Paginator"; import { DashboardTagsControl } from "@/components/tags-control/TagsControl"; @@ -8,7 +8,6 @@ import { DashboardTagsControl } from "@/components/tags-control/TagsControl"; import { wrap as itemsList, ControllerType } from "@/components/items-list/ItemsList"; import { ResourceItemsSource } from "@/components/items-list/classes/ItemsSource"; import { UrlStateStorage } from "@/components/items-list/classes/StateStorage"; -import { ErrorBoundaryContext } from "@/components/ErrorBoundary"; import LoadingState from "@/components/items-list/components/LoadingState"; import * as Sidebar from "@/components/items-list/components/Sidebar"; import ItemsTable, { Columns } from "@/components/items-list/components/ItemsTable"; @@ -76,7 +75,7 @@ class DashboardList extends React.Component { return (
- + ( - - - {({ handleError }) => ( - - )} - - - ), - }, - { + render: pageProps => , + }), + routeWithUserSession({ path: "/dashboards/favorites", title: "Favorite Dashboards", - render: currentRoute => ( - - - {({ handleError }) => ( - - )} - - - ), - }, + render: pageProps => , + }), ]; diff --git a/client/app/pages/dashboards/DashboardPage.jsx b/client/app/pages/dashboards/DashboardPage.jsx index 72d0fbcd59..cf66cddda1 100644 --- a/client/app/pages/dashboards/DashboardPage.jsx +++ b/client/app/pages/dashboards/DashboardPage.jsx @@ -9,14 +9,13 @@ import Menu from "antd/lib/menu"; import Icon from "antd/lib/icon"; import Modal from "antd/lib/modal"; import Tooltip from "antd/lib/tooltip"; -import AuthenticatedPageWrapper from "@/components/ApplicationArea/AuthenticatedPageWrapper"; +import routeWithUserSession from "@/components/ApplicationArea/routeWithUserSession"; import DashboardGrid from "@/components/dashboards/DashboardGrid"; import FavoritesControl from "@/components/FavoritesControl"; import EditInPlace from "@/components/EditInPlace"; import { DashboardTagsControl } from "@/components/tags-control/TagsControl"; import Parameters from "@/components/Parameters"; import Filters from "@/components/Filters"; -import { ErrorBoundaryContext } from "@/components/ErrorBoundary"; import { Dashboard } from "@/services/dashboard"; import recordEvent from "@/services/recordEvent"; import getTags from "@/services/getTags"; @@ -407,13 +406,7 @@ DashboardPage.defaultProps = { onError: PropTypes.func, }; -export default { +export default routeWithUserSession({ path: "/dashboard/:dashboardSlug", - render: currentRoute => ( - - - {({ handleError }) => } - - - ), -}; + render: pageProps => , +}); diff --git a/client/app/pages/dashboards/PublicDashboardPage.jsx b/client/app/pages/dashboards/PublicDashboardPage.jsx index fa37c138d6..dcc9a79a24 100644 --- a/client/app/pages/dashboards/PublicDashboardPage.jsx +++ b/client/app/pages/dashboards/PublicDashboardPage.jsx @@ -1,13 +1,12 @@ import { isEmpty } from "lodash"; import React from "react"; import PropTypes from "prop-types"; -import SignedOutPageWrapper from "@/components/ApplicationArea/SignedOutPageWrapper"; +import routeWithApiKeySession from "@/components/ApplicationArea/routeWithApiKeySession"; import BigMessage from "@/components/BigMessage"; import PageHeader from "@/components/PageHeader"; import Parameters from "@/components/Parameters"; import DashboardGrid from "@/components/dashboards/DashboardGrid"; import Filters from "@/components/Filters"; -import { ErrorBoundaryContext } from "@/components/ErrorBoundary"; import { Dashboard } from "@/services/dashboard"; import logoUrl from "@/assets/images/redash_icon_small.png"; import useDashboard from "./hooks/useDashboard"; @@ -96,14 +95,8 @@ class PublicDashboardPage extends React.Component { } } -export default { +export default routeWithApiKeySession({ path: "/public/dashboards/:token", - authenticated: false, - render: currentRoute => ( - - - {({ handleError }) => } - - - ), -}; + render: pageProps => , + getApiKey: currentRoute => currentRoute.routeParams.token, +}); diff --git a/client/app/pages/data-sources/DataSourcesList.jsx b/client/app/pages/data-sources/DataSourcesList.jsx index e21d779594..0512285511 100644 --- a/client/app/pages/data-sources/DataSourcesList.jsx +++ b/client/app/pages/data-sources/DataSourcesList.jsx @@ -4,7 +4,7 @@ import Button from "antd/lib/button"; import { isEmpty } from "lodash"; import DataSource, { IMG_ROOT } from "@/services/data-source"; import { policy } from "@/services/policy"; -import AuthenticatedPageWrapper from "@/components/ApplicationArea/AuthenticatedPageWrapper"; +import routeWithUserSession from "@/components/ApplicationArea/routeWithUserSession"; import navigateTo from "@/components/ApplicationArea/navigateTo"; import CardsList from "@/components/cards-list/CardsList"; import LoadingState from "@/components/items-list/components/LoadingState"; @@ -12,7 +12,6 @@ import CreateSourceDialog from "@/components/CreateSourceDialog"; import DynamicComponent from "@/components/DynamicComponent"; import helper from "@/components/dynamic-form/dynamicFormHelper"; import wrapSettingsTab from "@/components/SettingsWrapper"; -import { ErrorBoundaryContext } from "@/components/ErrorBoundary"; import recordEvent from "@/services/recordEvent"; class DataSourcesList extends React.Component { @@ -156,28 +155,14 @@ const DataSourcesListPage = wrapSettingsTab( ); export default [ - { + routeWithUserSession({ path: "/data_sources", title: "Data Sources", - render: currentRoute => ( - - - {({ handleError }) => } - - - ), - }, - { + render: pageProps => , + }), + routeWithUserSession({ path: "/data_sources/new", title: "Data Sources", - render: currentRoute => ( - - - {({ handleError }) => ( - - )} - - - ), - }, + render: pageProps => , + }), ]; diff --git a/client/app/pages/data-sources/EditDataSource.jsx b/client/app/pages/data-sources/EditDataSource.jsx index a9bca67293..f04ea18183 100644 --- a/client/app/pages/data-sources/EditDataSource.jsx +++ b/client/app/pages/data-sources/EditDataSource.jsx @@ -3,7 +3,7 @@ import PropTypes from "prop-types"; import { get, find, toUpper } from "lodash"; import Modal from "antd/lib/modal"; import DataSource, { IMG_ROOT } from "@/services/data-source"; -import AuthenticatedPageWrapper from "@/components/ApplicationArea/AuthenticatedPageWrapper"; +import routeWithUserSession from "@/components/ApplicationArea/routeWithUserSession"; import navigateTo from "@/components/ApplicationArea/navigateTo"; import notification from "@/services/notification"; import LoadingState from "@/components/items-list/components/LoadingState"; @@ -11,7 +11,6 @@ import DynamicForm from "@/components/dynamic-form/DynamicForm"; import helper from "@/components/dynamic-form/dynamicFormHelper"; import HelpTrigger, { TYPES as HELP_TRIGGER_TYPES } from "@/components/HelpTrigger"; import wrapSettingsTab from "@/components/SettingsWrapper"; -import { ErrorBoundaryContext } from "@/components/ErrorBoundary"; class EditDataSource extends React.Component { static propTypes = { @@ -139,14 +138,8 @@ class EditDataSource extends React.Component { const EditDataSourcePage = wrapSettingsTab(null, EditDataSource); -export default { +export default routeWithUserSession({ path: "/data_sources/:dataSourceId([0-9]+)", title: "Data Sources", - render: currentRoute => ( - - - {({ handleError }) => } - - - ), -}; + render: pageProps => , +}); diff --git a/client/app/pages/destinations/DestinationsList.jsx b/client/app/pages/destinations/DestinationsList.jsx index 4a4828bccb..e807df188a 100644 --- a/client/app/pages/destinations/DestinationsList.jsx +++ b/client/app/pages/destinations/DestinationsList.jsx @@ -4,14 +4,13 @@ import Button from "antd/lib/button"; import { isEmpty, isString, find, get } from "lodash"; import Destination, { IMG_ROOT } from "@/services/destination"; import { policy } from "@/services/policy"; -import AuthenticatedPageWrapper from "@/components/ApplicationArea/AuthenticatedPageWrapper"; +import routeWithUserSession from "@/components/ApplicationArea/routeWithUserSession"; import navigateTo from "@/components/ApplicationArea/navigateTo"; import CardsList from "@/components/cards-list/CardsList"; import LoadingState from "@/components/items-list/components/LoadingState"; import CreateSourceDialog from "@/components/CreateSourceDialog"; import helper from "@/components/dynamic-form/dynamicFormHelper"; import wrapSettingsTab from "@/components/SettingsWrapper"; -import { ErrorBoundaryContext } from "@/components/ErrorBoundary"; class DestinationsList extends React.Component { static propTypes = { @@ -144,28 +143,14 @@ const DestinationsListPage = wrapSettingsTab( ); export default [ - { + routeWithUserSession({ path: "/destinations", title: "Alert Destinations", - render: currentRoute => ( - - - {({ handleError }) => } - - - ), - }, - { + render: pageProps => , + }), + routeWithUserSession({ path: "/destinations/new", title: "Alert Destinations", - render: currentRoute => ( - - - {({ handleError }) => ( - - )} - - - ), - }, + render: pageProps => , + }), ]; diff --git a/client/app/pages/destinations/EditDestination.jsx b/client/app/pages/destinations/EditDestination.jsx index bd5f54259e..3d11df6a49 100644 --- a/client/app/pages/destinations/EditDestination.jsx +++ b/client/app/pages/destinations/EditDestination.jsx @@ -3,14 +3,13 @@ import React from "react"; import PropTypes from "prop-types"; import Modal from "antd/lib/modal"; import Destination, { IMG_ROOT } from "@/services/destination"; -import AuthenticatedPageWrapper from "@/components/ApplicationArea/AuthenticatedPageWrapper"; +import routeWithUserSession from "@/components/ApplicationArea/routeWithUserSession"; import navigateTo from "@/components/ApplicationArea/navigateTo"; import notification from "@/services/notification"; import LoadingState from "@/components/items-list/components/LoadingState"; import DynamicForm from "@/components/dynamic-form/DynamicForm"; import helper from "@/components/dynamic-form/dynamicFormHelper"; import wrapSettingsTab from "@/components/SettingsWrapper"; -import { ErrorBoundaryContext } from "@/components/ErrorBoundary"; class EditDestination extends React.Component { static propTypes = { @@ -106,14 +105,8 @@ class EditDestination extends React.Component { const EditDestinationPage = wrapSettingsTab(null, EditDestination); -export default { +export default routeWithUserSession({ path: "/destinations/:destinationId([0-9]+)", title: "Alert Destinations", - render: currentRoute => ( - - - {({ handleError }) => } - - - ), -}; + render: pageProps => , +}); diff --git a/client/app/pages/groups/GroupDataSources.jsx b/client/app/pages/groups/GroupDataSources.jsx index 360936f226..9cc409b3e9 100644 --- a/client/app/pages/groups/GroupDataSources.jsx +++ b/client/app/pages/groups/GroupDataSources.jsx @@ -5,11 +5,11 @@ import Dropdown from "antd/lib/dropdown"; import Menu from "antd/lib/menu"; import Icon from "antd/lib/icon"; -import AuthenticatedPageWrapper from "@/components/ApplicationArea/AuthenticatedPageWrapper"; +import routeWithUserSession from "@/components/ApplicationArea/routeWithUserSession"; import navigateTo from "@/components/ApplicationArea/navigateTo"; import Paginator from "@/components/Paginator"; -import { wrap as liveItemsList, ControllerType } from "@/components/items-list/ItemsList"; +import { wrap as itemsList, ControllerType } from "@/components/items-list/ItemsList"; import { ResourceItemsSource } from "@/components/items-list/classes/ItemsSource"; import { StateStorage } from "@/components/items-list/classes/StateStorage"; @@ -23,7 +23,6 @@ import ListItemAddon from "@/components/groups/ListItemAddon"; import Sidebar from "@/components/groups/DetailsPageSidebar"; import Layout from "@/components/layouts/ContentWithSidebar"; import wrapSettingsTab from "@/components/SettingsWrapper"; -import { ErrorBoundaryContext } from "@/components/ErrorBoundary"; import notification from "@/services/notification"; import { currentUser } from "@/services/auth"; @@ -231,7 +230,7 @@ class GroupDataSources extends React.Component { const GroupDataSourcesPage = wrapSettingsTab( null, - liveItemsList( + itemsList( GroupDataSources, () => new ResourceItemsSource({ @@ -247,20 +246,8 @@ const GroupDataSourcesPage = wrapSettingsTab( ) ); -export default { +export default routeWithUserSession({ path: "/groups/:groupId([0-9]+)/data_sources", title: "Group Data Sources", - render: currentRoute => ( - - - {({ handleError }) => ( - - )} - - - ), -}; + render: pageProps => , +}); diff --git a/client/app/pages/groups/GroupMembers.jsx b/client/app/pages/groups/GroupMembers.jsx index eebe42c941..1548db0b0d 100644 --- a/client/app/pages/groups/GroupMembers.jsx +++ b/client/app/pages/groups/GroupMembers.jsx @@ -2,11 +2,11 @@ import { includes, map } from "lodash"; import React from "react"; import Button from "antd/lib/button"; -import AuthenticatedPageWrapper from "@/components/ApplicationArea/AuthenticatedPageWrapper"; +import routeWithUserSession from "@/components/ApplicationArea/routeWithUserSession"; import navigateTo from "@/components/ApplicationArea/navigateTo"; import Paginator from "@/components/Paginator"; -import { wrap as liveItemsList, ControllerType } from "@/components/items-list/ItemsList"; +import { wrap as itemsList, ControllerType } from "@/components/items-list/ItemsList"; import { ResourceItemsSource } from "@/components/items-list/classes/ItemsSource"; import { StateStorage } from "@/components/items-list/classes/StateStorage"; @@ -20,7 +20,6 @@ import ListItemAddon from "@/components/groups/ListItemAddon"; import Sidebar from "@/components/groups/DetailsPageSidebar"; import Layout from "@/components/layouts/ContentWithSidebar"; import wrapSettingsTab from "@/components/SettingsWrapper"; -import { ErrorBoundaryContext } from "@/components/ErrorBoundary"; import notification from "@/services/notification"; import { currentUser } from "@/services/auth"; @@ -194,7 +193,7 @@ class GroupMembers extends React.Component { const GroupMembersPage = wrapSettingsTab( null, - liveItemsList( + itemsList( GroupMembers, () => new ResourceItemsSource({ @@ -210,20 +209,8 @@ const GroupMembersPage = wrapSettingsTab( ) ); -export default { +export default routeWithUserSession({ path: "/groups/:groupId([0-9]+)", title: "Group Members", - render: currentRoute => ( - - - {({ handleError }) => ( - - )} - - - ), -}; + render: pageProps => , +}); diff --git a/client/app/pages/groups/GroupsList.jsx b/client/app/pages/groups/GroupsList.jsx index 8f5406eae5..e3d43fe63a 100644 --- a/client/app/pages/groups/GroupsList.jsx +++ b/client/app/pages/groups/GroupsList.jsx @@ -1,11 +1,11 @@ import React from "react"; import Button from "antd/lib/button"; -import AuthenticatedPageWrapper from "@/components/ApplicationArea/AuthenticatedPageWrapper"; +import routeWithUserSession from "@/components/ApplicationArea/routeWithUserSession"; import navigateTo from "@/components/ApplicationArea/navigateTo"; import Paginator from "@/components/Paginator"; -import { wrap as liveItemsList, ControllerType } from "@/components/items-list/ItemsList"; +import { wrap as itemsList, ControllerType } from "@/components/items-list/ItemsList"; import { ResourceItemsSource } from "@/components/items-list/classes/ItemsSource"; import { StateStorage } from "@/components/items-list/classes/StateStorage"; @@ -16,7 +16,6 @@ import ItemsTable, { Columns } from "@/components/items-list/components/ItemsTab import CreateGroupDialog from "@/components/groups/CreateGroupDialog"; import DeleteGroupButton from "@/components/groups/DeleteGroupButton"; import wrapSettingsTab from "@/components/SettingsWrapper"; -import { ErrorBoundaryContext } from "@/components/ErrorBoundary"; import Group from "@/services/group"; import { currentUser } from "@/services/auth"; @@ -133,7 +132,7 @@ const GroupsListPage = wrapSettingsTab( path: "groups", order: 3, }, - liveItemsList( + itemsList( GroupsList, () => new ResourceItemsSource({ @@ -149,20 +148,8 @@ const GroupsListPage = wrapSettingsTab( ) ); -export default { +export default routeWithUserSession({ path: "/groups", title: "Groups", - render: currentRoute => ( - - - {({ handleError }) => ( - - )} - - - ), -}; + render: pageProps => , +}); diff --git a/client/app/pages/home/Home.jsx b/client/app/pages/home/Home.jsx index 2ef9abfdfd..641d0b6d17 100644 --- a/client/app/pages/home/Home.jsx +++ b/client/app/pages/home/Home.jsx @@ -4,7 +4,7 @@ import PropTypes from "prop-types"; import { includes, isEmpty } from "lodash"; import Alert from "antd/lib/alert"; import Icon from "antd/lib/icon"; -import AuthenticatedPageWrapper from "@/components/ApplicationArea/AuthenticatedPageWrapper"; +import routeWithUserSession from "@/components/ApplicationArea/routeWithUserSession"; import EmptyState from "@/components/empty-state/EmptyState"; import DynamicComponent from "@/components/DynamicComponent"; import BeaconConsent from "@/components/BeaconConsent"; @@ -173,12 +173,8 @@ function Home() { ); } -export default { +export default routeWithUserSession({ path: "/", title: "Redash", - render: currentRoute => ( - - - - ), -}; + render: pageProps => , +}); diff --git a/client/app/pages/queries-list/QueriesList.jsx b/client/app/pages/queries-list/QueriesList.jsx index 287973978c..f528be1ffd 100644 --- a/client/app/pages/queries-list/QueriesList.jsx +++ b/client/app/pages/queries-list/QueriesList.jsx @@ -1,6 +1,6 @@ import React from "react"; -import AuthenticatedPageWrapper from "@/components/ApplicationArea/AuthenticatedPageWrapper"; +import routeWithUserSession from "@/components/ApplicationArea/routeWithUserSession"; import PageHeader from "@/components/PageHeader"; import Paginator from "@/components/Paginator"; import { QueryTagsControl } from "@/components/tags-control/TagsControl"; @@ -15,7 +15,6 @@ import * as Sidebar from "@/components/items-list/components/Sidebar"; import ItemsTable, { Columns } from "@/components/items-list/components/ItemsTable"; import Layout from "@/components/layouts/ContentWithSidebar"; -import { ErrorBoundaryContext } from "@/components/ErrorBoundary"; import { Query } from "@/services/query"; import { currentUser } from "@/services/auth"; @@ -93,7 +92,7 @@ class QueriesList extends React.Component { return (
- + ( - - - {({ handleError }) => ( - - )} - - - ), - }, - { + render: pageProps => , + }), + routeWithUserSession({ path: "/queries/favorites", title: "Favorite Queries", - render: currentRoute => ( - - - {({ handleError }) => ( - - )} - - - ), - }, - { + render: pageProps => , + }), + routeWithUserSession({ path: "/queries/archive", title: "Archived Queries", - render: currentRoute => ( - - - {({ handleError }) => ( - - )} - - - ), - }, - { + render: pageProps => , + }), + routeWithUserSession({ path: "/queries/my", title: "My Queries", - render: currentRoute => ( - - - {({ handleError }) => ( - - )} - - - ), - }, + render: pageProps => , + }), ]; diff --git a/client/app/pages/queries/QuerySource.jsx b/client/app/pages/queries/QuerySource.jsx index b4087d6a7c..f109148a27 100644 --- a/client/app/pages/queries/QuerySource.jsx +++ b/client/app/pages/queries/QuerySource.jsx @@ -3,7 +3,7 @@ import React, { useState, useRef, useEffect, useCallback } from "react"; import PropTypes from "prop-types"; import { useDebouncedCallback } from "use-debounce"; import Select from "antd/lib/select"; -import AuthenticatedPageWrapper from "@/components/ApplicationArea/AuthenticatedPageWrapper"; +import routeWithUserSession from "@/components/ApplicationArea/routeWithUserSession"; import Resizable from "@/components/Resizable"; import Parameters from "@/components/Parameters"; import EditInPlace from "@/components/EditInPlace"; @@ -11,7 +11,6 @@ import EditVisualizationButton from "@/components/EditVisualizationButton"; import QueryControlDropdown from "@/components/EditVisualizationButton/QueryControlDropdown"; import QueryEditor from "@/components/queries/QueryEditor"; import TimeAgo from "@/components/TimeAgo"; -import { ErrorBoundaryContext } from "@/components/ErrorBoundary"; import { durationHumanize, prettySize } from "@/lib/utils"; import { Query } from "@/services/query"; import recordEvent from "@/services/recordEvent"; @@ -445,30 +444,20 @@ QuerySource.propTypes = { }; export default [ - { + routeWithUserSession({ path: "/queries/new", - render: currentRoute => ( - - - {({ handleError }) => } - - - ), + render: pageProps => , resolve: { query: () => Query.newQuery(), }, - }, - { + bodyClass: "fixed-layout", + }), + routeWithUserSession({ path: "/queries/:queryId([0-9]+)/source", - render: currentRoute => ( - - - {({ handleError }) => } - - - ), + render: pageProps => , resolve: { query: ({ queryId }) => Query.get({ id: queryId }), }, - }, + bodyClass: "fixed-layout", + }), ]; diff --git a/client/app/pages/queries/QueryView.jsx b/client/app/pages/queries/QueryView.jsx index f4be264071..db6ea15a39 100644 --- a/client/app/pages/queries/QueryView.jsx +++ b/client/app/pages/queries/QueryView.jsx @@ -2,13 +2,12 @@ import React, { useState, useEffect, useCallback } from "react"; import PropTypes from "prop-types"; import Divider from "antd/lib/divider"; -import AuthenticatedPageWrapper from "@/components/ApplicationArea/AuthenticatedPageWrapper"; +import routeWithUserSession from "@/components/ApplicationArea/routeWithUserSession"; import EditInPlace from "@/components/EditInPlace"; import Parameters from "@/components/Parameters"; import TimeAgo from "@/components/TimeAgo"; import QueryControlDropdown from "@/components/EditVisualizationButton/QueryControlDropdown"; import EditVisualizationButton from "@/components/EditVisualizationButton"; -import { ErrorBoundaryContext } from "@/components/ErrorBoundary"; import { Query } from "@/services/query"; import DataSource from "@/services/data-source"; @@ -185,16 +184,10 @@ function QueryView(props) { QueryView.propTypes = { query: PropTypes.object.isRequired }; // eslint-disable-line react/forbid-prop-types -export default { +export default routeWithUserSession({ path: "/queries/:queryId([0-9]+)", - render: currentRoute => ( - - - {({ handleError }) => } - - - ), + render: pageProps => , resolve: { query: ({ queryId }) => Query.get({ id: queryId }), }, -}; +}); diff --git a/client/app/pages/queries/VisualizationEmbed.jsx b/client/app/pages/queries/VisualizationEmbed.jsx index 842eb9f380..6589a9b39d 100644 --- a/client/app/pages/queries/VisualizationEmbed.jsx +++ b/client/app/pages/queries/VisualizationEmbed.jsx @@ -8,7 +8,7 @@ import Dropdown from "antd/lib/dropdown"; import Icon from "antd/lib/icon"; import Menu from "antd/lib/menu"; import Tooltip from "antd/lib/tooltip"; -import SignedOutPageWrapper from "@/components/ApplicationArea/SignedOutPageWrapper"; +import routeWithApiKeySession from "@/components/ApplicationArea/routeWithApiKeySession"; import { Query } from "@/services/query"; import location from "@/services/location"; import { formatDateTime } from "@/lib/utils"; @@ -18,7 +18,6 @@ import { Moment } from "@/components/proptypes"; import TimeAgo from "@/components/TimeAgo"; import Timer from "@/components/Timer"; import QueryResultsLink from "@/components/EditVisualizationButton/QueryResultsLink"; -import { ErrorBoundaryContext } from "@/components/ErrorBoundary"; import VisualizationName from "@/visualizations/VisualizationName"; import VisualizationRenderer from "@/visualizations/VisualizationRenderer"; import { VisualizationType } from "@/visualizations"; @@ -265,16 +264,8 @@ VisualizationEmbed.defaultProps = { onError: () => {}, }; -export default { +export default routeWithApiKeySession({ path: "/embed/query/:queryId/visualization/:visualizationId", - authenticated: false, - render: currentRoute => ( - - - {({ handleError }) => ( - - )} - - - ), -}; + render: pageProps => , + getApiKey: () => location.search.api_key, +}); diff --git a/client/app/pages/query-snippets/QuerySnippetsList.jsx b/client/app/pages/query-snippets/QuerySnippetsList.jsx index 2459587faf..ee3b4920fb 100644 --- a/client/app/pages/query-snippets/QuerySnippetsList.jsx +++ b/client/app/pages/query-snippets/QuerySnippetsList.jsx @@ -3,19 +3,18 @@ import React from "react"; import Button from "antd/lib/button"; import Modal from "antd/lib/modal"; -import AuthenticatedPageWrapper from "@/components/ApplicationArea/AuthenticatedPageWrapper"; +import routeWithUserSession from "@/components/ApplicationArea/routeWithUserSession"; import navigateTo from "@/components/ApplicationArea/navigateTo"; import Paginator from "@/components/Paginator"; import QuerySnippetDialog from "@/components/query-snippets/QuerySnippetDialog"; -import { wrap as liveItemsList, ControllerType } from "@/components/items-list/ItemsList"; +import { wrap as itemsList, ControllerType } from "@/components/items-list/ItemsList"; import { ResourceItemsSource } from "@/components/items-list/classes/ItemsSource"; import { StateStorage } from "@/components/items-list/classes/StateStorage"; import LoadingState from "@/components/items-list/components/LoadingState"; import ItemsTable, { Columns } from "@/components/items-list/components/ItemsTable"; import wrapSettingsTab from "@/components/SettingsWrapper"; -import { ErrorBoundaryContext } from "@/components/ErrorBoundary"; import QuerySnippet from "@/services/query-snippet"; import { currentUser } from "@/services/auth"; @@ -193,7 +192,7 @@ const QuerySnippetsListPage = wrapSettingsTab( path: "query_snippets", order: 5, }, - liveItemsList( + itemsList( QuerySnippetsList, () => new ResourceItemsSource({ @@ -210,38 +209,14 @@ const QuerySnippetsListPage = wrapSettingsTab( ); export default [ - { + routeWithUserSession({ path: "/query_snippets", title: "Query Snippets", - render: currentRoute => ( - - - {({ handleError }) => ( - - )} - - - ), - }, - { + render: pageProps => , + }), + routeWithUserSession({ path: "/query_snippets/:querySnippetId(new|[0-9]+)", title: "Query Snippets", - render: currentRoute => ( - - - {({ handleError }) => ( - - )} - - - ), - }, + render: pageProps => , + }), ]; diff --git a/client/app/pages/settings/OrganizationSettings.jsx b/client/app/pages/settings/OrganizationSettings.jsx index a87d25c968..d5758fbc30 100644 --- a/client/app/pages/settings/OrganizationSettings.jsx +++ b/client/app/pages/settings/OrganizationSettings.jsx @@ -9,9 +9,8 @@ import Input from "antd/lib/input"; import Select from "antd/lib/select"; import Checkbox from "antd/lib/checkbox"; import Tooltip from "antd/lib/tooltip"; -import AuthenticatedPageWrapper from "@/components/ApplicationArea/AuthenticatedPageWrapper"; +import routeWithUserSession from "@/components/ApplicationArea/routeWithUserSession"; import LoadingState from "@/components/items-list/components/LoadingState"; -import { ErrorBoundaryContext } from "@/components/ErrorBoundary"; import { clientConfig } from "@/services/auth"; import recordEvent from "@/services/recordEvent"; @@ -281,14 +280,8 @@ const OrganizationSettingsPage = wrapSettingsTab( OrganizationSettings ); -export default { +export default routeWithUserSession({ path: "/settings/organization", title: "Organization Settings", - render: currentRoute => ( - - - {({ handleError }) => } - - - ), -}; + render: pageProps => , +}); diff --git a/client/app/pages/users/UserProfile.jsx b/client/app/pages/users/UserProfile.jsx index 3b34386916..d1a7554557 100644 --- a/client/app/pages/users/UserProfile.jsx +++ b/client/app/pages/users/UserProfile.jsx @@ -1,13 +1,12 @@ import React from "react"; import PropTypes from "prop-types"; -import AuthenticatedPageWrapper from "@/components/ApplicationArea/AuthenticatedPageWrapper"; +import routeWithUserSession from "@/components/ApplicationArea/routeWithUserSession"; import EmailSettingsWarning from "@/components/EmailSettingsWarning"; import UserEdit from "@/components/users/UserEdit"; import UserShow from "@/components/users/UserShow"; import LoadingState from "@/components/items-list/components/LoadingState"; import wrapSettingsTab from "@/components/SettingsWrapper"; -import { ErrorBoundaryContext } from "@/components/ErrorBoundary"; import User from "@/services/user"; import { currentUser } from "@/services/auth"; import "./settings.less"; @@ -58,26 +57,14 @@ const UserProfilePage = wrapSettingsTab( ); export default [ - { + routeWithUserSession({ path: "/users/me", title: "Account", - render: currentRoute => ( - - - {({ handleError }) => } - - - ), - }, - { + render: pageProps => , + }), + routeWithUserSession({ path: "/users/:userId([0-9]+)", title: "Users", - render: currentRoute => ( - - - {({ handleError }) => } - - - ), - }, + render: pageProps => , + }), ]; diff --git a/client/app/pages/users/UsersList.jsx b/client/app/pages/users/UsersList.jsx index 39c760003f..a5f3e54f2f 100644 --- a/client/app/pages/users/UsersList.jsx +++ b/client/app/pages/users/UsersList.jsx @@ -4,7 +4,7 @@ import PropTypes from "prop-types"; import Button from "antd/lib/button"; import Modal from "antd/lib/modal"; -import AuthenticatedPageWrapper from "@/components/ApplicationArea/AuthenticatedPageWrapper"; +import routeWithUserSession from "@/components/ApplicationArea/routeWithUserSession"; import Paginator from "@/components/Paginator"; import DynamicComponent from "@/components/DynamicComponent"; import { UserPreviewCard } from "@/components/PreviewCard"; @@ -22,7 +22,6 @@ import ItemsTable, { Columns } from "@/components/items-list/components/ItemsTab import Layout from "@/components/layouts/ContentWithSidebar"; import CreateUserDialog from "@/components/users/CreateUserDialog"; import wrapSettingsTab from "@/components/SettingsWrapper"; -import { ErrorBoundaryContext } from "@/components/ErrorBoundary"; import { currentUser } from "@/services/auth"; import { policy } from "@/services/policy"; @@ -278,72 +277,24 @@ const UsersListPage = wrapSettingsTab( ); export default [ - { - path: "/users", - title: "Users", - render: currentRoute => ( - - - {({ handleError }) => ( - - )} - - - ), - }, - { + routeWithUserSession({ path: "/users/new", title: "Users", - render: currentRoute => ( - - - {({ handleError }) => ( - - )} - - - ), - }, - { + render: pageProps => , + }), + routeWithUserSession({ + path: "/users", + title: "Users", + render: pageProps => , + }), + routeWithUserSession({ path: "/users/pending", title: "Pending Invitations", - render: currentRoute => ( - - - {({ handleError }) => ( - - )} - - - ), - }, - { + render: pageProps => , + }), + routeWithUserSession({ path: "/users/disabled", title: "Disabled Users", - render: currentRoute => ( - - - {({ handleError }) => ( - - )} - - - ), - }, + render: pageProps => , + }), ];