@@ -19,9 +19,10 @@ import NoProjectMessage from 'sentry/components/noProjectMessage';
19
19
import { PageHeadingQuestionTooltip } from 'sentry/components/pageHeadingQuestionTooltip' ;
20
20
import Pagination from 'sentry/components/pagination' ;
21
21
import SearchBar from 'sentry/components/searchBar' ;
22
+ import { SegmentedControl } from 'sentry/components/segmentedControl' ;
22
23
import SentryDocumentTitle from 'sentry/components/sentryDocumentTitle' ;
23
24
import Switch from 'sentry/components/switchButton' ;
24
- import { IconAdd } from 'sentry/icons' ;
25
+ import { IconAdd , IconDashboard , IconList } from 'sentry/icons' ;
25
26
import { t } from 'sentry/locale' ;
26
27
import { space } from 'sentry/styles/space' ;
27
28
import type { SelectValue } from 'sentry/types/core' ;
@@ -64,12 +65,23 @@ const SORT_OPTIONS: SelectValue<string>[] = [
64
65
] ;
65
66
66
67
const 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' ;
67
74
68
75
function shouldShowTemplates ( ) : boolean {
69
76
const shouldShow = localStorage . getItem ( SHOW_TEMPLATES_KEY ) ;
70
77
return shouldShow === 'true' || shouldShow === null ;
71
78
}
72
79
80
+ function getDashboardsOverviewLayout ( ) : DashboardsLayout {
81
+ const dashboardsLayout = localStorage . getItem ( LAYOUT_KEY ) ;
82
+ return dashboardsLayout === GRID || dashboardsLayout === LIST ? dashboardsLayout : GRID ;
83
+ }
84
+
73
85
function ManageDashboards ( ) {
74
86
const organization = useOrganization ( ) ;
75
87
const navigate = useNavigate ( ) ;
@@ -81,6 +93,10 @@ function ManageDashboards() {
81
93
SHOW_TEMPLATES_KEY ,
82
94
shouldShowTemplates ( )
83
95
) ;
96
+ const [ dashboardsLayout , setDashboardsLayout ] = useLocalStorageState (
97
+ LAYOUT_KEY ,
98
+ getDashboardsOverviewLayout ( )
99
+ ) ;
84
100
const [ { rowCount, columnCount} , setGridSize ] = useState ( {
85
101
rowCount : DASHBOARD_GRID_DEFAULT_NUM_ROWS ,
86
102
columnCount : DASHBOARD_GRID_DEFAULT_NUM_COLUMNS ,
@@ -230,13 +246,37 @@ function ManageDashboards() {
230
246
function renderActions ( ) {
231
247
const activeSort = getActiveSort ( ) ;
232
248
return (
233
- < StyledActions >
249
+ < StyledActions listView = { organization . features . includes ( 'dashboards-table-view' ) } >
234
250
< SearchBar
235
251
defaultQuery = ""
236
252
query = { getQuery ( ) }
237
253
placeholder = { t ( 'Search Dashboards' ) }
238
254
onSearch = { query => handleSearch ( query ) }
239
255
/>
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 >
240
280
< CompactSelect
241
281
triggerProps = { { prefix : t ( 'Sort By' ) } }
242
282
value = { activeSort . value }
@@ -444,9 +484,10 @@ function ManageDashboards() {
444
484
) ;
445
485
}
446
486
447
- const StyledActions = styled ( 'div' ) `
487
+ const StyledActions = styled ( 'div' ) < { listView : boolean } > `
448
488
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' } ;
450
491
gap: ${ space ( 2 ) } ;
451
492
margin-bottom: ${ space ( 2 ) } ;
452
493
0 commit comments