Browse Source

feat(crons): Add sort selector (#64805)

Add sort selector component to be used on listing page, will follow up
with bulk edit modal sort

<img width="1268" alt="image"
src="https://github.com/getsentry/sentry/assets/9372512/1fe73370-e3a0-4eaa-ba49-c3817d359c92">
David Wang 1 year ago
parent
commit
3e4bf991a2

+ 7 - 3
static/app/views/monitors/components/overviewTimeline/index.tsx

@@ -18,6 +18,7 @@ import {
   GridLineOverlay,
   GridLineTimeLabels,
 } from 'sentry/views/monitors/components/overviewTimeline/gridLines';
+import {SortSelector} from 'sentry/views/monitors/components/overviewTimeline/sortSelector';
 import {makeMonitorListQueryKey} from 'sentry/views/monitors/utils';
 
 import type {Monitor} from '../../types';
@@ -145,9 +146,10 @@ export function OverviewTimeline({monitorList}: Props) {
   return (
     <MonitorListPanel>
       <TimelineWidthTracker ref={elementRef} />
-      <StickyResolutionSelector>
+      <HeaderControls>
         <ResolutionSelector />
-      </StickyResolutionSelector>
+        <SortSelector />
+      </HeaderControls>
       <StickyGridLineTimeLabels>
         <BorderlessGridLineTimeLabels
           timeWindowConfig={timeWindowConfig}
@@ -190,7 +192,9 @@ const MonitorListPanel = styled(Panel)`
   grid-template-columns: 350px 135px 1fr;
 `;
 
-const StickyResolutionSelector = styled(Sticky)`
+const HeaderControls = styled(Sticky)`
+  display: flex;
+  gap: ${space(0.5)};
   z-index: 1;
   padding: ${space(1.5)} ${space(2)};
   grid-column: 1/3;

+ 78 - 0
static/app/views/monitors/components/overviewTimeline/sortSelector.tsx

@@ -0,0 +1,78 @@
+import {Button} from 'sentry/components/button';
+import {CompositeSelect} from 'sentry/components/compactSelect/composite';
+import type {SelectOption} from 'sentry/components/compactSelect/types';
+import {IconSort} from 'sentry/icons';
+import {t} from 'sentry/locale';
+import useRouter from 'sentry/utils/useRouter';
+
+export enum MonitorSortOrder {
+  ASCENDING = '1',
+  DESCENDING = '0',
+}
+
+export enum MonitorSortOption {
+  STATUS = 'status',
+  NAME = 'name',
+  MUTED = 'muted',
+}
+
+const ORDER_OPTIONS = [
+  {label: t('Ascending'), value: MonitorSortOrder.ASCENDING},
+  {label: t('Descending'), value: MonitorSortOrder.DESCENDING},
+];
+
+const SORT_OPTIONS = [
+  {label: t('Status'), value: MonitorSortOption.STATUS},
+  {label: t('Name'), value: MonitorSortOption.NAME},
+  {label: t('Muted'), value: MonitorSortOption.MUTED},
+];
+
+interface Props {
+  onChangeOrder?: (order: SelectOption<MonitorSortOrder>) => void;
+  onChangeSort?: (sort: SelectOption<MonitorSortOption>) => void;
+  order?: MonitorSortOrder;
+  sort?: MonitorSortOption;
+}
+
+export function SortSelector({onChangeOrder, onChangeSort, order, sort}: Props) {
+  const {replace, location} = useRouter();
+
+  const selectedSort = sort ?? location.query?.sort ?? MonitorSortOption.STATUS;
+  const selectedOrder = order ?? location.query?.asc ?? MonitorSortOrder.DESCENDING;
+
+  const defaultOnChange = (newSort: MonitorSortOption, newOrder: MonitorSortOrder) => {
+    replace({...location, query: {...location.query, asc: newOrder, sort: newSort}});
+  };
+  const handleChangeSort =
+    onChangeSort ?? (newSort => defaultOnChange(newSort.value, selectedOrder));
+  const handleChangeOrder =
+    onChangeOrder ?? (newOrder => defaultOnChange(selectedSort, newOrder.value));
+
+  return (
+    <CompositeSelect
+      trigger={triggerProps => (
+        <Button
+          {...triggerProps}
+          size="xs"
+          aria-label={t('Sort Cron Monitors')}
+          icon={<IconSort size="sm" />}
+        >
+          {SORT_OPTIONS.find(({value}) => value === selectedSort)?.label ?? ''}
+        </Button>
+      )}
+    >
+      <CompositeSelect.Region
+        aria-label={t('Sort Options')}
+        value={selectedSort}
+        onChange={handleChangeSort}
+        options={SORT_OPTIONS}
+      />
+      <CompositeSelect.Region
+        aria-label={t('Sort Order Options')}
+        value={selectedOrder}
+        onChange={handleChangeOrder}
+        options={ORDER_OPTIONS}
+      />
+    </CompositeSelect>
+  );
+}

+ 13 - 2
static/app/views/monitors/utils.tsx

@@ -11,11 +11,22 @@ export function makeMonitorListQueryKey(
   organization: Organization,
   params: Record<string, any>
 ) {
-  const {query, project, environment, cursor} = params;
+  const {query, project, environment, cursor, sort, asc} = params;
 
   return [
     `/organizations/${organization.slug}/monitors/`,
-    {query: {cursor, query, project, environment, includeNew: true, per_page: 20}},
+    {
+      query: {
+        cursor,
+        query,
+        project,
+        environment,
+        includeNew: true,
+        per_page: 20,
+        sort,
+        asc,
+      },
+    },
   ] as const;
 }