Browse Source

feat(ddm): scratchpad save on enter (#57568)

Ogi 1 year ago
parent
commit
2ca6f0d081
2 changed files with 43 additions and 15 deletions
  1. 29 10
      static/app/views/ddm/metricScratchpad.tsx
  2. 14 5
      static/app/views/ddm/metricWidget.tsx

+ 29 - 10
static/app/views/ddm/metricScratchpad.tsx

@@ -14,6 +14,7 @@ import {IconBookmark, IconDelete, IconStar} from 'sentry/icons';
 import {t} from 'sentry/locale';
 import {space} from 'sentry/styles/space';
 import {clearQuery, updateQuery} from 'sentry/utils/metrics';
+import useKeyPress from 'sentry/utils/useKeyPress';
 import {useLocalStorageState} from 'sentry/utils/useLocalStorageState';
 import useOverlay from 'sentry/utils/useOverlay';
 import useRouter from 'sentry/utils/useRouter';
@@ -117,7 +118,7 @@ export function useScratchpads() {
     add,
     update,
     remove,
-    toggleSelect: toggleSelected,
+    toggleSelected,
     setDefault,
   };
 }
@@ -154,7 +155,6 @@ export function ScratchpadSelector() {
   return (
     <ScratchpadGroup>
       <Button
-        size="sm"
         disabled={!scratchpads.selected}
         onClick={() => {
           if (isDefaultSelected) {
@@ -175,12 +175,12 @@ export function ScratchpadSelector() {
       />
       <CompactSelect
         options={scratchpadOptions}
-        value={scratchpads.selected ?? ''}
+        value={scratchpads.selected ?? `None`}
         closeOnSelect={false}
         onChange={option => {
-          scratchpads.toggleSelect(option.value);
+          scratchpads.toggleSelected(option.value);
         }}
-        triggerProps={{prefix: t('Scratchpad'), size: 'sm'}}
+        triggerProps={{prefix: t('Scratchpad')}}
         emptyMessage="No scratchpads yet."
         disabled={false}
       />
@@ -195,13 +195,33 @@ function SaveAsDropdown({
   mode: 'save' | 'fork';
   onSave: (name: string) => void;
 }) {
-  const {isOpen, triggerProps, overlayProps, arrowProps} = useOverlay({});
+  const {
+    isOpen,
+    triggerProps,
+    overlayProps,
+    arrowProps,
+    state: {setOpen},
+  } = useOverlay({});
   const theme = useTheme();
   const [name, setName] = useState('');
 
+  const save = useCallback(() => {
+    onSave(name);
+    setOpen(false);
+    setName('');
+  }, [name, onSave, setOpen]);
+
+  const enterKeyPressed = useKeyPress('Enter', undefined, true);
+
+  useEffect(() => {
+    if (isOpen && enterKeyPressed && name) {
+      save();
+    }
+  }, [enterKeyPressed, isOpen, name, save]);
+
   return (
     <div>
-      <Button size="sm" icon={<IconStar />} {...triggerProps}>
+      <Button icon={<IconStar />} {...triggerProps}>
         {mode === 'fork' ? t('Fork as ...') : t('Save as ...')}
       </Button>
       <AnimatePresence>
@@ -218,12 +238,11 @@ function SaveAsDropdown({
                   onChange={({target}) => setName(target.value)}
                 />
                 <SaveAsButton
+                  priority="primary"
                   disabled={!name}
                   onClick={() => {
-                    onSave(name);
+                    save();
                   }}
-                  size="sm"
-                  priority="primary"
                 >
                   {mode === 'fork' ? t('Fork') : t('Save')}
                 </SaveAsButton>

+ 14 - 5
static/app/views/ddm/metricWidget.tsx

@@ -15,6 +15,7 @@ import Legend from 'sentry/components/charts/components/legend';
 import {LineChart} from 'sentry/components/charts/lineChart';
 import ReleaseSeries from 'sentry/components/charts/releaseSeries';
 import TransparentLoadingMask from 'sentry/components/charts/transparentLoadingMask';
+import {RELEASE_LINES_THRESHOLD} from 'sentry/components/charts/utils';
 import EmptyMessage from 'sentry/components/emptyMessage';
 import LoadingIndicator from 'sentry/components/loadingIndicator';
 import {normalizeDateTimeParams} from 'sentry/components/organizations/pageFilters/parse';
@@ -473,17 +474,25 @@ function MetricChart({
             preserveQueryParams
           >
             {({releaseSeries}) => {
-              const legend = releaseSeries[0]?.markLine?.data?.length
+              const releaseSeriesData = releaseSeries?.[0]?.markLine?.data ?? [];
+
+              const selected =
+                releaseSeriesData?.length >= RELEASE_LINES_THRESHOLD
+                  ? {[t('Releases')]: false}
+                  : {};
+
+              const legend = releaseSeriesData?.length
                 ? Legend({
                     itemGap: 20,
                     top: 0,
                     right: 20,
                     data: releaseSeries.map(s => s.seriesName),
                     theme: theme as Theme,
+                    selected,
                   })
                 : undefined;
 
-              const props = {
+              const allProps = {
                 series: [...seriesToShow, ...releaseSeries],
                 legend,
                 ...chartProps,
@@ -491,11 +500,11 @@ function MetricChart({
               };
 
               return displayType === MetricDisplayType.LINE ? (
-                <LineChart {...props} />
+                <LineChart {...allProps} />
               ) : displayType === MetricDisplayType.AREA ? (
-                <AreaChart {...props} />
+                <AreaChart {...allProps} />
               ) : (
-                <BarChart stacked {...props} />
+                <BarChart stacked {...allProps} />
               );
             }}
           </ReleaseSeries>