1
1
import { cx } from '@emotion/css' ;
2
2
import { Portal } from '@mui/material' ;
3
- import React , { PureComponent } from 'react' ;
3
+ import { PureComponent } from 'react' ;
4
4
import { connect , ConnectedProps , MapDispatchToProps , MapStateToProps } from 'react-redux' ;
5
5
6
6
import { NavModel , NavModelItem , TimeRange , PageLayoutType , locationUtil } from '@grafana/data' ;
7
7
import { selectors } from '@grafana/e2e-selectors' ;
8
8
import { config , locationService } from '@grafana/runtime' ;
9
- import { Themeable2 , withTheme2 , ToolbarButtonRow } from '@grafana/ui' ;
9
+ import { Themeable2 , withTheme2 , ToolbarButtonRow , ToolbarButton , ModalsController } from '@grafana/ui' ;
10
10
import { notifyApp } from 'app/core/actions' ;
11
+ import { ScrollRefElement } from 'app/core/components/NativeScrollbar' ;
11
12
import { Page } from 'app/core/components/Page/Page' ;
12
13
import { EntityNotFound } from 'app/core/components/PageNotFound/EntityNotFound' ;
13
14
import { GrafanaContext , GrafanaContextType } from 'app/core/context/GrafanaContext' ;
14
15
import { createErrorNotification } from 'app/core/copy/appNotification' ;
16
+ import { t } from 'app/core/internationalization' ;
15
17
import { getKioskMode } from 'app/core/navigation/kiosk' ;
16
18
import { GrafanaRouteComponentProps } from 'app/core/navigation/types' ;
17
19
import { FnGlobalState } from 'app/core/reducers/fn-slice' ;
18
20
import { getNavModel } from 'app/core/selectors/navModel' ;
19
21
import { PanelModel } from 'app/features/dashboard/state' ;
22
+ import { DashboardInteractions } from 'app/features/dashboard-scene/utils/interactions' ;
20
23
import { dashboardWatcher } from 'app/features/live/dashboard/dashboardWatcher' ;
21
24
import { updateTimeZoneForSession } from 'app/features/profile/state/reducers' ;
22
25
import { getPageNavFromSlug , getRootContentNavModel } from 'app/features/storage/StorageFolderPage' ;
@@ -26,6 +29,7 @@ import { PanelEditEnteredEvent, PanelEditExitedEvent } from 'app/types/events';
26
29
27
30
import { cancelVariables , templateVarsChangedInUrl } from '../../variables/state/actions' ;
28
31
import { findTemplateVarChanges } from '../../variables/utils' ;
32
+ import AddPanelButton from '../components/AddPanelButton/AddPanelButton' ;
29
33
import { AddWidgetModal } from '../components/AddWidgetModal/AddWidgetModal' ;
30
34
import { DashNav } from '../components/DashNav' ;
31
35
import { DashNavTimeControls } from '../components/DashNav/DashNavTimeControls' ;
@@ -36,6 +40,7 @@ import { DashboardPrompt } from '../components/DashboardPrompt/DashboardPrompt';
36
40
import { DashboardSettings } from '../components/DashboardSettings' ;
37
41
import { PanelInspector } from '../components/Inspector/PanelInspector' ;
38
42
import { PanelEditor } from '../components/PanelEditor/PanelEditor' ;
43
+ import { SaveDashboardDrawer } from '../components/SaveDashboard/SaveDashboardDrawer' ;
39
44
import { SubMenu } from '../components/SubMenu/SubMenu' ;
40
45
import { DashboardGrid } from '../dashgrid/DashboardGrid' ;
41
46
import { liveTimer } from '../dashgrid/liveTimer' ;
@@ -72,7 +77,7 @@ export type MapStateToDashboardPageProps = MapStateToProps<
72
77
Pick < DashboardState , 'initPhase' | 'initError' > & {
73
78
dashboard : ReturnType < DashboardState [ 'getModel' ] > ;
74
79
navIndex : StoreState [ 'navIndex' ] ;
75
- } & Pick < FnGlobalState , 'FNDashboard' | 'controlsContainer' > ,
80
+ } & Pick < FnGlobalState , 'FNDashboard' | 'controlsContainer' | 'isCustomDashboard' > ,
76
81
OwnProps ,
77
82
StoreState
78
83
> ;
@@ -93,6 +98,7 @@ export const mapStateToProps: MapStateToDashboardPageProps = (state) => ({
93
98
dashboard : state . dashboard . getModel ( ) ,
94
99
navIndex : state . navIndex ,
95
100
FNDashboard : state . fnGlobalState . FNDashboard ,
101
+ isCustomDashboard : state . fnGlobalState . isCustomDashboard ,
96
102
controlsContainer : state . fnGlobalState . controlsContainer ,
97
103
} ) ;
98
104
@@ -128,7 +134,7 @@ export interface State {
128
134
showLoadingState : boolean ;
129
135
panelNotFound : boolean ;
130
136
editPanelAccessDenied : boolean ;
131
- scrollElement ?: HTMLDivElement ;
137
+ scrollElement ?: ScrollRefElement ;
132
138
pageNav ?: NavModelItem ;
133
139
sectionNav ?: NavModel ;
134
140
}
@@ -152,9 +158,9 @@ export class UnthemedDashboardPage extends PureComponent<Props, State> {
152
158
153
159
componentDidMount ( ) {
154
160
this . initDashboard ( ) ;
155
- const { FNDashboard } = this . props ;
161
+ const { FNDashboard, isCustomDashboard } = this . props ;
156
162
157
- if ( ! FNDashboard ) {
163
+ if ( ! FNDashboard || isCustomDashboard ) {
158
164
this . forceRouteReloadCounter = ( this . props . history . location ?. state as any ) ?. routeReloadCounter || 0 ;
159
165
}
160
166
}
@@ -192,13 +198,13 @@ export class UnthemedDashboardPage extends PureComponent<Props, State> {
192
198
}
193
199
194
200
componentDidUpdate ( prevProps : Props , prevState : State ) {
195
- const { dashboard, match, templateVarsChangedInUrl, FNDashboard } = this . props ;
201
+ const { dashboard, match, templateVarsChangedInUrl, FNDashboard, isCustomDashboard } = this . props ;
196
202
197
203
if ( ! dashboard ) {
198
204
return ;
199
205
}
200
206
201
- if ( ! FNDashboard ) {
207
+ if ( ! FNDashboard || isCustomDashboard ) {
202
208
const routeReloadCounter = ( this . props . history . location ?. state as any ) ?. routeReloadCounter ;
203
209
204
210
if (
@@ -354,7 +360,7 @@ export class UnthemedDashboardPage extends PureComponent<Props, State> {
354
360
this . setState ( { updateScrollTop : 0 } ) ;
355
361
} ;
356
362
357
- setScrollRef = ( scrollElement : HTMLDivElement ) : void => {
363
+ setScrollRef = ( scrollElement : ScrollRefElement ) : void => {
358
364
this . setState ( { scrollElement } ) ;
359
365
} ;
360
366
@@ -378,7 +384,7 @@ export class UnthemedDashboardPage extends PureComponent<Props, State> {
378
384
}
379
385
380
386
render ( ) {
381
- const { dashboard, initError, queryParams, FNDashboard, controlsContainer } = this . props ;
387
+ const { dashboard, initError, queryParams, FNDashboard, controlsContainer, isCustomDashboard } = this . props ;
382
388
const { editPanel, viewPanel, pageNav, sectionNav } = this . state ;
383
389
const kioskMode = getKioskMode ( this . props . queryParams ) ;
384
390
@@ -391,12 +397,22 @@ export class UnthemedDashboardPage extends PureComponent<Props, State> {
391
397
392
398
const showToolbar = FNDashboard || ( kioskMode !== KioskMode . Full && ! queryParams . editview ) ;
393
399
400
+ const isFNDashboardEditable = ( isCustomDashboard && FNDashboard ) || ! FNDashboard ;
401
+
402
+ console . log ( 'Edit Panel: ' , { editPanel, sectionNav, pageNav, isFNDashboardEditable } ) ;
403
+ console . log ( 'Dashboard settings: ' , { editView : queryParams . editview , pageNav, sectionNav, isFNDashboardEditable } ) ;
404
+ console . log ( 'Add Widget: ' , {
405
+ isFNDashboardEditable,
406
+ addWidget : queryParams . addWidget ,
407
+ configToggle : config . featureToggles . vizAndWidgetSplit ,
408
+ } ) ;
409
+
394
410
const pageClassName = cx ( {
395
411
'panel-in-fullscreen' : Boolean ( viewPanel ) ,
396
412
'page-hidden' : Boolean ( queryParams . editview || editPanel ) ,
397
413
} ) ;
398
414
399
- if ( dashboard . meta . dashboardNotFound ) {
415
+ if ( dashboard . meta . dashboardNotFound && ! FNDashboard ) {
400
416
return (
401
417
< Page navId = "dashboards/browse" layout = { PageLayoutType . Canvas } pageNav = { { text : 'Not found' } } >
402
418
< EntityNotFound entity = "Dashboard" />
@@ -417,27 +433,56 @@ export class UnthemedDashboardPage extends PureComponent<Props, State> {
417
433
) ;
418
434
419
435
return (
420
- < React . Fragment >
436
+ < >
421
437
< Page
422
438
navModel = { sectionNav }
423
439
pageNav = { pageNav }
424
440
layout = { PageLayoutType . Canvas }
425
441
className = { pageClassName }
426
- // scrollRef={this.setScrollRef}
427
- // scrollTop={updateScrollTop}
428
- style = { { minHeight : '550px' } }
442
+ onSetScrollRef = { this . setScrollRef }
429
443
>
430
444
{ showToolbar && (
431
445
< header data-testid = { selectors . pages . Dashboard . DashNav . navV2 } >
432
446
{ FNDashboard ? (
433
- FNTimeRange
447
+ < div
448
+ style = { {
449
+ display : 'flex' ,
450
+ justifyContent : 'flex-end' ,
451
+ gap : 4 ,
452
+ } }
453
+ >
454
+ { isCustomDashboard && (
455
+ < >
456
+ < ModalsController key = "button-save" >
457
+ { ( { showModal, hideModal } ) => (
458
+ < ToolbarButton
459
+ tooltip = { t ( 'dashboard.toolbar.save' , 'Save dashboard' ) }
460
+ icon = "save"
461
+ onClick = { ( ) => {
462
+ showModal ( SaveDashboardDrawer , {
463
+ dashboard,
464
+ onDismiss : hideModal ,
465
+ } ) ;
466
+ } }
467
+ />
468
+ ) }
469
+ </ ModalsController >
470
+ < AddPanelButton
471
+ onToolbarAddMenuOpen = { DashboardInteractions . toolbarAddClick }
472
+ dashboard = { dashboard }
473
+ key = "panel-add-dropdown"
474
+ isFNDashboard
475
+ />
476
+ </ >
477
+ ) }
478
+ { FNTimeRange }
479
+ </ div >
434
480
) : (
435
481
< DashNav
436
482
dashboard = { dashboard }
437
483
title = { dashboard . title }
438
484
folderTitle = { dashboard . meta . folderTitle }
439
485
isFullscreen = { ! ! viewPanel }
440
- // onAddPanel={this.onAddPanel}
441
486
kioskMode = { kioskMode }
442
487
hideTimePicker = { dashboard . timepicker . hidden }
443
488
/>
@@ -453,14 +498,14 @@ export class UnthemedDashboardPage extends PureComponent<Props, State> {
453
498
) }
454
499
< DashboardGrid
455
500
dashboard = { dashboard }
456
- isEditable = { ! ! dashboard . meta . canEdit && ! FNDashboard }
501
+ isEditable = { isFNDashboardEditable && ! ! dashboard . meta . canEdit }
457
502
viewPanel = { viewPanel }
458
503
editPanel = { editPanel }
459
504
/>
460
505
461
506
{ inspectPanel && ! FNDashboard && < PanelInspector dashboard = { dashboard } panel = { inspectPanel } /> }
462
507
</ Page >
463
- { editPanel && ! FNDashboard && sectionNav && pageNav && (
508
+ { editPanel && sectionNav && pageNav && isFNDashboardEditable && (
464
509
< PanelEditor
465
510
dashboard = { dashboard }
466
511
sourcePanel = { editPanel }
@@ -469,24 +514,26 @@ export class UnthemedDashboardPage extends PureComponent<Props, State> {
469
514
pageNav = { pageNav }
470
515
/>
471
516
) }
472
- { queryParams . editview && ! FNDashboard && pageNav && sectionNav && (
517
+ { queryParams . editview && pageNav && sectionNav && isFNDashboardEditable && (
473
518
< DashboardSettings
474
519
dashboard = { dashboard }
475
520
editview = { queryParams . editview }
476
521
pageNav = { pageNav }
477
522
sectionNav = { sectionNav }
478
523
/>
479
524
) }
480
- { ! FNDashboard && queryParams . addWidget && config . featureToggles . vizAndWidgetSplit && < AddWidgetModal /> }
481
- </ React . Fragment >
525
+ { isFNDashboardEditable && queryParams . addWidget && config . featureToggles . vizAndWidgetSplit && (
526
+ < AddWidgetModal />
527
+ ) }
528
+ </ >
482
529
) ;
483
530
}
484
531
}
485
532
486
533
function updateStatePageNavFromProps ( props : Props , state : State ) : State {
487
- const { dashboard, FNDashboard } = props ;
534
+ const { dashboard, FNDashboard, isCustomDashboard } = props ;
488
535
489
- if ( ! dashboard || FNDashboard ) {
536
+ if ( ! dashboard || ( FNDashboard && ! isCustomDashboard ) ) {
490
537
return state ;
491
538
}
492
539
0 commit comments