@@ -16,7 +16,6 @@ import {
1616 EuiTitle ,
1717} from '@elastic/eui' ;
1818import React , { useCallback , useEffect , useState } from 'react' ;
19- import useMount from 'react-use/lib/useMount' ;
2019import { DashboardSavedObject } from '../..' ;
2120import {
2221 createConfirmStrings ,
@@ -29,15 +28,16 @@ import { DashboardAppServices, DashboardRedirect } from '../types';
2928import { confirmDiscardUnsavedChanges } from './confirm_overlays' ;
3029
3130const DashboardUnsavedItem = ( {
32- dashboard,
31+ id,
32+ title,
3333 onOpenClick,
3434 onDiscardClick,
3535} : {
36- dashboard ?: DashboardSavedObject ;
36+ id : string ;
37+ title ?: string ;
3738 onOpenClick : ( ) => void ;
3839 onDiscardClick : ( ) => void ;
3940} ) => {
40- const title = dashboard ?. title ?? getNewDashboardTitle ( ) ;
4141 return (
4242 < div className = "dshUnsavedListingItem" >
4343 < EuiFlexGroup
@@ -47,12 +47,20 @@ const DashboardUnsavedItem = ({
4747 responsive = { false }
4848 >
4949 < EuiFlexItem grow = { false } >
50- < EuiIcon color = "text" className = "dshUnsavedListingItem__icon" type = "dashboardApp" />
50+ < EuiIcon
51+ color = "text"
52+ className = "dshUnsavedListingItem__icon"
53+ type = { title ? 'dashboardApp' : 'clock' }
54+ />
5155 </ EuiFlexItem >
5256 < EuiFlexItem grow = { false } >
5357 < EuiTitle size = "xxs" >
54- < h4 className = "dshUnsavedListingItem__title" >
55- { dashboard ?. title ?? getNewDashboardTitle ( ) }
58+ < h4
59+ className = { `dshUnsavedListingItem__title ${
60+ title ? '' : 'dshUnsavedListingItem__loading'
61+ } `}
62+ >
63+ { title || dashboardUnsavedListingStrings . getLoadingTitle ( ) }
5664 </ h4 >
5765 </ EuiTitle >
5866 </ EuiFlexItem >
@@ -68,9 +76,10 @@ const DashboardUnsavedItem = ({
6876 flush = "left"
6977 size = "s"
7078 color = "primary"
79+ disabled = { ! title }
7180 onClick = { onOpenClick }
72- data-test-subj = { `edit-unsaved-${ title . split ( ' ' ) . join ( '-' ) } ` }
73- aria-label = { dashboardUnsavedListingStrings . getEditAriaLabel ( title ) }
81+ data-test-subj = { title ? `edit-unsaved-${ title . split ( ' ' ) . join ( '-' ) } ` : undefined }
82+ aria-label = { dashboardUnsavedListingStrings . getEditAriaLabel ( title ?? id ) }
7483 >
7584 { dashboardUnsavedListingStrings . getEditTitle ( ) }
7685 </ EuiButtonEmpty >
@@ -80,9 +89,10 @@ const DashboardUnsavedItem = ({
8089 flush = "left"
8190 size = "s"
8291 color = "danger"
92+ disabled = { ! title }
8393 onClick = { onDiscardClick }
84- data-test-subj = { `discard-unsaved-${ title . split ( ' ' ) . join ( '-' ) } ` }
85- aria-label = { dashboardUnsavedListingStrings . getDiscardAriaLabel ( title ) }
94+ data-test-subj = { title ? `discard-unsaved-${ title . split ( ' ' ) . join ( '-' ) } ` : undefined }
95+ aria-label = { dashboardUnsavedListingStrings . getDiscardAriaLabel ( title ?? id ) }
8696 >
8797 { dashboardUnsavedListingStrings . getDiscardTitle ( ) }
8898 </ EuiButtonEmpty >
@@ -92,6 +102,10 @@ const DashboardUnsavedItem = ({
92102 ) ;
93103} ;
94104
105+ interface UnsavedItemMap {
106+ [ key : string ] : DashboardSavedObject ;
107+ }
108+
95109export const DashboardUnsavedListing = ( { redirectTo } : { redirectTo : DashboardRedirect } ) => {
96110 const {
97111 services : {
@@ -101,8 +115,11 @@ export const DashboardUnsavedListing = ({ redirectTo }: { redirectTo: DashboardR
101115 } ,
102116 } = useKibana < DashboardAppServices > ( ) ;
103117
104- const [ items , setItems ] = useState < JSX . Element [ ] > ( [ ] ) ;
105- const [ dashboardIds , setDashboardIds ] = useState < string [ ] > ( [ ] ) ;
118+ const [ items , setItems ] = useState < UnsavedItemMap > ( { } ) ;
119+ const [ mounted , setMounted ] = useState ( true ) ;
120+ const [ dashboardIds , setDashboardIds ] = useState < string [ ] > (
121+ dashboardPanelStorage . getDashboardIdsWithUnsavedChanges ( )
122+ ) ;
106123
107124 const onOpen = useCallback (
108125 ( id ?: string ) => {
@@ -125,50 +142,52 @@ export const DashboardUnsavedListing = ({ redirectTo }: { redirectTo: DashboardR
125142 [ overlays , dashboardPanelStorage ]
126143 ) ;
127144
128- useMount ( ( ) => {
129- setDashboardIds ( dashboardPanelStorage . getDashboardIdsWithUnsavedChanges ( ) ) ;
145+ useEffect ( ( ) => {
146+ return ( ) => setMounted ( false ) ;
130147 } ) ;
131148
132149 useEffect ( ( ) => {
133- let hasNewDashboard = false ;
134150 const dashPromises = dashboardIds
135- . filter ( ( id ) => {
136- if ( id !== DASHBOARD_PANELS_UNSAVED_ID ) {
137- return true ;
138- }
139- hasNewDashboard = true ;
140- return false ;
141- } )
151+ . filter ( ( id ) => id !== DASHBOARD_PANELS_UNSAVED_ID )
142152 . map ( ( dashboardId ) => savedDashboards . get ( dashboardId ) ) ;
143153 Promise . all ( dashPromises ) . then ( ( dashboards : DashboardSavedObject [ ] ) => {
144- const newItems = dashboards . map ( ( dashboard ) => (
145- < DashboardUnsavedItem
146- key = { dashboard . id }
147- dashboard = { dashboard }
148- onOpenClick = { ( ) => onOpen ( dashboard . id ) }
149- onDiscardClick = { ( ) => onDiscard ( dashboard . id ) }
150- />
151- ) ) ;
152- if ( hasNewDashboard ) {
153- newItems . unshift (
154- < DashboardUnsavedItem
155- key = { DASHBOARD_PANELS_UNSAVED_ID }
156- onOpenClick = { ( ) => onOpen ( ) }
157- onDiscardClick = { ( ) => onDiscard ( ) }
158- />
159- ) ;
154+ const dashboardMap = { } ;
155+ if ( ! mounted ) {
156+ return ;
160157 }
161- setItems ( newItems ) ;
158+ setItems (
159+ dashboards . reduce ( ( map , dashboard ) => {
160+ return {
161+ ...map ,
162+ [ dashboard . id || DASHBOARD_PANELS_UNSAVED_ID ] : dashboard ,
163+ } ;
164+ } , dashboardMap )
165+ ) ;
162166 } ) ;
163- } , [ dashboardIds , onOpen , onDiscard , savedDashboards ] ) ;
167+ } , [ dashboardIds , savedDashboards , mounted ] ) ;
164168
165- return items . length === 0 ? null : (
169+ return dashboardIds . length === 0 ? null : (
166170 < >
167171 < EuiCallOut
168172 heading = "h3"
169- title = { dashboardUnsavedListingStrings . getUnsavedChangesTitle ( items . length > 1 ) }
173+ title = { dashboardUnsavedListingStrings . getUnsavedChangesTitle ( dashboardIds . length > 1 ) }
170174 >
171- { items }
175+ { dashboardIds . map ( ( dashboardId : string ) => {
176+ const title : string | undefined =
177+ dashboardId === DASHBOARD_PANELS_UNSAVED_ID
178+ ? getNewDashboardTitle ( )
179+ : items [ dashboardId ] ?. title ;
180+ const redirectId = dashboardId === DASHBOARD_PANELS_UNSAVED_ID ? undefined : dashboardId ;
181+ return (
182+ < DashboardUnsavedItem
183+ key = { dashboardId }
184+ id = { dashboardId }
185+ title = { title }
186+ onOpenClick = { ( ) => onOpen ( redirectId ) }
187+ onDiscardClick = { ( ) => onDiscard ( redirectId ) }
188+ />
189+ ) ;
190+ } ) }
172191 </ EuiCallOut >
173192 < EuiSpacer size = "m" />
174193 </ >
0 commit comments