fix: Manage hooks functionality; Create hook, Edit Hook (#2346)

This commit is contained in:
Pranav Deshmukh
2025-03-23 10:58:35 -06:00
committed by GitHub
parent a218d3491b
commit 684a937af0
5 changed files with 95 additions and 16 deletions
@@ -33,7 +33,7 @@
</div> </div>
<div fxLayout="row wrap" fxLayout.lt-md="column" fxLayoutGap="4%"> <div fxLayout="row wrap" fxLayout.lt-md="column" fxLayoutGap="4%">
<mat-form-field fxFlex="48%" *ngIf="hookForm.controls.name.value === 'Web'"> <mat-form-field fxFlex="40%" *ngIf="hookForm.controls.name.value === 'Web'">
<mat-label>{{ 'labels.inputs.Content Type' | translate }}</mat-label> <mat-label>{{ 'labels.inputs.Content Type' | translate }}</mat-label>
<mat-select required formControlName="contentType"> <mat-select required formControlName="contentType">
<mat-option [value]="'json'"> <mat-option [value]="'json'">
@@ -49,7 +49,7 @@
</mat-error> </mat-error>
</mat-form-field> </mat-form-field>
<mat-form-field fxFlex="48%" *ngIf="hookForm.controls.name.value === 'SMS Bridge'"> <mat-form-field fxFlex="40%" *ngIf="hookForm.controls.name.value === 'SMS Bridge'">
<mat-label>{{ 'labels.inputs.Phone Number' | translate }}</mat-label> <mat-label>{{ 'labels.inputs.Phone Number' | translate }}</mat-label>
<input matInput type="tel" #input maxlength="10" required formControlName="phoneNumber" /> <input matInput type="tel" #input maxlength="10" required formControlName="phoneNumber" />
<mat-hint align="end">{{ input.value?.length || 0 }}/10</mat-hint> <mat-hint align="end">{{ input.value?.length || 0 }}/10</mat-hint>
@@ -59,7 +59,7 @@
</mat-error> </mat-error>
</mat-form-field> </mat-form-field>
<mat-form-field fxFlex="48%"> <mat-form-field fxFlex="40%">
<mat-label>{{ 'labels.inputs.Payload URL' | translate }}</mat-label> <mat-label>{{ 'labels.inputs.Payload URL' | translate }}</mat-label>
<input matInput required formControlName="payloadUrl" /> <input matInput required formControlName="payloadUrl" />
<mat-error *ngIf="hookForm.controls.payloadUrl.hasError('required')"> <mat-error *ngIf="hookForm.controls.payloadUrl.hasError('required')">
@@ -105,14 +105,23 @@
<br /> <br />
<mat-divider [inset]="true"></mat-divider> <!-- <mat-divider [inset]="true"></mat-divider> -->
<br /> <br />
<div fxLayout="row wrap" fxLayoutGap="60%" fxLayout.lt-md="column"> <div fxLayout="row wrap" fxLayout.lt-md="column">
<p fxFlex="20%" class="mat-title">{{ 'labels.inputs.Events' | translate }}</p> <p fxFlex="20%" class="mat-title">
{{ 'labels.inputs.Events' | translate }}<span style="color: red">*</span>
</p>
<button mat-raised-button fxFlex="20%" type="button" color="primary" (click)="addEvent()"> <button
mat-raised-button
class="AddEventButton"
fxFlex="20%"
type="button"
color="primary"
(click)="addEvent()"
>
<fa-icon icon="plus" class="m-r-10"></fa-icon> <fa-icon icon="plus" class="m-r-10"></fa-icon>
{{ 'labels.buttons.Add' | translate }} {{ 'labels.inputs.Events' | translate }} {{ 'labels.buttons.Add' | translate }} {{ 'labels.inputs.Events' | translate }}
</button> </button>
@@ -11,6 +11,14 @@
} }
} }
mat-divider {
margin: 0 0 0.5em;
}
table { table {
width: 100%; width: 100%;
} }
.AddEventButton {
margin-bottom: 10px;
}
@@ -33,7 +33,7 @@
</div> </div>
<div fxLayout="row wrap" fxLayout.lt-md="column" fxLayoutGap="4%"> <div fxLayout="row wrap" fxLayout.lt-md="column" fxLayoutGap="4%">
<mat-form-field fxFlex="48%" *ngIf="hookForm.controls.name.value === 'Web'"> <mat-form-field fxFlex="40%" *ngIf="hookForm.controls.name.value === 'Web'">
<mat-label>{{ 'labels.inputs.Content Type' | translate }}</mat-label> <mat-label>{{ 'labels.inputs.Content Type' | translate }}</mat-label>
<mat-select required formControlName="contentType"> <mat-select required formControlName="contentType">
<mat-option [value]="'json'"> <mat-option [value]="'json'">
@@ -49,7 +49,7 @@
</mat-error> </mat-error>
</mat-form-field> </mat-form-field>
<mat-form-field fxFlex="48%" *ngIf="hookForm.controls.name.value === 'SMS Bridge'"> <mat-form-field fxFlex="40%" *ngIf="hookForm.controls.name.value === 'SMS Bridge'">
<mat-label>{{ 'labels.inputs.Phone Number' | translate }}</mat-label> <mat-label>{{ 'labels.inputs.Phone Number' | translate }}</mat-label>
<input matInput type="tel" #input maxlength="10" required formControlName="phoneNumber" /> <input matInput type="tel" #input maxlength="10" required formControlName="phoneNumber" />
<mat-hint align="end">{{ input.value?.length || 0 }}/10</mat-hint> <mat-hint align="end">{{ input.value?.length || 0 }}/10</mat-hint>
@@ -59,7 +59,7 @@
</mat-error> </mat-error>
</mat-form-field> </mat-form-field>
<mat-form-field fxFlex="48%"> <mat-form-field fxFlex="40%">
<mat-label>{{ 'labels.inputs.Payload URL' | translate }}</mat-label> <mat-label>{{ 'labels.inputs.Payload URL' | translate }}</mat-label>
<input matInput required formControlName="payloadUrl" /> <input matInput required formControlName="payloadUrl" />
<mat-error *ngIf="hookForm.controls.payloadUrl.hasError('required')"> <mat-error *ngIf="hookForm.controls.payloadUrl.hasError('required')">
@@ -109,10 +109,19 @@
<br /> <br />
<div fxLayout="row wrap" fxLayoutGap="60%" fxLayout.lt-md="column"> <div fxLayout="row wrap" fxLayout.lt-md="column">
<p fxFlex="20%" class="mat-title">{{ 'labels.inputs.Events' | translate }}</p> <p fxFlex="20%" class="mat-title">
{{ 'labels.inputs.Events' | translate }} <span style="color: red">*</span>
</p>
<button mat-raised-button fxFlex="20%" type="button" color="primary" (click)="addEvent()"> <button
mat-raised-button
class="AddEventButton"
fxFlex="20%"
type="button"
color="primary"
(click)="addEvent()"
>
<fa-icon icon="plus" class="m-r-10"></fa-icon> <fa-icon icon="plus" class="m-r-10"></fa-icon>
{{ 'labels.buttons.Add' | translate }} {{ 'labels.inputs.Events' | translate }} {{ 'labels.buttons.Add' | translate }} {{ 'labels.inputs.Events' | translate }}
</button> </button>
@@ -131,6 +140,10 @@
<td mat-cell *matCellDef="let event">{{ event.actionName }}</td> <td mat-cell *matCellDef="let event">{{ event.actionName }}</td>
</ng-container> </ng-container>
<div *ngIf="cannotDeleteLastEvent" class="error-message">
<p>At least one event is required. Cannot delete the last event.</p>
</div>
<ng-container matColumnDef="actions"> <ng-container matColumnDef="actions">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Actions' | translate }}</th> <th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Actions' | translate }}</th>
<td mat-cell *matCellDef="let i = index"> <td mat-cell *matCellDef="let i = index">
@@ -146,14 +159,16 @@
</mat-card-content> </mat-card-content>
<mat-card-actions fxLayout="row" fxLayout.xs="column" fxLayoutAlign="center" fxLayoutGap="5px"> <mat-card-actions fxLayout="row" fxLayout.xs="column" fxLayoutAlign="center" fxLayoutGap="5px">
<button type="button" mat-raised-button [routerLink]="['../']">{{ 'labels.inputs.Cancel' | translate }}</button> <button type="button" mat-raised-button [routerLink]="['../']">
{{ 'labels.buttons.Cancel' | translate }}
</button>
<button <button
mat-raised-button mat-raised-button
color="primary" color="primary"
[disabled]="(!hookForm.valid || hookForm.pristine) && !eventsDataChanged" [disabled]="(!hookForm.valid || hookForm.pristine) && !eventsDataChanged"
*mifosxHasPermission="'UPDATE_HOOK'" *mifosxHasPermission="'UPDATE_HOOK'"
> >
{{ 'labels.inputs.Submit' | translate }} {{ 'labels.buttons.Submit' | translate }}
</button> </button>
</mat-card-actions> </mat-card-actions>
</form> </form>
@@ -14,3 +14,26 @@
table { table {
width: 100%; width: 100%;
} }
.AddEventButton {
margin-bottom: 10px;
}
.error-message {
color: red;
font-weight: bold;
margin-top: 10px;
padding: 5px;
background-color: #ffe6e6;
border: 1px solid red;
border-radius: 5px;
}
.error-snackbar {
background-color: #f44336;
color: white;
}
.error-snackbar .mat-simple-snackbar-action {
color: white;
}
@@ -5,6 +5,11 @@ import { MatDialog } from '@angular/material/dialog';
import { MatSort } from '@angular/material/sort'; import { MatSort } from '@angular/material/sort';
import { MatTableDataSource } from '@angular/material/table'; import { MatTableDataSource } from '@angular/material/table';
import { ActivatedRoute, Router } from '@angular/router'; import { ActivatedRoute, Router } from '@angular/router';
import { MatSnackBarModule } from '@angular/material/snack-bar';
import { NgModule } from '@angular/core';
import { MatSnackBar } from '@angular/material/snack-bar';
import { ChangeDetectorRef } from '@angular/core';
/** Custom Services */ /** Custom Services */
import { SystemService } from '../../system.service'; import { SystemService } from '../../system.service';
@@ -17,12 +22,18 @@ import { AddEventDialogComponent } from '../add-event-dialog/add-event-dialog.co
/** /**
* Edit Hook Component. * Edit Hook Component.
*/ */
@Component({ @Component({
selector: 'mifosx-edit-hook', selector: 'mifosx-edit-hook',
templateUrl: './edit-hook.component.html', templateUrl: './edit-hook.component.html',
styleUrls: ['./edit-hook.component.scss'] styleUrls: ['./edit-hook.component.scss']
}) })
export class EditHookComponent implements OnInit { export class EditHookComponent implements OnInit {
@NgModule({
imports: [
MatSnackBarModule
]
})
/** Hooks Template Data. */ /** Hooks Template Data. */
hooksTemplateData: any; hooksTemplateData: any;
/** Hook Data. */ /** Hook Data. */
@@ -39,6 +50,7 @@ export class EditHookComponent implements OnInit {
dataSource: MatTableDataSource<any>; dataSource: MatTableDataSource<any>;
/** Events Data. */ /** Events Data. */
eventsData: any[] = []; eventsData: any[] = [];
cannotDeleteLastEvent: boolean = false;
/** Boolean to check if events data is changed or not. */ /** Boolean to check if events data is changed or not. */
eventsDataChanged: Boolean = false; eventsDataChanged: Boolean = false;
/** Sorter for events table. */ /** Sorter for events table. */
@@ -59,7 +71,9 @@ export class EditHookComponent implements OnInit {
private router: Router, private router: Router,
private formBuilder: UntypedFormBuilder, private formBuilder: UntypedFormBuilder,
private dialog: MatDialog, private dialog: MatDialog,
private translateService: TranslateService private translateService: TranslateService,
private snackBar: MatSnackBar,
private cdr: ChangeDetectorRef
) { ) {
this.route.data.subscribe((data: { hooksTemplate: any; hook: any }) => { this.route.data.subscribe((data: { hooksTemplate: any; hook: any }) => {
this.hooksTemplateData = data.hooksTemplate; this.hooksTemplateData = data.hooksTemplate;
@@ -169,6 +183,14 @@ export class EditHookComponent implements OnInit {
* @param {number} index Array index from where event form needs to be removed. * @param {number} index Array index from where event form needs to be removed.
*/ */
deleteEvent(index: number) { deleteEvent(index: number) {
if (this.eventsData.length === 1) {
this.snackBar.open('At least one event is required. Cannot delete the last event.', 'Close', {
duration: 3000,
panelClass: ['error-snackbar']
});
return;
}
const deleteEventDialogRef = this.dialog.open(DeleteDialogComponent, { const deleteEventDialogRef = this.dialog.open(DeleteDialogComponent, {
data: { data: {
deleteContext: deleteContext:
@@ -177,11 +199,13 @@ export class EditHookComponent implements OnInit {
this.eventsData[index].entityName this.eventsData[index].entityName
} }
}); });
deleteEventDialogRef.afterClosed().subscribe((response: any) => { deleteEventDialogRef.afterClosed().subscribe((response: any) => {
if (response.delete) { if (response.delete) {
this.eventsData.splice(index, 1); this.eventsData.splice(index, 1);
this.dataSource.connect().next(this.eventsData); this.dataSource.connect().next(this.eventsData);
this.eventsDataChanged = true; this.eventsDataChanged = true;
this.cdr.detectChanges();
} }
}); });
} }