Browse Source

feat(ddm): dashboard feature guard (#64875)

Ogi 1 year ago
parent
commit
d1a1eab8c8

+ 22 - 3
static/app/views/ddm/contextMenu.tsx

@@ -1,10 +1,12 @@
-import {useMemo} from 'react';
+import {Fragment, useMemo} from 'react';
 import * as Sentry from '@sentry/react';
 
 import {openAddToDashboardModal, openModal} from 'sentry/actionCreators/modal';
 import {navigateTo} from 'sentry/actionCreators/navigation';
+import FeatureDisabled from 'sentry/components/acl/featureDisabled';
 import type {MenuItemProps} from 'sentry/components/dropdownMenu';
 import {DropdownMenu} from 'sentry/components/dropdownMenu';
+import {Hovercard} from 'sentry/components/hovercard';
 import {
   IconClose,
   IconCopy,
@@ -33,6 +35,7 @@ import {OrganizationContext} from 'sentry/views/organizationContext';
 
 type ContextMenuProps = {
   displayType: MetricDisplayType;
+  hasDashboardFeature: boolean;
   metricsQuery: MetricsQuery;
   widgetIndex: number;
 };
@@ -41,6 +44,7 @@ export function MetricQueryContextMenu({
   metricsQuery,
   displayType,
   widgetIndex,
+  hasDashboardFeature,
 }: ContextMenuProps) {
   const organization = useOrganization();
   const router = useRouter();
@@ -88,8 +92,22 @@ export function MetricQueryContextMenu({
       {
         leadingItems: [<IconDashboard key="icon" />],
         key: 'add-dashoard',
-        label: t('Add to Dashboard'),
-        disabled: !createDashboardWidget,
+        label: hasDashboardFeature ? (
+          <Fragment>{t('Add to Dashboard')}</Fragment>
+        ) : (
+          <Hovercard
+            body={
+              <FeatureDisabled
+                features="organizations:dashboards-edit1"
+                hideHelpToggle
+                featureName={t('Dashboard Editing')}
+              />
+            }
+          >
+            {t('Add to Dashboard')}
+          </Hovercard>
+        ),
+        disabled: !hasDashboardFeature || !createDashboardWidget,
         onAction: () => {
           trackAnalytics('ddm.add-to-dashboard', {
             organization,
@@ -129,6 +147,7 @@ export function MetricQueryContextMenu({
       },
     ],
     [
+      hasDashboardFeature,
       createAlert,
       createDashboardWidget,
       metricsQuery.mri,

+ 13 - 4
static/app/views/ddm/layout.tsx

@@ -4,6 +4,7 @@ import * as Sentry from '@sentry/react';
 
 import emptyStateImg from 'sentry-images/spot/custom-metrics-empty-state.svg';
 
+import Feature from 'sentry/components/acl/feature';
 import {Button} from 'sentry/components/button';
 import FeatureBadge from 'sentry/components/featureBadge';
 import FloatingFeedbackWidget from 'sentry/components/feedback/widget/floatingFeedbackWidget';
@@ -63,10 +64,18 @@ export const DDMLayout = memo(() => {
           </Layout.Title>
         </Layout.HeaderContent>
         <Layout.HeaderActions>
-          <PageHeaderActions
-            showCustomMetricButton={hasMetrics}
-            addCustomMetric={() => addCustomMetric('header')}
-          />
+          <Feature
+            hookName="feature-disabled:dashboards-edit"
+            features="organizations:dashboards-edit"
+          >
+            {({hasFeature}) => (
+              <PageHeaderActions
+                showCustomMetricButton={hasMetrics}
+                addCustomMetric={() => addCustomMetric('header')}
+                hasDashboardFeature={hasFeature}
+              />
+            )}
+          </Feature>
         </Layout.HeaderActions>
       </Layout.Header>
       <Layout.Body>

+ 33 - 5
static/app/views/ddm/pageHeaderActions.tsx

@@ -1,10 +1,12 @@
-import {useCallback, useMemo} from 'react';
+import {Fragment, useCallback, useMemo} from 'react';
 import * as Sentry from '@sentry/react';
 
 import {navigateTo} from 'sentry/actionCreators/navigation';
+import FeatureDisabled from 'sentry/components/acl/featureDisabled';
 import {Button} from 'sentry/components/button';
 import ButtonBar from 'sentry/components/buttonBar';
 import {DropdownMenu} from 'sentry/components/dropdownMenu';
+import {Hovercard} from 'sentry/components/hovercard';
 import {
   IconAdd,
   IconBookmark,
@@ -28,10 +30,15 @@ import {useCreateDashboard} from 'sentry/views/ddm/useCreateDashboard';
 
 interface Props {
   addCustomMetric: () => void;
+  hasDashboardFeature: boolean;
   showCustomMetricButton: boolean;
 }
 
-export function PageHeaderActions({showCustomMetricButton, addCustomMetric}: Props) {
+export function PageHeaderActions({
+  showCustomMetricButton,
+  addCustomMetric,
+  hasDashboardFeature,
+}: Props) {
   const router = useRouter();
   const organization = useOrganization();
   const {selection} = usePageFilters();
@@ -62,7 +69,6 @@ export function PageHeaderActions({showCustomMetricButton, addCustomMetric}: Pro
       setDefaultQuery(router.location.query);
     }
   }, [isDefaultQuery, organization, router.location.query, setDefaultQuery]);
-
   const items = useMemo(
     () => [
       {
@@ -81,7 +87,22 @@ export function PageHeaderActions({showCustomMetricButton, addCustomMetric}: Pro
       {
         leadingItems: [<IconDashboard key="icon" />],
         key: 'add-dashboard',
-        label: t('Add to Dashboard'),
+        label: hasDashboardFeature ? (
+          <Fragment>{t('Add to Dashboard')}</Fragment>
+        ) : (
+          <Hovercard
+            body={
+              <FeatureDisabled
+                features="organizations:dashboards-edit1"
+                hideHelpToggle
+                featureName={t('Dashboard Editing')}
+              />
+            }
+          >
+            {t('Add to Dashboard')}
+          </Hovercard>
+        ),
+        disabled: !hasDashboardFeature,
         onAction: () => {
           trackAnalytics('ddm.add-to-dashboard', {
             organization,
@@ -97,7 +118,14 @@ export function PageHeaderActions({showCustomMetricButton, addCustomMetric}: Pro
         onAction: () => navigateTo(`/settings/projects/:projectId/metrics/`, router),
       },
     ],
-    [addWidget, createDashboard, hasEmptyWidget, organization, router]
+    [
+      addWidget,
+      createDashboard,
+      hasEmptyWidget,
+      organization,
+      router,
+      hasDashboardFeature,
+    ]
   );
 
   const alertItems = useMemo(

+ 23 - 14
static/app/views/ddm/queries.tsx

@@ -2,6 +2,7 @@ import {useCallback, useLayoutEffect} from 'react';
 import styled from '@emotion/styled';
 import * as echarts from 'echarts/core';
 
+import Feature from 'sentry/components/acl/feature';
 import {t} from 'sentry/locale';
 import {space} from 'sentry/styles/space';
 import type {MetricWidgetQueryParams} from 'sentry/utils/metrics/types';
@@ -60,20 +61,28 @@ export function Queries() {
             isEdit
             projects={selection.projects}
           />
-          <MetricQueryContextMenu
-            displayType={widget.displayType}
-            widgetIndex={index}
-            metricsQuery={{
-              mri: widget.mri,
-              query: widget.query,
-              op: widget.op,
-              groupBy: widget.groupBy,
-              projects: selection.projects,
-              datetime: selection.datetime,
-              environments: selection.environments,
-              title: widget.title,
-            }}
-          />
+          <Feature
+            hookName="feature-disabled:dashboards-edit"
+            features="organizations:dashboards-edit"
+          >
+            {({hasFeature}) => (
+              <MetricQueryContextMenu
+                displayType={widget.displayType}
+                widgetIndex={index}
+                hasDashboardFeature={hasFeature}
+                metricsQuery={{
+                  mri: widget.mri,
+                  query: widget.query,
+                  op: widget.op,
+                  groupBy: widget.groupBy,
+                  projects: selection.projects,
+                  datetime: selection.datetime,
+                  environments: selection.environments,
+                  title: widget.title,
+                }}
+              />
+            )}
+          </Feature>
         </Row>
       ))}
     </Wrapper>