55 Inject ,
66 Input ,
77 OnInit ,
8+ TemplateRef ,
89 ViewChild ,
910} from '@angular/core' ;
1011import {
@@ -72,7 +73,11 @@ import { DfPaywallComponent } from 'src/app/shared/components/df-paywall/df-payw
7273import { CommonModule } from '@angular/common' ;
7374import { MatIconModule } from '@angular/material/icon' ;
7475import { HttpClient } from '@angular/common/http' ;
75- import { MatDialog , MatDialogModule } from '@angular/material/dialog' ;
76+ import {
77+ MatDialog ,
78+ MatDialogModule ,
79+ MatDialogRef ,
80+ } from '@angular/material/dialog' ;
7681import { MatMenuModule } from '@angular/material/menu' ;
7782import { DfThemeService } from 'src/app/shared/services/df-theme.service' ;
7883import { MatButtonToggleModule } from '@angular/material/button-toggle' ;
@@ -94,6 +99,8 @@ import { DfSystemService } from 'src/app/shared/services/df-system.service';
9499import { DfPaywallModal } from 'src/app/shared/components/df-paywall-modal/df-paywall-modal.component' ;
95100import { DfAnalyticsService } from 'src/app/shared/services/df-analytics.service' ;
96101
102+ type UnsavedToolChoice = 'save' | 'discard' | 'cancel' ;
103+
97104// Add these interfaces at the bottom of the file with the other interfaces
98105interface RoleResponse {
99106 resource : Array < {
@@ -159,6 +166,7 @@ interface ServiceResponse {
159166 MatDividerModule ,
160167 DfSecurityConfigComponent ,
161168 MatMenuModule ,
169+ MatDialogModule ,
162170 ] ,
163171} )
164172export class DfServiceDetailsComponent implements OnInit {
@@ -255,6 +263,10 @@ export class DfServiceDetailsComponent implements OnInit {
255263 availableLookups : Array < { name : string } > = [ ] ;
256264 @ViewChild ( 'functionEditor' ) functionEditor : DfAceEditorComponent ;
257265 @ViewChild ( 'headersEditor' ) headersEditor : DfAceEditorComponent ;
266+ @ViewChild ( 'unsavedToolDialog' )
267+ unsavedToolDialogTpl ! : TemplateRef < unknown > ;
268+ private unsavedToolDialogRef : MatDialogRef < unknown , UnsavedToolChoice > | null =
269+ null ;
258270 private liveHeadersValue : string | null = null ;
259271 private liveFunctionValue : string | null = null ;
260272
@@ -1155,6 +1167,14 @@ export class DfServiceDetailsComponent implements OnInit {
11551167 this . editingToolIndex = null ;
11561168 }
11571169
1170+ hasUnsavedCustomTool ( ) : boolean {
1171+ return this . editingToolIndex !== null && this . customToolForm . dirty ;
1172+ }
1173+
1174+ closeUnsavedToolDialog ( choice : UnsavedToolChoice ) {
1175+ this . unsavedToolDialogRef ?. close ( choice ) ;
1176+ }
1177+
11581178 toggleCustomTool ( index : number , enabled : boolean ) {
11591179 this . customTools [ index ] . enabled = enabled ;
11601180 }
@@ -1450,6 +1470,37 @@ export class DfServiceDetailsComponent implements OnInit {
14501470 warnings : string [ ] = [ ] ;
14511471
14521472 save ( Cache : boolean , Continue : boolean ) {
1473+ if ( this . hasUnsavedCustomTool ( ) ) {
1474+ if ( this . unsavedToolDialogRef ) return ;
1475+ this . unsavedToolDialogRef = this . dialog . open <
1476+ unknown ,
1477+ unknown ,
1478+ UnsavedToolChoice
1479+ > ( this . unsavedToolDialogTpl , {
1480+ width : '440px' ,
1481+ disableClose : true ,
1482+ } ) ;
1483+ this . unsavedToolDialogRef . afterClosed ( ) . subscribe ( choice => {
1484+ this . unsavedToolDialogRef = null ;
1485+ if ( ! choice || choice === 'cancel' ) return ;
1486+ if ( choice === 'save' ) {
1487+ if ( this . customToolForm . invalid ) {
1488+ this . snackbarService . openSnackBar (
1489+ 'Custom tool has invalid fields. Fix them or discard the edit before saving the service.' ,
1490+ 'error'
1491+ ) ;
1492+ return ;
1493+ }
1494+ this . saveCustomTool ( ) ;
1495+ } else {
1496+ this . cancelCustomToolEdit ( ) ;
1497+ }
1498+ this . customToolForm . markAsPristine ( ) ;
1499+ this . save ( Cache , Continue ) ;
1500+ } ) ;
1501+ return ;
1502+ }
1503+
14531504 const data = this . serviceForm . getRawValue ( ) ;
14541505 if ( data . type === '' || data . name === '' ) {
14551506 return ;
0 commit comments