diff --git a/src/app/components/common/node-editor/flow-editor.module.ts b/src/app/components/common/node-editor/flow-editor.module.ts index ff23f22d3..00fa29271 100644 --- a/src/app/components/common/node-editor/flow-editor.module.ts +++ b/src/app/components/common/node-editor/flow-editor.module.ts @@ -20,11 +20,13 @@ import { AddTaskWizardComponent } from '../../core/north/add-task-wizard/add-tas import { ReadingsCountComponent } from './south/asset-readings/readings-count.component'; import { DirectivesModule } from '../../../directives/directives.module'; import { AssetTrackerComponent } from './south/asset-tracker/asset-tracker.component'; +import { canDeactivateGuard } from '../../../guards/can-deactivate/can-deactivate.guard'; const routes: Routes = [ { path: 'editor/:from', component: NodeEditorComponent, + canDeactivate: [canDeactivateGuard] }, { path: 'editor/:from/:name/details', diff --git a/src/app/components/common/node-editor/node-editor.component.html b/src/app/components/common/node-editor/node-editor.component.html index 5ae084a9e..9186efc98 100644 --- a/src/app/components/common/node-editor/node-editor.component.html +++ b/src/app/components/common/node-editor/node-editor.component.html @@ -42,8 +42,10 @@ - +
@@ -54,7 +56,7 @@ - + - -
+
-
@@ -113,8 +116,8 @@
- @@ -126,7 +129,8 @@

- +

@@ -138,8 +142,8 @@ + (selectedAsset)="selectAsset($event)" (reloadReadings)="getSouthservices()" + (exportReading)="getAssetReadings(readingService)">
@@ -147,12 +151,14 @@
@@ -191,6 +197,8 @@
+ +
@@ -71,4 +72,7 @@
- \ No newline at end of file + + + + diff --git a/src/app/components/core/configuration-manager/configuration-manager.component.ts b/src/app/components/core/configuration-manager/configuration-manager.component.ts index e054a9cee..e42d62263 100644 --- a/src/app/components/core/configuration-manager/configuration-manager.component.ts +++ b/src/app/components/core/configuration-manager/configuration-manager.component.ts @@ -6,6 +6,8 @@ import { AlertService, ConfigurationControlService, ConfigurationService, FileUploaderService, ProgressBarService, RolesService, SchedulesService } from '../../../services'; +import { Observable } from 'rxjs'; +import { DialogService } from '../../common/confirmation-dialog/dialog.service'; @Component({ selector: 'app-configuration-manager', @@ -35,9 +37,14 @@ export class ConfigurationManagerComponent implements OnInit { public ngProgress: ProgressBarService, private configurationControlService: ConfigurationControlService, private fileUploaderService: FileUploaderService, - public schedulesService: SchedulesService + public schedulesService: SchedulesService, + public unsavedChangesService: DialogService, ) { } + canDeactivate(): Observable | boolean { + return this.unsavedChangesService.confirm({ id: 'unsaved-changes-dialog', changeExist: !isEmpty(this.changedConfig) }); + } + ngOnInit() { this.getSchedules(); this.getTreeStructure(); @@ -51,7 +58,7 @@ export class ConfigurationManagerComponent implements OnInit { (data: any) => { this.categoryData = data.categories; const excludeCategories = this.scheduleNames.concat(["SOUTH", "NORTH", "NOTIFICATIONS"]); - + // filter south, north, notification, management, bucket, dispatcher categories this.categoryData = this.categoryData.filter((n: any) => { return !excludeCategories.includes(n.key.toUpperCase()); @@ -89,7 +96,7 @@ export class ConfigurationManagerComponent implements OnInit { node.id = node.key; node.name = (node.hasOwnProperty('displayName')) ? node.displayName : node.description; node.hasChildren = false; - // If the object has 'children' property recurse + // If the object has 'children' property recurse if (Array.isArray(node.children) && node.children.length > 0) { node.hasChildren = true; this.updateIdAndNameInTreeObject(node.children); @@ -113,7 +120,7 @@ export class ConfigurationManagerComponent implements OnInit { public onNodeActive(tree: TreeComponent) { const rootId = tree.treeModel.focusedNodeId?.toString(); - // In case of root node is in ['Advanced', 'General', 'Utilities'], + // In case of root node is in ['Advanced', 'General', 'Utilities'], // Expand the group and select first child if (['Advanced', 'General', 'Utilities'].includes(rootId)) { const nodes = tree.treeModel.nodes; diff --git a/src/app/components/core/configuration-manager/configuration.module.ts b/src/app/components/core/configuration-manager/configuration.module.ts index dcce513e6..9adf99a6e 100644 --- a/src/app/components/core/configuration-manager/configuration.module.ts +++ b/src/app/components/core/configuration-manager/configuration.module.ts @@ -8,11 +8,13 @@ import { ConfigurationManagerComponent } from '.'; import { DirectivesModule } from '../../../directives/directives.module'; import { ConfigurationService } from '../../../services'; import { SharedModule } from '../../../shared.module'; +import { canDeactivateGuard } from '../../../guards/can-deactivate/can-deactivate.guard'; const routes: Routes = [ { path: '', - component: ConfigurationManagerComponent + component: ConfigurationManagerComponent, + canDeactivate: [canDeactivateGuard] } ]; diff --git a/src/app/components/core/control-dispatcher/add-control-acl/add-control-acl.component.html b/src/app/components/core/control-dispatcher/add-control-acl/add-control-acl.component.html index 739ab3da3..2e968cd3f 100644 --- a/src/app/components/core/control-dispatcher/add-control-acl/add-control-acl.component.html +++ b/src/app/components/core/control-dispatcher/add-control-acl/add-control-acl.component.html @@ -18,7 +18,8 @@
+ class=" icon is-small has-tooltip-left has-tooltip-arrow tooltip is-pulled-right is-hovered help-icon" + data-tooltip="Help">
@@ -56,7 +57,8 @@
-
@@ -79,7 +81,8 @@
-
@@ -284,6 +287,10 @@
- +
- \ No newline at end of file + + + + diff --git a/src/app/components/core/control-dispatcher/add-control-acl/add-control-acl.component.ts b/src/app/components/core/control-dispatcher/add-control-acl/add-control-acl.component.ts index a7d6bc2a9..8c6907d87 100644 --- a/src/app/components/core/control-dispatcher/add-control-acl/add-control-acl.component.ts +++ b/src/app/components/core/control-dispatcher/add-control-acl/add-control-acl.component.ts @@ -8,6 +8,7 @@ import { uniqBy } from 'lodash'; import { DocService } from '../../../../services/doc.service'; import { CustomValidator } from '../../../../directives/custom-validator'; import { SUPPORTED_SERVICE_TYPES, QUOTATION_VALIDATION_PATTERN } from '../../../../utils'; +import { Observable } from 'rxjs'; @Component({ selector: 'app-add-control-acl', @@ -45,6 +46,10 @@ export class AddControlAclComponent implements OnInit { private servicesApiService: ServicesApiService, public sharedService: SharedService) { } + canDeactivate(): Observable | boolean { + return this.dialogService.confirm({ id: 'unsaved-changes-dialog', changeExist: this.aclForm.dirty }); + } + ngOnInit(): void { this.route.params.subscribe(params => { this.name = params['name']; diff --git a/src/app/components/core/control-dispatcher/add-control-script/add-control-script.component.html b/src/app/components/core/control-dispatcher/add-control-script/add-control-script.component.html index 446052453..3cd223339 100644 --- a/src/app/components/core/control-dispatcher/add-control-script/add-control-script.component.html +++ b/src/app/components/core/control-dispatcher/add-control-script/add-control-script.component.html @@ -135,4 +135,7 @@ - \ No newline at end of file + + + + diff --git a/src/app/components/core/control-dispatcher/add-control-script/add-control-script.component.ts b/src/app/components/core/control-dispatcher/add-control-script/add-control-script.component.ts index dd8297144..399ab2cd2 100644 --- a/src/app/components/core/control-dispatcher/add-control-script/add-control-script.component.ts +++ b/src/app/components/core/control-dispatcher/add-control-script/add-control-script.component.ts @@ -9,6 +9,7 @@ import { DocService } from '../../../../services/doc.service'; import { DialogService } from '../../../common/confirmation-dialog/dialog.service'; import { AddStepComponent } from './add-step/add-step.component'; import { QUOTATION_VALIDATION_PATTERN } from '../../../../utils'; +import { Observable } from 'rxjs'; @Component({ @@ -44,6 +45,10 @@ export class AddControlScriptComponent implements OnInit { public rolesService: RolesService, private router: Router) { } + canDeactivate(): Observable | boolean { + return this.dialogService.confirm({ id: 'unsaved-changes-dialog', changeExist: this.scriptForm.dirty }); + } + ngOnInit(): void { this.route.params.subscribe(params => { this.scriptName = params['name']; @@ -157,7 +162,7 @@ export class AddControlScriptComponent implements OnInit { steps.forEach((val: any) => { const keys = Object.keys(val); keys.forEach(key => { - // remove invalid(null, undefined) values from object + // remove invalid(null, undefined) values from object val[key] = pickBy(val[key]); if ('condition' in val[key]) { if (isEmpty(val[key]['condition'].key) || val[key]['condition'].value == null) { diff --git a/src/app/components/core/control-dispatcher/api-flow/add-edit-api-flow/add-edit-api-flow.component.html b/src/app/components/core/control-dispatcher/api-flow/add-edit-api-flow/add-edit-api-flow.component.html index ea0f133f4..4d7adaaf2 100644 --- a/src/app/components/core/control-dispatcher/api-flow/add-edit-api-flow/add-edit-api-flow.component.html +++ b/src/app/components/core/control-dispatcher/api-flow/add-edit-api-flow/add-edit-api-flow.component.html @@ -1,525 +1,563 @@
- - -
-
- - - - -
-
-
- + + +
+
+ + + + +
+
+
+ +
+
+
+
+
-
-
-
- -
-
-
- *required -
-
-
+
+
+ *required +
+
-
-
- -
-
-
-
- +
+
+ +
+
+
+
+
- +
+ +
+ +
+ +
+
+ *required +
+
+
+ +
- -
- -
-
- *required -
-
+
+ +
- - + +
-
- -
+
- -
-
- -
-
-
- -
+
+ +
- -
-
- -
-
-
-
-
-
-
-
-
-
-
- -
-
-
-
- - -
- - - -
-
-
-
-
- -
-
-
-
- - -
-
- *required -
- - - -
-
-
-
-
-
+
+ +
+
+ +
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+ + +
+ + +
+
+
+
+ +
+
+
+
+ + +
+
+ *required +
+ + + +
+
+
+
+
+
+
-
+
-
-
- -
+
+
+
+ +
+
+
-
-
-
-
-
-
-
- -
-
-
- -
-
- -
-
-
- -
-
- -
-
- -
-
-
-
- - -
-
-
-
- -
-
-
- -
-
-
-
-
+
+
+
+
+
+ +
+
+
+ +
+
+ +
-
-
-
-
- -
+
+ +
+
+ +
+
+ +
+
+
+
+ + +
-
-
- -
-
-
- -
-
- -
-
-
- -
-
- -
-
- -
-
-
-
- - -
-
-
-
- -
-
-
- -
-
-
-
-
-
-
-
-
-
- -
+
+
+ +
+
+ +
+
+ + +
+
+
+
+
+ +
-
-
-
-
-
-
-
-
-
- -
-
- -
-
-
-
-
-
-
-
-
-
-
- Setting execution access to be anonymous will allow any user to execute this entry point. It's recommended to disable the anonymous access & allow specific authorized users only. -
-
-
-
- -
-
-
- -
- -
-
-
-
-
-
- +
+
+ +
+
+
+ +
+
+ +
+
+
+ +
+
+ +
+
+ +
+
+
+
+ + +
-
-
-
- - -
- - - -

*Allow list will only be applicable when the anonymous access is disabled.

-
+
+
+ +
+
+
+
- -
-
+ + +
+
+
+
+
+ +
+
+
+
+
+
-
+
+
-
-
- -
-
-
- -
- -
-
-
- *required -
-
-
- - - -
-
+
+
+
- - + +
+ - + -
+ +
- -
+ +
- - -
- - -
-
\ No newline at end of file + + +
+ + +
+ + + + diff --git a/src/app/components/core/control-dispatcher/api-flow/add-edit-api-flow/add-edit-api-flow.component.ts b/src/app/components/core/control-dispatcher/api-flow/add-edit-api-flow/add-edit-api-flow.component.ts index e5014d16d..3d1ba69ee 100644 --- a/src/app/components/core/control-dispatcher/api-flow/add-edit-api-flow/add-edit-api-flow.component.ts +++ b/src/app/components/core/control-dispatcher/api-flow/add-edit-api-flow/add-edit-api-flow.component.ts @@ -9,235 +9,239 @@ import { ActivatedRoute, Router } from '@angular/router'; import { ControlUtilsService } from '../../control-utils.service'; import { DocService } from '../../../../../services/doc.service'; -import { Subject } from 'rxjs'; +import { Observable, Subject } from 'rxjs'; import { takeUntil } from 'rxjs/operators'; import { - AlertService, - ControlAPIFlowService, - ProgressBarService, - SchedulesService, - UserService, - RolesService, - SharedService, - AssetsService, - ControlPipelinesService - } from '../../../../../services'; - import { ControlDispatcherService } from '../../../../../services/control-dispatcher.service'; - import { DialogService } from '../../../../common/confirmation-dialog/dialog.service'; - import { QUOTATION_VALIDATION_PATTERN } from '../../../../../utils'; + AlertService, + ControlAPIFlowService, + ProgressBarService, + SchedulesService, + UserService, + RolesService, + SharedService, + AssetsService, + ControlPipelinesService +} from '../../../../../services'; +import { ControlDispatcherService } from '../../../../../services/control-dispatcher.service'; +import { DialogService } from '../../../../common/confirmation-dialog/dialog.service'; +import { QUOTATION_VALIDATION_PATTERN } from '../../../../../utils'; @Component({ - selector: 'app-add-edit-api-flow', - templateUrl: './add-edit-api-flow.component.html', - styleUrls: ['./add-edit-api-flow.component.css'] + selector: 'app-add-edit-api-flow', + templateUrl: './add-edit-api-flow.component.html', + styleUrls: ['./add-edit-api-flow.component.css'] }) export class AddEditAPIFlowComponent implements OnInit { - QUOTATION_VALIDATION_PATTERN = QUOTATION_VALIDATION_PATTERN; - - selectedType; - types = []; - - selectedDestinationType = { cpdid: 0, name: "Broadcast" }; // Typecast with DestinationType enum - selectedDestinationName = null; - - destinationTypes = []; - destinationNames = []; - - editMode = false; - - apiFlowName: string; - af: APIFlow; - - apiFlowForm: UntypedFormGroup; - - allUsers: User[]; - loggedInUsername: string; - - APIFlowType = ['write', 'operation']; - - destroy$: Subject = new Subject(); - - public reenableButton = new EventEmitter(false); - constructor( - private route: ActivatedRoute, - private assetService: AssetsService, - private controlAPIFlowService: ControlAPIFlowService, - private controlService: ControlDispatcherService, - private controlPipelinesService: ControlPipelinesService, - private schedulesService: SchedulesService, - private alertService: AlertService, - private ngProgress: ProgressBarService, - private fb: UntypedFormBuilder, - public rolesService: RolesService, - private dialogService: DialogService, - public docService: DocService, - public sharedService: SharedService, - private userService: UserService, - private controlUtilsService: ControlUtilsService, - private titlecasePipe: TitleCasePipe, - private router: Router) { - this.apiFlowForm = this.fb.group({ - name: ['', Validators.required], - description: ['', Validators.required], - operation_name: [''], - variables: this.fb.array([]), - constants: this.fb.array([]) - }); - this.sharedService.isUserLoggedIn - .pipe(takeUntil(this.destroy$)) - .subscribe(value => { - this.loggedInUsername = value.userName; - }); - } - - ngOnInit() { - this.af = { - name: '', - type: 'write', - description: '', - operation_name: '', - permitted: false, - destination: 'broadcast', - constants: {}, - variables: {}, - anonymous: false, - allow: [] - }; - this.getDestTypes(); - this.getUsers(); - this.route.params.subscribe(params => { - this.apiFlowName = params['name']; - if (this.apiFlowName) { - this.getAPIFlow(); - } else { - this.selectedType = 'write'; - } - }); - } - - addParameter(param = null, controlType = null) { - if (controlType == null) { - const variableControl = this.apiFlowForm.controls['variables']; - const constControl = this.apiFlowForm.controls['constants']; - variableControl.push(this.initParameter(param, 'variables')); - constControl.push(this.initParameter(param, 'constants')); - } else { - const control = this.apiFlowForm.controls[controlType]; - control.push(this.initParameter(param, controlType)); - } + QUOTATION_VALIDATION_PATTERN = QUOTATION_VALIDATION_PATTERN; + + selectedType; + types = []; + + selectedDestinationType = { cpdid: 0, name: "Broadcast" }; // Typecast with DestinationType enum + selectedDestinationName = null; + + destinationTypes = []; + destinationNames = []; + + editMode = false; + + apiFlowName: string; + af: APIFlow; + + apiFlowForm: UntypedFormGroup; + + allUsers: User[]; + loggedInUsername: string; + + APIFlowType = ['write', 'operation']; + + destroy$: Subject = new Subject(); + + public reenableButton = new EventEmitter(false); + constructor( + private route: ActivatedRoute, + private assetService: AssetsService, + private controlAPIFlowService: ControlAPIFlowService, + private controlService: ControlDispatcherService, + private controlPipelinesService: ControlPipelinesService, + private schedulesService: SchedulesService, + private alertService: AlertService, + private ngProgress: ProgressBarService, + private fb: UntypedFormBuilder, + public rolesService: RolesService, + private dialogService: DialogService, + public docService: DocService, + public sharedService: SharedService, + private userService: UserService, + private controlUtilsService: ControlUtilsService, + private titlecasePipe: TitleCasePipe, + private router: Router) { + this.apiFlowForm = this.fb.group({ + name: ['', Validators.required], + description: ['', Validators.required], + operation_name: [''], + variables: this.fb.array([]), + constants: this.fb.array([]) + }); + this.sharedService.isUserLoggedIn + .pipe(takeUntil(this.destroy$)) + .subscribe(value => { + this.loggedInUsername = value.userName; + }); + } + + canDeactivate(): Observable | boolean { + return this.dialogService.confirm({ id: 'unsaved-changes-dialog', changeExist: this.apiFlowForm.dirty }); + } + + ngOnInit() { + this.af = { + name: '', + type: 'write', + description: '', + operation_name: '', + permitted: false, + destination: 'broadcast', + constants: {}, + variables: {}, + anonymous: false, + allow: [] + }; + this.getDestTypes(); + this.getUsers(); + this.route.params.subscribe(params => { + this.apiFlowName = params['name']; + if (this.apiFlowName) { + this.getAPIFlow(); + } else { + this.selectedType = 'write'; + } + }); + } + + addParameter(param = null, controlType = null) { + if (controlType == null) { + const variableControl = this.apiFlowForm.controls['variables']; + const constControl = this.apiFlowForm.controls['constants']; + variableControl.push(this.initParameter(param, 'variables')); + constControl.push(this.initParameter(param, 'constants')); + } else { + const control = this.apiFlowForm.controls[controlType]; + control.push(this.initParameter(param, controlType)); } - - removeParameter(index: number, param) { - // remove parameter from the list - const control = this.apiFlowForm.controls[param]; - control.removeAt(index); - this.apiFlowForm.markAsDirty(); + } + + removeParameter(index: number, param) { + // remove parameter from the list + const control = this.apiFlowForm.controls[param]; + control.removeAt(index); + this.apiFlowForm.markAsDirty(); + } + + initParameter(param = null, controlType) { + if (controlType === 'variables') { + return this.fb.group({ + vName: [param?.key, Validators.required], + vValue: [param?.value] + }); + } else { + return this.fb.group({ + cName: [param?.key, Validators.required], + cValue: [param?.value] + }); } - - initParameter(param = null, controlType) { - if (controlType === 'variables') { - return this.fb.group({ - vName: [param?.key, Validators.required], - vValue: [param?.value] - }); - } else { - return this.fb.group({ - cName: [param?.key, Validators.required], - cValue: [param?.value] - }); - } + } + + fillParameters(param, controlType) { + let c = this.apiFlowForm.controls[controlType]; + c.clear(); + let i = 0; + for (const [key, value] of Object.entries(param)) { + this.addParameter({ index: i, key: key, value: value }, controlType); + i++; } + } - fillParameters(param, controlType) { - let c = this.apiFlowForm.controls[controlType]; - c.clear(); - let i = 0; - for (const [key, value] of Object.entries(param)) { - this.addParameter({ index: i, key: key, value: value }, controlType); - i++; + public toggleDropdown(id) { + const activeDropDowns = Array.prototype.slice.call(document.querySelectorAll('.dropdown.is-active')); + if (activeDropDowns.length > 0) { + if (activeDropDowns[0].id !== id) { + activeDropDowns[0].classList.remove('is-active'); } } + const dropDown = document.querySelector(`#${id}`); + dropDown.classList.toggle('is-active'); + } + + getAPIFlow() { + /** request started */ + this.ngProgress.start(); + this.controlAPIFlowService.getAPIFlow(this.apiFlowName) + .subscribe((data: APIFlow) => { + this.editMode = true; + this.ngProgress.done(); + this.af = data; + + this.apiFlowForm.get('name').setValue(data.name); + this.apiFlowForm.get('description').setValue(data.description); + if (data.type === 'operation') { + this.apiFlowForm.get('operation_name').setValue(data.operation_name); + } - public toggleDropdown(id) { - const activeDropDowns = Array.prototype.slice.call(document.querySelectorAll('.dropdown.is-active')); - if (activeDropDowns.length > 0) { - if (activeDropDowns[0].id !== id) { - activeDropDowns[0].classList.remove('is-active'); + this.getDestinationNames({ 'name': this.titlecasePipe.transform(this.af.destination) }); + if (this.af.destination.toLowerCase() !== 'broadcast') { + this.selectedDestinationName = this.af[this.af.destination.toLowerCase()]; } - } - const dropDown = document.querySelector(`#${id}`); - dropDown.classList.toggle('is-active'); - } + this.selectedType = data.type; + + this.fillParameters(data.variables, 'variables'); + this.fillParameters(data.constants, 'constants'); + }, error => { + /** request completed */ + this.ngProgress.done(); + if (error.status === 0) { + console.log('service down ', error); + } else { + this.alertService.error(error.statusText); + } + }); + } - getAPIFlow() { - /** request started */ - this.ngProgress.start(); - this.controlAPIFlowService.getAPIFlow(this.apiFlowName) - .subscribe((data: APIFlow) => { - this.editMode = true; - this.ngProgress.done(); - this.af = data; - - this.apiFlowForm.get('name').setValue(data.name); - this.apiFlowForm.get('description').setValue(data.description); - if (data.type === 'operation') { - this.apiFlowForm.get('operation_name').setValue(data.operation_name); - } - - this.getDestinationNames({'name': this.titlecasePipe.transform(this.af.destination)}); - if (this.af.destination.toLowerCase() !== 'broadcast') { - this.selectedDestinationName = this.af[this.af.destination.toLowerCase()]; - } - this.selectedType = data.type; - - this.fillParameters(data.variables, 'variables'); - this.fillParameters(data.constants, 'constants'); - }, error => { - /** request completed */ - this.ngProgress.done(); - if (error.status === 0) { - console.log('service down ', error); - } else { - this.alertService.error(error.statusText); - } - }); + saveAPIFlow(data) { + let payload = this.af; + + payload.name = data.name; + payload.description = data.description; + payload.type = this.selectedType; + if (payload.type === 'operation') { + payload.operation_name = data.operation_name; } - saveAPIFlow(data) { - let payload = this.af; - - payload.name = data.name; - payload.description = data.description; - payload.type = this.selectedType; - if (payload.type === 'operation') { - payload.operation_name = data.operation_name; - } - - const destination = this.af.destination.toLowerCase(); - payload.destination = destination; - if (destination !== 'broadcast') { - payload[destination] = this.selectedDestinationName; - } + const destination = this.af.destination.toLowerCase(); + payload.destination = destination; + if (destination !== 'broadcast') { + payload[destination] = this.selectedDestinationName; + } - let variables = {}; - let constants = {}; - data.variables.forEach(v => { variables[v.vName] = v.vValue }); - data.constants.forEach(c => { constants[c.cName] = c.cValue }); - payload.variables = variables; - payload.constants = constants; + let variables = {}; + let constants = {}; + data.variables.forEach(v => { variables[v.vName] = v.vValue }); + data.constants.forEach(c => { constants[c.cName] = c.cValue }); + payload.variables = variables; + payload.constants = constants; - if (this.editMode) { - this.updateAPIFlow(); - return; - } - this.addAPIFlow(); + if (this.editMode) { + this.updateAPIFlow(); + return; } + this.addAPIFlow(); + } - addAPIFlow() { - this.controlAPIFlowService.createAPIFlow(this.af) + addAPIFlow() { + this.controlAPIFlowService.createAPIFlow(this.af) .subscribe( (data: any) => { /** request completed */ @@ -255,11 +259,11 @@ export class AddEditAPIFlowComponent implements OnInit { } else { this.alertService.error(error.statusText); } - }); - } + }); + } - updateAPIFlow() { - this.controlAPIFlowService.updateAPIFlow(this.apiFlowName, this.af) + updateAPIFlow() { + this.controlAPIFlowService.updateAPIFlow(this.apiFlowName, this.af) .subscribe( (data: any) => { /** request completed */ @@ -277,236 +281,236 @@ export class AddEditAPIFlowComponent implements OnInit { } else { this.alertService.error(error.statusText); } - }); - } + }); + } - deleteAPIFlow() { - this.controlAPIFlowService.deleteAPIFlow(this.apiFlowName) - .subscribe( - (data: any) => { - /** request completed */ - this.ngProgress.done(); - this.reenableButton.emit(false); - this.alertService.success(data.message, true); - this.navigateToList(); - }, - error => { - /** request completed but error */ - this.ngProgress.done(); - this.reenableButton.emit(false); - if (error.status === 0) { - console.log('service down ', error); - } else { - this.alertService.error(error.statusText); - } - }); - } + deleteAPIFlow() { + this.controlAPIFlowService.deleteAPIFlow(this.apiFlowName) + .subscribe( + (data: any) => { + /** request completed */ + this.ngProgress.done(); + this.reenableButton.emit(false); + this.alertService.success(data.message, true); + this.navigateToList(); + }, + error => { + /** request completed but error */ + this.ngProgress.done(); + this.reenableButton.emit(false); + if (error.status === 0) { + console.log('service down ', error); + } else { + this.alertService.error(error.statusText); + } + }); + } - checkAndRequestAPIFlow() { - if (this.getFormControls('variables').length > 0) { - this.openModal('confirmation-execute-dialog') - } else { + checkAndRequestAPIFlow() { + if (this.getFormControls('variables').length > 0) { + this.openModal('confirmation-execute-dialog') + } else { this.requestAPIFlow({}); - } - } - - requestAPIFlow(payload) { - this.controlUtilsService.requestAPIFlow(this.af.name, payload); - this.getAPIFlow(); - } - - changeType(value) { - this.selectedType = value === 'Select Type' ? '' : value; } - - getDestTypes() { - this.controlPipelinesService.getSourceDestinationTypeList('destination') - .subscribe((data: any) => { - this.ngProgress.done(); - this.destinationTypes = data.filter(d => d.name !== 'Any'); - }, error => { - if (error.status === 0) { - console.log('service down ', error); - } else { - this.alertService.error(error.statusText); - } - }); - } - - navigateToList() { - this.router.navigate(['control-dispatcher/entry-points']); - } - - onCheckboxClicked(event) { - this.af.anonymous = event.target.checked; - } - - getFormControls(type): AbstractControl[] { - return (this.apiFlowForm.get(type)).controls; - } - - selectDestinationName(value) { - this.selectedDestinationName = value === 'Select Destination Name' ? null : value; - } - - getDestinationNames(selectedType) { - this.destinationNames = []; - this.selectedDestinationName = null; - this.af.destination = selectedType.name === 'Select Destination Type' ? '' : selectedType.name; - switch (selectedType.name) { - case 'Broadcast': - this.selectedDestinationName = null; - break; - case 'Service': - this.getServiceNames(); - break; - case 'Asset': - this.getAssetNames(); - break; - case 'Script': - this.getScriptNames(); - break; - default: - break; - } + } + + requestAPIFlow(payload) { + this.controlUtilsService.requestAPIFlow(this.af.name, payload); + this.getAPIFlow(); + } + + changeType(value) { + this.selectedType = value === 'Select Type' ? '' : value; + } + + getDestTypes() { + this.controlPipelinesService.getSourceDestinationTypeList('destination') + .subscribe((data: any) => { + this.ngProgress.done(); + this.destinationTypes = data.filter(d => d.name !== 'Any'); + }, error => { + if (error.status === 0) { + console.log('service down ', error); + } else { + this.alertService.error(error.statusText); + } + }); + } + + navigateToList() { + this.router.navigate(['control-dispatcher/entry-points']); + } + + onCheckboxClicked(event) { + this.af.anonymous = event.target.checked; + } + + getFormControls(type): AbstractControl[] { + return (this.apiFlowForm.get(type)).controls; + } + + selectDestinationName(value) { + this.selectedDestinationName = value === 'Select Destination Name' ? null : value; + } + + getDestinationNames(selectedType) { + this.destinationNames = []; + this.selectedDestinationName = null; + this.af.destination = selectedType.name === 'Select Destination Type' ? '' : selectedType.name; + switch (selectedType.name) { + case 'Broadcast': + this.selectedDestinationName = null; + break; + case 'Service': + this.getServiceNames(); + break; + case 'Asset': + this.getAssetNames(); + break; + case 'Script': + this.getScriptNames(); + break; + default: + break; } - - getServiceNames() { - let names = []; - /** request started */ - this.ngProgress.start(); - this.schedulesService.getSchedules(). - subscribe( - (data: any) => { - /** request completed */ - this.ngProgress.done(); - data.schedules.forEach(sch => { - if (this.af.destination === 'Service') { - if (['STARTUP'].includes(sch.type) && ['south_c', 'north_C'].includes(sch.processName)) { - if (sch.processName === 'south_c') { - sch.groupbyType = 'Southbound'; - } - if (sch.processName === 'north_C') { - sch.groupbyType = 'Northbound'; - } - names.push(sch); - } - } else { - if (!['STARTUP'].includes(sch.type)) { - names.push(sch); - } + } + + getServiceNames() { + let names = []; + /** request started */ + this.ngProgress.start(); + this.schedulesService.getSchedules(). + subscribe( + (data: any) => { + /** request completed */ + this.ngProgress.done(); + data.schedules.forEach(sch => { + if (this.af.destination === 'Service') { + if (['STARTUP'].includes(sch.type) && ['south_c', 'north_C'].includes(sch.processName)) { + if (sch.processName === 'south_c') { + sch.groupbyType = 'Southbound'; } - }); - let southboundSvc = []; - let northboundSvc = []; - names.forEach(svc => { - if (svc.processName === 'south_c') { - southboundSvc.push(svc); - } else { - northboundSvc.push(svc); + if (sch.processName === 'north_C') { + sch.groupbyType = 'Northbound'; } - }) - const SortedSouthboundSvc = southboundSvc.sort((a, b) => a.name.localeCompare(b.name)); - const SortedNorthboundSvc = northboundSvc.sort((a, b) => a.name.localeCompare(b.name)); - this.destinationNames = SortedSouthboundSvc.concat(SortedNorthboundSvc); - }, - error => { - /** request completed */ - this.ngProgress.done(); - if (error.status === 0) { - console.log('service down ', error); - } else { - this.alertService.error(error.statusText); + names.push(sch); } - }); - } - - getAssetNames() { - let nameList = []; - /** request started */ - this.ngProgress.start(); - this.assetService.getAsset() - .subscribe( - (data: any[]) => { - /** request completed */ - this.ngProgress.done(); - data.forEach(asset => { - asset['name'] = asset.assetCode; - nameList.push(asset); - }); - this.destinationNames = nameList.sort((a, b) => a.name.localeCompare(b.name)); - }, - error => { - /** request completed but error */ - this.ngProgress.done(); - if (error.status === 0) { - console.log('service down ', error); - } else { - this.alertService.error(error.statusText); + } else { + if (!['STARTUP'].includes(sch.type)) { + names.push(sch); } - }); - } - - getScriptNames() { - /** request started */ - this.ngProgress.start(); - this.controlService.fetchControlServiceScripts() - .subscribe((data: any) => { - this.ngProgress.done(); - this.destinationNames = data.scripts.sort((a, b) => a.name.localeCompare(b.name)); - }, error => { - /** request completed */ - this.ngProgress.done(); - if (error.status === 0) { - console.log('service down ', error); + } + }); + let southboundSvc = []; + let northboundSvc = []; + names.forEach(svc => { + if (svc.processName === 'south_c') { + southboundSvc.push(svc); } else { - this.alertService.error(error.statusText); + northboundSvc.push(svc); } + }) + const SortedSouthboundSvc = southboundSvc.sort((a, b) => a.name.localeCompare(b.name)); + const SortedNorthboundSvc = northboundSvc.sort((a, b) => a.name.localeCompare(b.name)); + this.destinationNames = SortedSouthboundSvc.concat(SortedNorthboundSvc); + }, + error => { + /** request completed */ + this.ngProgress.done(); + if (error.status === 0) { + console.log('service down ', error); + } else { + this.alertService.error(error.statusText); + } + }); + } + + getAssetNames() { + let nameList = []; + /** request started */ + this.ngProgress.start(); + this.assetService.getAsset() + .subscribe( + (data: any[]) => { + /** request completed */ + this.ngProgress.done(); + data.forEach(asset => { + asset['name'] = asset.assetCode; + nameList.push(asset); }); - } - - addValueControl(controlType) { - const control = this.apiFlowForm.controls[controlType]; - this.addParameter({index: control.value.length, key: '', value: ''}, controlType); - } - - getUsers() { - this.ngProgress.start(); - this.userService.getAllUsers() - .subscribe( - (userData) => { - /** request completed */ - this.ngProgress.done(); - this.allUsers = userData['users'].map(user => { - return user.userName; - }); - }, - error => { - /** request completed */ - this.ngProgress.done(); - if (error.status === 0) { - console.log('service down ', error); - } else { - this.alertService.error(error.statusText); - } - }); - } - - selectAllowedUsers(usernames) { - this.af.allow = usernames; - } + this.destinationNames = nameList.sort((a, b) => a.name.localeCompare(b.name)); + }, + error => { + /** request completed but error */ + this.ngProgress.done(); + if (error.status === 0) { + console.log('service down ', error); + } else { + this.alertService.error(error.statusText); + } + }); + } + + getScriptNames() { + /** request started */ + this.ngProgress.start(); + this.controlService.fetchControlServiceScripts() + .subscribe((data: any) => { + this.ngProgress.done(); + this.destinationNames = data.scripts.sort((a, b) => a.name.localeCompare(b.name)); + }, error => { + /** request completed */ + this.ngProgress.done(); + if (error.status === 0) { + console.log('service down ', error); + } else { + this.alertService.error(error.statusText); + } + }); + } - openModal(id: string) { - this.reenableButton.emit(false); - this.dialogService.open(id); - } - - closeModal(id: string) { - this.reenableButton.emit(false); - this.dialogService.close(id); - } + addValueControl(controlType) { + const control = this.apiFlowForm.controls[controlType]; + this.addParameter({ index: control.value.length, key: '', value: '' }, controlType); + } - goToLink(urlSlug: string) { - this.docService.goToSetPointControlDocLink(urlSlug); - } -} \ No newline at end of file + getUsers() { + this.ngProgress.start(); + this.userService.getAllUsers() + .subscribe( + (userData) => { + /** request completed */ + this.ngProgress.done(); + this.allUsers = userData['users'].map(user => { + return user.userName; + }); + }, + error => { + /** request completed */ + this.ngProgress.done(); + if (error.status === 0) { + console.log('service down ', error); + } else { + this.alertService.error(error.statusText); + } + }); + } + + selectAllowedUsers(usernames) { + this.af.allow = usernames; + } + + openModal(id: string) { + this.reenableButton.emit(false); + this.dialogService.open(id); + } + + closeModal(id: string) { + this.reenableButton.emit(false); + this.dialogService.close(id); + } + + goToLink(urlSlug: string) { + this.docService.goToSetPointControlDocLink(urlSlug); + } +} diff --git a/src/app/components/core/control-dispatcher/control-dispatcher.module.ts b/src/app/components/core/control-dispatcher/control-dispatcher.module.ts index a7032c6d7..cb08ffbb1 100644 --- a/src/app/components/core/control-dispatcher/control-dispatcher.module.ts +++ b/src/app/components/core/control-dispatcher/control-dispatcher.module.ts @@ -45,11 +45,13 @@ const routes: Routes = [ { path: 'script/add', component: AddControlScriptComponent, - canActivate: [RolesGuard] + canActivate: [RolesGuard], + canDeactivate: [canDeactivateGuard] }, { path: 'script/:name/details', - component: AddControlScriptComponent + component: AddControlScriptComponent, + canDeactivate: [canDeactivateGuard] }, { path: 'acl', @@ -58,11 +60,13 @@ const routes: Routes = [ { path: 'acl/add', component: AddControlAclComponent, - canActivate: [RolesGuard] + canActivate: [RolesGuard], + canDeactivate: [canDeactivateGuard] }, { path: 'acl/:name/details', - component: AddControlAclComponent + component: AddControlAclComponent, + canDeactivate: [canDeactivateGuard] }, { path: 'task/add', @@ -95,11 +99,13 @@ const routes: Routes = [ { path: 'entry-points/add', component: AddEditAPIFlowComponent, - canActivate: [RolesGuard] + canActivate: [RolesGuard], + canDeactivate: [canDeactivateGuard] }, { path: 'entry-points/:name/details', - component: AddEditAPIFlowComponent + component: AddEditAPIFlowComponent, + canDeactivate: [canDeactivateGuard] } ]; diff --git a/src/app/components/core/control-dispatcher/pipelines/add-pipeline/add-control-pipeline.component.ts b/src/app/components/core/control-dispatcher/pipelines/add-pipeline/add-control-pipeline.component.ts index dc43ce9d6..dde59e7ae 100644 --- a/src/app/components/core/control-dispatcher/pipelines/add-pipeline/add-control-pipeline.component.ts +++ b/src/app/components/core/control-dispatcher/pipelines/add-pipeline/add-control-pipeline.component.ts @@ -98,7 +98,7 @@ export class AddControlPipelineComponent implements OnInit { } canDeactivate(): Observable | boolean { - return this.dialogService.confirm({ id: 'unsaved-changes-dialog', changeExist: this.unsavedChangesInFilterForm }); + return this.dialogService.confirm({ id: 'unsaved-changes-dialog', changeExist: this.pipelineForm.dirty || this.unsavedChangesInFilterForm }); } ngOnInit(): void { let callsStack = { diff --git a/src/app/components/core/north/add-task-wizard/add-task-wizard.component.html b/src/app/components/core/north/add-task-wizard/add-task-wizard.component.html index db0a0b628..c3aef5f6c 100644 --- a/src/app/components/core/north/add-task-wizard/add-task-wizard.component.html +++ b/src/app/components/core/north/add-task-wizard/add-task-wizard.component.html @@ -21,7 +21,8 @@
- @@ -83,8 +84,9 @@
- + *North instance name is required. @@ -109,7 +111,8 @@
@@ -145,7 +148,7 @@ (changedConfigEvent)="getChangedConfig($event)" [from]="'add-task-form'" (formStatusEvent)="validConfigurationForm = $event">
-
+
@@ -172,9 +175,13 @@
+ [disabled]="taskForm.invalid || !validConfigurationForm" + [appDisableUntilResponse]="reenableButton">Next
-
\ No newline at end of file +
+ + + diff --git a/src/app/components/core/north/add-task-wizard/add-task-wizard.component.ts b/src/app/components/core/north/add-task-wizard/add-task-wizard.component.ts index c9ae56112..62296f3a3 100644 --- a/src/app/components/core/north/add-task-wizard/add-task-wizard.component.ts +++ b/src/app/components/core/north/add-task-wizard/add-task-wizard.component.ts @@ -2,7 +2,7 @@ import { Component, Input, OnInit, ViewChild, OnDestroy, ChangeDetectorRef, Even import { UntypedFormControl, UntypedFormGroup, Validators } from '@angular/forms'; import { ActivatedRoute, Router } from '@angular/router'; import { cloneDeep, sortBy } from 'lodash'; -import { Subscription } from 'rxjs'; +import { Observable, Subscription } from 'rxjs'; import { AlertService, SchedulesService, SharedService, PluginService, ProgressBarService, @@ -12,6 +12,7 @@ import Utils, { QUOTATION_VALIDATION_PATTERN } from '../../../../utils'; import { ViewLogsComponent } from '../../logs/packages-log/view-logs/view-logs.component'; import { DocService } from '../../../../services/doc.service'; import { CustomValidator } from '../../../../directives/custom-validator'; +import { DialogService } from '../../../common/confirmation-dialog/dialog.service'; @Component({ selector: 'app-add-task-wizard', @@ -68,7 +69,8 @@ export class AddTaskWizardComponent implements OnInit, OnDestroy { private docService: DocService, private fileUploaderService: FileUploaderService, private configurationControlService: ConfigurationControlService, - private cdRef: ChangeDetectorRef + private cdRef: ChangeDetectorRef, + private dialogService: DialogService ) { this.route.queryParams.subscribe(params => { if (params['source']) { @@ -77,6 +79,10 @@ export class AddTaskWizardComponent implements OnInit, OnDestroy { }); } + canDeactivate(): Observable | boolean { + return this.dialogService.confirm({ id: 'unsaved-changes-dialog', changeExist: this.taskForm.dirty }); + } + ngOnInit() { this.getSchedules(); this.taskForm.get('repeatDays').setValue('0'); diff --git a/src/app/components/core/north/north-task-modal/north-task-modal.component.html b/src/app/components/core/north/north-task-modal/north-task-modal.component.html index 82b4e1d3c..9f484aca1 100644 --- a/src/app/components/core/north/north-task-modal/north-task-modal.component.html +++ b/src/app/components/core/north/north-task-modal/north-task-modal.component.html @@ -4,7 +4,8 @@
@@ -176,6 +178,10 @@
- +
- \ No newline at end of file + + + + diff --git a/src/app/components/core/north/north-task-modal/north-task-modal.component.ts b/src/app/components/core/north/north-task-modal/north-task-modal.component.ts index f42571a57..20fe4538c 100644 --- a/src/app/components/core/north/north-task-modal/north-task-modal.component.ts +++ b/src/app/components/core/north/north-task-modal/north-task-modal.component.ts @@ -18,7 +18,7 @@ import Utils from '../../../../utils'; import { DialogService } from '../../../common/confirmation-dialog/dialog.service'; import { FilterAlertComponent } from '../../filter/filter-alert/filter-alert.component'; import { ConfigurationGroupComponent } from '../../configuration-manager/configuration-group/configuration-group.component'; -import { Subject, forkJoin, of } from 'rxjs'; +import { Observable, Subject, forkJoin, of } from 'rxjs'; import { catchError, map, takeUntil } from 'rxjs/operators'; import { NorthTask } from '../north-task'; import { FilterListComponent } from '../../filter/filter-list/filter-list.component'; @@ -94,7 +94,7 @@ export class NorthTaskModalComponent implements OnInit, OnChanges { this.getNorthTasks(true) } }) - } + } @HostListener('document:keydown.escape', ['$event']) onKeydownHandler() { const alertModal = document.getElementById('modal-box'); @@ -103,6 +103,11 @@ export class NorthTaskModalComponent implements OnInit, OnChanges { } } + canDeactivate(): Observable | boolean { + return this.dialogService.confirm({ id: 'unsaved-changes-dialog', changeExist: !isEmpty(this.changedConfig) }); + } + + ngOnInit() { } ngOnChanges(changes: SimpleChanges) { @@ -496,11 +501,11 @@ export class NorthTaskModalComponent implements OnInit, OnChanges { return noChange; } - navToNorthPage(){ + navToNorthPage() { this.router.navigate(['/north']); } - getNorthTasks(caching: boolean){ + getNorthTasks(caching: boolean) { this.northService.getNorthTasks(caching) .pipe(takeUntil(this.destroy$)) .subscribe( diff --git a/src/app/components/core/north/north.module.ts b/src/app/components/core/north/north.module.ts index 28e938665..71c0e052a 100644 --- a/src/app/components/core/north/north.module.ts +++ b/src/app/components/core/north/north.module.ts @@ -14,6 +14,7 @@ import { NorthTaskModalComponent } from './north-task-modal/north-task-modal.com import { NorthComponent } from './north.component'; import { FilterModule } from '../filter/filter.module'; import { DragDropModule } from '@angular/cdk/drag-drop'; +import { canDeactivateGuard } from '../../../guards/can-deactivate/can-deactivate.guard'; const routes: Routes = [ { @@ -23,11 +24,13 @@ const routes: Routes = [ { path: 'add', component: AddTaskWizardComponent, - canActivate: [RolesGuard] + canActivate: [RolesGuard], + canDeactivate: [canDeactivateGuard] }, { path: ':name/details', - component: NorthTaskModalComponent + component: NorthTaskModalComponent, + canDeactivate: [canDeactivateGuard] } ]; diff --git a/src/app/components/core/scheduler/scheduler.module.ts b/src/app/components/core/scheduler/scheduler.module.ts index 9aee0b742..9481986a8 100644 --- a/src/app/components/core/scheduler/scheduler.module.ts +++ b/src/app/components/core/scheduler/scheduler.module.ts @@ -11,6 +11,7 @@ import { ListSchedulesComponent } from './list-schedules/list-schedules.componen import { UpdateScheduleComponent } from './update-schedule/update-schedule.component'; import { NgSelectModule } from '@ng-select/ng-select'; import { ScheduleTypeResolver } from './update-schedule/schedule-type.resolver'; +import { canDeactivateGuard } from '../../../guards/can-deactivate/can-deactivate.guard'; const routes: Routes = [ { @@ -23,7 +24,8 @@ const routes: Routes = [ component: UpdateScheduleComponent, resolve: { data: ScheduleTypeResolver - } + }, + canDeactivate: [canDeactivateGuard] } ]; diff --git a/src/app/components/core/scheduler/update-schedule/update-schedule.component.html b/src/app/components/core/scheduler/update-schedule/update-schedule.component.html index 30c7cb03f..66db327a4 100644 --- a/src/app/components/core/scheduler/update-schedule/update-schedule.component.html +++ b/src/app/components/core/scheduler/update-schedule/update-schedule.component.html @@ -241,8 +241,10 @@
+ [disabled]="form?.invalid || (!form.dirty && form.pristine)" (click)="form?.valid && updateSchedule()" + [appDisableUntilResponse]="reenableButton">Save
-
\ No newline at end of file +
+ + diff --git a/src/app/components/core/scheduler/update-schedule/update-schedule.component.ts b/src/app/components/core/scheduler/update-schedule/update-schedule.component.ts index 7204e98e6..e686e7e94 100644 --- a/src/app/components/core/scheduler/update-schedule/update-schedule.component.ts +++ b/src/app/components/core/scheduler/update-schedule/update-schedule.component.ts @@ -7,6 +7,8 @@ import Utils, { QUOTATION_VALIDATION_PATTERN, weekDays } from '../../../../utils import { cloneDeep, isEmpty } from 'lodash'; import { Schedule } from '../schedule'; import { ActivatedRoute, Router } from '@angular/router'; +import { Observable } from 'rxjs'; +import { DialogService } from '../../../common/confirmation-dialog/dialog.service'; @Component({ selector: 'app-update-schedule', @@ -32,6 +34,7 @@ export class UpdateScheduleComponent implements OnInit { public router: Router, private schedulesService: SchedulesService, public fb: UntypedFormBuilder, + public unsavedChangesService: DialogService, private alertService: AlertService, public rolesService: RolesService) { this.form = this.fb.group({ @@ -60,6 +63,10 @@ export class UpdateScheduleComponent implements OnInit { }); } + canDeactivate(): Observable | boolean { + return this.unsavedChangesService.confirm({ id: 'unsaved-changes-dialog', changeExist: this.form.dirty }); + } + ngOnInit() { } public getWeekDays() { @@ -78,11 +85,11 @@ export class UpdateScheduleComponent implements OnInit { if (type.name == 'TIMED') { const time = Utils.convertTimeToSec(this.form.get('time').value); - // Set time control value when type is TIMED + // Set time control value when type is TIMED if (time == 0) { this.form.controls['time'].patchValue('00:00:01') } } - // Enable repeat & time control + // Enable repeat & time control this.form.controls['time'].enable(); this.form.controls['day'].enable(); this.form.controls['repeat'].enable(); @@ -130,7 +137,7 @@ export class UpdateScheduleComponent implements OnInit { const day = this.days.find(day => day.index == index); this.form.controls['day'].patchValue(day); this.form.controls['day'].updateValueAndValidity(); - // set default time + // set default time this.form.controls['time'].patchValue('00:00:01'); this.form.controls['time'].updateValueAndValidity(); return day; diff --git a/src/app/components/core/south/add-service-wizard/add-service-wizard.component.html b/src/app/components/core/south/add-service-wizard/add-service-wizard.component.html index f8586286d..d69af80ce 100644 --- a/src/app/components/core/south/add-service-wizard/add-service-wizard.component.html +++ b/src/app/components/core/south/add-service-wizard/add-service-wizard.component.html @@ -21,7 +21,8 @@
- @@ -85,7 +86,8 @@
+ formControlName="name" title="No single quotes and double quotes!" + [pattern]="QUOTATION_VALIDATION_PATTERN"> Service name is required @@ -99,7 +101,7 @@ (changedConfigEvent)="getChangedConfig($event)" [from]="'add-service-form'" (formStatusEvent)="validConfigurationForm = $event">
-
+
@@ -126,9 +128,13 @@
+ [disabled]="serviceForm.invalid || !validConfigurationForm" + [appDisableUntilResponse]="reenableButton">Next
- \ No newline at end of file + + + + diff --git a/src/app/components/core/south/add-service-wizard/add-service-wizard.component.ts b/src/app/components/core/south/add-service-wizard/add-service-wizard.component.ts index 9d2e0f787..e6f0fe956 100644 --- a/src/app/components/core/south/add-service-wizard/add-service-wizard.component.ts +++ b/src/app/components/core/south/add-service-wizard/add-service-wizard.component.ts @@ -1,7 +1,7 @@ import { Component, Input, OnInit, ViewChild, OnDestroy, ChangeDetectorRef, EventEmitter } from '@angular/core'; import { UntypedFormBuilder, UntypedFormControl, UntypedFormGroup, Validators } from '@angular/forms'; import { ActivatedRoute, Router } from '@angular/router'; -import { Subscription } from 'rxjs'; +import { Observable, Subscription } from 'rxjs'; import { cloneDeep, sortBy } from 'lodash'; import { @@ -13,6 +13,7 @@ import { ViewLogsComponent } from '../../logs/packages-log/view-logs/view-logs.c import { DocService } from '../../../../services/doc.service'; import { CustomValidator } from '../../../../directives/custom-validator'; import { QUOTATION_VALIDATION_PATTERN } from '../../../../utils'; +import { DialogService } from '../../../common/confirmation-dialog/dialog.service'; @Component({ selector: 'app-add-service-wizard', @@ -61,7 +62,8 @@ export class AddServiceWizardComponent implements OnInit, OnDestroy { private docService: DocService, private configurationControlService: ConfigurationControlService, private fileUploaderService: FileUploaderService, - private cdRef: ChangeDetectorRef + private cdRef: ChangeDetectorRef, + private dialogService: DialogService ) { this.route.queryParams.subscribe(params => { if (params['source']) { @@ -70,6 +72,10 @@ export class AddServiceWizardComponent implements OnInit, OnDestroy { }); } + canDeactivate(): Observable | boolean { + return this.dialogService.confirm({ id: 'unsaved-changes-dialog', changeExist: this.serviceForm.dirty }); + } + ngOnInit() { this.getSchedules(); this.serviceForm = this.formBuilder.group({ diff --git a/src/app/components/core/south/south-service-modal/south-service-modal.component.html b/src/app/components/core/south/south-service-modal/south-service-modal.component.html index 593b0919e..679325d79 100644 --- a/src/app/components/core/south/south-service-modal/south-service-modal.component.html +++ b/src/app/components/core/south/south-service-modal/south-service-modal.component.html @@ -133,4 +133,7 @@ - \ No newline at end of file + + + + diff --git a/src/app/components/core/south/south-service-modal/south-service-modal.component.ts b/src/app/components/core/south/south-service-modal/south-service-modal.component.ts index 791bfc2a5..056c853d6 100644 --- a/src/app/components/core/south/south-service-modal/south-service-modal.component.ts +++ b/src/app/components/core/south/south-service-modal/south-service-modal.component.ts @@ -22,7 +22,7 @@ import { MAX_INT_SIZE } from '../../../../utils'; import { DialogService } from '../../../common/confirmation-dialog/dialog.service'; import { FilterAlertComponent } from '../../filter/filter-alert/filter-alert.component'; import { ConfigurationGroupComponent } from '../../configuration-manager/configuration-group/configuration-group.component'; -import { Subject, forkJoin, of } from 'rxjs'; +import { Observable, Subject, forkJoin, of } from 'rxjs'; import { catchError, map, takeUntil } from 'rxjs/operators'; import { Service } from '../south-service'; import { FilterListComponent } from '../../filter/filter-list/filter-list.component'; @@ -107,6 +107,10 @@ export class SouthServiceModalComponent implements OnInit { } } + canDeactivate(): Observable | boolean { + return this.dialogService.confirm({ id: 'unsaved-changes-dialog', changeExist: !isEmpty(this.changedConfig) }); + } + ngOnInit() { } public getSouthboundServices(caching: boolean) { diff --git a/src/app/components/core/south/south.module.ts b/src/app/components/core/south/south.module.ts index 603d5a09e..80a05940d 100644 --- a/src/app/components/core/south/south.module.ts +++ b/src/app/components/core/south/south.module.ts @@ -13,6 +13,7 @@ import { AddServiceWizardComponent } from './add-service-wizard/add-service-wiza import { SouthServiceModalComponent } from './south-service-modal/south-service-modal.component'; import { SouthComponent } from './south.component'; import { FlowEditorModule } from '../../common/node-editor/flow-editor.module'; +import { canDeactivateGuard } from '../../../guards/can-deactivate/can-deactivate.guard'; const routes: Routes = [ { @@ -22,11 +23,13 @@ const routes: Routes = [ { path: 'add', component: AddServiceWizardComponent, - canActivate: [RolesGuard] + canActivate: [RolesGuard], + canDeactivate: [canDeactivateGuard] }, { path: ':name/details', - component: SouthServiceModalComponent + component: SouthServiceModalComponent, + canDeactivate: [canDeactivateGuard] }, ]; diff --git a/src/app/shared.module.ts b/src/app/shared.module.ts index 1146f82a4..31bf8db71 100644 --- a/src/app/shared.module.ts +++ b/src/app/shared.module.ts @@ -24,6 +24,7 @@ import { ServiceConfigComponent } from './components/core/notifications/service- import { ListTypeConfigurationComponent } from './components/core/configuration-manager/list-type-configuration/list-type-configuration.component'; import { KvListTypeConfigurationComponent } from './components/core/configuration-manager/kv-list-type-configuration/kv-list-type-configuration.component'; +import { UnsavedChangesDialogComponent } from './components/common/unsaved-changes-dialog/unsaved-changes-dialog.component'; @NgModule({ imports: [ @@ -51,6 +52,7 @@ import { KvListTypeConfigurationComponent } from './components/core/configuratio AddServiceWizardComponent, AddTaskWizardComponent, TaskScheduleComponent, + UnsavedChangesDialogComponent, NotificationServiceWarningComponent, ServiceConfigComponent ], @@ -67,6 +69,7 @@ import { KvListTypeConfigurationComponent } from './components/core/configuratio AddServiceWizardComponent, AddTaskWizardComponent, TaskScheduleComponent, + UnsavedChangesDialogComponent, NotificationServiceWarningComponent, ServiceConfigComponent ]