@gravitee/ui-policy-studio-angular 15.3.0 → 15.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,7 @@
1
1
  import { get, cloneDeep, uniqueId, capitalize, trim, isEmpty, flatten, uniq, toLower, isNil, has, filter, isEqual, differenceBy, omit, unionBy } from 'lodash';
2
2
  import * as i0 from '@angular/core';
3
3
  import { Component, Inject, EventEmitter, Input, Output, Injectable, Pipe, ChangeDetectionStrategy } from '@angular/core';
4
- import { BehaviorSubject, Subject, of, EMPTY, timer } from 'rxjs';
4
+ import { Subject, BehaviorSubject, of, EMPTY, timer } from 'rxjs';
5
5
  import * as i2 from '@angular/common';
6
6
  import { CommonModule } from '@angular/common';
7
7
  import * as i6$1 from '@gravitee/ui-particles-angular';
@@ -10,23 +10,23 @@ import * as i3$1 from '@angular/material/tooltip';
10
10
  import { MatTooltipModule, MatTooltip } from '@angular/material/tooltip';
11
11
  import * as i4 from '@angular/material/button';
12
12
  import { MatButtonModule } from '@angular/material/button';
13
- import { tap, map, catchError, takeUntil, startWith } from 'rxjs/operators';
14
- import * as i7$2 from '@angular/material/menu';
15
- import { MatMenuModule } from '@angular/material/menu';
16
13
  import * as i8 from '@angular/cdk/drag-drop';
17
14
  import { moveItemInArray, transferArrayItem, DragDropModule } from '@angular/cdk/drag-drop';
18
- import * as i1 from '@angular/material/dialog';
19
- import { MAT_DIALOG_DATA, MatDialogModule } from '@angular/material/dialog';
20
15
  import * as i3 from '@angular/forms';
21
16
  import { UntypedFormGroup, UntypedFormControl, ReactiveFormsModule, FormControl } from '@angular/forms';
22
17
  import * as i5 from '@angular/material/form-field';
23
18
  import { MatFormFieldModule } from '@angular/material/form-field';
19
+ import * as i7$1 from '@angular/material/input';
20
+ import { MatInputModule } from '@angular/material/input';
21
+ import * as i7$2 from '@angular/material/menu';
22
+ import { MatMenuModule } from '@angular/material/menu';
23
+ import { debounceTime, startWith, distinctUntilChanged, tap, takeUntil, map, catchError } from 'rxjs/operators';
24
+ import * as i1 from '@angular/material/dialog';
25
+ import { MAT_DIALOG_DATA, MatDialogModule } from '@angular/material/dialog';
24
26
  import * as i6 from '@angular/material/select';
25
27
  import { MatSelectModule } from '@angular/material/select';
26
- import * as i7$1 from '@angular/material/slide-toggle';
28
+ import * as i7 from '@angular/material/slide-toggle';
27
29
  import { MatSlideToggleModule } from '@angular/material/slide-toggle';
28
- import * as i7 from '@angular/material/input';
29
- import { MatInputModule } from '@angular/material/input';
30
30
  import * as i5$1 from '@angular/material/icon';
31
31
  import * as i3$2 from '@angular/material/tabs';
32
32
  import { MatTabsModule } from '@angular/material/tabs';
@@ -306,60 +306,34 @@ const toPolicy = (genericPolicy) => {
306
306
  * See the License for the specific language governing permissions and
307
307
  * limitations under the License.
308
308
  */
309
- class GioPolicyStudioFlowMessageFormDialogComponent {
309
+ class GioPolicyStudioFlowExecutionFormDialogComponent {
310
310
  constructor(dialogRef, flowDialogData) {
311
311
  this.dialogRef = dialogRef;
312
- this.entrypoints = [];
313
- this.mode = 'create';
314
- this.entrypoints = flowDialogData?.entrypoints ?? [];
315
- this.existingFlow = cloneDeep(flowDialogData?.flow);
316
- this.mode = this.existingFlow ? 'edit' : 'create';
317
- const channelSelector = flowDialogData?.flow?.selectors?.find(s => s.type === 'CHANNEL');
318
- const conditionSelector = flowDialogData?.flow?.selectors?.find(s => s.type === 'CONDITION');
319
- this.flowFormGroup = new UntypedFormGroup({
320
- name: new UntypedFormControl(flowDialogData?.flow?.name ?? ''),
321
- channelOperator: new UntypedFormControl(channelSelector?.channelOperator ?? 'EQUALS'),
322
- channel: new UntypedFormControl(channelSelector?.channel ?? ''),
323
- operations: new UntypedFormControl(channelSelector?.operations ?? []),
324
- entrypoints: new UntypedFormControl(channelSelector?.entrypoints ?? []),
325
- condition: new UntypedFormControl(conditionSelector?.condition ?? ''),
312
+ this.readOnly = false;
313
+ this.existingFlowExecution = cloneDeep(flowDialogData?.flowExecution);
314
+ this.flowExecutionFormGroup = new UntypedFormGroup({
315
+ mode: new UntypedFormControl(flowDialogData?.flowExecution?.mode ?? 'DEFAULT'),
316
+ matchRequired: new UntypedFormControl(flowDialogData?.flowExecution?.matchRequired ?? false),
326
317
  });
318
+ this.readOnly = Boolean(flowDialogData.readOnly);
319
+ if (this.readOnly) {
320
+ this.flowExecutionFormGroup.disable({ emitEvent: false });
321
+ }
327
322
  }
328
323
  onSubmit() {
329
- const channelSelectorToSave = {
330
- type: 'CHANNEL',
331
- channel: this.flowFormGroup?.get('channel')?.value,
332
- channelOperator: this.flowFormGroup?.get('channelOperator')?.value,
333
- operations: this.flowFormGroup?.get('operations')?.value,
334
- entrypoints: this.flowFormGroup?.get('entrypoints')?.value,
335
- };
336
- const conditionValue = this.flowFormGroup?.get('condition')?.value;
337
- const conditionSelectorToSave = conditionValue
338
- ? {
339
- type: 'CONDITION',
340
- condition: conditionValue,
341
- }
342
- : undefined;
343
- const flowToSave = {
344
- // New id for new flow
345
- _id: uniqueId('flow_'),
346
- // If existing flow, keep root props
347
- ...this.existingFlow,
348
- // Mark as changed
349
- _hasChanged: true,
350
- // Add changes
351
- name: this.flowFormGroup?.get('name')?.value,
352
- selectors: conditionSelectorToSave ? [channelSelectorToSave, conditionSelectorToSave] : [channelSelectorToSave],
353
- enabled: this.existingFlow ? this.existingFlow.enabled : true,
324
+ const flowExecutionToSave = {
325
+ ...this.existingFlowExecution,
326
+ mode: this.flowExecutionFormGroup?.get('mode')?.value,
327
+ matchRequired: this.flowExecutionFormGroup?.get('matchRequired')?.value,
354
328
  };
355
329
  this.dialogRef.close({
356
- ...flowToSave,
330
+ ...flowExecutionToSave,
357
331
  });
358
332
  }
359
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: GioPolicyStudioFlowMessageFormDialogComponent, deps: [{ token: i1.MatDialogRef }, { token: MAT_DIALOG_DATA }], target: i0.ɵɵFactoryTarget.Component }); }
360
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.4", type: GioPolicyStudioFlowMessageFormDialogComponent, isStandalone: true, selector: "gio-ps-flow-message-form-dialog", ngImport: i0, template: "<!--\n\n Copyright (C) 2015 The Gravitee team (http://gravitee.io)\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n\n-->\n<h2 mat-dialog-title class=\"title\">\n {{ mode === 'create' ? 'Create a new flow' : 'Edit flow'\n }}<button class=\"title__closeBtn\" mat-icon-button aria-label=\"Close dialog\" [mat-dialog-close]=\"false\">\n <mat-icon svgIcon=\"gio:cancel\"></mat-icon>\n </button>\n</h2>\n\n<mat-dialog-content *ngIf=\"flowFormGroup\" class=\"content\" [formGroup]=\"flowFormGroup\">\n <p>Flows allow you to apply different policies per event phases. For example you can reroute calls based on the URL specified.</p>\n\n <div class=\"content__row\">\n <mat-form-field>\n <mat-label>Flow name</mat-label>\n <input matInput formControlName=\"name\" cdkFocusInitial />\n <mat-hint>Names will be automatically generated with channel and operation if left blank.</mat-hint>\n </mat-form-field>\n </div>\n <div class=\"content__row\">\n <mat-form-field>\n <mat-label>Operator</mat-label>\n <mat-select formControlName=\"channelOperator\">\n <mat-option value=\"EQUALS\">Equals</mat-option>\n <mat-option value=\"STARTS_WITH\">Starts with</mat-option>\n </mat-select>\n <mat-hint>Channel operator.</mat-hint>\n </mat-form-field>\n\n <mat-form-field>\n <mat-label>Channel</mat-label>\n <input matInput formControlName=\"channel\" />\n <mat-hint>Publish or Subscribe channel. This is the path of your request.</mat-hint>\n </mat-form-field>\n </div>\n\n <div class=\"content__row\">\n <mat-form-field>\n <mat-label>Entrypoints</mat-label>\n <mat-select multiple formControlName=\"entrypoints\">\n <mat-option *ngFor=\"let entrypoint of entrypoints\" [value]=\"entrypoint.type\">{{ entrypoint.name }}</mat-option>\n </mat-select>\n <mat-hint>Entrypoints where your flow will be executed. They will all be executed if left empty.</mat-hint>\n </mat-form-field>\n </div>\n\n <div class=\"content__row\">\n <mat-form-field>\n <mat-label>Entrypoints supported operations</mat-label>\n <mat-select multiple formControlName=\"operations\">\n <mat-option value=\"PUBLISH\">Publish</mat-option>\n <mat-option value=\"SUBSCRIBE\">Subscribe</mat-option>\n </mat-select>\n <mat-hint>They will all be supported if left empty.</mat-hint>\n </mat-form-field>\n </div>\n\n <div class=\"content__row\">\n <mat-form-field>\n <mat-label>Condition</mat-label>\n <input matInput formControlName=\"condition\" />\n <mat-hint>Condition to execute the flow, supports Expression Language.</mat-hint>\n </mat-form-field>\n </div>\n</mat-dialog-content>\n\n<mat-dialog-actions class=\"actions\" align=\"end\">\n <button class=\"actions__cancelBtn\" mat-button [mat-dialog-close]=\"false\">Cancel</button>\n <button class=\"actions__saveBtn\" color=\"primary\" mat-flat-button role=\"dialog\" (click)=\"onSubmit()\">\n {{ mode === 'create' ? 'Create' : 'Save' }}\n </button>\n</mat-dialog-actions>\n", styles: [".title__closeBtn{top:0;right:-24px;float:right}.content__row{display:flex;align-items:flex-start;gap:16px}.content__row mat-form-field{flex:1 1 auto}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i3.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i3.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i3.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i4.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: i4.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "ngmodule", type: MatDialogModule }, { kind: "directive", type: i1.MatDialogClose, selector: "[mat-dialog-close], [matDialogClose]", inputs: ["aria-label", "type", "mat-dialog-close", "matDialogClose"], exportAs: ["matDialogClose"] }, { kind: "directive", type: i1.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: i1.MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }, { kind: "directive", type: i1.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i5.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i5.MatLabel, selector: "mat-label" }, { kind: "directive", type: i5.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i6.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i6.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i7.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatSlideToggleModule }, { kind: "ngmodule", type: GioFormSlideToggleModule }, { kind: "ngmodule", type: GioBannerModule }, { kind: "ngmodule", type: GioIconsModule }, { kind: "component", type: i5$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }] }); }
333
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: GioPolicyStudioFlowExecutionFormDialogComponent, deps: [{ token: i1.MatDialogRef }, { token: MAT_DIALOG_DATA }], target: i0.ɵɵFactoryTarget.Component }); }
334
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.4", type: GioPolicyStudioFlowExecutionFormDialogComponent, isStandalone: true, selector: "gio-ps-flow-execution-form-dialog", ngImport: i0, template: "<!--\n\n Copyright (C) 2015 The Gravitee team (http://gravitee.io)\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n\n-->\n<h2 mat-dialog-title class=\"title\">\n Flow execution\n\n <button class=\"title__closeBtn\" mat-icon-button aria-label=\"Close dialog\" [mat-dialog-close]=\"\">\n <mat-icon svgIcon=\"gio:cancel\"></mat-icon>\n </button>\n</h2>\n\n<mat-dialog-content *ngIf=\"flowExecutionFormGroup\" class=\"content\" [formGroup]=\"flowExecutionFormGroup\">\n <div class=\"content__row\">\n <gio-banner-info>\n By default, flow selection is based on the operators defined in your flows, either when it \u201Cmatches with\u201D or \u201Cstarts with\u201D a path. You\n can choose the \"Best match\" option to select a flow from the closest path.\n </gio-banner-info>\n </div>\n <div class=\"content__row\">\n <mat-form-field>\n <mat-label>Default flow mode</mat-label>\n <mat-select formControlName=\"mode\">\n <mat-option value=\"BEST_MATCH\">Best Match</mat-option>\n <mat-option value=\"DEFAULT\">Default</mat-option>\n </mat-select>\n <mat-hint>Change how the flow selection is made</mat-hint>\n </mat-form-field>\n </div>\n\n <div class=\"content__row\">\n <gio-form-slide-toggle>\n <gio-form-label>Fail on flow mismatch</gio-form-label>\n Respond with an error when requests don\u2019t match any defined flow\n <mat-slide-toggle gioFormSlideToggle formControlName=\"matchRequired\"></mat-slide-toggle>\n </gio-form-slide-toggle>\n </div>\n</mat-dialog-content>\n\n<mat-dialog-actions class=\"actions\" align=\"end\">\n <button [disabled]=\"readOnly\" class=\"actions__cancelBtn\" mat-button [mat-dialog-close]=\"\">Cancel</button>\n <button [disabled]=\"readOnly\" class=\"actions__saveBtn\" color=\"primary\" mat-flat-button role=\"dialog\" (click)=\"onSubmit()\">Save</button>\n</mat-dialog-actions>\n", styles: [".title__closeBtn{top:0;right:-24px;float:right}.content__row{display:flex;align-items:flex-start;gap:16px}.content__row mat-form-field{flex:1 1 auto}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i3.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i3.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i4.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: i4.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "ngmodule", type: MatDialogModule }, { kind: "directive", type: i1.MatDialogClose, selector: "[mat-dialog-close], [matDialogClose]", inputs: ["aria-label", "type", "mat-dialog-close", "matDialogClose"], exportAs: ["matDialogClose"] }, { kind: "directive", type: i1.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: i1.MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }, { kind: "directive", type: i1.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i5.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i5.MatLabel, selector: "mat-label" }, { kind: "directive", type: i5.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i6.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i6.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatSlideToggleModule }, { kind: "component", type: i7.MatSlideToggle, selector: "mat-slide-toggle", inputs: ["name", "id", "labelPosition", "aria-label", "aria-labelledby", "aria-describedby", "required", "color", "disabled", "disableRipple", "tabIndex", "checked", "hideIcon", "disabledInteractive"], outputs: ["change", "toggleChange"], exportAs: ["matSlideToggle"] }, { kind: "ngmodule", type: GioFormSlideToggleModule }, { kind: "component", type: i6$1.GioFormSlideToggleComponent, selector: "gio-form-slide-toggle", inputs: ["appearance"] }, { kind: "component", type: i6$1.GioFormLabelComponent, selector: "gio-form-label" }, { kind: "directive", type: i6$1.GioFormSlideToggleDirective, selector: "[gioFormSlideToggle]" }, { kind: "ngmodule", type: GioBannerModule }, { kind: "component", type: i6$1.GioBannerInfoComponent, selector: "gio-banner-info" }, { kind: "ngmodule", type: GioIconsModule }, { kind: "component", type: i5$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }] }); }
361
335
  }
362
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: GioPolicyStudioFlowMessageFormDialogComponent, decorators: [{
336
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: GioPolicyStudioFlowExecutionFormDialogComponent, decorators: [{
363
337
  type: Component,
364
338
  args: [{ imports: [
365
339
  CommonModule,
@@ -368,12 +342,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImpor
368
342
  MatDialogModule,
369
343
  MatFormFieldModule,
370
344
  MatSelectModule,
371
- MatInputModule,
372
345
  MatSlideToggleModule,
373
346
  GioFormSlideToggleModule,
374
347
  GioBannerModule,
375
348
  GioIconsModule,
376
- ], selector: 'gio-ps-flow-message-form-dialog', template: "<!--\n\n Copyright (C) 2015 The Gravitee team (http://gravitee.io)\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n\n-->\n<h2 mat-dialog-title class=\"title\">\n {{ mode === 'create' ? 'Create a new flow' : 'Edit flow'\n }}<button class=\"title__closeBtn\" mat-icon-button aria-label=\"Close dialog\" [mat-dialog-close]=\"false\">\n <mat-icon svgIcon=\"gio:cancel\"></mat-icon>\n </button>\n</h2>\n\n<mat-dialog-content *ngIf=\"flowFormGroup\" class=\"content\" [formGroup]=\"flowFormGroup\">\n <p>Flows allow you to apply different policies per event phases. For example you can reroute calls based on the URL specified.</p>\n\n <div class=\"content__row\">\n <mat-form-field>\n <mat-label>Flow name</mat-label>\n <input matInput formControlName=\"name\" cdkFocusInitial />\n <mat-hint>Names will be automatically generated with channel and operation if left blank.</mat-hint>\n </mat-form-field>\n </div>\n <div class=\"content__row\">\n <mat-form-field>\n <mat-label>Operator</mat-label>\n <mat-select formControlName=\"channelOperator\">\n <mat-option value=\"EQUALS\">Equals</mat-option>\n <mat-option value=\"STARTS_WITH\">Starts with</mat-option>\n </mat-select>\n <mat-hint>Channel operator.</mat-hint>\n </mat-form-field>\n\n <mat-form-field>\n <mat-label>Channel</mat-label>\n <input matInput formControlName=\"channel\" />\n <mat-hint>Publish or Subscribe channel. This is the path of your request.</mat-hint>\n </mat-form-field>\n </div>\n\n <div class=\"content__row\">\n <mat-form-field>\n <mat-label>Entrypoints</mat-label>\n <mat-select multiple formControlName=\"entrypoints\">\n <mat-option *ngFor=\"let entrypoint of entrypoints\" [value]=\"entrypoint.type\">{{ entrypoint.name }}</mat-option>\n </mat-select>\n <mat-hint>Entrypoints where your flow will be executed. They will all be executed if left empty.</mat-hint>\n </mat-form-field>\n </div>\n\n <div class=\"content__row\">\n <mat-form-field>\n <mat-label>Entrypoints supported operations</mat-label>\n <mat-select multiple formControlName=\"operations\">\n <mat-option value=\"PUBLISH\">Publish</mat-option>\n <mat-option value=\"SUBSCRIBE\">Subscribe</mat-option>\n </mat-select>\n <mat-hint>They will all be supported if left empty.</mat-hint>\n </mat-form-field>\n </div>\n\n <div class=\"content__row\">\n <mat-form-field>\n <mat-label>Condition</mat-label>\n <input matInput formControlName=\"condition\" />\n <mat-hint>Condition to execute the flow, supports Expression Language.</mat-hint>\n </mat-form-field>\n </div>\n</mat-dialog-content>\n\n<mat-dialog-actions class=\"actions\" align=\"end\">\n <button class=\"actions__cancelBtn\" mat-button [mat-dialog-close]=\"false\">Cancel</button>\n <button class=\"actions__saveBtn\" color=\"primary\" mat-flat-button role=\"dialog\" (click)=\"onSubmit()\">\n {{ mode === 'create' ? 'Create' : 'Save' }}\n </button>\n</mat-dialog-actions>\n", styles: [".title__closeBtn{top:0;right:-24px;float:right}.content__row{display:flex;align-items:flex-start;gap:16px}.content__row mat-form-field{flex:1 1 auto}\n"] }]
349
+ ], selector: 'gio-ps-flow-execution-form-dialog', template: "<!--\n\n Copyright (C) 2015 The Gravitee team (http://gravitee.io)\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n\n-->\n<h2 mat-dialog-title class=\"title\">\n Flow execution\n\n <button class=\"title__closeBtn\" mat-icon-button aria-label=\"Close dialog\" [mat-dialog-close]=\"\">\n <mat-icon svgIcon=\"gio:cancel\"></mat-icon>\n </button>\n</h2>\n\n<mat-dialog-content *ngIf=\"flowExecutionFormGroup\" class=\"content\" [formGroup]=\"flowExecutionFormGroup\">\n <div class=\"content__row\">\n <gio-banner-info>\n By default, flow selection is based on the operators defined in your flows, either when it \u201Cmatches with\u201D or \u201Cstarts with\u201D a path. You\n can choose the \"Best match\" option to select a flow from the closest path.\n </gio-banner-info>\n </div>\n <div class=\"content__row\">\n <mat-form-field>\n <mat-label>Default flow mode</mat-label>\n <mat-select formControlName=\"mode\">\n <mat-option value=\"BEST_MATCH\">Best Match</mat-option>\n <mat-option value=\"DEFAULT\">Default</mat-option>\n </mat-select>\n <mat-hint>Change how the flow selection is made</mat-hint>\n </mat-form-field>\n </div>\n\n <div class=\"content__row\">\n <gio-form-slide-toggle>\n <gio-form-label>Fail on flow mismatch</gio-form-label>\n Respond with an error when requests don\u2019t match any defined flow\n <mat-slide-toggle gioFormSlideToggle formControlName=\"matchRequired\"></mat-slide-toggle>\n </gio-form-slide-toggle>\n </div>\n</mat-dialog-content>\n\n<mat-dialog-actions class=\"actions\" align=\"end\">\n <button [disabled]=\"readOnly\" class=\"actions__cancelBtn\" mat-button [mat-dialog-close]=\"\">Cancel</button>\n <button [disabled]=\"readOnly\" class=\"actions__saveBtn\" color=\"primary\" mat-flat-button role=\"dialog\" (click)=\"onSubmit()\">Save</button>\n</mat-dialog-actions>\n", styles: [".title__closeBtn{top:0;right:-24px;float:right}.content__row{display:flex;align-items:flex-start;gap:16px}.content__row mat-form-field{flex:1 1 auto}\n"] }]
377
350
  }], ctorParameters: () => [{ type: i1.MatDialogRef }, { type: undefined, decorators: [{
378
351
  type: Inject,
379
352
  args: [MAT_DIALOG_DATA]
@@ -394,30 +367,32 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImpor
394
367
  * See the License for the specific language governing permissions and
395
368
  * limitations under the License.
396
369
  */
397
- const METHODS_AUTOCOMPLETE = ['ALL', ...HttpMethods];
398
- class GioPolicyStudioFlowProxyFormDialogComponent {
370
+ class GioPolicyStudioFlowMessageFormDialogComponent {
399
371
  constructor(dialogRef, flowDialogData) {
400
372
  this.dialogRef = dialogRef;
373
+ this.entrypoints = [];
401
374
  this.mode = 'create';
402
- this.methods = METHODS_AUTOCOMPLETE;
375
+ this.entrypoints = flowDialogData?.entrypoints ?? [];
403
376
  this.existingFlow = cloneDeep(flowDialogData?.flow);
404
377
  this.mode = this.existingFlow ? 'edit' : 'create';
405
- const httpSelector = flowDialogData?.flow?.selectors?.find(s => s.type === 'HTTP');
378
+ const channelSelector = flowDialogData?.flow?.selectors?.find(s => s.type === 'CHANNEL');
406
379
  const conditionSelector = flowDialogData?.flow?.selectors?.find(s => s.type === 'CONDITION');
407
380
  this.flowFormGroup = new UntypedFormGroup({
408
381
  name: new UntypedFormControl(flowDialogData?.flow?.name ?? ''),
409
- pathOperator: new UntypedFormControl(httpSelector?.pathOperator ?? 'EQUALS'),
410
- path: new UntypedFormControl(sanitizePathFormValue(httpSelector?.path)),
411
- methods: new UntypedFormControl(sanitizeMethodFormValue(httpSelector?.methods)),
382
+ channelOperator: new UntypedFormControl(channelSelector?.channelOperator ?? 'EQUALS'),
383
+ channel: new UntypedFormControl(channelSelector?.channel ?? ''),
384
+ operations: new UntypedFormControl(channelSelector?.operations ?? []),
385
+ entrypoints: new UntypedFormControl(channelSelector?.entrypoints ?? []),
412
386
  condition: new UntypedFormControl(conditionSelector?.condition ?? ''),
413
387
  });
414
388
  }
415
389
  onSubmit() {
416
- const httpSelectorToSave = {
417
- type: 'HTTP',
418
- path: sanitizePath(this.flowFormGroup?.get('path')?.value),
419
- pathOperator: this.flowFormGroup?.get('pathOperator')?.value,
420
- methods: sanitizeMethods(this.flowFormGroup?.get('methods')?.value),
390
+ const channelSelectorToSave = {
391
+ type: 'CHANNEL',
392
+ channel: this.flowFormGroup?.get('channel')?.value,
393
+ channelOperator: this.flowFormGroup?.get('channelOperator')?.value,
394
+ operations: this.flowFormGroup?.get('operations')?.value,
395
+ entrypoints: this.flowFormGroup?.get('entrypoints')?.value,
421
396
  };
422
397
  const conditionValue = this.flowFormGroup?.get('condition')?.value;
423
398
  const conditionSelectorToSave = conditionValue
@@ -435,20 +410,17 @@ class GioPolicyStudioFlowProxyFormDialogComponent {
435
410
  _hasChanged: true,
436
411
  // Add changes
437
412
  name: this.flowFormGroup?.get('name')?.value,
438
- selectors: conditionSelectorToSave ? [httpSelectorToSave, conditionSelectorToSave] : [httpSelectorToSave],
413
+ selectors: conditionSelectorToSave ? [channelSelectorToSave, conditionSelectorToSave] : [channelSelectorToSave],
439
414
  enabled: this.existingFlow ? this.existingFlow.enabled : true,
440
415
  };
441
416
  this.dialogRef.close({
442
417
  ...flowToSave,
443
418
  });
444
419
  }
445
- tagValidationHook(tag, validationCb) {
446
- validationCb(METHODS_AUTOCOMPLETE.map(m => `${m}`).includes(tag.toUpperCase()));
447
- }
448
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: GioPolicyStudioFlowProxyFormDialogComponent, deps: [{ token: i1.MatDialogRef }, { token: MAT_DIALOG_DATA }], target: i0.ɵɵFactoryTarget.Component }); }
449
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.4", type: GioPolicyStudioFlowProxyFormDialogComponent, isStandalone: true, selector: "gio-ps-flow-proxy-form-dialog", ngImport: i0, template: "<!--\n\n Copyright (C) 2015 The Gravitee team (http://gravitee.io)\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n\n-->\n<h2 mat-dialog-title class=\"title\">\n {{ mode === 'create' ? 'Create a new flow' : 'Edit flow' }}\n\n <button class=\"title__closeBtn\" mat-icon-button aria-label=\"Close dialog\" [mat-dialog-close]=\"false\">\n <mat-icon svgIcon=\"gio:cancel\"></mat-icon>\n </button>\n</h2>\n\n<mat-dialog-content *ngIf=\"flowFormGroup\" class=\"content\" [formGroup]=\"flowFormGroup\">\n <p>\n Flows allow you to apply different policies per HTTP path and/or method. For example you can reroute calls based on the URL specified.\n </p>\n\n <div class=\"content__row\">\n <mat-form-field>\n <mat-label>Flow name</mat-label>\n <input matInput formControlName=\"name\" cdkFocusInitial />\n <mat-hint>Names will be automatically generated with path and method if left blank</mat-hint>\n </mat-form-field>\n </div>\n <div class=\"content__row\">\n <mat-form-field>\n <mat-label>Operator</mat-label>\n <mat-select formControlName=\"pathOperator\">\n <mat-option value=\"EQUALS\">Equals</mat-option>\n <mat-option value=\"STARTS_WITH\">Starts with</mat-option>\n </mat-select>\n <mat-hint>Path operator</mat-hint>\n </mat-form-field>\n\n <mat-form-field>\n <mat-label>Path</mat-label>\n <span matTextPrefix>/&nbsp;</span>\n <input matInput formControlName=\"path\" />\n <mat-hint>Path</mat-hint>\n </mat-form-field>\n </div>\n\n <div class=\"content__row\">\n <mat-form-field>\n <mat-label>Methods for your flow</mat-label>\n <gio-form-tags-input\n formControlName=\"methods\"\n [autocompleteOptions]=\"methods\"\n [tagValidationHook]=\"tagValidationHook\"\n ></gio-form-tags-input>\n </mat-form-field>\n </div>\n\n <div class=\"content__row\">\n <mat-form-field>\n <mat-label>Condition</mat-label>\n <input matInput formControlName=\"condition\" />\n <mat-hint>Condition to execute the flow, supports Expression Language</mat-hint>\n </mat-form-field>\n </div>\n</mat-dialog-content>\n\n<mat-dialog-actions class=\"actions\" align=\"end\">\n <button class=\"actions__cancelBtn\" mat-button [mat-dialog-close]=\"false\">Cancel</button>\n <button class=\"actions__saveBtn\" color=\"primary\" mat-flat-button role=\"dialog\" (click)=\"onSubmit()\">\n {{ mode === 'create' ? 'Create' : 'Save' }}\n </button>\n</mat-dialog-actions>\n", styles: [".title__closeBtn{top:0;right:-24px;float:right}.content__row{display:flex;align-items:flex-start;gap:16px}.content__row mat-form-field{flex:1 1 auto}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i3.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i3.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i3.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i4.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: i4.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "ngmodule", type: MatDialogModule }, { kind: "directive", type: i1.MatDialogClose, selector: "[mat-dialog-close], [matDialogClose]", inputs: ["aria-label", "type", "mat-dialog-close", "matDialogClose"], exportAs: ["matDialogClose"] }, { kind: "directive", type: i1.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: i1.MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }, { kind: "directive", type: i1.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i5.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i5.MatLabel, selector: "mat-label" }, { kind: "directive", type: i5.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "directive", type: i5.MatPrefix, selector: "[matPrefix], [matIconPrefix], [matTextPrefix]", inputs: ["matTextPrefix"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i6.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i6.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i7.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatSlideToggleModule }, { kind: "ngmodule", type: GioFormSlideToggleModule }, { kind: "ngmodule", type: GioBannerModule }, { kind: "ngmodule", type: GioIconsModule }, { kind: "component", type: i5$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: GioFormTagsInputModule }, { kind: "component", type: i6$1.GioFormTagsInputComponent, selector: "gio-form-tags-input", inputs: ["aria-label", "addOnBlur", "tagValidationHook", "autocompleteOptions", "displayValueWith", "useAutocompleteOptionValueOnly", "placeholder", "required", "disabled"] }] }); }
420
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: GioPolicyStudioFlowMessageFormDialogComponent, deps: [{ token: i1.MatDialogRef }, { token: MAT_DIALOG_DATA }], target: i0.ɵɵFactoryTarget.Component }); }
421
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.4", type: GioPolicyStudioFlowMessageFormDialogComponent, isStandalone: true, selector: "gio-ps-flow-message-form-dialog", ngImport: i0, template: "<!--\n\n Copyright (C) 2015 The Gravitee team (http://gravitee.io)\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n\n-->\n<h2 mat-dialog-title class=\"title\">\n {{ mode === 'create' ? 'Create a new flow' : 'Edit flow'\n }}<button class=\"title__closeBtn\" mat-icon-button aria-label=\"Close dialog\" [mat-dialog-close]=\"false\">\n <mat-icon svgIcon=\"gio:cancel\"></mat-icon>\n </button>\n</h2>\n\n<mat-dialog-content *ngIf=\"flowFormGroup\" class=\"content\" [formGroup]=\"flowFormGroup\">\n <p>Flows allow you to apply different policies per event phases. For example you can reroute calls based on the URL specified.</p>\n\n <div class=\"content__row\">\n <mat-form-field>\n <mat-label>Flow name</mat-label>\n <input matInput formControlName=\"name\" cdkFocusInitial />\n <mat-hint>Names will be automatically generated with channel and operation if left blank.</mat-hint>\n </mat-form-field>\n </div>\n <div class=\"content__row\">\n <mat-form-field>\n <mat-label>Operator</mat-label>\n <mat-select formControlName=\"channelOperator\">\n <mat-option value=\"EQUALS\">Equals</mat-option>\n <mat-option value=\"STARTS_WITH\">Starts with</mat-option>\n </mat-select>\n <mat-hint>Channel operator.</mat-hint>\n </mat-form-field>\n\n <mat-form-field>\n <mat-label>Channel</mat-label>\n <input matInput formControlName=\"channel\" />\n <mat-hint>Publish or Subscribe channel. This is the path of your request.</mat-hint>\n </mat-form-field>\n </div>\n\n <div class=\"content__row\">\n <mat-form-field>\n <mat-label>Entrypoints</mat-label>\n <mat-select multiple formControlName=\"entrypoints\">\n <mat-option *ngFor=\"let entrypoint of entrypoints\" [value]=\"entrypoint.type\">{{ entrypoint.name }}</mat-option>\n </mat-select>\n <mat-hint>Entrypoints where your flow will be executed. They will all be executed if left empty.</mat-hint>\n </mat-form-field>\n </div>\n\n <div class=\"content__row\">\n <mat-form-field>\n <mat-label>Entrypoints supported operations</mat-label>\n <mat-select multiple formControlName=\"operations\">\n <mat-option value=\"PUBLISH\">Publish</mat-option>\n <mat-option value=\"SUBSCRIBE\">Subscribe</mat-option>\n </mat-select>\n <mat-hint>They will all be supported if left empty.</mat-hint>\n </mat-form-field>\n </div>\n\n <div class=\"content__row\">\n <mat-form-field>\n <mat-label>Condition</mat-label>\n <input matInput formControlName=\"condition\" />\n <mat-hint>Condition to execute the flow, supports Expression Language.</mat-hint>\n </mat-form-field>\n </div>\n</mat-dialog-content>\n\n<mat-dialog-actions class=\"actions\" align=\"end\">\n <button class=\"actions__cancelBtn\" mat-button [mat-dialog-close]=\"false\">Cancel</button>\n <button class=\"actions__saveBtn\" color=\"primary\" mat-flat-button role=\"dialog\" (click)=\"onSubmit()\">\n {{ mode === 'create' ? 'Create' : 'Save' }}\n </button>\n</mat-dialog-actions>\n", styles: [".title__closeBtn{top:0;right:-24px;float:right}.content__row{display:flex;align-items:flex-start;gap:16px}.content__row mat-form-field{flex:1 1 auto}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i3.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i3.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i3.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i4.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: i4.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "ngmodule", type: MatDialogModule }, { kind: "directive", type: i1.MatDialogClose, selector: "[mat-dialog-close], [matDialogClose]", inputs: ["aria-label", "type", "mat-dialog-close", "matDialogClose"], exportAs: ["matDialogClose"] }, { kind: "directive", type: i1.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: i1.MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }, { kind: "directive", type: i1.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i5.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i5.MatLabel, selector: "mat-label" }, { kind: "directive", type: i5.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i6.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i6.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i7$1.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatSlideToggleModule }, { kind: "ngmodule", type: GioFormSlideToggleModule }, { kind: "ngmodule", type: GioBannerModule }, { kind: "ngmodule", type: GioIconsModule }, { kind: "component", type: i5$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }] }); }
450
422
  }
451
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: GioPolicyStudioFlowProxyFormDialogComponent, decorators: [{
423
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: GioPolicyStudioFlowMessageFormDialogComponent, decorators: [{
452
424
  type: Component,
453
425
  args: [{ imports: [
454
426
  CommonModule,
@@ -462,34 +434,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImpor
462
434
  GioFormSlideToggleModule,
463
435
  GioBannerModule,
464
436
  GioIconsModule,
465
- GioFormTagsInputModule,
466
- ], selector: 'gio-ps-flow-proxy-form-dialog', template: "<!--\n\n Copyright (C) 2015 The Gravitee team (http://gravitee.io)\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n\n-->\n<h2 mat-dialog-title class=\"title\">\n {{ mode === 'create' ? 'Create a new flow' : 'Edit flow' }}\n\n <button class=\"title__closeBtn\" mat-icon-button aria-label=\"Close dialog\" [mat-dialog-close]=\"false\">\n <mat-icon svgIcon=\"gio:cancel\"></mat-icon>\n </button>\n</h2>\n\n<mat-dialog-content *ngIf=\"flowFormGroup\" class=\"content\" [formGroup]=\"flowFormGroup\">\n <p>\n Flows allow you to apply different policies per HTTP path and/or method. For example you can reroute calls based on the URL specified.\n </p>\n\n <div class=\"content__row\">\n <mat-form-field>\n <mat-label>Flow name</mat-label>\n <input matInput formControlName=\"name\" cdkFocusInitial />\n <mat-hint>Names will be automatically generated with path and method if left blank</mat-hint>\n </mat-form-field>\n </div>\n <div class=\"content__row\">\n <mat-form-field>\n <mat-label>Operator</mat-label>\n <mat-select formControlName=\"pathOperator\">\n <mat-option value=\"EQUALS\">Equals</mat-option>\n <mat-option value=\"STARTS_WITH\">Starts with</mat-option>\n </mat-select>\n <mat-hint>Path operator</mat-hint>\n </mat-form-field>\n\n <mat-form-field>\n <mat-label>Path</mat-label>\n <span matTextPrefix>/&nbsp;</span>\n <input matInput formControlName=\"path\" />\n <mat-hint>Path</mat-hint>\n </mat-form-field>\n </div>\n\n <div class=\"content__row\">\n <mat-form-field>\n <mat-label>Methods for your flow</mat-label>\n <gio-form-tags-input\n formControlName=\"methods\"\n [autocompleteOptions]=\"methods\"\n [tagValidationHook]=\"tagValidationHook\"\n ></gio-form-tags-input>\n </mat-form-field>\n </div>\n\n <div class=\"content__row\">\n <mat-form-field>\n <mat-label>Condition</mat-label>\n <input matInput formControlName=\"condition\" />\n <mat-hint>Condition to execute the flow, supports Expression Language</mat-hint>\n </mat-form-field>\n </div>\n</mat-dialog-content>\n\n<mat-dialog-actions class=\"actions\" align=\"end\">\n <button class=\"actions__cancelBtn\" mat-button [mat-dialog-close]=\"false\">Cancel</button>\n <button class=\"actions__saveBtn\" color=\"primary\" mat-flat-button role=\"dialog\" (click)=\"onSubmit()\">\n {{ mode === 'create' ? 'Create' : 'Save' }}\n </button>\n</mat-dialog-actions>\n", styles: [".title__closeBtn{top:0;right:-24px;float:right}.content__row{display:flex;align-items:flex-start;gap:16px}.content__row mat-form-field{flex:1 1 auto}\n"] }]
437
+ ], selector: 'gio-ps-flow-message-form-dialog', template: "<!--\n\n Copyright (C) 2015 The Gravitee team (http://gravitee.io)\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n\n-->\n<h2 mat-dialog-title class=\"title\">\n {{ mode === 'create' ? 'Create a new flow' : 'Edit flow'\n }}<button class=\"title__closeBtn\" mat-icon-button aria-label=\"Close dialog\" [mat-dialog-close]=\"false\">\n <mat-icon svgIcon=\"gio:cancel\"></mat-icon>\n </button>\n</h2>\n\n<mat-dialog-content *ngIf=\"flowFormGroup\" class=\"content\" [formGroup]=\"flowFormGroup\">\n <p>Flows allow you to apply different policies per event phases. For example you can reroute calls based on the URL specified.</p>\n\n <div class=\"content__row\">\n <mat-form-field>\n <mat-label>Flow name</mat-label>\n <input matInput formControlName=\"name\" cdkFocusInitial />\n <mat-hint>Names will be automatically generated with channel and operation if left blank.</mat-hint>\n </mat-form-field>\n </div>\n <div class=\"content__row\">\n <mat-form-field>\n <mat-label>Operator</mat-label>\n <mat-select formControlName=\"channelOperator\">\n <mat-option value=\"EQUALS\">Equals</mat-option>\n <mat-option value=\"STARTS_WITH\">Starts with</mat-option>\n </mat-select>\n <mat-hint>Channel operator.</mat-hint>\n </mat-form-field>\n\n <mat-form-field>\n <mat-label>Channel</mat-label>\n <input matInput formControlName=\"channel\" />\n <mat-hint>Publish or Subscribe channel. This is the path of your request.</mat-hint>\n </mat-form-field>\n </div>\n\n <div class=\"content__row\">\n <mat-form-field>\n <mat-label>Entrypoints</mat-label>\n <mat-select multiple formControlName=\"entrypoints\">\n <mat-option *ngFor=\"let entrypoint of entrypoints\" [value]=\"entrypoint.type\">{{ entrypoint.name }}</mat-option>\n </mat-select>\n <mat-hint>Entrypoints where your flow will be executed. They will all be executed if left empty.</mat-hint>\n </mat-form-field>\n </div>\n\n <div class=\"content__row\">\n <mat-form-field>\n <mat-label>Entrypoints supported operations</mat-label>\n <mat-select multiple formControlName=\"operations\">\n <mat-option value=\"PUBLISH\">Publish</mat-option>\n <mat-option value=\"SUBSCRIBE\">Subscribe</mat-option>\n </mat-select>\n <mat-hint>They will all be supported if left empty.</mat-hint>\n </mat-form-field>\n </div>\n\n <div class=\"content__row\">\n <mat-form-field>\n <mat-label>Condition</mat-label>\n <input matInput formControlName=\"condition\" />\n <mat-hint>Condition to execute the flow, supports Expression Language.</mat-hint>\n </mat-form-field>\n </div>\n</mat-dialog-content>\n\n<mat-dialog-actions class=\"actions\" align=\"end\">\n <button class=\"actions__cancelBtn\" mat-button [mat-dialog-close]=\"false\">Cancel</button>\n <button class=\"actions__saveBtn\" color=\"primary\" mat-flat-button role=\"dialog\" (click)=\"onSubmit()\">\n {{ mode === 'create' ? 'Create' : 'Save' }}\n </button>\n</mat-dialog-actions>\n", styles: [".title__closeBtn{top:0;right:-24px;float:right}.content__row{display:flex;align-items:flex-start;gap:16px}.content__row mat-form-field{flex:1 1 auto}\n"] }]
467
438
  }], ctorParameters: () => [{ type: i1.MatDialogRef }, { type: undefined, decorators: [{
468
439
  type: Inject,
469
440
  args: [MAT_DIALOG_DATA]
470
441
  }] }] });
471
- const sanitizeMethods = (value) => {
472
- if (!value || value.find(m => m === 'ALL'))
473
- return [];
474
- return value;
475
- };
476
- const sanitizeMethodFormValue = (methods) => {
477
- if (!methods || methods.length === 0)
478
- return ['ALL'];
479
- return methods;
480
- };
481
- const sanitizePath = (path) => {
482
- if (!path || !path.startsWith('/')) {
483
- return `/${path}`;
484
- }
485
- return path;
486
- };
487
- const sanitizePathFormValue = (path) => {
488
- if (path && path.startsWith('/')) {
489
- return path.substring(1);
490
- }
491
- return path ?? '';
492
- };
493
442
 
494
443
  /*
495
444
  * Copyright (C) 2015 The Gravitee team (http://gravitee.io)
@@ -506,34 +455,41 @@ const sanitizePathFormValue = (path) => {
506
455
  * See the License for the specific language governing permissions and
507
456
  * limitations under the License.
508
457
  */
509
- class GioPolicyStudioFlowExecutionFormDialogComponent {
458
+ class GioPolicyStudioFlowNativeFormDialogComponent {
510
459
  constructor(dialogRef, flowDialogData) {
511
460
  this.dialogRef = dialogRef;
512
- this.readOnly = false;
513
- this.existingFlowExecution = cloneDeep(flowDialogData?.flowExecution);
514
- this.flowExecutionFormGroup = new UntypedFormGroup({
515
- mode: new UntypedFormControl(flowDialogData?.flowExecution?.mode ?? 'DEFAULT'),
516
- matchRequired: new UntypedFormControl(flowDialogData?.flowExecution?.matchRequired ?? false),
461
+ this.mode = 'create';
462
+ this.existingFlow = cloneDeep(flowDialogData?.flow);
463
+ this.mode = this.existingFlow ? 'edit' : 'create';
464
+ this.flowFormGroup = new UntypedFormGroup({
465
+ name: new UntypedFormControl(flowDialogData?.flow?.name ?? ''),
517
466
  });
518
- this.readOnly = Boolean(flowDialogData.readOnly);
519
- if (this.readOnly) {
520
- this.flowExecutionFormGroup.disable({ emitEvent: false });
521
- }
467
+ this.defaultFlowName = capitalize(flowDialogData.parentGroupName) + ' flow';
522
468
  }
523
469
  onSubmit() {
524
- const flowExecutionToSave = {
525
- ...this.existingFlowExecution,
526
- mode: this.flowExecutionFormGroup?.get('mode')?.value,
527
- matchRequired: this.flowExecutionFormGroup?.get('matchRequired')?.value,
470
+ const flowToSave = {
471
+ // New id for new flow
472
+ _id: uniqueId('flow_'),
473
+ // If existing flow, keep root props
474
+ ...this.existingFlow,
475
+ // Mark as changed
476
+ _hasChanged: true,
477
+ // Add changes
478
+ name: this.getFlowName(),
479
+ enabled: this.existingFlow ? this.existingFlow.enabled : true,
528
480
  };
529
481
  this.dialogRef.close({
530
- ...flowExecutionToSave,
482
+ ...flowToSave,
531
483
  });
532
484
  }
533
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: GioPolicyStudioFlowExecutionFormDialogComponent, deps: [{ token: i1.MatDialogRef }, { token: MAT_DIALOG_DATA }], target: i0.ɵɵFactoryTarget.Component }); }
534
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.4", type: GioPolicyStudioFlowExecutionFormDialogComponent, isStandalone: true, selector: "gio-ps-flow-execution-form-dialog", ngImport: i0, template: "<!--\n\n Copyright (C) 2015 The Gravitee team (http://gravitee.io)\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n\n-->\n<h2 mat-dialog-title class=\"title\">\n Flow execution\n\n <button class=\"title__closeBtn\" mat-icon-button aria-label=\"Close dialog\" [mat-dialog-close]=\"\">\n <mat-icon svgIcon=\"gio:cancel\"></mat-icon>\n </button>\n</h2>\n\n<mat-dialog-content *ngIf=\"flowExecutionFormGroup\" class=\"content\" [formGroup]=\"flowExecutionFormGroup\">\n <div class=\"content__row\">\n <gio-banner-info>\n By default, flow selection is based on the operators defined in your flows, either when it \u201Cmatches with\u201D or \u201Cstarts with\u201D a path. You\n can choose the \"Best match\" option to select a flow from the closest path.\n </gio-banner-info>\n </div>\n <div class=\"content__row\">\n <mat-form-field>\n <mat-label>Default flow mode</mat-label>\n <mat-select formControlName=\"mode\">\n <mat-option value=\"BEST_MATCH\">Best Match</mat-option>\n <mat-option value=\"DEFAULT\">Default</mat-option>\n </mat-select>\n <mat-hint>Change how the flow selection is made</mat-hint>\n </mat-form-field>\n </div>\n\n <div class=\"content__row\">\n <gio-form-slide-toggle>\n <gio-form-label>Fail on flow mismatch</gio-form-label>\n Respond with an error when requests don\u2019t match any defined flow\n <mat-slide-toggle gioFormSlideToggle formControlName=\"matchRequired\"></mat-slide-toggle>\n </gio-form-slide-toggle>\n </div>\n</mat-dialog-content>\n\n<mat-dialog-actions class=\"actions\" align=\"end\">\n <button [disabled]=\"readOnly\" class=\"actions__cancelBtn\" mat-button [mat-dialog-close]=\"\">Cancel</button>\n <button [disabled]=\"readOnly\" class=\"actions__saveBtn\" color=\"primary\" mat-flat-button role=\"dialog\" (click)=\"onSubmit()\">Save</button>\n</mat-dialog-actions>\n", styles: [".title__closeBtn{top:0;right:-24px;float:right}.content__row{display:flex;align-items:flex-start;gap:16px}.content__row mat-form-field{flex:1 1 auto}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i3.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i3.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i4.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: i4.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "ngmodule", type: MatDialogModule }, { kind: "directive", type: i1.MatDialogClose, selector: "[mat-dialog-close], [matDialogClose]", inputs: ["aria-label", "type", "mat-dialog-close", "matDialogClose"], exportAs: ["matDialogClose"] }, { kind: "directive", type: i1.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: i1.MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }, { kind: "directive", type: i1.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i5.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i5.MatLabel, selector: "mat-label" }, { kind: "directive", type: i5.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i6.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i6.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatSlideToggleModule }, { kind: "component", type: i7$1.MatSlideToggle, selector: "mat-slide-toggle", inputs: ["name", "id", "labelPosition", "aria-label", "aria-labelledby", "aria-describedby", "required", "color", "disabled", "disableRipple", "tabIndex", "checked", "hideIcon", "disabledInteractive"], outputs: ["change", "toggleChange"], exportAs: ["matSlideToggle"] }, { kind: "ngmodule", type: GioFormSlideToggleModule }, { kind: "component", type: i6$1.GioFormSlideToggleComponent, selector: "gio-form-slide-toggle", inputs: ["appearance"] }, { kind: "component", type: i6$1.GioFormLabelComponent, selector: "gio-form-label" }, { kind: "directive", type: i6$1.GioFormSlideToggleDirective, selector: "[gioFormSlideToggle]" }, { kind: "ngmodule", type: GioBannerModule }, { kind: "component", type: i6$1.GioBannerInfoComponent, selector: "gio-banner-info" }, { kind: "ngmodule", type: GioIconsModule }, { kind: "component", type: i5$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }] }); }
485
+ getFlowName() {
486
+ const inputName = trim(this.flowFormGroup?.get('name')?.value);
487
+ return isEmpty(inputName) ? this.defaultFlowName : inputName;
488
+ }
489
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: GioPolicyStudioFlowNativeFormDialogComponent, deps: [{ token: i1.MatDialogRef }, { token: MAT_DIALOG_DATA }], target: i0.ɵɵFactoryTarget.Component }); }
490
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.4", type: GioPolicyStudioFlowNativeFormDialogComponent, isStandalone: true, selector: "gio-ps-flow-native-form-dialog", ngImport: i0, template: "<!--\n\n Copyright (C) 2015 The Gravitee team (http://gravitee.io)\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n\n-->\n<h2 mat-dialog-title class=\"title\">\n {{ mode === 'create' ? 'Create a new flow' : 'Edit flow' }}\n\n <button class=\"title__closeBtn\" mat-icon-button aria-label=\"Close dialog\" [mat-dialog-close]=\"false\">\n <mat-icon svgIcon=\"gio:cancel\"></mat-icon>\n </button>\n</h2>\n\n<mat-dialog-content *ngIf=\"flowFormGroup\" class=\"content\" [formGroup]=\"flowFormGroup\">\n <p>Flow allow you to apply different policies. Only one flow is allowed for a native API.</p>\n\n <div class=\"content__row\">\n <mat-form-field>\n <mat-label>Flow name</mat-label>\n <input matInput formControlName=\"name\" cdkFocusInitial />\n <mat-hint>Names will be automatically generated if left blank</mat-hint>\n </mat-form-field>\n </div>\n</mat-dialog-content>\n\n<mat-dialog-actions class=\"actions\" align=\"end\">\n <button class=\"actions__cancelBtn\" mat-button [mat-dialog-close]=\"false\">Cancel</button>\n <button class=\"actions__saveBtn\" color=\"primary\" mat-flat-button role=\"dialog\" (click)=\"onSubmit()\">\n {{ mode === 'create' ? 'Create' : 'Save' }}\n </button>\n</mat-dialog-actions>\n", styles: [".title__closeBtn{top:0;right:-24px;float:right}.content__row{display:flex;align-items:flex-start;gap:16px}.content__row mat-form-field{flex:1 1 auto}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i3.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i3.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i3.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i4.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: i4.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "ngmodule", type: MatDialogModule }, { kind: "directive", type: i1.MatDialogClose, selector: "[mat-dialog-close], [matDialogClose]", inputs: ["aria-label", "type", "mat-dialog-close", "matDialogClose"], exportAs: ["matDialogClose"] }, { kind: "directive", type: i1.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: i1.MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }, { kind: "directive", type: i1.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i5.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i5.MatLabel, selector: "mat-label" }, { kind: "directive", type: i5.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i7$1.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatSlideToggleModule }, { kind: "ngmodule", type: GioFormSlideToggleModule }, { kind: "ngmodule", type: GioBannerModule }, { kind: "ngmodule", type: GioIconsModule }, { kind: "component", type: i5$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: GioFormTagsInputModule }] }); }
535
491
  }
536
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: GioPolicyStudioFlowExecutionFormDialogComponent, decorators: [{
492
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: GioPolicyStudioFlowNativeFormDialogComponent, decorators: [{
537
493
  type: Component,
538
494
  args: [{ imports: [
539
495
  CommonModule,
@@ -542,11 +498,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImpor
542
498
  MatDialogModule,
543
499
  MatFormFieldModule,
544
500
  MatSelectModule,
501
+ MatInputModule,
545
502
  MatSlideToggleModule,
546
503
  GioFormSlideToggleModule,
547
504
  GioBannerModule,
548
505
  GioIconsModule,
549
- ], selector: 'gio-ps-flow-execution-form-dialog', template: "<!--\n\n Copyright (C) 2015 The Gravitee team (http://gravitee.io)\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n\n-->\n<h2 mat-dialog-title class=\"title\">\n Flow execution\n\n <button class=\"title__closeBtn\" mat-icon-button aria-label=\"Close dialog\" [mat-dialog-close]=\"\">\n <mat-icon svgIcon=\"gio:cancel\"></mat-icon>\n </button>\n</h2>\n\n<mat-dialog-content *ngIf=\"flowExecutionFormGroup\" class=\"content\" [formGroup]=\"flowExecutionFormGroup\">\n <div class=\"content__row\">\n <gio-banner-info>\n By default, flow selection is based on the operators defined in your flows, either when it \u201Cmatches with\u201D or \u201Cstarts with\u201D a path. You\n can choose the \"Best match\" option to select a flow from the closest path.\n </gio-banner-info>\n </div>\n <div class=\"content__row\">\n <mat-form-field>\n <mat-label>Default flow mode</mat-label>\n <mat-select formControlName=\"mode\">\n <mat-option value=\"BEST_MATCH\">Best Match</mat-option>\n <mat-option value=\"DEFAULT\">Default</mat-option>\n </mat-select>\n <mat-hint>Change how the flow selection is made</mat-hint>\n </mat-form-field>\n </div>\n\n <div class=\"content__row\">\n <gio-form-slide-toggle>\n <gio-form-label>Fail on flow mismatch</gio-form-label>\n Respond with an error when requests don\u2019t match any defined flow\n <mat-slide-toggle gioFormSlideToggle formControlName=\"matchRequired\"></mat-slide-toggle>\n </gio-form-slide-toggle>\n </div>\n</mat-dialog-content>\n\n<mat-dialog-actions class=\"actions\" align=\"end\">\n <button [disabled]=\"readOnly\" class=\"actions__cancelBtn\" mat-button [mat-dialog-close]=\"\">Cancel</button>\n <button [disabled]=\"readOnly\" class=\"actions__saveBtn\" color=\"primary\" mat-flat-button role=\"dialog\" (click)=\"onSubmit()\">Save</button>\n</mat-dialog-actions>\n", styles: [".title__closeBtn{top:0;right:-24px;float:right}.content__row{display:flex;align-items:flex-start;gap:16px}.content__row mat-form-field{flex:1 1 auto}\n"] }]
506
+ GioFormTagsInputModule,
507
+ ], selector: 'gio-ps-flow-native-form-dialog', template: "<!--\n\n Copyright (C) 2015 The Gravitee team (http://gravitee.io)\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n\n-->\n<h2 mat-dialog-title class=\"title\">\n {{ mode === 'create' ? 'Create a new flow' : 'Edit flow' }}\n\n <button class=\"title__closeBtn\" mat-icon-button aria-label=\"Close dialog\" [mat-dialog-close]=\"false\">\n <mat-icon svgIcon=\"gio:cancel\"></mat-icon>\n </button>\n</h2>\n\n<mat-dialog-content *ngIf=\"flowFormGroup\" class=\"content\" [formGroup]=\"flowFormGroup\">\n <p>Flow allow you to apply different policies. Only one flow is allowed for a native API.</p>\n\n <div class=\"content__row\">\n <mat-form-field>\n <mat-label>Flow name</mat-label>\n <input matInput formControlName=\"name\" cdkFocusInitial />\n <mat-hint>Names will be automatically generated if left blank</mat-hint>\n </mat-form-field>\n </div>\n</mat-dialog-content>\n\n<mat-dialog-actions class=\"actions\" align=\"end\">\n <button class=\"actions__cancelBtn\" mat-button [mat-dialog-close]=\"false\">Cancel</button>\n <button class=\"actions__saveBtn\" color=\"primary\" mat-flat-button role=\"dialog\" (click)=\"onSubmit()\">\n {{ mode === 'create' ? 'Create' : 'Save' }}\n </button>\n</mat-dialog-actions>\n", styles: [".title__closeBtn{top:0;right:-24px;float:right}.content__row{display:flex;align-items:flex-start;gap:16px}.content__row mat-form-field{flex:1 1 auto}\n"] }]
550
508
  }], ctorParameters: () => [{ type: i1.MatDialogRef }, { type: undefined, decorators: [{
551
509
  type: Inject,
552
510
  args: [MAT_DIALOG_DATA]
@@ -567,18 +525,38 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImpor
567
525
  * See the License for the specific language governing permissions and
568
526
  * limitations under the License.
569
527
  */
570
- class GioPolicyStudioFlowNativeFormDialogComponent {
528
+ const METHODS_AUTOCOMPLETE = ['ALL', ...HttpMethods];
529
+ class GioPolicyStudioFlowProxyFormDialogComponent {
571
530
  constructor(dialogRef, flowDialogData) {
572
531
  this.dialogRef = dialogRef;
573
532
  this.mode = 'create';
533
+ this.methods = METHODS_AUTOCOMPLETE;
574
534
  this.existingFlow = cloneDeep(flowDialogData?.flow);
575
535
  this.mode = this.existingFlow ? 'edit' : 'create';
536
+ const httpSelector = flowDialogData?.flow?.selectors?.find(s => s.type === 'HTTP');
537
+ const conditionSelector = flowDialogData?.flow?.selectors?.find(s => s.type === 'CONDITION');
576
538
  this.flowFormGroup = new UntypedFormGroup({
577
539
  name: new UntypedFormControl(flowDialogData?.flow?.name ?? ''),
540
+ pathOperator: new UntypedFormControl(httpSelector?.pathOperator ?? 'EQUALS'),
541
+ path: new UntypedFormControl(sanitizePathFormValue(httpSelector?.path)),
542
+ methods: new UntypedFormControl(sanitizeMethodFormValue(httpSelector?.methods)),
543
+ condition: new UntypedFormControl(conditionSelector?.condition ?? ''),
578
544
  });
579
- this.defaultFlowName = capitalize(flowDialogData.parentGroupName) + ' flow';
580
545
  }
581
546
  onSubmit() {
547
+ const httpSelectorToSave = {
548
+ type: 'HTTP',
549
+ path: sanitizePath(this.flowFormGroup?.get('path')?.value),
550
+ pathOperator: this.flowFormGroup?.get('pathOperator')?.value,
551
+ methods: sanitizeMethods(this.flowFormGroup?.get('methods')?.value),
552
+ };
553
+ const conditionValue = this.flowFormGroup?.get('condition')?.value;
554
+ const conditionSelectorToSave = conditionValue
555
+ ? {
556
+ type: 'CONDITION',
557
+ condition: conditionValue,
558
+ }
559
+ : undefined;
582
560
  const flowToSave = {
583
561
  // New id for new flow
584
562
  _id: uniqueId('flow_'),
@@ -587,21 +565,21 @@ class GioPolicyStudioFlowNativeFormDialogComponent {
587
565
  // Mark as changed
588
566
  _hasChanged: true,
589
567
  // Add changes
590
- name: this.getFlowName(),
568
+ name: this.flowFormGroup?.get('name')?.value,
569
+ selectors: conditionSelectorToSave ? [httpSelectorToSave, conditionSelectorToSave] : [httpSelectorToSave],
591
570
  enabled: this.existingFlow ? this.existingFlow.enabled : true,
592
571
  };
593
572
  this.dialogRef.close({
594
573
  ...flowToSave,
595
574
  });
596
575
  }
597
- getFlowName() {
598
- const inputName = trim(this.flowFormGroup?.get('name')?.value);
599
- return isEmpty(inputName) ? this.defaultFlowName : inputName;
576
+ tagValidationHook(tag, validationCb) {
577
+ validationCb(METHODS_AUTOCOMPLETE.map(m => `${m}`).includes(tag.toUpperCase()));
600
578
  }
601
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: GioPolicyStudioFlowNativeFormDialogComponent, deps: [{ token: i1.MatDialogRef }, { token: MAT_DIALOG_DATA }], target: i0.ɵɵFactoryTarget.Component }); }
602
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.4", type: GioPolicyStudioFlowNativeFormDialogComponent, isStandalone: true, selector: "gio-ps-flow-native-form-dialog", ngImport: i0, template: "<!--\n\n Copyright (C) 2015 The Gravitee team (http://gravitee.io)\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n\n-->\n<h2 mat-dialog-title class=\"title\">\n {{ mode === 'create' ? 'Create a new flow' : 'Edit flow' }}\n\n <button class=\"title__closeBtn\" mat-icon-button aria-label=\"Close dialog\" [mat-dialog-close]=\"false\">\n <mat-icon svgIcon=\"gio:cancel\"></mat-icon>\n </button>\n</h2>\n\n<mat-dialog-content *ngIf=\"flowFormGroup\" class=\"content\" [formGroup]=\"flowFormGroup\">\n <p>Flow allow you to apply different policies. Only one flow is allowed for a native API.</p>\n\n <div class=\"content__row\">\n <mat-form-field>\n <mat-label>Flow name</mat-label>\n <input matInput formControlName=\"name\" cdkFocusInitial />\n <mat-hint>Names will be automatically generated if left blank</mat-hint>\n </mat-form-field>\n </div>\n</mat-dialog-content>\n\n<mat-dialog-actions class=\"actions\" align=\"end\">\n <button class=\"actions__cancelBtn\" mat-button [mat-dialog-close]=\"false\">Cancel</button>\n <button class=\"actions__saveBtn\" color=\"primary\" mat-flat-button role=\"dialog\" (click)=\"onSubmit()\">\n {{ mode === 'create' ? 'Create' : 'Save' }}\n </button>\n</mat-dialog-actions>\n", styles: [".title__closeBtn{top:0;right:-24px;float:right}.content__row{display:flex;align-items:flex-start;gap:16px}.content__row mat-form-field{flex:1 1 auto}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i3.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i3.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i3.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i4.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: i4.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "ngmodule", type: MatDialogModule }, { kind: "directive", type: i1.MatDialogClose, selector: "[mat-dialog-close], [matDialogClose]", inputs: ["aria-label", "type", "mat-dialog-close", "matDialogClose"], exportAs: ["matDialogClose"] }, { kind: "directive", type: i1.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: i1.MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }, { kind: "directive", type: i1.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i5.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i5.MatLabel, selector: "mat-label" }, { kind: "directive", type: i5.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i7.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatSlideToggleModule }, { kind: "ngmodule", type: GioFormSlideToggleModule }, { kind: "ngmodule", type: GioBannerModule }, { kind: "ngmodule", type: GioIconsModule }, { kind: "component", type: i5$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: GioFormTagsInputModule }] }); }
579
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: GioPolicyStudioFlowProxyFormDialogComponent, deps: [{ token: i1.MatDialogRef }, { token: MAT_DIALOG_DATA }], target: i0.ɵɵFactoryTarget.Component }); }
580
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.4", type: GioPolicyStudioFlowProxyFormDialogComponent, isStandalone: true, selector: "gio-ps-flow-proxy-form-dialog", ngImport: i0, template: "<!--\n\n Copyright (C) 2015 The Gravitee team (http://gravitee.io)\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n\n-->\n<h2 mat-dialog-title class=\"title\">\n {{ mode === 'create' ? 'Create a new flow' : 'Edit flow' }}\n\n <button class=\"title__closeBtn\" mat-icon-button aria-label=\"Close dialog\" [mat-dialog-close]=\"false\">\n <mat-icon svgIcon=\"gio:cancel\"></mat-icon>\n </button>\n</h2>\n\n<mat-dialog-content *ngIf=\"flowFormGroup\" class=\"content\" [formGroup]=\"flowFormGroup\">\n <p>\n Flows allow you to apply different policies per HTTP path and/or method. For example you can reroute calls based on the URL specified.\n </p>\n\n <div class=\"content__row\">\n <mat-form-field>\n <mat-label>Flow name</mat-label>\n <input matInput formControlName=\"name\" cdkFocusInitial />\n <mat-hint>Names will be automatically generated with path and method if left blank</mat-hint>\n </mat-form-field>\n </div>\n <div class=\"content__row\">\n <mat-form-field>\n <mat-label>Operator</mat-label>\n <mat-select formControlName=\"pathOperator\">\n <mat-option value=\"EQUALS\">Equals</mat-option>\n <mat-option value=\"STARTS_WITH\">Starts with</mat-option>\n </mat-select>\n <mat-hint>Path operator</mat-hint>\n </mat-form-field>\n\n <mat-form-field>\n <mat-label>Path</mat-label>\n <span matTextPrefix>/&nbsp;</span>\n <input matInput formControlName=\"path\" />\n <mat-hint>Path</mat-hint>\n </mat-form-field>\n </div>\n\n <div class=\"content__row\">\n <mat-form-field>\n <mat-label>Methods for your flow</mat-label>\n <gio-form-tags-input\n formControlName=\"methods\"\n [autocompleteOptions]=\"methods\"\n [tagValidationHook]=\"tagValidationHook\"\n ></gio-form-tags-input>\n </mat-form-field>\n </div>\n\n <div class=\"content__row\">\n <mat-form-field>\n <mat-label>Condition</mat-label>\n <input matInput formControlName=\"condition\" />\n <mat-hint>Condition to execute the flow, supports Expression Language</mat-hint>\n </mat-form-field>\n </div>\n</mat-dialog-content>\n\n<mat-dialog-actions class=\"actions\" align=\"end\">\n <button class=\"actions__cancelBtn\" mat-button [mat-dialog-close]=\"false\">Cancel</button>\n <button class=\"actions__saveBtn\" color=\"primary\" mat-flat-button role=\"dialog\" (click)=\"onSubmit()\">\n {{ mode === 'create' ? 'Create' : 'Save' }}\n </button>\n</mat-dialog-actions>\n", styles: [".title__closeBtn{top:0;right:-24px;float:right}.content__row{display:flex;align-items:flex-start;gap:16px}.content__row mat-form-field{flex:1 1 auto}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i3.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i3.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i3.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i4.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: i4.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "ngmodule", type: MatDialogModule }, { kind: "directive", type: i1.MatDialogClose, selector: "[mat-dialog-close], [matDialogClose]", inputs: ["aria-label", "type", "mat-dialog-close", "matDialogClose"], exportAs: ["matDialogClose"] }, { kind: "directive", type: i1.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: i1.MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }, { kind: "directive", type: i1.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i5.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i5.MatLabel, selector: "mat-label" }, { kind: "directive", type: i5.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "directive", type: i5.MatPrefix, selector: "[matPrefix], [matIconPrefix], [matTextPrefix]", inputs: ["matTextPrefix"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i6.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i6.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i7$1.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatSlideToggleModule }, { kind: "ngmodule", type: GioFormSlideToggleModule }, { kind: "ngmodule", type: GioBannerModule }, { kind: "ngmodule", type: GioIconsModule }, { kind: "component", type: i5$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: GioFormTagsInputModule }, { kind: "component", type: i6$1.GioFormTagsInputComponent, selector: "gio-form-tags-input", inputs: ["aria-label", "addOnBlur", "tagValidationHook", "autocompleteOptions", "displayValueWith", "useAutocompleteOptionValueOnly", "placeholder", "required", "disabled"] }] }); }
603
581
  }
604
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: GioPolicyStudioFlowNativeFormDialogComponent, decorators: [{
582
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: GioPolicyStudioFlowProxyFormDialogComponent, decorators: [{
605
583
  type: Component,
606
584
  args: [{ imports: [
607
585
  CommonModule,
@@ -616,11 +594,33 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImpor
616
594
  GioBannerModule,
617
595
  GioIconsModule,
618
596
  GioFormTagsInputModule,
619
- ], selector: 'gio-ps-flow-native-form-dialog', template: "<!--\n\n Copyright (C) 2015 The Gravitee team (http://gravitee.io)\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n\n-->\n<h2 mat-dialog-title class=\"title\">\n {{ mode === 'create' ? 'Create a new flow' : 'Edit flow' }}\n\n <button class=\"title__closeBtn\" mat-icon-button aria-label=\"Close dialog\" [mat-dialog-close]=\"false\">\n <mat-icon svgIcon=\"gio:cancel\"></mat-icon>\n </button>\n</h2>\n\n<mat-dialog-content *ngIf=\"flowFormGroup\" class=\"content\" [formGroup]=\"flowFormGroup\">\n <p>Flow allow you to apply different policies. Only one flow is allowed for a native API.</p>\n\n <div class=\"content__row\">\n <mat-form-field>\n <mat-label>Flow name</mat-label>\n <input matInput formControlName=\"name\" cdkFocusInitial />\n <mat-hint>Names will be automatically generated if left blank</mat-hint>\n </mat-form-field>\n </div>\n</mat-dialog-content>\n\n<mat-dialog-actions class=\"actions\" align=\"end\">\n <button class=\"actions__cancelBtn\" mat-button [mat-dialog-close]=\"false\">Cancel</button>\n <button class=\"actions__saveBtn\" color=\"primary\" mat-flat-button role=\"dialog\" (click)=\"onSubmit()\">\n {{ mode === 'create' ? 'Create' : 'Save' }}\n </button>\n</mat-dialog-actions>\n", styles: [".title__closeBtn{top:0;right:-24px;float:right}.content__row{display:flex;align-items:flex-start;gap:16px}.content__row mat-form-field{flex:1 1 auto}\n"] }]
597
+ ], selector: 'gio-ps-flow-proxy-form-dialog', template: "<!--\n\n Copyright (C) 2015 The Gravitee team (http://gravitee.io)\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n\n-->\n<h2 mat-dialog-title class=\"title\">\n {{ mode === 'create' ? 'Create a new flow' : 'Edit flow' }}\n\n <button class=\"title__closeBtn\" mat-icon-button aria-label=\"Close dialog\" [mat-dialog-close]=\"false\">\n <mat-icon svgIcon=\"gio:cancel\"></mat-icon>\n </button>\n</h2>\n\n<mat-dialog-content *ngIf=\"flowFormGroup\" class=\"content\" [formGroup]=\"flowFormGroup\">\n <p>\n Flows allow you to apply different policies per HTTP path and/or method. For example you can reroute calls based on the URL specified.\n </p>\n\n <div class=\"content__row\">\n <mat-form-field>\n <mat-label>Flow name</mat-label>\n <input matInput formControlName=\"name\" cdkFocusInitial />\n <mat-hint>Names will be automatically generated with path and method if left blank</mat-hint>\n </mat-form-field>\n </div>\n <div class=\"content__row\">\n <mat-form-field>\n <mat-label>Operator</mat-label>\n <mat-select formControlName=\"pathOperator\">\n <mat-option value=\"EQUALS\">Equals</mat-option>\n <mat-option value=\"STARTS_WITH\">Starts with</mat-option>\n </mat-select>\n <mat-hint>Path operator</mat-hint>\n </mat-form-field>\n\n <mat-form-field>\n <mat-label>Path</mat-label>\n <span matTextPrefix>/&nbsp;</span>\n <input matInput formControlName=\"path\" />\n <mat-hint>Path</mat-hint>\n </mat-form-field>\n </div>\n\n <div class=\"content__row\">\n <mat-form-field>\n <mat-label>Methods for your flow</mat-label>\n <gio-form-tags-input\n formControlName=\"methods\"\n [autocompleteOptions]=\"methods\"\n [tagValidationHook]=\"tagValidationHook\"\n ></gio-form-tags-input>\n </mat-form-field>\n </div>\n\n <div class=\"content__row\">\n <mat-form-field>\n <mat-label>Condition</mat-label>\n <input matInput formControlName=\"condition\" />\n <mat-hint>Condition to execute the flow, supports Expression Language</mat-hint>\n </mat-form-field>\n </div>\n</mat-dialog-content>\n\n<mat-dialog-actions class=\"actions\" align=\"end\">\n <button class=\"actions__cancelBtn\" mat-button [mat-dialog-close]=\"false\">Cancel</button>\n <button class=\"actions__saveBtn\" color=\"primary\" mat-flat-button role=\"dialog\" (click)=\"onSubmit()\">\n {{ mode === 'create' ? 'Create' : 'Save' }}\n </button>\n</mat-dialog-actions>\n", styles: [".title__closeBtn{top:0;right:-24px;float:right}.content__row{display:flex;align-items:flex-start;gap:16px}.content__row mat-form-field{flex:1 1 auto}\n"] }]
620
598
  }], ctorParameters: () => [{ type: i1.MatDialogRef }, { type: undefined, decorators: [{
621
599
  type: Inject,
622
600
  args: [MAT_DIALOG_DATA]
623
601
  }] }] });
602
+ const sanitizeMethods = (value) => {
603
+ if (!value || value.find(m => m === 'ALL'))
604
+ return [];
605
+ return value;
606
+ };
607
+ const sanitizeMethodFormValue = (methods) => {
608
+ if (!methods || methods.length === 0)
609
+ return ['ALL'];
610
+ return methods;
611
+ };
612
+ const sanitizePath = (path) => {
613
+ if (!path || !path.startsWith('/')) {
614
+ return `/${path}`;
615
+ }
616
+ return path;
617
+ };
618
+ const sanitizePathFormValue = (path) => {
619
+ if (path && path.startsWith('/')) {
620
+ return path.substring(1);
621
+ }
622
+ return path ?? '';
623
+ };
624
624
 
625
625
  /*
626
626
  * Copyright (C) 2022 The Gravitee team (http://gravitee.io)
@@ -651,7 +651,15 @@ class GioPolicyStudioFlowsMenuComponent {
651
651
  this.flowExecutionChange = new EventEmitter();
652
652
  this.deleteFlow = new EventEmitter();
653
653
  this.flowGroupMenuItems = [];
654
+ this.searchControl = new FormControl('');
655
+ this.filteredFlowGroupMenuItems = [];
656
+ this.unsubscribe$ = new Subject();
654
657
  this.enterPredicate = () => true;
658
+ this.searchControl.valueChanges
659
+ .pipe(debounceTime(300), startWith(''), distinctUntilChanged(), tap(searchTerm => {
660
+ this.applyFilter(searchTerm || '');
661
+ }), takeUntil(this.unsubscribe$))
662
+ .subscribe();
655
663
  }
656
664
  ngOnChanges(changes) {
657
665
  if (changes.flowsGroups || changes.selectedFlowId) {
@@ -725,6 +733,54 @@ class GioPolicyStudioFlowsMenuComponent {
725
733
  return true;
726
734
  };
727
735
  }
736
+ this.applyFilter(this.searchControl.value || '');
737
+ }
738
+ ngOnDestroy() {
739
+ this.unsubscribe$.next();
740
+ this.unsubscribe$.complete();
741
+ }
742
+ applyFilter(searchTerm) {
743
+ const term = searchTerm.toLowerCase();
744
+ if (!term) {
745
+ this.filteredFlowGroupMenuItems = [...this.flowGroupMenuItems];
746
+ return;
747
+ }
748
+ this.filteredFlowGroupMenuItems = this.flowGroupMenuItems
749
+ .map(group => {
750
+ const filteredFlows = group?.flows?.filter(flow => {
751
+ return ((group.name && group.name?.toLowerCase().includes(term)) ||
752
+ (flow.name && flow.name?.toLowerCase().includes(term)) ||
753
+ (flow.pathOrChannelLabel && flow.pathOrChannelLabel?.toLowerCase().includes(term)) ||
754
+ (flow.selectors && flow.selectors?.some(selector => this.selectorMatches(selector, term))) ||
755
+ (flow.badges && flow.badges?.some(badges => badges.label?.toLowerCase().includes(term))));
756
+ });
757
+ return { ...group, flows: filteredFlows };
758
+ })
759
+ .filter(group => group.flows.length > 0);
760
+ }
761
+ resetSearchTerm() {
762
+ this.searchControl.setValue('');
763
+ this.applyFilter('');
764
+ }
765
+ selectorMatches(selector, term) {
766
+ const type = selector.type;
767
+ if (type === 'HTTP') {
768
+ const httpSelector = selector;
769
+ if (httpSelector.path?.toLowerCase().includes(term))
770
+ return true;
771
+ if (httpSelector.methods?.some(method => method.toLowerCase().includes(term))) {
772
+ return true;
773
+ }
774
+ }
775
+ if (type === 'CHANNEL') {
776
+ const channelSelector = selector;
777
+ if (channelSelector.channel?.toLowerCase().includes(term))
778
+ return true;
779
+ if (channelSelector.operations?.some(op => op.toLowerCase().includes(term))) {
780
+ return true;
781
+ }
782
+ }
783
+ return false;
728
784
  }
729
785
  selectFlow(groupId, flowId) {
730
786
  const flow = this.flowsGroups.find(fg => fg._id === groupId)?.flows.find(f => f._id === flowId);
@@ -927,11 +983,22 @@ class GioPolicyStudioFlowsMenuComponent {
927
983
  this.selectedFlowIdChange.emit(duplicatedFlow._id);
928
984
  }
929
985
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: GioPolicyStudioFlowsMenuComponent, deps: [{ token: i1.MatDialog }], target: i0.ɵɵFactoryTarget.Component }); }
930
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.4", type: GioPolicyStudioFlowsMenuComponent, isStandalone: true, selector: "gio-ps-flows-menu", inputs: { readOnly: "readOnly", loading: "loading", apiType: "apiType", flowExecution: "flowExecution", flowsGroups: "flowsGroups", selectedFlowId: "selectedFlowId", entrypoints: "entrypoints", entrypointsInfo: "entrypointsInfo" }, outputs: { selectedFlowIdChange: "selectedFlowIdChange", flowsGroupsChange: "flowsGroupsChange", flowExecutionChange: "flowExecutionChange", deleteFlow: "deleteFlow" }, usesOnChanges: true, ngImport: i0, template: "<!--\n\n Copyright (C) 2023 The Gravitee team (http://gravitee.io)\n \n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n \n http://www.apache.org/licenses/LICENSE-2.0\n \n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n\n-->\n\n<div class=\"header\">\n <div class=\"header__label\">\n Flows <mat-icon svgIcon=\"gio:info\" matTooltip=\"Flows allow you to apply different policies on your API event phases\"></mat-icon>\n </div>\n @if (apiType !== 'NATIVE') {\n <div class=\"header__configBtn\">\n <button class=\"header__configBtn_edit\" mat-stroked-button [disabled]=\"loading\" (click)=\"onConfigureExecution(flowExecution)\">\n <mat-icon [svgIcon]=\"readOnly ? 'gio:eye-empty' : 'gio:settings'\"></mat-icon>\n </button>\n </div>\n }\n</div>\n\n<div class=\"list\" *ngIf=\"!loading; else loadingList\" cdkDropListGroup>\n <div\n *ngFor=\"let flowsGroup of flowGroupMenuItems\"\n class=\"list__flowsGroup\"\n cdkDropList\n [cdkDropListData]=\"flowsGroup\"\n [cdkDropListEnterPredicate]=\"enterPredicate\"\n (cdkDropListDropped)=\"onDropFlow($event)\"\n >\n <div class=\"list__flowsGroup__header\">\n <div class=\"list__flowsGroup__header__label\">\n <span>{{ (flowsGroup._isPlan ? 'Plan: ' : '') + flowsGroup.name }}</span>\n </div>\n <div class=\"list__flowsGroup__header__addBtn\">\n @if (apiType === 'NATIVE') {\n <span [matTooltipDisabled]=\"flowsGroup.flows.length < 1\" matTooltip=\"Only one flow is allowed for a native API\">\n <button mat-button [disabled]=\"readOnly || flowsGroup.flows.length > 0\" (click)=\"onAddFlow(flowsGroup)\">\n <mat-icon svgIcon=\"gio:plus\" matTooltip=\"New flow\"></mat-icon>\n </button>\n </span>\n } @else {\n <button mat-button [disabled]=\"readOnly\" (click)=\"onAddFlow(flowsGroup)\">\n <mat-icon svgIcon=\"gio:plus\" matTooltip=\"New flow\"></mat-icon>\n </button>\n }\n </div>\n </div>\n\n <div class=\"list__flowsGroup__flows\">\n @for (flow of flowsGroup.flows; track flow._id) {\n <div\n class=\"list__flowsGroup__flows__flow\"\n [class.selected]=\"flow.selected\"\n [class.disabled]=\"!flow.enabled\"\n (click)=\"selectFlow(flowsGroup._id, flow._id)\"\n (mouseout)=\"flow.mouseOver = false\"\n (mouseover)=\"flow.mouseOver = true\"\n cdkDrag\n >\n <div class=\"list__flowsGroup__flows__flow__left\">\n <div *ngIf=\"flow.name\" class=\"list__flowsGroup__flows__flow__left__name\" [attr.title]=\"flow.name\">\n {{ flow.name }}\n </div>\n @if (apiType !== 'NATIVE') {\n <div class=\"list__flowsGroup__flows__flow__left__infos\">\n <div class=\"list__flowsGroup__flows__flow__left__infos__badges\">\n <span\n *ngFor=\"let badge of flow.badges\"\n class=\"list__flowsGroup__flows__flow__left__infos__badges__badge\"\n [ngClass]=\"badge.class\"\n >{{ badge.label }}</span\n >\n </div>\n <div class=\"list__flowsGroup__flows__flow__left__infos__pathOrChannelLabel\">\n <span *ngIf=\"flow.pathOrChannelLabel; else emptyPathOrChannelLabel\" [attr.title]=\"flow.pathOrChannelLabel\">{{\n flow.pathOrChannelLabel\n }}</span>\n <ng-template #emptyPathOrChannelLabel>\n <em>Empty</em>\n </ng-template>\n </div>\n\n <span\n *ngIf=\"flow.hasCondition\"\n class=\"list__flowsGroup__flows__flow__left__infos__conditionBadge gio-badge-neutral\"\n matTooltip=\"Conditioned\"\n ><mat-icon svgIcon=\"gio:if\"></mat-icon\n ></span>\n </div>\n }\n </div>\n <div class=\"list__flowsGroup__flows__flow__right\">\n <button\n class=\"list__flowsGroup__flows__flow__right__name__menu\"\n mat-button\n [disabled]=\"readOnly\"\n [matMenuTriggerFor]=\"flowMenu\"\n (click)=\"$event.stopPropagation()\"\n >\n <mat-icon svgIcon=\"gio:more-vertical\"></mat-icon>\n </button>\n <mat-menu #flowMenu=\"matMenu\">\n <button [disabled]=\"readOnly\" mat-menu-item (click)=\"onDisableFlow(flow._id)\">\n <mat-icon [svgIcon]=\"flow.enabled ? 'gio:prohibition' : 'gio:check-circled-outline'\"></mat-icon>\n <span>{{ flow.enabled ? 'Disable' : 'Enable' }}</span>\n </button>\n <button mat-menu-item (click)=\"onEditFlow(flow._id)\"><mat-icon svgIcon=\"gio:edit-pencil\"></mat-icon> Edit</button>\n <button mat-menu-item (click)=\"onDeleteFlow(flow._id)\"><mat-icon svgIcon=\"gio:trash\"></mat-icon> Delete</button>\n @if (apiType !== 'NATIVE') {\n <button mat-menu-item (click)=\"onDuplicateFlow(flowsGroup._id, flow._id)\">\n <mat-icon svgIcon=\"gio:copy\"></mat-icon> Duplicate\n </button>\n }\n </mat-menu>\n </div>\n </div>\n }\n </div>\n </div>\n</div>\n\n<ng-template #loadingList>\n <div class=\"loadingList\">\n <gio-loader></gio-loader>\n </div>\n</ng-template>\n", styles: ["@charset \"UTF-8\";.gio-top-bar-menu .gio-badge-accent{background-color:var(--gio-oem-palette--active, #ffc2ac);color:var(--gio-oem-palette--active-contrast, #1e1b1b)}:host{display:flex;height:100%;max-height:100%;flex-direction:column;padding-top:16px}.header{display:flex;align-items:center;padding:0 16px;margin-bottom:16px}.header__label{font-family:Kanit,Helvetica Neue,sans-serif;font-size:16px;font-weight:500;letter-spacing:.4px;line-height:24px;display:flex;flex:1 1 auto;align-items:center;margin-bottom:0;gap:8px}.header__configBtn{margin-left:8px}.list{padding:0 16px;overflow-y:overlay}.list__flowsGroup{display:flex;flex-direction:column;padding-bottom:8px;gap:8px}.list__flowsGroup__header{display:flex;align-items:center;padding:8px 0 0;border-radius:8px}.list__flowsGroup__header__label{font-size:14px;font-weight:700;line-height:20px;font-family:Manrope,sans-serif;letter-spacing:.4px;display:flex;overflow:hidden;flex:1 1 auto;align-items:center;gap:8px}.list__flowsGroup__header__label>mat-icon{width:22px;height:22px;flex:0 0 auto}.list__flowsGroup__header__label>span{display:-webkit-box;overflow:hidden;flex:1 1 auto;-webkit-box-orient:vertical;-webkit-line-clamp:2}.list__flowsGroup__header__addBtn{margin-left:8px}.list__flowsGroup__flows{display:flex;flex-direction:column;gap:8px}.list__flowsGroup__flows__flow{display:flex;overflow:hidden;height:68px;flex-direction:row;align-items:center;justify-content:space-between;padding:7px;border:1px solid #b2aaa9;border-radius:8px;background-color:#fff}.list__flowsGroup__flows__flow.disabled{border:1px solid rgba(178,170,169,0);background-color:#f7f7f8cc;text-decoration:line-through}.list__flowsGroup__flows__flow:hover,.list__flowsGroup__flows__flow.selected{padding:6px;border:2px solid #ffa685;cursor:pointer}.list__flowsGroup__flows__flow__left{display:flex;overflow:hidden;flex:1 1 auto;flex-direction:column;gap:8px}.list__flowsGroup__flows__flow__left__name{overflow:hidden;padding-left:4px;text-overflow:ellipsis;white-space:nowrap}.list__flowsGroup__flows__flow__left__infos{display:flex;align-items:center}.list__flowsGroup__flows__flow__left__infos__badges{flex:0 0 auto}.list__flowsGroup__flows__flow__left__infos__badges__badge{width:auto}.list__flowsGroup__flows__flow__left__infos__pathOrChannelLabel{overflow:hidden;flex:1 1 auto;direction:rtl;text-align:left;text-overflow:ellipsis;white-space:nowrap}.list__flowsGroup__flows__flow__left__infos__pathOrChannelLabel span{direction:ltr;unicode-bidi:bidi-override}.list__flowsGroup__flows__flow__left__infos__conditionBadge{flex:0 0 auto}.list__flowsGroup.cdk-drop-list-dragging{pointer-events:none}.list__flowsGroup .cdk-drag-preview{box-sizing:border-box;border-radius:4px;box-shadow:0 5px 5px -3px #0003,0 8px 10px 1px #00000024,0 3px 14px 2px #0000001f}.list__flowsGroup .cdk-drag-placeholder *{opacity:0}.list__flowsGroup .cdk-drag-animating{transition:transform .25s cubic-bezier(0,0,.2,1)}.list__flowsGroup.cdk-drop-list-dragging .list__flowsGroup__flows__flow:not(.cdk-drag-placeholder){transition:transform .25s cubic-bezier(0,0,.2,1)}.loadingList{display:flex;height:100%;flex-direction:column;align-items:center;justify-content:center}\n"], dependencies: [{ kind: "ngmodule", type: GioIconsModule }, { kind: "component", type: i5$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i3$1.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i4.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: GioLoaderModule }, { kind: "component", type: i6$1.GioLoaderComponent, selector: "gio-loader" }, { kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i7$2.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i7$2.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i7$2.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "ngmodule", type: DragDropModule }, { kind: "directive", type: i8.CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep", "cdkDropListElementContainer"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: i8.CdkDropListGroup, selector: "[cdkDropListGroup]", inputs: ["cdkDropListGroupDisabled"], exportAs: ["cdkDropListGroup"] }, { kind: "directive", type: i8.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }] }); }
986
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.4", type: GioPolicyStudioFlowsMenuComponent, isStandalone: true, selector: "gio-ps-flows-menu", inputs: { readOnly: "readOnly", loading: "loading", apiType: "apiType", flowExecution: "flowExecution", flowsGroups: "flowsGroups", selectedFlowId: "selectedFlowId", entrypoints: "entrypoints", entrypointsInfo: "entrypointsInfo" }, outputs: { selectedFlowIdChange: "selectedFlowIdChange", flowsGroupsChange: "flowsGroupsChange", flowExecutionChange: "flowExecutionChange", deleteFlow: "deleteFlow" }, usesOnChanges: true, ngImport: i0, template: "<!--\n\n Copyright (C) 2023 The Gravitee team (http://gravitee.io)\n \n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n \n http://www.apache.org/licenses/LICENSE-2.0\n \n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n\n-->\n\n<div class=\"header\">\n <div class=\"header__label\">\n Flows <mat-icon svgIcon=\"gio:info\" matTooltip=\"Flows allow you to apply different policies on your API event phases\"></mat-icon>\n </div>\n @if (apiType !== 'NATIVE') {\n <div class=\"header__configBtn\">\n <button class=\"header__configBtn_edit\" mat-stroked-button [disabled]=\"loading\" (click)=\"onConfigureExecution(flowExecution)\">\n <mat-icon [svgIcon]=\"readOnly ? 'gio:eye-empty' : 'gio:settings'\"></mat-icon>\n </button>\n </div>\n }\n</div>\n<div class=\"searchBar\" *ngIf=\"!loading\">\n <mat-form-field class=\"searchBar__input\">\n <mat-icon matPrefix>search</mat-icon>\n <input matInput placeholder=\"Search by name, path, or group...\" [formControl]=\"searchControl\" />\n <button *ngIf=\"searchControl.value\" matSuffix mat-icon-button aria-label=\"Clear\" (click)=\"resetSearchTerm()\">\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n</div>\n\n<div class=\"list\" *ngIf=\"!loading; else loadingList\" cdkDropListGroup>\n <div\n *ngFor=\"let flowsGroup of filteredFlowGroupMenuItems\"\n class=\"list__flowsGroup\"\n cdkDropList\n [cdkDropListData]=\"flowsGroup\"\n [cdkDropListEnterPredicate]=\"enterPredicate\"\n (cdkDropListDropped)=\"onDropFlow($event)\"\n >\n <div class=\"list__flowsGroup__header\">\n <div class=\"list__flowsGroup__header__label\">\n <span>{{ (flowsGroup._isPlan ? 'Plan: ' : '') + flowsGroup.name }}</span>\n </div>\n <div class=\"list__flowsGroup__header__addBtn\">\n @if (apiType === 'NATIVE') {\n <span [matTooltipDisabled]=\"flowsGroup.flows.length < 1\" matTooltip=\"Only one flow is allowed for a native API\">\n <button mat-button [disabled]=\"readOnly || flowsGroup.flows.length > 0\" (click)=\"onAddFlow(flowsGroup)\">\n <mat-icon svgIcon=\"gio:plus\" matTooltip=\"New flow\"></mat-icon>\n </button>\n </span>\n } @else {\n <button mat-button [disabled]=\"readOnly\" (click)=\"onAddFlow(flowsGroup)\">\n <mat-icon svgIcon=\"gio:plus\" matTooltip=\"New flow\"></mat-icon>\n </button>\n }\n </div>\n </div>\n\n <div class=\"list__flowsGroup__flows\">\n <ng-container *ngIf=\"flowsGroup.flows.length > 0; else noFlows\">\n @for (flow of flowsGroup.flows; track flow._id) {\n <div\n class=\"list__flowsGroup__flows__flow\"\n [class.selected]=\"flow.selected\"\n [class.disabled]=\"!flow.enabled\"\n (click)=\"selectFlow(flowsGroup._id, flow._id)\"\n (mouseout)=\"flow.mouseOver = false\"\n (mouseover)=\"flow.mouseOver = true\"\n cdkDrag\n >\n <div class=\"list__flowsGroup__flows__flow__left\">\n <div *ngIf=\"flow.name\" class=\"list__flowsGroup__flows__flow__left__name\" [attr.title]=\"flow.name\">\n {{ flow.name }}\n </div>\n @if (apiType !== 'NATIVE') {\n <div class=\"list__flowsGroup__flows__flow__left__infos\">\n <div class=\"list__flowsGroup__flows__flow__left__infos__badges\">\n <span\n *ngFor=\"let badge of flow.badges\"\n class=\"list__flowsGroup__flows__flow__left__infos__badges__badge\"\n [ngClass]=\"badge.class\"\n >{{ badge.label }}</span\n >\n </div>\n <div class=\"list__flowsGroup__flows__flow__left__infos__pathOrChannelLabel\">\n <span *ngIf=\"flow.pathOrChannelLabel; else emptyPathOrChannelLabel\" [attr.title]=\"flow.pathOrChannelLabel\">{{\n flow.pathOrChannelLabel\n }}</span>\n <ng-template #emptyPathOrChannelLabel>\n <em>Empty</em>\n </ng-template>\n </div>\n\n <span\n *ngIf=\"flow.hasCondition\"\n class=\"list__flowsGroup__flows__flow__left__infos__conditionBadge gio-badge-neutral\"\n matTooltip=\"Conditioned\"\n ><mat-icon svgIcon=\"gio:if\"></mat-icon\n ></span>\n </div>\n }\n </div>\n <div class=\"list__flowsGroup__flows__flow__right\">\n <button\n class=\"list__flowsGroup__flows__flow__right__name__menu\"\n mat-button\n [disabled]=\"readOnly\"\n [matMenuTriggerFor]=\"flowMenu\"\n (click)=\"$event.stopPropagation()\"\n >\n <mat-icon svgIcon=\"gio:more-vertical\"></mat-icon>\n </button>\n <mat-menu #flowMenu=\"matMenu\">\n <button [disabled]=\"readOnly\" mat-menu-item (click)=\"onDisableFlow(flow._id)\">\n <mat-icon [svgIcon]=\"flow.enabled ? 'gio:prohibition' : 'gio:check-circled-outline'\"></mat-icon>\n <span>{{ flow.enabled ? 'Disable' : 'Enable' }}</span>\n </button>\n <button mat-menu-item (click)=\"onEditFlow(flow._id)\"><mat-icon svgIcon=\"gio:edit-pencil\"></mat-icon> Edit</button>\n <button mat-menu-item (click)=\"onDeleteFlow(flow._id)\"><mat-icon svgIcon=\"gio:trash\"></mat-icon> Delete</button>\n @if (apiType !== 'NATIVE') {\n <button mat-menu-item (click)=\"onDuplicateFlow(flowsGroup._id, flow._id)\">\n <mat-icon svgIcon=\"gio:copy\"></mat-icon> Duplicate\n </button>\n }\n </mat-menu>\n </div>\n </div>\n }\n </ng-container>\n <ng-template #noFlows>\n <div class=\"list__flowsGroup__no-flows\">No flows yet</div>\n </ng-template>\n </div>\n </div>\n</div>\n\n<ng-template #loadingList>\n <div class=\"loadingList\">\n <gio-loader></gio-loader>\n </div>\n</ng-template>\n", styles: ["@charset \"UTF-8\";.gio-top-bar-menu .gio-badge-accent{background-color:var(--gio-oem-palette--active, #ffc2ac);color:var(--gio-oem-palette--active-contrast, #1e1b1b)}:host{display:flex;height:100%;max-height:100%;flex-direction:column;padding-top:16px}.header{display:flex;align-items:center;padding:0 16px;margin-bottom:14px}.header__label{font-family:Kanit,Helvetica Neue,sans-serif;font-size:16px;font-weight:500;letter-spacing:.4px;line-height:24px;display:flex;flex:1 1 auto;align-items:center;margin-bottom:0;gap:8px}.header__configBtn{margin-left:8px}.searchBar{display:flex;padding:0 16px}.searchBar__input{flex:1 1 auto}.list{padding:0 16px;overflow-y:overlay}.list__flowsGroup{display:flex;flex-direction:column;padding-bottom:8px;gap:8px}.list__flowsGroup__header{display:flex;align-items:center;padding:8px 0 0;border-radius:8px}.list__flowsGroup__header__label{font-size:14px;font-weight:700;line-height:20px;font-family:Manrope,sans-serif;letter-spacing:.4px;display:flex;overflow:hidden;flex:1 1 auto;align-items:center;gap:8px}.list__flowsGroup__header__label>mat-icon{width:22px;height:22px;flex:0 0 auto}.list__flowsGroup__header__label>span{display:-webkit-box;overflow:hidden;flex:1 1 auto;-webkit-box-orient:vertical;-webkit-line-clamp:2}.list__flowsGroup__header__addBtn{margin-left:8px}.list__flowsGroup__flows{display:flex;flex-direction:column;gap:8px}.list__flowsGroup__flows__flow{display:flex;overflow:hidden;height:68px;flex-direction:row;align-items:center;justify-content:space-between;padding:7px;border:1px solid #b2aaa9;border-radius:8px;background-color:#fff}.list__flowsGroup__flows__flow.disabled{border:1px solid rgba(178,170,169,0);background-color:#f7f7f8cc;text-decoration:line-through}.list__flowsGroup__flows__flow:hover,.list__flowsGroup__flows__flow.selected{padding:6px;border:2px solid #ffa685;cursor:pointer}.list__flowsGroup__flows__flow__left{display:flex;overflow:hidden;flex:1 1 auto;flex-direction:column;gap:8px}.list__flowsGroup__flows__flow__left__name{overflow:hidden;padding-left:4px;text-overflow:ellipsis;white-space:nowrap}.list__flowsGroup__flows__flow__left__infos{display:flex;align-items:center}.list__flowsGroup__flows__flow__left__infos__badges{flex:0 0 auto}.list__flowsGroup__flows__flow__left__infos__badges__badge{width:auto}.list__flowsGroup__flows__flow__left__infos__pathOrChannelLabel{overflow:hidden;flex:1 1 auto;direction:rtl;text-align:left;text-overflow:ellipsis;white-space:nowrap}.list__flowsGroup__flows__flow__left__infos__pathOrChannelLabel span{direction:ltr;unicode-bidi:bidi-override}.list__flowsGroup__flows__flow__left__infos__conditionBadge{flex:0 0 auto}.list__flowsGroup__no-flows{font-style:italic}.list__flowsGroup.cdk-drop-list-dragging{pointer-events:none}.list__flowsGroup .cdk-drag-preview{box-sizing:border-box;border-radius:4px;box-shadow:0 5px 5px -3px #0003,0 8px 10px 1px #00000024,0 3px 14px 2px #0000001f}.list__flowsGroup .cdk-drag-placeholder *{opacity:0}.list__flowsGroup .cdk-drag-animating{transition:transform .25s cubic-bezier(0,0,.2,1)}.list__flowsGroup.cdk-drop-list-dragging .list__flowsGroup__flows__flow:not(.cdk-drag-placeholder){transition:transform .25s cubic-bezier(0,0,.2,1)}.loadingList{display:flex;height:100%;flex-direction:column;align-items:center;justify-content:center}\n"], dependencies: [{ kind: "ngmodule", type: GioIconsModule }, { kind: "component", type: i5$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i3$1.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i4.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: i4.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: GioLoaderModule }, { kind: "component", type: i6$1.GioLoaderComponent, selector: "gio-loader" }, { kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i7$2.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i7$2.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i7$2.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "ngmodule", type: DragDropModule }, { kind: "directive", type: i8.CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep", "cdkDropListElementContainer"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: i8.CdkDropListGroup, selector: "[cdkDropListGroup]", inputs: ["cdkDropListGroupDisabled"], exportAs: ["cdkDropListGroup"] }, { kind: "directive", type: i8.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i7$1.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "component", type: i5.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i5.MatPrefix, selector: "[matPrefix], [matIconPrefix], [matTextPrefix]", inputs: ["matTextPrefix"] }, { kind: "directive", type: i5.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i3.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatFormFieldModule }] }); }
931
987
  }
932
988
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: GioPolicyStudioFlowsMenuComponent, decorators: [{
933
989
  type: Component,
934
- args: [{ imports: [GioIconsModule, MatTooltipModule, MatButtonModule, CommonModule, GioLoaderModule, MatMenuModule, DragDropModule], selector: 'gio-ps-flows-menu', template: "<!--\n\n Copyright (C) 2023 The Gravitee team (http://gravitee.io)\n \n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n \n http://www.apache.org/licenses/LICENSE-2.0\n \n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n\n-->\n\n<div class=\"header\">\n <div class=\"header__label\">\n Flows <mat-icon svgIcon=\"gio:info\" matTooltip=\"Flows allow you to apply different policies on your API event phases\"></mat-icon>\n </div>\n @if (apiType !== 'NATIVE') {\n <div class=\"header__configBtn\">\n <button class=\"header__configBtn_edit\" mat-stroked-button [disabled]=\"loading\" (click)=\"onConfigureExecution(flowExecution)\">\n <mat-icon [svgIcon]=\"readOnly ? 'gio:eye-empty' : 'gio:settings'\"></mat-icon>\n </button>\n </div>\n }\n</div>\n\n<div class=\"list\" *ngIf=\"!loading; else loadingList\" cdkDropListGroup>\n <div\n *ngFor=\"let flowsGroup of flowGroupMenuItems\"\n class=\"list__flowsGroup\"\n cdkDropList\n [cdkDropListData]=\"flowsGroup\"\n [cdkDropListEnterPredicate]=\"enterPredicate\"\n (cdkDropListDropped)=\"onDropFlow($event)\"\n >\n <div class=\"list__flowsGroup__header\">\n <div class=\"list__flowsGroup__header__label\">\n <span>{{ (flowsGroup._isPlan ? 'Plan: ' : '') + flowsGroup.name }}</span>\n </div>\n <div class=\"list__flowsGroup__header__addBtn\">\n @if (apiType === 'NATIVE') {\n <span [matTooltipDisabled]=\"flowsGroup.flows.length < 1\" matTooltip=\"Only one flow is allowed for a native API\">\n <button mat-button [disabled]=\"readOnly || flowsGroup.flows.length > 0\" (click)=\"onAddFlow(flowsGroup)\">\n <mat-icon svgIcon=\"gio:plus\" matTooltip=\"New flow\"></mat-icon>\n </button>\n </span>\n } @else {\n <button mat-button [disabled]=\"readOnly\" (click)=\"onAddFlow(flowsGroup)\">\n <mat-icon svgIcon=\"gio:plus\" matTooltip=\"New flow\"></mat-icon>\n </button>\n }\n </div>\n </div>\n\n <div class=\"list__flowsGroup__flows\">\n @for (flow of flowsGroup.flows; track flow._id) {\n <div\n class=\"list__flowsGroup__flows__flow\"\n [class.selected]=\"flow.selected\"\n [class.disabled]=\"!flow.enabled\"\n (click)=\"selectFlow(flowsGroup._id, flow._id)\"\n (mouseout)=\"flow.mouseOver = false\"\n (mouseover)=\"flow.mouseOver = true\"\n cdkDrag\n >\n <div class=\"list__flowsGroup__flows__flow__left\">\n <div *ngIf=\"flow.name\" class=\"list__flowsGroup__flows__flow__left__name\" [attr.title]=\"flow.name\">\n {{ flow.name }}\n </div>\n @if (apiType !== 'NATIVE') {\n <div class=\"list__flowsGroup__flows__flow__left__infos\">\n <div class=\"list__flowsGroup__flows__flow__left__infos__badges\">\n <span\n *ngFor=\"let badge of flow.badges\"\n class=\"list__flowsGroup__flows__flow__left__infos__badges__badge\"\n [ngClass]=\"badge.class\"\n >{{ badge.label }}</span\n >\n </div>\n <div class=\"list__flowsGroup__flows__flow__left__infos__pathOrChannelLabel\">\n <span *ngIf=\"flow.pathOrChannelLabel; else emptyPathOrChannelLabel\" [attr.title]=\"flow.pathOrChannelLabel\">{{\n flow.pathOrChannelLabel\n }}</span>\n <ng-template #emptyPathOrChannelLabel>\n <em>Empty</em>\n </ng-template>\n </div>\n\n <span\n *ngIf=\"flow.hasCondition\"\n class=\"list__flowsGroup__flows__flow__left__infos__conditionBadge gio-badge-neutral\"\n matTooltip=\"Conditioned\"\n ><mat-icon svgIcon=\"gio:if\"></mat-icon\n ></span>\n </div>\n }\n </div>\n <div class=\"list__flowsGroup__flows__flow__right\">\n <button\n class=\"list__flowsGroup__flows__flow__right__name__menu\"\n mat-button\n [disabled]=\"readOnly\"\n [matMenuTriggerFor]=\"flowMenu\"\n (click)=\"$event.stopPropagation()\"\n >\n <mat-icon svgIcon=\"gio:more-vertical\"></mat-icon>\n </button>\n <mat-menu #flowMenu=\"matMenu\">\n <button [disabled]=\"readOnly\" mat-menu-item (click)=\"onDisableFlow(flow._id)\">\n <mat-icon [svgIcon]=\"flow.enabled ? 'gio:prohibition' : 'gio:check-circled-outline'\"></mat-icon>\n <span>{{ flow.enabled ? 'Disable' : 'Enable' }}</span>\n </button>\n <button mat-menu-item (click)=\"onEditFlow(flow._id)\"><mat-icon svgIcon=\"gio:edit-pencil\"></mat-icon> Edit</button>\n <button mat-menu-item (click)=\"onDeleteFlow(flow._id)\"><mat-icon svgIcon=\"gio:trash\"></mat-icon> Delete</button>\n @if (apiType !== 'NATIVE') {\n <button mat-menu-item (click)=\"onDuplicateFlow(flowsGroup._id, flow._id)\">\n <mat-icon svgIcon=\"gio:copy\"></mat-icon> Duplicate\n </button>\n }\n </mat-menu>\n </div>\n </div>\n }\n </div>\n </div>\n</div>\n\n<ng-template #loadingList>\n <div class=\"loadingList\">\n <gio-loader></gio-loader>\n </div>\n</ng-template>\n", styles: ["@charset \"UTF-8\";.gio-top-bar-menu .gio-badge-accent{background-color:var(--gio-oem-palette--active, #ffc2ac);color:var(--gio-oem-palette--active-contrast, #1e1b1b)}:host{display:flex;height:100%;max-height:100%;flex-direction:column;padding-top:16px}.header{display:flex;align-items:center;padding:0 16px;margin-bottom:16px}.header__label{font-family:Kanit,Helvetica Neue,sans-serif;font-size:16px;font-weight:500;letter-spacing:.4px;line-height:24px;display:flex;flex:1 1 auto;align-items:center;margin-bottom:0;gap:8px}.header__configBtn{margin-left:8px}.list{padding:0 16px;overflow-y:overlay}.list__flowsGroup{display:flex;flex-direction:column;padding-bottom:8px;gap:8px}.list__flowsGroup__header{display:flex;align-items:center;padding:8px 0 0;border-radius:8px}.list__flowsGroup__header__label{font-size:14px;font-weight:700;line-height:20px;font-family:Manrope,sans-serif;letter-spacing:.4px;display:flex;overflow:hidden;flex:1 1 auto;align-items:center;gap:8px}.list__flowsGroup__header__label>mat-icon{width:22px;height:22px;flex:0 0 auto}.list__flowsGroup__header__label>span{display:-webkit-box;overflow:hidden;flex:1 1 auto;-webkit-box-orient:vertical;-webkit-line-clamp:2}.list__flowsGroup__header__addBtn{margin-left:8px}.list__flowsGroup__flows{display:flex;flex-direction:column;gap:8px}.list__flowsGroup__flows__flow{display:flex;overflow:hidden;height:68px;flex-direction:row;align-items:center;justify-content:space-between;padding:7px;border:1px solid #b2aaa9;border-radius:8px;background-color:#fff}.list__flowsGroup__flows__flow.disabled{border:1px solid rgba(178,170,169,0);background-color:#f7f7f8cc;text-decoration:line-through}.list__flowsGroup__flows__flow:hover,.list__flowsGroup__flows__flow.selected{padding:6px;border:2px solid #ffa685;cursor:pointer}.list__flowsGroup__flows__flow__left{display:flex;overflow:hidden;flex:1 1 auto;flex-direction:column;gap:8px}.list__flowsGroup__flows__flow__left__name{overflow:hidden;padding-left:4px;text-overflow:ellipsis;white-space:nowrap}.list__flowsGroup__flows__flow__left__infos{display:flex;align-items:center}.list__flowsGroup__flows__flow__left__infos__badges{flex:0 0 auto}.list__flowsGroup__flows__flow__left__infos__badges__badge{width:auto}.list__flowsGroup__flows__flow__left__infos__pathOrChannelLabel{overflow:hidden;flex:1 1 auto;direction:rtl;text-align:left;text-overflow:ellipsis;white-space:nowrap}.list__flowsGroup__flows__flow__left__infos__pathOrChannelLabel span{direction:ltr;unicode-bidi:bidi-override}.list__flowsGroup__flows__flow__left__infos__conditionBadge{flex:0 0 auto}.list__flowsGroup.cdk-drop-list-dragging{pointer-events:none}.list__flowsGroup .cdk-drag-preview{box-sizing:border-box;border-radius:4px;box-shadow:0 5px 5px -3px #0003,0 8px 10px 1px #00000024,0 3px 14px 2px #0000001f}.list__flowsGroup .cdk-drag-placeholder *{opacity:0}.list__flowsGroup .cdk-drag-animating{transition:transform .25s cubic-bezier(0,0,.2,1)}.list__flowsGroup.cdk-drop-list-dragging .list__flowsGroup__flows__flow:not(.cdk-drag-placeholder){transition:transform .25s cubic-bezier(0,0,.2,1)}.loadingList{display:flex;height:100%;flex-direction:column;align-items:center;justify-content:center}\n"] }]
990
+ args: [{ imports: [
991
+ GioIconsModule,
992
+ MatTooltipModule,
993
+ MatButtonModule,
994
+ CommonModule,
995
+ GioLoaderModule,
996
+ MatMenuModule,
997
+ DragDropModule,
998
+ MatInputModule,
999
+ ReactiveFormsModule,
1000
+ MatFormFieldModule,
1001
+ ], selector: 'gio-ps-flows-menu', template: "<!--\n\n Copyright (C) 2023 The Gravitee team (http://gravitee.io)\n \n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n \n http://www.apache.org/licenses/LICENSE-2.0\n \n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n\n-->\n\n<div class=\"header\">\n <div class=\"header__label\">\n Flows <mat-icon svgIcon=\"gio:info\" matTooltip=\"Flows allow you to apply different policies on your API event phases\"></mat-icon>\n </div>\n @if (apiType !== 'NATIVE') {\n <div class=\"header__configBtn\">\n <button class=\"header__configBtn_edit\" mat-stroked-button [disabled]=\"loading\" (click)=\"onConfigureExecution(flowExecution)\">\n <mat-icon [svgIcon]=\"readOnly ? 'gio:eye-empty' : 'gio:settings'\"></mat-icon>\n </button>\n </div>\n }\n</div>\n<div class=\"searchBar\" *ngIf=\"!loading\">\n <mat-form-field class=\"searchBar__input\">\n <mat-icon matPrefix>search</mat-icon>\n <input matInput placeholder=\"Search by name, path, or group...\" [formControl]=\"searchControl\" />\n <button *ngIf=\"searchControl.value\" matSuffix mat-icon-button aria-label=\"Clear\" (click)=\"resetSearchTerm()\">\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n</div>\n\n<div class=\"list\" *ngIf=\"!loading; else loadingList\" cdkDropListGroup>\n <div\n *ngFor=\"let flowsGroup of filteredFlowGroupMenuItems\"\n class=\"list__flowsGroup\"\n cdkDropList\n [cdkDropListData]=\"flowsGroup\"\n [cdkDropListEnterPredicate]=\"enterPredicate\"\n (cdkDropListDropped)=\"onDropFlow($event)\"\n >\n <div class=\"list__flowsGroup__header\">\n <div class=\"list__flowsGroup__header__label\">\n <span>{{ (flowsGroup._isPlan ? 'Plan: ' : '') + flowsGroup.name }}</span>\n </div>\n <div class=\"list__flowsGroup__header__addBtn\">\n @if (apiType === 'NATIVE') {\n <span [matTooltipDisabled]=\"flowsGroup.flows.length < 1\" matTooltip=\"Only one flow is allowed for a native API\">\n <button mat-button [disabled]=\"readOnly || flowsGroup.flows.length > 0\" (click)=\"onAddFlow(flowsGroup)\">\n <mat-icon svgIcon=\"gio:plus\" matTooltip=\"New flow\"></mat-icon>\n </button>\n </span>\n } @else {\n <button mat-button [disabled]=\"readOnly\" (click)=\"onAddFlow(flowsGroup)\">\n <mat-icon svgIcon=\"gio:plus\" matTooltip=\"New flow\"></mat-icon>\n </button>\n }\n </div>\n </div>\n\n <div class=\"list__flowsGroup__flows\">\n <ng-container *ngIf=\"flowsGroup.flows.length > 0; else noFlows\">\n @for (flow of flowsGroup.flows; track flow._id) {\n <div\n class=\"list__flowsGroup__flows__flow\"\n [class.selected]=\"flow.selected\"\n [class.disabled]=\"!flow.enabled\"\n (click)=\"selectFlow(flowsGroup._id, flow._id)\"\n (mouseout)=\"flow.mouseOver = false\"\n (mouseover)=\"flow.mouseOver = true\"\n cdkDrag\n >\n <div class=\"list__flowsGroup__flows__flow__left\">\n <div *ngIf=\"flow.name\" class=\"list__flowsGroup__flows__flow__left__name\" [attr.title]=\"flow.name\">\n {{ flow.name }}\n </div>\n @if (apiType !== 'NATIVE') {\n <div class=\"list__flowsGroup__flows__flow__left__infos\">\n <div class=\"list__flowsGroup__flows__flow__left__infos__badges\">\n <span\n *ngFor=\"let badge of flow.badges\"\n class=\"list__flowsGroup__flows__flow__left__infos__badges__badge\"\n [ngClass]=\"badge.class\"\n >{{ badge.label }}</span\n >\n </div>\n <div class=\"list__flowsGroup__flows__flow__left__infos__pathOrChannelLabel\">\n <span *ngIf=\"flow.pathOrChannelLabel; else emptyPathOrChannelLabel\" [attr.title]=\"flow.pathOrChannelLabel\">{{\n flow.pathOrChannelLabel\n }}</span>\n <ng-template #emptyPathOrChannelLabel>\n <em>Empty</em>\n </ng-template>\n </div>\n\n <span\n *ngIf=\"flow.hasCondition\"\n class=\"list__flowsGroup__flows__flow__left__infos__conditionBadge gio-badge-neutral\"\n matTooltip=\"Conditioned\"\n ><mat-icon svgIcon=\"gio:if\"></mat-icon\n ></span>\n </div>\n }\n </div>\n <div class=\"list__flowsGroup__flows__flow__right\">\n <button\n class=\"list__flowsGroup__flows__flow__right__name__menu\"\n mat-button\n [disabled]=\"readOnly\"\n [matMenuTriggerFor]=\"flowMenu\"\n (click)=\"$event.stopPropagation()\"\n >\n <mat-icon svgIcon=\"gio:more-vertical\"></mat-icon>\n </button>\n <mat-menu #flowMenu=\"matMenu\">\n <button [disabled]=\"readOnly\" mat-menu-item (click)=\"onDisableFlow(flow._id)\">\n <mat-icon [svgIcon]=\"flow.enabled ? 'gio:prohibition' : 'gio:check-circled-outline'\"></mat-icon>\n <span>{{ flow.enabled ? 'Disable' : 'Enable' }}</span>\n </button>\n <button mat-menu-item (click)=\"onEditFlow(flow._id)\"><mat-icon svgIcon=\"gio:edit-pencil\"></mat-icon> Edit</button>\n <button mat-menu-item (click)=\"onDeleteFlow(flow._id)\"><mat-icon svgIcon=\"gio:trash\"></mat-icon> Delete</button>\n @if (apiType !== 'NATIVE') {\n <button mat-menu-item (click)=\"onDuplicateFlow(flowsGroup._id, flow._id)\">\n <mat-icon svgIcon=\"gio:copy\"></mat-icon> Duplicate\n </button>\n }\n </mat-menu>\n </div>\n </div>\n }\n </ng-container>\n <ng-template #noFlows>\n <div class=\"list__flowsGroup__no-flows\">No flows yet</div>\n </ng-template>\n </div>\n </div>\n</div>\n\n<ng-template #loadingList>\n <div class=\"loadingList\">\n <gio-loader></gio-loader>\n </div>\n</ng-template>\n", styles: ["@charset \"UTF-8\";.gio-top-bar-menu .gio-badge-accent{background-color:var(--gio-oem-palette--active, #ffc2ac);color:var(--gio-oem-palette--active-contrast, #1e1b1b)}:host{display:flex;height:100%;max-height:100%;flex-direction:column;padding-top:16px}.header{display:flex;align-items:center;padding:0 16px;margin-bottom:14px}.header__label{font-family:Kanit,Helvetica Neue,sans-serif;font-size:16px;font-weight:500;letter-spacing:.4px;line-height:24px;display:flex;flex:1 1 auto;align-items:center;margin-bottom:0;gap:8px}.header__configBtn{margin-left:8px}.searchBar{display:flex;padding:0 16px}.searchBar__input{flex:1 1 auto}.list{padding:0 16px;overflow-y:overlay}.list__flowsGroup{display:flex;flex-direction:column;padding-bottom:8px;gap:8px}.list__flowsGroup__header{display:flex;align-items:center;padding:8px 0 0;border-radius:8px}.list__flowsGroup__header__label{font-size:14px;font-weight:700;line-height:20px;font-family:Manrope,sans-serif;letter-spacing:.4px;display:flex;overflow:hidden;flex:1 1 auto;align-items:center;gap:8px}.list__flowsGroup__header__label>mat-icon{width:22px;height:22px;flex:0 0 auto}.list__flowsGroup__header__label>span{display:-webkit-box;overflow:hidden;flex:1 1 auto;-webkit-box-orient:vertical;-webkit-line-clamp:2}.list__flowsGroup__header__addBtn{margin-left:8px}.list__flowsGroup__flows{display:flex;flex-direction:column;gap:8px}.list__flowsGroup__flows__flow{display:flex;overflow:hidden;height:68px;flex-direction:row;align-items:center;justify-content:space-between;padding:7px;border:1px solid #b2aaa9;border-radius:8px;background-color:#fff}.list__flowsGroup__flows__flow.disabled{border:1px solid rgba(178,170,169,0);background-color:#f7f7f8cc;text-decoration:line-through}.list__flowsGroup__flows__flow:hover,.list__flowsGroup__flows__flow.selected{padding:6px;border:2px solid #ffa685;cursor:pointer}.list__flowsGroup__flows__flow__left{display:flex;overflow:hidden;flex:1 1 auto;flex-direction:column;gap:8px}.list__flowsGroup__flows__flow__left__name{overflow:hidden;padding-left:4px;text-overflow:ellipsis;white-space:nowrap}.list__flowsGroup__flows__flow__left__infos{display:flex;align-items:center}.list__flowsGroup__flows__flow__left__infos__badges{flex:0 0 auto}.list__flowsGroup__flows__flow__left__infos__badges__badge{width:auto}.list__flowsGroup__flows__flow__left__infos__pathOrChannelLabel{overflow:hidden;flex:1 1 auto;direction:rtl;text-align:left;text-overflow:ellipsis;white-space:nowrap}.list__flowsGroup__flows__flow__left__infos__pathOrChannelLabel span{direction:ltr;unicode-bidi:bidi-override}.list__flowsGroup__flows__flow__left__infos__conditionBadge{flex:0 0 auto}.list__flowsGroup__no-flows{font-style:italic}.list__flowsGroup.cdk-drop-list-dragging{pointer-events:none}.list__flowsGroup .cdk-drag-preview{box-sizing:border-box;border-radius:4px;box-shadow:0 5px 5px -3px #0003,0 8px 10px 1px #00000024,0 3px 14px 2px #0000001f}.list__flowsGroup .cdk-drag-placeholder *{opacity:0}.list__flowsGroup .cdk-drag-animating{transition:transform .25s cubic-bezier(0,0,.2,1)}.list__flowsGroup.cdk-drop-list-dragging .list__flowsGroup__flows__flow:not(.cdk-drag-placeholder){transition:transform .25s cubic-bezier(0,0,.2,1)}.loadingList{display:flex;height:100%;flex-direction:column;align-items:center;justify-content:center}\n"] }]
935
1002
  }], ctorParameters: () => [{ type: i1.MatDialog }], propDecorators: { readOnly: [{
936
1003
  type: Input
937
1004
  }], loading: [{
@@ -1127,7 +1194,7 @@ class GioPolicyStudioStepFormComponent {
1127
1194
  });
1128
1195
  }
1129
1196
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: GioPolicyStudioStepFormComponent, deps: [{ token: GioPolicyStudioService }], target: i0.ɵɵFactoryTarget.Component }); }
1130
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.4", type: GioPolicyStudioStepFormComponent, isStandalone: true, selector: "gio-ps-step-form", inputs: { readOnly: "readOnly", step: "step", flowPhase: "flowPhase", apiType: "apiType", genericPolicy: "genericPolicy" }, outputs: { stepChange: "stepChange", isValid: "isValid" }, usesOnChanges: true, ngImport: i0, template: "<!--\n\n Copyright (C) 2023 The Gravitee team (http://gravitee.io)\n \n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n \n http://www.apache.org/licenses/LICENSE-2.0\n \n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n\n-->\n\n<div class=\"settings\">\n <div class=\"settings__header\">Settings</div>\n\n <div class=\"settings__content\">\n <ng-container *ngIf=\"stepForm && (policySchema$ | async) as policySchema; else loadingTmpl\" [formGroup]=\"stepForm\">\n <mat-form-field>\n <mat-label>Description</mat-label>\n <textarea matInput formControlName=\"description\" cdkFocusInitial></textarea>\n <mat-hint>Describe how your policy works.</mat-hint>\n </mat-form-field>\n\n <mat-form-field>\n <mat-label>Trigger condition</mat-label>\n <input matInput formControlName=\"condition\" />\n <mat-hint>The condition to execute this policy. Supports Expression Language.</mat-hint>\n </mat-form-field>\n\n @if (isMessage) {\n <mat-form-field>\n <mat-label>Message trigger condition</mat-label>\n <input matInput formControlName=\"messageCondition\" />\n <mat-hint>The condition to execute this policy on message. Supports Expression Language.</mat-hint>\n </mat-form-field>\n }\n\n <gio-form-json-schema\n *ngIf=\"policySchema\"\n [jsonSchema]=\"$any(policySchema)\"\n [context]=\"context\"\n (ready)=\"onJsonSchemaReady($event)\"\n formControlName=\"configuration\"\n ></gio-form-json-schema>\n </ng-container>\n </div>\n</div>\n\n<div class=\"documentation\">\n <div class=\"documentation__header\">Documentation</div>\n\n <div class=\"documentation__content\">\n <gio-banner-warning *ngIf=\"infoBanner\">\n Prerequisite message\n <span gioBannerBody>{{ infoBanner }}</span>\n </gio-banner-warning>\n <ng-container *ngIf=\"policyDocumentation$ | async as policyDocumentation; else loadingTmpl\">\n @switch (policyDocumentation.language) {\n @case ('ASCIIDOC') {\n <gio-asciidoctor [content]=\"policyDocumentation.content\"></gio-asciidoctor>\n }\n @case ('MARKDOWN') {\n <markdown class=\"documentation__content__markdown\" [data]=\"policyDocumentation.content\"></markdown>\n }\n }\n </ng-container>\n </div>\n</div>\n\n<ng-template #loadingTmpl>\n <gio-loader></gio-loader>\n</ng-template>\n", styles: ["@charset \"UTF-8\";.gio-top-bar-menu .gio-badge-accent{background-color:var(--gio-oem-palette--active, #ffc2ac);color:var(--gio-oem-palette--active-contrast, #1e1b1b)}:host{display:flex;flex-direction:row;border:1px solid #d2cecd;border-radius:8px}::ng-deep gio-ps-step-form .documentation__content__markdown table{overflow:hidden;width:100%;border:1px solid #d2cecd;border-radius:4px;margin-bottom:12px;border-collapse:separate;border-spacing:0}::ng-deep gio-ps-step-form .documentation__content__markdown table th,::ng-deep gio-ps-step-form .documentation__content__markdown table td{padding:8px;border-bottom:1px solid #d2cecd}::ng-deep gio-ps-step-form .documentation__content__markdown table tr:last-child td{border-bottom:none}::ng-deep gio-ps-step-form .documentation__content__markdown table th:first-child{border-top-left-radius:4px}::ng-deep gio-ps-step-form .documentation__content__markdown table th:last-child{border-top-right-radius:4px}::ng-deep gio-ps-step-form .documentation__content__markdown table tr:last-child td:first-child{border-bottom-left-radius:4px}::ng-deep gio-ps-step-form .documentation__content__markdown table tr:last-child td:last-child{border-bottom-right-radius:4px}.settings{display:flex;flex:0 0 50%;flex-direction:column}.settings__header{border-right:1px solid #d2cecd}.settings__content{display:flex;flex:1 1 auto;flex-direction:column;padding:16px;border-right:1px solid #d2cecd}.documentation{display:flex;overflow:auto;flex:0 0 50%;flex-direction:column}.documentation__content{overflow:auto;flex:1 1 auto;padding:16px}.settings__header,.documentation__header{padding:16px;border-bottom:1px solid #d2cecd;font-size:14px;font-weight:700;line-height:20px;font-family:Manrope,sans-serif;letter-spacing:.4px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "pipe", type: i2.AsyncPipe, name: "async" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i3.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i3.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i3.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i7.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "component", type: i5.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i5.MatLabel, selector: "mat-label" }, { kind: "directive", type: i5.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "ngmodule", type: GioFormJsonSchemaModule }, { kind: "component", type: i6$1.GioFormJsonSchemaComponent, selector: "gio-form-json-schema", inputs: ["jsonSchema", "context", "options"], outputs: ["ready"] }, { kind: "ngmodule", type: GioAsciidoctorModule }, { kind: "component", type: i7$3.GioAsciidoctorComponent, selector: "gio-asciidoctor", inputs: ["content", "src"] }, { kind: "ngmodule", type: GioLoaderModule }, { kind: "component", type: i6$1.GioLoaderComponent, selector: "gio-loader" }, { kind: "ngmodule", type: GioBannerModule }, { kind: "component", type: i6$1.GioBannerWarningComponent, selector: "gio-banner-warning" }, { kind: "directive", type: i6$1.GioBannerBodyDirective, selector: "[gioBannerBody]" }, { kind: "component", type: MarkdownComponent, selector: "markdown, [markdown]", inputs: ["data", "src", "disableSanitizer", "inline", "clipboard", "clipboardButtonComponent", "clipboardButtonTemplate", "emoji", "katex", "katexOptions", "mermaid", "mermaidOptions", "lineHighlight", "line", "lineOffset", "lineNumbers", "start", "commandLine", "filterOutput", "host", "prompt", "output", "user"], outputs: ["error", "load", "ready"] }] }); }
1197
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.4", type: GioPolicyStudioStepFormComponent, isStandalone: true, selector: "gio-ps-step-form", inputs: { readOnly: "readOnly", step: "step", flowPhase: "flowPhase", apiType: "apiType", genericPolicy: "genericPolicy" }, outputs: { stepChange: "stepChange", isValid: "isValid" }, usesOnChanges: true, ngImport: i0, template: "<!--\n\n Copyright (C) 2023 The Gravitee team (http://gravitee.io)\n \n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n \n http://www.apache.org/licenses/LICENSE-2.0\n \n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n\n-->\n\n<div class=\"settings\">\n <div class=\"settings__header\">Settings</div>\n\n <div class=\"settings__content\">\n <ng-container *ngIf=\"stepForm && (policySchema$ | async) as policySchema; else loadingTmpl\" [formGroup]=\"stepForm\">\n <mat-form-field>\n <mat-label>Description</mat-label>\n <textarea matInput formControlName=\"description\" cdkFocusInitial></textarea>\n <mat-hint>Describe how your policy works.</mat-hint>\n </mat-form-field>\n\n <mat-form-field>\n <mat-label>Trigger condition</mat-label>\n <input matInput formControlName=\"condition\" />\n <mat-hint>The condition to execute this policy. Supports Expression Language.</mat-hint>\n </mat-form-field>\n\n @if (isMessage) {\n <mat-form-field>\n <mat-label>Message trigger condition</mat-label>\n <input matInput formControlName=\"messageCondition\" />\n <mat-hint>The condition to execute this policy on message. Supports Expression Language.</mat-hint>\n </mat-form-field>\n }\n\n <gio-form-json-schema\n *ngIf=\"policySchema\"\n [jsonSchema]=\"$any(policySchema)\"\n [context]=\"context\"\n (ready)=\"onJsonSchemaReady($event)\"\n formControlName=\"configuration\"\n ></gio-form-json-schema>\n </ng-container>\n </div>\n</div>\n\n<div class=\"documentation\">\n <div class=\"documentation__header\">Documentation</div>\n\n <div class=\"documentation__content\">\n <gio-banner-warning *ngIf=\"infoBanner\">\n Prerequisite message\n <span gioBannerBody>{{ infoBanner }}</span>\n </gio-banner-warning>\n <ng-container *ngIf=\"policyDocumentation$ | async as policyDocumentation; else loadingTmpl\">\n @switch (policyDocumentation.language) {\n @case ('ASCIIDOC') {\n <gio-asciidoctor [content]=\"policyDocumentation.content\"></gio-asciidoctor>\n }\n @case ('MARKDOWN') {\n <markdown class=\"documentation__content__markdown\" [data]=\"policyDocumentation.content\"></markdown>\n }\n }\n </ng-container>\n </div>\n</div>\n\n<ng-template #loadingTmpl>\n <gio-loader></gio-loader>\n</ng-template>\n", styles: ["@charset \"UTF-8\";.gio-top-bar-menu .gio-badge-accent{background-color:var(--gio-oem-palette--active, #ffc2ac);color:var(--gio-oem-palette--active-contrast, #1e1b1b)}:host{display:flex;flex-direction:row;border:1px solid #d2cecd;border-radius:8px}::ng-deep gio-ps-step-form .documentation__content__markdown table{overflow:hidden;width:100%;border:1px solid #d2cecd;border-radius:4px;margin-bottom:12px;border-collapse:separate;border-spacing:0}::ng-deep gio-ps-step-form .documentation__content__markdown table th,::ng-deep gio-ps-step-form .documentation__content__markdown table td{padding:8px;border-bottom:1px solid #d2cecd}::ng-deep gio-ps-step-form .documentation__content__markdown table tr:last-child td{border-bottom:none}::ng-deep gio-ps-step-form .documentation__content__markdown table th:first-child{border-top-left-radius:4px}::ng-deep gio-ps-step-form .documentation__content__markdown table th:last-child{border-top-right-radius:4px}::ng-deep gio-ps-step-form .documentation__content__markdown table tr:last-child td:first-child{border-bottom-left-radius:4px}::ng-deep gio-ps-step-form .documentation__content__markdown table tr:last-child td:last-child{border-bottom-right-radius:4px}.settings{display:flex;flex:0 0 50%;flex-direction:column}.settings__header{border-right:1px solid #d2cecd}.settings__content{display:flex;flex:1 1 auto;flex-direction:column;padding:16px;border-right:1px solid #d2cecd}.documentation{display:flex;overflow:auto;flex:0 0 50%;flex-direction:column}.documentation__content{overflow:auto;flex:1 1 auto;padding:16px}.settings__header,.documentation__header{padding:16px;border-bottom:1px solid #d2cecd;font-size:14px;font-weight:700;line-height:20px;font-family:Manrope,sans-serif;letter-spacing:.4px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "pipe", type: i2.AsyncPipe, name: "async" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i3.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i3.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i3.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i7$1.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "component", type: i5.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i5.MatLabel, selector: "mat-label" }, { kind: "directive", type: i5.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "ngmodule", type: GioFormJsonSchemaModule }, { kind: "component", type: i6$1.GioFormJsonSchemaComponent, selector: "gio-form-json-schema", inputs: ["jsonSchema", "context", "options"], outputs: ["ready"] }, { kind: "ngmodule", type: GioAsciidoctorModule }, { kind: "component", type: i7$3.GioAsciidoctorComponent, selector: "gio-asciidoctor", inputs: ["content", "src"] }, { kind: "ngmodule", type: GioLoaderModule }, { kind: "component", type: i6$1.GioLoaderComponent, selector: "gio-loader" }, { kind: "ngmodule", type: GioBannerModule }, { kind: "component", type: i6$1.GioBannerWarningComponent, selector: "gio-banner-warning" }, { kind: "directive", type: i6$1.GioBannerBodyDirective, selector: "[gioBannerBody]" }, { kind: "component", type: MarkdownComponent, selector: "markdown, [markdown]", inputs: ["data", "src", "disableSanitizer", "inline", "clipboard", "clipboardButtonComponent", "clipboardButtonTemplate", "emoji", "katex", "katexOptions", "mermaid", "mermaidOptions", "lineHighlight", "line", "lineOffset", "lineNumbers", "start", "commandLine", "filterOutput", "host", "prompt", "output", "user"], outputs: ["error", "load", "ready"] }] }); }
1131
1198
  }
1132
1199
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: GioPolicyStudioStepFormComponent, decorators: [{
1133
1200
  type: Component,
@@ -1278,7 +1345,7 @@ class GioPolicyStudioPoliciesCatalogDialogComponent {
1278
1345
  this.isUnlicensed = false;
1279
1346
  }
1280
1347
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: GioPolicyStudioPoliciesCatalogDialogComponent, deps: [{ token: i1.MatDialogRef }, { token: MAT_DIALOG_DATA }], target: i0.ɵɵFactoryTarget.Component }); }
1281
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.4", type: GioPolicyStudioPoliciesCatalogDialogComponent, isStandalone: true, selector: "gio-ps-policies-catalog-dialog", ngImport: i0, template: "<!--\n\n Copyright (C) 2015 The Gravitee team (http://gravitee.io)\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n\n-->\n<h2 mat-dialog-title class=\"title\">\n @if (selectedPolicy) {\n <button class=\"title__goBackBtn\" mat-stroked-button (click)=\"onGoBack()\">\n <mat-icon svgIcon=\"gio:arrow-left\"></mat-icon>\n Go back\n </button>\n }\n Policies for <span class=\"title__phase\">{{ flowPhaseLabel }}</span> phase\n\n <button class=\"title__closeBtn\" mat-icon-button aria-label=\"Close dialog\" [mat-dialog-close]=\"\">\n <mat-icon svgIcon=\"gio:cancel\"></mat-icon>\n </button>\n</h2>\n\n<ng-container>\n <mat-dialog-content *ngIf=\"!selectedPolicy\" class=\"policiesCatalog\">\n <div class=\"policiesCatalog__filters\" [formGroup]=\"filtersForm\">\n <mat-form-field class=\"policiesCatalog__filters__search\" appearance=\"outline\">\n <mat-label>Search</mat-label>\n <input matInput formControlName=\"search\" cdkFocusInitial />\n <button\n matIconSuffix\n mat-icon-button\n aria-label=\"Clear\"\n *ngIf=\"filtersForm.get('search')?.value\"\n (click)=\"filtersForm.get('search')?.setValue('')\"\n >\n <mat-icon svgIcon=\"gio:cancel\"></mat-icon>\n </button>\n </mat-form-field>\n <mat-chip-listbox\n *ngIf=\"categories.length > 1\"\n class=\"policiesCatalog__filters__categories\"\n aria-label=\"Categories selection\"\n multiple\n formControlName=\"categories\"\n >\n <mat-chip-option *ngFor=\"let category of categories\" [selected]=\"category\" [value]=\"category\"\n >{{ category | titlecase }}\n </mat-chip-option>\n </mat-chip-listbox>\n </div>\n\n <div *ngIf=\"policies.length; else emptyPoliciesTpl\" class=\"policiesCatalog__list\">\n <div *ngFor=\"let policy of policies\" class=\"policiesCatalog__list__policy\">\n <div class=\"policiesCatalog__list__policy__head\">\n <mat-icon class=\"policiesCatalog__list__policy__head__icon\" [svgIcon]=\"policy.icon ?? 'gio:puzzle'\"></mat-icon>\n\n <span *ngIf=\"policy.name\" class=\"policiesCatalog__list__policy__head__name\">{{ policy.name }}</span>\n\n <span\n *ngIf=\"policy.genericPolicy.type === 'SHARED_POLICY_GROUP'\"\n class=\"gio-badge-neutral policiesCatalog__list__policy__head__badge\"\n matTooltip=\"Shared Policy Group\"\n >\n <mat-icon svgIcon=\"gio:users\"></mat-icon>\n </span>\n </div>\n\n <div class=\"policiesCatalog__list__policy__enterprise\" *ngIf=\"policy.deployed === false\">\n <mat-icon\n class=\"policiesCatalog__list__policy__enterprise__lock\"\n [svgIcon]=\"'gio:lock'\"\n matTooltip=\"This policy is only available for users with an enterprise license.\"\n ></mat-icon>\n </div>\n\n <div *ngIf=\"policy.description\" class=\"policiesCatalog__list__policy__description\">{{ policy.description }}</div>\n\n <button class=\"policiesCatalog__list__policy__selectBtn\" mat-stroked-button role=\"dialog\" (click)=\"onSelectPolicy(policy)\">\n Select\n </button>\n </div>\n </div>\n </mat-dialog-content>\n</ng-container>\n\n<ng-template #emptyPoliciesTpl>\n <div class=\"emptyPoliciesCatalog\">No policies available.</div>\n</ng-template>\n\n<mat-dialog-content *ngIf=\"selectedPolicy\" class=\"policyForm\">\n <gio-banner *ngIf=\"isUnlicensed\" type=\"error\" icon=\"gio:universe\">\n This policy is only available for users with an enterprise license.\n <span gioBannerBody>Request a license to upgrade your account and unlock this policy</span>\n <div gioBannerAction>\n <a *ngIf=\"trialUrl\" mat-stroked-button [href]=\"trialUrl\" target=\"_blank\">Request upgrade</a>\n </div>\n </gio-banner>\n\n <div class=\"policyForm__info\">\n <div class=\"policyForm__info__head\">\n <mat-icon class=\"policyForm__info__head__icon\" [svgIcon]=\"selectedPolicy.icon ?? 'gio:puzzle'\"></mat-icon>\n\n <span *ngIf=\"selectedPolicy.name\" class=\"policyForm__info__head__name\">{{ selectedPolicy.name }}</span>\n\n <span *ngIf=\"selectedPolicy.type === 'SHARED_POLICY_GROUP'\" class=\"gio-badge-neutral policiesCatalog__list__policy__head__badge\">\n <mat-icon svgIcon=\"gio:users\"></mat-icon>&nbsp;Shared Policy Group\n </span>\n </div>\n\n <div *ngIf=\"selectedPolicy.description\" class=\"policyForm__info__description\">{{ selectedPolicy.description }}</div>\n </div>\n\n <gio-ps-step-form\n [genericPolicy]=\"selectedPolicy\"\n [flowPhase]=\"flowPhase\"\n [apiType]=\"apiType\"\n (stepChange)=\"onStepChange($event)\"\n (isValid)=\"onIsValid($event)\"\n ></gio-ps-step-form>\n</mat-dialog-content>\n\n<mat-dialog-actions class=\"actions\" align=\"end\">\n <button class=\"actions__cancelBtn\" mat-button [mat-dialog-close]=\"\">Cancel</button>\n <button\n *ngIf=\"selectedPolicy\"\n class=\"actions__addBtn\"\n color=\"primary\"\n mat-flat-button\n role=\"dialog\"\n [disabled]=\"!isValid || isUnlicensed\"\n (click)=\"onAddPolicy()\"\n >\n Add policy\n </button>\n</mat-dialog-actions>\n", styles: ["@charset \"UTF-8\";.gio-top-bar-menu .gio-badge-accent{background-color:var(--gio-oem-palette--active, #ffc2ac);color:var(--gio-oem-palette--active-contrast, #1e1b1b)}.title__goBackBtn{margin-right:8px;line-height:normal}.title__closeBtn{top:0;right:-24px;float:right}.policiesCatalog__filters{display:flex;flex-direction:column;padding:0 0 8px;gap:8px}.policiesCatalog__filters__search{width:100%;height:54px;padding-bottom:0}.policiesCatalog__list{--grid-layout-gap: 16px;--grid-column-count: 3;--grid-item-min-width: 200px;--gap-count: calc(var(--grid-column-count) - 1);--total-gap-width: calc(var(--gap-count) * var(--grid-layout-gap));--grid-item-max-width: calc((100% - var(--total-gap-width)) / var(--grid-column-count));display:grid;grid-gap:var(--grid-layout-gap);grid-template-columns:repeat(auto-fill,minmax(max(var(--grid-item-min-width),var(--grid-item-max-width)),1fr))}.policiesCatalog__list__policy{position:relative;display:flex;flex-direction:column;align-items:flex-start;justify-content:space-between;padding:16px;border:1px solid #d2cecd;border-radius:8px;gap:4px}.policiesCatalog__list__policy__head{display:flex;align-items:center;align-self:stretch}.policiesCatalog__list__policy__head__icon{min-width:24px;flex:0 0 24px;margin-right:8px}.policiesCatalog__list__policy__head__name{overflow:hidden;flex:1 1 auto;text-overflow:ellipsis;white-space:nowrap}.policiesCatalog__list__policy__head__badge{float:left}.policiesCatalog__list__policy__enterprise{position:absolute;top:0;right:0;padding:8px 8px 8px 16px;border-radius:0 8px 0 38px;background:#f7f7f8;color:#da3b00}.policiesCatalog__list__policy__enterprise__lock{min-width:16px;max-width:16px;color:#da3b00}.policiesCatalog__list__policy__description{font-size:12px;font-weight:400;line-height:16px;font-family:Manrope,sans-serif;letter-spacing:normal;display:-webkit-box;overflow:hidden;-webkit-box-orient:vertical;color:#322f2f;-webkit-line-clamp:2}.policiesCatalog__list__policy__description:empty{display:none}.policiesCatalog__list__policy__selectBtn{margin-top:8px}.policyForm__goBackBtn{margin:16px 0}.policyForm__info{display:flex;max-width:100%;flex-direction:column;align-items:flex-start;padding-bottom:16px;gap:4px}.policyForm__info__head{display:flex;align-items:center}.policyForm__info__head__icon{min-width:24px;flex:1 1 24px;margin-right:8px}.policyForm__info__head__name{flex:1 1 auto}.policyForm__info__description{font-size:12px;font-weight:400;line-height:16px;font-family:Manrope,sans-serif;letter-spacing:normal;color:#322f2f}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "pipe", type: i2.TitleCasePipe, name: "titlecase" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i3.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i3.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i3.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i4.MatAnchor, selector: "a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button]", exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i4.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: i4.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "ngmodule", type: MatDialogModule }, { kind: "directive", type: i1.MatDialogClose, selector: "[mat-dialog-close], [matDialogClose]", inputs: ["aria-label", "type", "mat-dialog-close", "matDialogClose"], exportAs: ["matDialogClose"] }, { kind: "directive", type: i1.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: i1.MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }, { kind: "directive", type: i1.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i5.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i5.MatLabel, selector: "mat-label" }, { kind: "directive", type: i5.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatChipsModule }, { kind: "component", type: i6$2.MatChipListbox, selector: "mat-chip-listbox", inputs: ["multiple", "aria-orientation", "selectable", "compareWith", "required", "hideSingleSelectionIndicator", "value"], outputs: ["change"] }, { kind: "component", type: i6$2.MatChipOption, selector: "mat-basic-chip-option, [mat-basic-chip-option], mat-chip-option, [mat-chip-option]", inputs: ["selectable", "selected"], outputs: ["selectionChange"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i7.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: GioBannerModule }, { kind: "component", type: i6$1.GioBannerComponent, selector: "gio-banner", inputs: ["type", "icon", "collapsible"] }, { kind: "directive", type: i6$1.GioBannerBodyDirective, selector: "[gioBannerBody]" }, { kind: "directive", type: i6$1.GioBannerActionDirective, selector: "[gioBannerAction]" }, { kind: "ngmodule", type: GioIconsModule }, { kind: "component", type: i5$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: GioPolicyStudioStepFormComponent, selector: "gio-ps-step-form", inputs: ["readOnly", "step", "flowPhase", "apiType", "genericPolicy"], outputs: ["stepChange", "isValid"] }, { kind: "directive", type: MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }] }); }
1348
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.4", type: GioPolicyStudioPoliciesCatalogDialogComponent, isStandalone: true, selector: "gio-ps-policies-catalog-dialog", ngImport: i0, template: "<!--\n\n Copyright (C) 2015 The Gravitee team (http://gravitee.io)\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n\n-->\n<h2 mat-dialog-title class=\"title\">\n @if (selectedPolicy) {\n <button class=\"title__goBackBtn\" mat-stroked-button (click)=\"onGoBack()\">\n <mat-icon svgIcon=\"gio:arrow-left\"></mat-icon>\n Go back\n </button>\n }\n Policies for <span class=\"title__phase\">{{ flowPhaseLabel }}</span> phase\n\n <button class=\"title__closeBtn\" mat-icon-button aria-label=\"Close dialog\" [mat-dialog-close]=\"\">\n <mat-icon svgIcon=\"gio:cancel\"></mat-icon>\n </button>\n</h2>\n\n<ng-container>\n <mat-dialog-content *ngIf=\"!selectedPolicy\" class=\"policiesCatalog\">\n <div class=\"policiesCatalog__filters\" [formGroup]=\"filtersForm\">\n <mat-form-field class=\"policiesCatalog__filters__search\" appearance=\"outline\">\n <mat-label>Search</mat-label>\n <input matInput formControlName=\"search\" cdkFocusInitial />\n <button\n matIconSuffix\n mat-icon-button\n aria-label=\"Clear\"\n *ngIf=\"filtersForm.get('search')?.value\"\n (click)=\"filtersForm.get('search')?.setValue('')\"\n >\n <mat-icon svgIcon=\"gio:cancel\"></mat-icon>\n </button>\n </mat-form-field>\n <mat-chip-listbox\n *ngIf=\"categories.length > 1\"\n class=\"policiesCatalog__filters__categories\"\n aria-label=\"Categories selection\"\n multiple\n formControlName=\"categories\"\n >\n <mat-chip-option *ngFor=\"let category of categories\" [selected]=\"category\" [value]=\"category\"\n >{{ category | titlecase }}\n </mat-chip-option>\n </mat-chip-listbox>\n </div>\n\n <div *ngIf=\"policies.length; else emptyPoliciesTpl\" class=\"policiesCatalog__list\">\n <div *ngFor=\"let policy of policies\" class=\"policiesCatalog__list__policy\">\n <div class=\"policiesCatalog__list__policy__head\">\n <mat-icon class=\"policiesCatalog__list__policy__head__icon\" [svgIcon]=\"policy.icon ?? 'gio:puzzle'\"></mat-icon>\n\n <span *ngIf=\"policy.name\" class=\"policiesCatalog__list__policy__head__name\">{{ policy.name }}</span>\n\n <span\n *ngIf=\"policy.genericPolicy.type === 'SHARED_POLICY_GROUP'\"\n class=\"gio-badge-neutral policiesCatalog__list__policy__head__badge\"\n matTooltip=\"Shared Policy Group\"\n >\n <mat-icon svgIcon=\"gio:users\"></mat-icon>\n </span>\n </div>\n\n <div class=\"policiesCatalog__list__policy__enterprise\" *ngIf=\"policy.deployed === false\">\n <mat-icon\n class=\"policiesCatalog__list__policy__enterprise__lock\"\n [svgIcon]=\"'gio:lock'\"\n matTooltip=\"This policy is only available for users with an enterprise license.\"\n ></mat-icon>\n </div>\n\n <div *ngIf=\"policy.description\" class=\"policiesCatalog__list__policy__description\">{{ policy.description }}</div>\n\n <button class=\"policiesCatalog__list__policy__selectBtn\" mat-stroked-button role=\"dialog\" (click)=\"onSelectPolicy(policy)\">\n Select\n </button>\n </div>\n </div>\n </mat-dialog-content>\n</ng-container>\n\n<ng-template #emptyPoliciesTpl>\n <div class=\"emptyPoliciesCatalog\">No policies available.</div>\n</ng-template>\n\n<mat-dialog-content *ngIf=\"selectedPolicy\" class=\"policyForm\">\n <gio-banner *ngIf=\"isUnlicensed\" type=\"error\" icon=\"gio:universe\">\n This policy is only available for users with an enterprise license.\n <span gioBannerBody>Request a license to upgrade your account and unlock this policy</span>\n <div gioBannerAction>\n <a *ngIf=\"trialUrl\" mat-stroked-button [href]=\"trialUrl\" target=\"_blank\">Request upgrade</a>\n </div>\n </gio-banner>\n\n <div class=\"policyForm__info\">\n <div class=\"policyForm__info__head\">\n <mat-icon class=\"policyForm__info__head__icon\" [svgIcon]=\"selectedPolicy.icon ?? 'gio:puzzle'\"></mat-icon>\n\n <span *ngIf=\"selectedPolicy.name\" class=\"policyForm__info__head__name\">{{ selectedPolicy.name }}</span>\n\n <span *ngIf=\"selectedPolicy.type === 'SHARED_POLICY_GROUP'\" class=\"gio-badge-neutral policiesCatalog__list__policy__head__badge\">\n <mat-icon svgIcon=\"gio:users\"></mat-icon>&nbsp;Shared Policy Group\n </span>\n </div>\n\n <div *ngIf=\"selectedPolicy.description\" class=\"policyForm__info__description\">{{ selectedPolicy.description }}</div>\n </div>\n\n <gio-ps-step-form\n [genericPolicy]=\"selectedPolicy\"\n [flowPhase]=\"flowPhase\"\n [apiType]=\"apiType\"\n (stepChange)=\"onStepChange($event)\"\n (isValid)=\"onIsValid($event)\"\n ></gio-ps-step-form>\n</mat-dialog-content>\n\n<mat-dialog-actions class=\"actions\" align=\"end\">\n <button class=\"actions__cancelBtn\" mat-button [mat-dialog-close]=\"\">Cancel</button>\n <button\n *ngIf=\"selectedPolicy\"\n class=\"actions__addBtn\"\n color=\"primary\"\n mat-flat-button\n role=\"dialog\"\n [disabled]=\"!isValid || isUnlicensed\"\n (click)=\"onAddPolicy()\"\n >\n Add policy\n </button>\n</mat-dialog-actions>\n", styles: ["@charset \"UTF-8\";.gio-top-bar-menu .gio-badge-accent{background-color:var(--gio-oem-palette--active, #ffc2ac);color:var(--gio-oem-palette--active-contrast, #1e1b1b)}.title__goBackBtn{margin-right:8px;line-height:normal}.title__closeBtn{top:0;right:-24px;float:right}.policiesCatalog__filters{display:flex;flex-direction:column;padding:0 0 8px;gap:8px}.policiesCatalog__filters__search{width:100%;height:54px;padding-bottom:0}.policiesCatalog__list{--grid-layout-gap: 16px;--grid-column-count: 3;--grid-item-min-width: 200px;--gap-count: calc(var(--grid-column-count) - 1);--total-gap-width: calc(var(--gap-count) * var(--grid-layout-gap));--grid-item-max-width: calc((100% - var(--total-gap-width)) / var(--grid-column-count));display:grid;grid-gap:var(--grid-layout-gap);grid-template-columns:repeat(auto-fill,minmax(max(var(--grid-item-min-width),var(--grid-item-max-width)),1fr))}.policiesCatalog__list__policy{position:relative;display:flex;flex-direction:column;align-items:flex-start;justify-content:space-between;padding:16px;border:1px solid #d2cecd;border-radius:8px;gap:4px}.policiesCatalog__list__policy__head{display:flex;align-items:center;align-self:stretch}.policiesCatalog__list__policy__head__icon{min-width:24px;flex:0 0 24px;margin-right:8px}.policiesCatalog__list__policy__head__name{overflow:hidden;flex:1 1 auto;text-overflow:ellipsis;white-space:nowrap}.policiesCatalog__list__policy__head__badge{float:left}.policiesCatalog__list__policy__enterprise{position:absolute;top:0;right:0;padding:8px 8px 8px 16px;border-radius:0 8px 0 38px;background:#f7f7f8;color:#da3b00}.policiesCatalog__list__policy__enterprise__lock{min-width:16px;max-width:16px;color:#da3b00}.policiesCatalog__list__policy__description{font-size:12px;font-weight:400;line-height:16px;font-family:Manrope,sans-serif;letter-spacing:normal;display:-webkit-box;overflow:hidden;-webkit-box-orient:vertical;color:#322f2f;-webkit-line-clamp:2}.policiesCatalog__list__policy__description:empty{display:none}.policiesCatalog__list__policy__selectBtn{margin-top:8px}.policyForm__goBackBtn{margin:16px 0}.policyForm__info{display:flex;max-width:100%;flex-direction:column;align-items:flex-start;padding-bottom:16px;gap:4px}.policyForm__info__head{display:flex;align-items:center}.policyForm__info__head__icon{min-width:24px;flex:1 1 24px;margin-right:8px}.policyForm__info__head__name{flex:1 1 auto}.policyForm__info__description{font-size:12px;font-weight:400;line-height:16px;font-family:Manrope,sans-serif;letter-spacing:normal;color:#322f2f}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "pipe", type: i2.TitleCasePipe, name: "titlecase" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i3.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i3.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i3.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i4.MatAnchor, selector: "a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button]", exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i4.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: i4.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "ngmodule", type: MatDialogModule }, { kind: "directive", type: i1.MatDialogClose, selector: "[mat-dialog-close], [matDialogClose]", inputs: ["aria-label", "type", "mat-dialog-close", "matDialogClose"], exportAs: ["matDialogClose"] }, { kind: "directive", type: i1.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: i1.MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }, { kind: "directive", type: i1.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i5.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i5.MatLabel, selector: "mat-label" }, { kind: "directive", type: i5.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatChipsModule }, { kind: "component", type: i6$2.MatChipListbox, selector: "mat-chip-listbox", inputs: ["multiple", "aria-orientation", "selectable", "compareWith", "required", "hideSingleSelectionIndicator", "value"], outputs: ["change"] }, { kind: "component", type: i6$2.MatChipOption, selector: "mat-basic-chip-option, [mat-basic-chip-option], mat-chip-option, [mat-chip-option]", inputs: ["selectable", "selected"], outputs: ["selectionChange"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i7$1.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: GioBannerModule }, { kind: "component", type: i6$1.GioBannerComponent, selector: "gio-banner", inputs: ["type", "icon", "collapsible"] }, { kind: "directive", type: i6$1.GioBannerBodyDirective, selector: "[gioBannerBody]" }, { kind: "directive", type: i6$1.GioBannerActionDirective, selector: "[gioBannerAction]" }, { kind: "ngmodule", type: GioIconsModule }, { kind: "component", type: i5$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: GioPolicyStudioStepFormComponent, selector: "gio-ps-step-form", inputs: ["readOnly", "step", "flowPhase", "apiType", "genericPolicy"], outputs: ["stepChange", "isValid"] }, { kind: "directive", type: MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }] }); }
1282
1349
  }
1283
1350
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: GioPolicyStudioPoliciesCatalogDialogComponent, decorators: [{
1284
1351
  type: Component,