UNPKG

@alauda-fe/custom-resource-quota

Version:

custom resource

727 lines 104 kB
import { __decorate, __metadata } from "tslib"; import { ButtonComponent, FORM_MODULE, IconComponent, INPUT_GROUP_MODULE, InputComponent, SELECT_MODULE, TooltipDirective, } from '@alauda/ui'; import { TranslateService, bind, ValidateRowDuplicateService, isEqual, publishRef, ObservableInput, ArrayFormTableComponent, ArrayFormTableHeaderDirective, TRANSLATE_MODULE, ArrayFormTableRowDirective, DeclareDirective, PurePipe, ParseJsonTranslatePipe, ERRORS_MAPPER_MODULE, ArrayFormTableRowControlDirective, } from '@alauda-fe/common'; import { AsyncPipe, NgClass, NgForOf, NgIf } from '@angular/common'; import { ChangeDetectionStrategy, Component, Injector, Input, } from '@angular/core'; import { ControlContainer, FormGroup, ReactiveFormsModule, Validators, } from '@angular/forms'; import { cloneDeep, flatMap, groupBy, has, isObject, omit, pick, remove, toPairs, } from 'lodash-es'; import { BaseResourceFormArrayComponent } from 'ng-resource-form-util'; import { BehaviorSubject, Observable, combineLatest, debounceTime, distinctUntilChanged, map, takeUntil, tap, } from 'rxjs'; import { ActionType, QuotaItemType, } from '../types'; import * as i0 from "@angular/core"; import * as i1 from "@angular/forms"; import * as i2 from "@alauda-fe/common"; import * as i3 from "@alauda/ui"; const _c0 = (a0, a1, a2, a3, a4) => [a0, a1, a2, a3, a4]; const _c1 = (a0, a1, a2, a3, a4, a5, a6) => [a0, a1, a2, a3, a4, a5, a6]; const _c2 = a0 => ({ excludesTypes: a0 }); const _c3 = (a0, a1) => ({ keyInvalid: a0, keyDuplicated: a1 }); const _c4 = a0 => ({ pattern: a0 }); const _c5 = a0 => ({ "tw-mt-8": a0 }); function CustomResourceQuotaFormComponent_ng_container_1_Template(rf, ctx) { if (rf & 1) { i0.ɵɵelementContainerStart(0, 5); i0.ɵɵelementStart(1, "th", 6); i0.ɵɵtext(2); i0.ɵɵpipe(3, "translate"); i0.ɵɵelementEnd(); i0.ɵɵelementStart(4, "th", 6); i0.ɵɵtext(5); i0.ɵɵpipe(6, "translate"); i0.ɵɵelementEnd(); i0.ɵɵelementContainerEnd(); } if (rf & 2) { const ctx_r0 = i0.ɵɵnextContext(); i0.ɵɵadvance(); i0.ɵɵclassMap((ctx_r0.form.controls == null ? null : ctx_r0.form.controls.length) ? "tw-required-mark" : ""); i0.ɵɵadvance(); i0.ɵɵtextInterpolate1(" ", i0.ɵɵpipeBind1(3, 6, "type"), " "); i0.ɵɵadvance(2); i0.ɵɵclassMap((ctx_r0.form.controls == null ? null : ctx_r0.form.controls.length) ? "tw-required-mark" : ""); i0.ɵɵadvance(); i0.ɵɵtextInterpolate1(" ", i0.ɵɵpipeBind1(6, 8, "value"), " "); } } function CustomResourceQuotaFormComponent_ng_container_2_ng_container_3_ng_container_1_aui_option_1_Template(rf, ctx) { if (rf & 1) { i0.ɵɵelementStart(0, "aui-option", 14); i0.ɵɵpipe(1, "aclParseJsonTranslate"); i0.ɵɵtext(2); i0.ɵɵpipe(3, "aclParseJsonTranslate"); i0.ɵɵelementEnd(); } if (rf & 2) { const state_r4 = ctx.declare; const item_r5 = i0.ɵɵnextContext().$implicit; i0.ɵɵnextContext(); const disabledTemplate_r6 = i0.ɵɵreference(3); i0.ɵɵproperty("value", item_r5.key)("label", i0.ɵɵpipeBind1(1, 7, item_r5.name))("disabled", state_r4.isDisabled)("auiTooltip", disabledTemplate_r6)("auiTooltipContext", i0.ɵɵpureFunction1(11, _c2, state_r4.excludesTypes))("auiTooltipDisabled", !state_r4.isDisabled); i0.ɵɵadvance(2); i0.ɵɵtextInterpolate1(" ", i0.ɵɵpipeBind1(3, 9, item_r5.name), " "); } } function CustomResourceQuotaFormComponent_ng_container_2_ng_container_3_ng_container_1_Template(rf, ctx) { if (rf & 1) { i0.ɵɵelementContainerStart(0); i0.ɵɵtemplate(1, CustomResourceQuotaFormComponent_ng_container_2_ng_container_3_ng_container_1_aui_option_1_Template, 4, 13, "aui-option", 13); i0.ɵɵpipe(2, "async"); i0.ɵɵpipe(3, "pure"); i0.ɵɵelementContainerEnd(); } if (rf & 2) { const item_r5 = ctx.$implicit; const options_r7 = i0.ɵɵnextContext().declare; const index_r8 = i0.ɵɵnextContext().index; const ctx_r0 = i0.ɵɵnextContext(); i0.ɵɵadvance(); i0.ɵɵproperty("declare", i0.ɵɵpipeBindV(3, 3, i0.ɵɵpureFunction7(11, _c1, ctx_r0.form == null ? null : ctx_r0.form.value, ctx_r0.getKindDisabledState, item_r5, options_r7, index_r8, ctx_r0.podContainerIndex, i0.ɵɵpipeBind1(2, 1, ctx_r0.kindDisabledStateTrigger$$)))); } } function CustomResourceQuotaFormComponent_ng_container_2_ng_container_3_ng_template_2_li_4_Template(rf, ctx) { if (rf & 1) { i0.ɵɵelementStart(0, "li"); i0.ɵɵtext(1); i0.ɵɵpipe(2, "aclParseJsonTranslate"); i0.ɵɵelementEnd(); } if (rf & 2) { const t_r9 = ctx.$implicit; i0.ɵɵadvance(); i0.ɵɵtextInterpolate1(" ", i0.ɵɵpipeBind1(2, 1, t_r9), " "); } } function CustomResourceQuotaFormComponent_ng_container_2_ng_container_3_ng_template_2_Template(rf, ctx) { if (rf & 1) { i0.ɵɵelementStart(0, "div", 15); i0.ɵɵtext(1); i0.ɵɵpipe(2, "translate"); i0.ɵɵelementEnd(); i0.ɵɵelementStart(3, "ul", 16); i0.ɵɵtemplate(4, CustomResourceQuotaFormComponent_ng_container_2_ng_container_3_ng_template_2_li_4_Template, 3, 3, "li", 12); i0.ɵɵelementEnd(); } if (rf & 2) { const excludesTypes_r10 = ctx.excludesTypes; i0.ɵɵadvance(); i0.ɵɵtextInterpolate1(" ", i0.ɵɵpipeBind1(2, 2, "custom_resource_kind_excludes_tip"), " "); i0.ɵɵadvance(3); i0.ɵɵproperty("ngForOf", excludesTypes_r10); } } function CustomResourceQuotaFormComponent_ng_container_2_ng_container_3_Template(rf, ctx) { if (rf & 1) { i0.ɵɵelementContainerStart(0); i0.ɵɵtemplate(1, CustomResourceQuotaFormComponent_ng_container_2_ng_container_3_ng_container_1_Template, 4, 19, "ng-container", 12)(2, CustomResourceQuotaFormComponent_ng_container_2_ng_container_3_ng_template_2_Template, 5, 4, "ng-template", null, 0, i0.ɵɵtemplateRefExtractor); i0.ɵɵelementContainerEnd(); } if (rf & 2) { const options_r7 = ctx.declare; i0.ɵɵadvance(); i0.ɵɵproperty("ngForOf", options_r7); } } function CustomResourceQuotaFormComponent_ng_container_2_acl_errors_mapper_8_Template(rf, ctx) { if (rf & 1) { i0.ɵɵelement(0, "acl-errors-mapper", 17); i0.ɵɵpipe(1, "translate"); i0.ɵɵpipe(2, "translate"); } if (rf & 2) { const control_r3 = i0.ɵɵnextContext().$implicit; i0.ɵɵproperty("errors", (control_r3.errors == null ? null : control_r3.errors.duplicateError) || control_r3.get("key").errors)("errorsMapper", i0.ɵɵpureFunction2(6, _c3, i0.ɵɵpipeBind1(1, 2, "invalid_pattern"), i0.ɵɵpipeBind1(2, 4, "type_duplicated_errors"))); } } function CustomResourceQuotaFormComponent_ng_container_2_ng_container_10_ng_container_1_span_4_Template(rf, ctx) { if (rf & 1) { i0.ɵɵelementStart(0, "span", 24); i0.ɵɵtext(1); i0.ɵɵpipe(2, "translate"); i0.ɵɵelementEnd(); } if (rf & 2) { const context_r11 = i0.ɵɵnextContext(2).declare; i0.ɵɵadvance(); i0.ɵɵtextInterpolate(context_r11.resourceUnit || i0.ɵɵpipeBind1(2, 1, context_r11.unit)); } } function CustomResourceQuotaFormComponent_ng_container_2_ng_container_10_ng_container_1_aui_icon_5_Template(rf, ctx) { if (rf & 1) { i0.ɵɵelement(0, "aui-icon", 25); } if (rf & 2) { const description_r12 = ctx.ngIf; i0.ɵɵproperty("auiTooltip", description_r12); } } function CustomResourceQuotaFormComponent_ng_container_2_ng_container_10_ng_container_1_acl_errors_mapper_7_Template(rf, ctx) { if (rf & 1) { i0.ɵɵelement(0, "acl-errors-mapper", 17); i0.ɵɵpipe(1, "translate"); } if (rf & 2) { const control_r3 = i0.ɵɵnextContext(3).$implicit; i0.ɵɵproperty("errors", control_r3.get("value").errors)("errorsMapper", i0.ɵɵpureFunction1(4, _c4, i0.ɵɵpipeBind1(1, 2, "support_positive_integer"))); } } function CustomResourceQuotaFormComponent_ng_container_2_ng_container_10_ng_container_1_Template(rf, ctx) { if (rf & 1) { i0.ɵɵelementContainerStart(0); i0.ɵɵelementStart(1, "div", 19)(2, "aui-input-group", 20); i0.ɵɵelement(3, "input", 21); i0.ɵɵtemplate(4, CustomResourceQuotaFormComponent_ng_container_2_ng_container_10_ng_container_1_span_4_Template, 3, 3, "span", 22); i0.ɵɵelementEnd(); i0.ɵɵtemplate(5, CustomResourceQuotaFormComponent_ng_container_2_ng_container_10_ng_container_1_aui_icon_5_Template, 1, 1, "aui-icon", 23); i0.ɵɵpipe(6, "translate"); i0.ɵɵelementEnd(); i0.ɵɵtemplate(7, CustomResourceQuotaFormComponent_ng_container_2_ng_container_10_ng_container_1_acl_errors_mapper_7_Template, 2, 6, "acl-errors-mapper", 11); i0.ɵɵelementContainerEnd(); } if (rf & 2) { const context_r11 = i0.ɵɵnextContext().declare; const control_r3 = i0.ɵɵnextContext().$implicit; const ctx_r0 = i0.ɵɵnextContext(); i0.ɵɵadvance(3); i0.ɵɵproperty("min", 0); i0.ɵɵadvance(); i0.ɵɵproperty("ngIf", context_r11.resourceUnit || context_r11.unit && context_r11.unit !== "unit_ge"); i0.ɵɵadvance(); i0.ɵɵproperty("ngIf", i0.ɵɵpipeBind1(6, 4, context_r11 == null ? null : context_r11.description)); i0.ɵɵadvance(2); i0.ɵɵproperty("ngIf", control_r3.get("value").dirty || (ctx_r0.controlContainer == null ? null : ctx_r0.controlContainer.formDirective == null ? null : ctx_r0.controlContainer.formDirective.submitted)); } } function CustomResourceQuotaFormComponent_ng_container_2_ng_container_10_ng_container_2_div_1_span_4_Template(rf, ctx) { if (rf & 1) { i0.ɵɵelementStart(0, "span", 24); i0.ɵɵtext(1); i0.ɵɵpipe(2, "translate"); i0.ɵɵelementEnd(); } if (rf & 2) { const c_r13 = i0.ɵɵnextContext().$implicit; i0.ɵɵadvance(); i0.ɵɵtextInterpolate(c_r13.resourceUnit || i0.ɵɵpipeBind1(2, 1, c_r13.unit)); } } function CustomResourceQuotaFormComponent_ng_container_2_ng_container_10_ng_container_2_div_1_span_5_Template(rf, ctx) { if (rf & 1) { i0.ɵɵelementStart(0, "span", 30); i0.ɵɵpipe(1, "translate"); i0.ɵɵtext(2); i0.ɵɵpipe(3, "translate"); i0.ɵɵelementEnd(); } if (rf & 2) { const c_r13 = i0.ɵɵnextContext().$implicit; i0.ɵɵproperty("title", i0.ɵɵpipeBind1(1, 2, c_r13.name)); i0.ɵɵadvance(2); i0.ɵɵtextInterpolate(i0.ɵɵpipeBind1(3, 4, c_r13.name)); } } function CustomResourceQuotaFormComponent_ng_container_2_ng_container_10_ng_container_2_div_1_aui_icon_6_Template(rf, ctx) { if (rf & 1) { i0.ɵɵelement(0, "aui-icon", 25); } if (rf & 2) { const description_r14 = ctx.ngIf; i0.ɵɵproperty("auiTooltip", description_r14); } } function CustomResourceQuotaFormComponent_ng_container_2_ng_container_10_ng_container_2_div_1_acl_errors_mapper_8_Template(rf, ctx) { if (rf & 1) { i0.ɵɵelement(0, "acl-errors-mapper", 17); i0.ɵɵpipe(1, "translate"); } if (rf & 2) { let tmp_10_0; const c_r13 = i0.ɵɵnextContext().$implicit; const control_r3 = i0.ɵɵnextContext(3).$implicit; i0.ɵɵproperty("errors", (tmp_10_0 = control_r3.get("value")) == null ? null : tmp_10_0.controls == null ? null : tmp_10_0.controls[c_r13.key] == null ? null : tmp_10_0.controls[c_r13.key].errors)("errorsMapper", i0.ɵɵpureFunction1(4, _c4, i0.ɵɵpipeBind1(1, 2, "support_positive_integer"))); } } function CustomResourceQuotaFormComponent_ng_container_2_ng_container_10_ng_container_2_div_1_Template(rf, ctx) { if (rf & 1) { i0.ɵɵelementStart(0, "div", 27)(1, "div", 19)(2, "aui-input-group", 20); i0.ɵɵelement(3, "input", 28); i0.ɵɵtemplate(4, CustomResourceQuotaFormComponent_ng_container_2_ng_container_10_ng_container_2_div_1_span_4_Template, 3, 3, "span", 22)(5, CustomResourceQuotaFormComponent_ng_container_2_ng_container_10_ng_container_2_div_1_span_5_Template, 4, 6, "span", 29); i0.ɵɵelementEnd(); i0.ɵɵtemplate(6, CustomResourceQuotaFormComponent_ng_container_2_ng_container_10_ng_container_2_div_1_aui_icon_6_Template, 1, 1, "aui-icon", 23); i0.ɵɵpipe(7, "translate"); i0.ɵɵelementEnd(); i0.ɵɵtemplate(8, CustomResourceQuotaFormComponent_ng_container_2_ng_container_10_ng_container_2_div_1_acl_errors_mapper_8_Template, 2, 6, "acl-errors-mapper", 11); i0.ɵɵelementEnd(); } if (rf & 2) { let tmp_15_0; const c_r13 = ctx.$implicit; const i_r15 = ctx.index; const control_r3 = i0.ɵɵnextContext(3).$implicit; const ctx_r0 = i0.ɵɵnextContext(); i0.ɵɵproperty("ngClass", i0.ɵɵpureFunction1(9, _c5, !!i_r15)); i0.ɵɵadvance(3); i0.ɵɵproperty("formControlName", c_r13.key)("min", 0); i0.ɵɵadvance(); i0.ɵɵproperty("ngIf", c_r13.resourceUnit || c_r13.unit && c_r13.unit !== "unit_ge"); i0.ɵɵadvance(); i0.ɵɵproperty("ngIf", c_r13.name); i0.ɵɵadvance(); i0.ɵɵproperty("ngIf", i0.ɵɵpipeBind1(7, 7, c_r13 == null ? null : c_r13.description)); i0.ɵɵadvance(2); i0.ɵɵproperty("ngIf", ((tmp_15_0 = control_r3.get("value")) == null ? null : tmp_15_0.controls == null ? null : tmp_15_0.controls[c_r13.key] == null ? null : tmp_15_0.controls[c_r13.key].dirty) || (ctx_r0.controlContainer == null ? null : ctx_r0.controlContainer.formDirective == null ? null : ctx_r0.controlContainer.formDirective.submitted)); } } function CustomResourceQuotaFormComponent_ng_container_2_ng_container_10_ng_container_2_Template(rf, ctx) { if (rf & 1) { i0.ɵɵelementContainerStart(0); i0.ɵɵtemplate(1, CustomResourceQuotaFormComponent_ng_container_2_ng_container_10_ng_container_2_div_1_Template, 9, 11, "div", 26); i0.ɵɵelementContainerEnd(); } if (rf & 2) { const context_r11 = i0.ɵɵnextContext().declare; i0.ɵɵadvance(); i0.ɵɵproperty("ngForOf", context_r11 == null ? null : context_r11.groupResources); } } function CustomResourceQuotaFormComponent_ng_container_2_ng_container_10_Template(rf, ctx) { if (rf & 1) { i0.ɵɵelementContainerStart(0); i0.ɵɵtemplate(1, CustomResourceQuotaFormComponent_ng_container_2_ng_container_10_ng_container_1_Template, 8, 6, "ng-container", 18)(2, CustomResourceQuotaFormComponent_ng_container_2_ng_container_10_ng_container_2_Template, 2, 1, "ng-container", 18); i0.ɵɵelementContainerEnd(); } if (rf & 2) { const context_r11 = ctx.declare; i0.ɵɵadvance(); i0.ɵɵproperty("ngIf", !(context_r11 == null ? null : context_r11.groupResources)); i0.ɵɵadvance(); i0.ɵɵproperty("ngIf", context_r11 == null ? null : context_r11.groupResources); } } function CustomResourceQuotaFormComponent_ng_container_2_Template(rf, ctx) { if (rf & 1) { const _r2 = i0.ɵɵgetCurrentView(); i0.ɵɵelementContainerStart(0, 7); i0.ɵɵelementStart(1, "td", 8)(2, "aui-select", 9); i0.ɵɵlistener("valueChange", function CustomResourceQuotaFormComponent_ng_container_2_Template_aui_select_valueChange_2_listener() { const control_r3 = i0.ɵɵrestoreView(_r2).$implicit; return i0.ɵɵresetView(control_r3.get("value").patchValue("")); })("show", function CustomResourceQuotaFormComponent_ng_container_2_Template_aui_select_show_2_listener() { i0.ɵɵrestoreView(_r2); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.refreshKindDisabledState()); }); i0.ɵɵtemplate(3, CustomResourceQuotaFormComponent_ng_container_2_ng_container_3_Template, 4, 1, "ng-container", 10); i0.ɵɵpipe(4, "async"); i0.ɵɵelementStart(5, "aui-option-placeholder"); i0.ɵɵtext(6); i0.ɵɵpipe(7, "translate"); i0.ɵɵelementEnd()(); i0.ɵɵtemplate(8, CustomResourceQuotaFormComponent_ng_container_2_acl_errors_mapper_8_Template, 3, 9, "acl-errors-mapper", 11); i0.ɵɵelementEnd(); i0.ɵɵelementStart(9, "td", 8); i0.ɵɵtemplate(10, CustomResourceQuotaFormComponent_ng_container_2_ng_container_10_Template, 3, 2, "ng-container", 10); i0.ɵɵpipe(11, "async"); i0.ɵɵpipe(12, "async"); i0.ɵɵpipe(13, "pure"); i0.ɵɵelementEnd(); i0.ɵɵelementContainerEnd(); } if (rf & 2) { let tmp_4_0; const control_r3 = ctx.$implicit; const ctx_r0 = i0.ɵɵnextContext(); i0.ɵɵproperty("formGroup", control_r3); i0.ɵɵadvance(2); i0.ɵɵproperty("readonly", (tmp_4_0 = control_r3.get("disabled")) == null ? null : tmp_4_0.value); i0.ɵɵadvance(); i0.ɵɵproperty("declare", i0.ɵɵpipeBind1(4, 6, ctx_r0.customResourceLimitsMixed$)); i0.ɵɵadvance(3); i0.ɵɵtextInterpolate1(" ", i0.ɵɵpipeBind1(7, 8, "no_data"), " "); i0.ɵɵadvance(2); i0.ɵɵproperty("ngIf", (control_r3.errors == null ? null : control_r3.errors.duplicateError) || control_r3.get("key").dirty || (ctx_r0.controlContainer == null ? null : ctx_r0.controlContainer.formDirective == null ? null : ctx_r0.controlContainer.formDirective.submitted)); i0.ɵɵadvance(2); i0.ɵɵproperty("declare", i0.ɵɵpipeBindV(13, 14, i0.ɵɵpureFunction5(20, _c0, control_r3.get("key").value, ctx_r0.getResourceQuotaContext, i0.ɵɵpipeBind1(11, 10, ctx_r0.translate.locale$), i0.ɵɵpipeBind1(12, 12, ctx_r0.customResourceLimitsMixed$), control_r3))); } } function CustomResourceQuotaFormComponent_ng_container_3_Template(rf, ctx) { if (rf & 1) { const _r16 = i0.ɵɵgetCurrentView(); i0.ɵɵelementContainerStart(0); i0.ɵɵelementStart(1, "button", 31); i0.ɵɵlistener("click", function CustomResourceQuotaFormComponent_ng_container_3_Template_button_click_1_listener() { const index_r17 = i0.ɵɵrestoreView(_r16).index; const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.remove(index_r17)); }); i0.ɵɵelement(2, "aui-icon", 32); i0.ɵɵelementEnd(); i0.ɵɵelementContainerEnd(); } if (rf & 2) { let tmp_3_0; const control_r18 = ctx.$implicit; i0.ɵɵadvance(); i0.ɵɵproperty("disabled", (tmp_3_0 = control_r18.get("disabled")) == null ? null : tmp_3_0.value)("square", true)("plain", true); } } const QuotaTypes = ['StorageQuota', 'ExtendedResource', 'OtherQuota']; const QUOTA_KEY_PATTERN = /^(([\da-z]([\da-z-]*[\da-z])?(\.[\da-z]([\da-z-]*[\da-z])?)*)\/?([\dA-Za-z]([\w.-]*[\dA-Za-z])?)?)$/; const DEFAULT_RESOURCE_QUOTA = new Set([ QuotaItemType.CPU_LIMITS, QuotaItemType.CPU_REQUESTS, QuotaItemType.MEMORY_LIMITS, QuotaItemType.MEMORY_REQUESTS, QuotaItemType.PODS, 'cpu', 'memory', ]); export class CustomResourceQuotaFormComponent extends BaseResourceFormArrayComponent { constructor(controlContainer, injector, translate, rowDupService) { super(injector); this.controlContainer = controlContainer; this.translate = translate; this.rowDupService = rowDupService; this.maxLimits = {}; this.actionType = ActionType.CREATE; this.customResourceLimits = []; this.podContainersResources = [ { limits: {}, requests: {}, }, ]; this.podContainerIndex = 0; this.kindDisabledStateTrigger$$ = new BehaviorSubject(0); this.customResourceLimitsWithGroup = []; this.excludeCustomResourceConfigs = {}; this.customResourceLimitsWithGroup$ = this.customResourceLimits$.pipe(map(customResource => { const byGroup = groupBy(customResource, 'group'); const result = toPairs(byGroup) .filter(groupItems => groupItems[1]?.length > 1) .map(([key, values]) => { const groupI18n = byGroup[key].find(i => !!i.groupI18n)?.groupI18n; return this.convertCustomResourceData({ key, groupI18n, groupResources: values.map(v => this.convertCustomResourceData(v)), }); }); this.customResourceLimitsWithGroup = result; return result; }), publishRef()); this.customResourceLimitsWithNoGroup$ = this.customResourceLimits$.pipe(map(customResource => { const byGroup = groupBy(customResource, 'group'); return toPairs(byGroup) .filter(groupItems => groupItems[1]?.length === 1) .map(([_, values]) => { return this.convertCustomResourceData(values[0]); }); }), publishRef()); this.customResourceLimitsMixed$ = combineLatest([ this.customResourceLimitsWithGroup$, this.customResourceLimitsWithNoGroup$, ]).pipe(map(([a, b]) => [...a, ...b]), publishRef()); this.convertCustomResourceData = ({ key, descriptionEn, descriptionZh, labelEn, labelZh, groupResources, resourceUnit, excludeResources, groupI18n, }) => { return { key: `${key}`, name: groupResources ? groupI18n || key : labelZh ? { en: labelEn, zh: labelZh, } : key, unit: 'unit_ge', resourceUnit, description: { zh: descriptionZh, en: descriptionEn, }, groupResources, excludeResources, }; }; } ngAfterViewInit() { super.ngAfterViewInit(); this.form.valueChanges .pipe(debounceTime(0), distinctUntilChanged(isEqual), takeUntil(this.destroy$)) .subscribe(() => this.form.controls.forEach(ctrl => ctrl.updateValueAndValidity())); combineLatest([this.maxLimits$, this.customResourceLimitsMixed$]) .pipe(takeUntil(this.destroy$), tap(([maxLimits, customResourceLimitsMixed]) => { const defaultQuotaItemsModel = this.getDefaultQuotaItemsModel(maxLimits, customResourceLimitsMixed); if (this.actionType === ActionType.CREATE) { if (maxLimits) { if (this.form.length) { this.form.clear(); } defaultQuotaItemsModel.forEach((model, index) => this.form.insert(index, this.createNewQuotaItemControl(model))); } else { this.form.clear(); } } else { requestAnimationFrame(() => { const keyVisibleModels = cloneDeep(this.formModel .filter(model => model.value) .map(model => { return { ...model, }; })); const targetQuotaFormModel = this.getDefaultQuotaItemsModel(keyVisibleModels?.reduce((acc, curr) => { acc[curr.key] = curr.value; return acc; }, {}), customResourceLimitsMixed); this.form.clear(); targetQuotaFormModel.forEach(model => { this.form.push(this.createNewQuotaItemControl(model, keyVisibleModels)); }); this.cdr.markForCheck(); }); } })) .subscribe(); } getOnFormArrayResizeFn() { return () => this.createNewQuotaItemControl(); } adaptFormModel(formModel) { const transferredModel = formModel?.reduce((acc, { key, value }) => { if (isObject(value)) { Object.entries(value)?.forEach(([k, v]) => { acc[k] = v; }); } else { acc[key] = value; } return acc; }, {}); return { ...this.excludeCustomResourceConfigs, ...transferredModel, }; } adaptResourceModel(resource) { return this.selfAdaptResourceModel(resource, true); } selfAdaptResourceModel(resource, needCache = false) { const targetGroupResource = []; if (needCache) { this.excludeCustomResourceConfigs = omit(resource, this.customResourceLimits?.map(config => config.key)) || {}; } const visibleCustomResourceConfigMap = pick(resource, this.customResourceLimits?.map(config => config.key)); const targetResources = isObject(visibleCustomResourceConfigMap) ? Object.keys(visibleCustomResourceConfigMap).map(k => ({ [k]: visibleCustomResourceConfigMap[k], })) : []; if (this.customResourceLimitsWithGroup?.length) { this.customResourceLimitsWithGroup.forEach(group => { if (group.groupResources?.length && group.groupResources.some(r => targetResources.some(s => has(s, r.key)))) { const filters = group.groupResources.filter(r => targetResources.some(s => has(s, r.key))); targetGroupResource.push({ [group.key]: filters.reduce((acc, curr) => { return { ...acc, ...targetResources.find(r => has(r, curr.key)), }; }, {}), }); filters.forEach(filter => { remove(targetResources, obj => has(obj, filter.key)); }); } }); } const wrapper = (item) => { const [key, value] = Object.entries(item).flat(); const type = this.getQuotaType(key); return { type, key, value, }; }; return [...targetGroupResource, ...targetResources].map(wrapper); } refreshKindDisabledState() { this.kindDisabledStateTrigger$$.next(Date.now()); } getKindDisabledState(models, currQuotaType, quotaTypes, inModelIndex, podContainerIndex, _SELF_REFRESH_NUMBER) { const formValueItems = this.selfAdaptResourceModel(this.podContainersResources ?.filter((_, i) => i !== podContainerIndex) ?.reduce((acc, curr) => { return { ...acc, ...curr?.limits, }; }, {})); const mergedFormValueItems = [ ...formValueItems, ...(models || []).filter((model, index) => index !== inModelIndex && !formValueItems.some(item => item.key === model.key)), ]; const getMatchedItems = (excludeResources) => { const excludeKeys = excludeResources.split(','); return mergedFormValueItems.filter(item => isObject(item.value) ? excludeKeys.some(key => has(item.value, key)) : excludeKeys.includes(item.key)); }; const getExcludesTypes = (matched) => matched .map(m => quotaTypes.find(q => q.key === m.key)?.name) .filter(Boolean); const processExcludeResources = (excludeResources) => { const matched = getMatchedItems(excludeResources); return { isDisabled: matched.length > 0, excludesTypes: getExcludesTypes(matched), }; }; if (currQuotaType.groupResources) { for (const context of currQuotaType.groupResources) { if (context.excludeResources) { const result = processExcludeResources(context.excludeResources); if (result.isDisabled) return result; } } return { isDisabled: false }; } if (currQuotaType.excludeResources) { return processExcludeResources(currQuotaType.excludeResources); } return { isDisabled: false }; } getResourceQuotaContext(key, _locale, customResourceLimits, control) { const { unit, description, groupResources, excludeResources, resourceUnit, } = customResourceLimits?.find(custom => custom.key === key) || {}; const originValue = control.get('value')?.value; control.removeControl('value'); control.addControl('value', groupResources?.length ? this.fb.group(groupResources.reduce((acc, curr) => { acc[curr.key] = this.fb.control(originValue?.[curr.key], [ Validators.required, ]); return acc; }, {})) : this.fb.control(isObject(originValue) ? '' : originValue, [ Validators.required, ])); return groupResources?.length ? { groupResources, } : this.getQuotaContext({ unit, resourceUnit, description, excludeResources, }); } createNewQuotaItemControl(model, keyVisibleModels) { return this.fb.group({ key: [ model?.key || '', [Validators.required, this.keyDuplicateValidator, this.keyValidator], ], value: model?.groupResources ? this.fb.group(model.groupResources.reduce((acc, curr) => { acc[curr.key] = this.fb.control(keyVisibleModels?.find(v => v.key === curr.key) ?.value ?? model.value ?? '', [Validators.required]); return acc; }, {})) : [ (keyVisibleModels?.find(v => v.key === model.key) ?? model) ?.value ?? '', [Validators.required], ], }, { validators: [ this.rowDupService.createFormArrayValidator({ rowKeys: [{ keyDuplicated: ['key'] }], formArray: this.form, }), ], }); } keyDuplicateValidator(ctrl) { const key = ctrl.value; return DEFAULT_RESOURCE_QUOTA.has(key) ? { keyDuplicated: true, } : null; } keyValidator(ctrl) { const key = ctrl.value; return !key || QUOTA_KEY_PATTERN.test(key) ? null : { keyInvalid: true, }; } getFormModel(model) { return { type: 'ExtendedResource', key: '', value: '', ...model, }; } getQuotaContext(context) { return { unit: 'unit_Gi', ...context, }; } getQuotaType(key) { const isCustomResource = this.customResourceLimits?.some(resource => resource.key === key); if (isCustomResource) { return 'ExtendedResource'; } return 'OtherQuota'; } getDefaultQuotaItemsModel(model, customResourceLimits) { const getFormModelByKey = (key) => { const hasCustomResourceLimit = customResourceLimits?.some(resource => resource.key === key); if (hasCustomResourceLimit) { return this.getFormModel({ type: 'ExtendedResource', key, value: null, }); } return null; }; const keys = Object.keys(model ?? {}); let result = []; const groupedLimits = customResourceLimits.filter(c => !!c.groupResources?.length && c.groupResources.some(r => keys.includes(r.key))); const groupedLimitsKeys = flatMap(groupedLimits, arr => arr.groupResources).map(r => r.key); result = result.concat(groupedLimits.map(g => ({ type: 'ExtendedResource', key: g.key, groupResources: g.groupResources.map(r => ({ type: 'ExtendedResource', key: r.key, value: null, })), }))); return result.concat(keys .filter(k => !groupedLimitsKeys.includes(k)) .map(r => getFormModelByKey(r)) .filter(Boolean)); } static { this.ɵfac = function CustomResourceQuotaFormComponent_Factory(t) { return new (t || CustomResourceQuotaFormComponent)(i0.ɵɵdirectiveInject(i1.ControlContainer), i0.ɵɵdirectiveInject(i0.Injector), i0.ɵɵdirectiveInject(i2.TranslateService), i0.ɵɵdirectiveInject(i2.ValidateRowDuplicateService)); }; } static { this.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: CustomResourceQuotaFormComponent, selectors: [["acl-custom-resource-quota-form"]], inputs: { maxLimits: "maxLimits", actionType: "actionType", customResourceLimits: "customResourceLimits", podContainersResources: "podContainersResources", podContainerIndex: "podContainerIndex" }, standalone: true, features: [i0.ɵɵProvidersFeature([ValidateRowDuplicateService]), i0.ɵɵInheritDefinitionFeature, i0.ɵɵStandaloneFeature], decls: 4, vars: 3, consts: [["disabledTemplate", ""], [3, "add", "remove", "formGroup", "rows", "rowSeparator"], ["auiFormItemControl", "", "required", "", 4, "aclArrayFormTableHeader"], [3, "formGroup", 4, "aclArrayFormTableRow"], [4, "aclArrayFormTableRowControl"], ["auiFormItemControl", "", "required", ""], ["width", "50%"], [3, "formGroup"], [1, "!tw-align-top"], ["auiFormItemControl", "", "formControlName", "key", 3, "valueChange", "show", "readonly"], [4, "declare"], [3, "errors", "errorsMapper", 4, "ngIf"], [4, "ngFor", "ngForOf"], [3, "value", "label", "disabled", "auiTooltip", "auiTooltipContext", "auiTooltipDisabled", 4, "declare"], [3, "value", "label", "disabled", "auiTooltip", "auiTooltipContext", "auiTooltipDisabled"], [1, "tw-mb-4"], [1, "acl-tooltip-ul"], [3, "errors", "errorsMapper"], [4, "ngIf"], [1, "tw-flex", "tw-items-center"], [1, "tw-flex-1"], ["aui-input", "", "auiFormItemControl", "", "formControlName", "value", 3, "min"], ["auiInputAddonAfter", "", 4, "ngIf"], ["class", "tw-question tw-ml-8", "icon", "question_circle", 3, "auiTooltip", 4, "ngIf"], ["auiInputAddonAfter", ""], ["icon", "question_circle", 1, "tw-question", "tw-ml-8", 3, "auiTooltip"], ["formGroupName", "value", 3, "ngClass", 4, "ngFor", "ngForOf"], ["formGroupName", "value", 3, "ngClass"], ["aui-input", "", "auiFormItemControl", "", 3, "formControlName", "min"], ["class", "tw-max-w-[100px] tw-text-overflow", "auiInputAddonBefore", "", 3, "title", 4, "ngIf"], ["auiInputAddonBefore", "", 1, "tw-max-w-[100px]", "tw-text-overflow", 3, "title"], ["aui-button", "text", "type", "button", 3, "click", "disabled", "square", "plain"], ["icon", "minus_circle"]], template: function CustomResourceQuotaFormComponent_Template(rf, ctx) { if (rf & 1) { i0.ɵɵelementStart(0, "acl-array-form-table", 1); i0.ɵɵlistener("add", function CustomResourceQuotaFormComponent_Template_acl_array_form_table_add_0_listener() { return ctx.add(); })("remove", function CustomResourceQuotaFormComponent_Template_acl_array_form_table_remove_0_listener($event) { return ctx.remove($event); }); i0.ɵɵtemplate(1, CustomResourceQuotaFormComponent_ng_container_1_Template, 7, 10, "ng-container", 2)(2, CustomResourceQuotaFormComponent_ng_container_2_Template, 14, 26, "ng-container", 3)(3, CustomResourceQuotaFormComponent_ng_container_3_Template, 3, 3, "ng-container", 4); i0.ɵɵelementEnd(); } if (rf & 2) { i0.ɵɵproperty("formGroup", ctx.form)("rows", ctx.form.controls)("rowSeparator", true); } }, dependencies: [ArrayFormTableComponent, ReactiveFormsModule, i1.DefaultValueAccessor, i1.NgControlStatus, i1.NgControlStatusGroup, i1.FormGroupDirective, i1.FormControlName, i1.FormGroupName, ArrayFormTableHeaderDirective, i2.TranslatePipe, ArrayFormTableRowDirective, i3.SelectComponent, i3.OptionComponent, i3.OptionPlaceholderComponent, DeclareDirective, AsyncPipe, NgForOf, PurePipe, ParseJsonTranslatePipe, TooltipDirective, i2.ErrorsMapperComponent, NgIf, i3.InputGroupComponent, i3.InputAddonAfterDirective, i3.InputAddonBeforeDirective, InputComponent, i3.FormItemControlDirective, IconComponent, NgClass, ArrayFormTableRowControlDirective, ButtonComponent], styles: ["[_nghost-%COMP%] .aui-select .aui-input[readonly]{background-color:rgb(var(--aui-color-n-8))}"], changeDetection: 0 }); } } __decorate([ ObservableInput(), __metadata("design:type", Observable) ], CustomResourceQuotaFormComponent.prototype, "maxLimits$", void 0); __decorate([ ObservableInput(), __metadata("design:type", Observable) ], CustomResourceQuotaFormComponent.prototype, "customResourceLimits$", void 0); __decorate([ bind, __metadata("design:type", Function), __metadata("design:paramtypes", [Array, Object, Array, Number, Number, Number]), __metadata("design:returntype", Object) ], CustomResourceQuotaFormComponent.prototype, "getKindDisabledState", null); __decorate([ bind, __metadata("design:type", Function), __metadata("design:paramtypes", [String, String, Array, FormGroup]), __metadata("design:returntype", Object) ], CustomResourceQuotaFormComponent.prototype, "getResourceQuotaContext", null); (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(CustomResourceQuotaFormComponent, [{ type: Component, args: [{ standalone: true, selector: 'acl-custom-resource-quota-form', changeDetection: ChangeDetectionStrategy.OnPush, providers: [ValidateRowDuplicateService], imports: [ ArrayFormTableComponent, ReactiveFormsModule, ArrayFormTableHeaderDirective, TRANSLATE_MODULE, ArrayFormTableRowDirective, SELECT_MODULE, DeclareDirective, AsyncPipe, NgForOf, PurePipe, ParseJsonTranslatePipe, TooltipDirective, ERRORS_MAPPER_MODULE, NgIf, INPUT_GROUP_MODULE, InputComponent, FORM_MODULE, IconComponent, NgClass, ArrayFormTableRowControlDirective, ButtonComponent, ], template: "<acl-array-form-table\n [formGroup]=\"$any(form)\"\n [rows]=\"form.controls\"\n (add)=\"add()\"\n (remove)=\"remove($event)\"\n [rowSeparator]=\"true\"\n>\n <ng-container\n *aclArrayFormTableHeader\n auiFormItemControl\n required\n >\n <th\n width=\"50%\"\n [class]=\"form.controls?.length ? 'tw-required-mark' : ''\"\n >\n {{ 'type' | translate }}\n </th>\n <th\n width=\"50%\"\n [class]=\"form.controls?.length ? 'tw-required-mark' : ''\"\n >\n {{ 'value' | translate }}\n </th>\n </ng-container>\n\n <ng-container\n *aclArrayFormTableRow=\"let control; let index = index\"\n [formGroup]=\"control\"\n >\n <td class=\"!tw-align-top\">\n <!-- \u6269\u5C55\u8D44\u6E90 -->\n <aui-select\n auiFormItemControl\n formControlName=\"key\"\n [readonly]=\"control.get('disabled')?.value\"\n (valueChange)=\"control.get('value').patchValue('')\"\n (show)=\"refreshKindDisabledState()\"\n >\n <ng-container *declare=\"customResourceLimitsMixed$ | async as options\">\n <ng-container *ngFor=\"let item of options\">\n <aui-option\n *declare=\"\n form?.value\n | pure\n : getKindDisabledState\n : item\n : options\n : index\n : podContainerIndex\n : (kindDisabledStateTrigger$$ | async) as state\n \"\n [value]=\"item.key\"\n [label]=\"item.name | aclParseJsonTranslate\"\n [disabled]=\"state.isDisabled\"\n [auiTooltip]=\"disabledTemplate\"\n [auiTooltipContext]=\"{\n excludesTypes: state.excludesTypes,\n }\"\n [auiTooltipDisabled]=\"!state.isDisabled\"\n >\n {{ item.name | aclParseJsonTranslate }}\n </aui-option>\n </ng-container>\n <ng-template\n #disabledTemplate\n let-excludesTypes=\"excludesTypes\"\n >\n <div class=\"tw-mb-4\">\n {{ 'custom_resource_kind_excludes_tip' | translate }}\n </div>\n <ul class=\"acl-tooltip-ul\">\n <li *ngFor=\"let t of excludesTypes\">\n {{ t | aclParseJsonTranslate }}\n </li>\n </ul>\n </ng-template>\n </ng-container>\n <aui-option-placeholder>\n {{ 'no_data' | translate }}\n </aui-option-placeholder>\n </aui-select>\n <acl-errors-mapper\n *ngIf=\"\n control.errors?.duplicateError ||\n control.get('key').dirty ||\n $any(controlContainer?.formDirective)?.submitted\n \"\n [errors]=\"control.errors?.duplicateError || control.get('key').errors\"\n [errorsMapper]=\"{\n keyInvalid: 'invalid_pattern' | translate,\n keyDuplicated: 'type_duplicated_errors' | translate,\n }\"\n ></acl-errors-mapper>\n </td>\n <td class=\"!tw-align-top\">\n <ng-container\n *declare=\"\n control.get('key').value\n | pure\n : getResourceQuotaContext\n : (translate.locale$ | async)\n : (customResourceLimitsMixed$ | async)\n : control as context\n \"\n >\n <ng-container *ngIf=\"!context?.groupResources\">\n <div class=\"tw-flex tw-items-center\">\n <aui-input-group class=\"tw-flex-1\">\n <input\n aui-input\n auiFormItemControl\n formControlName=\"value\"\n [min]=\"0\"\n />\n <span\n *ngIf=\"\n context.resourceUnit ||\n (context.unit && context.unit !== 'unit_ge')\n \"\n auiInputAddonAfter\n >{{ context.resourceUnit || (context.unit | translate) }}</span\n >\n </aui-input-group>\n <aui-icon\n *ngIf=\"context?.description | translate as description\"\n class=\"tw-question tw-ml-8\"\n icon=\"question_circle\"\n [auiTooltip]=\"description\"\n ></aui-icon>\n </div>\n <acl-errors-mapper\n *ngIf=\"\n control.get('value').dirty ||\n $any(controlContainer?.formDirective)?.submitted\n \"\n [errors]=\"control.get('value').errors\"\n [errorsMapper]=\"{\n pattern: 'support_positive_integer' | translate,\n }\"\n ></acl-errors-mapper>\n </ng-container>\n\n <!-- groupResources -->\n <ng-container *ngIf=\"context?.groupResources\">\n <div\n *ngFor=\"let c of context?.groupResources; let i = index\"\n formGroupName=\"value\"\n [ngClass]=\"{ 'tw-mt-8': !!i }\"\n >\n <div class=\"tw-flex tw-items-center\">\n <aui-input-group class=\"tw-flex-1\">\n <input\n aui-input\n auiFormItemControl\n [formControlName]=\"c.key\"\n [min]=\"0\"\n />\n <span\n *ngIf=\"c.resourceUnit || (c.unit && c.unit !== 'unit_ge')\"\n auiInputAddonAfter\n >{{ c.resourceUnit || (c.unit | translate) }}</span\n >\n <span\n *ngIf=\"c.name\"\n class=\"tw-max-w-[100px] tw-text-overflow\"\n [title]=\"c.name | translate\"\n auiInputAddonBefore\n >{{ c.name | translate }}</span\n >\n </aui-input-group>\n <aui-icon\n *ngIf=\"c?.description | translate as description\"\n class=\"tw-question tw-ml-8\"\n icon=\"question_circle\"\n [auiTooltip]=\"description\"\n ></aui-icon>\n </div>\n <acl-errors-mapper\n *ngIf=\"\n control.get('value')?.controls?.[c.key]?.dirty ||\n $any(controlContainer?.formDirective)?.submitted\n \"\n [errors]=\"control.get('value')?.controls?.[c.key]?.errors\"\n [errorsMapper]=\"{\n pattern: 'support_positive_integer' | translate,\n }\"\n ></acl-errors-mapper>\n </div>\n </ng-container>\n </ng-container>\n </td>\n </ng-container>\n\n <ng-container *aclArrayFormTableRowControl=\"let control; let index = index\">\n <button\n aui-button=\"text\"\n type=\"button\"\n [disabled]=\"control.get('disabled')?.value\"\n (click)=\"remove(index)\"\n [square]=\"true\"\n [plain]=\"true\"\n >\n <aui-icon icon=\"minus_circle\"></aui-icon>\n </button>\n </ng-container>\n</acl-array-form-table>\n", styles: [":host ::ng-deep .aui-select .aui-input[readonly]{background-color:rgb(var(--aui-color-n-8))}\n"] }] }], () => [{ type: i1.ControlContainer }, { type: i0.Injector }, { type: i2.TranslateService }, { type: i2.ValidateRowDuplicateService }], { maxLimits: [{ type: Input }], maxLimits$: [], actionType: [{ type: Input }], customResourceLimits: [{ type: Input }], customResourceLimits$: [], podContainersResources: [{ type: Input }], podContainerIndex: [{ type: Input }], getKindDisabledState: [], getResourceQuotaContext: [] }); })(); (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(CustomResourceQuotaFormComponent, { className: "CustomResourceQuotaFormComponent", filePath: "custom-resource-form/component.ts", lineNumber: 147 }); })(); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vbW9kdWxlcy9jdXN0b20tcmVzb3VyY2UtcXVvdGEvc3JjL2N1c3RvbS1yZXNvdXJjZS1mb3JtL2NvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uL21vZHVsZXMvY3VzdG9tLXJlc291cmNlLXF1b3RhL3NyYy9jdXN0b20tcmVzb3VyY2UtZm9ybS90ZW1wbGF0ZS5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQSxPQUFPLEVBQ0wsZUFBZSxFQUNmLFdBQVcsRUFDWCxhQUFhLEVBQ2Isa0JBQWtCLEVBQ2xCLGNBQWMsRUFDZCxhQUFhLEVBQ2IsZ0JBQWdCLEdBQ2pCLE1BQU0sWUFBWSxDQUFDO0FBQ3BCLE9BQU8sRUFFTCxnQkFBZ0IsRUFDaEIsSUFBSSxFQUNKLDJCQUEyQixFQUMzQixPQUFPLEVBQ1AsVUFBVSxFQUdWLGVBQWUsRUFDZix1QkFBdUIsRUFDdkIsNkJBQTZCLEVBQzdCLGdCQUFnQixFQUNoQiwwQkFBMEIsRUFDMUIsZ0JBQWdCLEVBQ2hCLFFBQVEsRUFDUixzQkFBc0IsRUFDdEIsb0JBQW9CLEVBQ3BCLGlDQUFpQyxHQUNsQyxNQUFNLG1CQUFtQixDQUFDO0FBQzNCLE9BQU8sRUFBRSxTQUFTLEVBQUUsT0FBTyxFQUFFLE9BQU8sRUFBRSxJQUFJLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUNwRSxPQUFPLEVBRUwsdUJBQXVCLEVBQ3ZCLFNBQVMsRUFDVCxRQUFRLEVBQ1IsS0FBSyxHQUNOLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFFTCxnQkFBZ0IsRUFFaEIsU0FBUyxFQUNULG1CQUFtQixFQUNuQixVQUFVLEdBQ1gsTUFBTSxnQkFBZ0IsQ0FBQztBQUN4QixPQUFPLEVBQ0wsU0FBUyxFQUNULE9BQU8sRUFDUCxPQUFPLEVBQ1AsR0FBRyxFQUNILFFBQVEsRUFDUixJQUFJLEVBQ0osSUFBSSxFQUNKLE1BQU0sRUFDTixP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