view.tsx 3.8 KB

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