@@ -19,9 +19,10 @@ import NoProjectMessage from 'sentry/components/noProjectMessage';
1919import { PageHeadingQuestionTooltip } from 'sentry/components/pageHeadingQuestionTooltip' ;
2020import Pagination from 'sentry/components/pagination' ;
2121import SearchBar from 'sentry/components/searchBar' ;
22+ import { SegmentedControl } from 'sentry/components/segmentedControl' ;
2223import SentryDocumentTitle from 'sentry/components/sentryDocumentTitle' ;
2324import Switch from 'sentry/components/switchButton' ;
24- import { IconAdd } from 'sentry/icons' ;
25+ import { IconAdd , IconDashboard , IconList } from 'sentry/icons' ;
2526import { t } from 'sentry/locale' ;
2627import { space } from 'sentry/styles/space' ;
2728import type { SelectValue } from 'sentry/types/core' ;
@@ -64,12 +65,23 @@ const SORT_OPTIONS: SelectValue<string>[] = [
6465] ;
6566
6667const SHOW_TEMPLATES_KEY = 'dashboards-show-templates' ;
68+ export const LAYOUT_KEY = 'dashboards-overview-layout' ;
69+
70+ const GRID = 'grid' ;
71+ const LIST = 'list' ;
72+
73+ type DashboardsLayout = 'grid' | 'list' ;
6774
6875function shouldShowTemplates ( ) : boolean {
6976 const shouldShow = localStorage . getItem ( SHOW_TEMPLATES_KEY ) ;
7077 return shouldShow === 'true' || shouldShow === null ;
7178}
7279
80+ function getDashboardsOverviewLayout ( ) : DashboardsLayout {
81+ const dashboardsLayout = localStorage . getItem ( LAYOUT_KEY ) ;
82+ return dashboardsLayout === GRID || dashboardsLayout === LIST ? dashboardsLayout : GRID ;
83+ }
84+
7385function ManageDashboards ( ) {
7486 const organization = useOrganization ( ) ;
7587 const navigate = useNavigate ( ) ;
@@ -81,6 +93,10 @@ function ManageDashboards() {
8193 SHOW_TEMPLATES_KEY ,
8294 shouldShowTemplates ( )
8395 ) ;
96+ const [ dashboardsLayout , setDashboardsLayout ] = useLocalStorageState (
97+ LAYOUT_KEY ,
98+ getDashboardsOverviewLayout ( )
99+ ) ;
84100 const [ { rowCount, columnCount} , setGridSize ] = useState ( {
85101 rowCount : DASHBOARD_GRID_DEFAULT_NUM_ROWS ,
86102 columnCount : DASHBOARD_GRID_DEFAULT_NUM_COLUMNS ,
@@ -230,13 +246,37 @@ function ManageDashboards() {
230246 function renderActions ( ) {
231247 const activeSort = getActiveSort ( ) ;
232248 return (
233- < StyledActions >
249+ < StyledActions listView = { organization . features . includes ( 'dashboards-table-view' ) } >
234250 < SearchBar
235251 defaultQuery = ""
236252 query = { getQuery ( ) }
237253 placeholder = { t ( 'Search Dashboards' ) }
238254 onSearch = { query => handleSearch ( query ) }
239255 />
256+ < Feature features = { 'organizations:dashboards-table-view' } >
257+ < SegmentedControl < DashboardsLayout >
258+ onChange = { setDashboardsLayout }
259+ size = "md"
260+ value = { dashboardsLayout }
261+ aria-label = { t ( 'Layout Control' ) }
262+ >
263+ < SegmentedControl . Item
264+ key = "grid"
265+ textValue = "grid"
266+ aria-label = { t ( 'Grid View' ) }
267+ >
268+ { /* TODO (nikkikapadia): replace this icon with correct one once made */ }
269+ < IconDashboard />
270+ </ SegmentedControl . Item >
271+ < SegmentedControl . Item
272+ key = "list"
273+ textValue = "list"
274+ aria-label = { t ( 'List View' ) }
275+ >
276+ < IconList />
277+ </ SegmentedControl . Item >
278+ </ SegmentedControl >
279+ </ Feature >
240280 < CompactSelect
241281 triggerProps = { { prefix : t ( 'Sort By' ) } }
242282 value = { activeSort . value }
@@ -444,9 +484,10 @@ function ManageDashboards() {
444484 ) ;
445485}
446486
447- const StyledActions = styled ( 'div' ) `
487+ const StyledActions = styled ( 'div' ) < { listView : boolean } > `
448488 display: grid;
449- grid-template-columns: auto max-content;
489+ grid-template-columns: ${ p =>
490+ p . listView ? 'auto max-content max-content' : 'auto max-content' } ;
450491 gap: ${ space ( 2 ) } ;
451492 margin-bottom: ${ space ( 2 ) } ;
452493
0 commit comments