1
- import React , { useCallback , useEffect , useRef , useState } from 'react' ;
1
+ import React from 'react' ;
2
2
import {
3
3
Button ,
4
4
css ,
@@ -13,19 +13,17 @@ import {
13
13
RadioGroup ,
14
14
spacing ,
15
15
SpinLoader ,
16
- openToast ,
17
16
} from '@mongodb-js/compass-components' ;
17
+ import type { ExportDiagramFormat } from '../store/export-diagram' ;
18
18
import {
19
19
closeExportModal ,
20
- selectCurrentModel ,
21
- getCurrentDiagramFromState ,
22
- } from '../store/diagram' ;
20
+ exportDiagram ,
21
+ selectFormat ,
22
+ } from '../store/export- diagram' ;
23
23
import { connect } from 'react-redux' ;
24
24
import type { DataModelingState } from '../store/reducer' ;
25
- import type { StaticModel } from '../services/data-model-storage' ;
26
- import { exportToJson , exportToPng } from '../services/export-diagram' ;
27
25
import { useDiagram } from '@mongodb-js/diagramming' ;
28
- import { isCancelError } from '@mongodb-js/compass-utils ' ;
26
+ import type { DiagramInstance } from '@mongodb-js/diagramming ' ;
29
27
30
28
const nbsp = '\u00a0' ;
31
29
@@ -52,79 +50,27 @@ const footerStyles = css({
52
50
53
51
type ExportDiagramModalProps = {
54
52
isModalOpen : boolean ;
55
- diagramLabel : string ;
56
- model : StaticModel | null ;
53
+ isExporting : boolean ;
54
+ exportFormat ?: ExportDiagramFormat ;
55
+ onExportDiagram : ( diagramInstance : DiagramInstance ) => void ;
56
+ onSelectFormat : ( format : ExportDiagramFormat ) => void ;
57
57
onCloseClick : ( ) => void ;
58
58
} ;
59
59
60
60
const ExportDiagramModal = ( {
61
61
isModalOpen,
62
- diagramLabel,
63
- model,
62
+ isExporting,
63
+ exportFormat,
64
+ onExportDiagram,
65
+ onSelectFormat,
64
66
onCloseClick,
65
67
} : ExportDiagramModalProps ) => {
66
- const [ exportFormat , setExportFormat ] = useState < 'png' | 'json' | null > ( null ) ;
67
68
const diagram = useDiagram ( ) ;
68
- const [ isExporting , setIsExporting ] = useState ( false ) ;
69
- const abortControllerRef = useRef < AbortController | null > ( null ) ;
70
- useEffect ( ( ) => {
71
- const cleanup = ( ) => {
72
- if ( abortControllerRef . current ) {
73
- abortControllerRef . current . abort ( ) ;
74
- abortControllerRef . current = null ;
75
- }
76
- } ;
77
- const abortController = new AbortController ( ) ;
78
- if ( isModalOpen ) {
79
- abortControllerRef . current = abortController ;
80
- } else {
81
- cleanup ( ) ;
82
- }
83
- return cleanup ;
84
- } , [ isModalOpen ] ) ;
85
-
86
- const onClose = useCallback ( ( ) => {
87
- setIsExporting ( false ) ;
88
- abortControllerRef . current ?. abort ( ) ;
89
- abortControllerRef . current = null ;
90
- onCloseClick ( ) ;
91
- } , [ onCloseClick ] ) ;
92
-
93
- const onExport = useCallback ( async ( ) => {
94
- try {
95
- if ( ! exportFormat || ! model ) {
96
- return ;
97
- }
98
- setIsExporting ( true ) ;
99
- if ( exportFormat === 'json' ) {
100
- exportToJson ( diagramLabel , model ) ;
101
- } else if ( exportFormat === 'png' ) {
102
- await exportToPng (
103
- diagramLabel ,
104
- diagram ,
105
- abortControllerRef . current ?. signal
106
- ) ;
107
- }
108
- } catch ( error ) {
109
- if ( isCancelError ( error ) ) {
110
- return ;
111
- }
112
- openToast ( 'export-diagram-error' , {
113
- variant : 'warning' ,
114
- title : 'Export failed' ,
115
- description : `An error occurred while exporting the diagram: ${
116
- ( error as Error ) . message
117
- } `,
118
- } ) ;
119
- } finally {
120
- onClose ( ) ;
121
- }
122
- } , [ exportFormat , onClose , model , diagram , diagramLabel ] ) ;
123
69
124
70
return (
125
71
< Modal
126
72
open = { isModalOpen }
127
- setOpen = { onClose }
73
+ setOpen = { onCloseClick }
128
74
data-testid = "export-diagram-modal"
129
75
>
130
76
< ModalHeader
@@ -153,7 +99,7 @@ const ExportDiagramModal = ({
153
99
checked = { exportFormat === 'png' }
154
100
value = "png"
155
101
aria-label = "PNG"
156
- onClick = { ( ) => setExportFormat ( 'png' ) }
102
+ onClick = { ( ) => onSelectFormat ( 'png' ) }
157
103
>
158
104
PNG
159
105
</ Radio >
@@ -164,7 +110,7 @@ const ExportDiagramModal = ({
164
110
checked = { exportFormat === 'json' }
165
111
value = "json"
166
112
aria-label = "JSON"
167
- onClick = { ( ) => setExportFormat ( 'json' ) }
113
+ onClick = { ( ) => onSelectFormat ( 'json' ) }
168
114
>
169
115
JSON
170
116
</ Radio >
@@ -175,15 +121,19 @@ const ExportDiagramModal = ({
175
121
< ModalFooter className = { footerStyles } >
176
122
< Button
177
123
variant = "primary"
178
- onClick = { ( ) => void onExport ( ) }
124
+ onClick = { ( ) => onExportDiagram ( diagram ) }
179
125
data-testid = "export-button"
180
- disabled = { ! exportFormat || ! model }
126
+ disabled = { ! exportFormat }
181
127
loadingIndicator = { < SpinLoader /> }
182
128
isLoading = { isExporting }
183
129
>
184
130
Export
185
131
</ Button >
186
- < Button variant = "default" onClick = { onClose } data-testid = "cancel-button" >
132
+ < Button
133
+ variant = "default"
134
+ onClick = { onCloseClick }
135
+ data-testid = "cancel-button"
136
+ >
187
137
Cancel
188
138
</ Button >
189
139
</ ModalFooter >
@@ -193,17 +143,18 @@ const ExportDiagramModal = ({
193
143
194
144
export default connect (
195
145
( state : DataModelingState ) => {
196
- const { diagram } = state ;
197
- const model = diagram
198
- ? selectCurrentModel ( getCurrentDiagramFromState ( state ) )
199
- : null ;
146
+ const {
147
+ exportDiagram : { isExporting, isModalOpen, exportFormat } ,
148
+ } = state ;
200
149
return {
201
- model ,
202
- diagramLabel : diagram ?. name ?? 'Schema Preview' ,
203
- isModalOpen : Boolean ( diagram ?. isExportModalOpen ) ,
150
+ isModalOpen ,
151
+ isExporting ,
152
+ exportFormat ,
204
153
} ;
205
154
} ,
206
155
{
207
156
onCloseClick : closeExportModal ,
157
+ onSelectFormat : selectFormat ,
158
+ onExportDiagram : exportDiagram ,
208
159
}
209
160
) ( ExportDiagramModal ) ;
0 commit comments