view.tsx 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. import {useEffect, useState} from 'react';
  2. import {browserHistory, RouteComponentProps} from 'react-router';
  3. import pick from 'lodash/pick';
  4. import {updateDashboardVisit} from 'sentry/actionCreators/dashboards';
  5. import Feature from 'sentry/components/acl/feature';
  6. import {Alert} from 'sentry/components/alert';
  7. import ErrorBoundary from 'sentry/components/errorBoundary';
  8. import NotFound from 'sentry/components/errors/notFound';
  9. import * as Layout from 'sentry/components/layouts/thirds';
  10. import LoadingIndicator from 'sentry/components/loadingIndicator';
  11. import {t} from 'sentry/locale';
  12. import {Organization} from 'sentry/types';
  13. import useApi from 'sentry/utils/useApi';
  14. import withOrganization from 'sentry/utils/withOrganization';
  15. import DashboardDetail from './detail';
  16. import OrgDashboards from './orgDashboards';
  17. import {DashboardState, Widget} from './types';
  18. import {constructWidgetFromQuery} from './utils';
  19. const ALLOWED_PARAMS = [
  20. 'start',
  21. 'end',
  22. 'utc',
  23. 'period',
  24. 'project',
  25. 'environment',
  26. 'statsPeriod',
  27. ];
  28. type Props = RouteComponentProps<
  29. {dashboardId: string; orgId: string; widgetId?: number},
  30. {}
  31. > & {
  32. children: React.ReactNode;
  33. organization: Organization;
  34. };
  35. function ViewEditDashboard(props: Props) {
  36. const api = useApi();
  37. const {organization, params, location} = props;
  38. const dashboardId = params.dashboardId;
  39. const orgSlug = organization.slug;
  40. const [newWidget, setNewWidget] = useState<Widget | undefined>();
  41. const [dashboardInitialState, setDashboardInitialState] = useState(DashboardState.VIEW);
  42. useEffect(() => {
  43. if (dashboardId && dashboardId !== 'default-overview') {
  44. updateDashboardVisit(api, orgSlug, dashboardId);
  45. }
  46. }, [api, orgSlug, dashboardId]);
  47. useEffect(() => {
  48. const constructedWidget = constructWidgetFromQuery(location.query);
  49. setNewWidget(constructedWidget);
  50. // Clean up url after constructing widget from query string, only allow GHS params
  51. if (constructedWidget) {
  52. setDashboardInitialState(DashboardState.EDIT);
  53. browserHistory.replace({
  54. pathname: location.pathname,
  55. query: pick(location.query, ALLOWED_PARAMS),
  56. });
  57. }
  58. }, [location.pathname]);
  59. return (
  60. <DashboardBasicFeature organization={organization}>
  61. <OrgDashboards
  62. api={api}
  63. location={location}
  64. params={params}
  65. organization={organization}
  66. >
  67. {({dashboard, dashboards, error, onDashboardUpdate}) => {
  68. return error ? (
  69. <NotFound />
  70. ) : dashboard ? (
  71. <ErrorBoundary>
  72. <DashboardDetail
  73. {...props}
  74. initialState={dashboardInitialState}
  75. dashboard={dashboard}
  76. dashboards={dashboards}
  77. onDashboardUpdate={onDashboardUpdate}
  78. newWidget={newWidget}
  79. onSetNewWidget={() => setNewWidget(undefined)}
  80. />
  81. </ErrorBoundary>
  82. ) : (
  83. <LoadingIndicator />
  84. );
  85. }}
  86. </OrgDashboards>
  87. </DashboardBasicFeature>
  88. );
  89. }
  90. export default withOrganization(ViewEditDashboard);
  91. type FeatureProps = {
  92. children: React.ReactNode;
  93. organization: Organization;
  94. };
  95. export const DashboardBasicFeature = ({organization, children}: FeatureProps) => {
  96. const renderDisabled = () => (
  97. <Layout.Page withPadding>
  98. <Alert type="warning">{t("You don't have access to this feature")}</Alert>
  99. </Layout.Page>
  100. );
  101. return (
  102. <Feature
  103. hookName="feature-disabled:dashboards-page"
  104. features={['organizations:dashboards-basic']}
  105. organization={organization}
  106. renderDisabled={renderDisabled}
  107. >
  108. {children}
  109. </Feature>
  110. );
  111. };