@epistola.app/valtimo-plugin 0.3.2 → 0.3.3
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.
- package/fesm2022/epistola.app-valtimo-plugin.mjs +66 -26
- package/fesm2022/epistola.app-valtimo-plugin.mjs.map +1 -1
- package/lib/components/generate-document-configuration/generate-document-configuration.component.d.ts +16 -0
- package/lib/models/config.d.ts +11 -1
- package/lib/models/template.d.ts +7 -0
- package/lib/services/epistola-plugin.service.d.ts +5 -1
- package/package.json +4 -4
|
@@ -11,12 +11,12 @@ import * as i3 from '@valtimo/components';
|
|
|
11
11
|
import { FormModule, InputModule, ValuePathSelectorPrefix, ValuePathSelectorComponent, SelectModule, registerCustomFormioComponent } from '@valtimo/components';
|
|
12
12
|
import { BehaviorSubject, combineLatest, take, Subject, merge, of } from 'rxjs';
|
|
13
13
|
import { startWith, delay, takeUntil, filter, map, tap, switchMap, catchError, take as take$1, debounceTime } from 'rxjs/operators';
|
|
14
|
-
import * as
|
|
14
|
+
import * as i4 from '@angular/forms';
|
|
15
15
|
import { FormsModule } from '@angular/forms';
|
|
16
|
-
import * as i2$
|
|
16
|
+
import * as i2$2 from '@valtimo/process-link';
|
|
17
17
|
import * as i7 from '@formio/angular';
|
|
18
18
|
import { FormioModule } from '@formio/angular';
|
|
19
|
-
import * as i4 from '@angular/platform-browser';
|
|
19
|
+
import * as i4$1 from '@angular/platform-browser';
|
|
20
20
|
|
|
21
21
|
function initialResource(empty) {
|
|
22
22
|
return { data: empty, loading: false, error: null };
|
|
@@ -57,6 +57,12 @@ class EpistolaPluginService {
|
|
|
57
57
|
getTemplateDetails(pluginConfigurationId, templateId) {
|
|
58
58
|
return this.http.get(`${this.apiEndpoint}/configurations/${pluginConfigurationId}/templates/${templateId}`);
|
|
59
59
|
}
|
|
60
|
+
/**
|
|
61
|
+
* Get all attribute definitions for a plugin configuration's tenant.
|
|
62
|
+
*/
|
|
63
|
+
getAttributes(pluginConfigurationId) {
|
|
64
|
+
return this.http.get(`${this.apiEndpoint}/configurations/${pluginConfigurationId}/attributes`);
|
|
65
|
+
}
|
|
60
66
|
/**
|
|
61
67
|
* Get all available environments for a plugin configuration.
|
|
62
68
|
*/
|
|
@@ -291,7 +297,7 @@ class ValueInputComponent {
|
|
|
291
297
|
return 'browse';
|
|
292
298
|
}
|
|
293
299
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: ValueInputComponent, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
|
|
294
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.20", type: ValueInputComponent, isStandalone: true, selector: "epistola-value-input", inputs: { name: "name", value: "value", pluginId: "pluginId", caseDefinitionKey: "caseDefinitionKey", processVariables: "processVariables", disabled: "disabled", placeholder: "placeholder" }, outputs: { valueChange: "valueChange" }, usesOnChanges: true, ngImport: i0, template: "<div class=\"value-input\">\n <div class=\"input-mode-group\">\n <button type=\"button\" class=\"mode-btn\" [class.mode-active]=\"inputMode === 'browse'\" [disabled]=\"disabled\" (click)=\"setInputMode('browse')\" [title]=\"'browseMode' | pluginTranslate: pluginId | async\">\u229E</button>\n <button type=\"button\" class=\"mode-btn\" [class.mode-active]=\"inputMode === 'pv'\" [disabled]=\"disabled\" (click)=\"setInputMode('pv')\" [title]=\"'pvMode' | pluginTranslate: pluginId | async\">pv</button>\n <button type=\"button\" class=\"mode-btn\" [class.mode-active]=\"inputMode === 'expression'\" [disabled]=\"disabled\" (click)=\"setInputMode('expression')\" [title]=\"'expressionMode' | pluginTranslate: pluginId | async\">fx</button>\n </div>\n\n <!-- Browse mode: ValuePathSelector -->\n <div class=\"input-control\" *ngIf=\"inputMode === 'browse'\">\n <valtimo-value-path-selector\n [name]=\"name\"\n [caseDefinitionKey]=\"caseDefinitionKey\"\n [prefixes]=\"[ValuePathSelectorPrefix.DOC, ValuePathSelectorPrefix.CASE]\"\n [notation]=\"'dots'\"\n [disabled]=\"disabled\"\n [defaultValue]=\"browseDefault\"\n [showCaseDefinitionSelector]=\"!caseDefinitionKey\"\n (valueChangeEvent)=\"onBrowseValueChange($event)\"\n ></valtimo-value-path-selector>\n </div>\n\n <!-- PV mode: dropdown (when available) or text fallback -->\n <div class=\"input-control\" *ngIf=\"inputMode === 'pv'\">\n <select\n *ngIf=\"processVariables.length > 0; else pvFallback\"\n class=\"pv-select\"\n [disabled]=\"disabled\"\n [(ngModel)]=\"selectedPv\"\n (ngModelChange)=\"onPvChange($event)\"\n >\n <option value=\"\">{{ 'pvPlaceholder' | pluginTranslate: pluginId | async }}</option>\n <option *ngFor=\"let pv of processVariables\" [value]=\"pv\">{{ pv }}</option>\n </select>\n <ng-template #pvFallback>\n <v-input\n [name]=\"'pvfb_' + name\"\n [defaultValue]=\"selectedPv\"\n [disabled]=\"disabled\"\n [placeholder]=\"'pvPlaceholder' | pluginTranslate: pluginId | async\"\n (valueChange)=\"onPvChange($event)\"\n ></v-input>\n </ng-template>\n </div>\n\n <!-- Expression mode: text input -->\n <div class=\"input-control\" *ngIf=\"inputMode === 'expression'\">\n <v-input\n [name]=\"'fx_' + name\"\n [defaultValue]=\"value\"\n [disabled]=\"disabled\"\n [placeholder]=\"placeholder\"\n (valueChange)=\"onExpressionValueChange($event)\"\n ></v-input>\n </div>\n</div>\n", styles: [".value-input{display:flex;align-items:flex-start;gap:.5rem;min-width:0}.value-input ::ng-deep [data-test-id=valuePathSelectorToggle]{display:none!important}.input-control{flex:1;min-width:0}.input-mode-group{flex:0 0 auto;display:flex;margin-top:.25rem;border:1px solid #c6c6c6;border-radius:4px;overflow:hidden}.input-mode-group .mode-btn{width:32px;height:32px;padding:0;border:none;border-right:1px solid #c6c6c6;background:#f4f4f4;color:#525252;font-size:.75rem;font-weight:600;cursor:pointer;display:flex;align-items:center;justify-content:center;transition:background-color .15s}.input-mode-group .mode-btn:last-child{border-right:none}.input-mode-group .mode-btn:hover:not(:disabled){background:#e0e0e0}.input-mode-group .mode-btn.mode-active{background:#0f62fe;color:#fff}.input-mode-group .mode-btn.mode-active:hover:not(:disabled){background:#0353e9}.input-mode-group .mode-btn:disabled{opacity:.5;cursor:not-allowed}.pv-select{width:100%;height:2.5rem;padding:0 .75rem;border:1px solid #c6c6c6;border-radius:4px;background:#fff;color:#161616;font-size:.875rem;cursor:pointer}.pv-select:focus{outline:2px solid #0f62fe;outline-offset:-2px}.pv-select:disabled{opacity:.5;cursor:not-allowed;background:#f4f4f4}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "pipe", type: i1$1.AsyncPipe, name: "async" }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type:
|
|
300
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.20", type: ValueInputComponent, isStandalone: true, selector: "epistola-value-input", inputs: { name: "name", value: "value", pluginId: "pluginId", caseDefinitionKey: "caseDefinitionKey", processVariables: "processVariables", disabled: "disabled", placeholder: "placeholder" }, outputs: { valueChange: "valueChange" }, usesOnChanges: true, ngImport: i0, template: "<div class=\"value-input\">\n <div class=\"input-mode-group\">\n <button type=\"button\" class=\"mode-btn\" [class.mode-active]=\"inputMode === 'browse'\" [disabled]=\"disabled\" (click)=\"setInputMode('browse')\" [title]=\"'browseMode' | pluginTranslate: pluginId | async\">\u229E</button>\n <button type=\"button\" class=\"mode-btn\" [class.mode-active]=\"inputMode === 'pv'\" [disabled]=\"disabled\" (click)=\"setInputMode('pv')\" [title]=\"'pvMode' | pluginTranslate: pluginId | async\">pv</button>\n <button type=\"button\" class=\"mode-btn\" [class.mode-active]=\"inputMode === 'expression'\" [disabled]=\"disabled\" (click)=\"setInputMode('expression')\" [title]=\"'expressionMode' | pluginTranslate: pluginId | async\">fx</button>\n </div>\n\n <!-- Browse mode: ValuePathSelector -->\n <div class=\"input-control\" *ngIf=\"inputMode === 'browse'\">\n <valtimo-value-path-selector\n [name]=\"name\"\n [caseDefinitionKey]=\"caseDefinitionKey\"\n [prefixes]=\"[ValuePathSelectorPrefix.DOC, ValuePathSelectorPrefix.CASE]\"\n [notation]=\"'dots'\"\n [disabled]=\"disabled\"\n [defaultValue]=\"browseDefault\"\n [showCaseDefinitionSelector]=\"!caseDefinitionKey\"\n (valueChangeEvent)=\"onBrowseValueChange($event)\"\n ></valtimo-value-path-selector>\n </div>\n\n <!-- PV mode: dropdown (when available) or text fallback -->\n <div class=\"input-control\" *ngIf=\"inputMode === 'pv'\">\n <select\n *ngIf=\"processVariables.length > 0; else pvFallback\"\n class=\"pv-select\"\n [disabled]=\"disabled\"\n [(ngModel)]=\"selectedPv\"\n (ngModelChange)=\"onPvChange($event)\"\n >\n <option value=\"\">{{ 'pvPlaceholder' | pluginTranslate: pluginId | async }}</option>\n <option *ngFor=\"let pv of processVariables\" [value]=\"pv\">{{ pv }}</option>\n </select>\n <ng-template #pvFallback>\n <v-input\n [name]=\"'pvfb_' + name\"\n [defaultValue]=\"selectedPv\"\n [disabled]=\"disabled\"\n [placeholder]=\"'pvPlaceholder' | pluginTranslate: pluginId | async\"\n (valueChange)=\"onPvChange($event)\"\n ></v-input>\n </ng-template>\n </div>\n\n <!-- Expression mode: text input -->\n <div class=\"input-control\" *ngIf=\"inputMode === 'expression'\">\n <v-input\n [name]=\"'fx_' + name\"\n [defaultValue]=\"value\"\n [disabled]=\"disabled\"\n [placeholder]=\"placeholder\"\n (valueChange)=\"onExpressionValueChange($event)\"\n ></v-input>\n </div>\n</div>\n", styles: [".value-input{display:flex;align-items:flex-start;gap:.5rem;min-width:0}.value-input ::ng-deep [data-test-id=valuePathSelectorToggle]{display:none!important}.input-control{flex:1;min-width:0}.input-mode-group{flex:0 0 auto;display:flex;margin-top:.25rem;border:1px solid #c6c6c6;border-radius:4px;overflow:hidden}.input-mode-group .mode-btn{width:32px;height:32px;padding:0;border:none;border-right:1px solid #c6c6c6;background:#f4f4f4;color:#525252;font-size:.75rem;font-weight:600;cursor:pointer;display:flex;align-items:center;justify-content:center;transition:background-color .15s}.input-mode-group .mode-btn:last-child{border-right:none}.input-mode-group .mode-btn:hover:not(:disabled){background:#e0e0e0}.input-mode-group .mode-btn.mode-active{background:#0f62fe;color:#fff}.input-mode-group .mode-btn.mode-active:hover:not(:disabled){background:#0353e9}.input-mode-group .mode-btn:disabled{opacity:.5;cursor:not-allowed}.pv-select{width:100%;height:2.5rem;padding:0 .75rem;border:1px solid #c6c6c6;border-radius:4px;background:#fff;color:#161616;font-size:.875rem;cursor:pointer}.pv-select:focus{outline:2px solid #0f62fe;outline-offset:-2px}.pv-select:disabled{opacity:.5;cursor:not-allowed;background:#f4f4f4}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "pipe", type: i1$1.AsyncPipe, name: "async" }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i4.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i4.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i4.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i4.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i4.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: PluginTranslatePipeModule }, { kind: "pipe", type: i2$1.PluginTranslatePipe, name: "pluginTranslate" }, { kind: "ngmodule", type: InputModule }, { kind: "component", type: i3.InputComponent, selector: "v-input", inputs: ["name", "type", "title", "titleTranslationKey", "defaultValue", "widthPx", "fullWidth", "margin", "smallMargin", "disabled", "step", "min", "maxLength", "tooltip", "required", "hideNumberSpinBox", "smallLabel", "rows", "clear$", "carbonTheme", "placeholder", "dataTestId", "trim", "presetsTitle", "presetOptions"], outputs: ["valueChange"] }, { kind: "component", type: ValuePathSelectorComponent, selector: "valtimo-value-path-selector", inputs: ["name", "appendInline", "margin", "marginLg", "marginXl", "disabled", "caseDefinitionKey", "caseDefinitionVersionTag", "buildingBlockDefinitionKey", "buildingBlockDefinitionVersionTag", "prefixes", "label", "tooltip", "required", "showCaseDefinitionSelector", "notation", "dropUp", "defaultValue", "type", "parentItem", "filterItems"], outputs: ["valueChangeEvent", "collectionSelected"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
295
301
|
}
|
|
296
302
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: ValueInputComponent, decorators: [{
|
|
297
303
|
type: Component,
|
|
@@ -673,6 +679,7 @@ class GenerateDocumentConfigurationComponent {
|
|
|
673
679
|
selectedVariantId$ = new BehaviorSubject('');
|
|
674
680
|
variantSelectionMode = 'explicit';
|
|
675
681
|
variantAttributeEntries = [];
|
|
682
|
+
availableAttributeKeys = [];
|
|
676
683
|
caseDefinitionKey = null;
|
|
677
684
|
processVariables = [];
|
|
678
685
|
requiredFieldsStatus = { mapped: 0, total: 0 };
|
|
@@ -693,6 +700,7 @@ class GenerateDocumentConfigurationComponent {
|
|
|
693
700
|
this.initPluginConfiguration();
|
|
694
701
|
this.initTemplatesLoading();
|
|
695
702
|
this.initEnvironmentsLoading();
|
|
703
|
+
this.initAttributesLoading();
|
|
696
704
|
this.initVariantsLoading();
|
|
697
705
|
this.initTemplateFieldsLoading();
|
|
698
706
|
this.openSaveSubscription();
|
|
@@ -731,12 +739,12 @@ class GenerateDocumentConfigurationComponent {
|
|
|
731
739
|
onVariantSelectionModeChange(mode) {
|
|
732
740
|
this.variantSelectionMode = mode;
|
|
733
741
|
if (mode === 'attributes' && this.variantAttributeEntries.length === 0) {
|
|
734
|
-
this.variantAttributeEntries = [{ key: '', value: '' }];
|
|
742
|
+
this.variantAttributeEntries = [{ key: '', value: '', required: true }];
|
|
735
743
|
}
|
|
736
744
|
this.revalidate();
|
|
737
745
|
}
|
|
738
746
|
addAttributeEntry() {
|
|
739
|
-
this.variantAttributeEntries = [...this.variantAttributeEntries, { key: '', value: '' }];
|
|
747
|
+
this.variantAttributeEntries = [...this.variantAttributeEntries, { key: '', value: '', required: true }];
|
|
740
748
|
this.revalidate();
|
|
741
749
|
}
|
|
742
750
|
removeAttributeEntry(index) {
|
|
@@ -746,6 +754,21 @@ class GenerateDocumentConfigurationComponent {
|
|
|
746
754
|
onAttributeEntryChange() {
|
|
747
755
|
this.revalidate();
|
|
748
756
|
}
|
|
757
|
+
onKeySelected(entry, value) {
|
|
758
|
+
if (value === '__custom__') {
|
|
759
|
+
entry._customKey = true;
|
|
760
|
+
entry.key = '';
|
|
761
|
+
}
|
|
762
|
+
else {
|
|
763
|
+
entry.key = value;
|
|
764
|
+
}
|
|
765
|
+
this.onAttributeEntryChange();
|
|
766
|
+
}
|
|
767
|
+
cancelCustomKey(entry) {
|
|
768
|
+
entry._customKey = false;
|
|
769
|
+
entry.key = '';
|
|
770
|
+
this.onAttributeEntryChange();
|
|
771
|
+
}
|
|
749
772
|
revalidate() {
|
|
750
773
|
const currentFormValue = this.formValue$.getValue();
|
|
751
774
|
if (currentFormValue) {
|
|
@@ -770,10 +793,18 @@ class GenerateDocumentConfigurationComponent {
|
|
|
770
793
|
if (this.prefillConfiguration$) {
|
|
771
794
|
this.prefillConfiguration$.pipe(takeUntil(this.destroy$), filter(config => !!config?.templateId)).subscribe(config => {
|
|
772
795
|
this.selectedTemplateId$.next(config.templateId);
|
|
773
|
-
if (config.variantAttributes && Object.keys(config.variantAttributes).length > 0) {
|
|
796
|
+
if (config.variantAttributes && (Array.isArray(config.variantAttributes) ? config.variantAttributes.length > 0 : Object.keys(config.variantAttributes).length > 0)) {
|
|
774
797
|
this.variantSelectionMode = 'attributes';
|
|
775
|
-
|
|
776
|
-
|
|
798
|
+
if (Array.isArray(config.variantAttributes)) {
|
|
799
|
+
// New format: VariantAttributeEntry[]
|
|
800
|
+
this.variantAttributeEntries = config.variantAttributes
|
|
801
|
+
.map(e => ({ key: e.key, value: e.value, required: e.required !== false }));
|
|
802
|
+
}
|
|
803
|
+
else {
|
|
804
|
+
// Old format: Record<string, string> — treat all as required
|
|
805
|
+
this.variantAttributeEntries = Object.entries(config.variantAttributes)
|
|
806
|
+
.map(([key, value]) => ({ key, value: String(value), required: true }));
|
|
807
|
+
}
|
|
777
808
|
}
|
|
778
809
|
else if (config.variantId) {
|
|
779
810
|
this.variantSelectionMode = 'explicit';
|
|
@@ -813,6 +844,12 @@ class GenerateDocumentConfigurationComponent {
|
|
|
813
844
|
this.environments$.next(successResource(environments.map(e => ({ id: e.id, text: e.name }))));
|
|
814
845
|
});
|
|
815
846
|
}
|
|
847
|
+
initAttributesLoading() {
|
|
848
|
+
this.pluginConfigurationId$.pipe(takeUntil(this.destroy$), filter(id => !!id), switchMap(configurationId => this.epistolaPluginService.getAttributes(configurationId).pipe(catchError(() => of([]))))).subscribe(attributes => {
|
|
849
|
+
this.availableAttributeKeys = attributes.map(a => a.key).sort();
|
|
850
|
+
this.cdr.markForCheck();
|
|
851
|
+
});
|
|
852
|
+
}
|
|
816
853
|
initVariantsLoading() {
|
|
817
854
|
combineLatest([
|
|
818
855
|
this.pluginConfigurationId$,
|
|
@@ -880,20 +917,17 @@ class GenerateDocumentConfigurationComponent {
|
|
|
880
917
|
config.variantId = formValue.variantId;
|
|
881
918
|
}
|
|
882
919
|
else {
|
|
883
|
-
config.variantAttributes =
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
config.variantAttributes[entry.key] = entry.value;
|
|
887
|
-
}
|
|
888
|
-
}
|
|
920
|
+
config.variantAttributes = this.variantAttributeEntries
|
|
921
|
+
.filter(e => e.key && e.value)
|
|
922
|
+
.map(e => ({ key: e.key, value: e.value, required: e.required }));
|
|
889
923
|
}
|
|
890
924
|
this.configuration.emit(config);
|
|
891
925
|
}
|
|
892
926
|
});
|
|
893
927
|
});
|
|
894
928
|
}
|
|
895
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: GenerateDocumentConfigurationComponent, deps: [{ token: EpistolaPluginService }, { token: i2$
|
|
896
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.20", type: GenerateDocumentConfigurationComponent, isStandalone: true, selector: "epistola-generate-document-configuration", inputs: { save$: "save$", disabled$: "disabled$", pluginId: "pluginId", prefillConfiguration$: "prefillConfiguration$", selectedPluginConfigurationData$: "selectedPluginConfigurationData$", context$: "context$" }, outputs: { valid: "valid", configuration: "configuration" }, ngImport: i0, template: "<v-form\n (valueChange)=\"formValueChange($event)\"\n *ngIf=\"{\n disabled: disabled$ | async,\n prefill: prefillConfiguration$ ? (prefillConfiguration$ | async) : null,\n templates: templates$ | async,\n variants: variants$ | async,\n environments: environments$ | async,\n templateFields: templateFields$ | async,\n selectedTemplateId: selectedTemplateId$ | async\n } as obs\"\n>\n <v-select\n name=\"templateId\"\n [title]=\"'templateId' | pluginTranslate: pluginId | async\"\n [tooltip]=\"'templateIdTooltip' | pluginTranslate: pluginId | async\"\n [margin]=\"true\"\n [items]=\"obs.templates.data\"\n [defaultSelectionId]=\"obs.prefill?.templateId\"\n [disabled]=\"obs.disabled || obs.templates.loading\"\n [required]=\"true\"\n [loading]=\"obs.templates.loading\"\n >\n </v-select>\n <div *ngIf=\"obs.templates.error\" class=\"loading-error\">{{ obs.templates.error }}</div>\n\n <!-- Variant selection mode toggle -->\n <div class=\"variant-mode-toggle\" *ngIf=\"obs.selectedTemplateId\">\n <label class=\"variant-mode-label\">{{ 'variantSelectionMode' | pluginTranslate: pluginId | async }}</label>\n <div class=\"variant-mode-buttons\">\n <button\n type=\"button\"\n class=\"variant-mode-btn\"\n [class.active]=\"variantSelectionMode === 'explicit'\"\n (click)=\"onVariantSelectionModeChange('explicit')\"\n [disabled]=\"obs.disabled\"\n >{{ 'selectByVariant' | pluginTranslate: pluginId | async }}</button>\n <button\n type=\"button\"\n class=\"variant-mode-btn\"\n [class.active]=\"variantSelectionMode === 'attributes'\"\n (click)=\"onVariantSelectionModeChange('attributes')\"\n [disabled]=\"obs.disabled\"\n >{{ 'selectByAttributes' | pluginTranslate: pluginId | async }}</button>\n </div>\n </div>\n\n <!-- Explicit variant selection (dropdown) -->\n <v-select\n *ngIf=\"variantSelectionMode === 'explicit'\"\n name=\"variantId\"\n [title]=\"'variantId' | pluginTranslate: pluginId | async\"\n [tooltip]=\"'variantIdTooltip' | pluginTranslate: pluginId | async\"\n [margin]=\"true\"\n [items]=\"obs.variants.data\"\n [defaultSelectionId]=\"obs.prefill?.variantId\"\n [disabled]=\"obs.disabled || obs.variants.loading || !obs.selectedTemplateId\"\n [required]=\"false\"\n [loading]=\"obs.variants.loading\"\n >\n </v-select>\n <div *ngIf=\"obs.variants.error\" class=\"loading-error\">{{ obs.variants.error }}</div>\n\n <!-- Attribute-based variant selection -->\n <div *ngIf=\"variantSelectionMode === 'attributes' && obs.selectedTemplateId\" class=\"variant-attributes-section\">\n <label class=\"variant-attributes-label\">{{ 'variantAttributes' | pluginTranslate: pluginId | async }}</label>\n <div class=\"variant-attributes-list\">\n <div *ngFor=\"let entry of variantAttributeEntries; let i = index\" class=\"variant-attribute-row\">\n <input\n type=\"text\"\n class=\"variant-attribute-input\"\n [placeholder]=\"'attributeKey' | pluginTranslate: pluginId | async\"\n [(ngModel)]=\"entry.key\"\n (ngModelChange)=\"onAttributeEntryChange()\"\n [disabled]=\"obs.disabled\"\n />\n <input\n type=\"text\"\n class=\"variant-attribute-input\"\n [placeholder]=\"'attributeValue' | pluginTranslate: pluginId | async\"\n [(ngModel)]=\"entry.value\"\n (ngModelChange)=\"onAttributeEntryChange()\"\n [disabled]=\"obs.disabled\"\n />\n <button\n type=\"button\"\n class=\"variant-attribute-remove-btn\"\n (click)=\"removeAttributeEntry(i)\"\n [disabled]=\"obs.disabled\"\n title=\"{{ 'removeAttribute' | pluginTranslate: pluginId | async }}\"\n >×</button>\n </div>\n </div>\n <button\n type=\"button\"\n class=\"variant-attribute-add-btn\"\n (click)=\"addAttributeEntry()\"\n [disabled]=\"obs.disabled\"\n >+ {{ 'addAttribute' | pluginTranslate: pluginId | async }}</button>\n </div>\n\n <v-select\n name=\"environmentId\"\n [title]=\"'environmentId' | pluginTranslate: pluginId | async\"\n [tooltip]=\"'environmentIdTooltip' | pluginTranslate: pluginId | async\"\n [margin]=\"true\"\n [items]=\"obs.environments.data\"\n [defaultSelectionId]=\"obs.prefill?.environmentId\"\n [disabled]=\"obs.disabled || obs.environments.loading\"\n [required]=\"false\"\n [loading]=\"obs.environments.loading\"\n >\n </v-select>\n <div *ngIf=\"obs.environments.error\" class=\"loading-error\">{{ obs.environments.error }}</div>\n\n <v-select\n name=\"outputFormat\"\n [title]=\"'outputFormat' | pluginTranslate: pluginId | async\"\n [tooltip]=\"'outputFormatTooltip' | pluginTranslate: pluginId | async\"\n [margin]=\"true\"\n [items]=\"outputFormatOptions\"\n [defaultSelectionId]=\"obs.prefill?.outputFormat || 'PDF'\"\n [disabled]=\"obs.disabled\"\n [required]=\"true\"\n >\n </v-select>\n\n <v-input\n name=\"filename\"\n [title]=\"'filename' | pluginTranslate: pluginId | async\"\n [tooltip]=\"'filenameTooltip' | pluginTranslate: pluginId | async\"\n [margin]=\"true\"\n [defaultValue]=\"obs.prefill?.filename\"\n [disabled]=\"obs.disabled\"\n [required]=\"true\"\n >\n </v-input>\n\n <v-input\n name=\"correlationId\"\n [title]=\"'correlationId' | pluginTranslate: pluginId | async\"\n [tooltip]=\"'correlationIdTooltip' | pluginTranslate: pluginId | async\"\n [margin]=\"true\"\n [defaultValue]=\"obs.prefill?.correlationId\"\n [disabled]=\"obs.disabled\"\n [required]=\"false\"\n >\n </v-input>\n\n <v-input\n name=\"resultProcessVariable\"\n [title]=\"'resultProcessVariable' | pluginTranslate: pluginId | async\"\n [tooltip]=\"'resultProcessVariableTooltip' | pluginTranslate: pluginId | async\"\n [margin]=\"true\"\n [defaultValue]=\"obs.prefill?.resultProcessVariable\"\n [disabled]=\"obs.disabled\"\n [required]=\"true\"\n >\n </v-input>\n</v-form>\n\n<div *ngIf=\"(templateFields$ | async)?.error as templateFieldsError\" class=\"loading-error\">{{ templateFieldsError }}</div>\n\n<epistola-data-mapping-tree\n *ngIf=\"(selectedTemplateId$ | async)\"\n [pluginId]=\"pluginId\"\n [templateFields]=\"(templateFields$ | async)?.data ?? []\"\n [disabled]=\"!!(disabled$ | async)\"\n [prefillMapping]=\"prefillDataMapping\"\n [caseDefinitionKey]=\"caseDefinitionKey\"\n [processVariables]=\"processVariables\"\n (mappingChange)=\"onDataMappingChange($event)\"\n (requiredFieldsStatus)=\"onRequiredFieldsStatusChange($event)\"\n></epistola-data-mapping-tree>\n\n<div class=\"validation-summary\" *ngIf=\"(selectedTemplateId$ | async) && requiredFieldsStatus.total > 0\">\n <span *ngIf=\"requiredFieldsStatus.mapped === requiredFieldsStatus.total\" class=\"validation-complete\">\n {{ 'requiredFieldsComplete' | pluginTranslate: pluginId | async }}\n </span>\n <span *ngIf=\"requiredFieldsStatus.mapped < requiredFieldsStatus.total\" class=\"validation-incomplete\">\n {{ requiredFieldsStatus.mapped }} / {{ requiredFieldsStatus.total }}\n {{ 'validationSummary' | pluginTranslate: pluginId | async }}\n </span>\n</div>\n", styles: [".loading-error{padding:.25rem .75rem;font-size:.8125rem;color:#dc3545}.validation-summary{margin-top:.5rem;padding:.5rem .75rem;border-radius:4px;font-size:.875rem}.validation-summary .validation-complete{color:#198754}.validation-summary .validation-incomplete{color:#dc3545;font-weight:500}.variant-mode-toggle{margin-bottom:1rem;padding:0 .75rem}.variant-mode-label{display:block;font-size:.875rem;font-weight:500;margin-bottom:.375rem}.variant-mode-buttons{display:flex;gap:0;border:1px solid #d1d5db;border-radius:4px;overflow:hidden;width:fit-content}.variant-mode-btn{padding:.375rem .75rem;font-size:.8125rem;background:#fff;border:none;border-right:1px solid #d1d5db;cursor:pointer;color:#374151;transition:background-color .15s,color .15s}.variant-mode-btn:last-child{border-right:none}.variant-mode-btn:hover:not([disabled]){background:#f3f4f6}.variant-mode-btn.active{background:#2563eb;color:#fff}.variant-mode-btn[disabled]{opacity:.5;cursor:not-allowed}.variant-attributes-section{margin-bottom:1rem;padding:0 .75rem}.variant-attributes-label{display:block;font-size:.875rem;font-weight:500;margin-bottom:.375rem}.variant-attributes-list{display:flex;flex-direction:column;gap:.375rem}.variant-attribute-row{display:flex;gap:.375rem;align-items:center}.variant-attribute-input{flex:1;padding:.375rem .5rem;font-size:.8125rem;border:1px solid #d1d5db;border-radius:4px;outline:none}.variant-attribute-input:focus{border-color:#2563eb;box-shadow:0 0 0 1px #2563eb}.variant-attribute-input[disabled]{opacity:.5;background:#f9fafb}.variant-attribute-remove-btn{padding:.25rem .5rem;font-size:1rem;line-height:1;background:none;border:1px solid #d1d5db;border-radius:4px;cursor:pointer;color:#6b7280}.variant-attribute-remove-btn:hover:not([disabled]){color:#dc3545;border-color:#dc3545}.variant-attribute-remove-btn[disabled]{opacity:.5;cursor:not-allowed}.variant-attribute-add-btn{margin-top:.375rem;padding:.25rem .5rem;font-size:.8125rem;background:none;border:1px dashed #d1d5db;border-radius:4px;cursor:pointer;color:#6b7280}.variant-attribute-add-btn:hover:not([disabled]){color:#2563eb;border-color:#2563eb}.variant-attribute-add-btn[disabled]{opacity:.5;cursor:not-allowed}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "pipe", type: i1$1.AsyncPipe, name: "async" }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2$2.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: i2$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: PluginTranslatePipeModule }, { kind: "pipe", type: i2$1.PluginTranslatePipe, name: "pluginTranslate" }, { kind: "ngmodule", type: FormModule }, { kind: "component", type: i3.FormComponent, selector: "v-form", inputs: ["className"], outputs: ["valueChange"] }, { kind: "ngmodule", type: InputModule }, { kind: "component", type: i3.InputComponent, selector: "v-input", inputs: ["name", "type", "title", "titleTranslationKey", "defaultValue", "widthPx", "fullWidth", "margin", "smallMargin", "disabled", "step", "min", "maxLength", "tooltip", "required", "hideNumberSpinBox", "smallLabel", "rows", "clear$", "carbonTheme", "placeholder", "dataTestId", "trim", "presetsTitle", "presetOptions"], outputs: ["valueChange"] }, { kind: "ngmodule", type: SelectModule }, { kind: "component", type: i3.SelectComponent, selector: "v-select", inputs: ["items", "defaultSelection", "defaultSelectionId", "defaultSelectionIds", "disabled", "dropUp", "invalid", "multiple", "margin", "widthInPx", "notFoundText", "clearAllText", "clearText", "clearable", "name", "title", "titleTranslationKey", "clearSelectionSubject$", "tooltip", "required", "loading", "loadingText", "placeholder", "smallMargin", "carbonTheme", "appendInline", "warn", "warnText", "dataTestId"], outputs: ["selectedChange"] }, { kind: "component", type: DataMappingTreeComponent, selector: "epistola-data-mapping-tree", inputs: ["pluginId", "templateFields", "prefillMapping", "disabled", "caseDefinitionKey", "processVariables"], outputs: ["mappingChange", "requiredFieldsStatus"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
929
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: GenerateDocumentConfigurationComponent, deps: [{ token: EpistolaPluginService }, { token: i2$2.ProcessLinkStateService }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
|
|
930
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.20", type: GenerateDocumentConfigurationComponent, isStandalone: true, selector: "epistola-generate-document-configuration", inputs: { save$: "save$", disabled$: "disabled$", pluginId: "pluginId", prefillConfiguration$: "prefillConfiguration$", selectedPluginConfigurationData$: "selectedPluginConfigurationData$", context$: "context$" }, outputs: { valid: "valid", configuration: "configuration" }, ngImport: i0, template: "<v-form\n (valueChange)=\"formValueChange($event)\"\n *ngIf=\"{\n disabled: disabled$ | async,\n prefill: prefillConfiguration$ ? (prefillConfiguration$ | async) : null,\n templates: templates$ | async,\n variants: variants$ | async,\n environments: environments$ | async,\n templateFields: templateFields$ | async,\n selectedTemplateId: selectedTemplateId$ | async\n } as obs\"\n>\n <v-select\n name=\"templateId\"\n [title]=\"'templateId' | pluginTranslate: pluginId | async\"\n [tooltip]=\"'templateIdTooltip' | pluginTranslate: pluginId | async\"\n [margin]=\"true\"\n [items]=\"obs.templates.data\"\n [defaultSelectionId]=\"obs.prefill?.templateId\"\n [disabled]=\"obs.disabled || obs.templates.loading\"\n [required]=\"true\"\n [loading]=\"obs.templates.loading\"\n >\n </v-select>\n <div *ngIf=\"obs.templates.error\" class=\"loading-error\">{{ obs.templates.error }}</div>\n\n <!-- Variant selection mode toggle -->\n <div class=\"variant-mode-toggle\" *ngIf=\"obs.selectedTemplateId\">\n <label class=\"variant-mode-label\">{{ 'variantSelectionMode' | pluginTranslate: pluginId | async }}</label>\n <div class=\"variant-mode-buttons\">\n <button\n type=\"button\"\n class=\"variant-mode-btn\"\n [class.active]=\"variantSelectionMode === 'explicit'\"\n (click)=\"onVariantSelectionModeChange('explicit')\"\n [disabled]=\"obs.disabled\"\n >{{ 'selectByVariant' | pluginTranslate: pluginId | async }}</button>\n <button\n type=\"button\"\n class=\"variant-mode-btn\"\n [class.active]=\"variantSelectionMode === 'attributes'\"\n (click)=\"onVariantSelectionModeChange('attributes')\"\n [disabled]=\"obs.disabled\"\n >{{ 'selectByAttributes' | pluginTranslate: pluginId | async }}</button>\n </div>\n </div>\n\n <!-- Explicit variant selection (dropdown) -->\n <v-select\n *ngIf=\"variantSelectionMode === 'explicit'\"\n name=\"variantId\"\n [title]=\"'variantId' | pluginTranslate: pluginId | async\"\n [tooltip]=\"'variantIdTooltip' | pluginTranslate: pluginId | async\"\n [margin]=\"true\"\n [items]=\"obs.variants.data\"\n [defaultSelectionId]=\"obs.prefill?.variantId\"\n [disabled]=\"obs.disabled || obs.variants.loading || !obs.selectedTemplateId\"\n [required]=\"false\"\n [loading]=\"obs.variants.loading\"\n >\n </v-select>\n <div *ngIf=\"obs.variants.error\" class=\"loading-error\">{{ obs.variants.error }}</div>\n\n <!-- Attribute-based variant selection -->\n <div *ngIf=\"variantSelectionMode === 'attributes' && obs.selectedTemplateId\" class=\"variant-attributes-section\">\n <label class=\"variant-attributes-label\">{{ 'variantAttributes' | pluginTranslate: pluginId | async }}</label>\n <div class=\"variant-attributes-list\">\n <div *ngFor=\"let entry of variantAttributeEntries; let i = index\" class=\"variant-attribute-row\">\n <select\n *ngIf=\"!entry._customKey\"\n class=\"variant-attribute-input\"\n [ngModel]=\"entry.key\"\n (ngModelChange)=\"onKeySelected(entry, $event)\"\n [disabled]=\"obs.disabled\"\n >\n <option value=\"\" disabled>{{ 'attributeKey' | pluginTranslate: pluginId | async }}</option>\n <option *ngFor=\"let key of availableAttributeKeys\" [value]=\"key\">{{ key }}</option>\n <option value=\"__custom__\">{{ 'attributeKeyCustom' | pluginTranslate: pluginId | async }}</option>\n </select>\n <div *ngIf=\"entry._customKey\" class=\"custom-key-input\">\n <input\n type=\"text\"\n class=\"variant-attribute-input\"\n [placeholder]=\"'attributeKey' | pluginTranslate: pluginId | async\"\n [(ngModel)]=\"entry.key\"\n (ngModelChange)=\"onAttributeEntryChange()\"\n [disabled]=\"obs.disabled\"\n />\n <button type=\"button\" class=\"custom-key-cancel\" (click)=\"cancelCustomKey(entry)\" [disabled]=\"obs.disabled\">×</button>\n </div>\n <input\n type=\"text\"\n class=\"variant-attribute-input\"\n [placeholder]=\"'attributeValue' | pluginTranslate: pluginId | async\"\n [(ngModel)]=\"entry.value\"\n (ngModelChange)=\"onAttributeEntryChange()\"\n [disabled]=\"obs.disabled\"\n />\n <label class=\"variant-attribute-required-toggle\">\n <input\n type=\"checkbox\"\n [(ngModel)]=\"entry.required\"\n (ngModelChange)=\"onAttributeEntryChange()\"\n [disabled]=\"obs.disabled\"\n />\n <span class=\"required-label\">{{ (entry.required ? 'attributeRequired' : 'attributePreferred') | pluginTranslate: pluginId | async }}</span>\n </label>\n <button\n type=\"button\"\n class=\"variant-attribute-remove-btn\"\n (click)=\"removeAttributeEntry(i)\"\n [disabled]=\"obs.disabled\"\n title=\"{{ 'removeAttribute' | pluginTranslate: pluginId | async }}\"\n >×</button>\n </div>\n </div>\n <button\n type=\"button\"\n class=\"variant-attribute-add-btn\"\n (click)=\"addAttributeEntry()\"\n [disabled]=\"obs.disabled\"\n >+ {{ 'addAttribute' | pluginTranslate: pluginId | async }}</button>\n </div>\n\n <v-select\n name=\"environmentId\"\n [title]=\"'environmentId' | pluginTranslate: pluginId | async\"\n [tooltip]=\"'environmentIdTooltip' | pluginTranslate: pluginId | async\"\n [margin]=\"true\"\n [items]=\"obs.environments.data\"\n [defaultSelectionId]=\"obs.prefill?.environmentId\"\n [disabled]=\"obs.disabled || obs.environments.loading\"\n [required]=\"false\"\n [loading]=\"obs.environments.loading\"\n >\n </v-select>\n <div *ngIf=\"obs.environments.error\" class=\"loading-error\">{{ obs.environments.error }}</div>\n\n <v-select\n name=\"outputFormat\"\n [title]=\"'outputFormat' | pluginTranslate: pluginId | async\"\n [tooltip]=\"'outputFormatTooltip' | pluginTranslate: pluginId | async\"\n [margin]=\"true\"\n [items]=\"outputFormatOptions\"\n [defaultSelectionId]=\"obs.prefill?.outputFormat || 'PDF'\"\n [disabled]=\"obs.disabled\"\n [required]=\"true\"\n >\n </v-select>\n\n <v-input\n name=\"filename\"\n [title]=\"'filename' | pluginTranslate: pluginId | async\"\n [tooltip]=\"'filenameTooltip' | pluginTranslate: pluginId | async\"\n [margin]=\"true\"\n [defaultValue]=\"obs.prefill?.filename\"\n [disabled]=\"obs.disabled\"\n [required]=\"true\"\n >\n </v-input>\n\n <v-input\n name=\"correlationId\"\n [title]=\"'correlationId' | pluginTranslate: pluginId | async\"\n [tooltip]=\"'correlationIdTooltip' | pluginTranslate: pluginId | async\"\n [margin]=\"true\"\n [defaultValue]=\"obs.prefill?.correlationId\"\n [disabled]=\"obs.disabled\"\n [required]=\"false\"\n >\n </v-input>\n\n <v-input\n name=\"resultProcessVariable\"\n [title]=\"'resultProcessVariable' | pluginTranslate: pluginId | async\"\n [tooltip]=\"'resultProcessVariableTooltip' | pluginTranslate: pluginId | async\"\n [margin]=\"true\"\n [defaultValue]=\"obs.prefill?.resultProcessVariable\"\n [disabled]=\"obs.disabled\"\n [required]=\"true\"\n >\n </v-input>\n</v-form>\n\n<div *ngIf=\"(templateFields$ | async)?.error as templateFieldsError\" class=\"loading-error\">{{ templateFieldsError }}</div>\n\n<epistola-data-mapping-tree\n *ngIf=\"(selectedTemplateId$ | async)\"\n [pluginId]=\"pluginId\"\n [templateFields]=\"(templateFields$ | async)?.data ?? []\"\n [disabled]=\"!!(disabled$ | async)\"\n [prefillMapping]=\"prefillDataMapping\"\n [caseDefinitionKey]=\"caseDefinitionKey\"\n [processVariables]=\"processVariables\"\n (mappingChange)=\"onDataMappingChange($event)\"\n (requiredFieldsStatus)=\"onRequiredFieldsStatusChange($event)\"\n></epistola-data-mapping-tree>\n\n<div class=\"validation-summary\" *ngIf=\"(selectedTemplateId$ | async) && requiredFieldsStatus.total > 0\">\n <span *ngIf=\"requiredFieldsStatus.mapped === requiredFieldsStatus.total\" class=\"validation-complete\">\n {{ 'requiredFieldsComplete' | pluginTranslate: pluginId | async }}\n </span>\n <span *ngIf=\"requiredFieldsStatus.mapped < requiredFieldsStatus.total\" class=\"validation-incomplete\">\n {{ requiredFieldsStatus.mapped }} / {{ requiredFieldsStatus.total }}\n {{ 'validationSummary' | pluginTranslate: pluginId | async }}\n </span>\n</div>\n", styles: [".loading-error{padding:.25rem .75rem;font-size:.8125rem;color:#dc3545}.validation-summary{margin-top:.5rem;padding:.5rem .75rem;border-radius:4px;font-size:.875rem}.validation-summary .validation-complete{color:#198754}.validation-summary .validation-incomplete{color:#dc3545;font-weight:500}.variant-mode-toggle{margin-bottom:1rem;padding:0 .75rem}.variant-mode-label{display:block;font-size:.875rem;font-weight:500;margin-bottom:.375rem}.variant-mode-buttons{display:flex;gap:0;border:1px solid #d1d5db;border-radius:4px;overflow:hidden;width:fit-content}.variant-mode-btn{padding:.375rem .75rem;font-size:.8125rem;background:#fff;border:none;border-right:1px solid #d1d5db;cursor:pointer;color:#374151;transition:background-color .15s,color .15s}.variant-mode-btn:last-child{border-right:none}.variant-mode-btn:hover:not([disabled]){background:#f3f4f6}.variant-mode-btn.active{background:#2563eb;color:#fff}.variant-mode-btn[disabled]{opacity:.5;cursor:not-allowed}.variant-attributes-section{margin-bottom:1rem;padding:0 .75rem}.variant-attributes-label{display:block;font-size:.875rem;font-weight:500;margin-bottom:.375rem}.variant-attributes-list{display:flex;flex-direction:column;gap:.375rem}.variant-attribute-row{display:flex;gap:.375rem;align-items:center}.variant-attribute-input{flex:1;padding:.375rem .5rem;font-size:.8125rem;border:1px solid #d1d5db;border-radius:4px;outline:none}.variant-attribute-input:focus{border-color:#2563eb;box-shadow:0 0 0 1px #2563eb}.variant-attribute-input[disabled]{opacity:.5;background:#f9fafb}.custom-key-input{display:flex;flex:1;gap:.25rem}.custom-key-input .variant-attribute-input{flex:1}.custom-key-cancel{padding:.25rem .5rem;font-size:1rem;line-height:1;background:none;border:1px solid #d1d5db;border-radius:4px;cursor:pointer;color:#6b7280}.custom-key-cancel:hover:not([disabled]){color:#dc3545;border-color:#dc3545}.custom-key-cancel[disabled]{opacity:.5;cursor:not-allowed}.variant-attribute-required-toggle{display:flex;align-items:center;gap:.25rem;font-size:.75rem;color:#374151;white-space:nowrap;cursor:pointer}.variant-attribute-required-toggle input[type=checkbox]{margin:0;cursor:pointer}.variant-attribute-required-toggle .required-label{-webkit-user-select:none;user-select:none}.variant-attribute-remove-btn{padding:.25rem .5rem;font-size:1rem;line-height:1;background:none;border:1px solid #d1d5db;border-radius:4px;cursor:pointer;color:#6b7280}.variant-attribute-remove-btn:hover:not([disabled]){color:#dc3545;border-color:#dc3545}.variant-attribute-remove-btn[disabled]{opacity:.5;cursor:not-allowed}.variant-attribute-add-btn{margin-top:.375rem;padding:.25rem .5rem;font-size:.8125rem;background:none;border:1px dashed #d1d5db;border-radius:4px;cursor:pointer;color:#6b7280}.variant-attribute-add-btn:hover:not([disabled]){color:#2563eb;border-color:#2563eb}.variant-attribute-add-btn[disabled]{opacity:.5;cursor:not-allowed}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "pipe", type: i1$1.AsyncPipe, name: "async" }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i4.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i4.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i4.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: i4.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i4.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i4.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i4.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: PluginTranslatePipeModule }, { kind: "pipe", type: i2$1.PluginTranslatePipe, name: "pluginTranslate" }, { kind: "ngmodule", type: FormModule }, { kind: "component", type: i3.FormComponent, selector: "v-form", inputs: ["className"], outputs: ["valueChange"] }, { kind: "ngmodule", type: InputModule }, { kind: "component", type: i3.InputComponent, selector: "v-input", inputs: ["name", "type", "title", "titleTranslationKey", "defaultValue", "widthPx", "fullWidth", "margin", "smallMargin", "disabled", "step", "min", "maxLength", "tooltip", "required", "hideNumberSpinBox", "smallLabel", "rows", "clear$", "carbonTheme", "placeholder", "dataTestId", "trim", "presetsTitle", "presetOptions"], outputs: ["valueChange"] }, { kind: "ngmodule", type: SelectModule }, { kind: "component", type: i3.SelectComponent, selector: "v-select", inputs: ["items", "defaultSelection", "defaultSelectionId", "defaultSelectionIds", "disabled", "dropUp", "invalid", "multiple", "margin", "widthInPx", "notFoundText", "clearAllText", "clearText", "clearable", "name", "title", "titleTranslationKey", "clearSelectionSubject$", "tooltip", "required", "loading", "loadingText", "placeholder", "smallMargin", "carbonTheme", "appendInline", "warn", "warnText", "dataTestId"], outputs: ["selectedChange"] }, { kind: "component", type: DataMappingTreeComponent, selector: "epistola-data-mapping-tree", inputs: ["pluginId", "templateFields", "prefillMapping", "disabled", "caseDefinitionKey", "processVariables"], outputs: ["mappingChange", "requiredFieldsStatus"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
897
931
|
}
|
|
898
932
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: GenerateDocumentConfigurationComponent, decorators: [{
|
|
899
933
|
type: Component,
|
|
@@ -905,8 +939,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.20", ngImpo
|
|
|
905
939
|
InputModule,
|
|
906
940
|
SelectModule,
|
|
907
941
|
DataMappingTreeComponent
|
|
908
|
-
], template: "<v-form\n (valueChange)=\"formValueChange($event)\"\n *ngIf=\"{\n disabled: disabled$ | async,\n prefill: prefillConfiguration$ ? (prefillConfiguration$ | async) : null,\n templates: templates$ | async,\n variants: variants$ | async,\n environments: environments$ | async,\n templateFields: templateFields$ | async,\n selectedTemplateId: selectedTemplateId$ | async\n } as obs\"\n>\n <v-select\n name=\"templateId\"\n [title]=\"'templateId' | pluginTranslate: pluginId | async\"\n [tooltip]=\"'templateIdTooltip' | pluginTranslate: pluginId | async\"\n [margin]=\"true\"\n [items]=\"obs.templates.data\"\n [defaultSelectionId]=\"obs.prefill?.templateId\"\n [disabled]=\"obs.disabled || obs.templates.loading\"\n [required]=\"true\"\n [loading]=\"obs.templates.loading\"\n >\n </v-select>\n <div *ngIf=\"obs.templates.error\" class=\"loading-error\">{{ obs.templates.error }}</div>\n\n <!-- Variant selection mode toggle -->\n <div class=\"variant-mode-toggle\" *ngIf=\"obs.selectedTemplateId\">\n <label class=\"variant-mode-label\">{{ 'variantSelectionMode' | pluginTranslate: pluginId | async }}</label>\n <div class=\"variant-mode-buttons\">\n <button\n type=\"button\"\n class=\"variant-mode-btn\"\n [class.active]=\"variantSelectionMode === 'explicit'\"\n (click)=\"onVariantSelectionModeChange('explicit')\"\n [disabled]=\"obs.disabled\"\n >{{ 'selectByVariant' | pluginTranslate: pluginId | async }}</button>\n <button\n type=\"button\"\n class=\"variant-mode-btn\"\n [class.active]=\"variantSelectionMode === 'attributes'\"\n (click)=\"onVariantSelectionModeChange('attributes')\"\n [disabled]=\"obs.disabled\"\n >{{ 'selectByAttributes' | pluginTranslate: pluginId | async }}</button>\n </div>\n </div>\n\n <!-- Explicit variant selection (dropdown) -->\n <v-select\n *ngIf=\"variantSelectionMode === 'explicit'\"\n name=\"variantId\"\n [title]=\"'variantId' | pluginTranslate: pluginId | async\"\n [tooltip]=\"'variantIdTooltip' | pluginTranslate: pluginId | async\"\n [margin]=\"true\"\n [items]=\"obs.variants.data\"\n [defaultSelectionId]=\"obs.prefill?.variantId\"\n [disabled]=\"obs.disabled || obs.variants.loading || !obs.selectedTemplateId\"\n [required]=\"false\"\n [loading]=\"obs.variants.loading\"\n >\n </v-select>\n <div *ngIf=\"obs.variants.error\" class=\"loading-error\">{{ obs.variants.error }}</div>\n\n <!-- Attribute-based variant selection -->\n <div *ngIf=\"variantSelectionMode === 'attributes' && obs.selectedTemplateId\" class=\"variant-attributes-section\">\n <label class=\"variant-attributes-label\">{{ 'variantAttributes' | pluginTranslate: pluginId | async }}</label>\n <div class=\"variant-attributes-list\">\n <div *ngFor=\"let entry of variantAttributeEntries; let i = index\" class=\"variant-attribute-row\">\n <input\n type=\"text\"\n class=\"variant-attribute-input\"\n [placeholder]=\"'attributeKey' | pluginTranslate: pluginId | async\"\n [(ngModel)]=\"entry.key\"\n (ngModelChange)=\"onAttributeEntryChange()\"\n [disabled]=\"obs.disabled\"\n />\n <input\n type=\"text\"\n class=\"variant-attribute-input\"\n [placeholder]=\"'attributeValue' | pluginTranslate: pluginId | async\"\n [(ngModel)]=\"entry.value\"\n (ngModelChange)=\"onAttributeEntryChange()\"\n [disabled]=\"obs.disabled\"\n />\n <button\n type=\"button\"\n class=\"variant-attribute-remove-btn\"\n (click)=\"removeAttributeEntry(i)\"\n [disabled]=\"obs.disabled\"\n title=\"{{ 'removeAttribute' | pluginTranslate: pluginId | async }}\"\n >×</button>\n </div>\n </div>\n <button\n type=\"button\"\n class=\"variant-attribute-add-btn\"\n (click)=\"addAttributeEntry()\"\n [disabled]=\"obs.disabled\"\n >+ {{ 'addAttribute' | pluginTranslate: pluginId | async }}</button>\n </div>\n\n <v-select\n name=\"environmentId\"\n [title]=\"'environmentId' | pluginTranslate: pluginId | async\"\n [tooltip]=\"'environmentIdTooltip' | pluginTranslate: pluginId | async\"\n [margin]=\"true\"\n [items]=\"obs.environments.data\"\n [defaultSelectionId]=\"obs.prefill?.environmentId\"\n [disabled]=\"obs.disabled || obs.environments.loading\"\n [required]=\"false\"\n [loading]=\"obs.environments.loading\"\n >\n </v-select>\n <div *ngIf=\"obs.environments.error\" class=\"loading-error\">{{ obs.environments.error }}</div>\n\n <v-select\n name=\"outputFormat\"\n [title]=\"'outputFormat' | pluginTranslate: pluginId | async\"\n [tooltip]=\"'outputFormatTooltip' | pluginTranslate: pluginId | async\"\n [margin]=\"true\"\n [items]=\"outputFormatOptions\"\n [defaultSelectionId]=\"obs.prefill?.outputFormat || 'PDF'\"\n [disabled]=\"obs.disabled\"\n [required]=\"true\"\n >\n </v-select>\n\n <v-input\n name=\"filename\"\n [title]=\"'filename' | pluginTranslate: pluginId | async\"\n [tooltip]=\"'filenameTooltip' | pluginTranslate: pluginId | async\"\n [margin]=\"true\"\n [defaultValue]=\"obs.prefill?.filename\"\n [disabled]=\"obs.disabled\"\n [required]=\"true\"\n >\n </v-input>\n\n <v-input\n name=\"correlationId\"\n [title]=\"'correlationId' | pluginTranslate: pluginId | async\"\n [tooltip]=\"'correlationIdTooltip' | pluginTranslate: pluginId | async\"\n [margin]=\"true\"\n [defaultValue]=\"obs.prefill?.correlationId\"\n [disabled]=\"obs.disabled\"\n [required]=\"false\"\n >\n </v-input>\n\n <v-input\n name=\"resultProcessVariable\"\n [title]=\"'resultProcessVariable' | pluginTranslate: pluginId | async\"\n [tooltip]=\"'resultProcessVariableTooltip' | pluginTranslate: pluginId | async\"\n [margin]=\"true\"\n [defaultValue]=\"obs.prefill?.resultProcessVariable\"\n [disabled]=\"obs.disabled\"\n [required]=\"true\"\n >\n </v-input>\n</v-form>\n\n<div *ngIf=\"(templateFields$ | async)?.error as templateFieldsError\" class=\"loading-error\">{{ templateFieldsError }}</div>\n\n<epistola-data-mapping-tree\n *ngIf=\"(selectedTemplateId$ | async)\"\n [pluginId]=\"pluginId\"\n [templateFields]=\"(templateFields$ | async)?.data ?? []\"\n [disabled]=\"!!(disabled$ | async)\"\n [prefillMapping]=\"prefillDataMapping\"\n [caseDefinitionKey]=\"caseDefinitionKey\"\n [processVariables]=\"processVariables\"\n (mappingChange)=\"onDataMappingChange($event)\"\n (requiredFieldsStatus)=\"onRequiredFieldsStatusChange($event)\"\n></epistola-data-mapping-tree>\n\n<div class=\"validation-summary\" *ngIf=\"(selectedTemplateId$ | async) && requiredFieldsStatus.total > 0\">\n <span *ngIf=\"requiredFieldsStatus.mapped === requiredFieldsStatus.total\" class=\"validation-complete\">\n {{ 'requiredFieldsComplete' | pluginTranslate: pluginId | async }}\n </span>\n <span *ngIf=\"requiredFieldsStatus.mapped < requiredFieldsStatus.total\" class=\"validation-incomplete\">\n {{ requiredFieldsStatus.mapped }} / {{ requiredFieldsStatus.total }}\n {{ 'validationSummary' | pluginTranslate: pluginId | async }}\n </span>\n</div>\n", styles: [".loading-error{padding:.25rem .75rem;font-size:.8125rem;color:#dc3545}.validation-summary{margin-top:.5rem;padding:.5rem .75rem;border-radius:4px;font-size:.875rem}.validation-summary .validation-complete{color:#198754}.validation-summary .validation-incomplete{color:#dc3545;font-weight:500}.variant-mode-toggle{margin-bottom:1rem;padding:0 .75rem}.variant-mode-label{display:block;font-size:.875rem;font-weight:500;margin-bottom:.375rem}.variant-mode-buttons{display:flex;gap:0;border:1px solid #d1d5db;border-radius:4px;overflow:hidden;width:fit-content}.variant-mode-btn{padding:.375rem .75rem;font-size:.8125rem;background:#fff;border:none;border-right:1px solid #d1d5db;cursor:pointer;color:#374151;transition:background-color .15s,color .15s}.variant-mode-btn:last-child{border-right:none}.variant-mode-btn:hover:not([disabled]){background:#f3f4f6}.variant-mode-btn.active{background:#2563eb;color:#fff}.variant-mode-btn[disabled]{opacity:.5;cursor:not-allowed}.variant-attributes-section{margin-bottom:1rem;padding:0 .75rem}.variant-attributes-label{display:block;font-size:.875rem;font-weight:500;margin-bottom:.375rem}.variant-attributes-list{display:flex;flex-direction:column;gap:.375rem}.variant-attribute-row{display:flex;gap:.375rem;align-items:center}.variant-attribute-input{flex:1;padding:.375rem .5rem;font-size:.8125rem;border:1px solid #d1d5db;border-radius:4px;outline:none}.variant-attribute-input:focus{border-color:#2563eb;box-shadow:0 0 0 1px #2563eb}.variant-attribute-input[disabled]{opacity:.5;background:#f9fafb}.variant-attribute-remove-btn{padding:.25rem .5rem;font-size:1rem;line-height:1;background:none;border:1px solid #d1d5db;border-radius:4px;cursor:pointer;color:#6b7280}.variant-attribute-remove-btn:hover:not([disabled]){color:#dc3545;border-color:#dc3545}.variant-attribute-remove-btn[disabled]{opacity:.5;cursor:not-allowed}.variant-attribute-add-btn{margin-top:.375rem;padding:.25rem .5rem;font-size:.8125rem;background:none;border:1px dashed #d1d5db;border-radius:4px;cursor:pointer;color:#6b7280}.variant-attribute-add-btn:hover:not([disabled]){color:#2563eb;border-color:#2563eb}.variant-attribute-add-btn[disabled]{opacity:.5;cursor:not-allowed}\n"] }]
|
|
909
|
-
}], ctorParameters: () => [{ type: EpistolaPluginService }, { type: i2$
|
|
942
|
+
], template: "<v-form\n (valueChange)=\"formValueChange($event)\"\n *ngIf=\"{\n disabled: disabled$ | async,\n prefill: prefillConfiguration$ ? (prefillConfiguration$ | async) : null,\n templates: templates$ | async,\n variants: variants$ | async,\n environments: environments$ | async,\n templateFields: templateFields$ | async,\n selectedTemplateId: selectedTemplateId$ | async\n } as obs\"\n>\n <v-select\n name=\"templateId\"\n [title]=\"'templateId' | pluginTranslate: pluginId | async\"\n [tooltip]=\"'templateIdTooltip' | pluginTranslate: pluginId | async\"\n [margin]=\"true\"\n [items]=\"obs.templates.data\"\n [defaultSelectionId]=\"obs.prefill?.templateId\"\n [disabled]=\"obs.disabled || obs.templates.loading\"\n [required]=\"true\"\n [loading]=\"obs.templates.loading\"\n >\n </v-select>\n <div *ngIf=\"obs.templates.error\" class=\"loading-error\">{{ obs.templates.error }}</div>\n\n <!-- Variant selection mode toggle -->\n <div class=\"variant-mode-toggle\" *ngIf=\"obs.selectedTemplateId\">\n <label class=\"variant-mode-label\">{{ 'variantSelectionMode' | pluginTranslate: pluginId | async }}</label>\n <div class=\"variant-mode-buttons\">\n <button\n type=\"button\"\n class=\"variant-mode-btn\"\n [class.active]=\"variantSelectionMode === 'explicit'\"\n (click)=\"onVariantSelectionModeChange('explicit')\"\n [disabled]=\"obs.disabled\"\n >{{ 'selectByVariant' | pluginTranslate: pluginId | async }}</button>\n <button\n type=\"button\"\n class=\"variant-mode-btn\"\n [class.active]=\"variantSelectionMode === 'attributes'\"\n (click)=\"onVariantSelectionModeChange('attributes')\"\n [disabled]=\"obs.disabled\"\n >{{ 'selectByAttributes' | pluginTranslate: pluginId | async }}</button>\n </div>\n </div>\n\n <!-- Explicit variant selection (dropdown) -->\n <v-select\n *ngIf=\"variantSelectionMode === 'explicit'\"\n name=\"variantId\"\n [title]=\"'variantId' | pluginTranslate: pluginId | async\"\n [tooltip]=\"'variantIdTooltip' | pluginTranslate: pluginId | async\"\n [margin]=\"true\"\n [items]=\"obs.variants.data\"\n [defaultSelectionId]=\"obs.prefill?.variantId\"\n [disabled]=\"obs.disabled || obs.variants.loading || !obs.selectedTemplateId\"\n [required]=\"false\"\n [loading]=\"obs.variants.loading\"\n >\n </v-select>\n <div *ngIf=\"obs.variants.error\" class=\"loading-error\">{{ obs.variants.error }}</div>\n\n <!-- Attribute-based variant selection -->\n <div *ngIf=\"variantSelectionMode === 'attributes' && obs.selectedTemplateId\" class=\"variant-attributes-section\">\n <label class=\"variant-attributes-label\">{{ 'variantAttributes' | pluginTranslate: pluginId | async }}</label>\n <div class=\"variant-attributes-list\">\n <div *ngFor=\"let entry of variantAttributeEntries; let i = index\" class=\"variant-attribute-row\">\n <select\n *ngIf=\"!entry._customKey\"\n class=\"variant-attribute-input\"\n [ngModel]=\"entry.key\"\n (ngModelChange)=\"onKeySelected(entry, $event)\"\n [disabled]=\"obs.disabled\"\n >\n <option value=\"\" disabled>{{ 'attributeKey' | pluginTranslate: pluginId | async }}</option>\n <option *ngFor=\"let key of availableAttributeKeys\" [value]=\"key\">{{ key }}</option>\n <option value=\"__custom__\">{{ 'attributeKeyCustom' | pluginTranslate: pluginId | async }}</option>\n </select>\n <div *ngIf=\"entry._customKey\" class=\"custom-key-input\">\n <input\n type=\"text\"\n class=\"variant-attribute-input\"\n [placeholder]=\"'attributeKey' | pluginTranslate: pluginId | async\"\n [(ngModel)]=\"entry.key\"\n (ngModelChange)=\"onAttributeEntryChange()\"\n [disabled]=\"obs.disabled\"\n />\n <button type=\"button\" class=\"custom-key-cancel\" (click)=\"cancelCustomKey(entry)\" [disabled]=\"obs.disabled\">×</button>\n </div>\n <input\n type=\"text\"\n class=\"variant-attribute-input\"\n [placeholder]=\"'attributeValue' | pluginTranslate: pluginId | async\"\n [(ngModel)]=\"entry.value\"\n (ngModelChange)=\"onAttributeEntryChange()\"\n [disabled]=\"obs.disabled\"\n />\n <label class=\"variant-attribute-required-toggle\">\n <input\n type=\"checkbox\"\n [(ngModel)]=\"entry.required\"\n (ngModelChange)=\"onAttributeEntryChange()\"\n [disabled]=\"obs.disabled\"\n />\n <span class=\"required-label\">{{ (entry.required ? 'attributeRequired' : 'attributePreferred') | pluginTranslate: pluginId | async }}</span>\n </label>\n <button\n type=\"button\"\n class=\"variant-attribute-remove-btn\"\n (click)=\"removeAttributeEntry(i)\"\n [disabled]=\"obs.disabled\"\n title=\"{{ 'removeAttribute' | pluginTranslate: pluginId | async }}\"\n >×</button>\n </div>\n </div>\n <button\n type=\"button\"\n class=\"variant-attribute-add-btn\"\n (click)=\"addAttributeEntry()\"\n [disabled]=\"obs.disabled\"\n >+ {{ 'addAttribute' | pluginTranslate: pluginId | async }}</button>\n </div>\n\n <v-select\n name=\"environmentId\"\n [title]=\"'environmentId' | pluginTranslate: pluginId | async\"\n [tooltip]=\"'environmentIdTooltip' | pluginTranslate: pluginId | async\"\n [margin]=\"true\"\n [items]=\"obs.environments.data\"\n [defaultSelectionId]=\"obs.prefill?.environmentId\"\n [disabled]=\"obs.disabled || obs.environments.loading\"\n [required]=\"false\"\n [loading]=\"obs.environments.loading\"\n >\n </v-select>\n <div *ngIf=\"obs.environments.error\" class=\"loading-error\">{{ obs.environments.error }}</div>\n\n <v-select\n name=\"outputFormat\"\n [title]=\"'outputFormat' | pluginTranslate: pluginId | async\"\n [tooltip]=\"'outputFormatTooltip' | pluginTranslate: pluginId | async\"\n [margin]=\"true\"\n [items]=\"outputFormatOptions\"\n [defaultSelectionId]=\"obs.prefill?.outputFormat || 'PDF'\"\n [disabled]=\"obs.disabled\"\n [required]=\"true\"\n >\n </v-select>\n\n <v-input\n name=\"filename\"\n [title]=\"'filename' | pluginTranslate: pluginId | async\"\n [tooltip]=\"'filenameTooltip' | pluginTranslate: pluginId | async\"\n [margin]=\"true\"\n [defaultValue]=\"obs.prefill?.filename\"\n [disabled]=\"obs.disabled\"\n [required]=\"true\"\n >\n </v-input>\n\n <v-input\n name=\"correlationId\"\n [title]=\"'correlationId' | pluginTranslate: pluginId | async\"\n [tooltip]=\"'correlationIdTooltip' | pluginTranslate: pluginId | async\"\n [margin]=\"true\"\n [defaultValue]=\"obs.prefill?.correlationId\"\n [disabled]=\"obs.disabled\"\n [required]=\"false\"\n >\n </v-input>\n\n <v-input\n name=\"resultProcessVariable\"\n [title]=\"'resultProcessVariable' | pluginTranslate: pluginId | async\"\n [tooltip]=\"'resultProcessVariableTooltip' | pluginTranslate: pluginId | async\"\n [margin]=\"true\"\n [defaultValue]=\"obs.prefill?.resultProcessVariable\"\n [disabled]=\"obs.disabled\"\n [required]=\"true\"\n >\n </v-input>\n</v-form>\n\n<div *ngIf=\"(templateFields$ | async)?.error as templateFieldsError\" class=\"loading-error\">{{ templateFieldsError }}</div>\n\n<epistola-data-mapping-tree\n *ngIf=\"(selectedTemplateId$ | async)\"\n [pluginId]=\"pluginId\"\n [templateFields]=\"(templateFields$ | async)?.data ?? []\"\n [disabled]=\"!!(disabled$ | async)\"\n [prefillMapping]=\"prefillDataMapping\"\n [caseDefinitionKey]=\"caseDefinitionKey\"\n [processVariables]=\"processVariables\"\n (mappingChange)=\"onDataMappingChange($event)\"\n (requiredFieldsStatus)=\"onRequiredFieldsStatusChange($event)\"\n></epistola-data-mapping-tree>\n\n<div class=\"validation-summary\" *ngIf=\"(selectedTemplateId$ | async) && requiredFieldsStatus.total > 0\">\n <span *ngIf=\"requiredFieldsStatus.mapped === requiredFieldsStatus.total\" class=\"validation-complete\">\n {{ 'requiredFieldsComplete' | pluginTranslate: pluginId | async }}\n </span>\n <span *ngIf=\"requiredFieldsStatus.mapped < requiredFieldsStatus.total\" class=\"validation-incomplete\">\n {{ requiredFieldsStatus.mapped }} / {{ requiredFieldsStatus.total }}\n {{ 'validationSummary' | pluginTranslate: pluginId | async }}\n </span>\n</div>\n", styles: [".loading-error{padding:.25rem .75rem;font-size:.8125rem;color:#dc3545}.validation-summary{margin-top:.5rem;padding:.5rem .75rem;border-radius:4px;font-size:.875rem}.validation-summary .validation-complete{color:#198754}.validation-summary .validation-incomplete{color:#dc3545;font-weight:500}.variant-mode-toggle{margin-bottom:1rem;padding:0 .75rem}.variant-mode-label{display:block;font-size:.875rem;font-weight:500;margin-bottom:.375rem}.variant-mode-buttons{display:flex;gap:0;border:1px solid #d1d5db;border-radius:4px;overflow:hidden;width:fit-content}.variant-mode-btn{padding:.375rem .75rem;font-size:.8125rem;background:#fff;border:none;border-right:1px solid #d1d5db;cursor:pointer;color:#374151;transition:background-color .15s,color .15s}.variant-mode-btn:last-child{border-right:none}.variant-mode-btn:hover:not([disabled]){background:#f3f4f6}.variant-mode-btn.active{background:#2563eb;color:#fff}.variant-mode-btn[disabled]{opacity:.5;cursor:not-allowed}.variant-attributes-section{margin-bottom:1rem;padding:0 .75rem}.variant-attributes-label{display:block;font-size:.875rem;font-weight:500;margin-bottom:.375rem}.variant-attributes-list{display:flex;flex-direction:column;gap:.375rem}.variant-attribute-row{display:flex;gap:.375rem;align-items:center}.variant-attribute-input{flex:1;padding:.375rem .5rem;font-size:.8125rem;border:1px solid #d1d5db;border-radius:4px;outline:none}.variant-attribute-input:focus{border-color:#2563eb;box-shadow:0 0 0 1px #2563eb}.variant-attribute-input[disabled]{opacity:.5;background:#f9fafb}.custom-key-input{display:flex;flex:1;gap:.25rem}.custom-key-input .variant-attribute-input{flex:1}.custom-key-cancel{padding:.25rem .5rem;font-size:1rem;line-height:1;background:none;border:1px solid #d1d5db;border-radius:4px;cursor:pointer;color:#6b7280}.custom-key-cancel:hover:not([disabled]){color:#dc3545;border-color:#dc3545}.custom-key-cancel[disabled]{opacity:.5;cursor:not-allowed}.variant-attribute-required-toggle{display:flex;align-items:center;gap:.25rem;font-size:.75rem;color:#374151;white-space:nowrap;cursor:pointer}.variant-attribute-required-toggle input[type=checkbox]{margin:0;cursor:pointer}.variant-attribute-required-toggle .required-label{-webkit-user-select:none;user-select:none}.variant-attribute-remove-btn{padding:.25rem .5rem;font-size:1rem;line-height:1;background:none;border:1px solid #d1d5db;border-radius:4px;cursor:pointer;color:#6b7280}.variant-attribute-remove-btn:hover:not([disabled]){color:#dc3545;border-color:#dc3545}.variant-attribute-remove-btn[disabled]{opacity:.5;cursor:not-allowed}.variant-attribute-add-btn{margin-top:.375rem;padding:.25rem .5rem;font-size:.8125rem;background:none;border:1px dashed #d1d5db;border-radius:4px;cursor:pointer;color:#6b7280}.variant-attribute-add-btn:hover:not([disabled]){color:#2563eb;border-color:#2563eb}.variant-attribute-add-btn[disabled]{opacity:.5;cursor:not-allowed}\n"] }]
|
|
943
|
+
}], ctorParameters: () => [{ type: EpistolaPluginService }, { type: i2$2.ProcessLinkStateService }, { type: i0.ChangeDetectorRef }], propDecorators: { save$: [{
|
|
910
944
|
type: Input
|
|
911
945
|
}], disabled$: [{
|
|
912
946
|
type: Input
|
|
@@ -1223,7 +1257,7 @@ class EpistolaRetryFormComponent {
|
|
|
1223
1257
|
processInstanceId,
|
|
1224
1258
|
sourceActivityId: this.sourceActivityId || null,
|
|
1225
1259
|
overrides: formData
|
|
1226
|
-
}, { responseType: 'blob' }).subscribe({
|
|
1260
|
+
}, { responseType: 'blob', headers: new HttpHeaders().set('X-Skip-Interceptor', '422') }).subscribe({
|
|
1227
1261
|
next: (blob) => {
|
|
1228
1262
|
this.currentBlobUrl = URL.createObjectURL(blob);
|
|
1229
1263
|
this.previewUrl = this.sanitizer.bypassSecurityTrustResourceUrl(this.currentBlobUrl);
|
|
@@ -1286,7 +1320,7 @@ class EpistolaRetryFormComponent {
|
|
|
1286
1320
|
}
|
|
1287
1321
|
});
|
|
1288
1322
|
}
|
|
1289
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: EpistolaRetryFormComponent, deps: [{ token: EpistolaPluginService }, { token: i3.FormIoStateService }, { token: i0.ChangeDetectorRef }, { token: i1.HttpClient }, { token: i4.DomSanitizer }, { token: i2.ConfigService }], target: i0.ɵɵFactoryTarget.Component });
|
|
1323
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: EpistolaRetryFormComponent, deps: [{ token: EpistolaPluginService }, { token: i3.FormIoStateService }, { token: i0.ChangeDetectorRef }, { token: i1.HttpClient }, { token: i4$1.DomSanitizer }, { token: i2.ConfigService }], target: i0.ɵɵFactoryTarget.Component });
|
|
1290
1324
|
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.20", type: EpistolaRetryFormComponent, isStandalone: true, selector: "epistola-retry-form-component", inputs: { value: "value", disabled: "disabled", label: "label", sourceActivityId: "sourceActivityId" }, outputs: { valueChange: "valueChange" }, usesOnChanges: true, ngImport: i0, template: `
|
|
1291
1325
|
<div *ngIf="loading" class="epistola-retry-loading">Loading form...</div>
|
|
1292
1326
|
<div *ngIf="error" class="epistola-retry-error">{{ error }}</div>
|
|
@@ -1350,7 +1384,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.20", ngImpo
|
|
|
1350
1384
|
</div>
|
|
1351
1385
|
</div>
|
|
1352
1386
|
`, styles: [".epistola-retry-loading{padding:1rem;color:#6c757d}.epistola-retry-error{padding:.5rem;color:#dc3545}.epistola-retry-container{display:flex;gap:1rem}.epistola-retry-form{flex:2;min-width:0}.epistola-retry-preview{flex:1;min-width:0;border:1px solid #dee2e6;border-radius:4px;padding:1rem;background:#f8f9fa;display:flex;flex-direction:column}.preview-expanded .epistola-retry-preview{flex:1}.preview-header{display:flex;justify-content:space-between;align-items:center;font-weight:700;margin-bottom:.5rem;color:#495057}.preview-toggle{background:none;border:1px solid #6c757d;border-radius:4px;color:#6c757d;padding:.2rem .5rem;font-size:.75rem;cursor:pointer}.preview-toggle:hover{background:#e9ecef}.preview-loading{color:#6c757d;font-style:italic}.preview-pdf{width:100%;flex:1;min-height:500px}.preview-expanded .preview-pdf{min-height:80vh}.preview-error{color:#dc3545}.preview-empty{color:#6c757d;font-style:italic}\n"] }]
|
|
1353
|
-
}], ctorParameters: () => [{ type: EpistolaPluginService }, { type: i3.FormIoStateService }, { type: i0.ChangeDetectorRef }, { type: i1.HttpClient }, { type: i4.DomSanitizer }, { type: i2.ConfigService }], propDecorators: { value: [{
|
|
1387
|
+
}], ctorParameters: () => [{ type: EpistolaPluginService }, { type: i3.FormIoStateService }, { type: i0.ChangeDetectorRef }, { type: i1.HttpClient }, { type: i4$1.DomSanitizer }, { type: i2.ConfigService }], propDecorators: { value: [{
|
|
1354
1388
|
type: Input
|
|
1355
1389
|
}], valueChange: [{
|
|
1356
1390
|
type: Output
|
|
@@ -1427,7 +1461,7 @@ class EpistolaPreviewButtonComponent {
|
|
|
1427
1461
|
this.currentBlobUrl = null;
|
|
1428
1462
|
}
|
|
1429
1463
|
}
|
|
1430
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: EpistolaPreviewButtonComponent, deps: [{ token: i1.HttpClient }, { token: i4.DomSanitizer }, { token: i2.ConfigService }], target: i0.ɵɵFactoryTarget.Component });
|
|
1464
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: EpistolaPreviewButtonComponent, deps: [{ token: i1.HttpClient }, { token: i4$1.DomSanitizer }, { token: i2.ConfigService }], target: i0.ɵɵFactoryTarget.Component });
|
|
1431
1465
|
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.20", type: EpistolaPreviewButtonComponent, isStandalone: true, selector: "epistola-preview-button-component", inputs: { value: "value", disabled: "disabled", label: "label" }, outputs: { valueChange: "valueChange" }, ngImport: i0, template: `
|
|
1432
1466
|
<button
|
|
1433
1467
|
type="button"
|
|
@@ -1495,7 +1529,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.20", ngImpo
|
|
|
1495
1529
|
</div>
|
|
1496
1530
|
</div>
|
|
1497
1531
|
`, styles: [".preview-modal-overlay{position:fixed;top:0;left:0;width:100vw;height:100vh;background:#00000080;display:flex;align-items:center;justify-content:center;z-index:10000}.preview-modal-content{background:#fff;border-radius:8px;width:90vw;height:90vh;max-width:1200px;display:flex;flex-direction:column;overflow:hidden;box-shadow:0 8px 32px #0000004d}.preview-modal-header{display:flex;justify-content:space-between;align-items:center;padding:.75rem 1rem;border-bottom:1px solid #dee2e6;font-weight:700;font-size:1rem}.preview-modal-close{background:none;border:none;font-size:1.5rem;cursor:pointer;color:#6c757d;line-height:1;padding:0 .25rem}.preview-modal-close:hover{color:#333}.preview-modal-body{flex:1;overflow:hidden;display:flex;flex-direction:column}.preview-loading,.preview-error{padding:2rem;text-align:center}.preview-error{color:#dc3545}.preview-pdf{width:100%;flex:1}\n"] }]
|
|
1498
|
-
}], ctorParameters: () => [{ type: i1.HttpClient }, { type: i4.DomSanitizer }, { type: i2.ConfigService }], propDecorators: { value: [{
|
|
1532
|
+
}], ctorParameters: () => [{ type: i1.HttpClient }, { type: i4$1.DomSanitizer }, { type: i2.ConfigService }], propDecorators: { value: [{
|
|
1499
1533
|
type: Input
|
|
1500
1534
|
}], valueChange: [{
|
|
1501
1535
|
type: Output
|
|
@@ -1639,7 +1673,7 @@ class EpistolaDocumentPreviewComponent {
|
|
|
1639
1673
|
this.previewUrl = null;
|
|
1640
1674
|
}
|
|
1641
1675
|
}
|
|
1642
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: EpistolaDocumentPreviewComponent, deps: [{ token: EpistolaPluginService }, { token: i1.HttpClient }, { token: i4.DomSanitizer }, { token: i2.ConfigService }, { token: i3.FormIoStateService }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
|
|
1676
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: EpistolaDocumentPreviewComponent, deps: [{ token: EpistolaPluginService }, { token: i1.HttpClient }, { token: i4$1.DomSanitizer }, { token: i2.ConfigService }, { token: i3.FormIoStateService }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
|
|
1643
1677
|
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.20", type: EpistolaDocumentPreviewComponent, isStandalone: true, selector: "epistola-document-preview-component", inputs: { value: "value", disabled: "disabled", label: "label" }, outputs: { valueChange: "valueChange" }, usesOnChanges: true, ngImport: i0, template: `
|
|
1644
1678
|
<div class="epistola-preview-panel">
|
|
1645
1679
|
<div class="preview-header">
|
|
@@ -1735,7 +1769,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.20", ngImpo
|
|
|
1735
1769
|
</div>
|
|
1736
1770
|
</div>
|
|
1737
1771
|
`, styles: [".epistola-preview-panel{border:1px solid #dee2e6;border-radius:4px;background:#f8f9fa;display:flex;flex-direction:column}.preview-header{display:flex;justify-content:space-between;align-items:center;padding:.5rem 1rem;border-bottom:1px solid #dee2e6;font-weight:700;color:#495057;flex-wrap:wrap;gap:.5rem}.preview-controls{display:flex;align-items:center;gap:.5rem}.preview-select{border:1px solid #ced4da;border-radius:4px;padding:.25rem .5rem;font-size:.8rem;background:#fff;max-width:300px}.preview-refresh{background:none;border:1px solid #6c757d;border-radius:4px;color:#6c757d;padding:.25rem .75rem;font-size:.8rem;cursor:pointer;display:flex;align-items:center;white-space:nowrap}.preview-refresh:hover:not(:disabled){background:#e9ecef}.preview-refresh:disabled{opacity:.5;cursor:not-allowed}.preview-body{display:flex;flex-direction:column;min-height:500px}.preview-loading{padding:2rem;text-align:center;color:#6c757d;font-style:italic}.preview-unavailable{padding:1.5rem;text-align:center;color:#6c757d;font-style:italic}.preview-unavailable i{margin-right:.25rem}.preview-pdf{width:100%;flex:1;min-height:500px}.preview-empty{padding:2rem;text-align:center;color:#6c757d;font-style:italic}\n"] }]
|
|
1738
|
-
}], ctorParameters: () => [{ type: EpistolaPluginService }, { type: i1.HttpClient }, { type: i4.DomSanitizer }, { type: i2.ConfigService }, { type: i3.FormIoStateService }, { type: i0.ChangeDetectorRef }], propDecorators: { value: [{
|
|
1772
|
+
}], ctorParameters: () => [{ type: EpistolaPluginService }, { type: i1.HttpClient }, { type: i4$1.DomSanitizer }, { type: i2.ConfigService }, { type: i3.FormIoStateService }, { type: i0.ChangeDetectorRef }], propDecorators: { value: [{
|
|
1739
1773
|
type: Input
|
|
1740
1774
|
}], valueChange: [{
|
|
1741
1775
|
type: Output
|
|
@@ -1968,9 +2002,12 @@ const epistolaPluginSpecification = {
|
|
|
1968
2002
|
variantAttributes: 'Variant kenmerken',
|
|
1969
2003
|
variantAttributesTooltip: 'Kenmerken voor automatische variant selectie. Waarden kunnen expressies zijn (doc:, pv:, case:).',
|
|
1970
2004
|
attributeKey: 'Kenmerk',
|
|
2005
|
+
attributeKeyCustom: 'Aangepast...',
|
|
1971
2006
|
attributeValue: 'Waarde',
|
|
1972
2007
|
addAttribute: 'Kenmerk toevoegen',
|
|
1973
2008
|
removeAttribute: 'Kenmerk verwijderen',
|
|
2009
|
+
attributeRequired: 'Verplicht',
|
|
2010
|
+
attributePreferred: 'Voorkeur',
|
|
1974
2011
|
environmentId: 'Omgeving',
|
|
1975
2012
|
environmentIdTooltip: 'Selecteer de doelomgeving (optioneel)',
|
|
1976
2013
|
correlationId: 'Correlatie ID',
|
|
@@ -2054,9 +2091,12 @@ const epistolaPluginSpecification = {
|
|
|
2054
2091
|
variantAttributes: 'Variant attributes',
|
|
2055
2092
|
variantAttributesTooltip: 'Attributes for automatic variant selection. Values can be expressions (doc:, pv:, case:).',
|
|
2056
2093
|
attributeKey: 'Attribute',
|
|
2094
|
+
attributeKeyCustom: 'Custom...',
|
|
2057
2095
|
attributeValue: 'Value',
|
|
2058
2096
|
addAttribute: 'Add attribute',
|
|
2059
2097
|
removeAttribute: 'Remove attribute',
|
|
2098
|
+
attributeRequired: 'Required',
|
|
2099
|
+
attributePreferred: 'Preferred',
|
|
2060
2100
|
environmentId: 'Environment',
|
|
2061
2101
|
environmentIdTooltip: 'Select the target environment (optional)',
|
|
2062
2102
|
correlationId: 'Correlation ID',
|