custom headers / params

This commit is contained in:
shamoon 2024-11-02 21:42:16 -07:00
parent 76672b0760
commit 558a0296a4
No known key found for this signature in database
7 changed files with 143 additions and 4 deletions

View File

@ -131,6 +131,7 @@ import { GlobalSearchComponent } from './components/app-frame/global-search/glob
import { HotkeyDialogComponent } from './components/common/hotkey-dialog/hotkey-dialog.component'
import { DeletePagesConfirmDialogComponent } from './components/common/confirm-dialog/delete-pages-confirm-dialog/delete-pages-confirm-dialog.component'
import { TrashComponent } from './components/admin/trash/trash.component'
import { EntriesComponent } from './components/common/input/entries/entries.component'
import {
airplane,
archive,
@ -522,6 +523,7 @@ function initializeApp(settings: SettingsService) {
HotkeyDialogComponent,
DeletePagesConfirmDialogComponent,
TrashComponent,
EntriesComponent,
],
bootstrap: [AppComponent],
imports: [

View File

@ -336,8 +336,8 @@
<div class="row">
<div class="col">
<pngx-input-text i18n-title title="Webhook url" formControlName="webhook_url" [error]="error?.actions?.[i]?.webhook_url"></pngx-input-text>
<pngx-input-text i18n-title title="Webhook params" formControlName="webhook_params" [error]="error?.actions?.[i]?.webhook_params"></pngx-input-text>
<pngx-input-text i18n-title title="Webhook headers" formControlName="webhook_headers" [error]="error?.actions?.[i]?.webhook_headers"></pngx-input-text>
<pngx-input-entries i18n-title title="Webhook params" formControlName="webhook_params" [error]="error?.actions?.[i]?.webhook_params"></pngx-input-entries>
<pngx-input-entries i18n-title title="Webhook headers" formControlName="webhook_headers" [error]="error?.actions?.[i]?.webhook_headers"></pngx-input-entries>
<pngx-input-switch i18n-title title="Include document" formControlName="webhook_include_document"></pngx-input-switch>
</div>
</div>

View File

@ -0,0 +1,29 @@
<div class="mb-3" [class.pb-3]="error">
<div class="row">
<div class="d-flex align-items-center mb-2">
@if (title) {
<label class="form-label mb-0" [class.mb-md-0]="horizontal" [for]="inputId">{{title}}</label>
}
<button type="button" class="btn btn-sm btn-outline-primary ms-4" (click)="addEntry()">
<i-bs name="plus-circle"></i-bs>&nbsp;<ng-container i18n>Add</ng-container>
</button>
</div>
<div class="position-relative">
@for (entry of entries; let i = $index; track entry[0]) {
<div class="input-group mb-3">
<input type="text" class="form-control" [(ngModel)]="entry[0]" (change)="inputChange()" [disabled]="disabled" autocomplete="off">
<input type="text" class="form-control" [(ngModel)]="entry[1]" (change)="inputChange()" [disabled]="disabled" autocomplete="off">
<button type="button" class="btn btn-outline-secondary" (click)="removeEntry(i)">
<i-bs class="text-danger" name="trash"></i-bs>
</button>
</div>
}
@if (hint) {
<small class="form-text text-muted" [innerHTML]="hint | safeHtml"></small>
}
<div class="invalid-feedback position-absolute top-100">
{{error}}
</div>
</div>
</div>
</div>

View File

@ -0,0 +1,63 @@
import { ComponentFixture, TestBed } from '@angular/core/testing'
import {
FormsModule,
NG_VALUE_ACCESSOR,
ReactiveFormsModule,
} from '@angular/forms'
import { EntriesComponent } from './entries.component'
import { NgxBootstrapIconsModule, allIcons } from 'ngx-bootstrap-icons'
describe('EntriesComponent', () => {
let component: EntriesComponent
let fixture: ComponentFixture<EntriesComponent>
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [EntriesComponent],
imports: [
FormsModule,
ReactiveFormsModule,
NgxBootstrapIconsModule.pick(allIcons),
],
}).compileComponents()
})
beforeEach(() => {
fixture = TestBed.createComponent(EntriesComponent)
component = fixture.componentInstance
fixture.debugElement.injector.get(NG_VALUE_ACCESSOR)
fixture.detectChanges()
})
it('should add an entry', () => {
component.addEntry()
expect(component.entries.length).toBe(1)
expect(component.entries[0]).toEqual(['', ''])
})
it('should remove an entry', () => {
component.addEntry()
component.addEntry()
expect(component.entries.length).toBe(2)
component.removeEntry(0)
expect(component.entries.length).toBe(1)
})
it('should write value correctly', () => {
const newValue = { key1: 'value1', key2: 'value2' }
component.writeValue(newValue)
expect(component.entries).toEqual(Object.entries(newValue))
})
it('should correctly generate the value on input change', () => {
const onChangeSpy = jest.spyOn(component, 'onChange')
component.entries = [
['key1', 'value1'],
['key2', ''],
['', ''],
]
component.inputChange()
// Only the first two entries should be included
expect(onChangeSpy).toHaveBeenCalledWith({ key1: 'value1', key2: '' })
})
})

View File

@ -0,0 +1,45 @@
import { Component, forwardRef } from '@angular/core'
import { AbstractInputComponent } from '../abstract-input'
import { NG_VALUE_ACCESSOR } from '@angular/forms'
@Component({
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => EntriesComponent),
multi: true,
},
],
selector: 'pngx-input-entries',
templateUrl: './entries.component.html',
styleUrl: './entries.component.scss',
})
export class EntriesComponent extends AbstractInputComponent<object> {
entries = []
constructor() {
super()
}
inputChange(): void {
// Remove empty keys
this.onChange(
Object.fromEntries(this.entries.filter(([key]) => key?.length))
)
}
writeValue(newValue: any): void {
this.entries = Object.entries(newValue)
this.value = newValue
}
addEntry(): void {
this.entries.push(['', ''])
this.inputChange()
}
removeEntry(index: number): void {
this.entries.splice(index, 1)
this.inputChange()
}
}

View File

@ -75,9 +75,9 @@ export interface WorkflowAction extends ObjectWithId {
webhook_url?: string
webhook_params?: string
webhook_params?: object
webhook_headers?: string
webhook_headers?: object
webhook_include_document?: boolean
}