Repository: getsentry/sentry
Pull request: fix(dashboards): hide add widget card behind feature flag
- closes: #71641 



Problem statement:
Remove "add widget" on team plans
Custom dashboards are a Business plan feature only. On Free you don’t see any dashboards, but on Team you have a default dashboard visible. The “Add Widget” card currently appears on Team plans, but results in errors.

Example: [redacted as requested by customer]

Hints from issue discussion:

Commit message: fix(dashboards): hide add widget card behind feature flag

Patch to review:
diff --git a/static/app/views/dashboards/addWidget.tsx b/static/app/views/dashboards/addWidget.tsx
index 9c6b68fc4ebc91..a8217e0d13e9eb 100644
--- a/static/app/views/dashboards/addWidget.tsx
+++ b/static/app/views/dashboards/addWidget.tsx
@@ -2,6 +2,7 @@ import {useCallback, useMemo} from 'react';
 import {useSortable} from '@dnd-kit/sortable';
 import styled from '@emotion/styled';
 
+import Feature from 'sentry/components/acl/feature';
 import type {ButtonProps} from 'sentry/components/button';
 import {Button} from 'sentry/components/button';
 import DropdownButton from 'sentry/components/dropdownButton';
@@ -43,44 +44,46 @@ function AddWidget({onAddWidget}: Props) {
   const organization = useOrganization();
 
   return (
-    <WidgetWrapper
-      key="add"
-      ref={setNodeRef}
-      displayType={DisplayType.BIG_NUMBER}
-      layoutId={ADD_WIDGET_BUTTON_DRAG_ID}
-      style={{originX: 0, originY: 0}}
-      animate={
-        transform
-          ? {
-              x: transform.x,
-              y: transform.y,
-              scaleX: transform?.scaleX && transform.scaleX <= 1 ? transform.scaleX : 1,
-              scaleY: transform?.scaleY && transform.scaleY <= 1 ? transform.scaleY : 1,
-            }
-          : initialStyles
-      }
-      transition={{
-        duration: 0.25,
-      }}
-    >
-      {hasCustomMetrics(organization) ? (
-        <InnerWrapper>
-          <AddWidgetButton
-            onAddWidget={onAddWidget}
-            aria-label={t('Add Widget')}
-            data-test-id="widget-add"
-          />
-        </InnerWrapper>
-      ) : (
-        <InnerWrapper onClick={() => onAddWidget(DataSet.EVENTS)}>
-          <AddButton
-            data-test-id="widget-add"
-            icon={<IconAdd size="lg" isCircled color="inactive" />}
-            aria-label={t('Add widget')}
-          />
-        </InnerWrapper>
-      )}
-    </WidgetWrapper>
+    <Feature features={'dashboards-edit'}>
+      <WidgetWrapper
+        key="add"
+        ref={setNodeRef}
+        displayType={DisplayType.BIG_NUMBER}
+        layoutId={ADD_WIDGET_BUTTON_DRAG_ID}
+        style={{originX: 0, originY: 0}}
+        animate={
+          transform
+            ? {
+                x: transform.x,
+                y: transform.y,
+                scaleX: transform?.scaleX && transform.scaleX <= 1 ? transform.scaleX : 1,
+                scaleY: transform?.scaleY && transform.scaleY <= 1 ? transform.scaleY : 1,
+              }
+            : initialStyles
+        }
+        transition={{
+          duration: 0.25,
+        }}
+      >
+        {hasCustomMetrics(organization) ? (
+          <InnerWrapper>
+            <AddWidgetButton
+              onAddWidget={onAddWidget}
+              aria-label={t('Add Widget')}
+              data-test-id="widget-add"
+            />
+          </InnerWrapper>
+        ) : (
+          <InnerWrapper onClick={() => onAddWidget(DataSet.EVENTS)}>
+            <AddButton
+              data-test-id="widget-add"
+              icon={<IconAdd size="lg" isCircled color="inactive" />}
+              aria-label={t('Add widget')}
+            />
+          </InnerWrapper>
+        )}
+      </WidgetWrapper>
+    </Feature>
   );
 }
 


Code review comments:
diff_hunk: @@ -43,44 +44,46 @@ function AddWidget({onAddWidget}: Props) {
   const organization = useOrganization();
 
   return (
-    <WidgetWrapper
-      key="add"
-      ref={setNodeRef}
-      displayType={DisplayType.BIG_NUMBER}
-      layoutId={ADD_WIDGET_BUTTON_DRAG_ID}
-      style={{originX: 0, originY: 0}}
-      animate={
-        transform
-          ? {
-              x: transform.x,
-              y: transform.y,
-              scaleX: transform?.scaleX && transform.scaleX <= 1 ? transform.scaleX : 1,
-              scaleY: transform?.scaleY && transform.scaleY <= 1 ? transform.scaleY : 1,
-            }
-          : initialStyles
-      }
-      transition={{
-        duration: 0.25,
-      }}
-    >
-      {hasCustomMetrics(organization) ? (
-        <InnerWrapper>
-          <AddWidgetButton
-            onAddWidget={onAddWidget}
-            aria-label={t('Add Widget')}
-            data-test-id="widget-add"
-          />
-        </InnerWrapper>
-      ) : (
-        <InnerWrapper onClick={() => onAddWidget(DataSet.EVENTS)}>
-          <AddButton
-            data-test-id="widget-add"
-            icon={<IconAdd size="lg" isCircled color="inactive" />}
-            aria-label={t('Add widget')}
-          />
-        </InnerWrapper>
-      )}
-    </WidgetWrapper>
+    <Feature features={'dashboards-edit'}>
path: static/app/views/dashboards/addWidget.tsx
text: @user1:
```suggestion
    <Feature features="dashboards-edit">
```