view.tsx 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  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 NotFound from 'sentry/components/errors/notFound';
  8. import LoadingIndicator from 'sentry/components/loadingIndicator';
  9. import {t} from 'sentry/locale';
  10. import {PageContent} from 'sentry/styles/organization';
  11. import {Organization} from 'sentry/types';
  12. import useApi from 'sentry/utils/useApi';
  13. import withOrganization from 'sentry/utils/withOrganization';
  14. import DashboardDetail from './detail';
  15. import OrgDashboards from './orgDashboards';
  16. import {DashboardState, Widget} from './types';
  17. import {constructWidgetFromQuery} from './utils';
  18. const ALLOWED_PARAMS = ['start', 'end', 'utc', 'period', 'project', 'environment'];
  19. type Props = RouteComponentProps<{dashboardId: string; orgId: string}, {}> & {
  20. children: React.ReactNode;
  21. organization: Organization;
  22. };
  23. function ViewEditDashboard(props: Props) {
  24. const api = useApi();
  25. const {organization, params, location} = props;
  26. const dashboardId = params.dashboardId;
  27. const orgSlug = organization.slug;
  28. const [newWidget, setNewWidget] = useState<Widget | undefined>();
  29. useEffect(() => {
  30. if (dashboardId && dashboardId !== 'default-overview') {
  31. updateDashboardVisit(api, orgSlug, dashboardId);
  32. }
  33. const constructedWidget = constructWidgetFromQuery(location.query);
  34. setNewWidget(constructedWidget);
  35. // Clean up url after constructing widget from query string, only allow GHS params
  36. if (constructedWidget) {
  37. browserHistory.replace({
  38. pathname: location.pathname,
  39. query: pick(location.query, ALLOWED_PARAMS),
  40. });
  41. }
  42. }, [api, orgSlug, dashboardId]);
  43. return (
  44. <DashboardBasicFeature organization={organization}>
  45. <OrgDashboards
  46. api={api}
  47. location={location}
  48. params={params}
  49. organization={organization}
  50. >
  51. {({dashboard, dashboards, error, onDashboardUpdate}) => {
  52. return error ? (
  53. <NotFound />
  54. ) : dashboard ? (
  55. <DashboardDetail
  56. {...props}
  57. initialState={newWidget ? DashboardState.EDIT : DashboardState.VIEW}
  58. dashboard={dashboard}
  59. dashboards={dashboards}
  60. onDashboardUpdate={onDashboardUpdate}
  61. newWidget={newWidget}
  62. />
  63. ) : (
  64. <LoadingIndicator />
  65. );
  66. }}
  67. </OrgDashboards>
  68. </DashboardBasicFeature>
  69. );
  70. }
  71. export default withOrganization(ViewEditDashboard);
  72. type FeatureProps = {
  73. children: React.ReactNode;
  74. organization: Organization;
  75. };
  76. export const DashboardBasicFeature = ({organization, children}: FeatureProps) => {
  77. const renderDisabled = () => (
  78. <PageContent>
  79. <Alert type="warning">{t("You don't have access to this feature")}</Alert>
  80. </PageContent>
  81. );
  82. return (
  83. <Feature
  84. hookName="feature-disabled:dashboards-page"
  85. features={['organizations:dashboards-basic']}
  86. organization={organization}
  87. renderDisabled={renderDisabled}
  88. >
  89. {children}
  90. </Feature>
  91. );
  92. };