5
5
6
6
import React , { useEffect , useState } from 'react' ;
7
7
import { RouteComponentProps , useLocation } from 'react-router-dom' ;
8
- import { useSelector } from 'react-redux' ;
8
+ import { useDispatch , useSelector } from 'react-redux' ;
9
9
import { ReactFlowProvider } from 'reactflow' ;
10
10
import queryString from 'query-string' ;
11
11
import { EuiPage , EuiPageBody } from '@elastic/eui' ;
12
12
import { BREADCRUMBS } from '../../utils' ;
13
13
import { getCore } from '../../services' ;
14
14
import { WorkflowDetailHeader } from './components' ;
15
- import { AppState } from '../../store' ;
15
+ import { AppState , searchWorkflows } from '../../store' ;
16
16
import { ResizableWorkspace } from './workspace' ;
17
17
import { Launches } from './launches' ;
18
18
import { Prototype } from './prototype' ;
19
+ import {
20
+ DEFAULT_NEW_WORKFLOW_NAME ,
21
+ NEW_WORKFLOW_ID_URL ,
22
+ } from '../../../common' ;
19
23
20
24
export interface WorkflowDetailRouterProps {
21
25
workflowId : string ;
@@ -45,13 +49,27 @@ function replaceActiveTab(activeTab: string, props: WorkflowDetailProps) {
45
49
* The workflow details page. This is where users will configure, create, and
46
50
* test their created workflows. Additionally, can be used to load existing workflows
47
51
* to view details and/or make changes to them.
52
+ * New, unsaved workflows are cached in the redux store and displayed here.
48
53
*/
54
+
49
55
export function WorkflowDetail ( props : WorkflowDetailProps ) {
50
- const { workflows } = useSelector ( ( state : AppState ) => state . workflows ) ;
56
+ const dispatch = useDispatch ( ) ;
57
+ const { workflows, cachedWorkflow } = useSelector (
58
+ ( state : AppState ) => state . workflows
59
+ ) ;
60
+ const { isDirty } = useSelector ( ( state : AppState ) => state . workspace ) ;
51
61
52
- const workflow = workflows [ props . match ?. params ?. workflowId ] ;
53
- const workflowName = workflow ? workflow . name : '' ;
62
+ // selected workflow state
63
+ const workflowId = props . match ?. params ?. workflowId ;
64
+ const isNewWorkflow = workflowId === NEW_WORKFLOW_ID_URL ;
65
+ const workflow = isNewWorkflow ? cachedWorkflow : workflows [ workflowId ] ;
66
+ const workflowName = workflow
67
+ ? workflow . name
68
+ : isNewWorkflow && ! workflow
69
+ ? DEFAULT_NEW_WORKFLOW_NAME
70
+ : '' ;
54
71
72
+ // tab state
55
73
const tabFromUrl = queryString . parse ( useLocation ( ) . search ) [
56
74
ACTIVE_TAB_PARAM
57
75
] as WORKFLOW_DETAILS_TAB ;
@@ -78,6 +96,19 @@ export function WorkflowDetail(props: WorkflowDetailProps) {
78
96
] ) ;
79
97
} ) ;
80
98
99
+ // On initial load:
100
+ // - fetch workflow, if there is an existing workflow ID
101
+ // - add a window listener to warn users if they exit/refresh
102
+ // without saving latest changes
103
+ useEffect ( ( ) => {
104
+ if ( ! isNewWorkflow ) {
105
+ // TODO: can optimize to only fetch a single workflow
106
+ dispatch ( searchWorkflows ( { query : { match_all : { } } } ) ) ;
107
+ }
108
+ window . onbeforeunload = ( e ) =>
109
+ isDirty || isNewWorkflow ? true : undefined ;
110
+ } , [ ] ) ;
111
+
81
112
const tabs = [
82
113
{
83
114
id : WORKFLOW_DETAILS_TAB . EDITOR ,
@@ -112,7 +143,11 @@ export function WorkflowDetail(props: WorkflowDetailProps) {
112
143
< ReactFlowProvider >
113
144
< EuiPage >
114
145
< EuiPageBody >
115
- < WorkflowDetailHeader workflow = { workflow } tabs = { tabs } />
146
+ < WorkflowDetailHeader
147
+ workflow = { workflow }
148
+ isNewWorkflow = { isNewWorkflow }
149
+ tabs = { tabs }
150
+ />
116
151
{ selectedTabId === WORKFLOW_DETAILS_TAB . EDITOR && (
117
152
< ResizableWorkspace workflow = { workflow } />
118
153
) }
0 commit comments